https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5c54fb91791c5b628b54c…
commit 5c54fb91791c5b628b54c539872f89c6bf2a7828
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Thu Feb 18 11:36:14 2021 +0100
Commit: Jérôme Gardou <jerome.gardou(a)reactos.org>
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);
}
}