[NTOSKRNL] Drop the VACB lock.

This has have several benefits for ReactOS Cc:
- It helps reducing potential deadlocks situations in Cc
- It speeds up ReactOS by reducing locks
- It gets us a bit closer to Windows VACB

CORE-14349
This commit is contained in:
Pierre Schweitzer 2018-04-08 19:09:36 +02:00
parent 40017a54f9
commit 953dc72dad
4 changed files with 38 additions and 64 deletions

View file

@ -251,12 +251,14 @@ CcPurgeCacheSection (
while (!IsListEmpty(&FreeList)) while (!IsListEmpty(&FreeList))
{ {
ULONG Refs;
Vacb = CONTAINING_RECORD(RemoveHeadList(&FreeList), Vacb = CONTAINING_RECORD(RemoveHeadList(&FreeList),
ROS_VACB, ROS_VACB,
CacheMapVacbListEntry); CacheMapVacbListEntry);
InitializeListHead(&Vacb->CacheMapVacbListEntry); InitializeListHead(&Vacb->CacheMapVacbListEntry);
CcRosVacbDecRefCount(Vacb); Refs = CcRosVacbDecRefCount(Vacb);
CcRosInternalFreeVacb(Vacb); ASSERT(Refs == 0);
} }
return Success; return Success;

View file

@ -215,7 +215,6 @@ CcPinRead (
iBcb->Pinned = TRUE; iBcb->Pinned = TRUE;
iBcb->Vacb->PinCount++; iBcb->Vacb->PinCount++;
CcRosReleaseVacbLock(iBcb->Vacb);
if (Flags & PIN_EXCLUSIVE) if (Flags & PIN_EXCLUSIVE)
{ {
@ -308,7 +307,6 @@ CcUnpinDataForThread (
{ {
ExReleaseResourceForThreadLite(&iBcb->Lock, ResourceThreadId); ExReleaseResourceForThreadLite(&iBcb->Lock, ResourceThreadId);
iBcb->Pinned = FALSE; iBcb->Pinned = FALSE;
CcRosAcquireVacbLock(iBcb->Vacb, NULL);
iBcb->Vacb->PinCount--; iBcb->Vacb->PinCount--;
} }
@ -360,7 +358,6 @@ CcUnpinRepinnedBcb (
IoStatus->Information = 0; IoStatus->Information = 0;
if (WriteThrough) if (WriteThrough)
{ {
CcRosAcquireVacbLock(iBcb->Vacb, NULL);
if (iBcb->Vacb->Dirty) if (iBcb->Vacb->Dirty)
{ {
IoStatus->Status = CcRosFlushVacb(iBcb->Vacb); IoStatus->Status = CcRosFlushVacb(iBcb->Vacb);
@ -369,7 +366,6 @@ CcUnpinRepinnedBcb (
{ {
IoStatus->Status = STATUS_SUCCESS; IoStatus->Status = STATUS_SUCCESS;
} }
CcRosReleaseVacbLock(iBcb->Vacb);
} }
else else
{ {
@ -380,7 +376,6 @@ CcUnpinRepinnedBcb (
{ {
ExReleaseResourceLite(&iBcb->Lock); ExReleaseResourceLite(&iBcb->Lock);
iBcb->Pinned = FALSE; iBcb->Pinned = FALSE;
CcRosAcquireVacbLock(iBcb->Vacb, NULL);
iBcb->Vacb->PinCount--; iBcb->Vacb->PinCount--;
ASSERT(iBcb->Vacb->PinCount == 0); ASSERT(iBcb->Vacb->PinCount == 0);
} }

View file

@ -90,6 +90,11 @@ ULONG CcRosVacbDecRefCount_(PROS_VACB vacb, PCSTR file, INT line)
file, line, vacb, Refs, vacb->Dirty, vacb->PageOut); file, line, vacb, Refs, vacb->Dirty, vacb->PageOut);
} }
if (Refs == 0)
{
CcRosInternalFreeVacb(vacb);
}
return Refs; return Refs;
} }
ULONG CcRosVacbGetRefCount_(PROS_VACB vacb, PCSTR file, INT line) ULONG CcRosVacbGetRefCount_(PROS_VACB vacb, PCSTR file, INT line)
@ -107,9 +112,6 @@ ULONG CcRosVacbGetRefCount_(PROS_VACB vacb, PCSTR file, INT line)
} }
#endif #endif
NTSTATUS
CcRosInternalFreeVacb(PROS_VACB Vacb);
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -187,12 +189,10 @@ CcRosFlushDirtyPages (
PROS_VACB current; PROS_VACB current;
BOOLEAN Locked; BOOLEAN Locked;
NTSTATUS Status; NTSTATUS Status;
LARGE_INTEGER ZeroTimeout;
DPRINT("CcRosFlushDirtyPages(Target %lu)\n", Target); DPRINT("CcRosFlushDirtyPages(Target %lu)\n", Target);
(*Count) = 0; (*Count) = 0;
ZeroTimeout.QuadPart = 0;
KeEnterCriticalRegion(); KeEnterCriticalRegion();
KeAcquireGuardedMutex(&ViewLock); KeAcquireGuardedMutex(&ViewLock);
@ -228,22 +228,11 @@ CcRosFlushDirtyPages (
continue; continue;
} }
Status = CcRosAcquireVacbLock(current,
Wait ? NULL : &ZeroTimeout);
if (Status != STATUS_SUCCESS)
{
current->SharedCacheMap->Callbacks->ReleaseFromLazyWrite(
current->SharedCacheMap->LazyWriteContext);
CcRosVacbDecRefCount(current);
continue;
}
ASSERT(current->Dirty); ASSERT(current->Dirty);
/* One reference is added above */ /* One reference is added above */
if (CcRosVacbGetRefCount(current) > 2) if (CcRosVacbGetRefCount(current) > 2)
{ {
CcRosReleaseVacbLock(current);
current->SharedCacheMap->Callbacks->ReleaseFromLazyWrite( current->SharedCacheMap->Callbacks->ReleaseFromLazyWrite(
current->SharedCacheMap->LazyWriteContext); current->SharedCacheMap->LazyWriteContext);
CcRosVacbDecRefCount(current); CcRosVacbDecRefCount(current);
@ -254,7 +243,6 @@ CcRosFlushDirtyPages (
Status = CcRosFlushVacb(current); Status = CcRosFlushVacb(current);
CcRosReleaseVacbLock(current);
current->SharedCacheMap->Callbacks->ReleaseFromLazyWrite( current->SharedCacheMap->Callbacks->ReleaseFromLazyWrite(
current->SharedCacheMap->LazyWriteContext); current->SharedCacheMap->LazyWriteContext);
@ -410,13 +398,15 @@ retry:
while (!IsListEmpty(&FreeList)) while (!IsListEmpty(&FreeList))
{ {
ULONG Refs;
current_entry = RemoveHeadList(&FreeList); current_entry = RemoveHeadList(&FreeList);
current = CONTAINING_RECORD(current_entry, current = CONTAINING_RECORD(current_entry,
ROS_VACB, ROS_VACB,
CacheMapVacbListEntry); CacheMapVacbListEntry);
InitializeListHead(&current->CacheMapVacbListEntry); InitializeListHead(&current->CacheMapVacbListEntry);
CcRosVacbDecRefCount(current); Refs = CcRosVacbDecRefCount(current);
CcRosInternalFreeVacb(current); ASSERT(Refs == 0);
} }
DPRINT("Evicted %lu cache pages\n", (*NrFreed)); DPRINT("Evicted %lu cache pages\n", (*NrFreed));
@ -457,8 +447,6 @@ CcRosReleaseVacb (
Refs = CcRosVacbDecRefCount(Vacb); Refs = CcRosVacbDecRefCount(Vacb);
ASSERT(Refs > 0); ASSERT(Refs > 0);
CcRosReleaseVacbLock(Vacb);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -494,7 +482,6 @@ CcRosLookupVacb (
CcRosVacbIncRefCount(current); CcRosVacbIncRefCount(current);
KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldIrql); KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldIrql);
KeReleaseGuardedMutex(&ViewLock); KeReleaseGuardedMutex(&ViewLock);
CcRosAcquireVacbLock(current, NULL);
return current; return current;
} }
if (current->FileOffset.QuadPart > FileOffset) if (current->FileOffset.QuadPart > FileOffset)
@ -718,6 +705,7 @@ CcRosCreateVacb (
PLIST_ENTRY current_entry; PLIST_ENTRY current_entry;
NTSTATUS Status; NTSTATUS Status;
KIRQL oldIrql; KIRQL oldIrql;
ULONG Refs;
ASSERT(SharedCacheMap); ASSERT(SharedCacheMap);
@ -745,7 +733,6 @@ CcRosCreateVacb (
current->MappedCount = 0; current->MappedCount = 0;
current->ReferenceCount = 0; current->ReferenceCount = 0;
current->PinCount = 0; current->PinCount = 0;
KeInitializeMutex(&current->Mutex, 0);
InitializeListHead(&current->CacheMapVacbListEntry); InitializeListHead(&current->CacheMapVacbListEntry);
InitializeListHead(&current->DirtyVacbListEntry); InitializeListHead(&current->DirtyVacbListEntry);
InitializeListHead(&current->VacbLruListEntry); InitializeListHead(&current->VacbLruListEntry);
@ -760,7 +747,6 @@ CcRosCreateVacb (
return Status; return Status;
} }
CcRosAcquireVacbLock(current, NULL);
KeAcquireGuardedMutex(&ViewLock); KeAcquireGuardedMutex(&ViewLock);
*Vacb = current; *Vacb = current;
@ -792,12 +778,12 @@ CcRosCreateVacb (
current); current);
} }
#endif #endif
CcRosVacbDecRefCount(*Vacb);
CcRosReleaseVacbLock(*Vacb);
KeReleaseGuardedMutex(&ViewLock); KeReleaseGuardedMutex(&ViewLock);
CcRosInternalFreeVacb(*Vacb);
Refs = CcRosVacbDecRefCount(*Vacb);
ASSERT(Refs == 0);
*Vacb = current; *Vacb = current;
CcRosAcquireVacbLock(current, NULL);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
if (current->FileOffset.QuadPart < FileOffset) if (current->FileOffset.QuadPart < FileOffset)
@ -1111,7 +1097,6 @@ CcRosDeleteFileCache (
KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldIrql); KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldIrql);
current = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry); current = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry);
CcRosAcquireVacbLock(current, NULL);
RemoveEntryList(&current->VacbLruListEntry); RemoveEntryList(&current->VacbLruListEntry);
InitializeListHead(&current->VacbLruListEntry); InitializeListHead(&current->VacbLruListEntry);
if (current->Dirty) if (current->Dirty)
@ -1122,7 +1107,6 @@ CcRosDeleteFileCache (
DPRINT1("Freeing dirty VACB\n"); DPRINT1("Freeing dirty VACB\n");
} }
InsertHeadList(&FreeList, &current->CacheMapVacbListEntry); InsertHeadList(&FreeList, &current->CacheMapVacbListEntry);
CcRosReleaseVacbLock(current);
KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldIrql); KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldIrql);
} }
@ -1136,11 +1120,13 @@ CcRosDeleteFileCache (
while (!IsListEmpty(&FreeList)) while (!IsListEmpty(&FreeList))
{ {
ULONG Refs;
current_entry = RemoveTailList(&FreeList); current_entry = RemoveTailList(&FreeList);
current = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry); current = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry);
InitializeListHead(&current->CacheMapVacbListEntry); InitializeListHead(&current->CacheMapVacbListEntry);
CcRosVacbDecRefCount(current); Refs = CcRosVacbDecRefCount(current);
CcRosInternalFreeVacb(current); ASSERT(Refs == 0);
} }
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);

