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