Skip to content

Commit

Permalink
[NTOS:CC] Fix race condition between CcFlushCache and CcRosFlushDirty…
Browse files Browse the repository at this point in the history
…Pages

Also replace SHARED_CACHE_MAP_IN_LAZYWRITE flag with the flush cache lock.
CORE-19664
  • Loading branch information
TAN-Gaming committed Nov 16, 2024
1 parent 6aa11ac commit 79d9e8a
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 13 deletions.
38 changes: 26 additions & 12 deletions ntoskrnl/cc/view.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,28 +368,41 @@ CcRosFlushDirtyPages (

ASSERT(current->Dirty);

/* Do not lazy-write the same file concurrently. Fastfat ASSERTS on that */
if (SharedCacheMap->Flags & SHARED_CACHE_MAP_IN_LAZYWRITE)
{
CcRosVacbDecRefCount(current);
continue;
}

SharedCacheMap->Flags |= SHARED_CACHE_MAP_IN_LAZYWRITE;

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

KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);

/* Don't flush the same file cache concurrently (CORE-19664) */
if (!Wait)
{
Locked = KeTryToAcquireGuardedMutex(&SharedCacheMap->FlushCacheLock);
if (!Locked)
{
CcRosVacbDecRefCount(current);
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);

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

continue;
}
}
else
{
KeAcquireGuardedMutex(&SharedCacheMap->FlushCacheLock);
}

Locked = SharedCacheMap->Callbacks->AcquireForLazyWrite(SharedCacheMap->LazyWriteContext, Wait);
if (!Locked)
{
DPRINT("Not locked!");
ASSERT(!Wait);

KeReleaseGuardedMutex(&SharedCacheMap->FlushCacheLock);

CcRosVacbDecRefCount(current);
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;

if (--SharedCacheMap->OpenCount == 0)
CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);
Expand All @@ -402,15 +415,15 @@ CcRosFlushDirtyPages (

SharedCacheMap->Callbacks->ReleaseFromLazyWrite(SharedCacheMap->LazyWriteContext);

KeReleaseGuardedMutex(&SharedCacheMap->FlushCacheLock);

/* We release the VACB before acquiring the lock again, because
* CcRosVacbDecRefCount might free the VACB, as CcRosFlushVacb dropped a
* Refcount. Freeing must be done outside of the lock.
* The refcount is decremented atomically. So this is OK. */
CcRosVacbDecRefCount(current);
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);

SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;

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

Expand Down Expand Up @@ -1146,6 +1159,7 @@ CcFlushCache (
IoStatus->Information = 0;
}

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

/*
Expand Down
1 change: 0 additions & 1 deletion ntoskrnl/include/internal/cc.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,6 @@ 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

typedef struct _ROS_VACB
{
Expand Down

0 comments on commit 79d9e8a

Please sign in to comment.