[NTOSKRNL] Stubplement CcPinMappedData() and simplify CcPinRead()
[reactos.git] / 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 /* 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 PINTERNAL_BCB iBcb;
165 PROS_SHARED_CACHE_MAP SharedCacheMap;
166
167 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
168 FileObject, FileOffset, Length, Flags);
169
170 ASSERT(FileObject);
171 ASSERT(FileObject->SectionObjectPointer);
172 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap);
173
174 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
175 ASSERT(SharedCacheMap);
176 ASSERT(SharedCacheMap->PinAccess);
177
178 iBcb = *Bcb;
179 ASSERT(iBcb->Pinned == FALSE);
180
181 iBcb->Pinned = TRUE;
182 iBcb->Vacb->PinCount++;
183
184 if (Flags & PIN_EXCLUSIVE)
185 {
186 ExAcquireResourceExclusiveLite(&iBcb->Lock, TRUE);
187 }
188 else
189 {
190 ExAcquireResourceSharedLite(&iBcb->Lock, TRUE);
191 }
192
193 return TRUE;
194 }
195
196 /*
197 * @unimplemented
198 */
199 BOOLEAN
200 NTAPI
201 CcPinRead (
202 IN PFILE_OBJECT FileObject,
203 IN PLARGE_INTEGER FileOffset,
204 IN ULONG Length,
205 IN ULONG Flags,
206 OUT PVOID * Bcb,
207 OUT PVOID * Buffer)
208 {
209 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
210 FileObject, FileOffset, Length, Flags);
211
212 if (Flags & PIN_WAIT)
213 {
214 ++CcPinReadWait;
215 }
216 else
217 {
218 ++CcPinReadNoWait;
219 }
220
221 /* Map first */
222 if (!CcMapData(FileObject, FileOffset, Length, Flags, Bcb, Buffer))
223 {
224 return FALSE;
225 }
226
227 /* Pin then */
228 if (!CcPinMappedData(FileObject, FileOffset, Length, Flags, Bcb))
229 {
230 CcUnpinData(*Bcb);
231 return FALSE;
232 }
233
234 return TRUE;
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 if (!iBcb->Vacb->Dirty)
280 {
281 CcRosMarkDirtyVacb(iBcb->Vacb);
282 }
283 }
284
285
286 /*
287 * @implemented
288 */
289 VOID NTAPI
290 CcUnpinData (
291 IN PVOID Bcb)
292 {
293 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
294
295 CcUnpinDataForThread(Bcb, (ERESOURCE_THREAD)PsGetCurrentThread());
296 }
297
298 /*
299 * @unimplemented
300 */
301 VOID
302 NTAPI
303 CcUnpinDataForThread (
304 IN PVOID Bcb,
305 IN ERESOURCE_THREAD ResourceThreadId)
306 {
307 PINTERNAL_BCB iBcb = Bcb;
308
309 CCTRACE(CC_API_DEBUG, "Bcb=%p ResourceThreadId=%lu\n", Bcb, ResourceThreadId);
310
311 if (iBcb->Pinned)
312 {
313 ExReleaseResourceForThreadLite(&iBcb->Lock, ResourceThreadId);
314 iBcb->Pinned = FALSE;
315 iBcb->Vacb->PinCount--;
316 }
317
318 if (--iBcb->RefCount == 0)
319 {
320 CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap,
321 iBcb->Vacb,
322 TRUE,
323 iBcb->Dirty,
324 FALSE);
325
326 ExDeleteResourceLite(&iBcb->Lock);
327 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
328 }
329 }
330
331 /*
332 * @implemented
333 */
334 VOID
335 NTAPI
336 CcRepinBcb (
337 IN PVOID Bcb)
338 {
339 PINTERNAL_BCB iBcb = Bcb;
340
341 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
342
343 iBcb->RefCount++;
344 }
345
346 /*
347 * @unimplemented
348 */
349 VOID
350 NTAPI
351 CcUnpinRepinnedBcb (
352 IN PVOID Bcb,
353 IN BOOLEAN WriteThrough,
354 IN PIO_STATUS_BLOCK IoStatus)
355 {
356 PINTERNAL_BCB iBcb = Bcb;
357
358 CCTRACE(CC_API_DEBUG, "Bcb=%p WriteThrough=%d\n", Bcb, WriteThrough);
359
360 IoStatus->Status = STATUS_SUCCESS;
361 if (--iBcb->RefCount == 0)
362 {
363 IoStatus->Information = 0;
364 if (WriteThrough)
365 {
366 if (iBcb->Vacb->Dirty)
367 {
368 IoStatus->Status = CcRosFlushVacb(iBcb->Vacb);
369 }
370 else
371 {
372 IoStatus->Status = STATUS_SUCCESS;
373 }
374 }
375 else
376 {
377 IoStatus->Status = STATUS_SUCCESS;
378 }
379
380 if (iBcb->Pinned)
381 {
382 ExReleaseResourceLite(&iBcb->Lock);
383 iBcb->Pinned = FALSE;
384 iBcb->Vacb->PinCount--;
385 ASSERT(iBcb->Vacb->PinCount == 0);
386 }
387
388 CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap,
389 iBcb->Vacb,
390 TRUE,
391 iBcb->Dirty,
392 FALSE);
393
394 ExDeleteResourceLite(&iBcb->Lock);
395 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
396 }
397 }