xref: /reactos/ntoskrnl/cc/pin.c (revision da5f10af)
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             CcRosReleaseVacbLock(iBcb->Vacb);
219 
220             if (Flags & PIN_EXCLUSIVE)
221             {
222                 ExAcquireResourceExclusiveLite(&iBcb->Lock, TRUE);
223             }
224             else
225             {
226                 ExAcquireResourceSharedLite(&iBcb->Lock, TRUE);
227             }
228 
229             return TRUE;
230         }
231         else
232             CcUnpinData(*Bcb);
233     }
234     return FALSE;
235 }
236 
237 /*
238  * @unimplemented
239  */
240 BOOLEAN
241 NTAPI
242 CcPreparePinWrite (
243     IN	PFILE_OBJECT FileObject,
244     IN	PLARGE_INTEGER FileOffset,
245     IN	ULONG Length,
246     IN	BOOLEAN Zero,
247     IN	ULONG Flags,
248     OUT	PVOID * Bcb,
249     OUT	PVOID * Buffer)
250 {
251     CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Zero=%d Flags=0x%lx\n",
252         FileObject, FileOffset, Length, Zero, Flags);
253 
254     /*
255      * FIXME: This is function is similar to CcPinRead, but doesn't
256      * read the data if they're not present. Instead it should just
257      * prepare the VACBs and zero them out if Zero != FALSE.
258      *
259      * For now calling CcPinRead is better than returning error or
260      * just having UNIMPLEMENTED here.
261      */
262     return CcPinRead(FileObject, FileOffset, Length, Flags, Bcb, Buffer);
263 }
264 
265 /*
266  * @implemented
267  */
268 VOID NTAPI
269 CcSetDirtyPinnedData (
270     IN PVOID Bcb,
271     IN PLARGE_INTEGER Lsn)
272 {
273     PINTERNAL_BCB iBcb = Bcb;
274 
275     CCTRACE(CC_API_DEBUG, "Bcb=%p Lsn=%p\n",
276         Bcb, Lsn);
277 
278     iBcb->Dirty = TRUE;
279 }
280 
281 
282 /*
283  * @implemented
284  */
285 VOID NTAPI
286 CcUnpinData (
287     IN PVOID Bcb)
288 {
289     CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
290 
291     CcUnpinDataForThread(Bcb, (ERESOURCE_THREAD)PsGetCurrentThread());
292 }
293 
294 /*
295  * @unimplemented
296  */
297 VOID
298 NTAPI
299 CcUnpinDataForThread (
300     IN	PVOID Bcb,
301     IN	ERESOURCE_THREAD ResourceThreadId)
302 {
303     PINTERNAL_BCB iBcb = Bcb;
304 
305     CCTRACE(CC_API_DEBUG, "Bcb=%p ResourceThreadId=%lu\n", Bcb, ResourceThreadId);
306 
307     if (iBcb->Pinned)
308     {
309         ExReleaseResourceForThreadLite(&iBcb->Lock, ResourceThreadId);
310         iBcb->Pinned = FALSE;
311         CcRosAcquireVacbLock(iBcb->Vacb, NULL);
312         iBcb->Vacb->PinCount--;
313     }
314 
315     if (--iBcb->RefCount == 0)
316     {
317         CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap,
318                          iBcb->Vacb,
319                          TRUE,
320                          iBcb->Dirty,
321                          FALSE);
322 
323         ExDeleteResourceLite(&iBcb->Lock);
324         ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
325     }
326 }
327 
328 /*
329  * @implemented
330  */
331 VOID
332 NTAPI
333 CcRepinBcb (
334     IN	PVOID Bcb)
335 {
336     PINTERNAL_BCB iBcb = Bcb;
337 
338     CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
339 
340     iBcb->RefCount++;
341 }
342 
343 /*
344  * @unimplemented
345  */
346 VOID
347 NTAPI
348 CcUnpinRepinnedBcb (
349     IN	PVOID Bcb,
350     IN	BOOLEAN WriteThrough,
351     IN	PIO_STATUS_BLOCK IoStatus)
352 {
353     PINTERNAL_BCB iBcb = Bcb;
354 
355     CCTRACE(CC_API_DEBUG, "Bcb=%p WriteThrough=%d\n", Bcb, WriteThrough);
356 
357     IoStatus->Status = STATUS_SUCCESS;
358     if (--iBcb->RefCount == 0)
359     {
360         IoStatus->Information = 0;
361         if (WriteThrough)
362         {
363             CcRosAcquireVacbLock(iBcb->Vacb, NULL);
364             if (iBcb->Vacb->Dirty)
365             {
366                 IoStatus->Status = CcRosFlushVacb(iBcb->Vacb);
367             }
368             else
369             {
370                 IoStatus->Status = STATUS_SUCCESS;
371             }
372             CcRosReleaseVacbLock(iBcb->Vacb);
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             CcRosAcquireVacbLock(iBcb->Vacb, NULL);
384             iBcb->Vacb->PinCount--;
385         }
386         ExDeleteResourceLite(&iBcb->Lock);
387         ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
388     }
389 }
390