ReactOS 0.4.15-dev-7712-gbbbcd8e
view.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cc/view.c
5 * PURPOSE: Cache manager
6 *
7 * PROGRAMMERS: David Welch (welch@mcmail.com)
8 * Pierre Schweitzer (pierre@reactos.org)
9 */
10
11/* NOTES **********************************************************************
12 *
13 * This is not the NT implementation of a file cache nor anything much like
14 * it.
15 *
16 * The general procedure for a filesystem to implement a read or write
17 * dispatch routine is as follows
18 *
19 * (1) If caching for the FCB hasn't been initiated then so do by calling
20 * CcInitializeFileCache.
21 *
22 * (2) For each 4k region which is being read or written obtain a cache page
23 * by calling CcRequestCachePage.
24 *
25 * (3) If either the page is being read or not completely written, and it is
26 * not up to date then read its data from the underlying medium. If the read
27 * fails then call CcReleaseCachePage with VALID as FALSE and return a error.
28 *
29 * (4) Copy the data into or out of the page as necessary.
30 *
31 * (5) Release the cache page
32 */
33/* INCLUDES ******************************************************************/
34
35#include <ntoskrnl.h>
36#define NDEBUG
37#include <debug.h>
38
39/* GLOBALS *******************************************************************/
40
43
47
48/* Internal vars (MS):
49 * - Threshold above which lazy writer will start action
50 * - Amount of dirty pages
51 * - List for deferred writes
52 * - Spinlock when dealing with the deferred list
53 * - List for "clean" shared cache maps
54 */
60
61#if DBG
62ULONG CcRosVacbIncRefCount_(PROS_VACB vacb, PCSTR file, INT line)
63{
64 ULONG Refs;
65
67 if (vacb->SharedCacheMap->Trace)
68 {
69 DbgPrint("(%s:%i) VACB %p ++RefCount=%lu, Dirty %u, PageOut %lu\n",
70 file, line, vacb, Refs, vacb->Dirty, vacb->PageOut);
71 }
72
73 return Refs;
74}
75ULONG CcRosVacbDecRefCount_(PROS_VACB vacb, PCSTR file, INT line)
76{
77 ULONG Refs;
78 BOOLEAN VacbDirty = vacb->Dirty;
79 BOOLEAN VacbTrace = vacb->SharedCacheMap->Trace;
80 BOOLEAN VacbPageOut = vacb->PageOut;
81
83 ASSERT(!(Refs == 0 && VacbDirty));
84 if (VacbTrace)
85 {
86 DbgPrint("(%s:%i) VACB %p --RefCount=%lu, Dirty %u, PageOut %lu\n",
87 file, line, vacb, Refs, VacbDirty, VacbPageOut);
88 }
89
90 if (Refs == 0)
91 {
93 }
94
95 return Refs;
96}
97ULONG CcRosVacbGetRefCount_(PROS_VACB vacb, PCSTR file, INT line)
98{
99 ULONG Refs;
100
101 Refs = InterlockedCompareExchange((PLONG)&vacb->ReferenceCount, 0, 0);
102 if (vacb->SharedCacheMap->Trace)
103 {
104 DbgPrint("(%s:%i) VACB %p ==RefCount=%lu, Dirty %u, PageOut %lu\n",
105 file, line, vacb, Refs, vacb->Dirty, vacb->PageOut);
106 }
107
108 return Refs;
109}
110#endif
111
112
113/* FUNCTIONS *****************************************************************/
114
115VOID
117 PROS_SHARED_CACHE_MAP SharedCacheMap,
118 BOOLEAN Trace )
119{
120#if DBG
121 KIRQL oldirql;
122 PLIST_ENTRY current_entry;
124
125 if (!SharedCacheMap)
126 return;
127
128 SharedCacheMap->Trace = Trace;
129
130 if (Trace)
131 {
132 DPRINT1("Enabling Tracing for CacheMap 0x%p:\n", SharedCacheMap);
133
136
137 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
138 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
139 {
140 current = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry);
141 current_entry = current_entry->Flink;
142
143 DPRINT1(" VACB 0x%p enabled, RefCount %lu, Dirty %u, PageOut %lu, BaseAddress %p, FileOffset %I64d\n",
144 current, current->ReferenceCount, current->Dirty, current->PageOut, current->BaseAddress, current->FileOffset.QuadPart);
145 }
146
149 }
150 else
151 {
152 DPRINT1("Disabling Tracing for CacheMap 0x%p:\n", SharedCacheMap);
153 }
154
155#else
156 UNREFERENCED_PARAMETER(SharedCacheMap);
158#endif
159}
160
163 _In_ PROS_VACB Vacb,
165{
167 BOOLEAN HaveLock = FALSE;
168 PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
169
171
172 /* Lock for flush, if we are not already the top-level */
174 {
175 Status = FsRtlAcquireFileForCcFlushEx(Vacb->SharedCacheMap->FileObject);
176 if (!NT_SUCCESS(Status))
177 goto quit;
178 HaveLock = TRUE;
179 }
180
181 Status = MmFlushSegment(SharedCacheMap->FileObject->SectionObjectPointer,
182 &Vacb->FileOffset,
184 Iosb);
185
186 if (HaveLock)
187 {
188 FsRtlReleaseFileForCcFlush(Vacb->SharedCacheMap->FileObject);
189 }
190
191quit:
192 if (!NT_SUCCESS(Status))
193 CcRosMarkDirtyVacb(Vacb);
194 else
195 {
196 /* Update VDL */
197 if (SharedCacheMap->ValidDataLength.QuadPart < (Vacb->FileOffset.QuadPart + VACB_MAPPING_GRANULARITY))
198 {
199 SharedCacheMap->ValidDataLength.QuadPart = Vacb->FileOffset.QuadPart + VACB_MAPPING_GRANULARITY;
200 }
201 }
202
203 return Status;
204}
205
206static
210 PROS_SHARED_CACHE_MAP SharedCacheMap,
212/*
213 * FUNCTION: Releases the shared cache map associated with a file object
214 */
215{
216 PLIST_ENTRY current_entry;
217
218 ASSERT(SharedCacheMap);
219 ASSERT(SharedCacheMap == FileObject->SectionObjectPointer->SharedCacheMap);
220 ASSERT(SharedCacheMap->OpenCount == 0);
221
222 /* Remove all VACBs from the global lists */
224 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
225 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
226 {
227 PROS_VACB Vacb = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry);
228
231
232 if (Vacb->Dirty)
233 {
235 /* Mark it as dirty again so we know that we have to flush before freeing it */
236 Vacb->Dirty = TRUE;
237 }
238
239 current_entry = current_entry->Flink;
240 }
241
242 /* Make sure there is no trace anymore of this map */
243 FileObject->SectionObjectPointer->SharedCacheMap = NULL;
244 RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks);
245
248
249 /* Now that we're out of the locks, free everything for real */
250 while (!IsListEmpty(&SharedCacheMap->CacheMapVacbListHead))
251 {
252 PROS_VACB Vacb = CONTAINING_RECORD(RemoveHeadList(&SharedCacheMap->CacheMapVacbListHead), ROS_VACB, CacheMapVacbListEntry);
253 ULONG RefCount;
254
256
257 /* Flush to disk, if needed */
258 if (Vacb->Dirty)
259 {
262
263 Status = MmFlushSegment(FileObject->SectionObjectPointer, &Vacb->FileOffset, VACB_MAPPING_GRANULARITY, &Iosb);
264 if (!NT_SUCCESS(Status))
265 {
266 /* Complain. There's not much we can do */
267 DPRINT1("Failed to flush VACB to disk while deleting the cache entry. Status: 0x%08x\n", Status);
268 }
269 Vacb->Dirty = FALSE;
270 }
271
272 RefCount = CcRosVacbDecRefCount(Vacb);
273#if DBG // CORE-14578
274 if (RefCount != 0)
275 {
276 DPRINT1("Leaking VACB %p attached to %p (%I64d)\n", Vacb, FileObject, Vacb->FileOffset.QuadPart);
277 DPRINT1("There are: %d references left\n", RefCount);
278 DPRINT1("Map: %d\n", Vacb->MappedCount);
279 DPRINT1("Dirty: %d\n", Vacb->Dirty);
280 if (FileObject->FileName.Length != 0)
281 {
282 DPRINT1("File was: %wZ\n", &FileObject->FileName);
283 }
284 else
285 {
286 DPRINT1("No name for the file\n");
287 }
288 }
289#else
290 (void)RefCount;
291#endif
292 }
293
294 /* Release the references we own */
295 if(SharedCacheMap->Section)
296 ObDereferenceObject(SharedCacheMap->Section);
297 ObDereferenceObject(SharedCacheMap->FileObject);
298
299 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap);
300
301 /* Acquire the lock again for our caller */
303
304 return STATUS_SUCCESS;
305}
306
312 BOOLEAN CalledFromLazy)
313{
314 PLIST_ENTRY current_entry;
317 BOOLEAN FlushAll = (Target == MAXULONG);
318
319 DPRINT("CcRosFlushDirtyPages(Target %lu)\n", Target);
320
321 (*Count) = 0;
322
325
326 current_entry = DirtyVacbListHead.Flink;
327 if (current_entry == &DirtyVacbListHead)
328 {
329 DPRINT("No Dirty pages\n");
330 }
331
332 while (((current_entry != &DirtyVacbListHead) && (Target > 0)) || FlushAll)
333 {
334 PROS_SHARED_CACHE_MAP SharedCacheMap;
337
338 if (current_entry == &DirtyVacbListHead)
339 {
340 ASSERT(FlushAll);
342 break;
343 current_entry = DirtyVacbListHead.Flink;
344 }
345
346 current = CONTAINING_RECORD(current_entry,
347 ROS_VACB,
348 DirtyVacbListEntry);
349 current_entry = current_entry->Flink;
350
352
353 SharedCacheMap = current->SharedCacheMap;
354
355 /* When performing lazy write, don't handle temporary files */
356 if (CalledFromLazy && BooleanFlagOn(SharedCacheMap->FileObject->Flags, FO_TEMPORARY_FILE))
357 {
359 continue;
360 }
361
362 /* Don't attempt to lazy write the files that asked not to */
363 if (CalledFromLazy && BooleanFlagOn(SharedCacheMap->Flags, WRITEBEHIND_DISABLED))
364 {
366 continue;
367 }
368
369 ASSERT(current->Dirty);
370
371 /* Do not lazy-write the same file concurrently. Fastfat ASSERTS on that */
372 if (SharedCacheMap->Flags & SHARED_CACHE_MAP_IN_LAZYWRITE)
373 {
375 continue;
376 }
377
378 SharedCacheMap->Flags |= SHARED_CACHE_MAP_IN_LAZYWRITE;
379
380 /* Keep a ref on the shared cache map */
381 SharedCacheMap->OpenCount++;
382
384
385 Locked = SharedCacheMap->Callbacks->AcquireForLazyWrite(SharedCacheMap->LazyWriteContext, Wait);
386 if (!Locked)
387 {
388 DPRINT("Not locked!");
389 ASSERT(!Wait);
392 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;
393
394 if (--SharedCacheMap->OpenCount == 0)
395 CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);
396
397 continue;
398 }
399
402
403 SharedCacheMap->Callbacks->ReleaseFromLazyWrite(SharedCacheMap->LazyWriteContext);
404
405 /* We release the VACB before acquiring the lock again, because
406 * CcRosVacbDecRefCount might free the VACB, as CcRosFlushVacb dropped a
407 * Refcount. Freeing must be done outside of the lock.
408 * The refcount is decremented atomically. So this is OK. */
411
412 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;
413
414 if (--SharedCacheMap->OpenCount == 0)
415 CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);
416
419 {
420 DPRINT1("CC: Failed to flush VACB.\n");
421 }
422 else
423 {
424 ULONG PagesFreed;
425
426 /* How many pages did we free? */
427 PagesFreed = Iosb.Information / PAGE_SIZE;
428 (*Count) += PagesFreed;
429
430 if (!Wait)
431 {
432 /* Make sure we don't overflow target! */
433 if (Target < PagesFreed)
434 {
435 /* If we would have, jump to zero directly */
436 Target = 0;
437 }
438 else
439 {
440 Target -= PagesFreed;
441 }
442 }
443 }
444
445 current_entry = DirtyVacbListHead.Flink;
446 }
447
450
451 DPRINT("CcRosFlushDirtyPages() finished\n");
452 return STATUS_SUCCESS;
453}
454
455VOID
458 _Out_ PULONG NrFreed)
459/*
460 * FUNCTION: Try to free some memory from the file cache.
461 * ARGUMENTS:
462 * Target - The number of pages to be freed.
463 * NrFreed - Points to a variable where the number of pages
464 * actually freed is returned.
465 */
466{
467 PLIST_ENTRY current_entry;
469 ULONG PagesFreed;
470 KIRQL oldIrql;
471 LIST_ENTRY FreeList;
473 ULONG i;
474 BOOLEAN FlushedPages = FALSE;
475
476 DPRINT("CcRosTrimCache(Target %lu)\n", Target);
477
478 InitializeListHead(&FreeList);
479
480 *NrFreed = 0;
481
482retry:
484
485 current_entry = VacbLruListHead.Flink;
486 while (current_entry != &VacbLruListHead)
487 {
488 ULONG Refs;
489
490 current = CONTAINING_RECORD(current_entry,
491 ROS_VACB,
492 VacbLruListEntry);
493 current_entry = current_entry->Flink;
494
495 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
496
497 /* Reference the VACB */
499
500 /* Check if it's mapped and not dirty */
501 if (InterlockedCompareExchange((PLONG)&current->MappedCount, 0, 0) > 0 && !current->Dirty)
502 {
503 /* Page out the VACB */
504 for (i = 0; i < VACB_MAPPING_GRANULARITY / PAGE_SIZE; i++)
505 {
507
509 }
510 }
511
512 /* Dereference the VACB */
514
515 /* Check if we can free this entry now */
516 if (Refs < 2)
517 {
518 ASSERT(!current->Dirty);
519 ASSERT(!current->MappedCount);
520 ASSERT(Refs == 1);
521
522 RemoveEntryList(&current->CacheMapVacbListEntry);
523 RemoveEntryList(&current->VacbLruListEntry);
524 InitializeListHead(&current->VacbLruListEntry);
525 InsertHeadList(&FreeList, &current->CacheMapVacbListEntry);
526
527 /* Calculate how many pages we freed for Mm */
529 Target -= PagesFreed;
530 (*NrFreed) += PagesFreed;
531 }
532
533 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
534 }
535
537
538 /* Try flushing pages if we haven't met our target */
539 if ((Target > 0) && !FlushedPages)
540 {
541 /* Flush dirty pages to disk */
542 CcRosFlushDirtyPages(Target, &PagesFreed, FALSE, FALSE);
543 FlushedPages = TRUE;
544
545 /* We can only swap as many pages as we flushed */
546 if (PagesFreed < Target) Target = PagesFreed;
547
548 /* Check if we flushed anything */
549 if (PagesFreed != 0)
550 {
551 /* Try again after flushing dirty pages */
552 DPRINT("Flushed %lu dirty cache pages to disk\n", PagesFreed);
553 goto retry;
554 }
555 }
556
557 while (!IsListEmpty(&FreeList))
558 {
559 ULONG Refs;
560
561 current_entry = RemoveHeadList(&FreeList);
562 current = CONTAINING_RECORD(current_entry,
563 ROS_VACB,
564 CacheMapVacbListEntry);
565 InitializeListHead(&current->CacheMapVacbListEntry);
567 ASSERT(Refs == 0);
568 }
569
570 DPRINT("Evicted %lu cache pages\n", (*NrFreed));
571}
572
575 PROS_SHARED_CACHE_MAP SharedCacheMap,
576 PROS_VACB Vacb,
577 BOOLEAN Dirty,
578 BOOLEAN Mapped)
579{
580 ULONG Refs;
581 ASSERT(SharedCacheMap);
582
583 DPRINT("CcRosReleaseVacb(SharedCacheMap 0x%p, Vacb 0x%p)\n", SharedCacheMap, Vacb);
584
585 if (Dirty && !Vacb->Dirty)
586 {
587 CcRosMarkDirtyVacb(Vacb);
588 }
589
590 if (Mapped)
591 {
592 if (InterlockedIncrement((PLONG)&Vacb->MappedCount) == 1)
593 {
595 }
596 }
597
598 Refs = CcRosVacbDecRefCount(Vacb);
599 ASSERT(Refs > 0);
600
601 return STATUS_SUCCESS;
602}
603
604/* Returns with VACB Lock Held! */
607 PROS_SHARED_CACHE_MAP SharedCacheMap,
609{
610 PLIST_ENTRY current_entry;
612 KIRQL oldIrql;
613
614 ASSERT(SharedCacheMap);
615
616 DPRINT("CcRosLookupVacb(SharedCacheMap 0x%p, FileOffset %I64u)\n",
617 SharedCacheMap, FileOffset);
618
621
622 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
623 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
624 {
625 current = CONTAINING_RECORD(current_entry,
626 ROS_VACB,
627 CacheMapVacbListEntry);
628 if (IsPointInRange(current->FileOffset.QuadPart,
630 FileOffset))
631 {
635 return current;
636 }
637 if (current->FileOffset.QuadPart > FileOffset)
638 break;
639 current_entry = current_entry->Flink;
640 }
641
644
645 return NULL;
646}
647
648VOID
650 PROS_VACB Vacb)
651{
652 KIRQL oldIrql;
653 PROS_SHARED_CACHE_MAP SharedCacheMap;
654
655 SharedCacheMap = Vacb->SharedCacheMap;
656
659
660 ASSERT(!Vacb->Dirty);
661
663 /* FIXME: There is no reason to account for the whole VACB. */
667
668 /* Move to the tail of the LRU list */
671
672 Vacb->Dirty = TRUE;
673
675
676 /* Schedule a lazy writer run to now that we have dirty VACB */
678 {
680 }
682}
683
684VOID
686 PROS_VACB Vacb,
687 BOOLEAN LockViews)
688{
689 KIRQL oldIrql;
690 PROS_SHARED_CACHE_MAP SharedCacheMap;
691
692 SharedCacheMap = Vacb->SharedCacheMap;
693
694 if (LockViews)
695 {
698 }
699
700 ASSERT(Vacb->Dirty);
701
702 Vacb->Dirty = FALSE;
703
706
709
711
712 if (LockViews)
713 {
716 }
717}
718
721 VOID)
722{
723 KIRQL oldIrql;
724 PLIST_ENTRY current_entry;
725 PROS_VACB to_free = NULL;
726
728
729 /* Browse all the available VACB */
730 current_entry = VacbLruListHead.Flink;
731 while ((current_entry != &VacbLruListHead) && (to_free == NULL))
732 {
733 ULONG Refs;
735
736 current = CONTAINING_RECORD(current_entry,
737 ROS_VACB,
738 VacbLruListEntry);
739
740 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
741
742 /* Only deal with unused VACB, we will free them */
744 if (Refs < 2)
745 {
746 ASSERT(!current->Dirty);
747 ASSERT(!current->MappedCount);
748 ASSERT(Refs == 1);
749
750 /* Reset it, this is the one we want to free */
751 RemoveEntryList(&current->CacheMapVacbListEntry);
752 InitializeListHead(&current->CacheMapVacbListEntry);
753 RemoveEntryList(&current->VacbLruListEntry);
754 InitializeListHead(&current->VacbLruListEntry);
755
756 to_free = current;
757 }
758
759 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
760
761 current_entry = current_entry->Flink;
762 }
763
765
766 /* And now, free the VACB that we found, if any. */
767 if (to_free == NULL)
768 {
769 return FALSE;
770 }
771
772 /* This must be its last ref */
773 NT_VERIFY(CcRosVacbDecRefCount(to_free) == 0);
774
775 return TRUE;
776}
777
778static
781 PROS_SHARED_CACHE_MAP SharedCacheMap,
783 PROS_VACB *Vacb)
784{
786 PROS_VACB previous;
787 PLIST_ENTRY current_entry;
789 KIRQL oldIrql;
790 ULONG Refs;
792
793 ASSERT(SharedCacheMap);
794
795 DPRINT("CcRosCreateVacb()\n");
796
797 current = ExAllocateFromNPagedLookasideList(&VacbLookasideList);
798 current->BaseAddress = NULL;
799 current->Dirty = FALSE;
800 current->PageOut = FALSE;
801 current->FileOffset.QuadPart = ROUND_DOWN(FileOffset, VACB_MAPPING_GRANULARITY);
802 current->SharedCacheMap = SharedCacheMap;
803 current->MappedCount = 0;
804 current->ReferenceCount = 0;
805 InitializeListHead(&current->CacheMapVacbListEntry);
806 InitializeListHead(&current->DirtyVacbListEntry);
807 InitializeListHead(&current->VacbLruListEntry);
808
810
811 while (TRUE)
812 {
813 /* Map VACB in system space */
814 Status = MmMapViewInSystemSpaceEx(SharedCacheMap->Section, &current->BaseAddress, &ViewSize, &current->FileOffset, 0);
815 if (NT_SUCCESS(Status))
816 {
817 break;
818 }
819
820 /*
821 * If no space left, try to prune one unused VACB to recover space to map our VACB.
822 * If it succeeds, retry to map, otherwise just fail.
823 */
825 {
826 ExFreeToNPagedLookasideList(&VacbLookasideList, current);
827 return Status;
828 }
829 }
830
831#if DBG
832 if (SharedCacheMap->Trace)
833 {
834 DPRINT1("CacheMap 0x%p: new VACB: 0x%p, file offset %I64d, BaseAddress %p\n",
835 SharedCacheMap, current, current->FileOffset.QuadPart, current->BaseAddress);
836 }
837#endif
838
840
841 *Vacb = current;
842 /* There is window between the call to CcRosLookupVacb
843 * and CcRosCreateVacb. We must check if a VACB for the
844 * file offset exist. If there is a VACB, we release
845 * our newly created VACB and return the existing one.
846 */
848 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
849 previous = NULL;
850 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
851 {
852 current = CONTAINING_RECORD(current_entry,
853 ROS_VACB,
854 CacheMapVacbListEntry);
855 if (IsPointInRange(current->FileOffset.QuadPart,
857 FileOffset))
858 {
861#if DBG
862 if (SharedCacheMap->Trace)
863 {
864 DPRINT1("CacheMap 0x%p: deleting newly created VACB 0x%p ( found existing one 0x%p )\n",
865 SharedCacheMap,
866 (*Vacb),
867 current);
868 }
869#endif
871
872 Refs = CcRosVacbDecRefCount(*Vacb);
873 ASSERT(Refs == 0);
874
875 *Vacb = current;
876 return STATUS_SUCCESS;
877 }
878 if (current->FileOffset.QuadPart < FileOffset)
879 {
880 ASSERT(previous == NULL ||
881 previous->FileOffset.QuadPart < current->FileOffset.QuadPart);
882 previous = current;
883 }
884 if (current->FileOffset.QuadPart > FileOffset)
885 break;
886 current_entry = current_entry->Flink;
887 }
888 /* There was no existing VACB. */
889 current = *Vacb;
890 if (previous)
891 {
892 InsertHeadList(&previous->CacheMapVacbListEntry, &current->CacheMapVacbListEntry);
893 }
894 else
895 {
896 InsertHeadList(&SharedCacheMap->CacheMapVacbListHead, &current->CacheMapVacbListEntry);
897 }
899 InsertTailList(&VacbLruListHead, &current->VacbLruListEntry);
900
901 /* Reference it to allow release */
903
905
906 return Status;
907}
908
911 _In_ PROS_VACB Vacb,
913 _In_ BOOLEAN NoRead,
916)
917{
919
921
922#if 0
923 if ((Vacb->FileOffset.QuadPart + Offset) > Vacb->SharedCacheMap->SectionSize.QuadPart)
924 {
925 DPRINT1("Vacb read beyond the file size!\n");
926 return FALSE;
927 }
928#endif
929
930 BaseAddress = (PVOID)((ULONG_PTR)Vacb->BaseAddress + Offset);
931
932 /* Check if the pages are resident */
934 {
935 if (!Wait)
936 {
937 return FALSE;
938 }
939
940 if (!NoRead)
941 {
942 PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
943 NTSTATUS Status = MmMakeDataSectionResident(SharedCacheMap->FileObject->SectionObjectPointer,
944 Vacb->FileOffset.QuadPart + Offset,
945 Length,
946 &SharedCacheMap->ValidDataLength);
947 if (!NT_SUCCESS(Status))
949 }
950 }
951
952 return TRUE;
953}
954
955
958 PROS_SHARED_CACHE_MAP SharedCacheMap,
960 PROS_VACB *Vacb)
961{
964 ULONG Refs;
966
967 ASSERT(SharedCacheMap);
968
969 DPRINT("CcRosGetVacb()\n");
970
971 /*
972 * Look for a VACB already mapping the same data.
973 */
974 current = CcRosLookupVacb(SharedCacheMap, FileOffset);
975 if (current == NULL)
976 {
977 /*
978 * Otherwise create a new VACB.
979 */
980 Status = CcRosCreateVacb(SharedCacheMap, FileOffset, &current);
981 if (!NT_SUCCESS(Status))
982 {
983 return Status;
984 }
985 }
986
988
990
991 /* Move to the tail of the LRU list */
992 RemoveEntryList(&current->VacbLruListEntry);
993 InsertTailList(&VacbLruListHead, &current->VacbLruListEntry);
994
996
997 /*
998 * Return the VACB to the caller.
999 */
1000 *Vacb = current;
1001
1002 ASSERT(Refs > 1);
1003
1004 return STATUS_SUCCESS;
1005}
1006
1009 PROS_SHARED_CACHE_MAP SharedCacheMap,
1011 PROS_VACB *Vacb)
1012/*
1013 * FUNCTION: Request a page mapping for a shared cache map
1014 */
1015{
1016
1017 ASSERT(SharedCacheMap);
1018
1020 {
1021 DPRINT1("Bad fileoffset %I64x should be multiple of %x",
1023 KeBugCheck(CACHE_MANAGER);
1024 }
1025
1026 return CcRosGetVacb(SharedCacheMap,
1027 FileOffset,
1028 Vacb);
1029}
1030
1033 PROS_VACB Vacb)
1034/*
1035 * FUNCTION: Releases a VACB associated with a shared cache map
1036 */
1037{
1039
1040 DPRINT("Freeing VACB 0x%p\n", Vacb);
1041#if DBG
1042 if (Vacb->SharedCacheMap->Trace)
1043 {
1044 DPRINT1("CacheMap 0x%p: deleting VACB: 0x%p\n", Vacb->SharedCacheMap, Vacb);
1045 }
1046#endif
1047
1048 if (Vacb->ReferenceCount != 0)
1049 {
1050 DPRINT1("Invalid free: %ld\n", Vacb->ReferenceCount);
1051 if (Vacb->SharedCacheMap->FileObject && Vacb->SharedCacheMap->FileObject->FileName.Length)
1052 {
1053 DPRINT1("For file: %wZ\n", &Vacb->SharedCacheMap->FileObject->FileName);
1054 }
1055 }
1056
1057 ASSERT(Vacb->ReferenceCount == 0);
1061
1062 /* Delete the mapping */
1064 if (!NT_SUCCESS(Status))
1065 {
1066 DPRINT1("Failed to unmap VACB from System address space! Status 0x%08X\n", Status);
1067 ASSERT(FALSE);
1068 /* Proceed with the deĺetion anyway */
1069 }
1070
1071 RtlFillMemory(Vacb, sizeof(*Vacb), 0xfd);
1072 ExFreeToNPagedLookasideList(&VacbLookasideList, Vacb);
1073 return STATUS_SUCCESS;
1074}
1075
1076/*
1077 * @implemented
1078 */
1079VOID
1080NTAPI
1082 IN PSECTION_OBJECT_POINTERS SectionObjectPointers,
1084 IN ULONG Length,
1086{
1087 PROS_SHARED_CACHE_MAP SharedCacheMap;
1088 LONGLONG FlushStart, FlushEnd;
1090
1091 CCTRACE(CC_API_DEBUG, "SectionObjectPointers=%p FileOffset=0x%I64X Length=%lu\n",
1092 SectionObjectPointers, FileOffset ? FileOffset->QuadPart : 0LL, Length);
1093
1094 if (!SectionObjectPointers)
1095 {
1097 goto quit;
1098 }
1099
1100 if (!SectionObjectPointers->SharedCacheMap)
1101 {
1102 /* Forward this to Mm */
1103 MmFlushSegment(SectionObjectPointers, FileOffset, Length, IoStatus);
1104 return;
1105 }
1106
1107 SharedCacheMap = SectionObjectPointers->SharedCacheMap;
1108 ASSERT(SharedCacheMap);
1109 if (FileOffset)
1110 {
1111 FlushStart = FileOffset->QuadPart;
1112 Status = RtlLongLongAdd(FlushStart, Length, &FlushEnd);
1113 if (!NT_SUCCESS(Status))
1114 goto quit;
1115 }
1116 else
1117 {
1118 FlushStart = 0;
1119 FlushEnd = SharedCacheMap->FileSize.QuadPart;
1120 }
1121
1123 if (IoStatus)
1124 {
1125 IoStatus->Information = 0;
1126 }
1127
1128 /*
1129 * We flush the VACBs that we find here.
1130 * If there is no (dirty) VACB, it doesn't mean that there is no data to flush, so we call Mm to be sure.
1131 * This is suboptimal, but this is due to the lack of granularity of how we track dirty cache data
1132 */
1133 while (FlushStart < FlushEnd)
1134 {
1135 BOOLEAN DirtyVacb = FALSE;
1136 PROS_VACB vacb = CcRosLookupVacb(SharedCacheMap, FlushStart);
1137
1138 if (vacb != NULL)
1139 {
1140 if (vacb->Dirty)
1141 {
1142 IO_STATUS_BLOCK VacbIosb = { 0 };
1143 Status = CcRosFlushVacb(vacb, &VacbIosb);
1144 if (!NT_SUCCESS(Status))
1145 {
1146 goto quit;
1147 }
1148 DirtyVacb = TRUE;
1149
1150 if (IoStatus)
1151 IoStatus->Information += VacbIosb.Information;
1152 }
1153
1154 CcRosReleaseVacb(SharedCacheMap, vacb, FALSE, FALSE);
1155 }
1156
1157 if (!DirtyVacb)
1158 {
1159 IO_STATUS_BLOCK MmIosb;
1160 LARGE_INTEGER MmOffset;
1161
1162 MmOffset.QuadPart = FlushStart;
1163
1164 if (FlushEnd - (FlushEnd % VACB_MAPPING_GRANULARITY) <= FlushStart)
1165 {
1166 /* The whole range fits within a VACB chunk. */
1167 Status = MmFlushSegment(SectionObjectPointers, &MmOffset, FlushEnd - FlushStart, &MmIosb);
1168 }
1169 else
1170 {
1171 ULONG MmLength = VACB_MAPPING_GRANULARITY - (FlushStart % VACB_MAPPING_GRANULARITY);
1172 Status = MmFlushSegment(SectionObjectPointers, &MmOffset, MmLength, &MmIosb);
1173 }
1174
1175 if (!NT_SUCCESS(Status))
1176 goto quit;
1177
1178 if (IoStatus)
1179 IoStatus->Information += MmIosb.Information;
1180
1181 /* Update VDL */
1182 if (SharedCacheMap->ValidDataLength.QuadPart < FlushEnd)
1183 SharedCacheMap->ValidDataLength.QuadPart = FlushEnd;
1184 }
1185
1186 if (!NT_SUCCESS(RtlLongLongAdd(FlushStart, VACB_MAPPING_GRANULARITY, &FlushStart)))
1187 {
1188 /* We're at the end of file ! */
1189 break;
1190 }
1191
1192 /* Round down to next VACB start now */
1193 FlushStart -= FlushStart % VACB_MAPPING_GRANULARITY;
1194 }
1195
1196quit:
1197 if (IoStatus)
1198 {
1199 IoStatus->Status = Status;
1200 }
1201}
1202
1206/*
1207 * FUNCTION: Called by the file system when a handle to a file object
1208 * has been closed.
1209 */
1210{
1211 KIRQL OldIrql;
1212 PPRIVATE_CACHE_MAP PrivateMap;
1213 PROS_SHARED_CACHE_MAP SharedCacheMap;
1214
1216
1217 if (FileObject->SectionObjectPointer->SharedCacheMap != NULL)
1218 {
1219 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
1220
1221 /* Closing the handle, so kill the private cache map
1222 * Before you event try to remove it from FO, always
1223 * lock the master lock, to be sure not to race
1224 * with a potential read ahead ongoing!
1225 */
1226 PrivateMap = FileObject->PrivateCacheMap;
1227 FileObject->PrivateCacheMap = NULL;
1228
1229 if (PrivateMap != NULL)
1230 {
1231 /* Remove it from the file */
1232 KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock);
1233 RemoveEntryList(&PrivateMap->PrivateLinks);
1235
1236 /* And free it. */
1237 if (PrivateMap != &SharedCacheMap->PrivateCacheMap)
1238 {
1240 }
1241 else
1242 {
1243 PrivateMap->NodeTypeCode = 0;
1244 }
1245
1246 ASSERT(SharedCacheMap->OpenCount > 0);
1247
1248 SharedCacheMap->OpenCount--;
1249 if (SharedCacheMap->OpenCount == 0)
1250 {
1251 CcRosDeleteFileCache(FileObject, SharedCacheMap, &OldIrql);
1252 }
1253 }
1254 }
1256 return STATUS_SUCCESS;
1257}
1258
1263 BOOLEAN PinAccess,
1264 PCACHE_MANAGER_CALLBACKS CallBacks,
1265 PVOID LazyWriterContext)
1266/*
1267 * FUNCTION: Initializes a shared cache map for a file object
1268 */
1269{
1270 KIRQL OldIrql;
1272 PROS_SHARED_CACHE_MAP SharedCacheMap;
1273
1274 DPRINT("CcRosInitializeFileCache(FileObject 0x%p)\n", FileObject);
1275
1277
1278 Allocated = FALSE;
1279 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
1280 if (SharedCacheMap == NULL)
1281 {
1282 Allocated = TRUE;
1283 SharedCacheMap = ExAllocateFromNPagedLookasideList(&SharedCacheMapLookasideList);
1284 if (SharedCacheMap == NULL)
1285 {
1287 }
1288 RtlZeroMemory(SharedCacheMap, sizeof(*SharedCacheMap));
1289 SharedCacheMap->NodeTypeCode = NODE_TYPE_SHARED_MAP;
1290 SharedCacheMap->NodeByteSize = sizeof(*SharedCacheMap);
1291 SharedCacheMap->FileObject = FileObject;
1292 SharedCacheMap->Callbacks = CallBacks;
1293 SharedCacheMap->LazyWriteContext = LazyWriterContext;
1294 SharedCacheMap->SectionSize = FileSizes->AllocationSize;
1295 SharedCacheMap->FileSize = FileSizes->FileSize;
1296 SharedCacheMap->ValidDataLength = FileSizes->ValidDataLength;
1297 SharedCacheMap->PinAccess = PinAccess;
1298 SharedCacheMap->DirtyPageThreshold = 0;
1299 SharedCacheMap->DirtyPages = 0;
1300 InitializeListHead(&SharedCacheMap->PrivateList);
1301 KeInitializeSpinLock(&SharedCacheMap->CacheMapLock);
1302 InitializeListHead(&SharedCacheMap->CacheMapVacbListHead);
1303 InitializeListHead(&SharedCacheMap->BcbList);
1304
1305 SharedCacheMap->Flags = SHARED_CACHE_MAP_IN_CREATION;
1306
1309 NULL,
1310 KernelMode);
1311
1312 FileObject->SectionObjectPointer->SharedCacheMap = SharedCacheMap;
1313
1314 //CcRosTraceCacheMap(SharedCacheMap, TRUE);
1315 }
1316 else if (SharedCacheMap->Flags & SHARED_CACHE_MAP_IN_CREATION)
1317 {
1318 /* The shared cache map is being created somewhere else. Wait for that to happen */
1319 KEVENT Waiter;
1320 PKEVENT PreviousWaiter = SharedCacheMap->CreateEvent;
1321
1323 SharedCacheMap->CreateEvent = &Waiter;
1324
1326
1328
1329 if (PreviousWaiter)
1330 KeSetEvent(PreviousWaiter, IO_NO_INCREMENT, FALSE);
1331
1333 }
1334
1335 if (FileObject->PrivateCacheMap == NULL)
1336 {
1337 PPRIVATE_CACHE_MAP PrivateMap;
1338
1339 /* Allocate the private cache map for this handle */
1340 if (SharedCacheMap->PrivateCacheMap.NodeTypeCode != 0)
1341 {
1343 }
1344 else
1345 {
1346 PrivateMap = &SharedCacheMap->PrivateCacheMap;
1347 }
1348
1349 if (PrivateMap == NULL)
1350 {
1351 /* If we also allocated the shared cache map for this file, kill it */
1352 if (Allocated)
1353 {
1354 RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks);
1355
1356 FileObject->SectionObjectPointer->SharedCacheMap = NULL;
1358 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap);
1359 }
1360
1363 }
1364
1365 /* Initialize it */
1366 RtlZeroMemory(PrivateMap, sizeof(PRIVATE_CACHE_MAP));
1367 PrivateMap->NodeTypeCode = NODE_TYPE_PRIVATE_MAP;
1368 PrivateMap->ReadAheadMask = PAGE_SIZE - 1;
1369 PrivateMap->FileObject = FileObject;
1371
1372 /* Link it to the file */
1373 KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock);
1374 InsertTailList(&SharedCacheMap->PrivateList, &PrivateMap->PrivateLinks);
1376
1377 FileObject->PrivateCacheMap = PrivateMap;
1378 SharedCacheMap->OpenCount++;
1379 }
1380
1382
1383 /* Create the section */
1384 if (Allocated)
1385 {
1387
1388 ASSERT(SharedCacheMap->Section == NULL);
1389
1391 &SharedCacheMap->Section,
1393 NULL,
1394 &SharedCacheMap->SectionSize,
1397 NULL,
1398 FileObject);
1399
1401
1402 if (!NT_SUCCESS(Status))
1403 {
1405 return Status;
1406 }
1407
1409
1411 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_CREATION;
1412
1413 if (SharedCacheMap->CreateEvent)
1414 {
1415 KeSetEvent(SharedCacheMap->CreateEvent, IO_NO_INCREMENT, FALSE);
1416 SharedCacheMap->CreateEvent = NULL;
1417 }
1418
1420 }
1421
1422 return STATUS_SUCCESS;
1423}
1424
1425/*
1426 * @implemented
1427 */
1429NTAPI
1431 IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
1432{
1433 PROS_SHARED_CACHE_MAP SharedCacheMap;
1434
1435 CCTRACE(CC_API_DEBUG, "SectionObjectPointers=%p\n", SectionObjectPointers);
1436
1437 if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
1438 {
1439 SharedCacheMap = SectionObjectPointers->SharedCacheMap;
1440 ASSERT(SharedCacheMap);
1441 return SharedCacheMap->FileObject;
1442 }
1443 return NULL;
1444}
1445
1446CODE_SEG("INIT")
1447VOID
1448NTAPI
1450 VOID)
1451{
1452 DPRINT("CcInitView()\n");
1453
1460 NULL,
1461 NULL,
1462 0,
1463 sizeof(INTERNAL_BCB),
1464 TAG_BCB,
1465 20);
1467 NULL,
1468 NULL,
1469 0,
1470 sizeof(ROS_SHARED_CACHE_MAP),
1472 20);
1474 NULL,
1475 NULL,
1476 0,
1477 sizeof(ROS_VACB),
1478 TAG_VACB,
1479 20);
1480
1482}
1483
1484#if DBG && defined(KDBG)
1485
1486#include <kdbg/kdb.h>
1487
1488BOOLEAN
1489ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[])
1490{
1491 PLIST_ENTRY ListEntry;
1492 UNICODE_STRING NoName = RTL_CONSTANT_STRING(L"No name for File");
1493
1494 KdbpPrint(" Usage Summary (in kb)\n");
1495 KdbpPrint("Shared\t\tMapped\tDirty\tName\n");
1496 /* No need to lock the spin lock here, we're in DBG */
1497 for (ListEntry = CcCleanSharedCacheMapList.Flink;
1498 ListEntry != &CcCleanSharedCacheMapList;
1499 ListEntry = ListEntry->Flink)
1500 {
1501 PLIST_ENTRY Vacbs;
1502 ULONG Mapped = 0, Dirty = 0;
1503 PROS_SHARED_CACHE_MAP SharedCacheMap;
1505 PWSTR Extra = L"";
1506
1507 SharedCacheMap = CONTAINING_RECORD(ListEntry, ROS_SHARED_CACHE_MAP, SharedCacheMapLinks);
1508
1509 /* Dirty size */
1510 Dirty = (SharedCacheMap->DirtyPages * PAGE_SIZE) / 1024;
1511
1512 /* First, count for all the associated VACB */
1513 for (Vacbs = SharedCacheMap->CacheMapVacbListHead.Flink;
1514 Vacbs != &SharedCacheMap->CacheMapVacbListHead;
1515 Vacbs = Vacbs->Flink)
1516 {
1517 Mapped += VACB_MAPPING_GRANULARITY / 1024;
1518 }
1519
1520 /* Setup name */
1521 if (SharedCacheMap->FileObject != NULL &&
1522 SharedCacheMap->FileObject->FileName.Length != 0)
1523 {
1524 FileName = &SharedCacheMap->FileObject->FileName;
1525 }
1526 else if (SharedCacheMap->FileObject != NULL &&
1527 SharedCacheMap->FileObject->FsContext != NULL &&
1528 ((PFSRTL_COMMON_FCB_HEADER)(SharedCacheMap->FileObject->FsContext))->NodeTypeCode == 0x0502 &&
1529 ((PFSRTL_COMMON_FCB_HEADER)(SharedCacheMap->FileObject->FsContext))->NodeByteSize == 0x1F8 &&
1530 ((PUNICODE_STRING)(((PUCHAR)SharedCacheMap->FileObject->FsContext) + 0x100))->Length != 0)
1531 {
1532 FileName = (PUNICODE_STRING)(((PUCHAR)SharedCacheMap->FileObject->FsContext) + 0x100);
1533 Extra = L" (FastFAT)";
1534 }
1535 else
1536 {
1537 FileName = &NoName;
1538 }
1539
1540 /* And print */
1541 KdbpPrint("%p\t%d\t%d\t%wZ%S\n", SharedCacheMap, Mapped, Dirty, FileName, Extra);
1542 }
1543
1544 return TRUE;
1545}
1546
1547BOOLEAN
1548ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[])
1549{
1550 KdbpPrint("CcTotalDirtyPages:\t%lu (%lu Kb)\n", CcTotalDirtyPages,
1551 (CcTotalDirtyPages * PAGE_SIZE) / 1024);
1552 KdbpPrint("CcDirtyPageThreshold:\t%lu (%lu Kb)\n", CcDirtyPageThreshold,
1553 (CcDirtyPageThreshold * PAGE_SIZE) / 1024);
1554 KdbpPrint("MmAvailablePages:\t%lu (%lu Kb)\n", MmAvailablePages,
1555 (MmAvailablePages * PAGE_SIZE) / 1024);
1556 KdbpPrint("MmThrottleTop:\t\t%lu (%lu Kb)\n", MmThrottleTop,
1557 (MmThrottleTop * PAGE_SIZE) / 1024);
1558 KdbpPrint("MmThrottleBottom:\t%lu (%lu Kb)\n", MmThrottleBottom,
1559 (MmThrottleBottom * PAGE_SIZE) / 1024);
1560 KdbpPrint("MmModifiedPageListHead.Total:\t%lu (%lu Kb)\n", MmModifiedPageListHead.Total,
1562
1564 {
1565 KdbpPrint("CcTotalDirtyPages above the threshold, writes should be throttled\n");
1566 }
1567 else if (CcTotalDirtyPages + 64 >= CcDirtyPageThreshold)
1568 {
1569 KdbpPrint("CcTotalDirtyPages within 64 (max charge) pages of the threshold, writes may be throttled\n");
1570 }
1571 else
1572 {
1573 KdbpPrint("CcTotalDirtyPages below the threshold, writes should not be throttled\n");
1574 }
1575
1576 return TRUE;
1577}
1578
1579#endif // DBG && defined(KDBG)
1580
1581/* EOF */
NTSTATUS NTAPI MmUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:3128
static CC_FILE_SIZES FileSizes
unsigned char BOOLEAN
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
void quit(int argc, const char *argv[])
Definition: cmds.c:1606
#define DPRINT1
Definition: precomp.h:8
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1431
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Trace(x)
Definition: inflate.c:42
return Iosb
Definition: create.c:4402
#define TAG_BCB
Definition: nodetype.h:157
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
struct _FSRTL_COMMON_FCB_HEADER * PFSRTL_COMMON_FCB_HEADER
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:33
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN PFCB IN VBO OUT PLBO OUT PULONG OUT PBOOLEAN Allocated
Definition: fatprocs.h:310
struct _FileName FileName
Definition: fatprocs.h:896
#define FSRTL_CACHE_TOP_LEVEL_IRP
Definition: fsrtltypes.h:60
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
#define DbgPrint
Definition: hal.h:12
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:599
#define InterlockedCompareExchange
Definition: interlocked.h:104
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
VOID KdbpPrint(_In_ PSTR Format, _In_ ...)
Prints the given string with printf-like formatting.
Definition: kdb_cli.c:3082
BOOLEAN ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[])
BOOLEAN ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[])
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
VOID CcScheduleLazyWriteScan(IN BOOLEAN NoDelay)
Definition: lazywrite.c:210
LAZY_WRITER LazyWriter
Definition: lazywrite.c:37
VOID NTAPI ExInitializeNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth)
Definition: lookas.c:218
#define ASSERT(a)
Definition: mode.c:44
struct task_struct * current
Definition: linux.c:32
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define min(a, b)
Definition: monoChain.cc:55
#define _Out_opt_
Definition: ms_sal.h:346
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define KernelMode
Definition: asm.h:34
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:408
VOID NTAPI CcInitCacheZeroPage(VOID)
Definition: copy.c:56
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:209
int Count
Definition: noreturn.cpp:7
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1293
#define SEC_RESERVE
Definition: nt_native.h:1323
#define FILE_ALL_ACCESS
Definition: nt_native.h:651
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
VOID CcRosTraceCacheMap(PROS_SHARED_CACHE_MAP SharedCacheMap, BOOLEAN Trace)
Definition: view.c:116
static NTSTATUS CcRosDeleteFileCache(PFILE_OBJECT FileObject, PROS_SHARED_CACHE_MAP SharedCacheMap, PKIRQL OldIrql)
Definition: view.c:208
VOID CcRosMarkDirtyVacb(PROS_VACB Vacb)
Definition: view.c:649
NTSTATUS CcRosInitializeFileCache(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes, BOOLEAN PinAccess, PCACHE_MANAGER_CALLBACKS CallBacks, PVOID LazyWriterContext)
Definition: view.c:1260
LIST_ENTRY CcCleanSharedCacheMapList
Definition: view.c:59
static LIST_ENTRY VacbLruListHead
Definition: view.c:42
KSPIN_LOCK CcDeferredWriteSpinLock
Definition: view.c:58
NTSTATUS CcRosReleaseVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, PROS_VACB Vacb, BOOLEAN Dirty, BOOLEAN Mapped)
Definition: view.c:574
NTSTATUS CcRosFlushVacb(_In_ PROS_VACB Vacb, _Out_opt_ PIO_STATUS_BLOCK Iosb)
Definition: view.c:162
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointers, IN PLARGE_INTEGER FileOffset OPTIONAL, IN ULONG Length, OUT PIO_STATUS_BLOCK IoStatus)
Definition: view.c:1081
NTSTATUS CcRosRequestVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:1008
LIST_ENTRY CcDeferredWrites
Definition: view.c:57
NPAGED_LOOKASIDE_LIST iBcbLookasideList
Definition: view.c:44
BOOLEAN CcRosEnsureVacbResident(_In_ PROS_VACB Vacb, _In_ BOOLEAN Wait, _In_ BOOLEAN NoRead, _In_ ULONG Offset, _In_ ULONG Length)
Definition: view.c:910
PROS_VACB CcRosLookupVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset)
Definition: view.c:606
NTSTATUS CcRosReleaseFileCache(PFILE_OBJECT FileObject)
Definition: view.c:1204
PFILE_OBJECT NTAPI CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
Definition: view.c:1430
VOID NTAPI CcInitView(VOID)
Definition: view.c:1449
VOID CcRosTrimCache(_In_ ULONG Target, _Out_ PULONG NrFreed)
Definition: view.c:456
LIST_ENTRY DirtyVacbListHead
Definition: view.c:41
static NPAGED_LOOKASIDE_LIST SharedCacheMapLookasideList
Definition: view.c:45
NTSTATUS CcRosInternalFreeVacb(PROS_VACB Vacb)
Definition: view.c:1032
NTSTATUS CcRosGetVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:957
static NPAGED_LOOKASIDE_LIST VacbLookasideList
Definition: view.c:46
BOOLEAN CcRosFreeOneUnusedVacb(VOID)
Definition: view.c:720
ULONG CcDirtyPageThreshold
Definition: view.c:55
ULONG CcTotalDirtyPages
Definition: view.c:56
VOID CcRosUnmarkDirtyVacb(PROS_VACB Vacb, BOOLEAN LockViews)
Definition: view.c:685
NTSTATUS CcRosFlushDirtyPages(ULONG Target, PULONG Count, BOOLEAN Wait, BOOLEAN CalledFromLazy)
Definition: view.c:308
static NTSTATUS CcRosCreateVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:780
NTSTATUS NTAPI FsRtlAcquireFileForCcFlushEx(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1692
VOID NTAPI FsRtlReleaseFileForCcFlush(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1765
#define CcRosVacbIncRefCount(vacb)
Definition: cc.h:495
FORCEINLINE BOOLEAN IsPointInRange(_In_ LONGLONG Offset1, _In_ LONGLONG Length1, _In_ LONGLONG Point)
Definition: cc.h:461
#define WRITEBEHIND_DISABLED
Definition: cc.h:202
#define CcRosVacbGetRefCount(vacb)
Definition: cc.h:510
#define NODE_TYPE_PRIVATE_MAP
Definition: cc.h:287
#define CC_API_DEBUG
Definition: cc.h:11
#define SHARED_CACHE_MAP_IN_CREATION
Definition: cc.h:203
#define CCTRACE(x, fmt,...)
Definition: cc.h:36
#define SHARED_CACHE_MAP_IN_LAZYWRITE
Definition: cc.h:204
FORCEINLINE ULONG CcRosVacbDecRefCount(PROS_VACB vacb)
Definition: cc.h:498
#define NODE_TYPE_SHARED_MAP
Definition: cc.h:288
ULONG MmThrottleTop
Definition: mminit.c:396
MMPFNLIST MmModifiedPageListHead
Definition: pfnlist.c:45
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1306
BOOLEAN NTAPI MmArePagesResident(_In_ PEPROCESS Process, _In_ PVOID BaseAddress, _In_ ULONG Length)
Definition: section.c:4775
NTSTATUS NTAPI MmFlushSegment(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER Offset, _In_ ULONG Length, _Out_opt_ PIO_STATUS_BLOCK Iosb)
Definition: section.c:4940
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
NTSTATUS NTAPI MmMakeDataSectionResident(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length, _In_ PLARGE_INTEGER ValidDataLength)
Definition: section.c:4920
ULONG MmThrottleBottom
Definition: mminit.c:397
NTSTATUS NTAPI MmMapViewInSystemSpaceEx(_In_ PVOID Section, _Outptr_result_bytebuffer_(*ViewSize) PVOID *MappedBase, _Inout_ PSIZE_T ViewSize, _Inout_ PLARGE_INTEGER SectionOffset, _In_ ULONG_PTR Flags)
Definition: section.c:4460
NTSTATUS NTAPI MmPageOutPhysicalAddress(PFN_NUMBER Page)
Definition: rmap.c:51
#define ExRaiseStatus
Definition: ntoskrnl.h:114
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
PHYSICAL_ADDRESS NTAPI MmGetPhysicalAddress(IN PVOID Address)
Definition: stubs.c:685
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:381
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
ULONG PFN_NUMBER
Definition: ke.h:9
NTSTATUS NTAPI MmCreateSection(OUT PVOID *Section, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL, IN PFILE_OBJECT FileObject OPTIONAL)
Definition: section.c:4620
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
PACQUIRE_FOR_LAZY_WRITE AcquireForLazyWrite
Definition: cctypes.h:39
PRELEASE_FROM_LAZY_WRITE ReleaseFromLazyWrite
Definition: cctypes.h:40
LARGE_INTEGER FileSize
Definition: cctypes.h:16
LARGE_INTEGER ValidDataLength
Definition: cctypes.h:17
LARGE_INTEGER AllocationSize
Definition: cctypes.h:15
BOOLEAN ScanActive
Definition: cc.h:246
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PFN_NUMBER Total
Definition: mm.h:443
PFILE_OBJECT FileObject
Definition: cctypes.h:76
ULONG ReadAheadMask
Definition: cctypes.h:75
KSPIN_LOCK ReadAheadSpinLock
Definition: cctypes.h:83
CSHORT NodeTypeCode
Definition: cctypes.h:71
LIST_ENTRY PrivateLinks
Definition: cctypes.h:84
LIST_ENTRY CacheMapVacbListHead
Definition: cc.h:193
LARGE_INTEGER FileSize
Definition: cc.h:175
PRIVATE_CACHE_MAP PrivateCacheMap
Definition: cc.h:190
KSPIN_LOCK CacheMapLock
Definition: cc.h:195
PKEVENT CreateEvent
Definition: cc.h:184
LARGE_INTEGER ValidDataLength
Definition: cc.h:178
PCACHE_MANAGER_CALLBACKS Callbacks
Definition: cc.h:185
LIST_ENTRY SharedCacheMapLinks
Definition: cc.h:181
CSHORT NodeTypeCode
Definition: cc.h:172
ULONG DirtyPageThreshold
Definition: cc.h:188
ULONG OpenCount
Definition: cc.h:174
PVOID LazyWriteContext
Definition: cc.h:186
ULONG DirtyPages
Definition: cc.h:180
LIST_ENTRY PrivateList
Definition: cc.h:187
LARGE_INTEGER SectionSize
Definition: cc.h:177
CSHORT NodeByteSize
Definition: cc.h:173
BOOLEAN PinAccess
Definition: cc.h:194
LIST_ENTRY BcbList
Definition: cc.h:176
PFILE_OBJECT FileObject
Definition: cc.h:179
Definition: cc.h:207
ULONG MappedCount
Definition: cc.h:214
LIST_ENTRY CacheMapVacbListEntry
Definition: cc.h:216
BOOLEAN Dirty
Definition: cc.h:211
PROS_SHARED_CACHE_MAP SharedCacheMap
Definition: cc.h:226
LARGE_INTEGER FileOffset
Definition: cc.h:222
PVOID BaseAddress
Definition: cc.h:209
volatile ULONG ReferenceCount
Definition: cc.h:224
BOOLEAN PageOut
Definition: cc.h:213
LIST_ENTRY DirtyVacbListEntry
Definition: cc.h:218
LIST_ENTRY VacbLruListEntry
Definition: cc.h:220
Definition: fci.c:127
Definition: parser.c:49
#define TAG_PRIVATE_CACHE_MAP
Definition: tag.h:17
#define TAG_SHARED_CACHE_MAP
Definition: tag.h:16
#define TAG_VACB
Definition: tag.h:15
#define LL
Definition: tui.h:150
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint16_t * PWSTR
Definition: typedefs.h:56
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
int64_t LONGLONG
Definition: typedefs.h:68
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
const char * PCSTR
Definition: typedefs.h:52
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
#define VACB_MAPPING_GRANULARITY
struct LOOKASIDE_ALIGN _NPAGED_LOOKASIDE_LIST NPAGED_LOOKASIDE_LIST
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define FO_TEMPORARY_FILE
Definition: iotypes.h:1791
* PFILE_OBJECT
Definition: iotypes.h:1998
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ Executive
Definition: ketypes.h:415
@ LockQueueMasterLock
Definition: ketypes.h:663
#define ObDereferenceObject
Definition: obfuncs.h:203
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3287