[NTOSKRNL] Don't make CcScheduleReadAhead() too noisy
[reactos.git] / ntoskrnl / cc / cacheman.c
index 1718dde..9ef906e 100644 (file)
@@ -51,7 +51,9 @@ CcInitializeCacheManager(VOID)
 
     /* Initialize lazy-writer lists */
     InitializeListHead(&CcIdleWorkerThreadList);
+    InitializeListHead(&CcExpressWorkQueue);
     InitializeListHead(&CcRegularWorkQueue);
+    InitializeListHead(&CcPostTickWorkQueue);
 
     /* Define lazy writer threshold and the amount of workers,
       * depending on the system type
@@ -106,9 +108,6 @@ CcInitializeCacheManager(VOID)
     /* Lookaside list for our work items */
     ExInitializeNPagedLookasideList(&CcTwilightLookasideList, NULL, NULL, 0, sizeof(WORK_QUEUE_ENTRY), 'KWcC', 0);
 
-    /* HACK: for lazy writer watching */
-    KeInitializeEvent(&iLazyWriterNotify, NotificationEvent, FALSE);
-
     return TRUE;
 }
 
@@ -162,11 +161,104 @@ CcScheduleReadAhead (
        IN      ULONG                   Length
        )
 {
-       UNIMPLEMENTED;
+    KIRQL OldIrql;
+    LARGE_INTEGER NewOffset;
+    PROS_SHARED_CACHE_MAP SharedCacheMap;
+    PPRIVATE_CACHE_MAP PrivateCacheMap;
+    static ULONG Warn;
+
+    SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
+    PrivateCacheMap = FileObject->PrivateCacheMap;
+
+    /* If file isn't cached, or if read ahead is disabled, this is no op */
+    if (SharedCacheMap == NULL || PrivateCacheMap == NULL ||
+        BooleanFlagOn(SharedCacheMap->Flags, READAHEAD_DISABLED))
+    {
+        return;
+    }
+
+    /* Round read length with read ahead mask */
+    Length = ROUND_UP(Length, PrivateCacheMap->ReadAheadMask + 1);
+    /* Compute the offset we'll reach */
+    NewOffset.QuadPart = FileOffset->QuadPart + Length;
+
+    /* Lock read ahead spin lock */
+    KeAcquireSpinLock(&PrivateCacheMap->ReadAheadSpinLock, &OldIrql);
+    /* Easy case: the file is sequentially read */
+    if (BooleanFlagOn(FileObject->Flags, FO_SEQUENTIAL_ONLY))
+    {
+        /* If we went backward, this is no go! */
+        if (NewOffset.QuadPart < PrivateCacheMap->ReadAheadOffset[1].QuadPart)
+        {
+            KeReleaseSpinLock(&PrivateCacheMap->ReadAheadSpinLock, OldIrql);
+            return;
+        }
+
+        /* FIXME: hackish, but will do the job for now */
+        PrivateCacheMap->ReadAheadOffset[1].QuadPart = NewOffset.QuadPart;
+        PrivateCacheMap->ReadAheadLength[1] = Length;
+    }
+    /* Other cases: try to find some logic in that mess... */
+    else
+    {
+        /* Let's check if we always read the same way (like going down in the file)
+         * and pretend it's enough for now
+         */
+        if (PrivateCacheMap->FileOffset2.QuadPart >= PrivateCacheMap->FileOffset1.QuadPart &&
+            FileOffset->QuadPart >= PrivateCacheMap->FileOffset2.QuadPart)
+        {
+            /* FIXME: hackish, but will do the job for now */
+            PrivateCacheMap->ReadAheadOffset[1].QuadPart = NewOffset.QuadPart;
+            PrivateCacheMap->ReadAheadLength[1] = Length;
+        }
+        else
+        {
+            /* FIXME: handle the other cases */
+            KeReleaseSpinLock(&PrivateCacheMap->ReadAheadSpinLock, OldIrql);
+               if (!Warn++) UNIMPLEMENTED;
+            return;
+        }
+    }
+
+    /* If read ahead isn't active yet */
+    if (!PrivateCacheMap->Flags.ReadAheadActive)
+    {
+        PWORK_QUEUE_ENTRY WorkItem;
+
+        /* It's active now!
+         * Be careful with the mask, you don't want to mess with node code
+         */
+        InterlockedOr((volatile long *)&PrivateCacheMap->UlongFlags, 0x10000);
+        KeReleaseSpinLock(&PrivateCacheMap->ReadAheadSpinLock, OldIrql);
+
+        /* Get a work item */
+        WorkItem = ExAllocateFromNPagedLookasideList(&CcTwilightLookasideList);
+        if (WorkItem != NULL)
+        {
+            /* Reference our FO so that it doesn't go in between */
+            ObReferenceObject(FileObject);
+
+            /* We want to do read ahead! */
+            WorkItem->Function = ReadAhead;
+            WorkItem->Parameters.Read.FileObject = FileObject;
+
+            /* Queue in the read ahead dedicated queue */
+            CcPostWorkQueue(WorkItem, &CcExpressWorkQueue);
+
+            return;
+        }
+
+        /* Fail path: lock again, and revert read ahead active */
+        KeAcquireSpinLock(&PrivateCacheMap->ReadAheadSpinLock, &OldIrql);
+        InterlockedAnd((volatile long *)&PrivateCacheMap->UlongFlags, 0xFFFEFFFF);
+    }
+
+    /* Done (fail) */
+    KeReleaseSpinLock(&PrivateCacheMap->ReadAheadSpinLock, OldIrql);
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 VOID
 NTAPI
@@ -176,10 +268,35 @@ CcSetAdditionalCacheAttributes (
        IN      BOOLEAN         DisableWriteBehind
        )
 {
+    KIRQL OldIrql;
+    PROS_SHARED_CACHE_MAP SharedCacheMap;
+
     CCTRACE(CC_API_DEBUG, "FileObject=%p DisableReadAhead=%d DisableWriteBehind=%d\n",
         FileObject, DisableReadAhead, DisableWriteBehind);
 
-       UNIMPLEMENTED;
+    SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
+
+    OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
+
+    if (DisableReadAhead)
+    {
+        SetFlag(SharedCacheMap->Flags, READAHEAD_DISABLED);
+    }
+    else
+    {
+        ClearFlag(SharedCacheMap->Flags, READAHEAD_DISABLED);
+    }
+
+    if (DisableWriteBehind)
+    {
+        /* FIXME: also set flag 0x200 */
+        SetFlag(SharedCacheMap->Flags, WRITEBEHIND_DISABLED);
+    }
+    else
+    {
+        ClearFlag(SharedCacheMap->Flags, WRITEBEHIND_DISABLED);
+    }
+    KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
 }
 
 /*
@@ -236,7 +353,7 @@ CcSetDirtyPageThreshold (
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 VOID
 NTAPI
@@ -245,10 +362,11 @@ CcSetReadAheadGranularity (
        IN      ULONG           Granularity
        )
 {
-    static ULONG Warn;
+    PPRIVATE_CACHE_MAP PrivateMap;
 
     CCTRACE(CC_API_DEBUG, "FileObject=%p Granularity=%lu\n",
         FileObject, Granularity);
 
-    if (!Warn++) UNIMPLEMENTED;
+    PrivateMap = FileObject->PrivateCacheMap;
+    PrivateMap->ReadAheadMask = Granularity - 1;
 }