diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c index 774e5e9d426..0ba5d3d3706 100644 --- a/ntoskrnl/cc/view.c +++ b/ntoskrnl/cc/view.c @@ -382,11 +382,31 @@ CcRosFlushDirtyPages ( KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); + /* Make sure we don't race with CcFlushCache. + * FIXME: This is suboptimal. */ + if (!CcRosAcquireFileCacheForFlush(SharedCacheMap, Wait)) + { + ASSERT(!Wait); + + CcRosVacbDecRefCount(current); + OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); + SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE; + + /* We're flushing somewhere else, don't allow deleting here */ + ASSERT(SharedCacheMap->OpenCount > 1); + SharedCacheMap->OpenCount--; + + continue; + } + Locked = SharedCacheMap->Callbacks->AcquireForLazyWrite(SharedCacheMap->LazyWriteContext, Wait); if (!Locked) { DPRINT("Not locked!"); ASSERT(!Wait); + + CcRosReleaseFileCacheFromFlush(SharedCacheMap); + CcRosVacbDecRefCount(current); OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE; @@ -402,6 +422,8 @@ CcRosFlushDirtyPages ( SharedCacheMap->Callbacks->ReleaseFromLazyWrite(SharedCacheMap->LazyWriteContext); + CcRosReleaseFileCacheFromFlush(SharedCacheMap); + /* 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. @@ -1145,7 +1167,9 @@ CcFlushCache ( IoStatus->Information = 0; } - KeAcquireGuardedMutex(&SharedCacheMap->FlushCacheLock); + /* Don't flush the same file concurrently (CORE-19664). + * FIXME: This is suboptimal. */ + CcRosAcquireFileCacheForFlush(SharedCacheMap, TRUE); /* * We flush the VACBs that we find here. @@ -1216,7 +1240,7 @@ CcFlushCache ( FlushStart -= FlushStart % VACB_MAPPING_GRANULARITY; } - KeReleaseGuardedMutex(&SharedCacheMap->FlushCacheLock); + CcRosReleaseFileCacheFromFlush(SharedCacheMap); quit: if (IoStatus) diff --git a/ntoskrnl/include/internal/cc.h b/ntoskrnl/include/internal/cc.h index b37c5478f05..3d3c143baf1 100644 --- a/ntoskrnl/include/internal/cc.h +++ b/ntoskrnl/include/internal/cc.h @@ -364,6 +364,30 @@ CcRosUnmarkDirtyVacb( PROS_VACB Vacb, BOOLEAN LockViews); +FORCEINLINE +BOOLEAN +CcRosAcquireFileCacheForFlush( + _In_ PROS_SHARED_CACHE_MAP SharedCacheMap, + _In_ BOOLEAN Wait) +{ + if (!Wait) + { + return KeTryToAcquireGuardedMutex(&SharedCacheMap->FlushCacheLock); + } + + KeAcquireGuardedMutex(&SharedCacheMap->FlushCacheLock); + + return TRUE; +} + +FORCEINLINE +VOID +CcRosReleaseFileCacheFromFlush( + _In_ PROS_SHARED_CACHE_MAP SharedCacheMap) +{ + KeReleaseGuardedMutex(&SharedCacheMap->FlushCacheLock); +} + NTSTATUS CcRosFlushDirtyPages( ULONG Target,