[NTOSKRNL] Implement CcPostDeferredWrites() that executes deferred writes.
authorPierre Schweitzer <pierre@reactos.org>
Wed, 7 Feb 2018 19:27:55 +0000 (20:27 +0100)
committerPierre Schweitzer <pierre@reactos.org>
Wed, 7 Feb 2018 20:37:17 +0000 (21:37 +0100)
Make use of it in the lazy writer

ntoskrnl/cc/copy.c
ntoskrnl/cc/lazywrite.c
ntoskrnl/include/internal/cc.h

index ca39f7c..a150848 100644 (file)
@@ -361,6 +361,80 @@ CcCopyData (
     return TRUE;
 }
 
     return TRUE;
 }
 
+VOID
+CcPostDeferredWrites(VOID)
+{
+    ULONG WrittenBytes;
+
+    /* We'll try to write as much as we can */
+    WrittenBytes = 0;
+    while (TRUE)
+    {
+        KIRQL OldIrql;
+        PLIST_ENTRY ListEntry;
+        PDEFERRED_WRITE DeferredWrite;
+
+        DeferredWrite = NULL;
+
+        /* Lock our deferred writes list */
+        KeAcquireSpinLock(&CcDeferredWriteSpinLock, &OldIrql);
+        for (ListEntry = CcDeferredWrites.Flink;
+             ListEntry != &CcDeferredWrites;
+             ListEntry = ListEntry->Flink)
+        {
+            /* Extract an entry */
+            DeferredWrite = CONTAINING_RECORD(ListEntry, DEFERRED_WRITE, DeferredWriteLinks);
+
+            /* Compute the modified bytes, based on what we already wrote */
+            WrittenBytes += DeferredWrite->BytesToWrite;
+            /* We overflowed, give up */
+            if (WrittenBytes < DeferredWrite->BytesToWrite)
+            {
+                DeferredWrite = NULL;
+                break;
+            }
+
+            /* Check we can write */
+            if (CcCanIWrite(DeferredWrite->FileObject, WrittenBytes, FALSE, TRUE))
+            {
+                /* We can, so remove it from the list and stop looking for entry */
+                RemoveEntryList(&DeferredWrite->DeferredWriteLinks);
+                break;
+            }
+
+            /* If we don't accept modified pages, stop here */
+            if (!DeferredWrite->LimitModifiedPages)
+            {
+                DeferredWrite = NULL;
+                break;
+            }
+
+            /* Reset count as nothing was written yet */
+            WrittenBytes -= DeferredWrite->BytesToWrite;
+            DeferredWrite = NULL;
+        }
+        KeReleaseSpinLock(&CcDeferredWriteSpinLock, OldIrql);
+
+        /* Nothing to write found, give up */
+        if (DeferredWrite == NULL)
+        {
+            break;
+        }
+
+        /* If we have an event, set it and quit */
+        if (DeferredWrite->Event)
+        {
+            KeSetEvent(DeferredWrite->Event, IO_NO_INCREMENT, FALSE);
+        }
+        /* Otherwise, call the write routine and free the context */
+        else
+        {
+            DeferredWrite->PostRoutine(DeferredWrite->Context1, DeferredWrite->Context2);
+            ExFreePoolWithTag(DeferredWrite, 'CcDw');
+        }
+    }
+}
+
 /*
  * @unimplemented
  */
 /*
  * @unimplemented
  */
@@ -532,6 +606,9 @@ CcDeferWrite (
                                     &CcDeferredWriteSpinLock);
     }
 
                                     &CcDeferredWriteSpinLock);
     }
 
+    /* Try to execute the posted writes */
+    CcPostDeferredWrites();
+
     /* FIXME: lock master */
     if (!LazyWriter.ScanActive)
     {
     /* FIXME: lock master */
     if (!LazyWriter.ScanActive)
     {
index d38c693..4619aa8 100644 (file)
@@ -159,33 +159,10 @@ CcLazyWriteScan(VOID)
         DPRINT1("Lazy writer done (%d)\n", Count);
     }
 
         DPRINT1("Lazy writer done (%d)\n", Count);
     }
 
-    /* Likely not optimal, but let's handle one deferred write now! */
-    ListEntry = ExInterlockedRemoveHeadList(&CcDeferredWrites, &CcDeferredWriteSpinLock);
-    if (ListEntry != NULL)
+    /* If we have deferred writes, try them now! */
+    if (!IsListEmpty(&CcDeferredWrites))
     {
     {
-        PDEFERRED_WRITE Context;
-
-        /* Extract the context */
-        Context = CONTAINING_RECORD(ListEntry, DEFERRED_WRITE, DeferredWriteLinks);
-        ASSERT(Context->NodeTypeCode == NODE_TYPE_DEFERRED_WRITE);
-
-        /* Can we write now? */
-        if (CcCanIWrite(Context->FileObject, Context->BytesToWrite, FALSE, TRUE))
-        {
-            /* Yes! Do it, and destroy the associated context */
-            Context->PostRoutine(Context->Context1, Context->Context2);
-            ExFreePoolWithTag(Context, 'CcDw');
-        }
-        else
-        {
-            /* Otherwise, requeue it, but in tail, so that it doesn't block others
-             * This is clearly to improve, but given the poor algorithm used now
-             * It's better than nothing!
-             */
-            ExInterlockedInsertTailList(&CcDeferredWrites,
-                                        &Context->DeferredWriteLinks,
-                                        &CcDeferredWriteSpinLock);
-        }
+        CcPostDeferredWrites();
     }
 
     while (!IsListEmpty(&ToPost))
     }
 
     while (!IsListEmpty(&ToPost))
index 820cf7a..157b655 100644 (file)
@@ -428,6 +428,9 @@ CcScanDpc(
 VOID
 CcScheduleLazyWriteScan(BOOLEAN NoDelay);
 
 VOID
 CcScheduleLazyWriteScan(BOOLEAN NoDelay);
 
+VOID
+CcPostDeferredWrites(VOID);
+
 FORCEINLINE
 NTSTATUS
 CcRosAcquireVacbLock(
 FORCEINLINE
 NTSTATUS
 CcRosAcquireVacbLock(