[SHELL32] SHChangeNotify: Use tree for CDirectoryList (#6784)
[reactos.git] / ntoskrnl / cc / cacheman.c
index aacf818..238fecb 100644 (file)
@@ -22,9 +22,9 @@ static ULONG BugCheckFileId = 0x4 << 16;
 
 /* FUNCTIONS *****************************************************************/
 
+CODE_SEG("INIT")
 VOID
 NTAPI
-INIT_FUNCTION
 CcPfInitializePrefetcher(VOID)
 {
     /* Notify debugger */
@@ -40,9 +40,8 @@ CcPfInitializePrefetcher(VOID)
     /* FIXME: Setup the rest of the prefetecher */
 }
 
+CODE_SEG("INIT")
 BOOLEAN
-NTAPI
-INIT_FUNCTION
 CcInitializeCacheManager(VOID)
 {
     ULONG Thread;
@@ -51,6 +50,7 @@ CcInitializeCacheManager(VOID)
 
     /* Initialize lazy-writer lists */
     InitializeListHead(&CcIdleWorkerThreadList);
+    InitializeListHead(&CcExpressWorkQueue);
     InitializeListHead(&CcRegularWorkQueue);
     InitializeListHead(&CcPostTickWorkQueue);
 
@@ -160,11 +160,103 @@ CcScheduleReadAhead (
        IN      ULONG                   Length
        )
 {
-       UNIMPLEMENTED;
+    KIRQL OldIrql;
+    LARGE_INTEGER NewOffset;
+    PROS_SHARED_CACHE_MAP SharedCacheMap;
+    PPRIVATE_CACHE_MAP PrivateCacheMap;
+
+    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);
+            UNIMPLEMENTED_ONCE;
+            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, PRIVATE_CACHE_MAP_READ_AHEAD_ACTIVE);
+        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, ~PRIVATE_CACHE_MAP_READ_AHEAD_ACTIVE);
+    }
+
+    /* Done (fail) */
+    KeReleaseSpinLock(&PrivateCacheMap->ReadAheadSpinLock, OldIrql);
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 VOID
 NTAPI
@@ -174,10 +266,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);
 }
 
 /*
@@ -190,7 +307,7 @@ CcSetBcbOwnerPointer (
        IN      PVOID   Owner
        )
 {
-    PINTERNAL_BCB iBcb = Bcb;
+    PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB);
 
     CCTRACE(CC_API_DEBUG, "Bcb=%p Owner=%p\n",
         Bcb, Owner);
@@ -234,7 +351,7 @@ CcSetDirtyPageThreshold (
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 VOID
 NTAPI
@@ -243,10 +360,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;
 }