[NTOS:CC] Be sure to flush the whole file in CcFlushCache
[reactos.git] / ntoskrnl / cc / view.c
index 06ec867..591168e 100644 (file)
@@ -906,12 +906,19 @@ CcFlushCache (
     CCTRACE(CC_API_DEBUG, "SectionObjectPointers=%p FileOffset=0x%I64X Length=%lu\n",
         SectionObjectPointers, FileOffset ? FileOffset->QuadPart : 0LL, Length);
 
-    if (!SectionObjectPointers || !SectionObjectPointers->SharedCacheMap)
+    if (!SectionObjectPointers)
     {
         Status = STATUS_INVALID_PARAMETER;
         goto quit;
     }
 
+    if (!SectionObjectPointers->SharedCacheMap)
+    {
+        /* Forward this to Mm */
+        MmFlushSegment(SectionObjectPointers, FileOffset, Length, IoStatus);
+        return;
+    }
+
     SharedCacheMap = SectionObjectPointers->SharedCacheMap;
     ASSERT(SharedCacheMap);
     if (FileOffset)
@@ -934,8 +941,14 @@ CcFlushCache (
         IoStatus->Information = 0;
     }
 
+    /*
+     * We flush the VACBs that we find here.
+     * If there is no (dirty) VACB, it doesn't mean that there is no data to flush, so we call Mm to be sure.
+     * This is suboptimal, but this is due to the lack of granularity of how we track dirty cache data
+     */
     while (FlushStart < FlushEnd)
     {
+        BOOLEAN DirtyVacb = FALSE;
         PROS_VACB vacb = CcRosLookupVacb(SharedCacheMap, FlushStart);
 
         if (vacb != NULL)
@@ -947,6 +960,7 @@ CcFlushCache (
                 {
                     goto quit;
                 }
+                DirtyVacb = TRUE;
             }
 
             CcRosReleaseVacb(SharedCacheMap, vacb, FALSE, FALSE);
@@ -955,11 +969,39 @@ CcFlushCache (
                 IoStatus->Information += VACB_MAPPING_GRANULARITY;
         }
 
+        if (!DirtyVacb)
+        {
+            IO_STATUS_BLOCK MmIosb;
+            LARGE_INTEGER MmOffset;
+
+            MmOffset.QuadPart = FlushStart;
+
+            if (FlushEnd - (FlushEnd % VACB_MAPPING_GRANULARITY) <= FlushStart)
+            {
+                /* The whole range fits within a VACB chunk. */
+                Status = MmFlushSegment(SectionObjectPointers, &MmOffset, FlushEnd - FlushStart, &MmIosb);
+            }
+            else
+            {
+                ULONG MmLength = VACB_MAPPING_GRANULARITY - (FlushStart % VACB_MAPPING_GRANULARITY);
+                Status = MmFlushSegment(SectionObjectPointers, &MmOffset, MmLength, &MmIosb);
+            }
+
+            if (!NT_SUCCESS(Status))
+                goto quit;
+
+            if (IoStatus)
+                IoStatus->Information += MmIosb.Information;
+        }
+
         if (!NT_SUCCESS(RtlLongLongAdd(FlushStart, VACB_MAPPING_GRANULARITY, &FlushStart)))
         {
             /* We're at the end of file ! */
             break;
         }
+
+        /* Round down to next VACB start now */
+        FlushStart -= FlushStart % VACB_MAPPING_GRANULARITY;
     }
 
 quit: