https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5c54fb91791c5b628b54c539872f89c6bf2a7828

commit 5c54fb91791c5b628b54c539872f89c6bf2a7828
Author:     Jérôme Gardou <[email protected]>
AuthorDate: Thu Feb 18 11:36:14 2021 +0100
Commit:     Jérôme Gardou <[email protected]>
CommitDate: Wed Mar 24 11:22:28 2021 +0100

    [NTOS:CC] Rewrite CcPostDeferredWrites
    
    This allows to post small writes if there are any, and avoid holding the 
list lock for a long time.
---
 ntoskrnl/cc/copy.c | 79 +++++++++++++++++++++---------------------------------
 1 file changed, 31 insertions(+), 48 deletions(-)

diff --git a/ntoskrnl/cc/copy.c b/ntoskrnl/cc/copy.c
index cdab94c8313..3ab5b7852f3 100644
--- a/ntoskrnl/cc/copy.c
+++ b/ntoskrnl/cc/copy.c
@@ -72,74 +72,57 @@ CcInitCacheZeroPage (
 VOID
 CcPostDeferredWrites(VOID)
 {
-    ULONG WrittenBytes;
+    LIST_ENTRY ToInsertBack;
+
+    InitializeListHead(&ToInsertBack);
 
     /* We'll try to write as much as we can */
-    WrittenBytes = 0;
     while (TRUE)
     {
-        KIRQL OldIrql;
-        PLIST_ENTRY ListEntry;
         PDEFERRED_WRITE DeferredWrite;
+        PLIST_ENTRY ListEntry;
 
         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);
+        ListEntry = ExInterlockedRemoveHeadList(&CcDeferredWrites, 
&CcDeferredWriteSpinLock);
 
-            /* Compute the modified bytes, based on what we already wrote */
-            WrittenBytes += DeferredWrite->BytesToWrite;
-            /* We overflowed, give up */
-            if (WrittenBytes < DeferredWrite->BytesToWrite)
-            {
-                DeferredWrite = NULL;
-                break;
-            }
+        if (!ListEntry)
+            break;
 
-            /* Check we can write */
-            if (CcCanIWrite(DeferredWrite->FileObject, WrittenBytes, FALSE, 
RetryForceCheckPerFile))
+        DeferredWrite = CONTAINING_RECORD(ListEntry, DEFERRED_WRITE, 
DeferredWriteLinks);
+
+        /* Check if we can write */
+        if (CcCanIWrite(DeferredWrite->FileObject, 
DeferredWrite->BytesToWrite, FALSE, RetryForceCheckPerFile))
+        {
+            /* If we have an event, set it and go along */
+            if (DeferredWrite->Event)
             {
-                /* We can, so remove it from the list and stop looking for 
entry */
-                RemoveEntryList(&DeferredWrite->DeferredWriteLinks);
-                break;
+                KeSetEvent(DeferredWrite->Event, IO_NO_INCREMENT, FALSE);
             }
-
-            /* If we don't accept modified pages, stop here */
-            if (!DeferredWrite->LimitModifiedPages)
+            /* Otherwise, call the write routine and free the context */
+            else
             {
-                DeferredWrite = NULL;
-                break;
+                DeferredWrite->PostRoutine(DeferredWrite->Context1, 
DeferredWrite->Context2);
+                ExFreePoolWithTag(DeferredWrite, 'CcDw');
             }
-
-            /* Reset count as nothing was written yet */
-            WrittenBytes -= DeferredWrite->BytesToWrite;
-            DeferredWrite = NULL;
+            continue;
         }
-        KeReleaseSpinLock(&CcDeferredWriteSpinLock, OldIrql);
 
-        /* Nothing to write found, give up */
-        if (DeferredWrite == NULL)
+        /* Keep it for later */
+        InsertHeadList(&ToInsertBack, &DeferredWrite->DeferredWriteLinks);
+
+        /* If we don't accept modified pages, stop here */
+        if (!DeferredWrite->LimitModifiedPages)
         {
             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');
-        }
+    /* Insert what we couldn't write back in the list */
+    while (!IsListEmpty(&ToInsertBack))
+    {
+        PLIST_ENTRY ListEntry = RemoveTailList(&ToInsertBack);
+        ExInterlockedInsertHeadList(&CcDeferredWrites, ListEntry, 
&CcDeferredWriteSpinLock);
     }
 }
 

Reply via email to