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