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