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
7 * PROGRAMMERS: Alex Ionescu
10 /* INCLUDES ******************************************************************/
16 #ifndef VACB_MAPPING_GRANULARITY
17 #define VACB_MAPPING_GRANULARITY (256 * 1024)
20 /* GLOBALS *****************************************************************/
22 extern KGUARDED_MUTEX ViewLock
;
23 extern ULONG CcTotalDirtyPages
;
25 NTSTATUS
CcRosInternalFreeVacb(PROS_VACB Vacb
);
27 /* FUNCTIONS *****************************************************************/
36 IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine
,
42 CCTRACE(CC_API_DEBUG
, "LogHandle=%p DirtyPageRoutine=%p Context1=%p Context2=%p\n",
43 LogHandle
, DirtyPageRoutine
, Context1
, Context2
);
55 CcGetFileObjectFromBcb (
58 PINTERNAL_BCB iBcb
= (PINTERNAL_BCB
)Bcb
;
60 CCTRACE(CC_API_DEBUG
, "Bcb=%p\n", Bcb
);
62 return iBcb
->Vacb
->SharedCacheMap
->FileObject
;
70 CcGetLsnForFileObject (
71 IN PFILE_OBJECT FileObject
,
72 OUT PLARGE_INTEGER OldestLsn OPTIONAL
)
76 CCTRACE(CC_API_DEBUG
, "FileObject=%p\n", FileObject
);
88 CcInitializeCacheMap (
89 IN PFILE_OBJECT FileObject
,
90 IN PCC_FILE_SIZES FileSizes
,
92 IN PCACHE_MANAGER_CALLBACKS CallBacks
,
93 IN PVOID LazyWriterContext
)
100 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileSizes=%p PinAccess=%d CallBacks=%p LazyWriterContext=%p\n",
101 FileObject
, FileSizes
, PinAccess
, CallBacks
, LazyWriterContext
);
103 /* Call old ROS cache init function */
104 Status
= CcRosInitializeFileCache(FileObject
,
109 if (!NT_SUCCESS(Status
))
110 ExRaiseStatus(Status
);
123 /* Assume no dirty data */
124 BOOLEAN Dirty
= FALSE
;
126 CCTRACE(CC_API_DEBUG
, "Vpb=%p\n", Vpb
);
128 KeAcquireGuardedMutex(&ViewLock
);
130 /* Browse dirty VACBs */
131 for (Entry
= DirtyVacbListHead
.Flink
; Entry
!= &DirtyVacbListHead
; Entry
= Entry
->Flink
)
133 Vacb
= CONTAINING_RECORD(Entry
, ROS_VACB
, DirtyVacbListEntry
);
134 /* Look for these associated with our volume */
135 if (Vacb
->SharedCacheMap
->FileObject
->Vpb
!= Vpb
)
140 /* From now on, we are associated with our VPB */
142 /* Temporary files are not counted as dirty */
143 if (BooleanFlagOn(Vacb
->SharedCacheMap
->FileObject
->Flags
, FO_TEMPORARY_FILE
))
148 /* A single dirty VACB is enough to have dirty data */
156 KeReleaseGuardedMutex(&ViewLock
);
166 CcPurgeCacheSection (
167 IN PSECTION_OBJECT_POINTERS SectionObjectPointer
,
168 IN PLARGE_INTEGER FileOffset OPTIONAL
,
170 IN BOOLEAN UninitializeCacheMaps
)
172 PROS_SHARED_CACHE_MAP SharedCacheMap
;
173 LONGLONG StartOffset
;
177 PLIST_ENTRY ListEntry
;
182 CCTRACE(CC_API_DEBUG
, "SectionObjectPointer=%p\n FileOffset=%p Length=%lu UninitializeCacheMaps=%d",
183 SectionObjectPointer
, FileOffset
, Length
, UninitializeCacheMaps
);
185 if (UninitializeCacheMaps
)
187 DPRINT1("FIXME: CcPurgeCacheSection not uninitializing private cache maps\n");
190 SharedCacheMap
= SectionObjectPointer
->SharedCacheMap
;
194 StartOffset
= FileOffset
!= NULL
? FileOffset
->QuadPart
: 0;
195 if (Length
== 0 || FileOffset
== NULL
)
197 EndOffset
= MAXLONGLONG
;
201 EndOffset
= StartOffset
+ Length
;
202 ASSERT(EndOffset
> StartOffset
);
205 InitializeListHead(&FreeList
);
210 KeAcquireGuardedMutex(&ViewLock
);
211 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &OldIrql
);
212 ListEntry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
213 while (ListEntry
!= &SharedCacheMap
->CacheMapVacbListHead
)
215 Vacb
= CONTAINING_RECORD(ListEntry
, ROS_VACB
, CacheMapVacbListEntry
);
216 ListEntry
= ListEntry
->Flink
;
218 /* Skip VACBs outside the range, or only partially in range */
219 if (Vacb
->FileOffset
.QuadPart
< StartOffset
)
223 ViewEnd
= min(Vacb
->FileOffset
.QuadPart
+ VACB_MAPPING_GRANULARITY
,
224 SharedCacheMap
->SectionSize
.QuadPart
);
225 if (ViewEnd
>= EndOffset
)
230 /* Still in use, it cannot be purged, fail */
231 if (Vacb
->ReferenceCount
!= 0 && !Vacb
->Dirty
)
237 /* This VACB is in range, so unlink it and mark for free */
238 RemoveEntryList(&Vacb
->VacbLruListEntry
);
241 RemoveEntryList(&Vacb
->DirtyVacbListEntry
);
242 CcTotalDirtyPages
-= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
244 RemoveEntryList(&Vacb
->CacheMapVacbListEntry
);
245 InsertHeadList(&FreeList
, &Vacb
->CacheMapVacbListEntry
);
247 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, OldIrql
);
248 KeReleaseGuardedMutex(&ViewLock
);
250 while (!IsListEmpty(&FreeList
))
252 Vacb
= CONTAINING_RECORD(RemoveHeadList(&FreeList
),
254 CacheMapVacbListEntry
);
255 CcRosInternalFreeVacb(Vacb
);
267 IN PFILE_OBJECT FileObject
,
268 IN PCC_FILE_SIZES FileSizes
)
271 PROS_SHARED_CACHE_MAP SharedCacheMap
;
273 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileSizes=%p\n",
274 FileObject
, FileSizes
);
276 DPRINT("CcSetFileSizes(FileObject 0x%p, FileSizes 0x%p)\n",
277 FileObject
, FileSizes
);
278 DPRINT("AllocationSize %I64d, FileSize %I64d, ValidDataLength %I64d\n",
279 FileSizes
->AllocationSize
.QuadPart
,
280 FileSizes
->FileSize
.QuadPart
,
281 FileSizes
->ValidDataLength
.QuadPart
);
283 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
286 * It is valid to call this function on file objects that weren't
287 * initialized for caching. In this case it's simple no-op.
289 if (SharedCacheMap
== NULL
)
292 if (FileSizes
->AllocationSize
.QuadPart
< SharedCacheMap
->SectionSize
.QuadPart
)
294 CcPurgeCacheSection(FileObject
->SectionObjectPointer
,
295 &FileSizes
->AllocationSize
,
300 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldirql
);
301 SharedCacheMap
->SectionSize
= FileSizes
->AllocationSize
;
302 SharedCacheMap
->FileSize
= FileSizes
->FileSize
;
303 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldirql
);
311 CcSetLogHandleForFile (
312 IN PFILE_OBJECT FileObject
,
314 IN PFLUSH_TO_LSN FlushToLsnRoutine
)
316 CCTRACE(CC_API_DEBUG
, "FileObject=%p LogHandle=%p FlushToLsnRoutine=%p\n",
317 FileObject
, LogHandle
, FlushToLsnRoutine
);
327 CcUninitializeCacheMap (
328 IN PFILE_OBJECT FileObject
,
329 IN PLARGE_INTEGER TruncateSize OPTIONAL
,
330 IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL
)
333 PROS_SHARED_CACHE_MAP SharedCacheMap
;
336 CCTRACE(CC_API_DEBUG
, "FileObject=%p TruncateSize=%p UninitializeCompleteEvent=%p\n",
337 FileObject
, TruncateSize
, UninitializeCompleteEvent
);
339 if (TruncateSize
!= NULL
&&
340 FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
342 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
343 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &OldIrql
);
344 if (SharedCacheMap
->FileSize
.QuadPart
> TruncateSize
->QuadPart
)
346 SharedCacheMap
->FileSize
= *TruncateSize
;
348 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, OldIrql
);
349 CcPurgeCacheSection(FileObject
->SectionObjectPointer
,
355 Status
= CcRosReleaseFileCache(FileObject
);
356 if (UninitializeCompleteEvent
)
358 KeSetEvent(&UninitializeCompleteEvent
->Event
, IO_NO_INCREMENT
, FALSE
);
360 return NT_SUCCESS(Status
);
366 IN PFILE_OBJECT FileObject
,
367 IN PCC_FILE_SIZES FileSizes
)
369 PROS_SHARED_CACHE_MAP SharedCacheMap
;
371 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
376 FileSizes
->AllocationSize
= SharedCacheMap
->SectionSize
;
377 FileSizes
->FileSize
= FileSizes
->ValidDataLength
= SharedCacheMap
->FileSize
;