mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:03:00 +00:00
[NTOSKRNL] Implement CcPostDeferredWrites() that executes deferred writes.
Make use of it in the lazy writer
This commit is contained in:
parent
f4e67aa837
commit
92e64a6c9b
3 changed files with 83 additions and 26 deletions
|
@ -361,6 +361,80 @@ CcCopyData (
|
||||||
return TRUE;
|
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
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
|
@ -532,6 +606,9 @@ CcDeferWrite (
|
||||||
&CcDeferredWriteSpinLock);
|
&CcDeferredWriteSpinLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try to execute the posted writes */
|
||||||
|
CcPostDeferredWrites();
|
||||||
|
|
||||||
/* FIXME: lock master */
|
/* FIXME: lock master */
|
||||||
if (!LazyWriter.ScanActive)
|
if (!LazyWriter.ScanActive)
|
||||||
{
|
{
|
||||||
|
|
|
@ -159,33 +159,10 @@ CcLazyWriteScan(VOID)
|
||||||
DPRINT1("Lazy writer done (%d)\n", Count);
|
DPRINT1("Lazy writer done (%d)\n", Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Likely not optimal, but let's handle one deferred write now! */
|
/* If we have deferred writes, try them now! */
|
||||||
ListEntry = ExInterlockedRemoveHeadList(&CcDeferredWrites, &CcDeferredWriteSpinLock);
|
if (!IsListEmpty(&CcDeferredWrites))
|
||||||
if (ListEntry != NULL)
|
|
||||||
{
|
{
|
||||||
PDEFERRED_WRITE Context;
|
CcPostDeferredWrites();
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!IsListEmpty(&ToPost))
|
while (!IsListEmpty(&ToPost))
|
||||||
|
|
|
@ -428,6 +428,9 @@ CcScanDpc(
|
||||||
VOID
|
VOID
|
||||||
CcScheduleLazyWriteScan(BOOLEAN NoDelay);
|
CcScheduleLazyWriteScan(BOOLEAN NoDelay);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CcPostDeferredWrites(VOID);
|
||||||
|
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CcRosAcquireVacbLock(
|
CcRosAcquireVacbLock(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue