ReactOS 0.4.15-dev-5884-gab5aff5
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
80 ASSERT(!(Refs == 0 && vacb->Dirty));
81 if (vacb->SharedCacheMap->Trace)
82 {
83 DbgPrint("(%s:%i) VACB %p --RefCount=%lu, Dirty %u, PageOut %lu\n",
84 file, line, vacb, Refs, vacb->Dirty, vacb->PageOut);
85 }
86
87 if (Refs == 0)
88 {
90 }
91
92 return Refs;
93}
94ULONG CcRosVacbGetRefCount_(PROS_VACB vacb, PCSTR file, INT line)
95{
96 ULONG Refs;
97
99 if (vacb->SharedCacheMap->Trace)
100 {
101 DbgPrint("(%s:%i) VACB %p ==RefCount=%lu, Dirty %u, PageOut %lu\n",
102 file, line, vacb, Refs, vacb->Dirty, vacb->PageOut);
103 }
104
105 return Refs;
106}
107#endif
108
109
110/* FUNCTIONS *****************************************************************/
111
112VOID
114 PROS_SHARED_CACHE_MAP SharedCacheMap,
115 BOOLEAN Trace )
116{
117#if DBG
118 KIRQL oldirql;
119 PLIST_ENTRY current_entry;
121
122 if (!SharedCacheMap)
123 return;
124
125 SharedCacheMap->Trace = Trace;
126
127 if (Trace)
128 {
129 DPRINT1("Enabling Tracing for CacheMap 0x%p:\n", SharedCacheMap);
130
133
134 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
135 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
136 {
137 current = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry);
138 current_entry = current_entry->Flink;
139
140 DPRINT1(" VACB 0x%p enabled, RefCount %lu, Dirty %u, PageOut %lu, BaseAddress %p, FileOffset %I64d\n",
141 current, current->ReferenceCount, current->Dirty, current->PageOut, current->BaseAddress, current->FileOffset.QuadPart);
142 }
143
146 }
147 else
148 {
149 DPRINT1("Disabling Tracing for CacheMap 0x%p:\n", SharedCacheMap);
150 }
151
152#else
153 UNREFERENCED_PARAMETER(SharedCacheMap);
155#endif
156}
157
160 _In_ PROS_VACB Vacb,
162{
164 BOOLEAN HaveLock = FALSE;
165 PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
166
168
169 /* Lock for flush, if we are not already the top-level */
171 {
172 Status = FsRtlAcquireFileForCcFlushEx(Vacb->SharedCacheMap->FileObject);
173 if (!NT_SUCCESS(Status))
174 goto quit;
175 HaveLock = TRUE;
176 }
177
178 Status = MmFlushSegment(SharedCacheMap->FileObject->SectionObjectPointer,
179 &Vacb->FileOffset,
181 Iosb);
182
183 if (HaveLock)
184 {
185 FsRtlReleaseFileForCcFlush(Vacb->SharedCacheMap->FileObject);
186 }
187
188quit:
189 if (!NT_SUCCESS(Status))
190 CcRosMarkDirtyVacb(Vacb);
191 else
192 {
193 /* Update VDL */
194 if (SharedCacheMap->ValidDataLength.QuadPart < (Vacb->FileOffset.QuadPart + VACB_MAPPING_GRANULARITY))
195 {
196 SharedCacheMap->ValidDataLength.QuadPart = Vacb->FileOffset.QuadPart + VACB_MAPPING_GRANULARITY;
197 }
198 }
199
200 return Status;
201}
202
203static
207 PROS_SHARED_CACHE_MAP SharedCacheMap,
209/*
210 * FUNCTION: Releases the shared cache map associated with a file object
211 */
212{
213 PLIST_ENTRY current_entry;
214
215 ASSERT(SharedCacheMap);
216 ASSERT(SharedCacheMap == FileObject->SectionObjectPointer->SharedCacheMap);
217 ASSERT(SharedCacheMap->OpenCount == 0);
218
219 /* Remove all VACBs from the global lists */
221 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
222 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
223 {
224 PROS_VACB Vacb = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry);
225
228
229 if (Vacb->Dirty)
230 {
232 /* Mark it as dirty again so we know that we have to flush before freeing it */
233 Vacb->Dirty = TRUE;
234 }
235
236 current_entry = current_entry->Flink;
237 }
238
239 /* Make sure there is no trace anymore of this map */
240 FileObject->SectionObjectPointer->SharedCacheMap = NULL;
241 RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks);
242
245
246 /* Now that we're out of the locks, free everything for real */
247 while (!IsListEmpty(&SharedCacheMap->CacheMapVacbListHead))
248 {
249 PROS_VACB Vacb = CONTAINING_RECORD(RemoveHeadList(&SharedCacheMap->CacheMapVacbListHead), ROS_VACB, CacheMapVacbListEntry);
250 ULONG RefCount;
251
253
254 /* Flush to disk, if needed */
255 if (Vacb->Dirty)
256 {
259
260 Status = MmFlushSegment(FileObject->SectionObjectPointer, &Vacb->FileOffset, VACB_MAPPING_GRANULARITY, &Iosb);
261 if (!NT_SUCCESS(Status))
262 {
263 /* Complain. There's not much we can do */
264 DPRINT1("Failed to flush VACB to disk while deleting the cache entry. Status: 0x%08x\n", Status);
265 }
266 Vacb->Dirty = FALSE;
267 }
268
269 RefCount = CcRosVacbDecRefCount(Vacb);
270#if DBG // CORE-14578
271 if (RefCount != 0)
272 {
273 DPRINT1("Leaking VACB %p attached to %p (%I64d)\n", Vacb, FileObject, Vacb->FileOffset.QuadPart);
274 DPRINT1("There are: %d references left\n", RefCount);
275 DPRINT1("Map: %d\n", Vacb->MappedCount);
276 DPRINT1("Dirty: %d\n", Vacb->Dirty);
277 if (FileObject->FileName.Length != 0)
278 {
279 DPRINT1("File was: %wZ\n", &FileObject->FileName);
280 }
281 else
282 {
283 DPRINT1("No name for the file\n");
284 }
285 }
286#else
287 (void)RefCount;
288#endif
289 }
290
291 /* Release the references we own */
292 if(SharedCacheMap->Section)
293 ObDereferenceObject(SharedCacheMap->Section);
294 ObDereferenceObject(SharedCacheMap->FileObject);
295
296 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap);
297
298 /* Acquire the lock again for our caller */
300
301 return STATUS_SUCCESS;
302}
303
309 BOOLEAN CalledFromLazy)
310{
311 PLIST_ENTRY current_entry;
314 BOOLEAN FlushAll = (Target == MAXULONG);
315
316 DPRINT("CcRosFlushDirtyPages(Target %lu)\n", Target);
317
318 (*Count) = 0;
319
322
323 current_entry = DirtyVacbListHead.Flink;
324 if (current_entry == &DirtyVacbListHead)
325 {
326 DPRINT("No Dirty pages\n");
327 }
328
329 while (((current_entry != &DirtyVacbListHead) && (Target > 0)) || FlushAll)
330 {
331 PROS_SHARED_CACHE_MAP SharedCacheMap;
334
335 if (current_entry == &DirtyVacbListHead)
336 {
337 ASSERT(FlushAll);
339 break;
340 current_entry = DirtyVacbListHead.Flink;
341 }
342
343 current = CONTAINING_RECORD(current_entry,
344 ROS_VACB,
345 DirtyVacbListEntry);
346 current_entry = current_entry->Flink;
347
349
350 SharedCacheMap = current->SharedCacheMap;
351
352 /* When performing lazy write, don't handle temporary files */
353 if (CalledFromLazy && BooleanFlagOn(SharedCacheMap->FileObject->Flags, FO_TEMPORARY_FILE))
354 {
356 continue;
357 }
358
359 /* Don't attempt to lazy write the files that asked not to */
360 if (CalledFromLazy && BooleanFlagOn(SharedCacheMap->Flags, WRITEBEHIND_DISABLED))
361 {
363 continue;
364 }
365
366 ASSERT(current->Dirty);
367
368 /* Do not lazy-write the same file concurrently. Fastfat ASSERTS on that */
369 if (SharedCacheMap->Flags & SHARED_CACHE_MAP_IN_LAZYWRITE)
370 {
372 continue;
373 }
374
375 SharedCacheMap->Flags |= SHARED_CACHE_MAP_IN_LAZYWRITE;
376
377 /* Keep a ref on the shared cache map */
378 SharedCacheMap->OpenCount++;
379
381
382 Locked = SharedCacheMap->Callbacks->AcquireForLazyWrite(SharedCacheMap->LazyWriteContext, Wait);
383 if (!Locked)
384 {
385 DPRINT("Not locked!");
386 ASSERT(!Wait);
389 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;
390
391 if (--SharedCacheMap->OpenCount == 0)
392 CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);
393
394 continue;
395 }
396
399
400 SharedCacheMap->Callbacks->ReleaseFromLazyWrite(SharedCacheMap->LazyWriteContext);
401
402 /* We release the VACB before acquiring the lock again, because
403 * CcRosVacbDecRefCount might free the VACB, as CcRosFlushVacb dropped a
404 * Refcount. Freeing must be done outside of the lock.
405 * The refcount is decremented atomically. So this is OK. */
408
409 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;
410
411 if (--SharedCacheMap->OpenCount == 0)
412 CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);
413
416 {
417 DPRINT1("CC: Failed to flush VACB.\n");
418 }
419 else
420 {
421 ULONG PagesFreed;
422
423 /* How many pages did we free? */
424 PagesFreed = Iosb.Information / PAGE_SIZE;
425 (*Count) += PagesFreed;
426
427 if (!Wait)
428 {
429 /* Make sure we don't overflow target! */
430 if (Target < PagesFreed)
431 {
432 /* If we would have, jump to zero directly */
433 Target = 0;
434 }
435 else
436 {
437 Target -= PagesFreed;
438 }
439 }
440 }
441
442 current_entry = DirtyVacbListHead.Flink;
443 }
444
447
448 DPRINT("CcRosFlushDirtyPages() finished\n");
449 return STATUS_SUCCESS;
450}
451
454 PROS_SHARED_CACHE_MAP SharedCacheMap,
455 PROS_VACB Vacb,
456 BOOLEAN Dirty,
457 BOOLEAN Mapped)
458{
459 ULONG Refs;
460 ASSERT(SharedCacheMap);
461
462 DPRINT("CcRosReleaseVacb(SharedCacheMap 0x%p, Vacb 0x%p)\n", SharedCacheMap, Vacb);
463
464 if (Dirty && !Vacb->Dirty)
465 {
466 CcRosMarkDirtyVacb(Vacb);
467 }
468
469 if (Mapped)
470 {
471 if (InterlockedIncrement((PLONG)&Vacb->MappedCount) == 1)
472 {
474 }
475 }
476
477 Refs = CcRosVacbDecRefCount(Vacb);
478 ASSERT(Refs > 0);
479
480 return STATUS_SUCCESS;
481}
482
483/* Returns with VACB Lock Held! */
486 PROS_SHARED_CACHE_MAP SharedCacheMap,
488{
489 PLIST_ENTRY current_entry;
491 KIRQL oldIrql;
492
493 ASSERT(SharedCacheMap);
494
495 DPRINT("CcRosLookupVacb(SharedCacheMap 0x%p, FileOffset %I64u)\n",
496 SharedCacheMap, FileOffset);
497
500
501 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
502 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
503 {
504 current = CONTAINING_RECORD(current_entry,
505 ROS_VACB,
506 CacheMapVacbListEntry);
507 if (IsPointInRange(current->FileOffset.QuadPart,
509 FileOffset))
510 {
514 return current;
515 }
516 if (current->FileOffset.QuadPart > FileOffset)
517 break;
518 current_entry = current_entry->Flink;
519 }
520
523
524 return NULL;
525}
526
527VOID
529 PROS_VACB Vacb)
530{
531 KIRQL oldIrql;
532 PROS_SHARED_CACHE_MAP SharedCacheMap;
533
534 SharedCacheMap = Vacb->SharedCacheMap;
535
538
539 ASSERT(!Vacb->Dirty);
540
542 /* FIXME: There is no reason to account for the whole VACB. */
546
547 /* Move to the tail of the LRU list */
550
551 Vacb->Dirty = TRUE;
552
554
555 /* Schedule a lazy writer run to now that we have dirty VACB */
557 {
559 }
561}
562
563VOID
565 PROS_VACB Vacb,
566 BOOLEAN LockViews)
567{
568 KIRQL oldIrql;
569 PROS_SHARED_CACHE_MAP SharedCacheMap;
570
571 SharedCacheMap = Vacb->SharedCacheMap;
572
573 if (LockViews)
574 {
577 }
578
579 ASSERT(Vacb->Dirty);
580
581 Vacb->Dirty = FALSE;
582
585
588
590
591 if (LockViews)
592 {
595 }
596}
597
598static
602{
603 ULONG cFreed;
604 BOOLEAN Freed;
605 KIRQL oldIrql;
607 LIST_ENTRY FreeList;
608 PLIST_ENTRY current_entry;
609
610 cFreed = 0;
611 Freed = FALSE;
612 InitializeListHead(&FreeList);
613
615
616 /* Browse all the available VACB */
617 current_entry = VacbLruListHead.Flink;
618 while (current_entry != &VacbLruListHead)
619 {
620 ULONG Refs;
621
622 current = CONTAINING_RECORD(current_entry,
623 ROS_VACB,
624 VacbLruListEntry);
625 current_entry = current_entry->Flink;
626
627 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
628
629 /* Only deal with unused VACB, we will free them */
631 if (Refs < 2)
632 {
633 ASSERT(!current->Dirty);
634 ASSERT(!current->MappedCount);
635 ASSERT(Refs == 1);
636
637 /* Reset and move to free list */
638 RemoveEntryList(&current->CacheMapVacbListEntry);
639 RemoveEntryList(&current->VacbLruListEntry);
640 InitializeListHead(&current->VacbLruListEntry);
641 InsertHeadList(&FreeList, &current->CacheMapVacbListEntry);
642 }
643
644 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
645
646 }
647
649
650 /* And now, free any of the found VACB, that'll free memory! */
651 while (!IsListEmpty(&FreeList))
652 {
653 ULONG Refs;
654
655 current_entry = RemoveHeadList(&FreeList);
656 current = CONTAINING_RECORD(current_entry,
657 ROS_VACB,
658 CacheMapVacbListEntry);
659 InitializeListHead(&current->CacheMapVacbListEntry);
661 ASSERT(Refs == 0);
662 ++cFreed;
663 }
664
665 /* If we freed at least one VACB, return success */
666 if (cFreed != 0)
667 {
668 Freed = TRUE;
669 }
670
671 /* If caller asked for free count, return it */
672 if (Count != NULL)
673 {
674 *Count = cFreed;
675 }
676
677 return Freed;
678}
679
680static
683 PROS_SHARED_CACHE_MAP SharedCacheMap,
685 PROS_VACB *Vacb)
686{
688 PROS_VACB previous;
689 PLIST_ENTRY current_entry;
691 KIRQL oldIrql;
692 ULONG Refs;
693 BOOLEAN Retried;
695
696 ASSERT(SharedCacheMap);
697
698 DPRINT("CcRosCreateVacb()\n");
699
700 current = ExAllocateFromNPagedLookasideList(&VacbLookasideList);
701 current->BaseAddress = NULL;
702 current->Dirty = FALSE;
703 current->PageOut = FALSE;
704 current->FileOffset.QuadPart = ROUND_DOWN(FileOffset, VACB_MAPPING_GRANULARITY);
705 current->SharedCacheMap = SharedCacheMap;
706 current->MappedCount = 0;
707 current->ReferenceCount = 0;
708 InitializeListHead(&current->CacheMapVacbListEntry);
709 InitializeListHead(&current->DirtyVacbListEntry);
710 InitializeListHead(&current->VacbLruListEntry);
711
713
714 Retried = FALSE;
715Retry:
716 /* Map VACB in system space */
717 Status = MmMapViewInSystemSpaceEx(SharedCacheMap->Section, &current->BaseAddress, &ViewSize, &current->FileOffset, 0);
718
719 if (!NT_SUCCESS(Status))
720 {
721 ULONG Freed;
722 /* If no space left, try to prune unused VACB
723 * to recover space to map our VACB
724 * If it succeed, retry to map, otherwise
725 * just fail.
726 */
727 if (!Retried && CcRosFreeUnusedVacb(&Freed))
728 {
729 DPRINT("Prunned %d VACB, trying again\n", Freed);
730 Retried = TRUE;
731 goto Retry;
732 }
733
734 ExFreeToNPagedLookasideList(&VacbLookasideList, current);
735 return Status;
736 }
737
738#if DBG
739 if (SharedCacheMap->Trace)
740 {
741 DPRINT1("CacheMap 0x%p: new VACB: 0x%p, file offset %I64d, BaseAddress %p\n",
742 SharedCacheMap, current, current->FileOffset.QuadPart, current->BaseAddress);
743 }
744#endif
745
747
748 *Vacb = current;
749 /* There is window between the call to CcRosLookupVacb
750 * and CcRosCreateVacb. We must check if a VACB for the
751 * file offset exist. If there is a VACB, we release
752 * our newly created VACB and return the existing one.
753 */
755 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
756 previous = NULL;
757 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
758 {
759 current = CONTAINING_RECORD(current_entry,
760 ROS_VACB,
761 CacheMapVacbListEntry);
762 if (IsPointInRange(current->FileOffset.QuadPart,
764 FileOffset))
765 {
768#if DBG
769 if (SharedCacheMap->Trace)
770 {
771 DPRINT1("CacheMap 0x%p: deleting newly created VACB 0x%p ( found existing one 0x%p )\n",
772 SharedCacheMap,
773 (*Vacb),
774 current);
775 }
776#endif
778
779 Refs = CcRosVacbDecRefCount(*Vacb);
780 ASSERT(Refs == 0);
781
782 *Vacb = current;
783 return STATUS_SUCCESS;
784 }
785 if (current->FileOffset.QuadPart < FileOffset)
786 {
787 ASSERT(previous == NULL ||
788 previous->FileOffset.QuadPart < current->FileOffset.QuadPart);
789 previous = current;
790 }
791 if (current->FileOffset.QuadPart > FileOffset)
792 break;
793 current_entry = current_entry->Flink;
794 }
795 /* There was no existing VACB. */
796 current = *Vacb;
797 if (previous)
798 {
799 InsertHeadList(&previous->CacheMapVacbListEntry, &current->CacheMapVacbListEntry);
800 }
801 else
802 {
803 InsertHeadList(&SharedCacheMap->CacheMapVacbListHead, &current->CacheMapVacbListEntry);
804 }
806 InsertTailList(&VacbLruListHead, &current->VacbLruListEntry);
808
809 /* Reference it to allow release */
811
812 return Status;
813}
814
817 _In_ PROS_VACB Vacb,
819 _In_ BOOLEAN NoRead,
822)
823{
825
827
828#if 0
829 if ((Vacb->FileOffset.QuadPart + Offset) > Vacb->SharedCacheMap->SectionSize.QuadPart)
830 {
831 DPRINT1("Vacb read beyond the file size!\n");
832 return FALSE;
833 }
834#endif
835
836 BaseAddress = (PVOID)((ULONG_PTR)Vacb->BaseAddress + Offset);
837
838 /* Check if the pages are resident */
840 {
841 if (!Wait)
842 {
843 return FALSE;
844 }
845
846 if (!NoRead)
847 {
848 PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
849 NTSTATUS Status = MmMakeDataSectionResident(SharedCacheMap->FileObject->SectionObjectPointer,
850 Vacb->FileOffset.QuadPart + Offset,
851 Length,
852 &SharedCacheMap->ValidDataLength);
853 if (!NT_SUCCESS(Status))
855 }
856 }
857
858 return TRUE;
859}
860
861
864 PROS_SHARED_CACHE_MAP SharedCacheMap,
866 PROS_VACB *Vacb)
867{
870 ULONG Refs;
872
873 ASSERT(SharedCacheMap);
874
875 DPRINT("CcRosGetVacb()\n");
876
877 /*
878 * Look for a VACB already mapping the same data.
879 */
880 current = CcRosLookupVacb(SharedCacheMap, FileOffset);
881 if (current == NULL)
882 {
883 /*
884 * Otherwise create a new VACB.
885 */
886 Status = CcRosCreateVacb(SharedCacheMap, FileOffset, &current);
887 if (!NT_SUCCESS(Status))
888 {
889 return Status;
890 }
891 }
892
894
896
897 /* Move to the tail of the LRU list */
898 RemoveEntryList(&current->VacbLruListEntry);
899 InsertTailList(&VacbLruListHead, &current->VacbLruListEntry);
900
902
903 /*
904 * Return the VACB to the caller.
905 */
906 *Vacb = current;
907
908 ASSERT(Refs > 1);
909
910 return STATUS_SUCCESS;
911}
912
915 PROS_SHARED_CACHE_MAP SharedCacheMap,
917 PROS_VACB *Vacb)
918/*
919 * FUNCTION: Request a page mapping for a shared cache map
920 */
921{
922
923 ASSERT(SharedCacheMap);
924
926 {
927 DPRINT1("Bad fileoffset %I64x should be multiple of %x",
929 KeBugCheck(CACHE_MANAGER);
930 }
931
932 return CcRosGetVacb(SharedCacheMap,
934 Vacb);
935}
936
939 PROS_VACB Vacb)
940/*
941 * FUNCTION: Releases a VACB associated with a shared cache map
942 */
943{
945
946 DPRINT("Freeing VACB 0x%p\n", Vacb);
947#if DBG
948 if (Vacb->SharedCacheMap->Trace)
949 {
950 DPRINT1("CacheMap 0x%p: deleting VACB: 0x%p\n", Vacb->SharedCacheMap, Vacb);
951 }
952#endif
953
954 if (Vacb->ReferenceCount != 0)
955 {
956 DPRINT1("Invalid free: %ld\n", Vacb->ReferenceCount);
957 if (Vacb->SharedCacheMap->FileObject && Vacb->SharedCacheMap->FileObject->FileName.Length)
958 {
959 DPRINT1("For file: %wZ\n", &Vacb->SharedCacheMap->FileObject->FileName);
960 }
961 }
962
963 ASSERT(Vacb->ReferenceCount == 0);
967
968 /* Delete the mapping */
970 if (!NT_SUCCESS(Status))
971 {
972 DPRINT1("Failed to unmap VACB from System address space! Status 0x%08X\n", Status);
973 ASSERT(FALSE);
974 /* Proceed with the deĺetion anyway */
975 }
976
977 RtlFillMemory(Vacb, sizeof(*Vacb), 0xfd);
978 ExFreeToNPagedLookasideList(&VacbLookasideList, Vacb);
979 return STATUS_SUCCESS;
980}
981
982/*
983 * @implemented
984 */
985VOID
986NTAPI
988 IN PSECTION_OBJECT_POINTERS SectionObjectPointers,
992{
993 PROS_SHARED_CACHE_MAP SharedCacheMap;
994 LONGLONG FlushStart, FlushEnd;
996
997 CCTRACE(CC_API_DEBUG, "SectionObjectPointers=%p FileOffset=0x%I64X Length=%lu\n",
998 SectionObjectPointers, FileOffset ? FileOffset->QuadPart : 0LL, Length);
999
1000 if (!SectionObjectPointers)
1001 {
1003 goto quit;
1004 }
1005
1006 if (!SectionObjectPointers->SharedCacheMap)
1007 {
1008 /* Forward this to Mm */
1009 MmFlushSegment(SectionObjectPointers, FileOffset, Length, IoStatus);
1010 return;
1011 }
1012
1013 SharedCacheMap = SectionObjectPointers->SharedCacheMap;
1014 ASSERT(SharedCacheMap);
1015 if (FileOffset)
1016 {
1017 FlushStart = FileOffset->QuadPart;
1018 Status = RtlLongLongAdd(FlushStart, Length, &FlushEnd);
1019 if (!NT_SUCCESS(Status))
1020 goto quit;
1021 }
1022 else
1023 {
1024 FlushStart = 0;
1025 FlushEnd = SharedCacheMap->FileSize.QuadPart;
1026 }
1027
1029 if (IoStatus)
1030 {
1031 IoStatus->Information = 0;
1032 }
1033
1034 /*
1035 * We flush the VACBs that we find here.
1036 * If there is no (dirty) VACB, it doesn't mean that there is no data to flush, so we call Mm to be sure.
1037 * This is suboptimal, but this is due to the lack of granularity of how we track dirty cache data
1038 */
1039 while (FlushStart < FlushEnd)
1040 {
1041 BOOLEAN DirtyVacb = FALSE;
1042 PROS_VACB vacb = CcRosLookupVacb(SharedCacheMap, FlushStart);
1043
1044 if (vacb != NULL)
1045 {
1046 if (vacb->Dirty)
1047 {
1048 IO_STATUS_BLOCK VacbIosb = { 0 };
1049 Status = CcRosFlushVacb(vacb, &VacbIosb);
1050 if (!NT_SUCCESS(Status))
1051 {
1052 goto quit;
1053 }
1054 DirtyVacb = TRUE;
1055
1056 if (IoStatus)
1057 IoStatus->Information += VacbIosb.Information;
1058 }
1059
1060 CcRosReleaseVacb(SharedCacheMap, vacb, FALSE, FALSE);
1061 }
1062
1063 if (!DirtyVacb)
1064 {
1065 IO_STATUS_BLOCK MmIosb;
1066 LARGE_INTEGER MmOffset;
1067
1068 MmOffset.QuadPart = FlushStart;
1069
1070 if (FlushEnd - (FlushEnd % VACB_MAPPING_GRANULARITY) <= FlushStart)
1071 {
1072 /* The whole range fits within a VACB chunk. */
1073 Status = MmFlushSegment(SectionObjectPointers, &MmOffset, FlushEnd - FlushStart, &MmIosb);
1074 }
1075 else
1076 {
1077 ULONG MmLength = VACB_MAPPING_GRANULARITY - (FlushStart % VACB_MAPPING_GRANULARITY);
1078 Status = MmFlushSegment(SectionObjectPointers, &MmOffset, MmLength, &MmIosb);
1079 }
1080
1081 if (!NT_SUCCESS(Status))
1082 goto quit;
1083
1084 if (IoStatus)
1085 IoStatus->Information += MmIosb.Information;
1086
1087 /* Update VDL */
1088 if (SharedCacheMap->ValidDataLength.QuadPart < FlushEnd)
1089 SharedCacheMap->ValidDataLength.QuadPart = FlushEnd;
1090 }
1091
1092 if (!NT_SUCCESS(RtlLongLongAdd(FlushStart, VACB_MAPPING_GRANULARITY, &FlushStart)))
1093 {
1094 /* We're at the end of file ! */
1095 break;
1096 }
1097
1098 /* Round down to next VACB start now */
1099 FlushStart -= FlushStart % VACB_MAPPING_GRANULARITY;
1100 }
1101
1102quit:
1103 if (IoStatus)
1104 {
1105 IoStatus->Status = Status;
1106 }
1107}
1108
1112/*
1113 * FUNCTION: Called by the file system when a handle to a file object
1114 * has been closed.
1115 */
1116{
1117 KIRQL OldIrql;
1118 PPRIVATE_CACHE_MAP PrivateMap;
1119 PROS_SHARED_CACHE_MAP SharedCacheMap;
1120
1122
1123 if (FileObject->SectionObjectPointer->SharedCacheMap != NULL)
1124 {
1125 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
1126
1127 /* Closing the handle, so kill the private cache map
1128 * Before you event try to remove it from FO, always
1129 * lock the master lock, to be sure not to race
1130 * with a potential read ahead ongoing!
1131 */
1132 PrivateMap = FileObject->PrivateCacheMap;
1133 FileObject->PrivateCacheMap = NULL;
1134
1135 if (PrivateMap != NULL)
1136 {
1137 /* Remove it from the file */
1138 KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock);
1139 RemoveEntryList(&PrivateMap->PrivateLinks);
1141
1142 /* And free it. */
1143 if (PrivateMap != &SharedCacheMap->PrivateCacheMap)
1144 {
1146 }
1147 else
1148 {
1149 PrivateMap->NodeTypeCode = 0;
1150 }
1151
1152 ASSERT(SharedCacheMap->OpenCount > 0);
1153
1154 SharedCacheMap->OpenCount--;
1155 if (SharedCacheMap->OpenCount == 0)
1156 {
1157 CcRosDeleteFileCache(FileObject, SharedCacheMap, &OldIrql);
1158 }
1159 }
1160 }
1162 return STATUS_SUCCESS;
1163}
1164
1169 BOOLEAN PinAccess,
1170 PCACHE_MANAGER_CALLBACKS CallBacks,
1171 PVOID LazyWriterContext)
1172/*
1173 * FUNCTION: Initializes a shared cache map for a file object
1174 */
1175{
1176 KIRQL OldIrql;
1178 PROS_SHARED_CACHE_MAP SharedCacheMap;
1179
1180 DPRINT("CcRosInitializeFileCache(FileObject 0x%p)\n", FileObject);
1181
1183
1184 Allocated = FALSE;
1185 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
1186 if (SharedCacheMap == NULL)
1187 {
1188 Allocated = TRUE;
1189 SharedCacheMap = ExAllocateFromNPagedLookasideList(&SharedCacheMapLookasideList);
1190 if (SharedCacheMap == NULL)
1191 {
1193 }
1194 RtlZeroMemory(SharedCacheMap, sizeof(*SharedCacheMap));
1195 SharedCacheMap->NodeTypeCode = NODE_TYPE_SHARED_MAP;
1196 SharedCacheMap->NodeByteSize = sizeof(*SharedCacheMap);
1197 SharedCacheMap->FileObject = FileObject;
1198 SharedCacheMap->Callbacks = CallBacks;
1199 SharedCacheMap->LazyWriteContext = LazyWriterContext;
1200 SharedCacheMap->SectionSize = FileSizes->AllocationSize;
1201 SharedCacheMap->FileSize = FileSizes->FileSize;
1202 SharedCacheMap->ValidDataLength = FileSizes->ValidDataLength;
1203 SharedCacheMap->PinAccess = PinAccess;
1204 SharedCacheMap->DirtyPageThreshold = 0;
1205 SharedCacheMap->DirtyPages = 0;
1206 InitializeListHead(&SharedCacheMap->PrivateList);
1207 KeInitializeSpinLock(&SharedCacheMap->CacheMapLock);
1208 InitializeListHead(&SharedCacheMap->CacheMapVacbListHead);
1209 InitializeListHead(&SharedCacheMap->BcbList);
1210
1211 SharedCacheMap->Flags = SHARED_CACHE_MAP_IN_CREATION;
1212
1215 NULL,
1216 KernelMode);
1217
1218 FileObject->SectionObjectPointer->SharedCacheMap = SharedCacheMap;
1219
1220 //CcRosTraceCacheMap(SharedCacheMap, TRUE);
1221 }
1222 else if (SharedCacheMap->Flags & SHARED_CACHE_MAP_IN_CREATION)
1223 {
1224 /* The shared cache map is being created somewhere else. Wait for that to happen */
1225 KEVENT Waiter;
1226 PKEVENT PreviousWaiter = SharedCacheMap->CreateEvent;
1227
1229 SharedCacheMap->CreateEvent = &Waiter;
1230
1232
1234
1235 if (PreviousWaiter)
1236 KeSetEvent(PreviousWaiter, IO_NO_INCREMENT, FALSE);
1237
1239 }
1240
1241 if (FileObject->PrivateCacheMap == NULL)
1242 {
1243 PPRIVATE_CACHE_MAP PrivateMap;
1244
1245 /* Allocate the private cache map for this handle */
1246 if (SharedCacheMap->PrivateCacheMap.NodeTypeCode != 0)
1247 {
1249 }
1250 else
1251 {
1252 PrivateMap = &SharedCacheMap->PrivateCacheMap;
1253 }
1254
1255 if (PrivateMap == NULL)
1256 {
1257 /* If we also allocated the shared cache map for this file, kill it */
1258 if (Allocated)
1259 {
1260 RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks);
1261
1262 FileObject->SectionObjectPointer->SharedCacheMap = NULL;
1264 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap);
1265 }
1266
1269 }
1270
1271 /* Initialize it */
1272 RtlZeroMemory(PrivateMap, sizeof(PRIVATE_CACHE_MAP));
1273 PrivateMap->NodeTypeCode = NODE_TYPE_PRIVATE_MAP;
1274 PrivateMap->ReadAheadMask = PAGE_SIZE - 1;
1275 PrivateMap->FileObject = FileObject;
1277
1278 /* Link it to the file */
1279 KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock);
1280 InsertTailList(&SharedCacheMap->PrivateList, &PrivateMap->PrivateLinks);
1282
1283 FileObject->PrivateCacheMap = PrivateMap;
1284 SharedCacheMap->OpenCount++;
1285 }
1286
1288
1289 /* Create the section */
1290 if (Allocated)
1291 {
1293
1294 ASSERT(SharedCacheMap->Section == NULL);
1295
1297 &SharedCacheMap->Section,
1299 NULL,
1300 &SharedCacheMap->SectionSize,
1303 NULL,
1304 FileObject);
1305
1307
1308 if (!NT_SUCCESS(Status))
1309 {
1311 return Status;
1312 }
1313
1315
1317 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_CREATION;
1318
1319 if (SharedCacheMap->CreateEvent)
1320 {
1321 KeSetEvent(SharedCacheMap->CreateEvent, IO_NO_INCREMENT, FALSE);
1322 SharedCacheMap->CreateEvent = NULL;
1323 }
1324
1326 }
1327
1328 return STATUS_SUCCESS;
1329}
1330
1331/*
1332 * @implemented
1333 */
1335NTAPI
1337 IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
1338{
1339 PROS_SHARED_CACHE_MAP SharedCacheMap;
1340
1341 CCTRACE(CC_API_DEBUG, "SectionObjectPointers=%p\n", SectionObjectPointers);
1342
1343 if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
1344 {
1345 SharedCacheMap = SectionObjectPointers->SharedCacheMap;
1346 ASSERT(SharedCacheMap);
1347 return SharedCacheMap->FileObject;
1348 }
1349 return NULL;
1350}
1351
1352CODE_SEG("INIT")
1353VOID
1354NTAPI
1356 VOID)
1357{
1358 DPRINT("CcInitView()\n");
1359
1366 NULL,
1367 NULL,
1368 0,
1369 sizeof(INTERNAL_BCB),
1370 TAG_BCB,
1371 20);
1373 NULL,
1374 NULL,
1375 0,
1376 sizeof(ROS_SHARED_CACHE_MAP),
1378 20);
1380 NULL,
1381 NULL,
1382 0,
1383 sizeof(ROS_VACB),
1384 TAG_VACB,
1385 20);
1386
1388}
1389
1390#if DBG && defined(KDBG)
1391BOOLEAN
1392ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[])
1393{
1394 PLIST_ENTRY ListEntry;
1395 UNICODE_STRING NoName = RTL_CONSTANT_STRING(L"No name for File");
1396
1397 KdbpPrint(" Usage Summary (in kb)\n");
1398 KdbpPrint("Shared\t\tMapped\tDirty\tName\n");
1399 /* No need to lock the spin lock here, we're in DBG */
1400 for (ListEntry = CcCleanSharedCacheMapList.Flink;
1401 ListEntry != &CcCleanSharedCacheMapList;
1402 ListEntry = ListEntry->Flink)
1403 {
1404 PLIST_ENTRY Vacbs;
1405 ULONG Mapped = 0, Dirty = 0;
1406 PROS_SHARED_CACHE_MAP SharedCacheMap;
1408 PWSTR Extra = L"";
1409
1410 SharedCacheMap = CONTAINING_RECORD(ListEntry, ROS_SHARED_CACHE_MAP, SharedCacheMapLinks);
1411
1412 /* Dirty size */
1413 Dirty = (SharedCacheMap->DirtyPages * PAGE_SIZE) / 1024;
1414
1415 /* First, count for all the associated VACB */
1416 for (Vacbs = SharedCacheMap->CacheMapVacbListHead.Flink;
1417 Vacbs != &SharedCacheMap->CacheMapVacbListHead;
1418 Vacbs = Vacbs->Flink)
1419 {
1420 Mapped += VACB_MAPPING_GRANULARITY / 1024;
1421 }
1422
1423 /* Setup name */
1424 if (SharedCacheMap->FileObject != NULL &&
1425 SharedCacheMap->FileObject->FileName.Length != 0)
1426 {
1427 FileName = &SharedCacheMap->FileObject->FileName;
1428 }
1429 else if (SharedCacheMap->FileObject != NULL &&
1430 SharedCacheMap->FileObject->FsContext != NULL &&
1431 ((PFSRTL_COMMON_FCB_HEADER)(SharedCacheMap->FileObject->FsContext))->NodeTypeCode == 0x0502 &&
1432 ((PFSRTL_COMMON_FCB_HEADER)(SharedCacheMap->FileObject->FsContext))->NodeByteSize == 0x1F8 &&
1433 ((PUNICODE_STRING)(((PUCHAR)SharedCacheMap->FileObject->FsContext) + 0x100))->Length != 0)
1434 {
1435 FileName = (PUNICODE_STRING)(((PUCHAR)SharedCacheMap->FileObject->FsContext) + 0x100);
1436 Extra = L" (FastFAT)";
1437 }
1438 else
1439 {
1440 FileName = &NoName;
1441 }
1442
1443 /* And print */
1444 KdbpPrint("%p\t%d\t%d\t%wZ%S\n", SharedCacheMap, Mapped, Dirty, FileName, Extra);
1445 }
1446
1447 return TRUE;
1448}
1449
1450BOOLEAN
1451ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[])
1452{
1453 KdbpPrint("CcTotalDirtyPages:\t%lu (%lu Kb)\n", CcTotalDirtyPages,
1454 (CcTotalDirtyPages * PAGE_SIZE) / 1024);
1455 KdbpPrint("CcDirtyPageThreshold:\t%lu (%lu Kb)\n", CcDirtyPageThreshold,
1456 (CcDirtyPageThreshold * PAGE_SIZE) / 1024);
1457 KdbpPrint("MmAvailablePages:\t%lu (%lu Kb)\n", MmAvailablePages,
1458 (MmAvailablePages * PAGE_SIZE) / 1024);
1459 KdbpPrint("MmThrottleTop:\t\t%lu (%lu Kb)\n", MmThrottleTop,
1460 (MmThrottleTop * PAGE_SIZE) / 1024);
1461 KdbpPrint("MmThrottleBottom:\t%lu (%lu Kb)\n", MmThrottleBottom,
1462 (MmThrottleBottom * PAGE_SIZE) / 1024);
1463 KdbpPrint("MmModifiedPageListHead.Total:\t%lu (%lu Kb)\n", MmModifiedPageListHead.Total,
1465
1467 {
1468 KdbpPrint("CcTotalDirtyPages above the threshold, writes should be throttled\n");
1469 }
1470 else if (CcTotalDirtyPages + 64 >= CcDirtyPageThreshold)
1471 {
1472 KdbpPrint("CcTotalDirtyPages within 64 (max charge) pages of the threshold, writes may be throttled\n");
1473 }
1474 else
1475 {
1476 KdbpPrint("CcTotalDirtyPages below the threshold, writes should not be throttled\n");
1477 }
1478
1479 return TRUE;
1480}
1481#endif
1482
1483/* 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:1427
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
_In_ PSCSI_REQUEST_BLOCK _Out_ NTSTATUS _Inout_ BOOLEAN * Retry
Definition: classpnp.h:312
#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 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
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:593
#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:3219
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:200
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:1099
#define _Out_opt_
Definition: ms_sal.h:346
#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:113
static NTSTATUS CcRosDeleteFileCache(PFILE_OBJECT FileObject, PROS_SHARED_CACHE_MAP SharedCacheMap, PKIRQL OldIrql)
Definition: view.c:205
VOID CcRosMarkDirtyVacb(PROS_VACB Vacb)
Definition: view.c:528
NTSTATUS CcRosInitializeFileCache(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes, BOOLEAN PinAccess, PCACHE_MANAGER_CALLBACKS CallBacks, PVOID LazyWriterContext)
Definition: view.c:1166
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:453
NTSTATUS CcRosFlushVacb(_In_ PROS_VACB Vacb, _Out_opt_ PIO_STATUS_BLOCK Iosb)
Definition: view.c:159
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointers, IN PLARGE_INTEGER FileOffset OPTIONAL, IN ULONG Length, OUT PIO_STATUS_BLOCK IoStatus)
Definition: view.c:987
NTSTATUS CcRosRequestVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:914
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:816
PROS_VACB CcRosLookupVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset)
Definition: view.c:485
NTSTATUS CcRosReleaseFileCache(PFILE_OBJECT FileObject)
Definition: view.c:1110
PFILE_OBJECT NTAPI CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
Definition: view.c:1336
VOID NTAPI CcInitView(VOID)
Definition: view.c:1355
LIST_ENTRY DirtyVacbListHead
Definition: view.c:41
static NPAGED_LOOKASIDE_LIST SharedCacheMapLookasideList
Definition: view.c:45
static BOOLEAN CcRosFreeUnusedVacb(PULONG Count)
Definition: view.c:600
NTSTATUS CcRosInternalFreeVacb(PROS_VACB Vacb)
Definition: view.c:938
NTSTATUS CcRosGetVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:863
static NPAGED_LOOKASIDE_LIST VacbLookasideList
Definition: view.c:46
ULONG CcDirtyPageThreshold
Definition: view.c:55
ULONG CcTotalDirtyPages
Definition: view.c:56
VOID CcRosUnmarkDirtyVacb(PROS_VACB Vacb, BOOLEAN LockViews)
Definition: view.c:564
NTSTATUS CcRosFlushDirtyPages(ULONG Target, PULONG Count, BOOLEAN Wait, BOOLEAN CalledFromLazy)
Definition: view.c:305
static NTSTATUS CcRosCreateVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:682
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
BOOLEAN NTAPI MmArePagesResident(_In_ PEPROCESS Process, _In_ PVOID BaseAddress, _In_ ULONG Length)
Definition: section.c:4676
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:4841
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:4821
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:4361
#define ExRaiseStatus
Definition: ntoskrnl.h:108
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
#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:4521
#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:792
@ Executive
Definition: ketypes.h:403
@ LockQueueMasterLock
Definition: ketypes.h:651
#define ObDereferenceObject
Definition: obfuncs.h:203