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 NTSTATUS
CcRosInternalFreeVacb(PROS_VACB Vacb
);
20 /* FUNCTIONS *****************************************************************/
29 IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine
,
35 CCTRACE(CC_API_DEBUG
, "LogHandle=%p DirtyPageRoutine=%p Context1=%p Context2=%p\n",
36 LogHandle
, DirtyPageRoutine
, Context1
, Context2
);
48 CcGetFileObjectFromBcb (
51 PINTERNAL_BCB iBcb
= (PINTERNAL_BCB
)Bcb
;
53 CCTRACE(CC_API_DEBUG
, "Bcb=%p\n", Bcb
);
55 return iBcb
->Vacb
->SharedCacheMap
->FileObject
;
63 CcGetLsnForFileObject (
64 IN PFILE_OBJECT FileObject
,
65 OUT PLARGE_INTEGER OldestLsn OPTIONAL
)
69 CCTRACE(CC_API_DEBUG
, "FileObject=%p\n", FileObject
);
81 CcInitializeCacheMap (
82 IN PFILE_OBJECT FileObject
,
83 IN PCC_FILE_SIZES FileSizes
,
85 IN PCACHE_MANAGER_CALLBACKS CallBacks
,
86 IN PVOID LazyWriterContext
)
93 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileSizes=%p PinAccess=%d CallBacks=%p LazyWriterContext=%p\n",
94 FileObject
, FileSizes
, PinAccess
, CallBacks
, LazyWriterContext
);
96 /* Call old ROS cache init function */
97 Status
= CcRosInitializeFileCache(FileObject
,
102 if (!NT_SUCCESS(Status
))
103 ExRaiseStatus(Status
);
117 /* Assume no dirty data */
118 BOOLEAN Dirty
= FALSE
;
120 CCTRACE(CC_API_DEBUG
, "Vpb=%p\n", Vpb
);
122 oldIrql
= KeAcquireQueuedSpinLock(LockQueueMasterLock
);
124 /* Browse dirty VACBs */
125 for (Entry
= DirtyVacbListHead
.Flink
; Entry
!= &DirtyVacbListHead
; Entry
= Entry
->Flink
)
127 Vacb
= CONTAINING_RECORD(Entry
, ROS_VACB
, DirtyVacbListEntry
);
128 /* Look for these associated with our volume */
129 if (Vacb
->SharedCacheMap
->FileObject
->Vpb
!= Vpb
)
134 /* From now on, we are associated with our VPB */
136 /* Temporary files are not counted as dirty */
137 if (BooleanFlagOn(Vacb
->SharedCacheMap
->FileObject
->Flags
, FO_TEMPORARY_FILE
))
142 /* A single dirty VACB is enough to have dirty data */
150 KeReleaseQueuedSpinLock(LockQueueMasterLock
, oldIrql
);
160 CcPurgeCacheSection (
161 IN PSECTION_OBJECT_POINTERS SectionObjectPointer
,
162 IN PLARGE_INTEGER FileOffset OPTIONAL
,
164 IN BOOLEAN UninitializeCacheMaps
)
166 PROS_SHARED_CACHE_MAP SharedCacheMap
;
167 LONGLONG StartOffset
;
171 PLIST_ENTRY ListEntry
;
176 CCTRACE(CC_API_DEBUG
, "SectionObjectPointer=%p\n FileOffset=%p Length=%lu UninitializeCacheMaps=%d",
177 SectionObjectPointer
, FileOffset
, Length
, UninitializeCacheMaps
);
179 if (UninitializeCacheMaps
)
181 DPRINT1("FIXME: CcPurgeCacheSection not uninitializing private cache maps\n");
184 SharedCacheMap
= SectionObjectPointer
->SharedCacheMap
;
188 StartOffset
= FileOffset
!= NULL
? FileOffset
->QuadPart
: 0;
189 if (Length
== 0 || FileOffset
== NULL
)
191 EndOffset
= MAXLONGLONG
;
195 EndOffset
= StartOffset
+ Length
;
196 ASSERT(EndOffset
> StartOffset
);
199 InitializeListHead(&FreeList
);
204 OldIrql
= KeAcquireQueuedSpinLock(LockQueueMasterLock
);
205 KeAcquireSpinLockAtDpcLevel(&SharedCacheMap
->CacheMapLock
);
206 ListEntry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
207 while (ListEntry
!= &SharedCacheMap
->CacheMapVacbListHead
)
211 Vacb
= CONTAINING_RECORD(ListEntry
, ROS_VACB
, CacheMapVacbListEntry
);
212 ListEntry
= ListEntry
->Flink
;
214 /* Skip VACBs outside the range, or only partially in range */
215 if (Vacb
->FileOffset
.QuadPart
< StartOffset
)
219 ViewEnd
= min(Vacb
->FileOffset
.QuadPart
+ VACB_MAPPING_GRANULARITY
,
220 SharedCacheMap
->SectionSize
.QuadPart
);
221 if (ViewEnd
>= EndOffset
)
226 /* Still in use, it cannot be purged, fail
227 * Allow one ref: VACB is supposed to be always 1-referenced
229 Refs
= CcRosVacbGetRefCount(Vacb
);
230 if ((Refs
> 1 && !Vacb
->Dirty
) ||
231 (Refs
> 2 && Vacb
->Dirty
))
237 /* This VACB is in range, so unlink it and mark for free */
238 ASSERT(Refs
== 1 || Vacb
->Dirty
);
239 RemoveEntryList(&Vacb
->VacbLruListEntry
);
240 InitializeListHead(&Vacb
->VacbLruListEntry
);
243 CcRosUnmarkDirtyVacb(Vacb
, FALSE
);
245 RemoveEntryList(&Vacb
->CacheMapVacbListEntry
);
246 InsertHeadList(&FreeList
, &Vacb
->CacheMapVacbListEntry
);
248 KeReleaseSpinLockFromDpcLevel(&SharedCacheMap
->CacheMapLock
);
249 KeReleaseQueuedSpinLock(LockQueueMasterLock
, OldIrql
);
251 while (!IsListEmpty(&FreeList
))
255 Vacb
= CONTAINING_RECORD(RemoveHeadList(&FreeList
),
257 CacheMapVacbListEntry
);
258 InitializeListHead(&Vacb
->CacheMapVacbListEntry
);
259 Refs
= CcRosVacbDecRefCount(Vacb
);
272 IN PFILE_OBJECT FileObject
,
273 IN PCC_FILE_SIZES FileSizes
)
276 PROS_SHARED_CACHE_MAP SharedCacheMap
;
278 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileSizes=%p\n",
279 FileObject
, FileSizes
);
281 DPRINT("CcSetFileSizes(FileObject 0x%p, FileSizes 0x%p)\n",
282 FileObject
, FileSizes
);
283 DPRINT("AllocationSize %I64d, FileSize %I64d, ValidDataLength %I64d\n",
284 FileSizes
->AllocationSize
.QuadPart
,
285 FileSizes
->FileSize
.QuadPart
,
286 FileSizes
->ValidDataLength
.QuadPart
);
288 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
291 * It is valid to call this function on file objects that weren't
292 * initialized for caching. In this case it's simple no-op.
294 if (SharedCacheMap
== NULL
)
297 if (FileSizes
->AllocationSize
.QuadPart
< SharedCacheMap
->SectionSize
.QuadPart
)
299 CcPurgeCacheSection(FileObject
->SectionObjectPointer
,
300 &FileSizes
->AllocationSize
,
305 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldirql
);
306 SharedCacheMap
->SectionSize
= FileSizes
->AllocationSize
;
307 SharedCacheMap
->FileSize
= FileSizes
->FileSize
;
308 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldirql
);
316 CcSetLogHandleForFile (
317 IN PFILE_OBJECT FileObject
,
319 IN PFLUSH_TO_LSN FlushToLsnRoutine
)
321 CCTRACE(CC_API_DEBUG
, "FileObject=%p LogHandle=%p FlushToLsnRoutine=%p\n",
322 FileObject
, LogHandle
, FlushToLsnRoutine
);
332 CcUninitializeCacheMap (
333 IN PFILE_OBJECT FileObject
,
334 IN PLARGE_INTEGER TruncateSize OPTIONAL
,
335 IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL
)
338 PROS_SHARED_CACHE_MAP SharedCacheMap
;
341 CCTRACE(CC_API_DEBUG
, "FileObject=%p TruncateSize=%p UninitializeCompleteEvent=%p\n",
342 FileObject
, TruncateSize
, UninitializeCompleteEvent
);
344 if (TruncateSize
!= NULL
&&
345 FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
347 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
348 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &OldIrql
);
349 if (SharedCacheMap
->FileSize
.QuadPart
> TruncateSize
->QuadPart
)
351 SharedCacheMap
->FileSize
= *TruncateSize
;
353 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, OldIrql
);
354 CcPurgeCacheSection(FileObject
->SectionObjectPointer
,
360 Status
= CcRosReleaseFileCache(FileObject
);
361 if (UninitializeCompleteEvent
)
363 KeSetEvent(&UninitializeCompleteEvent
->Event
, IO_NO_INCREMENT
, FALSE
);
365 return NT_SUCCESS(Status
);
371 IN PFILE_OBJECT FileObject
,
372 IN PCC_FILE_SIZES FileSizes
)
374 PROS_SHARED_CACHE_MAP SharedCacheMap
;
376 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
381 FileSizes
->AllocationSize
= SharedCacheMap
->SectionSize
;
382 FileSizes
->FileSize
= FileSizes
->ValidDataLength
= SharedCacheMap
->FileSize
;