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