ULONG CcFastReadNoWait;
ULONG CcFastReadResourceMiss;
+/* Counters:
+ * - Amount of pages flushed to the disk
+ * - Number of flush operations
+ */
+ULONG CcDataPages = 0;
+ULONG CcDataFlushes = 0;
+
/* FUNCTIONS *****************************************************************/
VOID
/* Remember it's locked */
Locked = TRUE;
+ /* Don't read past the end of the file */
+ if (CurrentOffset >= SharedCacheMap->FileSize.QuadPart)
+ {
+ goto Clear;
+ }
+ if (CurrentOffset + Length > SharedCacheMap->FileSize.QuadPart)
+ {
+ Length = SharedCacheMap->FileSize.QuadPart - CurrentOffset;
+ }
+
/* Next of the algorithm will lock like CcCopyData with the slight
* difference that we don't copy data back to an user-backed buffer
* We just bring data into Cc
{
/* Mark read ahead as unactive */
KeAcquireSpinLockAtDpcLevel(&PrivateCacheMap->ReadAheadSpinLock);
- InterlockedAnd((volatile long *)&PrivateCacheMap->UlongFlags, 0xFFFEFFFF);
+ InterlockedAnd((volatile long *)&PrivateCacheMap->UlongFlags, ~PRIVATE_CACHE_MAP_READ_AHEAD_ACTIVE);
KeReleaseSpinLockFromDpcLevel(&PrivateCacheMap->ReadAheadSpinLock);
}
- KeReleaseSpinLock(&PrivateCacheMap->ReadAheadSpinLock, OldIrql);
+ KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
/* If file was locked, release it */
if (Locked)
/* So, now allow write if:
* - Not the first try or we have no throttling yet
* AND:
- * - We don't execeed threshold!
+ * - We don't exceed threshold!
+ * - We don't exceed what Mm can allow us to use
+ * + If we're above top, that's fine
+ * + If we're above bottom with limited modified pages, that's fine
+ * + Otherwise, throttle!
*/
if ((TryContext != FirstTry || IsListEmpty(&CcDeferredWrites)) &&
CcTotalDirtyPages + Pages < CcDirtyPageThreshold &&
+ (MmAvailablePages > MmThrottleTop ||
+ (MmModifiedPageListHead.Total < 1000 && MmAvailablePages > MmThrottleBottom)) &&
!PerFileDefer)
{
return TRUE;