View file

@ -217,12 +217,9 @@ typedef struct _ROS_VACB
LIST_ENTRY VacbLruListEntry; LIST_ENTRY VacbLruListEntry;
/* Offset in the file which this view maps. */ /* Offset in the file which this view maps. */
LARGE_INTEGER FileOffset; LARGE_INTEGER FileOffset;
/* Mutex */
KMUTEX Mutex;
/* Number of references. */ /* Number of references. */
volatile ULONG ReferenceCount; volatile ULONG ReferenceCount;
/* How many times was it pinned? */ /* How many times was it pinned? */
_Guarded_by_(Mutex)
LONG PinCount; LONG PinCount;
/* Pointer to the shared cache map for the file which this view maps data for. */ /* Pointer to the shared cache map for the file which this view maps data for. */
PROS_SHARED_CACHE_MAP SharedCacheMap; PROS_SHARED_CACHE_MAP SharedCacheMap;
@ -470,28 +467,9 @@ VOID
CcPerformReadAhead( CcPerformReadAhead(
IN PFILE_OBJECT FileObject); IN PFILE_OBJECT FileObject);
FORCEINLINE
NTSTATUS NTSTATUS
CcRosAcquireVacbLock( CcRosInternalFreeVacb(
_Inout_ PROS_VACB Vacb, IN PROS_VACB Vacb);
_In_ PLARGE_INTEGER Timeout)
{
NTSTATUS Status;
Status = KeWaitForSingleObject(&Vacb->Mutex,
Executive,
KernelMode,
FALSE,
Timeout);
return Status;
}
FORCEINLINE
VOID
CcRosReleaseVacbLock(
_Inout_ PROS_VACB Vacb)
{
KeReleaseMutex(&Vacb->Mutex, FALSE);
}
FORCEINLINE FORCEINLINE
BOOLEAN BOOLEAN
@ -545,6 +523,19 @@ CcRosVacbGetRefCount_(
#else #else
#define CcRosVacbIncRefCount(vacb) InterlockedIncrement((PLONG)&(vacb)->ReferenceCount) #define CcRosVacbIncRefCount(vacb) InterlockedIncrement((PLONG)&(vacb)->ReferenceCount)
#define CcRosVacbDecRefCount(vacb) InterlockedDecrement((PLONG)&(vacb)->ReferenceCount) FORCEINLINE
ULONG
CcRosVacbDecRefCount(
PROS_VACB vacb)
{
ULONG Refs;
Refs = InterlockedDecrement((PLONG)&vacb->ReferenceCount);
if (Refs == 0)
{
CcRosInternalFreeVacb(vacb);
}
return Refs;
}
#define CcRosVacbGetRefCount(vacb) InterlockedCompareExchange((PLONG)&(vacb)->ReferenceCount, 0, 0) #define CcRosVacbGetRefCount(vacb) InterlockedCompareExchange((PLONG)&(vacb)->ReferenceCount, 0, 0)
#endif #endif