fb5f99aab26b936a4c715e3b0443df61deeb460b
[reactos.git] / ntoskrnl / cc / fs.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cc/fs.c
5 * PURPOSE: Implements cache managers functions useful for File Systems
6 *
7 * PROGRAMMERS: Alex Ionescu
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 #ifndef VACB_MAPPING_GRANULARITY
17 #define VACB_MAPPING_GRANULARITY (256 * 1024)
18 #endif
19
20 /* GLOBALS *****************************************************************/
21
22 extern KGUARDED_MUTEX ViewLock;
23 extern ULONG DirtyPageCount;
24
25 NTSTATUS CcRosInternalFreeVacb(PROS_VACB Vacb);
26
27 /* FUNCTIONS *****************************************************************/
28
29 /*
30 * @unimplemented
31 */
32 LARGE_INTEGER
33 NTAPI
34 CcGetDirtyPages (
35 IN PVOID LogHandle,
36 IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine,
37 IN PVOID Context1,
38 IN PVOID Context2)
39 {
40 LARGE_INTEGER i;
41
42 CCTRACE(CC_API_DEBUG, "LogHandle=%p DirtyPageRoutine=%p Context1=%p Context2=%p\n",
43 LogHandle, DirtyPageRoutine, Context1, Context2);
44
45 UNIMPLEMENTED;
46 i.QuadPart = 0;
47 return i;
48 }
49
50 /*
51 * @implemented
52 */
53 PFILE_OBJECT
54 NTAPI
55 CcGetFileObjectFromBcb (
56 IN PVOID Bcb)
57 {
58 PINTERNAL_BCB iBcb = (PINTERNAL_BCB)Bcb;
59
60 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
61
62 return iBcb->Vacb->SharedCacheMap->FileObject;
63 }
64
65 /*
66 * @unimplemented
67 */
68 LARGE_INTEGER
69 NTAPI
70 CcGetLsnForFileObject (
71 IN PFILE_OBJECT FileObject,
72 OUT PLARGE_INTEGER OldestLsn OPTIONAL)
73 {
74 LARGE_INTEGER i;
75
76 CCTRACE(CC_API_DEBUG, "FileObject=%p\n", FileObject);
77
78 UNIMPLEMENTED;
79 i.QuadPart = 0;
80 return i;
81 }
82
83 /*
84 * @unimplemented
85 */
86 VOID
87 NTAPI
88 CcInitializeCacheMap (
89 IN PFILE_OBJECT FileObject,
90 IN PCC_FILE_SIZES FileSizes,
91 IN BOOLEAN PinAccess,
92 IN PCACHE_MANAGER_CALLBACKS CallBacks,
93 IN PVOID LazyWriterContext)
94 {
95 NTSTATUS Status;
96
97 ASSERT(FileObject);
98 ASSERT(FileSizes);
99
100 CCTRACE(CC_API_DEBUG, "FileObject=%p FileSizes=%p PinAccess=%d CallBacks=%p LazyWriterContext=%p\n",
101 FileObject, FileSizes, PinAccess, CallBacks, LazyWriterContext);
102
103 /* Call old ROS cache init function */
104 Status = CcRosInitializeFileCache(FileObject,
105 FileSizes,
106 PinAccess,
107 CallBacks,
108 LazyWriterContext);
109 if (!NT_SUCCESS(Status))
110 ExRaiseStatus(Status);
111 }
112
113 /*
114 * @unimplemented
115 */
116 BOOLEAN
117 NTAPI
118 CcIsThereDirtyData (
119 IN PVPB Vpb)
120 {
121 CCTRACE(CC_API_DEBUG, "Vpb=%p\n", Vpb);
122
123 UNIMPLEMENTED;
124 return FALSE;
125 }
126
127 /*
128 * @unimplemented
129 */
130 BOOLEAN
131 NTAPI
132 CcPurgeCacheSection (
133 IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
134 IN PLARGE_INTEGER FileOffset OPTIONAL,
135 IN ULONG Length,
136 IN BOOLEAN UninitializeCacheMaps)
137 {
138 PROS_SHARED_CACHE_MAP SharedCacheMap;
139 LONGLONG StartOffset;
140 LONGLONG EndOffset;
141 LIST_ENTRY FreeList;
142 KIRQL OldIrql;
143 PLIST_ENTRY ListEntry;
144 PROS_VACB Vacb;
145 LONGLONG ViewEnd;
146 BOOLEAN Success;
147
148 CCTRACE(CC_API_DEBUG, "SectionObjectPointer=%p\n FileOffset=%p Length=%lu UninitializeCacheMaps=%d",
149 SectionObjectPointer, FileOffset, Length, UninitializeCacheMaps);
150
151 if (UninitializeCacheMaps)
152 {
153 DPRINT1("FIXME: CcPurgeCacheSection not uninitializing private cache maps\n");
154 }
155
156 SharedCacheMap = SectionObjectPointer->SharedCacheMap;
157 if (!SharedCacheMap)
158 return FALSE;
159
160 StartOffset = FileOffset != NULL ? FileOffset->QuadPart : 0;
161 if (Length == 0 || FileOffset == NULL)
162 {
163 EndOffset = MAXLONGLONG;
164 }
165 else
166 {
167 EndOffset = StartOffset + Length;
168 ASSERT(EndOffset > StartOffset);
169 }
170
171 InitializeListHead(&FreeList);
172
173 /* Assume success */
174 Success = TRUE;
175
176 KeAcquireGuardedMutex(&ViewLock);
177 KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &OldIrql);
178 ListEntry = SharedCacheMap->CacheMapVacbListHead.Flink;
179 while (ListEntry != &SharedCacheMap->CacheMapVacbListHead)
180 {
181 Vacb = CONTAINING_RECORD(ListEntry, ROS_VACB, CacheMapVacbListEntry);
182 ListEntry = ListEntry->Flink;
183
184 /* Skip VACBs outside the range, or only partially in range */
185 if (Vacb->FileOffset.QuadPart < StartOffset)
186 {
187 continue;
188 }
189 ViewEnd = min(Vacb->FileOffset.QuadPart + VACB_MAPPING_GRANULARITY,
190 SharedCacheMap->SectionSize.QuadPart);
191 if (ViewEnd >= EndOffset)
192 {
193 break;
194 }
195
196 /* Still in use, it cannot be purged, fail */
197 if (Vacb->ReferenceCount != 0 && !Vacb->Dirty)
198 {
199 Success = FALSE;
200 break;
201 }
202
203 /* This VACB is in range, so unlink it and mark for free */
204 RemoveEntryList(&Vacb->VacbLruListEntry);
205 if (Vacb->Dirty)
206 {
207 RemoveEntryList(&Vacb->DirtyVacbListEntry);
208 DirtyPageCount -= VACB_MAPPING_GRANULARITY / PAGE_SIZE;
209 }
210 RemoveEntryList(&Vacb->CacheMapVacbListEntry);
211 InsertHeadList(&FreeList, &Vacb->CacheMapVacbListEntry);
212 }
213 KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql);
214 KeReleaseGuardedMutex(&ViewLock);
215
216 while (!IsListEmpty(&FreeList))
217 {
218 Vacb = CONTAINING_RECORD(RemoveHeadList(&FreeList),
219 ROS_VACB,
220 CacheMapVacbListEntry);
221 CcRosInternalFreeVacb(Vacb);
222 }
223
224 return Success;
225 }
226
227
228 /*
229 * @implemented
230 */
231 VOID NTAPI
232 CcSetFileSizes (
233 IN PFILE_OBJECT FileObject,
234 IN PCC_FILE_SIZES FileSizes)
235 {
236 KIRQL oldirql;
237 PROS_SHARED_CACHE_MAP SharedCacheMap;
238
239 CCTRACE(CC_API_DEBUG, "FileObject=%p FileSizes=%p\n",
240 FileObject, FileSizes);
241
242 DPRINT("CcSetFileSizes(FileObject 0x%p, FileSizes 0x%p)\n",
243 FileObject, FileSizes);
244 DPRINT("AllocationSize %I64d, FileSize %I64d, ValidDataLength %I64d\n",
245 FileSizes->AllocationSize.QuadPart,
246 FileSizes->FileSize.QuadPart,
247 FileSizes->ValidDataLength.QuadPart);
248
249 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
250
251 /*
252 * It is valid to call this function on file objects that weren't
253 * initialized for caching. In this case it's simple no-op.
254 */
255 if (SharedCacheMap == NULL)
256 return;
257
258 if (FileSizes->AllocationSize.QuadPart < SharedCacheMap->SectionSize.QuadPart)
259 {
260 CcPurgeCacheSection(FileObject->SectionObjectPointer,
261 &FileSizes->AllocationSize,
262 0,
263 FALSE);
264 }
265
266 KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldirql);
267 SharedCacheMap->SectionSize = FileSizes->AllocationSize;
268 SharedCacheMap->FileSize = FileSizes->FileSize;
269 KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
270 }
271
272 /*
273 * @unimplemented
274 */
275 VOID
276 NTAPI
277 CcSetLogHandleForFile (
278 IN PFILE_OBJECT FileObject,
279 IN PVOID LogHandle,
280 IN PFLUSH_TO_LSN FlushToLsnRoutine)
281 {
282 CCTRACE(CC_API_DEBUG, "FileObject=%p LogHandle=%p FlushToLsnRoutine=%p\n",
283 FileObject, LogHandle, FlushToLsnRoutine);
284
285 UNIMPLEMENTED;
286 }
287
288 /*
289 * @unimplemented
290 */
291 BOOLEAN
292 NTAPI
293 CcUninitializeCacheMap (
294 IN PFILE_OBJECT FileObject,
295 IN PLARGE_INTEGER TruncateSize OPTIONAL,
296 IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL)
297 {
298 NTSTATUS Status;
299 PROS_SHARED_CACHE_MAP SharedCacheMap;
300 KIRQL OldIrql;
301
302 CCTRACE(CC_API_DEBUG, "FileObject=%p TruncateSize=%p UninitializeCompleteEvent=%p\n",
303 FileObject, TruncateSize, UninitializeCompleteEvent);
304
305 if (TruncateSize != NULL &&
306 FileObject->SectionObjectPointer != NULL &&
307 FileObject->SectionObjectPointer->SharedCacheMap != NULL)
308 {
309 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
310 KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &OldIrql);
311 if (SharedCacheMap->FileSize.QuadPart > TruncateSize->QuadPart)
312 {
313 SharedCacheMap->FileSize = *TruncateSize;
314 }
315 KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql);
316 CcPurgeCacheSection(FileObject->SectionObjectPointer,
317 TruncateSize,
318 0,
319 FALSE);
320 }
321
322 Status = CcRosReleaseFileCache(FileObject);
323 if (UninitializeCompleteEvent)
324 {
325 KeSetEvent(&UninitializeCompleteEvent->Event, IO_NO_INCREMENT, FALSE);
326 }
327 return NT_SUCCESS(Status);
328 }
329
330 BOOLEAN
331 NTAPI
332 CcGetFileSizes (
333 IN PFILE_OBJECT FileObject,
334 IN PCC_FILE_SIZES FileSizes)
335 {
336 PROS_SHARED_CACHE_MAP SharedCacheMap;
337
338 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
339
340 if (!SharedCacheMap)
341 return FALSE;
342
343 FileSizes->AllocationSize = SharedCacheMap->SectionSize;
344 FileSizes->FileSize = FileSizes->ValidDataLength = SharedCacheMap->FileSize;
345 return TRUE;
346 }