From: Pierre Schweitzer Date: Wed, 7 Feb 2018 19:27:55 +0000 (+0100) Subject: [NTOSKRNL] Implement CcPostDeferredWrites() that executes deferred writes. X-Git-Tag: 0.4.9-dev~71 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=92e64a6c9bbd68c81914c7ce63c4888b9ca4d54b [NTOSKRNL] Implement CcPostDeferredWrites() that executes deferred writes. Make use of it in the lazy writer --- diff --git a/ntoskrnl/cc/copy.c b/ntoskrnl/cc/copy.c index ca39f7cc180..a150848bb20 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 d38c6938b57..4619aa8c69a 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 820cf7a2cb1..157b655b3a5 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(