[NTOSKRNL] Implement CcPostDeferredWrites() that executes deferred writes.

Make use of it in the lazy writer
This commit is contained in:
Pierre Schweitzer 2018-02-07 20:27:55 +01:00
parent f4e67aa837
commit 92e64a6c9b
No known key found for this signature in database
GPG key ID: 7545556C3D585B0B
3 changed files with 83 additions and 26 deletions

View file

@ -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)
{

View file

@ -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))

View file

@ -428,6 +428,9 @@ CcScanDpc(
VOID
CcScheduleLazyWriteScan(BOOLEAN NoDelay);
VOID
CcPostDeferredWrites(VOID);
FORCEINLINE
NTSTATUS
CcRosAcquireVacbLock(