Reactos
1#pragma once
2
3//
4// Define this if you want debugging support
5//
6#define _CC_DEBUG_ 0x00
7
8//
9// These define the Debug Masks Supported
10//
11#define CC_API_DEBUG 0x01
12
13//
14// Debug/Tracing support
15//
16#if _CC_DEBUG_
17#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented
18#define CCTRACE(x, ...) \
19 { \
20 DbgPrintEx("%s [%.16s] - ", \
21 __FUNCTION__, \
22 PsGetCurrentProcess()->ImageFileName); \
23 DbgPrintEx(__VA_ARGS__); \
24 }
25#else
26#define CCTRACE(x, ...) \
27 if (x & CcRosTraceLevel) \
28 { \
29 DbgPrint("%s [%.16s] - ", \
30 __FUNCTION__, \
31 PsGetCurrentProcess()->ImageFileName); \
32 DbgPrint(__VA_ARGS__); \
33 }
34#endif
35#else
36#define CCTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__)
37#endif
38
39//
40// Global Cc Data
41//
42extern ULONG CcRosTraceLevel;
43extern LIST_ENTRY DirtyVacbListHead;
44extern ULONG CcDirtyPageThreshold;
45extern ULONG CcTotalDirtyPages;
46extern LIST_ENTRY CcDeferredWrites;
47extern KSPIN_LOCK CcDeferredWriteSpinLock;
48extern ULONG CcNumberWorkerThreads;
49extern LIST_ENTRY CcIdleWorkerThreadList;
50extern LIST_ENTRY CcExpressWorkQueue;
51extern LIST_ENTRY CcRegularWorkQueue;
52extern LIST_ENTRY CcPostTickWorkQueue;
53extern NPAGED_LOOKASIDE_LIST CcTwilightLookasideList;
54extern LARGE_INTEGER CcIdleDelay;
55
56//
57// Counters
58//
59extern ULONG CcLazyWritePages;
60extern ULONG CcLazyWriteIos;
61extern ULONG CcMapDataWait;
62extern ULONG CcMapDataNoWait;
63extern ULONG CcPinReadWait;
64extern ULONG CcPinReadNoWait;
65extern ULONG CcPinMappedDataCount;
66extern ULONG CcDataPages;
67extern ULONG CcDataFlushes;
68
69typedef struct _PF_SCENARIO_ID
70{
71 WCHAR ScenName[30];
72 ULONG HashId;
73} PF_SCENARIO_ID, *PPF_SCENARIO_ID;
74
75typedef struct _PF_LOG_ENTRY
76{
77 ULONG FileOffset:30;
78 ULONG Type:2;
79 union
80 {
81 ULONG FileKey;
82 ULONG FileSequenceNumber;
83 };
84} PF_LOG_ENTRY, *PPF_LOG_ENTRY;
85
86typedef struct _PFSN_LOG_ENTRIES
87{
88 LIST_ENTRY TraceBuffersLink;
89 LONG NumEntries;
90 LONG MaxEntries;
91 PF_LOG_ENTRY Entries[ANYSIZE_ARRAY];
92} PFSN_LOG_ENTRIES, *PPFSN_LOG_ENTRIES;
93
94typedef struct _PF_SECTION_INFO
95{
96 ULONG FileKey;
97 ULONG FileSequenceNumber;
98 ULONG FileIdLow;
99 ULONG FileIdHigh;
100} PF_SECTION_INFO, *PPF_SECTION_INFO;
101
102typedef struct _PF_TRACE_HEADER
103{
104 ULONG Version;
105 ULONG MagicNumber;
106 ULONG Size;
107 PF_SCENARIO_ID ScenarioId;
108 ULONG ScenarioType; // PF_SCENARIO_TYPE
109 ULONG EventEntryIdxs[8];
110 ULONG NumEventEntryIdxs;
111 ULONG TraceBufferOffset;
112 ULONG NumEntries;
113 ULONG SectionInfoOffset;
114 ULONG NumSections;
115 ULONG FaultsPerPeriod[10];
116 LARGE_INTEGER LaunchTime;
117 ULONGLONG Reserved[5];
118} PF_TRACE_HEADER, *PPF_TRACE_HEADER;
119
120typedef struct _PFSN_TRACE_DUMP
121{
122 LIST_ENTRY CompletedTracesLink;
123 PF_TRACE_HEADER Trace;
124} PFSN_TRACE_DUMP, *PPFSN_TRACE_DUMP;
125
126typedef struct _PFSN_TRACE_HEADER
127{
128 ULONG Magic;
129 LIST_ENTRY ActiveTracesLink;
130 PF_SCENARIO_ID ScenarioId;
131 ULONG ScenarioType; // PF_SCENARIO_TYPE
132 ULONG EventEntryIdxs[8];
133 ULONG NumEventEntryIdxs;
134 PPFSN_LOG_ENTRIES CurrentTraceBuffer;
135 LIST_ENTRY TraceBuffersList;
136 ULONG NumTraceBuffers;
137 KSPIN_LOCK TraceBufferSpinLock;
138 KTIMER TraceTimer;
139 LARGE_INTEGER TraceTimerPeriod;
140 KDPC TraceTimerDpc;
141 KSPIN_LOCK TraceTimerSpinLock;
142 ULONG FaultsPerPeriod[10];
143 LONG LastNumFaults;
144 LONG CurPeriod;
145 LONG NumFaults;
146 LONG MaxFaults;
147 PEPROCESS Process;
148 EX_RUNDOWN_REF RefCount;
149 WORK_QUEUE_ITEM EndTraceWorkItem;
150 LONG EndTraceCalled;
151 PPFSN_TRACE_DUMP TraceDump;
152 NTSTATUS TraceDumpStatus;
153 LARGE_INTEGER LaunchTime;
154 PPF_SECTION_INFO SectionInfo;
155 ULONG SectionInfoCount;
156} PFSN_TRACE_HEADER, *PPFSN_TRACE_HEADER;
157
158typedef struct _PFSN_PREFETCHER_GLOBALS
159{
160 LIST_ENTRY ActiveTraces;
161 KSPIN_LOCK ActiveTracesLock;
162 PPFSN_TRACE_HEADER SystemWideTrace;
163 LIST_ENTRY CompletedTraces;
164 FAST_MUTEX CompletedTracesLock;
165 LONG NumCompletedTraces;
166 PKEVENT CompletedTracesEvent;
167 LONG ActivePrefetches;
168} PFSN_PREFETCHER_GLOBALS, *PPFSN_PREFETCHER_GLOBALS;
169
170typedef struct _ROS_SHARED_CACHE_MAP
171{
172 CSHORT NodeTypeCode;
173 CSHORT NodeByteSize;
174 ULONG OpenCount;
175 LARGE_INTEGER FileSize;
176 LIST_ENTRY BcbList;
177 LARGE_INTEGER SectionSize;
178 LARGE_INTEGER ValidDataLength;
179 PFILE_OBJECT FileObject;
180 ULONG DirtyPages;
181 LIST_ENTRY SharedCacheMapLinks;
182 ULONG Flags;
183 PVOID Section;
184 PKEVENT CreateEvent;
185 PCACHE_MANAGER_CALLBACKS Callbacks;
186 PVOID LazyWriteContext;
187 LIST_ENTRY PrivateList;
188 ULONG DirtyPageThreshold;
189 KSPIN_LOCK BcbSpinLock;
190 PRIVATE_CACHE_MAP PrivateCacheMap;
191
192 /* ROS specific */
193 LIST_ENTRY CacheMapVacbListHead;
194 BOOLEAN PinAccess;
195 KSPIN_LOCK CacheMapLock;
196 KGUARDED_MUTEX FlushCacheLock;
197#if DBG
198 BOOLEAN Trace; /* enable extra trace output for this cache map and it's VACBs */
199#endif
200} ROS_SHARED_CACHE_MAP, *PROS_SHARED_CACHE_MAP;
201
202#define READAHEAD_DISABLED 0x1
203#define WRITEBEHIND_DISABLED 0x2
204#define SHARED_CACHE_MAP_IN_CREATION 0x4
205#define SHARED_CACHE_MAP_IN_LAZYWRITE 0x8
206
207typedef struct _ROS_VACB
208{
209 /* Base address of the region where the view's data is mapped. */
210 PVOID BaseAddress;
211 /* Are the contents of the view newer than those on disk. */
212 BOOLEAN Dirty;
213 /* Page out in progress */
214 BOOLEAN PageOut;
215 ULONG MappedCount;
216 /* Entry in the list of VACBs for this shared cache map. */
217 LIST_ENTRY CacheMapVacbListEntry;
218 /* Entry in the list of VACBs which are dirty. */
219 LIST_ENTRY DirtyVacbListEntry;
220 /* Entry in the list of VACBs. */
221 LIST_ENTRY VacbLruListEntry;
222 /* Offset in the file which this view maps. */
223 LARGE_INTEGER FileOffset;
224 /* Number of references. */
225 volatile ULONG ReferenceCount;
226 /* Pointer to the shared cache map for the file which this view maps data for. */
227 PROS_SHARED_CACHE_MAP SharedCacheMap;
228 /* Pointer to the next VACB in a chain. */
229} ROS_VACB, *PROS_VACB;
230
231typedef struct _INTERNAL_BCB
232{
233 /* Lock */
234 ERESOURCE Lock;
235 PUBLIC_BCB PFCB;
236 PROS_VACB Vacb;
237 ULONG PinCount;
238 CSHORT RefCount; /* (At offset 0x34 on WinNT4) */
239 LIST_ENTRY BcbEntry;
240} INTERNAL_BCB, *PINTERNAL_BCB;
241
242typedef struct _LAZY_WRITER
243{
244 LIST_ENTRY WorkQueue;
245 KDPC ScanDpc;
246 KTIMER ScanTimer;
247 BOOLEAN ScanActive;
248 BOOLEAN OtherWork;
249 BOOLEAN PendingTeardown;
250} LAZY_WRITER, *PLAZY_WRITER;
251
252typedef struct _WORK_QUEUE_ENTRY
253{
254 LIST_ENTRY WorkQueueLinks;
255 union
256 {
257 struct
258 {
259 FILE_OBJECT *FileObject;
260 } Read;
261 struct
262 {
263 SHARED_CACHE_MAP *SharedCacheMap;
264 } Write;
265 struct
266 {
267 KEVENT *Event;
268 } Event;
269 struct
270 {
271 unsigned long Reason;
272 } Notification;
273 } Parameters;
274 unsigned char Function;
275} WORK_QUEUE_ENTRY, *PWORK_QUEUE_ENTRY;
276
277typedef enum _WORK_QUEUE_FUNCTIONS
278{
279 ReadAhead = 1,
280 WriteBehind = 2,
281 LazyScan = 3,
282 SetDone = 4,
283} WORK_QUEUE_FUNCTIONS, *PWORK_QUEUE_FUNCTIONS;
284
285extern LAZY_WRITER LazyWriter;
286
287#define NODE_TYPE_DEFERRED_WRITE 0x02FC
288#define NODE_TYPE_PRIVATE_MAP 0x02FE
289#define NODE_TYPE_SHARED_MAP 0x02FF
290
291CODE_SEG("INIT")
292VOID
293NTAPI
294CcPfInitializePrefetcher(
295 VOID
296);
297
298VOID
299NTAPI
300CcMdlReadComplete2(
301 IN PFILE_OBJECT FileObject,
302 IN PMDL MemoryDescriptorList
303);
304
305VOID
306NTAPI
307CcMdlWriteComplete2(
308 IN PFILE_OBJECT FileObject,
309 IN PLARGE_INTEGER FileOffset,
310 IN PMDL MdlChain
311);
312
313NTSTATUS
314CcRosFlushVacb(
315 _In_ PROS_VACB Vacb,
316 _Out_opt_ PIO_STATUS_BLOCK Iosb
317);
318
319NTSTATUS
320CcRosGetVacb(
321 PROS_SHARED_CACHE_MAP SharedCacheMap,
322 LONGLONG FileOffset,
323 PROS_VACB *Vacb
324);
325
326BOOLEAN
327CcRosEnsureVacbResident(
328 _In_ PROS_VACB Vacb,
329 _In_ BOOLEAN Wait,
330 _In_ BOOLEAN NoRead,
331 _In_ ULONG Offset,
332 _In_ ULONG Length
333);
334
335CODE_SEG("INIT")
336VOID
337NTAPI
338CcInitView(VOID);
339
340VOID
341NTAPI
342CcShutdownLazyWriter(VOID);
343
344CODE_SEG("INIT")
345BOOLEAN
346CcInitializeCacheManager(VOID);
347
348PROS_VACB
349CcRosLookupVacb(
350 PROS_SHARED_CACHE_MAP SharedCacheMap,
351 LONGLONG FileOffset
352);
353
354VOID
355NTAPI
356CcInitCacheZeroPage(VOID);
357
358VOID
359CcRosMarkDirtyVacb(
360 PROS_VACB Vacb);
361
362VOID
363CcRosUnmarkDirtyVacb(
364 PROS_VACB Vacb,
365 BOOLEAN LockViews);
366
367NTSTATUS
368CcRosFlushDirtyPages(
369 ULONG Target,
370 PULONG Count,
371 BOOLEAN Wait,
372 BOOLEAN CalledFromLazy
373);
374
375VOID
376CcRosDereferenceCache(PFILE_OBJECT FileObject);
377
378VOID
379CcRosReferenceCache(PFILE_OBJECT FileObject);
380
381NTSTATUS
382CcRosReleaseVacb(
383 PROS_SHARED_CACHE_MAP SharedCacheMap,
384 PROS_VACB Vacb,
385 BOOLEAN Dirty,
386 BOOLEAN Mapped
387);
388
389NTSTATUS
390CcRosRequestVacb(
391 PROS_SHARED_CACHE_MAP SharedCacheMap,
392 LONGLONG FileOffset,
393 PROS_VACB *Vacb
394);
395
396NTSTATUS
397CcRosInitializeFileCache(
398 PFILE_OBJECT FileObject,
399 PCC_FILE_SIZES FileSizes,
400 BOOLEAN PinAccess,
401 PCACHE_MANAGER_CALLBACKS CallBacks,
402 PVOID LazyWriterContext
403);
404
405NTSTATUS
406CcRosReleaseFileCache(
407 PFILE_OBJECT FileObject
408);
409
410VOID
411NTAPI
412CcShutdownSystem(VOID);
413
414VOID
415NTAPI
416CcWorkerThread(PVOID Parameter);
417
418VOID
419NTAPI
420CcScanDpc(
421 PKDPC Dpc,
422 PVOID DeferredContext,
423 PVOID SystemArgument1,
424 PVOID SystemArgument2);
425
426VOID
427CcScheduleLazyWriteScan(BOOLEAN NoDelay);
428
429VOID
430CcPostDeferredWrites(VOID);
431
432VOID
433CcPostWorkQueue(
434 IN PWORK_QUEUE_ENTRY WorkItem,
435 IN PLIST_ENTRY WorkQueue);
436
437VOID
438CcPerformReadAhead(
439 IN PFILE_OBJECT FileObject);
440
441NTSTATUS
442CcRosInternalFreeVacb(
443 IN PROS_VACB Vacb);
444
445FORCEINLINE
446BOOLEAN
447DoRangesIntersect(
448 _In_ LONGLONG Offset1,
449 _In_ LONGLONG Length1,
450 _In_ LONGLONG Offset2,
451 _In_ LONGLONG Length2)
452{
453 if (Offset1 + Length1 <= Offset2)
454 return FALSE;
455 if (Offset2 + Length2 <= Offset1)
456 return FALSE;
457 return TRUE;
458}
459
460FORCEINLINE
461BOOLEAN
462IsPointInRange(
463 _In_ LONGLONG Offset1,
464 _In_ LONGLONG Length1,
465 _In_ LONGLONG Point)
466{
467 return DoRangesIntersect(Offset1, Length1, Point, 1);
468}
469
470#define CcBugCheck(A, B, C) KeBugCheckEx(CACHE_MANAGER, BugCheckFileId | ((ULONG)(__LINE__)), A, B, C)
471
472#if DBG
473#define CcRosVacbIncRefCount(vacb) CcRosVacbIncRefCount_(vacb,__FILE__,__LINE__)
474#define CcRosVacbDecRefCount(vacb) CcRosVacbDecRefCount_(vacb,__FILE__,__LINE__)
475#define CcRosVacbGetRefCount(vacb) CcRosVacbGetRefCount_(vacb,__FILE__,__LINE__)
476
477ULONG
478CcRosVacbIncRefCount_(
479 PROS_VACB vacb,
480 PCSTR file,
481 INT line);
482
483ULONG
484CcRosVacbDecRefCount_(
485 PROS_VACB vacb,
486 PCSTR file,
487 INT line);
488
489ULONG
490CcRosVacbGetRefCount_(
491 PROS_VACB vacb,
492 PCSTR file,
493 INT line);
494
495#else
496#define CcRosVacbIncRefCount(vacb) InterlockedIncrement((PLONG)&(vacb)->ReferenceCount)
497FORCEINLINE
498ULONG
499CcRosVacbDecRefCount(
500 PROS_VACB vacb)
501{
502 ULONG Refs;
503
504 Refs = InterlockedDecrement((PLONG)&vacb->ReferenceCount);
505 if (Refs == 0)
506 {
507 CcRosInternalFreeVacb(vacb);
508 }
509 return Refs;
510}
511#define CcRosVacbGetRefCount(vacb) InterlockedCompareExchange((PLONG)&(vacb)->ReferenceCount, 0, 0)
512#endif
513
514BOOLEAN
515CcRosFreeOneUnusedVacb(
516 VOID);