mirror of
https://github.com/reactos/reactos.git
synced 2024-11-23 19:43:31 +08:00
[NTOS:CC] Rewrite CcPostDeferredWrites
This allows to post small writes if there are any, and avoid holding the list lock for a long time.
This commit is contained in:
parent
b13a696513
commit
5c54fb9179
@ -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)
|
||||
ListEntry = ExInterlockedRemoveHeadList(&CcDeferredWrites, &CcDeferredWriteSpinLock);
|
||||
|
||||
if (!ListEntry)
|
||||
break;
|
||||
|
||||
DeferredWrite = CONTAINING_RECORD(ListEntry, DEFERRED_WRITE, DeferredWriteLinks);
|
||||
|
||||
/* Check if we can write */
|
||||
if (CcCanIWrite(DeferredWrite->FileObject, DeferredWrite->BytesToWrite, FALSE, RetryForceCheckPerFile))
|
||||
{
|
||||
/* 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)
|
||||
/* If we have an event, set it and go along */
|
||||
if (DeferredWrite->Event)
|
||||
{
|
||||
DeferredWrite = NULL;
|
||||
break;
|
||||
KeSetEvent(DeferredWrite->Event, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
|
||||
/* Check we can write */
|
||||
if (CcCanIWrite(DeferredWrite->FileObject, WrittenBytes, FALSE, RetryForceCheckPerFile))
|
||||
/* Otherwise, call the write routine and free the context */
|
||||
else
|
||||
{
|
||||
/* We can, so remove it from the list and stop looking for entry */
|
||||
RemoveEntryList(&DeferredWrite->DeferredWriteLinks);
|
||||
break;
|
||||
DeferredWrite->PostRoutine(DeferredWrite->Context1, DeferredWrite->Context2);
|
||||
ExFreePoolWithTag(DeferredWrite, 'CcDw');
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user