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 //
42 extern ULONG CcRosTraceLevel;
43 extern LIST_ENTRY DirtyVacbListHead;
44 extern ULONG CcDirtyPageThreshold;
45 extern ULONG CcTotalDirtyPages;
46 extern LIST_ENTRY CcDeferredWrites;
47 extern KSPIN_LOCK CcDeferredWriteSpinLock;
48 extern ULONG CcNumberWorkerThreads;
49 extern LIST_ENTRY CcIdleWorkerThreadList;
50 extern LIST_ENTRY CcExpressWorkQueue;
51 extern LIST_ENTRY CcRegularWorkQueue;
52 extern LIST_ENTRY CcPostTickWorkQueue;
53 extern NPAGED_LOOKASIDE_LIST CcTwilightLookasideList;
54 extern LARGE_INTEGER CcIdleDelay;
55
56 //
57 // Counters
58 //
59 extern ULONG CcLazyWritePages;
60 extern ULONG CcLazyWriteIos;
61 extern ULONG CcMapDataWait;
62 extern ULONG CcMapDataNoWait;
63 extern ULONG CcPinReadWait;
64 extern ULONG CcPinReadNoWait;
65 extern ULONG CcPinMappedDataCount;
66 extern ULONG CcDataPages;
67 extern ULONG CcDataFlushes;
68
69 typedef struct _PF_SCENARIO_ID
70 {
71 WCHAR ScenName[30];
72 ULONG HashId;
73 } PF_SCENARIO_ID, *PPF_SCENARIO_ID;
74
75 typedef 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
86 typedef 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
94 typedef 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
102 typedef 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
120 typedef struct _PFSN_TRACE_DUMP
121 {
122 LIST_ENTRY CompletedTracesLink;
123 PF_TRACE_HEADER Trace;
124 } PFSN_TRACE_DUMP, *PPFSN_TRACE_DUMP;
125
126 typedef 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
158 typedef 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
170 typedef 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
207 typedef 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
231 typedef 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
242 typedef 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
252 typedef 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
277 typedef 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
285 extern 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
291 CODE_SEG("INIT")
292 VOID
293 NTAPI
294 CcPfInitializePrefetcher(
295 VOID
296 );
297
298 VOID
299 NTAPI
300 CcMdlReadComplete2(
301 IN PFILE_OBJECT FileObject,
302 IN PMDL MemoryDescriptorList
303 );
304
305 VOID
306 NTAPI
307 CcMdlWriteComplete2(
308 IN PFILE_OBJECT FileObject,
309 IN PLARGE_INTEGER FileOffset,
310 IN PMDL MdlChain
311 );
312
313 NTSTATUS
314 CcRosFlushVacb(
315 _In_ PROS_VACB Vacb,
316 _Out_opt_ PIO_STATUS_BLOCK Iosb
317 );
318
319 NTSTATUS
320 CcRosGetVacb(
321 PROS_SHARED_CACHE_MAP SharedCacheMap,
322 LONGLONG FileOffset,
323 PROS_VACB *Vacb
324 );
325
326 BOOLEAN
327 CcRosEnsureVacbResident(
328 _In_ PROS_VACB Vacb,
329 _In_ BOOLEAN Wait,
330 _In_ BOOLEAN NoRead,
331 _In_ ULONG Offset,
332 _In_ ULONG Length
333 );
334
335 CODE_SEG("INIT")
336 VOID
337 NTAPI
338 CcInitView(VOID);
339
340 VOID
341 NTAPI
342 CcShutdownLazyWriter(VOID);
343
344 CODE_SEG("INIT")
345 BOOLEAN
346 CcInitializeCacheManager(VOID);
347
348 PROS_VACB
349 CcRosLookupVacb(
350 PROS_SHARED_CACHE_MAP SharedCacheMap,
351 LONGLONG FileOffset
352 );
353
354 VOID
355 NTAPI
356 CcInitCacheZeroPage(VOID);
357
358 VOID
359 CcRosMarkDirtyVacb(
360 PROS_VACB Vacb);
361
362 VOID
363 CcRosUnmarkDirtyVacb(
364 PROS_VACB Vacb,
365 BOOLEAN LockViews);
366
367 NTSTATUS
368 CcRosFlushDirtyPages(
369 ULONG Target,
370 PULONG Count,
371 BOOLEAN Wait,
372 BOOLEAN CalledFromLazy
373 );
374
375 VOID
376 CcRosDereferenceCache(PFILE_OBJECT FileObject);
377
378 VOID
379 CcRosReferenceCache(PFILE_OBJECT FileObject);
380
381 NTSTATUS
382 CcRosReleaseVacb(
383 PROS_SHARED_CACHE_MAP SharedCacheMap,
384 PROS_VACB Vacb,
385 BOOLEAN Dirty,
386 BOOLEAN Mapped
387 );
388
389 NTSTATUS
390 CcRosRequestVacb(
391 PROS_SHARED_CACHE_MAP SharedCacheMap,
392 LONGLONG FileOffset,
393 PROS_VACB *Vacb
394 );
395
396 NTSTATUS
397 CcRosInitializeFileCache(
398 PFILE_OBJECT FileObject,
399 PCC_FILE_SIZES FileSizes,
400 BOOLEAN PinAccess,
401 PCACHE_MANAGER_CALLBACKS CallBacks,
402 PVOID LazyWriterContext
403 );
404
405 NTSTATUS
406 CcRosReleaseFileCache(
407 PFILE_OBJECT FileObject
408 );
409
410 VOID
411 NTAPI
412 CcShutdownSystem(VOID);
413
414 VOID
415 NTAPI
416 CcWorkerThread(PVOID Parameter);
417
418 VOID
419 NTAPI
420 CcScanDpc(
421 PKDPC Dpc,
422 PVOID DeferredContext,
423 PVOID SystemArgument1,
424 PVOID SystemArgument2);
425
426 VOID
427 CcScheduleLazyWriteScan(BOOLEAN NoDelay);
428
429 VOID
430 CcPostDeferredWrites(VOID);
431
432 VOID
433 CcPostWorkQueue(
434 IN PWORK_QUEUE_ENTRY WorkItem,
435 IN PLIST_ENTRY WorkQueue);
436
437 VOID
438 CcPerformReadAhead(
439 IN PFILE_OBJECT FileObject);
440
441 NTSTATUS
442 CcRosInternalFreeVacb(
443 IN PROS_VACB Vacb);
444
445 FORCEINLINE
446 BOOLEAN
DoRangesIntersect(_In_ LONGLONG Offset1,_In_ LONGLONG Length1,_In_ LONGLONG Offset2,_In_ LONGLONG Length2)447 DoRangesIntersect(
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
460 FORCEINLINE
461 BOOLEAN
IsPointInRange(_In_ LONGLONG Offset1,_In_ LONGLONG Length1,_In_ LONGLONG Point)462 IsPointInRange(
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
477 ULONG
478 CcRosVacbIncRefCount_(
479 PROS_VACB vacb,
480 PCSTR file,
481 INT line);
482
483 ULONG
484 CcRosVacbDecRefCount_(
485 PROS_VACB vacb,
486 PCSTR file,
487 INT line);
488
489 ULONG
490 CcRosVacbGetRefCount_(
491 PROS_VACB vacb,
492 PCSTR file,
493 INT line);
494
495 #else
496 #define CcRosVacbIncRefCount(vacb) InterlockedIncrement((PLONG)&(vacb)->ReferenceCount)
497 FORCEINLINE
498 ULONG
CcRosVacbDecRefCount(PROS_VACB vacb)499 CcRosVacbDecRefCount(
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
514 BOOLEAN
515 CcRosFreeOneUnusedVacb(
516 VOID);
517