mirror of
https://github.com/reactos/reactos.git
synced 2024-07-10 14:45:06 +00:00
c7ad200f8b
This removes the "modified page writer" thread in Mm that was regularly blindly attempting to flush dirty pages to the disk. Instead, this commit introduces a lazy writer that will monitor dirty pages count and will flush them to disk when this count is above a threshold. The threshold is computed on Cc init. Compared to what was done previously, this lazy writer will only write down files that are not marked as temporary. The mechanisms involved in this lazy writer worker are well described in Windows Internals 4th editions (constants are coming from it ;-)). Also fixed a bad (and old!) bug in CcRosFlushDirtyPages() where target count could be overflow and the function would spin forever while holding the VACBs lock. This is mandatory as now lazy writer will call it with "random" values. This also allows implementing CcWaitForCurrentLazyWriterActivity() :-). Also renamed DirtyPageCount to its MS equivalent. CORE-14235
401 lines
8.6 KiB
C
401 lines
8.6 KiB
C
#pragma once
|
|
|
|
//
|
|
// Define this if you want debugging support
|
|
//
|
|
#define _CC_DEBUG_ 0x00
|
|
|
|
//
|
|
// These define the Debug Masks Supported
|
|
//
|
|
#define CC_API_DEBUG 0x01
|
|
|
|
//
|
|
// Debug/Tracing support
|
|
//
|
|
#if _CC_DEBUG_
|
|
#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented
|
|
#define CCTRACE(x, ...) \
|
|
{ \
|
|
DbgPrintEx("%s [%.16s] - ", \
|
|
__FUNCTION__, \
|
|
PsGetCurrentProcess()->ImageFileName); \
|
|
DbgPrintEx(__VA_ARGS__); \
|
|
}
|
|
#else
|
|
#define CCTRACE(x, ...) \
|
|
if (x & CcRosTraceLevel) \
|
|
{ \
|
|
DbgPrint("%s [%.16s] - ", \
|
|
__FUNCTION__, \
|
|
PsGetCurrentProcess()->ImageFileName); \
|
|
DbgPrint(__VA_ARGS__); \
|
|
}
|
|
#endif
|
|
#else
|
|
#define CCTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__)
|
|
#endif
|
|
|
|
//
|
|
// Global Cc Data
|
|
//
|
|
extern ULONG CcRosTraceLevel;
|
|
extern LIST_ENTRY DirtyVacbListHead;
|
|
|
|
typedef struct _PF_SCENARIO_ID
|
|
{
|
|
WCHAR ScenName[30];
|
|
ULONG HashId;
|
|
} PF_SCENARIO_ID, *PPF_SCENARIO_ID;
|
|
|
|
typedef struct _PF_LOG_ENTRY
|
|
{
|
|
ULONG FileOffset:30;
|
|
ULONG Type:2;
|
|
union
|
|
{
|
|
ULONG FileKey;
|
|
ULONG FileSequenceNumber;
|
|
};
|
|
} PF_LOG_ENTRY, *PPF_LOG_ENTRY;
|
|
|
|
typedef struct _PFSN_LOG_ENTRIES
|
|
{
|
|
LIST_ENTRY TraceBuffersLink;
|
|
LONG NumEntries;
|
|
LONG MaxEntries;
|
|
PF_LOG_ENTRY Entries[ANYSIZE_ARRAY];
|
|
} PFSN_LOG_ENTRIES, *PPFSN_LOG_ENTRIES;
|
|
|
|
typedef struct _PF_SECTION_INFO
|
|
{
|
|
ULONG FileKey;
|
|
ULONG FileSequenceNumber;
|
|
ULONG FileIdLow;
|
|
ULONG FileIdHigh;
|
|
} PF_SECTION_INFO, *PPF_SECTION_INFO;
|
|
|
|
typedef struct _PF_TRACE_HEADER
|
|
{
|
|
ULONG Version;
|
|
ULONG MagicNumber;
|
|
ULONG Size;
|
|
PF_SCENARIO_ID ScenarioId;
|
|
ULONG ScenarioType; // PF_SCENARIO_TYPE
|
|
ULONG EventEntryIdxs[8];
|
|
ULONG NumEventEntryIdxs;
|
|
ULONG TraceBufferOffset;
|
|
ULONG NumEntries;
|
|
ULONG SectionInfoOffset;
|
|
ULONG NumSections;
|
|
ULONG FaultsPerPeriod[10];
|
|
LARGE_INTEGER LaunchTime;
|
|
ULONGLONG Reserved[5];
|
|
} PF_TRACE_HEADER, *PPF_TRACE_HEADER;
|
|
|
|
typedef struct _PFSN_TRACE_DUMP
|
|
{
|
|
LIST_ENTRY CompletedTracesLink;
|
|
PF_TRACE_HEADER Trace;
|
|
} PFSN_TRACE_DUMP, *PPFSN_TRACE_DUMP;
|
|
|
|
typedef struct _PFSN_TRACE_HEADER
|
|
{
|
|
ULONG Magic;
|
|
LIST_ENTRY ActiveTracesLink;
|
|
PF_SCENARIO_ID ScenarioId;
|
|
ULONG ScenarioType; // PF_SCENARIO_TYPE
|
|
ULONG EventEntryIdxs[8];
|
|
ULONG NumEventEntryIdxs;
|
|
PPFSN_LOG_ENTRIES CurrentTraceBuffer;
|
|
LIST_ENTRY TraceBuffersList;
|
|
ULONG NumTraceBuffers;
|
|
KSPIN_LOCK TraceBufferSpinLock;
|
|
KTIMER TraceTimer;
|
|
LARGE_INTEGER TraceTimerPeriod;
|
|
KDPC TraceTimerDpc;
|
|
KSPIN_LOCK TraceTimerSpinLock;
|
|
ULONG FaultsPerPeriod[10];
|
|
LONG LastNumFaults;
|
|
LONG CurPeriod;
|
|
LONG NumFaults;
|
|
LONG MaxFaults;
|
|
PEPROCESS Process;
|
|
EX_RUNDOWN_REF RefCount;
|
|
WORK_QUEUE_ITEM EndTraceWorkItem;
|
|
LONG EndTraceCalled;
|
|
PPFSN_TRACE_DUMP TraceDump;
|
|
NTSTATUS TraceDumpStatus;
|
|
LARGE_INTEGER LaunchTime;
|
|
PPF_SECTION_INFO SectionInfo;
|
|
ULONG SectionInfoCount;
|
|
} PFSN_TRACE_HEADER, *PPFSN_TRACE_HEADER;
|
|
|
|
typedef struct _PFSN_PREFETCHER_GLOBALS
|
|
{
|
|
LIST_ENTRY ActiveTraces;
|
|
KSPIN_LOCK ActiveTracesLock;
|
|
PPFSN_TRACE_HEADER SystemWideTrace;
|
|
LIST_ENTRY CompletedTraces;
|
|
FAST_MUTEX CompletedTracesLock;
|
|
LONG NumCompletedTraces;
|
|
PKEVENT CompletedTracesEvent;
|
|
LONG ActivePrefetches;
|
|
} PFSN_PREFETCHER_GLOBALS, *PPFSN_PREFETCHER_GLOBALS;
|
|
|
|
typedef struct _ROS_SHARED_CACHE_MAP
|
|
{
|
|
LIST_ENTRY CacheMapVacbListHead;
|
|
ULONG TimeStamp;
|
|
PFILE_OBJECT FileObject;
|
|
LARGE_INTEGER SectionSize;
|
|
LARGE_INTEGER FileSize;
|
|
BOOLEAN PinAccess;
|
|
PCACHE_MANAGER_CALLBACKS Callbacks;
|
|
PVOID LazyWriteContext;
|
|
KSPIN_LOCK CacheMapLock;
|
|
ULONG OpenCount;
|
|
#if DBG
|
|
BOOLEAN Trace; /* enable extra trace output for this cache map and it's VACBs */
|
|
#endif
|
|
} ROS_SHARED_CACHE_MAP, *PROS_SHARED_CACHE_MAP;
|
|
|
|
typedef struct _ROS_VACB
|
|
{
|
|
/* Base address of the region where the view's data is mapped. */
|
|
PVOID BaseAddress;
|
|
/* Memory area representing the region where the view's data is mapped. */
|
|
struct _MEMORY_AREA* MemoryArea;
|
|
/* Are the contents of the view valid. */
|
|
BOOLEAN Valid;
|
|
/* Are the contents of the view newer than those on disk. */
|
|
BOOLEAN Dirty;
|
|
/* Page out in progress */
|
|
BOOLEAN PageOut;
|
|
ULONG MappedCount;
|
|
/* Entry in the list of VACBs for this shared cache map. */
|
|
LIST_ENTRY CacheMapVacbListEntry;
|
|
/* Entry in the list of VACBs which are dirty. */
|
|
LIST_ENTRY DirtyVacbListEntry;
|
|
/* Entry in the list of VACBs. */
|
|
LIST_ENTRY VacbLruListEntry;
|
|
/* Offset in the file which this view maps. */
|
|
LARGE_INTEGER FileOffset;
|
|
/* Mutex */
|
|
KMUTEX Mutex;
|
|
/* Number of references. */
|
|
ULONG ReferenceCount;
|
|
/* How many times was it pinned? */
|
|
_Guarded_by_(Mutex)
|
|
LONG PinCount;
|
|
/* Pointer to the shared cache map for the file which this view maps data for. */
|
|
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
|
/* Pointer to the next VACB in a chain. */
|
|
} ROS_VACB, *PROS_VACB;
|
|
|
|
typedef struct _INTERNAL_BCB
|
|
{
|
|
/* Lock */
|
|
ERESOURCE Lock;
|
|
PUBLIC_BCB PFCB;
|
|
PROS_VACB Vacb;
|
|
BOOLEAN Dirty;
|
|
BOOLEAN Pinned;
|
|
CSHORT RefCount; /* (At offset 0x34 on WinNT4) */
|
|
} INTERNAL_BCB, *PINTERNAL_BCB;
|
|
|
|
VOID
|
|
NTAPI
|
|
CcPfInitializePrefetcher(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
NTAPI
|
|
CcMdlReadComplete2(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PMDL MemoryDescriptorList
|
|
);
|
|
|
|
VOID
|
|
NTAPI
|
|
CcMdlWriteComplete2(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN PMDL MdlChain
|
|
);
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcRosFlushVacb(PROS_VACB Vacb);
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcRosGetVacb(
|
|
PROS_SHARED_CACHE_MAP SharedCacheMap,
|
|
LONGLONG FileOffset,
|
|
PLONGLONG BaseOffset,
|
|
PVOID *BaseAddress,
|
|
PBOOLEAN UptoDate,
|
|
PROS_VACB *Vacb
|
|
);
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
CcInitView(VOID);
|
|
|
|
VOID
|
|
NTAPI
|
|
CcShutdownLazyWriter(VOID);
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcReadVirtualAddress(PROS_VACB Vacb);
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcWriteVirtualAddress(PROS_VACB Vacb);
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
CcInitializeCacheManager(VOID);
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcRosUnmapVacb(
|
|
PROS_SHARED_CACHE_MAP SharedCacheMap,
|
|
LONGLONG FileOffset,
|
|
BOOLEAN NowDirty
|
|
);
|
|
|
|
PROS_VACB
|
|
NTAPI
|
|
CcRosLookupVacb(
|
|
PROS_SHARED_CACHE_MAP SharedCacheMap,
|
|
LONGLONG FileOffset
|
|
);
|
|
|
|
VOID
|
|
NTAPI
|
|
CcInitCacheZeroPage(VOID);
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcRosMarkDirtyVacb(
|
|
PROS_SHARED_CACHE_MAP SharedCacheMap,
|
|
LONGLONG FileOffset
|
|
);
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcRosFlushDirtyPages(
|
|
ULONG Target,
|
|
PULONG Count,
|
|
BOOLEAN Wait,
|
|
BOOLEAN CalledFromLazy
|
|
);
|
|
|
|
VOID
|
|
NTAPI
|
|
CcRosDereferenceCache(PFILE_OBJECT FileObject);
|
|
|
|
VOID
|
|
NTAPI
|
|
CcRosReferenceCache(PFILE_OBJECT FileObject);
|
|
|
|
VOID
|
|
NTAPI
|
|
CcRosRemoveIfClosed(PSECTION_OBJECT_POINTERS SectionObjectPointer);
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcRosReleaseVacb(
|
|
PROS_SHARED_CACHE_MAP SharedCacheMap,
|
|
PROS_VACB Vacb,
|
|
BOOLEAN Valid,
|
|
BOOLEAN Dirty,
|
|
BOOLEAN Mapped
|
|
);
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcRosRequestVacb(
|
|
PROS_SHARED_CACHE_MAP SharedCacheMap,
|
|
LONGLONG FileOffset,
|
|
PVOID* BaseAddress,
|
|
PBOOLEAN UptoDate,
|
|
PROS_VACB *Vacb
|
|
);
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcRosInitializeFileCache(
|
|
PFILE_OBJECT FileObject,
|
|
PCC_FILE_SIZES FileSizes,
|
|
BOOLEAN PinAccess,
|
|
PCACHE_MANAGER_CALLBACKS CallBacks,
|
|
PVOID LazyWriterContext
|
|
);
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcRosReleaseFileCache(
|
|
PFILE_OBJECT FileObject
|
|
);
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CcTryToInitializeFileCache(PFILE_OBJECT FileObject);
|
|
|
|
VOID
|
|
NTAPI
|
|
CcShutdownSystem(VOID);
|
|
|
|
FORCEINLINE
|
|
NTSTATUS
|
|
CcRosAcquireVacbLock(
|
|
_Inout_ PROS_VACB Vacb,
|
|
_In_ PLARGE_INTEGER Timeout)
|
|
{
|
|
NTSTATUS Status;
|
|
Status = KeWaitForSingleObject(&Vacb->Mutex,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
Timeout);
|
|
return Status;
|
|
}
|
|
|
|
FORCEINLINE
|
|
VOID
|
|
CcRosReleaseVacbLock(
|
|
_Inout_ PROS_VACB Vacb)
|
|
{
|
|
KeReleaseMutex(&Vacb->Mutex, FALSE);
|
|
}
|
|
|
|
FORCEINLINE
|
|
BOOLEAN
|
|
DoRangesIntersect(
|
|
_In_ LONGLONG Offset1,
|
|
_In_ LONGLONG Length1,
|
|
_In_ LONGLONG Offset2,
|
|
_In_ LONGLONG Length2)
|
|
{
|
|
if (Offset1 + Length1 <= Offset2)
|
|
return FALSE;
|
|
if (Offset2 + Length2 <= Offset1)
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
FORCEINLINE
|
|
BOOLEAN
|
|
IsPointInRange(
|
|
_In_ LONGLONG Offset1,
|
|
_In_ LONGLONG Length1,
|
|
_In_ LONGLONG Point)
|
|
{
|
|
return DoRangesIntersect(Offset1, Length1, Point, 1);
|
|
}
|