2d48a27a0aa56de7df7bb92ddb96fa3519d397e2
[reactos.git] / ntoskrnl / cc / pin.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cc/pin.c
5 * PURPOSE: Implements cache managers pinning interface
6 *
7 * PROGRAMMERS: ?
8 Pierre Schweitzer (pierre@reactos.org)
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16
17 /* GLOBALS *******************************************************************/
18
19 extern NPAGED_LOOKASIDE_LIST iBcbLookasideList;
20
21 /* Counters:
22 * - Number of calls to CcMapData that could wait
23 * - Number of calls to CcMapData that couldn't wait
24 * - Number of calls to CcPinRead that could wait
25 * - Number of calls to CcPinRead that couldn't wait
26 */
27 ULONG CcMapDataWait = 0;
28 ULONG CcMapDataNoWait = 0;
29 ULONG CcPinReadWait = 0;
30 ULONG CcPinReadNoWait = 0;
31
32 /* FUNCTIONS *****************************************************************/
33
34 /*
35 * @implemented
36 */
37 BOOLEAN
38 NTAPI
39 CcMapData (
40 IN PFILE_OBJECT FileObject,
41 IN PLARGE_INTEGER FileOffset,
42 IN ULONG Length,
43 IN ULONG Flags,
44 OUT PVOID *pBcb,
45 OUT PVOID *pBuffer)
46 {
47 LONGLONG ReadOffset;
48 BOOLEAN Valid;
49 PROS_SHARED_CACHE_MAP SharedCacheMap;
50 PROS_VACB Vacb;
51 NTSTATUS Status;
52 PINTERNAL_BCB iBcb;
53 LONGLONG ROffset;
54
55 DPRINT("CcMapData(FileObject 0x%p, FileOffset %I64x, Length %lu, Flags 0x%lx,"
56 " pBcb 0x%p, pBuffer 0x%p)\n", FileObject, FileOffset->QuadPart,
57 Length, Flags, pBcb, pBuffer);
58
59 if (Flags & MAP_WAIT)
60 {
61 ++CcMapDataWait;
62 }
63 else
64 {
65 ++CcMapDataNoWait;
66 }
67
68 ReadOffset = FileOffset->QuadPart;
69
70 ASSERT(FileObject);
71 ASSERT(FileObject->SectionObjectPointer);
72 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap);
73
74 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
75 ASSERT(SharedCacheMap);
76
77 DPRINT("SectionSize %I64x, FileSize %I64x\n",
78 SharedCacheMap->SectionSize.QuadPart,
79 SharedCacheMap->FileSize.QuadPart);
80
81 if (ReadOffset % VACB_MAPPING_GRANULARITY + Length > VACB_MAPPING_GRANULARITY)
82 {
83 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
84 FileObject, FileOffset, Length, Flags);
85 ExRaiseStatus(STATUS_INVALID_PARAMETER);
86 return FALSE;
87 }
88
89 ROffset = ROUND_DOWN(ReadOffset, VACB_MAPPING_GRANULARITY);
90 Status = CcRosRequestVacb(SharedCacheMap,
91 ROffset,
92 pBuffer,
93 &Valid,
94 &Vacb);
95 if (!NT_SUCCESS(Status))
96 {
97 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
98 FileObject, FileOffset, Length, Flags);
99 ExRaiseStatus(Status);
100 return FALSE;
101 }
102
103 if (!Valid)
104 {
105 if (!(Flags & MAP_WAIT))
106 {
107 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
108 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
109 FileObject, FileOffset, Length, Flags);
110 return FALSE;
111 }
112
113 Status = CcReadVirtualAddress(Vacb);
114 if (!NT_SUCCESS(Status))
115 {
116 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
117 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
118 FileObject, FileOffset, Length, Flags);
119 ExRaiseStatus(Status);
120 return FALSE;
121 }
122 }
123
124 *pBuffer = (PUCHAR)*pBuffer + ReadOffset % VACB_MAPPING_GRANULARITY;
125 iBcb = ExAllocateFromNPagedLookasideList(&iBcbLookasideList);
126 if (iBcb == NULL)
127 {
128 CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
129 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
130 FileObject, FileOffset, Length, Flags);
131 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
132 return FALSE;
133 }
134
135 RtlZeroMemory(iBcb, sizeof(*iBcb));
136 iBcb->PFCB.NodeTypeCode = 0xDE45; /* Undocumented (CAPTIVE_PUBLIC_BCB_NODETYPECODE) */
137 iBcb->PFCB.NodeByteSize = sizeof(PUBLIC_BCB);
138 iBcb->PFCB.MappedLength = Length;
139 iBcb->PFCB.MappedFileOffset = *FileOffset;
140 iBcb->Vacb = Vacb;
141 iBcb->Dirty = FALSE;
142 iBcb->Pinned = FALSE;
143 iBcb->RefCount = 1;
144 ExInitializeResourceLite(&iBcb->Lock);
145 *pBcb = (PVOID)iBcb;
146
147 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> TRUE Bcb=%p\n",
148 FileObject, FileOffset, Length, Flags, iBcb);
149 return TRUE;
150 }
151
152 /*
153 * @unimplemented
154 */
155 BOOLEAN
156 NTAPI
157 CcPinMappedData (
158 IN PFILE_OBJECT FileObject,
159 IN PLARGE_INTEGER FileOffset,
160 IN ULONG Length,
161 IN ULONG Flags,
162 OUT PVOID * Bcb)
163 {
164 PROS_SHARED_CACHE_MAP SharedCacheMap;
165
166 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
167 FileObject, FileOffset, Length, Flags);
168
169 ASSERT(FileObject);
170 ASSERT(FileObject->SectionObjectPointer);
171 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap);
172
173 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
174 ASSERT(SharedCacheMap);
175 ASSERT(SharedCacheMap->PinAccess);
176
177 /* no-op for current implementation. */
178 return TRUE;
179 }
180
181 /*
182 * @unimplemented
183 */
184 BOOLEAN
185 NTAPI
186 CcPinRead (
187 IN PFILE_OBJECT FileObject,
188 IN PLARGE_INTEGER FileOffset,
189 IN ULONG Length,
190 IN ULONG Flags,
191 OUT PVOID * Bcb,
192 OUT PVOID * Buffer)
193 {
194 PINTERNAL_BCB iBcb;
195
196 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
197 FileObject, FileOffset, Length, Flags);
198
199 if (Flags & PIN_WAIT)
200 {
201 ++CcPinReadWait;
202 }
203 else
204 {
205 ++CcPinReadNoWait;
206 }
207
208 if (CcMapData(FileObject, FileOffset, Length, Flags, Bcb, Buffer))
209 {
210 if (CcPinMappedData(FileObject, FileOffset, Length, Flags, Bcb))
211 {
212 iBcb = *Bcb;
213
214 ASSERT(iBcb->Pinned == FALSE);
215
216 iBcb->Pinned = TRUE;
217 iBcb->Vacb->PinCount++;
218
219 if (Flags & PIN_EXCLUSIVE)
220 {
221 ExAcquireResourceExclusiveLite(&iBcb->Lock, TRUE);
222 }
223 else
224 {
225 ExAcquireResourceSharedLite(&iBcb->Lock, TRUE);
226 }
227
228 return TRUE;
229 }
230 else
231 CcUnpinData(*Bcb);
232 }
233 return FALSE;
234 }
235
236 /*
237 * @unimplemented
238 */
239 BOOLEAN
240 NTAPI
241 CcPreparePinWrite (
242 IN PFILE_OBJECT FileObject,
243 IN PLARGE_INTEGER FileOffset,
244 IN ULONG Length,
245 IN BOOLEAN Zero,
246 IN ULONG Flags,
247 OUT PVOID * Bcb,
248 OUT PVOID * Buffer)
249 {
250 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Zero=%d Flags=0x%lx\n",
251 FileObject, FileOffset, Length, Zero, Flags);
252
253 /*
254 * FIXME: This is function is similar to CcPinRead, but doesn't
255 * read the data if they're not present. Instead it should just
256 * prepare the VACBs and zero them out if Zero != FALSE.
257 *
258 * For now calling CcPinRead is better than returning error or
259 * just having UNIMPLEMENTED here.
260 */
261 return CcPinRead(FileObject, FileOffset, Length, Flags, Bcb, Buffer);
262 }
263
264 /*
265 * @implemented
266 */
267 VOID NTAPI
268 CcSetDirtyPinnedData (
269 IN PVOID Bcb,
270 IN PLARGE_INTEGER Lsn)
271 {
272 PINTERNAL_BCB iBcb = Bcb;
273
274 CCTRACE(CC_API_DEBUG, "Bcb=%p Lsn=%p\n",
275 Bcb, Lsn);
276
277 iBcb->Dirty = TRUE;
278 if (!iBcb->Vacb->Dirty)
279 {
280 CcRosMarkDirtyVacb(iBcb->Vacb);
281 }
282 }
283
284
285 /*
286 * @implemented
287 */
288 VOID NTAPI
289 CcUnpinData (
290 IN PVOID Bcb)
291 {
292 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
293
294 CcUnpinDataForThread(Bcb, (ERESOURCE_THREAD)PsGetCurrentThread());
295 }
296
297 /*
298 * @unimplemented
299 */
300 VOID
301 NTAPI
302 CcUnpinDataForThread (
303 IN PVOID Bcb,
304 IN ERESOURCE_THREAD ResourceThreadId)
305 {
306 PINTERNAL_BCB iBcb = Bcb;
307
308 CCTRACE(CC_API_DEBUG, "Bcb=%p ResourceThreadId=%lu\n", Bcb, ResourceThreadId);
309
310 if (iBcb->Pinned)
311 {
312 ExReleaseResourceForThreadLite(&iBcb->Lock, ResourceThreadId);
313 iBcb->Pinned = FALSE;
314 iBcb->Vacb->PinCount--;
315 }
316
317 if (--iBcb->RefCount == 0)
318 {
319 CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap,
320 iBcb->Vacb,
321 TRUE,
322 iBcb->Dirty,
323 FALSE);
324
325 ExDeleteResourceLite(&iBcb->Lock);
326 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
327 }
328 }
329
330 /*
331 * @implemented
332 */
333 VOID
334 NTAPI
335 CcRepinBcb (
336 IN PVOID Bcb)
337 {
338 PINTERNAL_BCB iBcb = Bcb;
339
340 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
341
342 iBcb->RefCount++;
343 }
344
345 /*
346 * @unimplemented
347 */
348 VOID
349 NTAPI
350 CcUnpinRepinnedBcb (
351 IN PVOID Bcb,
352 IN BOOLEAN WriteThrough,
353 IN PIO_STATUS_BLOCK IoStatus)
354 {
355 PINTERNAL_BCB iBcb = Bcb;
356
357 CCTRACE(CC_API_DEBUG, "Bcb=%p WriteThrough=%d\n", Bcb, WriteThrough);
358
359 IoStatus->Status = STATUS_SUCCESS;
360 if (--iBcb->RefCount == 0)
361 {
362 IoStatus->Information = 0;
363 if (WriteThrough)
364 {
365 if (iBcb->Vacb->Dirty)
366 {
367 IoStatus->Status = CcRosFlushVacb(iBcb->Vacb);
368 }
369 else
370 {
371 IoStatus->Status = STATUS_SUCCESS;
372 }
373 }
374 else
375 {
376 IoStatus->Status = STATUS_SUCCESS;
377 }
378
379 if (iBcb->Pinned)
380 {
381 ExReleaseResourceLite(&iBcb->Lock);
382 iBcb->Pinned = FALSE;
383 iBcb->Vacb->PinCount--;
384 ASSERT(iBcb->Vacb->PinCount == 0);
385 }
386
387 CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap,
388 iBcb->Vacb,
389 TRUE,
390 iBcb->Dirty,
391 FALSE);
392
393 ExDeleteResourceLite(&iBcb->Lock);
394 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
395 }
396 }