Skip to content

Commit

Permalink
[NTOS:CC] Improve cache flush sync
Browse files Browse the repository at this point in the history
  • Loading branch information
TAN-Gaming committed Jan 8, 2025
1 parent 1dfba2a commit 3650091
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 10 deletions.
79 changes: 71 additions & 8 deletions ntoskrnl/cc/view.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,14 +368,16 @@ CcRosFlushDirtyPages (

ASSERT(current->Dirty);

/* Do not lazy-write the same file concurrently. Fastfat ASSERTS on that */
if (SharedCacheMap->Flags & SHARED_CACHE_MAP_IN_LAZYWRITE)
/* Don't flush the same file concurrently (CORE-19664) */
if (BooleanFlagOn(SharedCacheMap->Flags, SHARED_CACHE_MAP_IN_FLUSH))
{
CcRosVacbDecRefCount(current);
continue;
}

SharedCacheMap->Flags |= SHARED_CACHE_MAP_IN_LAZYWRITE;
/* We're going to flush now */
KeClearEvent(&SharedCacheMap->FlushDoneEvent);
SetFlag(SharedCacheMap->Flags, SHARED_CACHE_MAP_IN_FLUSH);

/* Keep a ref on the shared cache map */
SharedCacheMap->OpenCount++;
Expand All @@ -389,7 +391,9 @@ CcRosFlushDirtyPages (
ASSERT(!Wait);
CcRosVacbDecRefCount(current);
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;

ClearFlag(SharedCacheMap->Flags, SHARED_CACHE_MAP_IN_FLUSH);
KeSetEvent(&SharedCacheMap->FlushDoneEvent, IO_NO_INCREMENT, FALSE);

if (--SharedCacheMap->OpenCount == 0)
CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);
Expand All @@ -409,7 +413,8 @@ CcRosFlushDirtyPages (
CcRosVacbDecRefCount(current);
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);

SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;
ClearFlag(SharedCacheMap->Flags, SHARED_CACHE_MAP_IN_FLUSH);
KeSetEvent(&SharedCacheMap->FlushDoneEvent, IO_NO_INCREMENT, FALSE);

if (--SharedCacheMap->OpenCount == 0)
CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);
Expand Down Expand Up @@ -1093,6 +1098,63 @@ CcRosInternalFreeVacb (
return STATUS_SUCCESS;
}

static
VOID
CcRosAcquireFileCacheForFlush(
_In_ PROS_SHARED_CACHE_MAP SharedCacheMap)
{
KIRQL OldIrql;
BOOLEAN IsFlushing;

OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);

/* Keep a ref on the shared cache map */
SharedCacheMap->OpenCount++;

do
{
IsFlushing = BooleanFlagOn(SharedCacheMap->Flags, SHARED_CACHE_MAP_IN_FLUSH);
if (IsFlushing)
{
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);

/* Wait for the ongoing flush to complete */
KeWaitForSingleObject(&SharedCacheMap->FlushDoneEvent,
Executive,
KernelMode,
FALSE,
NULL);

OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
}

} while (IsFlushing);

/* We're going to flush now */
KeClearEvent(&SharedCacheMap->FlushDoneEvent);
SetFlag(SharedCacheMap->Flags, SHARED_CACHE_MAP_IN_FLUSH);

KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
}

static
VOID
CcRosReleaseFileCacheFromFlush(
_In_ PROS_SHARED_CACHE_MAP SharedCacheMap)
{
KIRQL OldIrql;

OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);

ClearFlag(SharedCacheMap->Flags, SHARED_CACHE_MAP_IN_FLUSH);
KeSetEvent(&SharedCacheMap->FlushDoneEvent, IO_NO_INCREMENT, FALSE);

if (--SharedCacheMap->OpenCount == 0)
CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);

KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
}

/*
* @implemented
*/
Expand Down Expand Up @@ -1145,7 +1207,8 @@ CcFlushCache (
IoStatus->Information = 0;
}

KeAcquireGuardedMutex(&SharedCacheMap->FlushCacheLock);
/* Don't flush the same file concurrently (CORE-19664) */
CcRosAcquireFileCacheForFlush(SharedCacheMap);

/*
* We flush the VACBs that we find here.
Expand Down Expand Up @@ -1216,7 +1279,7 @@ CcFlushCache (
FlushStart -= FlushStart % VACB_MAPPING_GRANULARITY;
}

KeReleaseGuardedMutex(&SharedCacheMap->FlushCacheLock);
CcRosReleaseFileCacheFromFlush(SharedCacheMap);

quit:
if (IoStatus)
Expand Down Expand Up @@ -1326,7 +1389,7 @@ CcRosInitializeFileCache (
KeInitializeSpinLock(&SharedCacheMap->CacheMapLock);
InitializeListHead(&SharedCacheMap->CacheMapVacbListHead);
InitializeListHead(&SharedCacheMap->BcbList);
KeInitializeGuardedMutex(&SharedCacheMap->FlushCacheLock);
KeInitializeEvent(&SharedCacheMap->FlushDoneEvent, NotificationEvent, FALSE);

SharedCacheMap->Flags = SHARED_CACHE_MAP_IN_CREATION;

Expand Down
4 changes: 2 additions & 2 deletions ntoskrnl/include/internal/cc.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ typedef struct _ROS_SHARED_CACHE_MAP
LIST_ENTRY CacheMapVacbListHead;
BOOLEAN PinAccess;
KSPIN_LOCK CacheMapLock;
KGUARDED_MUTEX FlushCacheLock;
KEVENT FlushDoneEvent;
#if DBG
BOOLEAN Trace; /* enable extra trace output for this cache map and it's VACBs */
#endif
Expand All @@ -202,7 +202,7 @@ typedef struct _ROS_SHARED_CACHE_MAP
#define READAHEAD_DISABLED 0x1
#define WRITEBEHIND_DISABLED 0x2
#define SHARED_CACHE_MAP_IN_CREATION 0x4
#define SHARED_CACHE_MAP_IN_LAZYWRITE 0x8
#define SHARED_CACHE_MAP_IN_FLUSH 0x8

typedef struct _ROS_VACB
{
Expand Down

0 comments on commit 3650091

Please sign in to comment.