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 /* GLOBALS *****************************************************************/
18 extern KGUARDED_MUTEX ViewLock
;
20 NTSTATUS
CcRosInternalFreeVacb(PROS_VACB Vacb
);
22 /* FUNCTIONS *****************************************************************/
31 IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine
,
37 CCTRACE(CC_API_DEBUG
, "LogHandle=%p DirtyPageRoutine=%p Context1=%p Context2=%p\n",
38 LogHandle
, DirtyPageRoutine
, Context1
, Context2
);
50 CcGetFileObjectFromBcb (
53 PINTERNAL_BCB iBcb
= (PINTERNAL_BCB
)Bcb
;
55 CCTRACE(CC_API_DEBUG
, "Bcb=%p\n", Bcb
);
57 return iBcb
->Vacb
->SharedCacheMap
->FileObject
;
65 CcGetLsnForFileObject (
66 IN PFILE_OBJECT FileObject
,
67 OUT PLARGE_INTEGER OldestLsn OPTIONAL
)
71 CCTRACE(CC_API_DEBUG
, "FileObject=%p\n", FileObject
);
83 CcInitializeCacheMap (
84 IN PFILE_OBJECT FileObject
,
85 IN PCC_FILE_SIZES FileSizes
,
87 IN PCACHE_MANAGER_CALLBACKS CallBacks
,
88 IN PVOID LazyWriterContext
)
95 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileSizes=%p PinAccess=%d CallBacks=%p LazyWriterContext=%p\n",
96 FileObject
, FileSizes
, PinAccess
, CallBacks
, LazyWriterContext
);
98 /* Call old ROS cache init function */
99 Status
= CcRosInitializeFileCache(FileObject
,
104 if (!NT_SUCCESS(Status
))
105 ExRaiseStatus(Status
);
118 /* Assume no dirty data */
119 BOOLEAN Dirty
= FALSE
;
121 CCTRACE(CC_API_DEBUG
, "Vpb=%p\n", Vpb
);
123 KeAcquireGuardedMutex(&ViewLock
);
125 /* Browse dirty VACBs */
126 for (Entry
= DirtyVacbListHead
.Flink
; Entry
!= &DirtyVacbListHead
; Entry
= Entry
->Flink
)
128 Vacb
= CONTAINING_RECORD(Entry
, ROS_VACB
, DirtyVacbListEntry
);
129 /* Look for these associated with our volume */
130 if (Vacb
->SharedCacheMap
->FileObject
->Vpb
!= Vpb
)
135 /* From now on, we are associated with our VPB */
137 /* Temporary files are not counted as dirty */
138 if (BooleanFlagOn(Vacb
->SharedCacheMap
->FileObject
->Flags
, FO_TEMPORARY_FILE
))
143 /* A single dirty VACB is enough to have dirty data */
151 KeReleaseGuardedMutex(&ViewLock
);
161 CcPurgeCacheSection (
162 IN PSECTION_OBJECT_POINTERS SectionObjectPointer
,
163 IN PLARGE_INTEGER FileOffset OPTIONAL
,
165 IN BOOLEAN UninitializeCacheMaps
)
167 PROS_SHARED_CACHE_MAP SharedCacheMap
;
168 LONGLONG StartOffset
;
172 PLIST_ENTRY ListEntry
;
177 CCTRACE(CC_API_DEBUG
, "SectionObjectPointer=%p\n FileOffset=%p Length=%lu UninitializeCacheMaps=%d",
178 SectionObjectPointer
, FileOffset
, Length
, UninitializeCacheMaps
);
180 if (UninitializeCacheMaps
)
182 DPRINT1("FIXME: CcPurgeCacheSection not uninitializing private cache maps\n");
185 SharedCacheMap
= SectionObjectPointer
->SharedCacheMap
;
189 StartOffset
= FileOffset
!= NULL
? FileOffset
->QuadPart
: 0;
190 if (Length
== 0 || FileOffset
== NULL
)
192 EndOffset
= MAXLONGLONG
;
196 EndOffset
= StartOffset
+ Length
;
197 ASSERT(EndOffset
> StartOffset
);
200 InitializeListHead(&FreeList
);
205 KeAcquireGuardedMutex(&ViewLock
);
206 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &OldIrql
);
207 ListEntry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
208 while (ListEntry
!= &SharedCacheMap
->CacheMapVacbListHead
)
212 Vacb
= CONTAINING_RECORD(ListEntry
, ROS_VACB
, CacheMapVacbListEntry
);
213 ListEntry
= ListEntry
->Flink
;
215 /* Skip VACBs outside the range, or only partially in range */
216 if (Vacb
->FileOffset
.QuadPart
< StartOffset
)
220 ViewEnd
= min(Vacb
->FileOffset
.QuadPart
+ VACB_MAPPING_GRANULARITY
,
221 SharedCacheMap
->SectionSize
.QuadPart
);
222 if (ViewEnd
>= EndOffset
)
227 /* Still in use, it cannot be purged, fail
228 * Allow one ref: VACB is supposed to be always 1-referenced
230 Refs
= CcRosVacbGetRefCount(Vacb
);
231 if ((Refs
> 1 && !Vacb
->Dirty
) ||
232 (Refs
> 2 && Vacb
->Dirty
))
238 /* This VACB is in range, so unlink it and mark for free */
239 ASSERT(Refs
== 1 || Vacb
->Dirty
);
240 RemoveEntryList(&Vacb
->VacbLruListEntry
);
241 InitializeListHead(&Vacb
->VacbLruListEntry
);
244 CcRosUnmarkDirtyVacb(Vacb
, FALSE
);
246 RemoveEntryList(&Vacb
->CacheMapVacbListEntry
);
247 InsertHeadList(&FreeList
, &Vacb
->CacheMapVacbListEntry
);
249 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, OldIrql
);
250 KeReleaseGuardedMutex(&ViewLock
);
252 while (!IsListEmpty(&FreeList
))
256 Vacb
= CONTAINING_RECORD(RemoveHeadList(&FreeList
),
258 CacheMapVacbListEntry
);
259 InitializeListHead(&Vacb
->CacheMapVacbListEntry
);
260 Refs
= CcRosVacbDecRefCount(Vacb
);
273 IN PFILE_OBJECT FileObject
,
274 IN PCC_FILE_SIZES FileSizes
)
277 PROS_SHARED_CACHE_MAP SharedCacheMap
;
279 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileSizes=%p\n",
280 FileObject
, FileSizes
);
282 DPRINT("CcSetFileSizes(FileObject 0x%p, FileSizes 0x%p)\n",
283 FileObject
, FileSizes
);
284 DPRINT("AllocationSize %I64d, FileSize %I64d, ValidDataLength %I64d\n",
285 FileSizes
->AllocationSize
.QuadPart
,
286 FileSizes
->FileSize
.QuadPart
,
287 FileSizes
->ValidDataLength
.QuadPart
);
289 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
292 * It is valid to call this function on file objects that weren't
293 * initialized for caching. In this case it's simple no-op.
295 if (SharedCacheMap
== NULL
)
298 if (FileSizes
->AllocationSize
.QuadPart
< SharedCacheMap
->SectionSize
.QuadPart
)
300 CcPurgeCacheSection(FileObject
->SectionObjectPointer
,
301 &FileSizes
->AllocationSize
,
306 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldirql
);
307 SharedCacheMap
->SectionSize
= FileSizes
->AllocationSize
;
308 SharedCacheMap
->FileSize
= FileSizes
->FileSize
;
309 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldirql
);
317 CcSetLogHandleForFile (
318 IN PFILE_OBJECT FileObject
,
320 IN PFLUSH_TO_LSN FlushToLsnRoutine
)
322 CCTRACE(CC_API_DEBUG
, "FileObject=%p LogHandle=%p FlushToLsnRoutine=%p\n",
323 FileObject
, LogHandle
, FlushToLsnRoutine
);
333 CcUninitializeCacheMap (
334 IN PFILE_OBJECT FileObject
,
335 IN PLARGE_INTEGER TruncateSize OPTIONAL
,
336 IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL
)
339 PROS_SHARED_CACHE_MAP SharedCacheMap
;
342 CCTRACE(CC_API_DEBUG
, "FileObject=%p TruncateSize=%p UninitializeCompleteEvent=%p\n",
343 FileObject
, TruncateSize
, UninitializeCompleteEvent
);
345 if (TruncateSize
!= NULL
&&
346 FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
348 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
349 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &OldIrql
);
350 if (SharedCacheMap
->FileSize
.QuadPart
> TruncateSize
->QuadPart
)
352 SharedCacheMap
->FileSize
= *TruncateSize
;
354 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, OldIrql
);
355 CcPurgeCacheSection(FileObject
->SectionObjectPointer
,
361 Status
= CcRosReleaseFileCache(FileObject
);
362 if (UninitializeCompleteEvent
)
364 KeSetEvent(&UninitializeCompleteEvent
->Event
, IO_NO_INCREMENT
, FALSE
);
366 return NT_SUCCESS(Status
);
372 IN PFILE_OBJECT FileObject
,
373 IN PCC_FILE_SIZES FileSizes
)
375 PROS_SHARED_CACHE_MAP SharedCacheMap
;
377 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
382 FileSizes
->AllocationSize
= SharedCacheMap
->SectionSize
;
383 FileSizes
->FileSize
= FileSizes
->ValidDataLength
= SharedCacheMap
->FileSize
;