mirror of
https://github.com/reactos/reactos.git
synced 2025-03-30 17:10:22 +00:00
[NTOSKRNL] Implement write behind in Cc
For now, this is just a split between scan and flush that were both done during lazy scan previously. Lazy scan shouldn't perform any write operation, but only queue a write behind operation. Our implementation is far from the original, as it seems our lazy scan should queue a write behind operation per shared cache map. Right now, we only perform global operation.
This commit is contained in:
parent
d5c74ae6fe
commit
7e97071c8b
2 changed files with 51 additions and 12 deletions
|
@ -109,15 +109,33 @@ CcScanDpc(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* And post it, it will be for lazy write */
|
/* And post it, it will be for lazy write */
|
||||||
WorkItem->Function = LazyWrite;
|
WorkItem->Function = LazyScan;
|
||||||
CcPostWorkQueue(WorkItem, &CcRegularWorkQueue);
|
CcPostWorkQueue(WorkItem, &CcRegularWorkQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CcWriteBehind(VOID)
|
||||||
|
{
|
||||||
|
ULONG Target, Count;
|
||||||
|
|
||||||
|
Target = CcTotalDirtyPages / 8;
|
||||||
|
if (Target != 0)
|
||||||
|
{
|
||||||
|
/* Flush! */
|
||||||
|
DPRINT("Lazy writer starting (%d)\n", Target);
|
||||||
|
CcRosFlushDirtyPages(Target, &Count, FALSE, TRUE);
|
||||||
|
|
||||||
|
/* And update stats */
|
||||||
|
CcLazyWritePages += Count;
|
||||||
|
++CcLazyWriteIos;
|
||||||
|
DPRINT("Lazy writer done (%d)\n", Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
CcLazyWriteScan(VOID)
|
CcLazyWriteScan(VOID)
|
||||||
{
|
{
|
||||||
ULONG Target;
|
ULONG Target;
|
||||||
ULONG Count;
|
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PLIST_ENTRY ListEntry;
|
PLIST_ENTRY ListEntry;
|
||||||
LIST_ENTRY ToPost;
|
LIST_ENTRY ToPost;
|
||||||
|
@ -142,14 +160,15 @@ CcLazyWriteScan(VOID)
|
||||||
Target = CcTotalDirtyPages / 8;
|
Target = CcTotalDirtyPages / 8;
|
||||||
if (Target != 0)
|
if (Target != 0)
|
||||||
{
|
{
|
||||||
/* Flush! */
|
/* There is stuff to flush, schedule a write-behind operation */
|
||||||
DPRINT("Lazy writer starting (%d)\n", Target);
|
|
||||||
CcRosFlushDirtyPages(Target, &Count, FALSE, TRUE);
|
|
||||||
|
|
||||||
/* And update stats */
|
/* Allocate a work item */
|
||||||
CcLazyWritePages += Count;
|
WorkItem = ExAllocateFromNPagedLookasideList(&CcTwilightLookasideList);
|
||||||
++CcLazyWriteIos;
|
if (WorkItem != NULL)
|
||||||
DPRINT("Lazy writer done (%d)\n", Count);
|
{
|
||||||
|
WorkItem->Function = WriteBehind;
|
||||||
|
CcPostWorkQueue(WorkItem, &CcRegularWorkQueue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Post items that were due for end of run */
|
/* Post items that were due for end of run */
|
||||||
|
@ -208,7 +227,7 @@ CcWorkerThread(
|
||||||
IN PVOID Parameter)
|
IN PVOID Parameter)
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
BOOLEAN DropThrottle;
|
BOOLEAN DropThrottle, WritePerformed;
|
||||||
PWORK_QUEUE_ITEM Item;
|
PWORK_QUEUE_ITEM Item;
|
||||||
#if DBG
|
#if DBG
|
||||||
PIRP TopLevel;
|
PIRP TopLevel;
|
||||||
|
@ -218,6 +237,8 @@ CcWorkerThread(
|
||||||
Item = Parameter;
|
Item = Parameter;
|
||||||
/* And by default, don't touch throttle */
|
/* And by default, don't touch throttle */
|
||||||
DropThrottle = FALSE;
|
DropThrottle = FALSE;
|
||||||
|
/* No write performed */
|
||||||
|
WritePerformed = FALSE;
|
||||||
|
|
||||||
#if DBG
|
#if DBG
|
||||||
/* Top level IRP should be clean when started
|
/* Top level IRP should be clean when started
|
||||||
|
@ -285,7 +306,12 @@ CcWorkerThread(
|
||||||
CcPerformReadAhead(WorkItem->Parameters.Read.FileObject);
|
CcPerformReadAhead(WorkItem->Parameters.Read.FileObject);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LazyWrite:
|
case WriteBehind:
|
||||||
|
CcWriteBehind();
|
||||||
|
WritePerformed = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LazyScan:
|
||||||
CcLazyWriteScan();
|
CcLazyWriteScan();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -309,6 +335,19 @@ CcWorkerThread(
|
||||||
--CcNumberActiveWorkerThreads;
|
--CcNumberActiveWorkerThreads;
|
||||||
KeReleaseQueuedSpinLock(LockQueueWorkQueueLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueueWorkQueueLock, OldIrql);
|
||||||
|
|
||||||
|
/* If there are pending write openations and we have at least 20 dirty pages */
|
||||||
|
if (!IsListEmpty(&CcDeferredWrites) && CcTotalDirtyPages >= 20)
|
||||||
|
{
|
||||||
|
/* And if we performed a write operation previously, then
|
||||||
|
* stress the system a bit and reschedule a scan to find
|
||||||
|
* stuff to write
|
||||||
|
*/
|
||||||
|
if (WritePerformed)
|
||||||
|
{
|
||||||
|
CcLazyWriteScan();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if DBG
|
#if DBG
|
||||||
/* Top level shouldn't have changed */
|
/* Top level shouldn't have changed */
|
||||||
if (TopLevel != IoGetTopLevelIrp())
|
if (TopLevel != IoGetTopLevelIrp())
|
||||||
|
|
|
@ -278,7 +278,7 @@ typedef enum _WORK_QUEUE_FUNCTIONS
|
||||||
{
|
{
|
||||||
ReadAhead = 1,
|
ReadAhead = 1,
|
||||||
WriteBehind = 2,
|
WriteBehind = 2,
|
||||||
LazyWrite = 3,
|
LazyScan = 3,
|
||||||
SetDone = 4,
|
SetDone = 4,
|
||||||
} WORK_QUEUE_FUNCTIONS, *PWORK_QUEUE_FUNCTIONS;
|
} WORK_QUEUE_FUNCTIONS, *PWORK_QUEUE_FUNCTIONS;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue