/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
+
#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 CcRosInternalFreeVacb(PROS_VACB Vacb);
-
/* FUNCTIONS *****************************************************************/
/*
CcGetFileObjectFromBcb (
IN PVOID Bcb)
{
- PINTERNAL_BCB iBcb = (PINTERNAL_BCB)Bcb;
+ PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB);
CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
{
PROS_VACB Vacb;
PLIST_ENTRY Entry;
+ KIRQL oldIrql;
/* Assume no dirty data */
BOOLEAN Dirty = FALSE;
CCTRACE(CC_API_DEBUG, "Vpb=%p\n", Vpb);
- KeAcquireGuardedMutex(&ViewLock);
+ oldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
/* Browse dirty VACBs */
for (Entry = DirtyVacbListHead.Flink; Entry != &DirtyVacbListHead; Entry = Entry->Flink)
}
}
- KeReleaseGuardedMutex(&ViewLock);
+ KeReleaseQueuedSpinLock(LockQueueMasterLock, oldIrql);
return Dirty;
}
IN BOOLEAN UninitializeCacheMaps)
{
PROS_SHARED_CACHE_MAP SharedCacheMap;
+ PPRIVATE_CACHE_MAP PrivateCacheMap;
LONGLONG StartOffset;
LONGLONG EndOffset;
LIST_ENTRY FreeList;
CCTRACE(CC_API_DEBUG, "SectionObjectPointer=%p\n FileOffset=%p Length=%lu UninitializeCacheMaps=%d",
SectionObjectPointer, FileOffset, Length, UninitializeCacheMaps);
- if (UninitializeCacheMaps)
+ /* Obtain the shared cache from the section */
+ SharedCacheMap = SectionObjectPointer->SharedCacheMap;
+ if (!SharedCacheMap)
{
- DPRINT1("FIXME: CcPurgeCacheSection not uninitializing private cache maps\n");
+ Success = TRUE;
+ goto purgeMm;
}
- SharedCacheMap = SectionObjectPointer->SharedCacheMap;
- if (!SharedCacheMap)
- return FALSE;
+ if (UninitializeCacheMaps)
+ {
+ /*
+ * We have gotten the acknowledgement that
+ * the caller wants to unintialize the private
+ * cache maps so let's do this. Since we already
+ * have the shared cache map from above, iterate
+ * over that cache's private lists.
+ */
+ while (!IsListEmpty(&SharedCacheMap->PrivateList))
+ {
+ /*
+ * This list is not empty, grab the
+ * private cache map.
+ */
+ PrivateCacheMap = CONTAINING_RECORD(SharedCacheMap->PrivateList.Flink, PRIVATE_CACHE_MAP, PrivateLinks);
+
+ /* Unintialize the private cache now */
+ CcUninitializeCacheMap(PrivateCacheMap->FileObject, NULL, NULL);
+ }
+ }
StartOffset = FileOffset != NULL ? FileOffset->QuadPart : 0;
if (Length == 0 || FileOffset == NULL)
/* Assume success */
Success = TRUE;
- KeAcquireGuardedMutex(&ViewLock);
- KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &OldIrql);
+ OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
+ KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock);
ListEntry = SharedCacheMap->CacheMapVacbListHead.Flink;
while (ListEntry != &SharedCacheMap->CacheMapVacbListHead)
{
+ ULONG Refs;
+
Vacb = CONTAINING_RECORD(ListEntry, ROS_VACB, CacheMapVacbListEntry);
ListEntry = ListEntry->Flink;
break;
}
- /* Still in use, it cannot be purged, fail */
- if (Vacb->ReferenceCount != 0 && !Vacb->Dirty)
+ /* Still in use, it cannot be purged, fail
+ * Allow one ref: VACB is supposed to be always 1-referenced
+ */
+ Refs = CcRosVacbGetRefCount(Vacb);
+ if ((Refs > 1 && !Vacb->Dirty) ||
+ (Refs > 2 && Vacb->Dirty))
{
Success = FALSE;
break;
}
/* This VACB is in range, so unlink it and mark for free */
+ ASSERT(Refs == 1 || Vacb->Dirty);
RemoveEntryList(&Vacb->VacbLruListEntry);
+ InitializeListHead(&Vacb->VacbLruListEntry);
if (Vacb->Dirty)
{
- RemoveEntryList(&Vacb->DirtyVacbListEntry);
- DirtyPageCount -= VACB_MAPPING_GRANULARITY / PAGE_SIZE;
+ CcRosUnmarkDirtyVacb(Vacb, FALSE);
}
RemoveEntryList(&Vacb->CacheMapVacbListEntry);
InsertHeadList(&FreeList, &Vacb->CacheMapVacbListEntry);
}
- KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql);
- KeReleaseGuardedMutex(&ViewLock);
+ KeReleaseSpinLockFromDpcLevel(&SharedCacheMap->CacheMapLock);
+ KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
while (!IsListEmpty(&FreeList))
{
+ ULONG Refs;
+
Vacb = CONTAINING_RECORD(RemoveHeadList(&FreeList),
ROS_VACB,
CacheMapVacbListEntry);
- CcRosInternalFreeVacb(Vacb);
+ InitializeListHead(&Vacb->CacheMapVacbListEntry);
+ Refs = CcRosVacbDecRefCount(Vacb);
+ ASSERT(Refs == 0);
}
+ /* Now make sure that Mm doesn't hold some pages here. */
+purgeMm:
+ if (Success)
+ Success = MmPurgeSegment(SectionObjectPointer, FileOffset, Length);
+
return Success;
}
IN PFILE_OBJECT FileObject,
IN PCC_FILE_SIZES FileSizes)
{
- KIRQL oldirql;
+ KIRQL OldIrql;
PROS_SHARED_CACHE_MAP SharedCacheMap;
+ LARGE_INTEGER OldSectionSize;
CCTRACE(CC_API_DEBUG, "FileObject=%p FileSizes=%p\n",
FileObject, FileSizes);
if (SharedCacheMap == NULL)
return;
- if (FileSizes->AllocationSize.QuadPart < SharedCacheMap->SectionSize.QuadPart)
+ /* Update the relevant fields */
+ KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &OldIrql);
+ OldSectionSize = SharedCacheMap->SectionSize;
+ SharedCacheMap->SectionSize = FileSizes->AllocationSize;
+ SharedCacheMap->FileSize = FileSizes->FileSize;
+ SharedCacheMap->ValidDataLength = FileSizes->ValidDataLength;
+ KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql);
+
+ if (FileSizes->AllocationSize.QuadPart < OldSectionSize.QuadPart)
{
CcPurgeCacheSection(FileObject->SectionObjectPointer,
&FileSizes->AllocationSize,
0,
FALSE);
}
-
- KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldirql);
- SharedCacheMap->SectionSize = FileSizes->AllocationSize;
- SharedCacheMap->FileSize = FileSizes->FileSize;
- KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
+ else
+ {
+ /* Extend our section object */
+ MmExtendSection(SharedCacheMap->Section, &SharedCacheMap->SectionSize);
+ }
}
/*
FileObject, TruncateSize, UninitializeCompleteEvent);
if (TruncateSize != NULL &&
- FileObject->SectionObjectPointer != NULL &&
FileObject->SectionObjectPointer->SharedCacheMap != NULL)
{
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;