#define NDEBUG
#include <debug.h>
-#ifndef VACB_MAPPING_GRANULARITY
-#define VACB_MAPPING_GRANULARITY (256 * 1024)
-#endif
-
/* GLOBALS *****************************************************************/
extern KGUARDED_MUTEX ViewLock;
-extern ULONG DirtyPageCount;
-NTSTATUS CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg);
+NTSTATUS CcRosInternalFreeVacb(PROS_VACB Vacb);
/* FUNCTIONS *****************************************************************/
LARGE_INTEGER
NTAPI
CcGetDirtyPages (
- IN PVOID LogHandle,
- IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine,
- IN PVOID Context1,
- IN PVOID Context2
- )
+ IN PVOID LogHandle,
+ IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine,
+ IN PVOID Context1,
+ IN PVOID Context2)
{
- LARGE_INTEGER i;
- UNIMPLEMENTED;
- i.QuadPart = 0;
- return i;
+ LARGE_INTEGER i;
+
+ CCTRACE(CC_API_DEBUG, "LogHandle=%p DirtyPageRoutine=%p Context1=%p Context2=%p\n",
+ LogHandle, DirtyPageRoutine, Context1, Context2);
+
+ UNIMPLEMENTED;
+ i.QuadPart = 0;
+ return i;
}
/*
PFILE_OBJECT
NTAPI
CcGetFileObjectFromBcb (
- IN PVOID Bcb
- )
+ IN PVOID Bcb)
{
- PINTERNAL_BCB iBcb = (PINTERNAL_BCB)Bcb;
- return iBcb->CacheSegment->Bcb->FileObject;
+ PINTERNAL_BCB iBcb = (PINTERNAL_BCB)Bcb;
+
+ CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
+
+ return iBcb->Vacb->SharedCacheMap->FileObject;
}
/*
LARGE_INTEGER
NTAPI
CcGetLsnForFileObject (
- IN PFILE_OBJECT FileObject,
- OUT PLARGE_INTEGER OldestLsn OPTIONAL
- )
+ IN PFILE_OBJECT FileObject,
+ OUT PLARGE_INTEGER OldestLsn OPTIONAL)
{
- LARGE_INTEGER i;
- UNIMPLEMENTED;
- i.QuadPart = 0;
- return i;
+ LARGE_INTEGER i;
+
+ CCTRACE(CC_API_DEBUG, "FileObject=%p\n", FileObject);
+
+ UNIMPLEMENTED;
+ i.QuadPart = 0;
+ return i;
}
/*
VOID
NTAPI
CcInitializeCacheMap (
- IN PFILE_OBJECT FileObject,
- IN PCC_FILE_SIZES FileSizes,
- IN BOOLEAN PinAccess,
- IN PCACHE_MANAGER_CALLBACKS CallBacks,
- IN PVOID LazyWriterContext
- )
+ IN PFILE_OBJECT FileObject,
+ IN PCC_FILE_SIZES FileSizes,
+ IN BOOLEAN PinAccess,
+ IN PCACHE_MANAGER_CALLBACKS CallBacks,
+ IN PVOID LazyWriterContext)
{
+ NTSTATUS Status;
+
ASSERT(FileObject);
ASSERT(FileSizes);
+ CCTRACE(CC_API_DEBUG, "FileObject=%p FileSizes=%p PinAccess=%d CallBacks=%p LazyWriterContext=%p\n",
+ FileObject, FileSizes, PinAccess, CallBacks, LazyWriterContext);
+
/* Call old ROS cache init function */
- CcRosInitializeFileCache(FileObject,
- /*PAGE_SIZE*/ VACB_MAPPING_GRANULARITY, CallBacks,
- LazyWriterContext);
+ Status = CcRosInitializeFileCache(FileObject,
+ FileSizes,
+ PinAccess,
+ CallBacks,
+ LazyWriterContext);
+ if (!NT_SUCCESS(Status))
+ ExRaiseStatus(Status);
}
/*
- * @unimplemented
+ * @implemented
*/
BOOLEAN
NTAPI
CcIsThereDirtyData (
- IN PVPB Vpb
- )
+ IN PVPB Vpb)
{
- UNIMPLEMENTED;
- return FALSE;
+ PROS_VACB Vacb;
+ PLIST_ENTRY Entry;
+ /* Assume no dirty data */
+ BOOLEAN Dirty = FALSE;
+
+ CCTRACE(CC_API_DEBUG, "Vpb=%p\n", Vpb);
+
+ KeAcquireGuardedMutex(&ViewLock);
+
+ /* Browse dirty VACBs */
+ for (Entry = DirtyVacbListHead.Flink; Entry != &DirtyVacbListHead; Entry = Entry->Flink)
+ {
+ Vacb = CONTAINING_RECORD(Entry, ROS_VACB, DirtyVacbListEntry);
+ /* Look for these associated with our volume */
+ if (Vacb->SharedCacheMap->FileObject->Vpb != Vpb)
+ {
+ continue;
+ }
+
+ /* From now on, we are associated with our VPB */
+
+ /* Temporary files are not counted as dirty */
+ if (BooleanFlagOn(Vacb->SharedCacheMap->FileObject->Flags, FO_TEMPORARY_FILE))
+ {
+ continue;
+ }
+
+ /* A single dirty VACB is enough to have dirty data */
+ if (Vacb->Dirty)
+ {
+ Dirty = TRUE;
+ break;
+ }
+ }
+
+ KeReleaseGuardedMutex(&ViewLock);
+
+ return Dirty;
}
/*
BOOLEAN
NTAPI
CcPurgeCacheSection (
- IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
- IN PLARGE_INTEGER FileOffset OPTIONAL,
- IN ULONG Length,
- IN BOOLEAN UninitializeCacheMaps
- )
+ IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
+ IN PLARGE_INTEGER FileOffset OPTIONAL,
+ IN ULONG Length,
+ IN BOOLEAN UninitializeCacheMaps)
{
- //UNIMPLEMENTED;
- return FALSE;
+ PROS_SHARED_CACHE_MAP SharedCacheMap;
+ LONGLONG StartOffset;
+ LONGLONG EndOffset;
+ LIST_ENTRY FreeList;
+ KIRQL OldIrql;
+ PLIST_ENTRY ListEntry;
+ PROS_VACB Vacb;
+ LONGLONG ViewEnd;
+ BOOLEAN Success;
+
+ CCTRACE(CC_API_DEBUG, "SectionObjectPointer=%p\n FileOffset=%p Length=%lu UninitializeCacheMaps=%d",
+ SectionObjectPointer, FileOffset, Length, UninitializeCacheMaps);
+
+ if (UninitializeCacheMaps)
+ {
+ DPRINT1("FIXME: CcPurgeCacheSection not uninitializing private cache maps\n");
+ }
+
+ SharedCacheMap = SectionObjectPointer->SharedCacheMap;
+ if (!SharedCacheMap)
+ return FALSE;
+
+ StartOffset = FileOffset != NULL ? FileOffset->QuadPart : 0;
+ if (Length == 0 || FileOffset == NULL)
+ {
+ EndOffset = MAXLONGLONG;
+ }
+ else
+ {
+ EndOffset = StartOffset + Length;
+ ASSERT(EndOffset > StartOffset);
+ }
+
+ InitializeListHead(&FreeList);
+
+ /* Assume success */
+ Success = TRUE;
+
+ KeAcquireGuardedMutex(&ViewLock);
+ KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &OldIrql);
+ ListEntry = SharedCacheMap->CacheMapVacbListHead.Flink;
+ while (ListEntry != &SharedCacheMap->CacheMapVacbListHead)
+ {
+ Vacb = CONTAINING_RECORD(ListEntry, ROS_VACB, CacheMapVacbListEntry);
+ ListEntry = ListEntry->Flink;
+
+ /* Skip VACBs outside the range, or only partially in range */
+ if (Vacb->FileOffset.QuadPart < StartOffset)
+ {
+ continue;
+ }
+ ViewEnd = min(Vacb->FileOffset.QuadPart + VACB_MAPPING_GRANULARITY,
+ SharedCacheMap->SectionSize.QuadPart);
+ if (ViewEnd >= EndOffset)
+ {
+ break;
+ }
+
+ /* Still in use, it cannot be purged, fail */
+ if (Vacb->ReferenceCount != 0 && !Vacb->Dirty)
+ {
+ Success = FALSE;
+ break;
+ }
+
+ /* This VACB is in range, so unlink it and mark for free */
+ RemoveEntryList(&Vacb->VacbLruListEntry);
+ if (Vacb->Dirty)
+ {
+ CcRosUnmarkDirtyVacb(Vacb, FALSE);
+ }
+ RemoveEntryList(&Vacb->CacheMapVacbListEntry);
+ InsertHeadList(&FreeList, &Vacb->CacheMapVacbListEntry);
+ }
+ KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql);
+ KeReleaseGuardedMutex(&ViewLock);
+
+ while (!IsListEmpty(&FreeList))
+ {
+ Vacb = CONTAINING_RECORD(RemoveHeadList(&FreeList),
+ ROS_VACB,
+ CacheMapVacbListEntry);
+ CcRosInternalFreeVacb(Vacb);
+ }
+
+ return Success;
}
* @implemented
*/
VOID NTAPI
-CcSetFileSizes (IN PFILE_OBJECT FileObject,
- IN PCC_FILE_SIZES FileSizes)
+CcSetFileSizes (
+ IN PFILE_OBJECT FileObject,
+ IN PCC_FILE_SIZES FileSizes)
{
- KIRQL oldirql;
- PBCB Bcb;
- PLIST_ENTRY current_entry;
- PCACHE_SEGMENT current;
- LIST_ENTRY FreeListHead;
- NTSTATUS Status;
-
- DPRINT("CcSetFileSizes(FileObject 0x%p, FileSizes 0x%p)\n",
- FileObject, FileSizes);
- DPRINT("AllocationSize %d, FileSize %d, ValidDataLength %d\n",
- (ULONG)FileSizes->AllocationSize.QuadPart,
- (ULONG)FileSizes->FileSize.QuadPart,
- (ULONG)FileSizes->ValidDataLength.QuadPart);
-
- Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
-
- /*
- * It is valid to call this function on file objects that weren't
- * initialized for caching. In this case it's simple no-op.
- */
- if (Bcb == NULL)
- return;
-
- if (FileSizes->AllocationSize.QuadPart < Bcb->AllocationSize.QuadPart)
- {
- InitializeListHead(&FreeListHead);
- KeAcquireGuardedMutex(&ViewLock);
- KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
-
- current_entry = Bcb->BcbSegmentListHead.Flink;
- while (current_entry != &Bcb->BcbSegmentListHead)
- {
- current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
- current_entry = current_entry->Flink;
- if (current->FileOffset > FileSizes->AllocationSize.QuadPart ||
- (current->FileOffset == 0 && FileSizes->AllocationSize.QuadPart == 0))
- {
- if (current->ReferenceCount == 0 || (current->ReferenceCount == 1 && current->Dirty))
- {
- RemoveEntryList(¤t->BcbSegmentListEntry);
- RemoveEntryList(¤t->CacheSegmentListEntry);
- RemoveEntryList(¤t->CacheSegmentLRUListEntry);
- if (current->Dirty)
- {
- RemoveEntryList(¤t->DirtySegmentListEntry);
- DirtyPageCount -= Bcb->CacheSegmentSize / PAGE_SIZE;
- }
- InsertHeadList(&FreeListHead, ¤t->BcbSegmentListEntry);
- }
- else
- {
- DPRINT1("Anyone has referenced a cache segment behind the new size.\n");
- KeBugCheck(CACHE_MANAGER);
- }
- }
- }
-
- Bcb->AllocationSize = FileSizes->AllocationSize;
- Bcb->FileSize = FileSizes->FileSize;
- KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
- KeReleaseGuardedMutex(&ViewLock);
-
- current_entry = FreeListHead.Flink;
- while(current_entry != &FreeListHead)
- {
- current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
- current_entry = current_entry->Flink;
- Status = CcRosInternalFreeCacheSegment(current);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CcRosInternalFreeCacheSegment failed, status = %x\n", Status);
- KeBugCheck(CACHE_MANAGER);
- }
- }
- }
- else
- {
- KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
- Bcb->AllocationSize = FileSizes->AllocationSize;
- Bcb->FileSize = FileSizes->FileSize;
- KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
- }
+ KIRQL oldirql;
+ PROS_SHARED_CACHE_MAP SharedCacheMap;
+
+ CCTRACE(CC_API_DEBUG, "FileObject=%p FileSizes=%p\n",
+ FileObject, FileSizes);
+
+ DPRINT("CcSetFileSizes(FileObject 0x%p, FileSizes 0x%p)\n",
+ FileObject, FileSizes);
+ DPRINT("AllocationSize %I64d, FileSize %I64d, ValidDataLength %I64d\n",
+ FileSizes->AllocationSize.QuadPart,
+ FileSizes->FileSize.QuadPart,
+ FileSizes->ValidDataLength.QuadPart);
+
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
+
+ /*
+ * It is valid to call this function on file objects that weren't
+ * initialized for caching. In this case it's simple no-op.
+ */
+ if (SharedCacheMap == NULL)
+ return;
+
+ if (FileSizes->AllocationSize.QuadPart < SharedCacheMap->SectionSize.QuadPart)
+ {
+ CcPurgeCacheSection(FileObject->SectionObjectPointer,
+ &FileSizes->AllocationSize,
+ 0,
+ FALSE);
+ }
+
+ KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldirql);
+ SharedCacheMap->SectionSize = FileSizes->AllocationSize;
+ SharedCacheMap->FileSize = FileSizes->FileSize;
+ KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
}
/*
VOID
NTAPI
CcSetLogHandleForFile (
- IN PFILE_OBJECT FileObject,
- IN PVOID LogHandle,
- IN PFLUSH_TO_LSN FlushToLsnRoutine
- )
+ IN PFILE_OBJECT FileObject,
+ IN PVOID LogHandle,
+ IN PFLUSH_TO_LSN FlushToLsnRoutine)
{
- UNIMPLEMENTED;
+ CCTRACE(CC_API_DEBUG, "FileObject=%p LogHandle=%p FlushToLsnRoutine=%p\n",
+ FileObject, LogHandle, FlushToLsnRoutine);
+
+ UNIMPLEMENTED;
}
/*
BOOLEAN
NTAPI
CcUninitializeCacheMap (
- IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER TruncateSize OPTIONAL,
- IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL
- )
+ IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER TruncateSize OPTIONAL,
+ IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL)
{
-#if 0
- UNIMPLEMENTED;
- return FALSE;
-#else
- return NT_SUCCESS(CcRosReleaseFileCache(FileObject));
-#endif
+ NTSTATUS Status;
+ PROS_SHARED_CACHE_MAP SharedCacheMap;
+ KIRQL OldIrql;
+
+ CCTRACE(CC_API_DEBUG, "FileObject=%p TruncateSize=%p UninitializeCompleteEvent=%p\n",
+ FileObject, TruncateSize, UninitializeCompleteEvent);
+
+ if (TruncateSize != NULL &&
+ FileObject->SectionObjectPointer->SharedCacheMap != NULL)
+ {
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
+ KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &OldIrql);
+ if (SharedCacheMap->FileSize.QuadPart > TruncateSize->QuadPart)
+ {
+ SharedCacheMap->FileSize = *TruncateSize;
+ }
+ KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql);
+ CcPurgeCacheSection(FileObject->SectionObjectPointer,
+ TruncateSize,
+ 0,
+ FALSE);
+ }
+
+ Status = CcRosReleaseFileCache(FileObject);
+ if (UninitializeCompleteEvent)
+ {
+ KeSetEvent(&UninitializeCompleteEvent->Event, IO_NO_INCREMENT, FALSE);
+ }
+ return NT_SUCCESS(Status);
}
BOOLEAN
NTAPI
-CcGetFileSizes
-(IN PFILE_OBJECT FileObject,
- IN PCC_FILE_SIZES FileSizes)
+CcGetFileSizes (
+ IN PFILE_OBJECT FileObject,
+ IN PCC_FILE_SIZES FileSizes)
{
- PBCB Bcb;
-
- Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+ PROS_SHARED_CACHE_MAP SharedCacheMap;
+
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
- if (!Bcb)
- return FALSE;
+ if (!SharedCacheMap)
+ return FALSE;
- FileSizes->AllocationSize = Bcb->AllocationSize;
- FileSizes->FileSize = FileSizes->ValidDataLength = Bcb->FileSize;
- return TRUE;
+ FileSizes->AllocationSize = SharedCacheMap->SectionSize;
+ FileSizes->FileSize = FileSizes->ValidDataLength = SharedCacheMap->FileSize;
+ return TRUE;
}