https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f93acd806aaff5a4698205ec8b432194b14a4f40

commit f93acd806aaff5a4698205ec8b432194b14a4f40
Author:     Pierre Schweitzer <[email protected]>
AuthorDate: Tue Jan 23 23:23:32 2018 +0100
Commit:     Pierre Schweitzer <[email protected]>
CommitDate: Tue Jan 23 23:25:26 2018 +0100

    [NTOSKRNL] Implement per-file dirty page threshold.
    Namely, implement CcSetDirtyPageThreshold() and add support for it
    in CcCanIWrite().
    
    Also added my name in the headers of the few files I touched tonight.
    
    CORE-14235
---
 ntoskrnl/cc/cacheman.c         | 18 +++++++++++++--
 ntoskrnl/cc/copy.c             | 52 ++++++++++++++++++++++++++++++++++++++++--
 ntoskrnl/cc/view.c             |  2 ++
 ntoskrnl/include/internal/cc.h |  1 +
 4 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/ntoskrnl/cc/cacheman.c b/ntoskrnl/cc/cacheman.c
index 2c2c2238c9..8303dd9dd8 100644
--- a/ntoskrnl/cc/cacheman.c
+++ b/ntoskrnl/cc/cacheman.c
@@ -5,6 +5,7 @@
  * PURPOSE:         Cache manager
  *
  * PROGRAMMERS:     David Welch ([email protected])
+ *                  Pierre Schweitzer ([email protected])
  */
 
 /* INCLUDES *****************************************************************/
@@ -140,7 +141,7 @@ CcSetBcbOwnerPointer (
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 VOID
 NTAPI
@@ -149,10 +150,23 @@ CcSetDirtyPageThreshold (
        IN      ULONG           DirtyPageThreshold
        )
 {
+    PFSRTL_COMMON_FCB_HEADER Fcb;
+    PROS_SHARED_CACHE_MAP SharedCacheMap;
+
     CCTRACE(CC_API_DEBUG, "FileObject=%p DirtyPageThreshold=%lu\n",
         FileObject, DirtyPageThreshold);
 
-       UNIMPLEMENTED;
+    SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
+    if (SharedCacheMap != NULL)
+    {
+        SharedCacheMap->DirtyPageThreshold = DirtyPageThreshold;
+    }
+
+    Fcb = FileObject->FsContext;
+    if (!BooleanFlagOn(Fcb->Flags, FSRTL_FLAG_LIMIT_MODIFIED_PAGES))
+    {
+        SetFlag(Fcb->Flags, FSRTL_FLAG_LIMIT_MODIFIED_PAGES);
+    }
 }
 
 /*
diff --git a/ntoskrnl/cc/copy.c b/ntoskrnl/cc/copy.c
index 4c68bf036b..db6f0f4920 100644
--- a/ntoskrnl/cc/copy.c
+++ b/ntoskrnl/cc/copy.c
@@ -4,7 +4,8 @@
  * FILE:            ntoskrnl/cc/copy.c
  * PURPOSE:         Implements cache managers copy interface
  *
- * PROGRAMMERS:
+ * PROGRAMMERS:     Some people?
+ *                  Pierre Schweitzer ([email protected])
  */
 
 /* INCLUDES ******************************************************************/
@@ -375,6 +376,12 @@ CcCanIWrite (
     IN BOOLEAN Wait,
     IN BOOLEAN Retrying)
 {
+    KIRQL OldIrql;
+    ULONG DirtyPages;
+    PLIST_ENTRY ListEntry;
+    PFSRTL_COMMON_FCB_HEADER Fcb;
+    PROS_SHARED_CACHE_MAP SharedCacheMap;
+
     CCTRACE(CC_API_DEBUG, "FileObject=%p BytesToWrite=%lu Wait=%d 
Retrying=%d\n",
         FileObject, BytesToWrite, Wait, Retrying);
 
@@ -392,7 +399,48 @@ CcCanIWrite (
         return FALSE;
     }
 
-    /* FIXME: Handle per-file threshold */
+    /* Is there a limit per file object? */
+    Fcb = FileObject->FsContext;
+    SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
+    if (!BooleanFlagOn(Fcb->Flags, FSRTL_FLAG_LIMIT_MODIFIED_PAGES) ||
+        SharedCacheMap->DirtyPageThreshold == 0)
+    {
+        /* Nope, so that's fine, allow write operation */
+        return TRUE;
+    }
+
+    /* There's a limit, start counting dirty pages */
+    DirtyPages = 0;
+    KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &OldIrql);
+    for (ListEntry = SharedCacheMap->CacheMapVacbListHead.Flink;
+         ListEntry != &SharedCacheMap->CacheMapVacbListHead;
+         ListEntry = ListEntry->Flink)
+    {
+        PROS_VACB Vacb;
+
+        Vacb = CONTAINING_RECORD(ListEntry,
+                                 ROS_VACB,
+                                 CacheMapVacbListEntry);
+        if (Vacb->Dirty)
+        {
+            DirtyPages += VACB_MAPPING_GRANULARITY / PAGE_SIZE;
+        }
+    }
+    KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql);
+
+    /* Is dirty page count above local threshold? */
+    if (DirtyPages > SharedCacheMap->DirtyPageThreshold)
+    {
+        return FALSE;
+    }
+
+    /* We cannot write if dirty pages count will bring use above
+     * XXX: Might not be accurate
+     */
+    if (DirtyPages + (BytesToWrite / PAGE_SIZE) > 
SharedCacheMap->DirtyPageThreshold)
+    {
+        return FALSE;
+    }
 
     return TRUE;
 }
diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c
index 61036b0d99..2bab26c446 100644
--- a/ntoskrnl/cc/view.c
+++ b/ntoskrnl/cc/view.c
@@ -5,6 +5,7 @@
  * PURPOSE:         Cache manager
  *
  * PROGRAMMERS:     David Welch ([email protected])
+ *                  Pierre Schweitzer ([email protected])
  */
 
 /* NOTES **********************************************************************
@@ -1333,6 +1334,7 @@ CcRosInitializeFileCache (
         SharedCacheMap->SectionSize = FileSizes->AllocationSize;
         SharedCacheMap->FileSize = FileSizes->FileSize;
         SharedCacheMap->PinAccess = PinAccess;
+        SharedCacheMap->DirtyPageThreshold = 0;
         KeInitializeSpinLock(&SharedCacheMap->CacheMapLock);
         InitializeListHead(&SharedCacheMap->CacheMapVacbListHead);
         FileObject->SectionObjectPointer->SharedCacheMap = SharedCacheMap;
diff --git a/ntoskrnl/include/internal/cc.h b/ntoskrnl/include/internal/cc.h
index 05eb53fec7..2699dfcf43 100644
--- a/ntoskrnl/include/internal/cc.h
+++ b/ntoskrnl/include/internal/cc.h
@@ -159,6 +159,7 @@ typedef struct _ROS_SHARED_CACHE_MAP
     PVOID LazyWriteContext;
     KSPIN_LOCK CacheMapLock;
     ULONG OpenCount;
+    ULONG DirtyPageThreshold;
 #if DBG
     BOOLEAN Trace; /* enable extra trace output for this cache map and it's 
VACBs */
 #endif

Reply via email to