https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f93acd806aaff5a469820…
commit f93acd806aaff5a4698205ec8b432194b14a4f40
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Tue Jan 23 23:23:32 2018 +0100
Commit: Pierre Schweitzer <pierre(a)reactos.org>
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 (welch(a)cwcom.net)
+ * Pierre Schweitzer (pierre(a)reactos.org)
*/
/* 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 (pierre(a)reactos.org)
*/
/* 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 (welch(a)mcmail.com)
+ * Pierre Schweitzer (pierre(a)reactos.org)
*/
/* 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