xref: /reactos/ntoskrnl/cc/pin.c (revision 234f89c0)
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 }
397