https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7e97071c8b715b16303ac…
commit 7e97071c8b715b16303ac7fa00be652b17f552ec
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Sun Dec 23 14:43:17 2018 +0100
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Sun Dec 23 14:45:38 2018 +0100
[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.
---
ntoskrnl/cc/lazywrite.c | 61 ++++++++++++++++++++++++++++++++++--------
ntoskrnl/include/internal/cc.h | 2 +-
2 files changed, 51 insertions(+), 12 deletions(-)
diff --git a/ntoskrnl/cc/lazywrite.c b/ntoskrnl/cc/lazywrite.c
index 8cb5adb2e7..275507e904 100644
--- a/ntoskrnl/cc/lazywrite.c
+++ b/ntoskrnl/cc/lazywrite.c
@@ -109,15 +109,33 @@ CcScanDpc(
}
/* And post it, it will be for lazy write */
- WorkItem->Function = LazyWrite;
+ WorkItem->Function = LazyScan;
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
CcLazyWriteScan(VOID)
{
ULONG Target;
- ULONG Count;
KIRQL OldIrql;
PLIST_ENTRY ListEntry;
LIST_ENTRY ToPost;
@@ -142,14 +160,15 @@ CcLazyWriteScan(VOID)
Target = CcTotalDirtyPages / 8;
if (Target != 0)
{
- /* Flush! */
- DPRINT("Lazy writer starting (%d)\n", Target);
- CcRosFlushDirtyPages(Target, &Count, FALSE, TRUE);
+ /* There is stuff to flush, schedule a write-behind operation */
- /* And update stats */
- CcLazyWritePages += Count;
- ++CcLazyWriteIos;
- DPRINT("Lazy writer done (%d)\n", Count);
+ /* Allocate a work item */
+ WorkItem = ExAllocateFromNPagedLookasideList(&CcTwilightLookasideList);
+ if (WorkItem != NULL)
+ {
+ WorkItem->Function = WriteBehind;
+ CcPostWorkQueue(WorkItem, &CcRegularWorkQueue);
+ }
}
/* Post items that were due for end of run */
@@ -208,7 +227,7 @@ CcWorkerThread(
IN PVOID Parameter)
{
KIRQL OldIrql;
- BOOLEAN DropThrottle;
+ BOOLEAN DropThrottle, WritePerformed;
PWORK_QUEUE_ITEM Item;
#if DBG
PIRP TopLevel;
@@ -218,6 +237,8 @@ CcWorkerThread(
Item = Parameter;
/* And by default, don't touch throttle */
DropThrottle = FALSE;
+ /* No write performed */
+ WritePerformed = FALSE;
#if DBG
/* Top level IRP should be clean when started
@@ -285,7 +306,12 @@ CcWorkerThread(
CcPerformReadAhead(WorkItem->Parameters.Read.FileObject);
break;
- case LazyWrite:
+ case WriteBehind:
+ CcWriteBehind();
+ WritePerformed = TRUE;
+ break;
+
+ case LazyScan:
CcLazyWriteScan();
break;
@@ -309,6 +335,19 @@ CcWorkerThread(
--CcNumberActiveWorkerThreads;
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
/* Top level shouldn't have changed */
if (TopLevel != IoGetTopLevelIrp())
diff --git a/ntoskrnl/include/internal/cc.h b/ntoskrnl/include/internal/cc.h
index 8a5fb73838..10bdb43a86 100644
--- a/ntoskrnl/include/internal/cc.h
+++ b/ntoskrnl/include/internal/cc.h
@@ -278,7 +278,7 @@ typedef enum _WORK_QUEUE_FUNCTIONS
{
ReadAhead = 1,
WriteBehind = 2,
- LazyWrite = 3,
+ LazyScan = 3,
SetDone = 4,
} WORK_QUEUE_FUNCTIONS, *PWORK_QUEUE_FUNCTIONS;