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