ReactOS 0.4.16-dev-983-g23ad936
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
37#define NDEBUG
38#include <debug.h>
39
40/* GLOBALS *******************************************************************/
41
44
48
49/* Internal vars (MS):
50 * - Threshold above which lazy writer will start action
51 * - Amount of dirty pages
52 * - List for deferred writes
53 * - Spinlock when dealing with the deferred list
54 * - List for "clean" shared cache maps
55 */
61
62#if DBG
63ULONG CcRosVacbIncRefCount_(PROS_VACB vacb, PCSTR file, INT line)
64{
65 ULONG Refs;
66
68 if (vacb->SharedCacheMap->Trace)
69 {
70 DbgPrint("(%s:%i) VACB %p ++RefCount=%lu, Dirty %u, PageOut %lu\n",
71 file, line, vacb, Refs, vacb->Dirty, vacb->PageOut);
72 }
73
74 return Refs;
75}
76ULONG CcRosVacbDecRefCount_(PROS_VACB vacb, PCSTR file, INT line)
77{
78 ULONG Refs;
79 BOOLEAN VacbDirty = vacb->Dirty;
80 BOOLEAN VacbTrace = vacb->SharedCacheMap->Trace;
81 BOOLEAN VacbPageOut = vacb->PageOut;
82
84 ASSERT(!(Refs == 0 && VacbDirty));
85 if (VacbTrace)
86 {
87 DbgPrint("(%s:%i) VACB %p --RefCount=%lu, Dirty %u, PageOut %lu\n",
88 file, line, vacb, Refs, VacbDirty, VacbPageOut);
89 }
90
91 if (Refs == 0)
92 {
94 }
95
96 return Refs;
97}
98ULONG CcRosVacbGetRefCount_(PROS_VACB vacb, PCSTR file, INT line)
99{
100 ULONG Refs;
101
102 Refs = InterlockedCompareExchange((PLONG)&vacb->ReferenceCount, 0, 0);
103 if (vacb->SharedCacheMap->Trace)
104 {
105 DbgPrint("(%s:%i) VACB %p ==RefCount=%lu, Dirty %u, PageOut %lu\n",
106 file, line, vacb, Refs, vacb->Dirty, vacb->PageOut);
107 }
108
109 return Refs;
110}
111#endif
112
113
114/* FUNCTIONS *****************************************************************/
115
116VOID
118 PROS_SHARED_CACHE_MAP SharedCacheMap,
119 BOOLEAN Trace )
120{
121#if DBG
122 KIRQL oldirql;
123 PLIST_ENTRY current_entry;
125
126 if (!SharedCacheMap)
127 return;
128
129 SharedCacheMap->Trace = Trace;
130
131 if (Trace)
132 {
133 DPRINT1("Enabling Tracing for CacheMap 0x%p:\n", SharedCacheMap);
134
137
138 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
139 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
140 {
141 current = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry);
142 current_entry = current_entry->Flink;
143
144 DPRINT1(" VACB 0x%p enabled, RefCount %lu, Dirty %u, PageOut %lu, BaseAddress %p, FileOffset %I64d\n",
145 current, current->ReferenceCount, current->Dirty, current->PageOut, current->BaseAddress, current->FileOffset.QuadPart);
146 }
147
150 }
151 else
152 {
153 DPRINT1("Disabling Tracing for CacheMap 0x%p:\n", SharedCacheMap);
154 }
155
156#else
157 UNREFERENCED_PARAMETER(SharedCacheMap);
159#endif
160}
161
164 _In_ PROS_VACB Vacb,
166{
168 BOOLEAN HaveLock = FALSE;
169 PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
170
172
173 /* Lock for flush, if we are not already the top-level */
175 {
176 Status = FsRtlAcquireFileForCcFlushEx(Vacb->SharedCacheMap->FileObject);
177 if (!NT_SUCCESS(Status))
178 goto quit;
179 HaveLock = TRUE;
180 }
181
182 Status = MmFlushSegment(SharedCacheMap->FileObject->SectionObjectPointer,
183 &Vacb->FileOffset,
185 Iosb);
186
187 if (HaveLock)
188 {
189 FsRtlReleaseFileForCcFlush(Vacb->SharedCacheMap->FileObject);
190 }
191
192quit:
193 if (!NT_SUCCESS(Status))
194 CcRosMarkDirtyVacb(Vacb);
195 else
196 {
197 /* Update VDL */
198 if (SharedCacheMap->ValidDataLength.QuadPart < (Vacb->FileOffset.QuadPart + VACB_MAPPING_GRANULARITY))
199 {
200 SharedCacheMap->ValidDataLength.QuadPart = Vacb->FileOffset.QuadPart + VACB_MAPPING_GRANULARITY;
201 }
202 }
203
204 return Status;
205}
206
207static
211 PROS_SHARED_CACHE_MAP SharedCacheMap,
213/*
214 * FUNCTION: Releases the shared cache map associated with a file object
215 */
216{
217 PLIST_ENTRY current_entry;
218
219 ASSERT(SharedCacheMap);
220 ASSERT(SharedCacheMap == FileObject->SectionObjectPointer->SharedCacheMap);
221 ASSERT(SharedCacheMap->OpenCount == 0);
222
223 /* Remove all VACBs from the global lists */
225 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
226 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
227 {
228 PROS_VACB Vacb = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry);
229
232
233 if (Vacb->Dirty)
234 {
236 /* Mark it as dirty again so we know that we have to flush before freeing it */
237 Vacb->Dirty = TRUE;
238 }
239
240 current_entry = current_entry->Flink;
241 }
242
243 /* Make sure there is no trace anymore of this map */
244 FileObject->SectionObjectPointer->SharedCacheMap = NULL;
245 RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks);
246
249
250 /* Now that we're out of the locks, free everything for real */
251 while (!IsListEmpty(&SharedCacheMap->CacheMapVacbListHead))
252 {
253 PROS_VACB Vacb = CONTAINING_RECORD(RemoveHeadList(&SharedCacheMap->CacheMapVacbListHead), ROS_VACB, CacheMapVacbListEntry);
254 ULONG RefCount;
255
257
258 /* Flush to disk, if needed */
259 if (Vacb->Dirty)
260 {
263
264 Status = MmFlushSegment(FileObject->SectionObjectPointer, &Vacb->FileOffset, VACB_MAPPING_GRANULARITY, &Iosb);
265 if (!NT_SUCCESS(Status))
266 {
267 /* Complain. There's not much we can do */
268 DPRINT1("Failed to flush VACB to disk while deleting the cache entry. Status: 0x%08x\n", Status);
269 }
270 Vacb->Dirty = FALSE;
271 }
272
273 RefCount = CcRosVacbDecRefCount(Vacb);
274#if DBG // CORE-14578
275 if (RefCount != 0)
276 {
277 DPRINT1("Leaking VACB %p attached to %p (%I64d)\n", Vacb, FileObject, Vacb->FileOffset.QuadPart);
278 DPRINT1("There are: %d references left\n", RefCount);
279 DPRINT1("Map: %d\n", Vacb->MappedCount);
280 DPRINT1("Dirty: %d\n", Vacb->Dirty);
281 if (FileObject->FileName.Length != 0)
282 {
283 DPRINT1("File was: %wZ\n", &FileObject->FileName);
284 }
285 else
286 {
287 DPRINT1("No name for the file\n");
288 }
289 }
290#else
291 (void)RefCount;
292#endif
293 }
294
295 /* Release the references we own */
296 if(SharedCacheMap->Section)
297 ObDereferenceObject(SharedCacheMap->Section);
298 ObDereferenceObject(SharedCacheMap->FileObject);
299
300 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap);
301
302 /* Acquire the lock again for our caller */
304
305 return STATUS_SUCCESS;
306}
307
313 BOOLEAN CalledFromLazy)
314{
315 PLIST_ENTRY current_entry;
318 BOOLEAN FlushAll = (Target == MAXULONG);
319
320 DPRINT("CcRosFlushDirtyPages(Target %lu)\n", Target);
321
322 (*Count) = 0;
323
326
327 current_entry = DirtyVacbListHead.Flink;
328 if (current_entry == &DirtyVacbListHead)
329 {
330 DPRINT("No Dirty pages\n");
331 }
332
333 while (((current_entry != &DirtyVacbListHead) && (Target > 0)) || FlushAll)
334 {
335 PROS_SHARED_CACHE_MAP SharedCacheMap;
338
339 if (current_entry == &DirtyVacbListHead)
340 {
341 ASSERT(FlushAll);
343 break;
344 current_entry = DirtyVacbListHead.Flink;
345 }
346
347 current = CONTAINING_RECORD(current_entry,
348 ROS_VACB,
349 DirtyVacbListEntry);
350 current_entry = current_entry->Flink;
351
353
354 SharedCacheMap = current->SharedCacheMap;
355
356 /* When performing lazy write, don't handle temporary files */
357 if (CalledFromLazy && BooleanFlagOn(SharedCacheMap->FileObject->Flags, FO_TEMPORARY_FILE))
358 {
360 continue;
361 }
362
363 /* Don't attempt to lazy write the files that asked not to */
364 if (CalledFromLazy && BooleanFlagOn(SharedCacheMap->Flags, WRITEBEHIND_DISABLED))
365 {
367 continue;
368 }
369
370 ASSERT(current->Dirty);
371
372 /* Do not lazy-write the same file concurrently. Fastfat ASSERTS on that */
373 if (SharedCacheMap->Flags & SHARED_CACHE_MAP_IN_LAZYWRITE)
374 {
376 continue;
377 }
378
379 SharedCacheMap->Flags |= SHARED_CACHE_MAP_IN_LAZYWRITE;
380
381 /* Keep a ref on the shared cache map */
382 SharedCacheMap->OpenCount++;
383
385
386 Locked = SharedCacheMap->Callbacks->AcquireForLazyWrite(SharedCacheMap->LazyWriteContext, Wait);
387 if (!Locked)
388 {
389 DPRINT("Not locked\n");
390 ASSERT(!Wait);
393 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;
394
395 if (--SharedCacheMap->OpenCount == 0)
396 CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);
397
398 continue;
399 }
400
403
404 SharedCacheMap->Callbacks->ReleaseFromLazyWrite(SharedCacheMap->LazyWriteContext);
405
406 /* We release the VACB before acquiring the lock again, because
407 * CcRosVacbDecRefCount might free the VACB, as CcRosFlushVacb dropped a
408 * Refcount. Freeing must be done outside of the lock.
409 * The refcount is decremented atomically. So this is OK. */
412
413 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;
414
415 if (--SharedCacheMap->OpenCount == 0)
416 CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);
417
420 {
421 DPRINT1("CC: Failed to flush VACB.\n");
422 }
423 else
424 {
425 ULONG PagesFreed;
426
427 /* How many pages did we free? */
428 PagesFreed = Iosb.Information / PAGE_SIZE;
429 (*Count) += PagesFreed;
430
431 if (!Wait)
432 {
433 /* Make sure we don't overflow target! */
434 if (Target < PagesFreed)
435 {
436 /* If we would have, jump to zero directly */
437 Target = 0;
438 }
439 else
440 {
441 Target -= PagesFreed;
442 }
443 }
444 }
445
446 current_entry = DirtyVacbListHead.Flink;
447 }
448
451
452 DPRINT("CcRosFlushDirtyPages() finished\n");
453 return STATUS_SUCCESS;
454}
455
456VOID
459 _Out_ PULONG NrFreed)
460/*
461 * FUNCTION: Try to free some memory from the file cache.
462 * ARGUMENTS:
463 * Target - The number of pages to be freed.
464 * NrFreed - Points to a variable where the number of pages
465 * actually freed is returned.
466 */
467{
468 PLIST_ENTRY current_entry;
470 ULONG PagesFreed;
471 KIRQL oldIrql;
473 BOOLEAN FlushedPages = FALSE;
474
475 DPRINT("CcRosTrimCache(Target %lu)\n", Target);
476
478
479 *NrFreed = 0;
480
481retry:
483
484 current_entry = VacbLruListHead.Flink;
485 while (current_entry != &VacbLruListHead)
486 {
487 ULONG Refs;
488
489 current = CONTAINING_RECORD(current_entry,
490 ROS_VACB,
491 VacbLruListEntry);
492
493 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
494
495 /* Reference the VACB */
497
498 /* Check if it's mapped and not dirty */
499 if (InterlockedCompareExchange((PLONG)&current->MappedCount, 0, 0) > 0 && !current->Dirty)
500 {
501 /* This code is never executed. It is left for reference only. */
502#if 1
503 DPRINT1("MmPageOutPhysicalAddress unexpectedly called\n");
504 ASSERT(FALSE);
505#else
506 ULONG i;
508
509 /* We have to break these locks to call MmPageOutPhysicalAddress */
510 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
512
513 /* Page out the VACB */
514 for (i = 0; i < VACB_MAPPING_GRANULARITY / PAGE_SIZE; i++)
515 {
517
519 }
520
521 /* Reacquire the locks */
523 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
524#endif
525 }
526
527 /* Only keep iterating though the loop while the lock is held */
528 current_entry = current_entry->Flink;
529
530 /* Dereference the VACB */
532
533 /* Check if we can free this entry now */
534 if (Refs < 2)
535 {
536 ASSERT(!current->Dirty);
537 ASSERT(!current->MappedCount);
538 ASSERT(Refs == 1);
539
540 RemoveEntryList(&current->CacheMapVacbListEntry);
541 RemoveEntryList(&current->VacbLruListEntry);
542 InitializeListHead(&current->VacbLruListEntry);
543 InsertHeadList(&FreeList, &current->CacheMapVacbListEntry);
544
545 /* Calculate how many pages we freed for Mm */
547 Target -= PagesFreed;
548 (*NrFreed) += PagesFreed;
549 }
550
551 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
552 }
553
555
556 /* Try flushing pages if we haven't met our target */
557 if ((Target > 0) && !FlushedPages)
558 {
559 /* Flush dirty pages to disk */
560 CcRosFlushDirtyPages(Target, &PagesFreed, FALSE, FALSE);
561 FlushedPages = TRUE;
562
563 /* We can only swap as many pages as we flushed */
564 if (PagesFreed < Target) Target = PagesFreed;
565
566 /* Check if we flushed anything */
567 if (PagesFreed != 0)
568 {
569 /* Try again after flushing dirty pages */
570 DPRINT("Flushed %lu dirty cache pages to disk\n", PagesFreed);
571 goto retry;
572 }
573 }
574
575 while (!IsListEmpty(&FreeList))
576 {
577 ULONG Refs;
578
579 current_entry = RemoveHeadList(&FreeList);
580 current = CONTAINING_RECORD(current_entry,
581 ROS_VACB,
582 CacheMapVacbListEntry);
583 InitializeListHead(&current->CacheMapVacbListEntry);
585 ASSERT(Refs == 0);
586 }
587
588 DPRINT("Evicted %lu cache pages\n", (*NrFreed));
589}
590
593 PROS_SHARED_CACHE_MAP SharedCacheMap,
594 PROS_VACB Vacb,
595 BOOLEAN Dirty,
596 BOOLEAN Mapped)
597{
598 ULONG Refs;
599 ASSERT(SharedCacheMap);
600
601 DPRINT("CcRosReleaseVacb(SharedCacheMap 0x%p, Vacb 0x%p)\n", SharedCacheMap, Vacb);
602
603 if (Dirty && !Vacb->Dirty)
604 {
605 CcRosMarkDirtyVacb(Vacb);
606 }
607
608 if (Mapped)
609 {
610 if (InterlockedIncrement((PLONG)&Vacb->MappedCount) == 1)
611 {
613 }
614 }
615
616 Refs = CcRosVacbDecRefCount(Vacb);
617 ASSERT(Refs > 0);
618
619 return STATUS_SUCCESS;
620}
621
622/* Returns with VACB Lock Held! */
625 PROS_SHARED_CACHE_MAP SharedCacheMap,
627{
628 PLIST_ENTRY current_entry;
630 KIRQL oldIrql;
631
632 ASSERT(SharedCacheMap);
633
634 DPRINT("CcRosLookupVacb(SharedCacheMap 0x%p, FileOffset %I64u)\n",
635 SharedCacheMap, FileOffset);
636
639
640 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
641 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
642 {
643 current = CONTAINING_RECORD(current_entry,
644 ROS_VACB,
645 CacheMapVacbListEntry);
646 if (IsPointInRange(current->FileOffset.QuadPart,
648 FileOffset))
649 {
653 return current;
654 }
655 if (current->FileOffset.QuadPart > FileOffset)
656 break;
657 current_entry = current_entry->Flink;
658 }
659
662
663 return NULL;
664}
665
666VOID
668 PROS_VACB Vacb)
669{
670 KIRQL oldIrql;
671 PROS_SHARED_CACHE_MAP SharedCacheMap;
672
673 SharedCacheMap = Vacb->SharedCacheMap;
674
677
678 ASSERT(!Vacb->Dirty);
679
681 /* FIXME: There is no reason to account for the whole VACB. */
685
686 /* Move to the tail of the LRU list */
689
690 Vacb->Dirty = TRUE;
691
693
694 /* Schedule a lazy writer run to now that we have dirty VACB */
696 {
698 }
700}
701
702VOID
704 PROS_VACB Vacb,
705 BOOLEAN LockViews)
706{
707 KIRQL oldIrql;
708 PROS_SHARED_CACHE_MAP SharedCacheMap;
709
710 SharedCacheMap = Vacb->SharedCacheMap;
711
712 if (LockViews)
713 {
716 }
717
718 ASSERT(Vacb->Dirty);
719
720 Vacb->Dirty = FALSE;
721
724
727
729
730 if (LockViews)
731 {
734 }
735}
736
739 VOID)
740{
741 KIRQL oldIrql;
742 PLIST_ENTRY current_entry;
743 PROS_VACB to_free = NULL;
744
746
747 /* Browse all the available VACB */
748 current_entry = VacbLruListHead.Flink;
749 while ((current_entry != &VacbLruListHead) && (to_free == NULL))
750 {
751 ULONG Refs;
753
754 current = CONTAINING_RECORD(current_entry,
755 ROS_VACB,
756 VacbLruListEntry);
757
758 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
759
760 /* Only deal with unused VACB, we will free them */
762 if (Refs < 2)
763 {
764 ASSERT(!current->Dirty);
765 ASSERT(!current->MappedCount);
766 ASSERT(Refs == 1);
767
768 /* Reset it, this is the one we want to free */
769 RemoveEntryList(&current->CacheMapVacbListEntry);
770 InitializeListHead(&current->CacheMapVacbListEntry);
771 RemoveEntryList(&current->VacbLruListEntry);
772 InitializeListHead(&current->VacbLruListEntry);
773
774 to_free = current;
775 }
776
777 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
778
779 current_entry = current_entry->Flink;
780 }
781
783
784 /* And now, free the VACB that we found, if any. */
785 if (to_free == NULL)
786 {
787 return FALSE;
788 }
789
790 /* This must be its last ref */
791 NT_VERIFY(CcRosVacbDecRefCount(to_free) == 0);
792
793 return TRUE;
794}
795
796static
799 PROS_SHARED_CACHE_MAP SharedCacheMap,
801 PROS_VACB *Vacb)
802{
804 PROS_VACB previous;
805 PLIST_ENTRY current_entry;
807 KIRQL oldIrql;
808 ULONG Refs;
810
811 ASSERT(SharedCacheMap);
812
813 DPRINT("CcRosCreateVacb()\n");
814
815 current = ExAllocateFromNPagedLookasideList(&VacbLookasideList);
816 if (!current)
817 {
819 }
820 current->BaseAddress = NULL;
821 current->Dirty = FALSE;
822 current->PageOut = FALSE;
823 current->FileOffset.QuadPart = ROUND_DOWN(FileOffset, VACB_MAPPING_GRANULARITY);
824 current->SharedCacheMap = SharedCacheMap;
825 current->MappedCount = 0;
826 current->ReferenceCount = 0;
827 InitializeListHead(&current->CacheMapVacbListEntry);
828 InitializeListHead(&current->DirtyVacbListEntry);
829 InitializeListHead(&current->VacbLruListEntry);
830
832
833 while (TRUE)
834 {
835 /* Map VACB in system space */
836 Status = MmMapViewInSystemSpaceEx(SharedCacheMap->Section, &current->BaseAddress, &ViewSize, &current->FileOffset, 0);
837 if (NT_SUCCESS(Status))
838 {
839 break;
840 }
841
842 /*
843 * If no space left, try to prune one unused VACB to recover space to map our VACB.
844 * If it succeeds, retry to map, otherwise just fail.
845 */
847 {
848 ExFreeToNPagedLookasideList(&VacbLookasideList, current);
849 return Status;
850 }
851 }
852
853#if DBG
854 if (SharedCacheMap->Trace)
855 {
856 DPRINT1("CacheMap 0x%p: new VACB: 0x%p, file offset %I64d, BaseAddress %p\n",
857 SharedCacheMap, current, current->FileOffset.QuadPart, current->BaseAddress);
858 }
859#endif
860
862
863 *Vacb = current;
864 /* There is window between the call to CcRosLookupVacb
865 * and CcRosCreateVacb. We must check if a VACB for the
866 * file offset exist. If there is a VACB, we release
867 * our newly created VACB and return the existing one.
868 */
870 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
871 previous = NULL;
872 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
873 {
874 current = CONTAINING_RECORD(current_entry,
875 ROS_VACB,
876 CacheMapVacbListEntry);
877 if (IsPointInRange(current->FileOffset.QuadPart,
879 FileOffset))
880 {
883#if DBG
884 if (SharedCacheMap->Trace)
885 {
886 DPRINT1("CacheMap 0x%p: deleting newly created VACB 0x%p ( found existing one 0x%p )\n",
887 SharedCacheMap,
888 (*Vacb),
889 current);
890 }
891#endif
893
894 Refs = CcRosVacbDecRefCount(*Vacb);
895 ASSERT(Refs == 0);
896
897 *Vacb = current;
898 return STATUS_SUCCESS;
899 }
900 if (current->FileOffset.QuadPart < FileOffset)
901 {
902 ASSERT(previous == NULL ||
903 previous->FileOffset.QuadPart < current->FileOffset.QuadPart);
904 previous = current;
905 }
906 if (current->FileOffset.QuadPart > FileOffset)
907 break;
908 current_entry = current_entry->Flink;
909 }
910 /* There was no existing VACB. */
911 current = *Vacb;
912 if (previous)
913 {
914 InsertHeadList(&previous->CacheMapVacbListEntry, &current->CacheMapVacbListEntry);
915 }
916 else
917 {
918 InsertHeadList(&SharedCacheMap->CacheMapVacbListHead, &current->CacheMapVacbListEntry);
919 }
921 InsertTailList(&VacbLruListHead, &current->VacbLruListEntry);
922
923 /* Reference it to allow release */
925
927
928 return Status;
929}
930
933 _In_ PROS_VACB Vacb,
935 _In_ BOOLEAN NoRead,
938)
939{
940 PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
941
943
944#if 0
945 if ((Vacb->FileOffset.QuadPart + Offset) > SharedCacheMap->SectionSize.QuadPart)
946 {
947 DPRINT1("Vacb read beyond the file size!\n");
948 return FALSE;
949 }
950#endif
951
952 /* Check if the pages are resident */
953 if (!MmIsDataSectionResident(SharedCacheMap->FileObject->SectionObjectPointer,
954 Vacb->FileOffset.QuadPart + Offset,
955 Length))
956 {
957 if (!Wait)
958 {
959 return FALSE;
960 }
961
962 if (!NoRead)
963 {
964 NTSTATUS Status = MmMakeDataSectionResident(SharedCacheMap->FileObject->SectionObjectPointer,
965 Vacb->FileOffset.QuadPart + Offset,
966 Length,
967 &SharedCacheMap->ValidDataLength);
968 if (!NT_SUCCESS(Status))
970 }
971 }
972
973 return TRUE;
974}
975
976
979 PROS_SHARED_CACHE_MAP SharedCacheMap,
981 PROS_VACB *Vacb)
982{
985 ULONG Refs;
987
988 ASSERT(SharedCacheMap);
989
990 DPRINT("CcRosGetVacb()\n");
991
992 /*
993 * Look for a VACB already mapping the same data.
994 */
995 current = CcRosLookupVacb(SharedCacheMap, FileOffset);
996 if (current == NULL)
997 {
998 /*
999 * Otherwise create a new VACB.
1000 */
1001 Status = CcRosCreateVacb(SharedCacheMap, FileOffset, &current);
1002 if (!NT_SUCCESS(Status))
1003 {
1004 return Status;
1005 }
1006 }
1007
1009
1011
1012 /* Move to the tail of the LRU list */
1013 RemoveEntryList(&current->VacbLruListEntry);
1014 InsertTailList(&VacbLruListHead, &current->VacbLruListEntry);
1015
1017
1018 /*
1019 * Return the VACB to the caller.
1020 */
1021 *Vacb = current;
1022
1023 ASSERT(Refs > 1);
1024
1025 return STATUS_SUCCESS;
1026}
1027
1030 PROS_SHARED_CACHE_MAP SharedCacheMap,
1032 PROS_VACB *Vacb)
1033/*
1034 * FUNCTION: Request a page mapping for a shared cache map
1035 */
1036{
1037
1038 ASSERT(SharedCacheMap);
1039
1041 {
1042 DPRINT1("Bad FileOffset %I64x: should be multiple of %x\n",
1044 KeBugCheck(CACHE_MANAGER);
1045 }
1046
1047 return CcRosGetVacb(SharedCacheMap,
1048 FileOffset,
1049 Vacb);
1050}
1051
1054 PROS_VACB Vacb)
1055/*
1056 * FUNCTION: Releases a VACB associated with a shared cache map
1057 */
1058{
1060
1061 DPRINT("Freeing VACB 0x%p\n", Vacb);
1062#if DBG
1063 if (Vacb->SharedCacheMap->Trace)
1064 {
1065 DPRINT1("CacheMap 0x%p: deleting VACB: 0x%p\n", Vacb->SharedCacheMap, Vacb);
1066 }
1067#endif
1068
1069 if (Vacb->ReferenceCount != 0)
1070 {
1071 DPRINT1("Invalid free: %ld\n", Vacb->ReferenceCount);
1072 if (Vacb->SharedCacheMap->FileObject && Vacb->SharedCacheMap->FileObject->FileName.Length)
1073 {
1074 DPRINT1("For file: %wZ\n", &Vacb->SharedCacheMap->FileObject->FileName);
1075 }
1076 }
1077
1078 ASSERT(Vacb->ReferenceCount == 0);
1082
1083 /* Delete the mapping */
1085 if (!NT_SUCCESS(Status))
1086 {
1087 DPRINT1("Failed to unmap VACB from System address space! Status 0x%08X\n", Status);
1088 ASSERT(FALSE);
1089 /* Proceed with the deĺetion anyway */
1090 }
1091
1092 RtlFillMemory(Vacb, sizeof(*Vacb), 0xfd);
1093 ExFreeToNPagedLookasideList(&VacbLookasideList, Vacb);
1094 return STATUS_SUCCESS;
1095}
1096
1097/*
1098 * @implemented
1099 */
1100VOID
1101NTAPI
1103 IN PSECTION_OBJECT_POINTERS SectionObjectPointers,
1105 IN ULONG Length,
1107{
1108 PROS_SHARED_CACHE_MAP SharedCacheMap;
1109 LONGLONG FlushStart, FlushEnd;
1111
1112 CCTRACE(CC_API_DEBUG, "SectionObjectPointers=%p FileOffset=0x%I64X Length=%lu\n",
1113 SectionObjectPointers, FileOffset ? FileOffset->QuadPart : 0LL, Length);
1114
1115 if (!SectionObjectPointers)
1116 {
1118 goto quit;
1119 }
1120
1121 if (!SectionObjectPointers->SharedCacheMap)
1122 {
1123 /* Forward this to Mm */
1124 MmFlushSegment(SectionObjectPointers, FileOffset, Length, IoStatus);
1125 return;
1126 }
1127
1128 SharedCacheMap = SectionObjectPointers->SharedCacheMap;
1129 ASSERT(SharedCacheMap);
1130 if (FileOffset)
1131 {
1132 FlushStart = FileOffset->QuadPart;
1133 Status = RtlLongLongAdd(FlushStart, Length, &FlushEnd);
1134 if (!NT_SUCCESS(Status))
1135 goto quit;
1136 }
1137 else
1138 {
1139 FlushStart = 0;
1140 FlushEnd = SharedCacheMap->FileSize.QuadPart;
1141 }
1142
1144 if (IoStatus)
1145 {
1146 IoStatus->Information = 0;
1147 }
1148
1149 KeAcquireGuardedMutex(&SharedCacheMap->FlushCacheLock);
1150
1151 /*
1152 * We flush the VACBs that we find here.
1153 * If there is no (dirty) VACB, it doesn't mean that there is no data to flush, so we call Mm to be sure.
1154 * This is suboptimal, but this is due to the lack of granularity of how we track dirty cache data
1155 */
1156 while (FlushStart < FlushEnd)
1157 {
1158 BOOLEAN DirtyVacb = FALSE;
1159 PROS_VACB vacb = CcRosLookupVacb(SharedCacheMap, FlushStart);
1160
1161 if (vacb != NULL)
1162 {
1163 if (vacb->Dirty)
1164 {
1165 IO_STATUS_BLOCK VacbIosb = { 0 };
1166 Status = CcRosFlushVacb(vacb, &VacbIosb);
1167 if (!NT_SUCCESS(Status))
1168 {
1169 CcRosReleaseVacb(SharedCacheMap, vacb, FALSE, FALSE);
1170 break;
1171 }
1172 DirtyVacb = TRUE;
1173
1174 if (IoStatus)
1175 IoStatus->Information += VacbIosb.Information;
1176 }
1177
1178 CcRosReleaseVacb(SharedCacheMap, vacb, FALSE, FALSE);
1179 }
1180
1181 if (!DirtyVacb)
1182 {
1183 IO_STATUS_BLOCK MmIosb;
1184 LARGE_INTEGER MmOffset;
1185
1186 MmOffset.QuadPart = FlushStart;
1187
1188 if (FlushEnd - (FlushEnd % VACB_MAPPING_GRANULARITY) <= FlushStart)
1189 {
1190 /* The whole range fits within a VACB chunk. */
1191 Status = MmFlushSegment(SectionObjectPointers, &MmOffset, FlushEnd - FlushStart, &MmIosb);
1192 }
1193 else
1194 {
1195 ULONG MmLength = VACB_MAPPING_GRANULARITY - (FlushStart % VACB_MAPPING_GRANULARITY);
1196 Status = MmFlushSegment(SectionObjectPointers, &MmOffset, MmLength, &MmIosb);
1197 }
1198
1199 if (!NT_SUCCESS(Status))
1200 break;
1201
1202 if (IoStatus)
1203 IoStatus->Information += MmIosb.Information;
1204
1205 /* Update VDL */
1206 if (SharedCacheMap->ValidDataLength.QuadPart < FlushEnd)
1207 SharedCacheMap->ValidDataLength.QuadPart = FlushEnd;
1208 }
1209
1210 if (!NT_SUCCESS(RtlLongLongAdd(FlushStart, VACB_MAPPING_GRANULARITY, &FlushStart)))
1211 {
1212 /* We're at the end of file ! */
1213 break;
1214 }
1215
1216 /* Round down to next VACB start now */
1217 FlushStart -= FlushStart % VACB_MAPPING_GRANULARITY;
1218 }
1219
1220 KeReleaseGuardedMutex(&SharedCacheMap->FlushCacheLock);
1221
1222quit:
1223 if (IoStatus)
1224 {
1225 IoStatus->Status = Status;
1226 }
1227}
1228
1232/*
1233 * FUNCTION: Called by the file system when a handle to a file object
1234 * has been closed.
1235 */
1236{
1237 KIRQL OldIrql;
1238 PPRIVATE_CACHE_MAP PrivateMap;
1239 PROS_SHARED_CACHE_MAP SharedCacheMap;
1240
1242
1243 if (FileObject->SectionObjectPointer->SharedCacheMap != NULL)
1244 {
1245 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
1246
1247 /* Closing the handle, so kill the private cache map
1248 * Before you event try to remove it from FO, always
1249 * lock the master lock, to be sure not to race
1250 * with a potential read ahead ongoing!
1251 */
1252 PrivateMap = FileObject->PrivateCacheMap;
1253 FileObject->PrivateCacheMap = NULL;
1254
1255 if (PrivateMap != NULL)
1256 {
1257 /* Remove it from the file */
1258 KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock);
1259 RemoveEntryList(&PrivateMap->PrivateLinks);
1261
1262 /* And free it. */
1263 if (PrivateMap != &SharedCacheMap->PrivateCacheMap)
1264 {
1266 }
1267 else
1268 {
1269 PrivateMap->NodeTypeCode = 0;
1270 }
1271
1272 ASSERT(SharedCacheMap->OpenCount > 0);
1273
1274 SharedCacheMap->OpenCount--;
1275 if (SharedCacheMap->OpenCount == 0)
1276 {
1277 CcRosDeleteFileCache(FileObject, SharedCacheMap, &OldIrql);
1278 }
1279 }
1280 }
1282 return STATUS_SUCCESS;
1283}
1284
1289 BOOLEAN PinAccess,
1290 PCACHE_MANAGER_CALLBACKS CallBacks,
1291 PVOID LazyWriterContext)
1292/*
1293 * FUNCTION: Initializes a shared cache map for a file object
1294 */
1295{
1296 KIRQL OldIrql;
1298 PROS_SHARED_CACHE_MAP SharedCacheMap;
1299
1300 DPRINT("CcRosInitializeFileCache(FileObject 0x%p)\n", FileObject);
1301
1303
1304 Allocated = FALSE;
1305 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
1306 if (SharedCacheMap == NULL)
1307 {
1308 SharedCacheMap = ExAllocateFromNPagedLookasideList(&SharedCacheMapLookasideList);
1309 if (SharedCacheMap == NULL)
1310 {
1313 }
1314 RtlZeroMemory(SharedCacheMap, sizeof(*SharedCacheMap));
1315 SharedCacheMap->NodeTypeCode = NODE_TYPE_SHARED_MAP;
1316 SharedCacheMap->NodeByteSize = sizeof(*SharedCacheMap);
1317 SharedCacheMap->FileObject = FileObject;
1318 SharedCacheMap->Callbacks = CallBacks;
1319 SharedCacheMap->LazyWriteContext = LazyWriterContext;
1320 SharedCacheMap->SectionSize = FileSizes->AllocationSize;
1321 SharedCacheMap->FileSize = FileSizes->FileSize;
1322 SharedCacheMap->ValidDataLength = FileSizes->ValidDataLength;
1323 SharedCacheMap->PinAccess = PinAccess;
1324 SharedCacheMap->DirtyPageThreshold = 0;
1325 SharedCacheMap->DirtyPages = 0;
1326 InitializeListHead(&SharedCacheMap->PrivateList);
1327 KeInitializeSpinLock(&SharedCacheMap->CacheMapLock);
1328 InitializeListHead(&SharedCacheMap->CacheMapVacbListHead);
1329 InitializeListHead(&SharedCacheMap->BcbList);
1330 KeInitializeGuardedMutex(&SharedCacheMap->FlushCacheLock);
1331
1332 SharedCacheMap->Flags = SHARED_CACHE_MAP_IN_CREATION;
1333
1336 NULL,
1337 KernelMode);
1338
1339 Allocated = TRUE;
1340 FileObject->SectionObjectPointer->SharedCacheMap = SharedCacheMap;
1341
1342 //CcRosTraceCacheMap(SharedCacheMap, TRUE);
1343 }
1344 else if (SharedCacheMap->Flags & SHARED_CACHE_MAP_IN_CREATION)
1345 {
1346 /* The shared cache map is being created somewhere else. Wait for that to happen */
1347 KEVENT Waiter;
1348 PKEVENT PreviousWaiter = SharedCacheMap->CreateEvent;
1349
1351 SharedCacheMap->CreateEvent = &Waiter;
1352
1354
1356
1357 if (PreviousWaiter)
1358 KeSetEvent(PreviousWaiter, IO_NO_INCREMENT, FALSE);
1359
1361 }
1362
1363 if (FileObject->PrivateCacheMap == NULL)
1364 {
1365 PPRIVATE_CACHE_MAP PrivateMap;
1366
1367 /* Allocate the private cache map for this handle */
1368 if (SharedCacheMap->PrivateCacheMap.NodeTypeCode != 0)
1369 {
1371 }
1372 else
1373 {
1374 PrivateMap = &SharedCacheMap->PrivateCacheMap;
1375 }
1376
1377 if (PrivateMap == NULL)
1378 {
1379 /* If we also allocated the shared cache map for this file, kill it */
1380 if (Allocated)
1381 {
1382 RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks);
1383
1384 FileObject->SectionObjectPointer->SharedCacheMap = NULL;
1386 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap);
1387 }
1388
1391 }
1392
1393 /* Initialize it */
1394 RtlZeroMemory(PrivateMap, sizeof(PRIVATE_CACHE_MAP));
1395 PrivateMap->NodeTypeCode = NODE_TYPE_PRIVATE_MAP;
1396 PrivateMap->ReadAheadMask = PAGE_SIZE - 1;
1397 PrivateMap->FileObject = FileObject;
1399
1400 /* Link it to the file */
1401 KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock);
1402 InsertTailList(&SharedCacheMap->PrivateList, &PrivateMap->PrivateLinks);
1404
1405 FileObject->PrivateCacheMap = PrivateMap;
1406 SharedCacheMap->OpenCount++;
1407 }
1408
1410
1411 /* Create the section */
1412 if (Allocated)
1413 {
1415
1416 ASSERT(SharedCacheMap->Section == NULL);
1417
1419 &SharedCacheMap->Section,
1421 NULL,
1422 &SharedCacheMap->SectionSize,
1425 NULL,
1426 FileObject);
1427
1429
1430 if (!NT_SUCCESS(Status))
1431 {
1433 return Status;
1434 }
1435
1437
1439 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_CREATION;
1440
1441 if (SharedCacheMap->CreateEvent)
1442 {
1443 KeSetEvent(SharedCacheMap->CreateEvent, IO_NO_INCREMENT, FALSE);
1444 SharedCacheMap->CreateEvent = NULL;
1445 }
1446
1448 }
1449
1450 return STATUS_SUCCESS;
1451}
1452
1453/*
1454 * @implemented
1455 */
1457NTAPI
1459 IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
1460{
1461 PROS_SHARED_CACHE_MAP SharedCacheMap;
1462
1463 CCTRACE(CC_API_DEBUG, "SectionObjectPointers=%p\n", SectionObjectPointers);
1464
1465 if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
1466 {
1467 SharedCacheMap = SectionObjectPointers->SharedCacheMap;
1468 ASSERT(SharedCacheMap);
1469 return SharedCacheMap->FileObject;
1470 }
1471 return NULL;
1472}
1473
1474CODE_SEG("INIT")
1475VOID
1476NTAPI
1478 VOID)
1479{
1480 DPRINT("CcInitView()\n");
1481
1488 NULL,
1489 NULL,
1490 0,
1491 sizeof(INTERNAL_BCB),
1492 TAG_BCB,
1493 20);
1495 NULL,
1496 NULL,
1497 0,
1498 sizeof(ROS_SHARED_CACHE_MAP),
1500 20);
1502 NULL,
1503 NULL,
1504 0,
1505 sizeof(ROS_VACB),
1506 TAG_VACB,
1507 20);
1508
1510}
1511
1512#if DBG && defined(KDBG)
1513
1514#include <kdbg/kdb.h>
1515
1516BOOLEAN
1517ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[])
1518{
1519 PLIST_ENTRY ListEntry;
1520 UNICODE_STRING NoName = RTL_CONSTANT_STRING(L"No name for File");
1521
1522 KdbpPrint(" Usage Summary (in kb)\n");
1523 KdbpPrint("Shared\t\tMapped\tDirty\tName\n");
1524 /* No need to lock the spin lock here, we're in DBG */
1525 for (ListEntry = CcCleanSharedCacheMapList.Flink;
1526 ListEntry != &CcCleanSharedCacheMapList;
1527 ListEntry = ListEntry->Flink)
1528 {
1529 PLIST_ENTRY Vacbs;
1530 ULONG Mapped = 0, Dirty = 0;
1531 PROS_SHARED_CACHE_MAP SharedCacheMap;
1533 PWSTR Extra = L"";
1534
1535 SharedCacheMap = CONTAINING_RECORD(ListEntry, ROS_SHARED_CACHE_MAP, SharedCacheMapLinks);
1536
1537 /* Dirty size */
1538 Dirty = (SharedCacheMap->DirtyPages * PAGE_SIZE) / 1024;
1539
1540 /* First, count for all the associated VACB */
1541 for (Vacbs = SharedCacheMap->CacheMapVacbListHead.Flink;
1542 Vacbs != &SharedCacheMap->CacheMapVacbListHead;
1543 Vacbs = Vacbs->Flink)
1544 {
1545 Mapped += VACB_MAPPING_GRANULARITY / 1024;
1546 }
1547
1548 /* Setup name */
1549 if (SharedCacheMap->FileObject != NULL &&
1550 SharedCacheMap->FileObject->FileName.Length != 0)
1551 {
1552 FileName = &SharedCacheMap->FileObject->FileName;
1553 }
1554 else if (SharedCacheMap->FileObject != NULL &&
1555 SharedCacheMap->FileObject->FsContext != NULL &&
1556 ((PFSRTL_COMMON_FCB_HEADER)(SharedCacheMap->FileObject->FsContext))->NodeTypeCode == 0x0502 &&
1557 ((PFSRTL_COMMON_FCB_HEADER)(SharedCacheMap->FileObject->FsContext))->NodeByteSize == 0x1F8 &&
1558 ((PUNICODE_STRING)(((PUCHAR)SharedCacheMap->FileObject->FsContext) + 0x100))->Length != 0)
1559 {
1560 FileName = (PUNICODE_STRING)(((PUCHAR)SharedCacheMap->FileObject->FsContext) + 0x100);
1561 Extra = L" (FastFAT)";
1562 }
1563 else
1564 {
1565 FileName = &NoName;
1566 }
1567
1568 /* And print */
1569 KdbpPrint("%p\t%d\t%d\t%wZ%S\n", SharedCacheMap, Mapped, Dirty, FileName, Extra);
1570 }
1571
1572 return TRUE;
1573}
1574
1575BOOLEAN
1576ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[])
1577{
1578 KdbpPrint("CcTotalDirtyPages:\t%lu (%lu Kb)\n", CcTotalDirtyPages,
1579 (CcTotalDirtyPages * PAGE_SIZE) / 1024);
1580 KdbpPrint("CcDirtyPageThreshold:\t%lu (%lu Kb)\n", CcDirtyPageThreshold,
1581 (CcDirtyPageThreshold * PAGE_SIZE) / 1024);
1582 KdbpPrint("MmAvailablePages:\t%lu (%lu Kb)\n", MmAvailablePages,
1583 (MmAvailablePages * PAGE_SIZE) / 1024);
1584 KdbpPrint("MmThrottleTop:\t\t%lu (%lu Kb)\n", MmThrottleTop,
1585 (MmThrottleTop * PAGE_SIZE) / 1024);
1586 KdbpPrint("MmThrottleBottom:\t%lu (%lu Kb)\n", MmThrottleBottom,
1587 (MmThrottleBottom * PAGE_SIZE) / 1024);
1588 KdbpPrint("MmModifiedPageListHead.Total:\t%lu (%lu Kb)\n", MmModifiedPageListHead.Total,
1590
1592 {
1593 KdbpPrint("CcTotalDirtyPages above the threshold, writes should be throttled\n");
1594 }
1595 else if (CcTotalDirtyPages + 64 >= CcDirtyPageThreshold)
1596 {
1597 KdbpPrint("CcTotalDirtyPages within 64 (max charge) pages of the threshold, writes may be throttled\n");
1598 }
1599 else
1600 {
1601 KdbpPrint("CcTotalDirtyPages below the threshold, writes should not be throttled\n");
1602 }
1603
1604 return TRUE;
1605}
1606
1607#endif // DBG && defined(KDBG)
1608
1609/* EOF */
NTSTATUS NTAPI MmUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:2761
#define CODE_SEG(...)
void FreeList(LOCATIONITEM *pItems)
Definition: CSearchBar.cpp:95
static CC_FILE_SIZES FileSizes
ULONG_PTR PFN_NUMBER
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:1434
_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:33
#define Trace(x)
Definition: inflate.c:42
return Iosb
Definition: create.c:4403
#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:311
struct _FileName FileName
Definition: fatprocs.h:897
#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 KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
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
VOID KdbpPrint(_In_ PSTR Format, _In_ ...)
Prints the given string with printf-like formatting.
Definition: kdb_cli.c:3160
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
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define KernelMode
Definition: asm.h:38
_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
#define _Out_opt_
Definition: no_sal2.h:214
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
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:325
_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:117
static NTSTATUS CcRosDeleteFileCache(PFILE_OBJECT FileObject, PROS_SHARED_CACHE_MAP SharedCacheMap, PKIRQL OldIrql)
Definition: view.c:209
VOID CcRosMarkDirtyVacb(PROS_VACB Vacb)
Definition: view.c:667
NTSTATUS CcRosInitializeFileCache(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes, BOOLEAN PinAccess, PCACHE_MANAGER_CALLBACKS CallBacks, PVOID LazyWriterContext)
Definition: view.c:1286
LIST_ENTRY CcCleanSharedCacheMapList
Definition: view.c:60
static LIST_ENTRY VacbLruListHead
Definition: view.c:43
KSPIN_LOCK CcDeferredWriteSpinLock
Definition: view.c:59
NTSTATUS CcRosReleaseVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, PROS_VACB Vacb, BOOLEAN Dirty, BOOLEAN Mapped)
Definition: view.c:592
NTSTATUS CcRosFlushVacb(_In_ PROS_VACB Vacb, _Out_opt_ PIO_STATUS_BLOCK Iosb)
Definition: view.c:163
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointers, IN PLARGE_INTEGER FileOffset OPTIONAL, IN ULONG Length, OUT PIO_STATUS_BLOCK IoStatus)
Definition: view.c:1102
NTSTATUS CcRosRequestVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:1029
LIST_ENTRY CcDeferredWrites
Definition: view.c:58
NPAGED_LOOKASIDE_LIST iBcbLookasideList
Definition: view.c:45
BOOLEAN CcRosEnsureVacbResident(_In_ PROS_VACB Vacb, _In_ BOOLEAN Wait, _In_ BOOLEAN NoRead, _In_ ULONG Offset, _In_ ULONG Length)
Definition: view.c:932
PROS_VACB CcRosLookupVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset)
Definition: view.c:624
NTSTATUS CcRosReleaseFileCache(PFILE_OBJECT FileObject)
Definition: view.c:1230
PFILE_OBJECT NTAPI CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
Definition: view.c:1458
VOID NTAPI CcInitView(VOID)
Definition: view.c:1477
VOID CcRosTrimCache(_In_ ULONG Target, _Out_ PULONG NrFreed)
Definition: view.c:457
LIST_ENTRY DirtyVacbListHead
Definition: view.c:42
static NPAGED_LOOKASIDE_LIST SharedCacheMapLookasideList
Definition: view.c:46
NTSTATUS CcRosInternalFreeVacb(PROS_VACB Vacb)
Definition: view.c:1053
NTSTATUS CcRosGetVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:978
static NPAGED_LOOKASIDE_LIST VacbLookasideList
Definition: view.c:47
BOOLEAN CcRosFreeOneUnusedVacb(VOID)
Definition: view.c:738
ULONG CcDirtyPageThreshold
Definition: view.c:56
ULONG CcTotalDirtyPages
Definition: view.c:57
VOID CcRosUnmarkDirtyVacb(PROS_VACB Vacb, BOOLEAN LockViews)
Definition: view.c:703
NTSTATUS CcRosFlushDirtyPages(ULONG Target, PULONG Count, BOOLEAN Wait, BOOLEAN CalledFromLazy)
Definition: view.c:309
static NTSTATUS CcRosCreateVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:798
NTSTATUS NTAPI FsRtlAcquireFileForCcFlushEx(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1698
VOID NTAPI FsRtlReleaseFileForCcFlush(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1771
#define CcRosVacbIncRefCount(vacb)
Definition: cc.h:496
FORCEINLINE BOOLEAN IsPointInRange(_In_ LONGLONG Offset1, _In_ LONGLONG Length1, _In_ LONGLONG Point)
Definition: cc.h:462
#define WRITEBEHIND_DISABLED
Definition: cc.h:203
#define CcRosVacbGetRefCount(vacb)
Definition: cc.h:511
#define NODE_TYPE_PRIVATE_MAP
Definition: cc.h:288
#define CC_API_DEBUG
Definition: cc.h:11
#define SHARED_CACHE_MAP_IN_CREATION
Definition: cc.h:204
#define CCTRACE(x, fmt,...)
Definition: cc.h:36
#define SHARED_CACHE_MAP_IN_LAZYWRITE
Definition: cc.h:205
FORCEINLINE ULONG CcRosVacbDecRefCount(PROS_VACB vacb)
Definition: cc.h:499
#define NODE_TYPE_SHARED_MAP
Definition: cc.h:289
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:1313
BOOLEAN NTAPI MmIsDataSectionResident(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length)
Definition: section.c:4932
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:5051
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:4974
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:4465
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
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:4625
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
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:247
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PFN_NUMBER Total
Definition: mm.h:450
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
KGUARDED_MUTEX FlushCacheLock
Definition: cc.h:196
Definition: cc.h:208
ULONG MappedCount
Definition: cc.h:215
LIST_ENTRY CacheMapVacbListEntry
Definition: cc.h:217
BOOLEAN Dirty
Definition: cc.h:212
PROS_SHARED_CACHE_MAP SharedCacheMap
Definition: cc.h:227
LARGE_INTEGER FileOffset
Definition: cc.h:223
PVOID BaseAddress
Definition: cc.h:210
volatile ULONG ReferenceCount
Definition: cc.h:225
BOOLEAN PageOut
Definition: cc.h:214
LIST_ENTRY DirtyVacbListEntry
Definition: cc.h:219
LIST_ENTRY VacbLruListEntry
Definition: cc.h:221
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:166
#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
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
#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:3304