[NTOS:CC] Simplify CcRosDeleteFileCache

This commit is contained in:
Jérôme Gardou 2020-12-30 10:53:31 +01:00
parent a9193b5cc2
commit 33cde28312

View file

@ -974,105 +974,94 @@ CcRosDeleteFileCache (
*/ */
{ {
PLIST_ENTRY current_entry; PLIST_ENTRY current_entry;
PROS_VACB current;
LIST_ENTRY FreeList;
ASSERT(SharedCacheMap); ASSERT(SharedCacheMap);
ASSERT(SharedCacheMap == FileObject->SectionObjectPointer->SharedCacheMap);
ASSERT(SharedCacheMap->OpenCount == 0);
SharedCacheMap->OpenCount++; /* 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); KeReleaseQueuedSpinLock(LockQueueMasterLock, *OldIrql);
CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, NULL); /* Now that we're out of the locks, free everything for real */
*OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
SharedCacheMap->OpenCount--;
if (SharedCacheMap->OpenCount == 0)
{
FileObject->SectionObjectPointer->SharedCacheMap = NULL;
/*
* Release all VACBs
*/
InitializeListHead(&FreeList);
KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock);
while (!IsListEmpty(&SharedCacheMap->CacheMapVacbListHead)) while (!IsListEmpty(&SharedCacheMap->CacheMapVacbListHead))
{ {
current_entry = RemoveTailList(&SharedCacheMap->CacheMapVacbListHead); PROS_VACB Vacb = CONTAINING_RECORD(RemoveHeadList(&SharedCacheMap->CacheMapVacbListHead), ROS_VACB, CacheMapVacbListEntry);
KeReleaseSpinLockFromDpcLevel(&SharedCacheMap->CacheMapLock); ULONG RefCount;
current = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry); InitializeListHead(&Vacb->CacheMapVacbListEntry);
RemoveEntryList(&current->VacbLruListEntry);
InitializeListHead(&current->VacbLruListEntry); /* Flush to disk, if needed */
if (current->Dirty) if (Vacb->Dirty)
{ {
KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock); SIZE_T FlushSize = min(VACB_MAPPING_GRANULARITY, Vacb->SharedCacheMap->SectionSize.QuadPart - Vacb->FileOffset.QuadPart);
CcRosUnmarkDirtyVacb(current, FALSE); IO_STATUS_BLOCK Iosb;
KeReleaseSpinLockFromDpcLevel(&SharedCacheMap->CacheMapLock); NTSTATUS Status;
DPRINT1("Freeing dirty VACB\n");
} Status = MmFlushVirtualMemory(NULL, &Vacb->BaseAddress, &FlushSize, &Iosb);
if (current->MappedCount != 0) if (!NT_SUCCESS(Status))
{ {
current->MappedCount = 0; /* Complain. There's not much we can do */
NT_VERIFY(CcRosVacbDecRefCount(current) > 0); DPRINT1("Failed to flush VACB to disk while deleting the cache entry. Status: 0x%08x\n", Status);
DPRINT1("Freeing mapped VACB\n");
} }
InsertHeadList(&FreeList, &current->CacheMapVacbListEntry); Vacb->Dirty = FALSE;
KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock);
} }
#if DBG
SharedCacheMap->Trace = FALSE;
#endif
KeReleaseSpinLockFromDpcLevel(&SharedCacheMap->CacheMapLock);
KeReleaseQueuedSpinLock(LockQueueMasterLock, *OldIrql); RefCount = CcRosVacbDecRefCount(Vacb);
if(SharedCacheMap->Section)
ObDereferenceObject(SharedCacheMap->Section);
ObDereferenceObject(SharedCacheMap->FileObject);
while (!IsListEmpty(&FreeList))
{
ULONG Refs;
current_entry = RemoveTailList(&FreeList);
current = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry);
InitializeListHead(&current->CacheMapVacbListEntry);
Refs = CcRosVacbDecRefCount(current);
#if DBG // CORE-14578 #if DBG // CORE-14578
if (Refs != 0) if (RefCount != 0)
{ {
DPRINT1("Leaking VACB %p attached to %p (%I64d)\n", current, FileObject, current->FileOffset.QuadPart); DPRINT1("Leaking VACB %p attached to %p (%I64d)\n", Vacb, FileObject, Vacb->FileOffset.QuadPart);
DPRINT1("There are: %d references left\n", Refs); DPRINT1("There are: %d references left\n", RefCount);
DPRINT1("Map: %d\n", current->MappedCount); DPRINT1("Map: %d\n", Vacb->MappedCount);
DPRINT1("Dirty: %d\n", current->Dirty); DPRINT1("Dirty: %d\n", Vacb->Dirty);
if (FileObject->FileName.Length != 0) if (FileObject->FileName.Length != 0)
{ {
DPRINT1("File was: %wZ\n", &FileObject->FileName); DPRINT1("File was: %wZ\n", &FileObject->FileName);
} }
else if (FileObject->FsContext != NULL &&
((PFSRTL_COMMON_FCB_HEADER)(FileObject->FsContext))->NodeTypeCode == 0x0502 &&
((PFSRTL_COMMON_FCB_HEADER)(FileObject->FsContext))->NodeByteSize == 0x1F8 &&
((PUNICODE_STRING)(((PUCHAR)FileObject->FsContext) + 0x100))->Length != 0)
{
DPRINT1("File was: %wZ (FastFAT)\n", (PUNICODE_STRING)(((PUCHAR)FileObject->FsContext) + 0x100));
}
else else
{ {
DPRINT1("No name for the file\n"); DPRINT1("No name for the file\n");
} }
} }
#else #else
ASSERT(Refs == 0); (void)RefCount;
#endif #endif
} }
*OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); /* Release the references we own */
RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks); if(SharedCacheMap->Section)
KeReleaseQueuedSpinLock(LockQueueMasterLock, *OldIrql); ObDereferenceObject(SharedCacheMap->Section);
ObDereferenceObject(SharedCacheMap->FileObject);
ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap); ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap);
/* Acquire the lock again for our caller */
*OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); *OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
}
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }