https://git.reactos.org/?p=reactos.git;a=commitdiff;h=92e64a6c9bbd68c81914c…
commit 92e64a6c9bbd68c81914c7ce63c4888b9ca4d54b
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Wed Feb 7 20:27:55 2018 +0100
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Wed Feb 7 21:37:17 2018 +0100
[NTOSKRNL] Implement CcPostDeferredWrites() that executes deferred writes.
Make use of it in the lazy writer
---
ntoskrnl/cc/copy.c | 77 ++++++++++++++++++++++++++++++++++++++++++
ntoskrnl/cc/lazywrite.c | 29 ++--------------
ntoskrnl/include/internal/cc.h | 3 ++
3 files changed, 83 insertions(+), 26 deletions(-)
diff --git a/ntoskrnl/cc/copy.c b/ntoskrnl/cc/copy.c
index ca39f7cc18..a150848bb2 100644
--- a/ntoskrnl/cc/copy.c
+++ b/ntoskrnl/cc/copy.c
@@ -361,6 +361,80 @@ CcCopyData (
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
*/
@@ -532,6 +606,9 @@ CcDeferWrite (
&CcDeferredWriteSpinLock);
}
+ /* Try to execute the posted writes */
+ CcPostDeferredWrites();
+
/* FIXME: lock master */
if (!LazyWriter.ScanActive)
{
diff --git a/ntoskrnl/cc/lazywrite.c b/ntoskrnl/cc/lazywrite.c
index d38c6938b5..4619aa8c69 100644
--- a/ntoskrnl/cc/lazywrite.c
+++ b/ntoskrnl/cc/lazywrite.c
@@ -159,33 +159,10 @@ CcLazyWriteScan(VOID)
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))
diff --git a/ntoskrnl/include/internal/cc.h b/ntoskrnl/include/internal/cc.h
index 820cf7a2cb..157b655b3a 100644
--- a/ntoskrnl/include/internal/cc.h
+++ b/ntoskrnl/include/internal/cc.h
@@ -428,6 +428,9 @@ CcScanDpc(
VOID
CcScheduleLazyWriteScan(BOOLEAN NoDelay);
+VOID
+CcPostDeferredWrites(VOID);
+
FORCEINLINE
NTSTATUS
CcRosAcquireVacbLock(