https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2a962eaf8c514a7b7a12bb...
commit 2a962eaf8c514a7b7a12bb121457c5bcbbd404fd Author: Jérôme Gardou jerome.gardou@reactos.org AuthorDate: Fri Feb 19 15:47:05 2021 +0100 Commit: Jérôme Gardou jerome.gardou@reactos.org CommitDate: Fri Feb 19 15:48:31 2021 +0100
[NTOS:CC] Keep a reference on the shared cache map of the file when we are in lazy write
This should fix "Leaking VACB" debug prints --- ntoskrnl/cc/view.c | 226 ++++++++++++++++++++++++++--------------------------- 1 file changed, 111 insertions(+), 115 deletions(-)
diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c index c9a13047447..6481c340fe0 100644 --- a/ntoskrnl/cc/view.c +++ b/ntoskrnl/cc/view.c @@ -200,6 +200,107 @@ quit: return Status; }
+static +NTSTATUS +CcRosDeleteFileCache ( + PFILE_OBJECT FileObject, + PROS_SHARED_CACHE_MAP SharedCacheMap, + PKIRQL OldIrql) +/* + * FUNCTION: Releases the shared cache map associated with a file object + */ +{ + PLIST_ENTRY current_entry; + + ASSERT(SharedCacheMap); + ASSERT(SharedCacheMap == FileObject->SectionObjectPointer->SharedCacheMap); + ASSERT(SharedCacheMap->OpenCount == 0); + + /* Remove all VACBs from the global lists */ + KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock); + current_entry = SharedCacheMap->CacheMapVacbListHead.Flink; + while (current_entry != &SharedCacheMap->CacheMapVacbListHead) + { + PROS_VACB Vacb = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry); + + RemoveEntryList(&Vacb->VacbLruListEntry); + InitializeListHead(&Vacb->VacbLruListEntry); + + if (Vacb->Dirty) + { + CcRosUnmarkDirtyVacb(Vacb, FALSE); + /* Mark it as dirty again so we know that we have to flush before freeing it */ + Vacb->Dirty = TRUE; + } + + current_entry = current_entry->Flink; + } + + /* Make sure there is no trace anymore of this map */ + FileObject->SectionObjectPointer->SharedCacheMap = NULL; + RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks); + + KeReleaseSpinLockFromDpcLevel(&SharedCacheMap->CacheMapLock); + KeReleaseQueuedSpinLock(LockQueueMasterLock, *OldIrql); + + /* Now that we're out of the locks, free everything for real */ + while (!IsListEmpty(&SharedCacheMap->CacheMapVacbListHead)) + { + PROS_VACB Vacb = CONTAINING_RECORD(RemoveHeadList(&SharedCacheMap->CacheMapVacbListHead), ROS_VACB, CacheMapVacbListEntry); + ULONG RefCount; + + InitializeListHead(&Vacb->CacheMapVacbListEntry); + + /* Flush to disk, if needed */ + if (Vacb->Dirty) + { + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + Status = MmFlushSegment(FileObject->SectionObjectPointer, &Vacb->FileOffset, VACB_MAPPING_GRANULARITY, &Iosb); + if (!NT_SUCCESS(Status)) + { + /* Complain. There's not much we can do */ + DPRINT1("Failed to flush VACB to disk while deleting the cache entry. Status: 0x%08x\n", Status); + } + Vacb->Dirty = FALSE; + } + + RefCount = CcRosVacbDecRefCount(Vacb); +#if DBG // CORE-14578 + if (RefCount != 0) + { + DPRINT1("Leaking VACB %p attached to %p (%I64d)\n", Vacb, FileObject, Vacb->FileOffset.QuadPart); + DPRINT1("There are: %d references left\n", RefCount); + DPRINT1("Map: %d\n", Vacb->MappedCount); + DPRINT1("Dirty: %d\n", Vacb->Dirty); + if (FileObject->FileName.Length != 0) + { + DPRINT1("File was: %wZ\n", &FileObject->FileName); + } + else + { + DPRINT1("No name for the file\n"); + } + } +#else + (void)RefCount; +#endif + } + + /* Release the references we own */ + if(SharedCacheMap->Section) + ObDereferenceObject(SharedCacheMap->Section); + ObDereferenceObject(SharedCacheMap->FileObject); + + ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap); + + /* Acquire the lock again for our caller */ + *OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); + + return STATUS_SUCCESS; +} + NTSTATUS CcRosFlushDirtyPages ( ULONG Target, @@ -273,6 +374,9 @@ CcRosFlushDirtyPages (
SharedCacheMap->Flags |= SHARED_CACHE_MAP_IN_LAZYWRITE;
+ /* Keep a ref on the shared cache map */ + SharedCacheMap->OpenCount++; + KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
Locked = SharedCacheMap->Callbacks->AcquireForLazyWrite(SharedCacheMap->LazyWriteContext, Wait); @@ -283,6 +387,10 @@ CcRosFlushDirtyPages ( CcRosVacbDecRefCount(current); OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE; + + if (--SharedCacheMap->OpenCount == 0) + CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql); + continue; }
@@ -300,6 +408,9 @@ CcRosFlushDirtyPages (
SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;
+ if (--SharedCacheMap->OpenCount == 0) + CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql); + if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE) && (Status != STATUS_MEDIA_WRITE_PROTECTED)) { @@ -1014,121 +1125,6 @@ quit: } }
-NTSTATUS -CcRosDeleteFileCache ( - PFILE_OBJECT FileObject, - PROS_SHARED_CACHE_MAP SharedCacheMap, - PKIRQL OldIrql) -/* - * FUNCTION: Releases the shared cache map associated with a file object - */ -{ - PLIST_ENTRY current_entry; - - ASSERT(SharedCacheMap); - ASSERT(SharedCacheMap == FileObject->SectionObjectPointer->SharedCacheMap); - ASSERT(SharedCacheMap->OpenCount == 0); - - /* Remove all VACBs from the global lists */ - KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock); - current_entry = SharedCacheMap->CacheMapVacbListHead.Flink; - while (current_entry != &SharedCacheMap->CacheMapVacbListHead) - { - PROS_VACB Vacb = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry); - - RemoveEntryList(&Vacb->VacbLruListEntry); - InitializeListHead(&Vacb->VacbLruListEntry); - - if (Vacb->Dirty) - { - CcRosUnmarkDirtyVacb(Vacb, FALSE); - /* Mark it as dirty again so we know that we have to flush before freeing it */ - Vacb->Dirty = TRUE; - } - - current_entry = current_entry->Flink; - } - - /* Make sure there is no trace anymore of this map */ - FileObject->SectionObjectPointer->SharedCacheMap = NULL; - RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks); - - KeReleaseSpinLockFromDpcLevel(&SharedCacheMap->CacheMapLock); - KeReleaseQueuedSpinLock(LockQueueMasterLock, *OldIrql); - - /* Now that we're out of the locks, free everything for real */ - while (!IsListEmpty(&SharedCacheMap->CacheMapVacbListHead)) - { - PROS_VACB Vacb = CONTAINING_RECORD(RemoveHeadList(&SharedCacheMap->CacheMapVacbListHead), ROS_VACB, CacheMapVacbListEntry); - ULONG RefCount; - - InitializeListHead(&Vacb->CacheMapVacbListEntry); - - /* Flush to disk, if needed */ - if (Vacb->Dirty) - { - IO_STATUS_BLOCK Iosb; - NTSTATUS Status; - - Status = MmFlushSegment(FileObject->SectionObjectPointer, &Vacb->FileOffset, VACB_MAPPING_GRANULARITY, &Iosb); - if (!NT_SUCCESS(Status)) - { - /* Complain. There's not much we can do */ - DPRINT1("Failed to flush VACB to disk while deleting the cache entry. Status: 0x%08x\n", Status); - } - Vacb->Dirty = FALSE; - } - - RefCount = CcRosVacbDecRefCount(Vacb); -#if DBG // CORE-14578 - if (RefCount != 0) - { - DPRINT1("Leaking VACB %p attached to %p (%I64d)\n", Vacb, FileObject, Vacb->FileOffset.QuadPart); - DPRINT1("There are: %d references left\n", RefCount); - DPRINT1("Map: %d\n", Vacb->MappedCount); - DPRINT1("Dirty: %d\n", Vacb->Dirty); - if (FileObject->FileName.Length != 0) - { - DPRINT1("File was: %wZ\n", &FileObject->FileName); - } - else - { - DPRINT1("No name for the file\n"); - } - } -#else - (void)RefCount; -#endif - } - - /* Release the references we own */ - if(SharedCacheMap->Section) - ObDereferenceObject(SharedCacheMap->Section); - ObDereferenceObject(SharedCacheMap->FileObject); - - ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap); - - /* Acquire the lock again for our caller */ - *OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); - - return STATUS_SUCCESS; -} - -VOID -CcRosReferenceCache ( - PFILE_OBJECT FileObject) -{ - PROS_SHARED_CACHE_MAP SharedCacheMap; - KIRQL OldIrql; - - OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); - SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; - ASSERT(SharedCacheMap); - ASSERT(SharedCacheMap->OpenCount != 0); - SharedCacheMap->OpenCount++; - KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); -} - NTSTATUS CcRosReleaseFileCache ( PFILE_OBJECT FileObject)