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