+/* FIXME: Someday this could somewhat implement write-behind/read-ahead */
+VOID
+NTAPI
+CciLazyWriter(PVOID Unused)
+{
+ LARGE_INTEGER OneSecond;
+
+ OneSecond.QuadPart = (LONGLONG)-1*1000*1000*10;
+
+ while (TRUE)
+ {
+ NTSTATUS Status;
+ PLIST_ENTRY ListEntry;
+ ULONG Target, Count = 0;
+
+ /* One per second or until we have to stop */
+ Status = KeWaitForSingleObject(&iLazyWriterShutdown,
+ Executive,
+ KernelMode,
+ FALSE,
+ &OneSecond);
+
+ /* If we succeeed, we've to stop running! */
+ if (Status == STATUS_SUCCESS)
+ {
+ break;
+ }
+
+ /* We're not sleeping anymore */
+ KeClearEvent(&iLazyWriterNotify);
+
+ /* Our target is one-eighth of the dirty pages */
+ 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);
+ }
+
+ /* Inform people waiting on us that we're done */
+ KeSetEvent(&iLazyWriterNotify, IO_DISK_INCREMENT, FALSE);
+
+ /* Likely not optimal, but let's handle one deferred write now! */
+ ListEntry = ExInterlockedRemoveHeadList(&CcDeferredWrites, &CcDeferredWriteSpinLock);
+ if (ListEntry != NULL)
+ {
+ PROS_DEFERRED_WRITE_CONTEXT Context;
+
+ /* Extract the context */
+ Context = CONTAINING_RECORD(ListEntry, ROS_DEFERRED_WRITE_CONTEXT, CcDeferredWritesEntry);
+
+ /* Can we write now? */
+ if (CcCanIWrite(Context->FileObject, Context->BytesToWrite, FALSE, Context->Retrying))
+ {
+ /* 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->CcDeferredWritesEntry,
+ &CcDeferredWriteSpinLock);
+ }
+ }
+ }
+}
+