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