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