X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=ntoskrnl%2Fcc%2Fview.c;h=e896c570932987c011b8de5b1cb03bcf17df3b8f;hp=4823d042681eb114866cfe8db663a43df1089785;hb=1e579843bcf2f54da8e717ec9713b86e9ad1c02c;hpb=f0c7f862d4da673ea3e4120918924af7a03ed0df diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c index 4823d042681..e896c570932 100644 --- a/ntoskrnl/cc/view.c +++ b/ntoskrnl/cc/view.c @@ -64,13 +64,8 @@ LIST_ENTRY CcDeferredWrites; KSPIN_LOCK CcDeferredWriteSpinLock; LIST_ENTRY CcCleanSharedCacheMapList; -/* Internal vars (ROS): - * - Lock for the CcCleanSharedCacheMapList list - */ -KSPIN_LOCK iSharedCacheMapLock; - #if DBG -static void CcRosVacbIncRefCount_(PROS_VACB vacb, const char* file, int line) +VOID CcRosVacbIncRefCount_(PROS_VACB vacb, PCSTR file, INT line) { ++vacb->ReferenceCount; if (vacb->SharedCacheMap->Trace) @@ -79,7 +74,7 @@ static void CcRosVacbIncRefCount_(PROS_VACB vacb, const char* file, int line) file, line, vacb, vacb->ReferenceCount, vacb->Dirty, vacb->PageOut); } } -static void CcRosVacbDecRefCount_(PROS_VACB vacb, const char* file, int line) +VOID CcRosVacbDecRefCount_(PROS_VACB vacb, PCSTR file, INT line) { ASSERT(vacb->ReferenceCount != 0); --vacb->ReferenceCount; @@ -90,11 +85,6 @@ static void CcRosVacbDecRefCount_(PROS_VACB vacb, const char* file, int line) file, line, vacb, vacb->ReferenceCount, vacb->Dirty, vacb->PageOut); } } -#define CcRosVacbIncRefCount(vacb) CcRosVacbIncRefCount_(vacb,__FILE__,__LINE__) -#define CcRosVacbDecRefCount(vacb) CcRosVacbDecRefCount_(vacb,__FILE__,__LINE__) -#else -#define CcRosVacbIncRefCount(vacb) (++((vacb)->ReferenceCount)) -#define CcRosVacbDecRefCount(vacb) (--((vacb)->ReferenceCount)) #endif NTSTATUS @@ -355,10 +345,11 @@ retry: CcRosVacbDecRefCount(current); /* Check if we can free this entry now */ - if (current->ReferenceCount == 0) + if (current->ReferenceCount < 2) { ASSERT(!current->Dirty); ASSERT(!current->MappedCount); + ASSERT(current->ReferenceCount == 1); RemoveEntryList(¤t->CacheMapVacbListEntry); RemoveEntryList(¤t->VacbLruListEntry); @@ -400,6 +391,7 @@ retry: current = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry); + CcRosVacbDecRefCount(current); CcRosInternalFreeVacb(current); } @@ -439,6 +431,8 @@ CcRosReleaseVacb ( CcRosVacbIncRefCount(Vacb); } + ASSERT(Vacb->ReferenceCount != 0); + CcRosReleaseVacbLock(Vacb); return STATUS_SUCCESS; @@ -580,16 +574,15 @@ CcRosMarkDirtyFile ( KeBugCheck(CACHE_MANAGER); } - if (!Vacb->Dirty) - { - CcRosMarkDirtyVacb(Vacb); - } - - CcRosReleaseVacbLock(Vacb); + CcRosReleaseVacb(SharedCacheMap, Vacb, Vacb->Valid, TRUE, FALSE); return STATUS_SUCCESS; } +/* + * Note: this is not the contrary function of + * CcRosMapVacbInKernelSpace() + */ NTSTATUS NTAPI CcRosUnmapVacb ( @@ -610,28 +603,22 @@ CcRosUnmapVacb ( return STATUS_UNSUCCESSFUL; } - if (NowDirty && !Vacb->Dirty) - { - CcRosMarkDirtyVacb(Vacb); - } - ASSERT(Vacb->MappedCount != 0); Vacb->MappedCount--; - CcRosVacbDecRefCount(Vacb); if (Vacb->MappedCount == 0) { CcRosVacbDecRefCount(Vacb); } - CcRosReleaseVacbLock(Vacb); + CcRosReleaseVacb(SharedCacheMap, Vacb, Vacb->Valid, NowDirty, FALSE); return STATUS_SUCCESS; } static NTSTATUS -CcRosMapVacb( +CcRosMapVacbInKernelSpace( PROS_VACB Vacb) { ULONG i; @@ -726,7 +713,7 @@ CcRosCreateVacb ( current->MappedCount = 0; current->DirtyVacbListEntry.Flink = NULL; current->DirtyVacbListEntry.Blink = NULL; - current->ReferenceCount = 1; + current->ReferenceCount = 0; current->PinCount = 0; KeInitializeMutex(¤t->Mutex, 0); CcRosAcquireVacbLock(current, NULL); @@ -790,6 +777,7 @@ CcRosCreateVacb ( } KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldIrql); InsertTailList(&VacbLruListHead, ¤t->VacbLruListEntry); + CcRosVacbIncRefCount(current); KeReleaseGuardedMutex(&ViewLock); MI_SET_USAGE(MI_USAGE_CACHE); @@ -811,7 +799,7 @@ CcRosCreateVacb ( } #endif - Status = CcRosMapVacb(current); + Status = CcRosMapVacbInKernelSpace(current); if (!NT_SUCCESS(Status)) { RemoveEntryList(¤t->CacheMapVacbListEntry); @@ -820,6 +808,9 @@ CcRosCreateVacb ( ExFreeToNPagedLookasideList(&VacbLookasideList, current); } + /* Reference it to allow release */ + CcRosVacbIncRefCount(current); + return Status; } @@ -946,6 +937,17 @@ CcRosInternalFreeVacb ( NULL); MmUnlockAddressSpace(MmGetKernelAddressSpace()); + if (Vacb->PinCount != 0 || Vacb->ReferenceCount != 0) + { + DPRINT1("Invalid free: %ld, %ld\n", Vacb->ReferenceCount, Vacb->PinCount); + if (Vacb->SharedCacheMap->FileObject && Vacb->SharedCacheMap->FileObject->FileName.Length) + { + DPRINT1("For file: %wZ\n", &Vacb->SharedCacheMap->FileObject->FileName); + } + } + + ASSERT(Vacb->PinCount == 0); + ASSERT(Vacb->ReferenceCount == 0); ExFreeToNPagedLookasideList(&VacbLookasideList, Vacb); return STATUS_SUCCESS; } @@ -966,7 +968,6 @@ CcFlushCache ( LONGLONG RemainingLength; PROS_VACB current; NTSTATUS Status; - KIRQL oldIrql; CCTRACE(CC_API_DEBUG, "SectionObjectPointers=%p FileOffset=%p Length=%lu\n", SectionObjectPointers, FileOffset, Length); @@ -1009,13 +1010,7 @@ CcFlushCache ( } } - CcRosReleaseVacbLock(current); - - KeAcquireGuardedMutex(&ViewLock); - KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldIrql); - CcRosVacbDecRefCount(current); - KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldIrql); - KeReleaseGuardedMutex(&ViewLock); + CcRosReleaseVacb(SharedCacheMap, current, current->Valid, current->Dirty, FALSE); } Offset.QuadPart += VACB_MAPPING_GRANULARITY; @@ -1097,12 +1092,13 @@ CcRosDeleteFileCache ( { current_entry = RemoveTailList(&FreeList); current = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry); + CcRosVacbDecRefCount(current); CcRosInternalFreeVacb(current); } - KeAcquireSpinLock(&iSharedCacheMapLock, &OldIrql); + OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks); - KeReleaseSpinLock(&iSharedCacheMapLock, OldIrql); + KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap); KeAcquireGuardedMutex(&ViewLock); @@ -1171,6 +1167,8 @@ CcRosReleaseFileCache ( * has been closed. */ { + KIRQL OldIrql; + PPRIVATE_CACHE_MAP PrivateMap; PROS_SHARED_CACHE_MAP SharedCacheMap; KeAcquireGuardedMutex(&ViewLock); @@ -1178,22 +1176,33 @@ CcRosReleaseFileCache ( if (FileObject->SectionObjectPointer->SharedCacheMap != NULL) { SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; - if (FileObject->PrivateCacheMap != NULL) - { - KIRQL OldIrql; - PPRIVATE_CACHE_MAP PrivateMap; - /* Closing the handle, so kill the private cache map */ - PrivateMap = FileObject->PrivateCacheMap; + /* Closing the handle, so kill the private cache map + * Before you event try to remove it from FO, always + * lock the master lock, to be sure not to race + * with a potential read ahead ongoing! + */ + OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); + PrivateMap = FileObject->PrivateCacheMap; + FileObject->PrivateCacheMap = NULL; + KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); + if (PrivateMap != NULL) + { /* Remove it from the file */ KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &OldIrql); RemoveEntryList(&PrivateMap->PrivateLinks); KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql); - /* And free it */ - FileObject->PrivateCacheMap = NULL; - ExFreePoolWithTag(PrivateMap, TAG_PRIVATE_CACHE_MAP); + /* And free it. */ + if (PrivateMap != &SharedCacheMap->PrivateCacheMap) + { + ExFreePoolWithTag(PrivateMap, TAG_PRIVATE_CACHE_MAP); + } + else + { + PrivateMap->NodeTypeCode = 0; + } if (SharedCacheMap->OpenCount > 0) { @@ -1261,24 +1270,32 @@ CcRosInitializeFileCache ( InitializeListHead(&SharedCacheMap->CacheMapVacbListHead); FileObject->SectionObjectPointer->SharedCacheMap = SharedCacheMap; - KeAcquireSpinLock(&iSharedCacheMapLock, &OldIrql); + OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); InsertTailList(&CcCleanSharedCacheMapList, &SharedCacheMap->SharedCacheMapLinks); - KeReleaseSpinLock(&iSharedCacheMapLock, OldIrql); + KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); } if (FileObject->PrivateCacheMap == NULL) { PPRIVATE_CACHE_MAP PrivateMap; /* Allocate the private cache map for this handle */ - PrivateMap = ExAllocatePoolWithTag(NonPagedPool, sizeof(PRIVATE_CACHE_MAP), TAG_PRIVATE_CACHE_MAP); + if (SharedCacheMap->PrivateCacheMap.NodeTypeCode != 0) + { + PrivateMap = ExAllocatePoolWithTag(NonPagedPool, sizeof(PRIVATE_CACHE_MAP), TAG_PRIVATE_CACHE_MAP); + } + else + { + PrivateMap = &SharedCacheMap->PrivateCacheMap; + } + if (PrivateMap == NULL) { /* If we also allocated the shared cache map for this file, kill it */ if (Allocated) { - KeAcquireSpinLock(&iSharedCacheMapLock, &OldIrql); + OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks); - KeReleaseSpinLock(&iSharedCacheMapLock, OldIrql); + KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); FileObject->SectionObjectPointer->SharedCacheMap = NULL; ObDereferenceObject(FileObject); @@ -1343,7 +1360,6 @@ CcInitView ( InitializeListHead(&CcDeferredWrites); InitializeListHead(&CcCleanSharedCacheMapList); KeInitializeSpinLock(&CcDeferredWriteSpinLock); - KeInitializeSpinLock(&iSharedCacheMapLock); KeInitializeGuardedMutex(&ViewLock); ExInitializeNPagedLookasideList(&iBcbLookasideList, NULL, @@ -1427,6 +1443,38 @@ ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[]) return TRUE; } + +BOOLEAN +ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[]) +{ + KdbpPrint("CcTotalDirtyPages:\t%lu (%lu Kb)\n", CcTotalDirtyPages, + (CcTotalDirtyPages * PAGE_SIZE) / 1024); + KdbpPrint("CcDirtyPageThreshold:\t%lu (%lu Kb)\n", CcDirtyPageThreshold, + (CcDirtyPageThreshold * PAGE_SIZE) / 1024); + KdbpPrint("MmAvailablePages:\t%lu (%lu Kb)\n", MmAvailablePages, + (MmAvailablePages * PAGE_SIZE) / 1024); + KdbpPrint("MmThrottleTop:\t\t%lu (%lu Kb)\n", MmThrottleTop, + (MmThrottleTop * PAGE_SIZE) / 1024); + KdbpPrint("MmThrottleBottom:\t%lu (%lu Kb)\n", MmThrottleBottom, + (MmThrottleBottom * PAGE_SIZE) / 1024); + KdbpPrint("MmModifiedPageListHead.Total:\t%lu (%lu Kb)\n", MmModifiedPageListHead.Total, + (MmModifiedPageListHead.Total * PAGE_SIZE) / 1024); + + if (CcTotalDirtyPages >= CcDirtyPageThreshold) + { + KdbpPrint("CcTotalDirtyPages above the threshold, writes should be throttled\n"); + } + else if (CcTotalDirtyPages + 64 >= CcDirtyPageThreshold) + { + KdbpPrint("CcTotalDirtyPages within 64 (max charge) pages of the threshold, writes may be throttled\n"); + } + else + { + KdbpPrint("CcTotalDirtyPages below the threshold, writes should not be throttled\n"); + } + + return TRUE; +} #endif /* EOF */