ReactOS 0.4.17-dev-503-g19f3949
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 BOOLEAN WasMarked;
170 PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
171
172 /*
173 * Remove the VACB from the dirty list before flushing. The return value
174 * tells us whether the VACB was actually dirty at this point.
175 * If WasMarked is FALSE a concurrent flush already removed it from the
176 * dirty list. We still call MmFlushSegment because the caller expects a
177 * reliable status: if we returned STATUS_SUCCESS immediately, the caller
178 * would believe the data was safely written when in fact the concurrent
179 * flush may have failed. We must not re-mark dirty on failure in this
180 * case, however, as we were not the one who removed the VACB from the list.
181 */
182 WasMarked = CcRosUnmarkDirtyVacb(Vacb, TRUE);
183
184 /* Lock for flush, if we are not already the top-level */
186 {
187 Status = FsRtlAcquireFileForCcFlushEx(Vacb->SharedCacheMap->FileObject);
188 if (!NT_SUCCESS(Status))
189 goto quit;
190 HaveLock = TRUE;
191 }
192
193 Status = MmFlushSegment(SharedCacheMap->FileObject->SectionObjectPointer,
194 &Vacb->FileOffset,
196 Iosb);
197
198 if (HaveLock)
199 {
200 FsRtlReleaseFileForCcFlush(Vacb->SharedCacheMap->FileObject);
201 }
202
203quit:
204 if (!NT_SUCCESS(Status))
205 {
206 /*
207 * Only re-mark dirty if we were the thread that removed it from the
208 * dirty list. If WasMarked is FALSE, another thread already removed it,
209 * so we must not change dirty tracking here (that thread will re-mark on failure).
210 * CcRosMarkDirtyVacb itself guards against double-insertion should
211 * another thread have concurrently re-marked the VACB dirty.
212 */
213 if (WasMarked)
214 CcRosMarkDirtyVacb(Vacb);
215 }
216 else
217 {
218 /* Update VDL */
219 if (SharedCacheMap->ValidDataLength.QuadPart < (Vacb->FileOffset.QuadPart + VACB_MAPPING_GRANULARITY))
220 {
221 SharedCacheMap->ValidDataLength.QuadPart = Vacb->FileOffset.QuadPart + VACB_MAPPING_GRANULARITY;
222 }
223 }
224
225 return Status;
226}
227
228static
232 PROS_SHARED_CACHE_MAP SharedCacheMap,
234/*
235 * FUNCTION: Releases the shared cache map associated with a file object
236 */
237{
238 LIST_ENTRY LocalVacbList;
239
240 ASSERT(SharedCacheMap);
241 ASSERT(SharedCacheMap == FileObject->SectionObjectPointer->SharedCacheMap);
242 ASSERT(SharedCacheMap->OpenCount == 0);
243
244 InitializeListHead(&LocalVacbList);
245
246 /*
247 * Remove all VACBs from the global lists while holding the lock. By also
248 * removing them from CacheMapVacbListHead here (under the lock), we ensure
249 * that a concurrent CcRosLookupVacb (which also holds the lock) cannot find
250 * any of these VACBs after we release the lock. Without this, a caller that
251 * already has a SharedCacheMap pointer (e.g. CcFlushCache) could look up a
252 * VACB between our lock release and the point where the second loop removes
253 * it from the list — leaving an outstanding reference that races with our
254 * CcRosVacbDecRefCount call below.
255 */
257 while (!IsListEmpty(&SharedCacheMap->CacheMapVacbListHead))
258 {
260 ROS_VACB, CacheMapVacbListEntry);
261
264
265 if (Vacb->Dirty)
266 {
268 /* Mark it as dirty again so we know that we have to flush before freeing it */
269 Vacb->Dirty = TRUE;
270 }
271
272 /*
273 * Move this VACB from the shared cache map list to our private local
274 * list. After the lock is released, CcRosLookupVacb can no longer find
275 * it, so no new lookup references can be created.
276 */
278 InsertTailList(&LocalVacbList, &Vacb->CacheMapVacbListEntry);
279 }
280
281 /* Make sure there is no trace anymore of this map */
282 FileObject->SectionObjectPointer->SharedCacheMap = NULL;
283 RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks);
284
287
288 /* Now that we're out of the locks, free everything for real */
289 while (!IsListEmpty(&LocalVacbList))
290 {
291 PROS_VACB Vacb = CONTAINING_RECORD(RemoveHeadList(&LocalVacbList), ROS_VACB, CacheMapVacbListEntry);
292 ULONG RefCount;
293
295
296 /* Flush to disk, if needed */
297 if (Vacb->Dirty)
298 {
301
302 Status = MmFlushSegment(FileObject->SectionObjectPointer, &Vacb->FileOffset, VACB_MAPPING_GRANULARITY, &Iosb);
303 if (!NT_SUCCESS(Status))
304 {
305 /* Complain. There's not much we can do */
306 DPRINT1("Failed to flush VACB to disk while deleting the cache entry. Status: 0x%08x\n", Status);
307 }
308 Vacb->Dirty = FALSE;
309 }
310
311 RefCount = CcRosVacbDecRefCount(Vacb);
312#if DBG // CORE-14578
313 if (RefCount != 0)
314 {
315 DPRINT1("Leaking VACB %p attached to %p (%I64d)\n", Vacb, FileObject, Vacb->FileOffset.QuadPart);
316 DPRINT1("There are: %d references left\n", RefCount);
317 DPRINT1("Map: %d\n", Vacb->MappedCount);
318 DPRINT1("Dirty: %d\n", Vacb->Dirty);
319 if (FileObject->FileName.Length != 0)
320 {
321 DPRINT1("File was: %wZ\n", &FileObject->FileName);
322 }
323 else
324 {
325 DPRINT1("No name for the file\n");
326 }
327 }
328#else
329 (void)RefCount;
330#endif
331 }
332
333 /* Release the references we own */
334 if(SharedCacheMap->Section)
335 ObDereferenceObject(SharedCacheMap->Section);
336 ObDereferenceObject(SharedCacheMap->FileObject);
337
338 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap);
339
340 /* Acquire the lock again for our caller */
342
343 return STATUS_SUCCESS;
344}
345
351 BOOLEAN CalledFromLazy)
352{
353 PLIST_ENTRY current_entry;
356 BOOLEAN FlushAll = (Target == MAXULONG);
357
358 DPRINT("CcRosFlushDirtyPages(Target %lu)\n", Target);
359
360 (*Count) = 0;
361
364
365 current_entry = DirtyVacbListHead.Flink;
366 if (current_entry == &DirtyVacbListHead)
367 {
368 DPRINT("No Dirty pages\n");
369 }
370
371 while (((current_entry != &DirtyVacbListHead) && (Target > 0)) || FlushAll)
372 {
373 PROS_SHARED_CACHE_MAP SharedCacheMap;
376
377 if (current_entry == &DirtyVacbListHead)
378 {
379 ASSERT(FlushAll);
381 break;
382 current_entry = DirtyVacbListHead.Flink;
383 }
384
385 current = CONTAINING_RECORD(current_entry,
386 ROS_VACB,
387 DirtyVacbListEntry);
388 current_entry = current_entry->Flink;
389
391
392 SharedCacheMap = current->SharedCacheMap;
393
394 /* When performing lazy write, don't handle temporary files */
395 if (CalledFromLazy && BooleanFlagOn(SharedCacheMap->FileObject->Flags, FO_TEMPORARY_FILE))
396 {
398 continue;
399 }
400
401 /* Don't attempt to lazy write the files that asked not to */
402 if (CalledFromLazy && BooleanFlagOn(SharedCacheMap->Flags, WRITEBEHIND_DISABLED))
403 {
405 continue;
406 }
407
408 ASSERT(current->Dirty);
409
410 /* Do not lazy-write the same file concurrently. Fastfat ASSERTS on that */
411 if (SharedCacheMap->Flags & SHARED_CACHE_MAP_IN_LAZYWRITE)
412 {
414 continue;
415 }
416
417 SharedCacheMap->Flags |= SHARED_CACHE_MAP_IN_LAZYWRITE;
418
419 /* Keep a ref on the shared cache map */
420 SharedCacheMap->OpenCount++;
421
423
424 Locked = SharedCacheMap->Callbacks->AcquireForLazyWrite(SharedCacheMap->LazyWriteContext, Wait);
425 if (!Locked)
426 {
427 DPRINT("Not locked\n");
428 ASSERT(!Wait);
431 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;
432
433 if (--SharedCacheMap->OpenCount == 0)
434 CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);
435
436 continue;
437 }
438
441
442 SharedCacheMap->Callbacks->ReleaseFromLazyWrite(SharedCacheMap->LazyWriteContext);
443
444 /* We release the VACB before acquiring the lock again, because
445 * CcRosVacbDecRefCount might free the VACB, as CcRosFlushVacb dropped a
446 * Refcount. Freeing must be done outside of the lock.
447 * The refcount is decremented atomically. So this is OK. */
450
451 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;
452
453 if (--SharedCacheMap->OpenCount == 0)
454 CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);
455
458 {
459 DPRINT1("CC: Failed to flush VACB.\n");
460 }
461 else
462 {
463 ULONG PagesFreed;
464
465 /* How many pages did we free? */
466 PagesFreed = Iosb.Information / PAGE_SIZE;
467 (*Count) += PagesFreed;
468
469 if (!Wait)
470 {
471 /* Make sure we don't overflow target! */
472 if (Target < PagesFreed)
473 {
474 /* If we would have, jump to zero directly */
475 Target = 0;
476 }
477 else
478 {
479 Target -= PagesFreed;
480 }
481 }
482 }
483
484 current_entry = DirtyVacbListHead.Flink;
485 }
486
489
490 DPRINT("CcRosFlushDirtyPages() finished\n");
491 return STATUS_SUCCESS;
492}
493
494VOID
497 _Out_ PULONG NrFreed)
498/*
499 * FUNCTION: Try to free some memory from the file cache.
500 * ARGUMENTS:
501 * Target - The number of pages to be freed.
502 * NrFreed - Points to a variable where the number of pages
503 * actually freed is returned.
504 */
505{
506 PLIST_ENTRY current_entry;
508 ULONG PagesFreed;
509 KIRQL oldIrql;
511 BOOLEAN FlushedPages = FALSE;
512
513 DPRINT("CcRosTrimCache(Target %lu)\n", Target);
514
516
517 *NrFreed = 0;
518
519retry:
521
522 current_entry = VacbLruListHead.Flink;
523 while (current_entry != &VacbLruListHead)
524 {
525 ULONG Refs;
526
527 current = CONTAINING_RECORD(current_entry,
528 ROS_VACB,
529 VacbLruListEntry);
530
531 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
532
533 /* Reference the VACB */
535
536 /* Check if it's mapped and not dirty */
537 if (InterlockedCompareExchange((PLONG)&current->MappedCount, 0, 0) > 0 && !current->Dirty)
538 {
539 /* This code is never executed. It is left for reference only. */
540#if 1
541 DPRINT1("MmPageOutPhysicalAddress unexpectedly called\n");
542 ASSERT(FALSE);
543#else
544 ULONG i;
546
547 /* We have to break these locks to call MmPageOutPhysicalAddress */
548 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
550
551 /* Page out the VACB */
552 for (i = 0; i < VACB_MAPPING_GRANULARITY / PAGE_SIZE; i++)
553 {
555
557 }
558
559 /* Reacquire the locks */
561 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
562#endif
563 }
564
565 /* Only keep iterating though the loop while the lock is held */
566 current_entry = current_entry->Flink;
567
568 /* Dereference the VACB */
570
571 /* Check if we can free this entry now */
572 if (Refs < 2)
573 {
574 ASSERT(!current->Dirty);
575 ASSERT(!current->MappedCount);
576 ASSERT(Refs == 1);
577
578 RemoveEntryList(&current->CacheMapVacbListEntry);
579 RemoveEntryList(&current->VacbLruListEntry);
580 InitializeListHead(&current->VacbLruListEntry);
581 InsertHeadList(&FreeList, &current->CacheMapVacbListEntry);
582
583 /* Calculate how many pages we freed for Mm */
585 Target -= PagesFreed;
586 (*NrFreed) += PagesFreed;
587 }
588
589 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
590 }
591
593
594 /* Try flushing pages if we haven't met our target */
595 if ((Target > 0) && !FlushedPages)
596 {
597 /* Flush dirty pages to disk */
598 CcRosFlushDirtyPages(Target, &PagesFreed, FALSE, FALSE);
599 FlushedPages = TRUE;
600
601 /* We can only swap as many pages as we flushed */
602 if (PagesFreed < Target) Target = PagesFreed;
603
604 /* Check if we flushed anything */
605 if (PagesFreed != 0)
606 {
607 /* Try again after flushing dirty pages */
608 DPRINT("Flushed %lu dirty cache pages to disk\n", PagesFreed);
609 goto retry;
610 }
611 }
612
613 while (!IsListEmpty(&FreeList))
614 {
615 ULONG Refs;
616
617 current_entry = RemoveHeadList(&FreeList);
618 current = CONTAINING_RECORD(current_entry,
619 ROS_VACB,
620 CacheMapVacbListEntry);
621 InitializeListHead(&current->CacheMapVacbListEntry);
623 ASSERT(Refs == 0);
624 }
625
626 DPRINT("Evicted %lu cache pages\n", (*NrFreed));
627}
628
631 PROS_SHARED_CACHE_MAP SharedCacheMap,
632 PROS_VACB Vacb,
633 BOOLEAN Dirty,
634 BOOLEAN Mapped)
635{
636 ASSERT(SharedCacheMap);
637
638 DPRINT("CcRosReleaseVacb(SharedCacheMap 0x%p, Vacb 0x%p)\n", SharedCacheMap, Vacb);
639
640 /*
641 * NOTE: Vacb->Dirty is read here without holding the spinlock as an
642 * optimisation to avoid an unnecessary lock acquisition. The check may
643 * race with a concurrent CcRosUnmarkDirtyVacb; however CcRosMarkDirtyVacb
644 * re-checks Dirty under the lock and is a safe no-op if the VACB has
645 * already been re-marked dirty by another thread in the meantime.
646 * If Vacb->Dirty is TRUE at the check (so we skip marking) and a concurrent
647 * flush then immediately unmarks it, that flush's MmFlushSegment call covers
648 * all dirty section pages, including those written by the caller of this
649 * function. Should that flush fail, CcRosFlushVacb re-marks the VACB dirty
650 * (WasMarked == TRUE path), ensuring those pages are retried. No dirty data
651 * can be silently lost through this race.
652 */
653 if (Dirty && !Vacb->Dirty)
654 {
655 CcRosMarkDirtyVacb(Vacb);
656 }
657
658 if (Mapped)
659 {
660 if (InterlockedIncrement((PLONG)&Vacb->MappedCount) == 1)
661 {
663 }
664 }
665
666 /*
667 * Release the caller's reference. The return value may legitimately be 0
668 * when CcRosDeleteFileCache has concurrently removed the cache-map-list
669 * reference while we held a lookup reference: our decrement is then the
670 * last one and CcRosVacbDecRefCount frees the VACB. That is safe because
671 * callers (e.g. CcFlushCache) do not access the VACB pointer after this
672 * call. Do NOT assert the result is > 0 here.
673 */
675
676 return STATUS_SUCCESS;
677}
678
679/* Returns with VACB Lock Held! */
682 PROS_SHARED_CACHE_MAP SharedCacheMap,
684{
685 PLIST_ENTRY current_entry;
687 KIRQL oldIrql;
688
689 ASSERT(SharedCacheMap);
690
691 DPRINT("CcRosLookupVacb(SharedCacheMap 0x%p, FileOffset %I64u)\n",
692 SharedCacheMap, FileOffset);
693
696
697 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
698 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
699 {
700 current = CONTAINING_RECORD(current_entry,
701 ROS_VACB,
702 CacheMapVacbListEntry);
703 if (IsPointInRange(current->FileOffset.QuadPart,
705 FileOffset))
706 {
710 return current;
711 }
712 if (current->FileOffset.QuadPart > FileOffset)
713 break;
714 current_entry = current_entry->Flink;
715 }
716
719
720 return NULL;
721}
722
723VOID
725 PROS_VACB Vacb)
726{
727 KIRQL oldIrql;
728 PROS_SHARED_CACHE_MAP SharedCacheMap;
729
730 SharedCacheMap = Vacb->SharedCacheMap;
731
734
735 if (Vacb->Dirty)
736 {
737 /*
738 * The VACB was already re-marked dirty by another thread between
739 * CcRosUnmarkDirtyVacb and this call (e.g. a concurrent writer via
740 * CcRosReleaseVacb) and the VACB has already been inserted into
741 * the dirty list.
742 */
745 return;
746 }
747
749 /* FIXME: There is no reason to account for the whole VACB. */
753
754 /* Move to the tail of the LRU list */
757
758 Vacb->Dirty = TRUE;
759
761
762 /* Schedule a lazy writer run to now that we have dirty VACB */
764 {
766 }
768}
769
772 PROS_VACB Vacb,
773 BOOLEAN LockViews)
774{
775 KIRQL oldIrql;
776 PROS_SHARED_CACHE_MAP SharedCacheMap;
777
778 SharedCacheMap = Vacb->SharedCacheMap;
779
780 if (LockViews)
781 {
784 }
785
786 if (!Vacb->Dirty)
787 {
788 ASSERT(LockViews);
789 /*
790 * The VACB was already unmarked by a concurrent flush (e.g. the lazy
791 * writer) between the caller's lockless Dirty check and this call.
792 * Proceeding would underflow CcTotalDirtyPages/DirtyPages, drop an
793 * extra refcount, and could ultimately free the VACB prematurely.
794 */
797
798 return FALSE;
799 }
800
801 Vacb->Dirty = FALSE;
802
805
808
810
811 if (LockViews)
812 {
815 }
816
817 return TRUE;
818}
819
822 VOID)
823{
824 KIRQL oldIrql;
825 PLIST_ENTRY current_entry;
826 PROS_VACB to_free = NULL;
827
829
830 /* Browse all the available VACB */
831 current_entry = VacbLruListHead.Flink;
832 while ((current_entry != &VacbLruListHead) && (to_free == NULL))
833 {
834 ULONG Refs;
836
837 current = CONTAINING_RECORD(current_entry,
838 ROS_VACB,
839 VacbLruListEntry);
840
841 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
842
843 /* Only deal with unused VACB, we will free them */
845 if (Refs < 2)
846 {
847 ASSERT(!current->Dirty);
848 ASSERT(!current->MappedCount);
849 ASSERT(Refs == 1);
850
851 /* Reset it, this is the one we want to free */
852 RemoveEntryList(&current->CacheMapVacbListEntry);
853 InitializeListHead(&current->CacheMapVacbListEntry);
854 RemoveEntryList(&current->VacbLruListEntry);
855 InitializeListHead(&current->VacbLruListEntry);
856
857 to_free = current;
858 }
859
860 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
861
862 current_entry = current_entry->Flink;
863 }
864
866
867 /* And now, free the VACB that we found, if any. */
868 if (to_free == NULL)
869 {
870 return FALSE;
871 }
872
873 /* This must be its last ref */
874 NT_VERIFY(CcRosVacbDecRefCount(to_free) == 0);
875
876 return TRUE;
877}
878
879static
882 PROS_SHARED_CACHE_MAP SharedCacheMap,
884 PROS_VACB *Vacb)
885{
887 PROS_VACB previous;
888 PLIST_ENTRY current_entry;
890 KIRQL oldIrql;
891 ULONG Refs;
893
894 ASSERT(SharedCacheMap);
895
896 DPRINT("CcRosCreateVacb()\n");
897
898 current = ExAllocateFromNPagedLookasideList(&VacbLookasideList);
899 if (!current)
900 {
902 }
903 current->BaseAddress = NULL;
904 current->Dirty = FALSE;
905 current->PageOut = FALSE;
906 current->FileOffset.QuadPart = ROUND_DOWN(FileOffset, VACB_MAPPING_GRANULARITY);
907 current->SharedCacheMap = SharedCacheMap;
908 current->MappedCount = 0;
909 current->ReferenceCount = 0;
910 InitializeListHead(&current->CacheMapVacbListEntry);
911 InitializeListHead(&current->DirtyVacbListEntry);
912 InitializeListHead(&current->VacbLruListEntry);
913
915
916 while (TRUE)
917 {
918 /* Map VACB in system space */
919 Status = MmMapViewInSystemSpaceEx(SharedCacheMap->Section, &current->BaseAddress, &ViewSize, &current->FileOffset, 0);
920 if (NT_SUCCESS(Status))
921 {
922 break;
923 }
924
925 /*
926 * If no space left, try to prune one unused VACB to recover space to map our VACB.
927 * If it succeeds, retry to map, otherwise just fail.
928 */
930 {
931 ExFreeToNPagedLookasideList(&VacbLookasideList, current);
932 return Status;
933 }
934 }
935
936#if DBG
937 if (SharedCacheMap->Trace)
938 {
939 DPRINT1("CacheMap 0x%p: new VACB: 0x%p, file offset %I64d, BaseAddress %p\n",
940 SharedCacheMap, current, current->FileOffset.QuadPart, current->BaseAddress);
941 }
942#endif
943
945
946 *Vacb = current;
947 /* There is window between the call to CcRosLookupVacb
948 * and CcRosCreateVacb. We must check if a VACB for the
949 * file offset exist. If there is a VACB, we release
950 * our newly created VACB and return the existing one.
951 */
953 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
954 previous = NULL;
955 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
956 {
957 current = CONTAINING_RECORD(current_entry,
958 ROS_VACB,
959 CacheMapVacbListEntry);
960 if (IsPointInRange(current->FileOffset.QuadPart,
962 FileOffset))
963 {
966#if DBG
967 if (SharedCacheMap->Trace)
968 {
969 DPRINT1("CacheMap 0x%p: deleting newly created VACB 0x%p ( found existing one 0x%p )\n",
970 SharedCacheMap,
971 (*Vacb),
972 current);
973 }
974#endif
976
977 Refs = CcRosVacbDecRefCount(*Vacb);
978 ASSERT(Refs == 0);
979
980 *Vacb = current;
981 return STATUS_SUCCESS;
982 }
983 if (current->FileOffset.QuadPart < FileOffset)
984 {
985 ASSERT(previous == NULL ||
986 previous->FileOffset.QuadPart < current->FileOffset.QuadPart);
987 previous = current;
988 }
989 if (current->FileOffset.QuadPart > FileOffset)
990 break;
991 current_entry = current_entry->Flink;
992 }
993 /* There was no existing VACB. */
994 current = *Vacb;
995 if (previous)
996 {
997 InsertHeadList(&previous->CacheMapVacbListEntry, &current->CacheMapVacbListEntry);
998 }
999 else
1000 {
1001 InsertHeadList(&SharedCacheMap->CacheMapVacbListHead, &current->CacheMapVacbListEntry);
1002 }
1004 InsertTailList(&VacbLruListHead, &current->VacbLruListEntry);
1005
1006 /* Reference it to allow release */
1008
1010
1011 return Status;
1012}
1013
1014BOOLEAN
1016 _In_ PROS_VACB Vacb,
1018 _In_ BOOLEAN NoRead,
1021)
1022{
1023 PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
1024
1026
1027#if 0
1028 if ((Vacb->FileOffset.QuadPart + Offset) > SharedCacheMap->SectionSize.QuadPart)
1029 {
1030 DPRINT1("Vacb read beyond the file size!\n");
1031 return FALSE;
1032 }
1033#endif
1034
1035 /* Check if the pages are resident */
1036 if (!MmIsDataSectionResident(SharedCacheMap->FileObject->SectionObjectPointer,
1037 Vacb->FileOffset.QuadPart + Offset,
1038 Length))
1039 {
1040 if (!Wait)
1041 {
1042 return FALSE;
1043 }
1044
1045 if (!NoRead)
1046 {
1047 NTSTATUS Status = MmMakeDataSectionResident(SharedCacheMap->FileObject->SectionObjectPointer,
1048 Vacb->FileOffset.QuadPart + Offset,
1049 Length,
1050 &SharedCacheMap->ValidDataLength);
1051 if (!NT_SUCCESS(Status))
1053 }
1054 }
1055
1056 return TRUE;
1057}
1058
1059
1062 PROS_SHARED_CACHE_MAP SharedCacheMap,
1064 PROS_VACB *Vacb)
1065{
1068 ULONG Refs;
1069 KIRQL OldIrql;
1070
1071 ASSERT(SharedCacheMap);
1072
1073 DPRINT("CcRosGetVacb()\n");
1074
1075 /*
1076 * Look for a VACB already mapping the same data.
1077 */
1078 current = CcRosLookupVacb(SharedCacheMap, FileOffset);
1079 if (current == NULL)
1080 {
1081 /*
1082 * Otherwise create a new VACB.
1083 */
1084 Status = CcRosCreateVacb(SharedCacheMap, FileOffset, &current);
1085 if (!NT_SUCCESS(Status))
1086 {
1087 return Status;
1088 }
1089 }
1090
1092
1094
1095 /* Move to the tail of the LRU list */
1096 RemoveEntryList(&current->VacbLruListEntry);
1097 InsertTailList(&VacbLruListHead, &current->VacbLruListEntry);
1098
1100
1101 /*
1102 * Return the VACB to the caller.
1103 */
1104 *Vacb = current;
1105
1106 ASSERT(Refs > 1);
1107
1108 return STATUS_SUCCESS;
1109}
1110
1113 PROS_SHARED_CACHE_MAP SharedCacheMap,
1115 PROS_VACB *Vacb)
1116/*
1117 * FUNCTION: Request a page mapping for a shared cache map
1118 */
1119{
1120
1121 ASSERT(SharedCacheMap);
1122
1124 {
1125 DPRINT1("Bad FileOffset %I64x: should be multiple of %x\n",
1127 KeBugCheck(CACHE_MANAGER);
1128 }
1129
1130 return CcRosGetVacb(SharedCacheMap,
1131 FileOffset,
1132 Vacb);
1133}
1134
1137 PROS_VACB Vacb)
1138/*
1139 * FUNCTION: Releases a VACB associated with a shared cache map
1140 */
1141{
1143
1144 DPRINT("Freeing VACB 0x%p\n", Vacb);
1145#if DBG
1146 if (Vacb->SharedCacheMap->Trace)
1147 {
1148 DPRINT1("CacheMap 0x%p: deleting VACB: 0x%p\n", Vacb->SharedCacheMap, Vacb);
1149 }
1150#endif
1151
1152 if (Vacb->ReferenceCount != 0)
1153 {
1154 DPRINT1("Invalid free: %ld\n", Vacb->ReferenceCount);
1155 if (Vacb->SharedCacheMap->FileObject && Vacb->SharedCacheMap->FileObject->FileName.Length)
1156 {
1157 DPRINT1("For file: %wZ\n", &Vacb->SharedCacheMap->FileObject->FileName);
1158 }
1159 }
1160
1161 ASSERT(Vacb->ReferenceCount == 0);
1165
1166 /* Delete the mapping */
1168 if (!NT_SUCCESS(Status))
1169 {
1170 DPRINT1("Failed to unmap VACB from System address space! Status 0x%08X\n", Status);
1171 ASSERT(FALSE);
1172 /* Proceed with the deĺetion anyway */
1173 }
1174
1175 RtlFillMemory(Vacb, sizeof(*Vacb), 0xfd);
1176 ExFreeToNPagedLookasideList(&VacbLookasideList, Vacb);
1177 return STATUS_SUCCESS;
1178}
1179
1180/*
1181 * @implemented
1182 */
1183VOID
1184NTAPI
1186 IN PSECTION_OBJECT_POINTERS SectionObjectPointers,
1188 IN ULONG Length,
1190{
1191 PROS_SHARED_CACHE_MAP SharedCacheMap;
1192 LONGLONG FlushStart, FlushEnd;
1194
1195 CCTRACE(CC_API_DEBUG, "SectionObjectPointers=%p FileOffset=0x%I64X Length=%lu\n",
1196 SectionObjectPointers, FileOffset ? FileOffset->QuadPart : 0LL, Length);
1197
1198 if (!SectionObjectPointers)
1199 {
1201 goto quit;
1202 }
1203
1204 if (!SectionObjectPointers->SharedCacheMap)
1205 {
1206 /* Forward this to Mm */
1207 MmFlushSegment(SectionObjectPointers, FileOffset, Length, IoStatus);
1208 return;
1209 }
1210
1211 SharedCacheMap = SectionObjectPointers->SharedCacheMap;
1212 ASSERT(SharedCacheMap);
1213 if (FileOffset)
1214 {
1215 FlushStart = FileOffset->QuadPart;
1216 Status = RtlLongLongAdd(FlushStart, Length, &FlushEnd);
1217 if (!NT_SUCCESS(Status))
1218 goto quit;
1219 }
1220 else
1221 {
1222 FlushStart = 0;
1223 FlushEnd = SharedCacheMap->FileSize.QuadPart;
1224 }
1225
1227 if (IoStatus)
1228 {
1229 IoStatus->Information = 0;
1230 }
1231
1232 KeAcquireGuardedMutex(&SharedCacheMap->FlushCacheLock);
1233
1234 /*
1235 * We flush the VACBs that we find here.
1236 * If there is no (dirty) VACB, it doesn't mean that there is no data to flush, so we call Mm to be sure.
1237 * This is suboptimal, but this is due to the lack of granularity of how we track dirty cache data
1238 */
1239 while (FlushStart < FlushEnd)
1240 {
1241 BOOLEAN DirtyVacb = FALSE;
1242 PROS_VACB vacb = CcRosLookupVacb(SharedCacheMap, FlushStart);
1243
1244 if (vacb != NULL)
1245 {
1246 /*
1247 * NOTE: vacb->Dirty is read here without holding the spinlock.
1248 * The lock was released by CcRosLookupVacb before returning. A
1249 * concurrent flush (lazy writer) may therefore clear Dirty between
1250 * this check and the CcRosFlushVacb call below. CcRosFlushVacb
1251 * handles this safely via the guarded CcRosUnmarkDirtyVacb path.
1252 */
1253 if (vacb->Dirty)
1254 {
1255 IO_STATUS_BLOCK VacbIosb = { 0 };
1256 Status = CcRosFlushVacb(vacb, &VacbIosb);
1257 if (!NT_SUCCESS(Status))
1258 {
1259 CcRosReleaseVacb(SharedCacheMap, vacb, FALSE, FALSE);
1260 break;
1261 }
1262 DirtyVacb = TRUE;
1263
1264 if (IoStatus)
1265 IoStatus->Information += VacbIosb.Information;
1266 }
1267
1268 CcRosReleaseVacb(SharedCacheMap, vacb, FALSE, FALSE);
1269 }
1270
1271 if (!DirtyVacb)
1272 {
1273 IO_STATUS_BLOCK MmIosb;
1274 LARGE_INTEGER MmOffset;
1275
1276 MmOffset.QuadPart = FlushStart;
1277
1278 if (FlushEnd - (FlushEnd % VACB_MAPPING_GRANULARITY) <= FlushStart)
1279 {
1280 /* The whole range fits within a VACB chunk. */
1281 Status = MmFlushSegment(SectionObjectPointers, &MmOffset, FlushEnd - FlushStart, &MmIosb);
1282 }
1283 else
1284 {
1285 ULONG MmLength = VACB_MAPPING_GRANULARITY - (FlushStart % VACB_MAPPING_GRANULARITY);
1286 Status = MmFlushSegment(SectionObjectPointers, &MmOffset, MmLength, &MmIosb);
1287 }
1288
1289 if (!NT_SUCCESS(Status))
1290 break;
1291
1292 if (IoStatus)
1293 IoStatus->Information += MmIosb.Information;
1294
1295 /* Update VDL */
1296 if (SharedCacheMap->ValidDataLength.QuadPart < FlushEnd)
1297 SharedCacheMap->ValidDataLength.QuadPart = FlushEnd;
1298 }
1299
1300 if (!NT_SUCCESS(RtlLongLongAdd(FlushStart, VACB_MAPPING_GRANULARITY, &FlushStart)))
1301 {
1302 /* We're at the end of file ! */
1303 break;
1304 }
1305
1306 /* Round down to next VACB start now */
1307 FlushStart -= FlushStart % VACB_MAPPING_GRANULARITY;
1308 }
1309
1310 KeReleaseGuardedMutex(&SharedCacheMap->FlushCacheLock);
1311
1312quit:
1313 if (IoStatus)
1314 {
1315 IoStatus->Status = Status;
1316 }
1317}
1318
1322/*
1323 * FUNCTION: Called by the file system when a handle to a file object
1324 * has been closed.
1325 */
1326{
1327 KIRQL OldIrql;
1328 PPRIVATE_CACHE_MAP PrivateMap;
1329 PROS_SHARED_CACHE_MAP SharedCacheMap;
1330
1332
1333 if (FileObject->SectionObjectPointer->SharedCacheMap != NULL)
1334 {
1335 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
1336
1337 /* Closing the handle, so kill the private cache map
1338 * Before you event try to remove it from FO, always
1339 * lock the master lock, to be sure not to race
1340 * with a potential read ahead ongoing!
1341 */
1342 PrivateMap = FileObject->PrivateCacheMap;
1343 FileObject->PrivateCacheMap = NULL;
1344
1345 if (PrivateMap != NULL)
1346 {
1347 /* Remove it from the file */
1348 KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock);
1349 RemoveEntryList(&PrivateMap->PrivateLinks);
1351
1352 /* And free it. */
1353 if (PrivateMap != &SharedCacheMap->PrivateCacheMap)
1354 {
1356 }
1357 else
1358 {
1359 PrivateMap->NodeTypeCode = 0;
1360 }
1361
1362 ASSERT(SharedCacheMap->OpenCount > 0);
1363
1364 SharedCacheMap->OpenCount--;
1365 if (SharedCacheMap->OpenCount == 0)
1366 {
1367 CcRosDeleteFileCache(FileObject, SharedCacheMap, &OldIrql);
1368 }
1369 }
1370 }
1372 return STATUS_SUCCESS;
1373}
1374
1379 BOOLEAN PinAccess,
1380 PCACHE_MANAGER_CALLBACKS CallBacks,
1381 PVOID LazyWriterContext)
1382/*
1383 * FUNCTION: Initializes a shared cache map for a file object
1384 */
1385{
1386 KIRQL OldIrql;
1388 PROS_SHARED_CACHE_MAP SharedCacheMap;
1389
1390 DPRINT("CcRosInitializeFileCache(FileObject 0x%p)\n", FileObject);
1391
1393
1394 Allocated = FALSE;
1395 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
1396 if (SharedCacheMap == NULL)
1397 {
1398 SharedCacheMap = ExAllocateFromNPagedLookasideList(&SharedCacheMapLookasideList);
1399 if (SharedCacheMap == NULL)
1400 {
1403 }
1404 RtlZeroMemory(SharedCacheMap, sizeof(*SharedCacheMap));
1405 SharedCacheMap->NodeTypeCode = NODE_TYPE_SHARED_MAP;
1406 SharedCacheMap->NodeByteSize = sizeof(*SharedCacheMap);
1407 SharedCacheMap->FileObject = FileObject;
1408 SharedCacheMap->Callbacks = CallBacks;
1409 SharedCacheMap->LazyWriteContext = LazyWriterContext;
1410 SharedCacheMap->SectionSize = FileSizes->AllocationSize;
1411 SharedCacheMap->FileSize = FileSizes->FileSize;
1412 SharedCacheMap->ValidDataLength = FileSizes->ValidDataLength;
1413 SharedCacheMap->PinAccess = PinAccess;
1414 SharedCacheMap->DirtyPageThreshold = 0;
1415 SharedCacheMap->DirtyPages = 0;
1416 InitializeListHead(&SharedCacheMap->PrivateList);
1417 KeInitializeSpinLock(&SharedCacheMap->CacheMapLock);
1418 InitializeListHead(&SharedCacheMap->CacheMapVacbListHead);
1419 InitializeListHead(&SharedCacheMap->BcbList);
1420 KeInitializeGuardedMutex(&SharedCacheMap->FlushCacheLock);
1421
1422 SharedCacheMap->Flags = SHARED_CACHE_MAP_IN_CREATION;
1423
1426 NULL,
1427 KernelMode);
1428
1429 Allocated = TRUE;
1430 FileObject->SectionObjectPointer->SharedCacheMap = SharedCacheMap;
1431
1432 //CcRosTraceCacheMap(SharedCacheMap, TRUE);
1433 }
1434 else if (SharedCacheMap->Flags & SHARED_CACHE_MAP_IN_CREATION)
1435 {
1436 /* The shared cache map is being created somewhere else. Wait for that to happen */
1437 KEVENT Waiter;
1438 PKEVENT PreviousWaiter = SharedCacheMap->CreateEvent;
1439
1441 SharedCacheMap->CreateEvent = &Waiter;
1442
1444
1446
1447 if (PreviousWaiter)
1448 KeSetEvent(PreviousWaiter, IO_NO_INCREMENT, FALSE);
1449
1451 }
1452
1453 if (FileObject->PrivateCacheMap == NULL)
1454 {
1455 PPRIVATE_CACHE_MAP PrivateMap;
1456
1457 /* Allocate the private cache map for this handle */
1458 if (SharedCacheMap->PrivateCacheMap.NodeTypeCode != 0)
1459 {
1461 }
1462 else
1463 {
1464 PrivateMap = &SharedCacheMap->PrivateCacheMap;
1465 }
1466
1467 if (PrivateMap == NULL)
1468 {
1469 /* If we also allocated the shared cache map for this file, kill it */
1470 if (Allocated)
1471 {
1472 RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks);
1473
1474 FileObject->SectionObjectPointer->SharedCacheMap = NULL;
1476 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap);
1477 }
1478
1481 }
1482
1483 /* Initialize it */
1484 RtlZeroMemory(PrivateMap, sizeof(PRIVATE_CACHE_MAP));
1485 PrivateMap->NodeTypeCode = NODE_TYPE_PRIVATE_MAP;
1486 PrivateMap->ReadAheadMask = PAGE_SIZE - 1;
1487 PrivateMap->FileObject = FileObject;
1489
1490 /* Link it to the file */
1491 KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock);
1492 InsertTailList(&SharedCacheMap->PrivateList, &PrivateMap->PrivateLinks);
1494
1495 FileObject->PrivateCacheMap = PrivateMap;
1496 SharedCacheMap->OpenCount++;
1497 }
1498
1500
1501 /* Create the section */
1502 if (Allocated)
1503 {
1505
1506 ASSERT(SharedCacheMap->Section == NULL);
1507
1509 &SharedCacheMap->Section,
1511 NULL,
1512 &SharedCacheMap->SectionSize,
1515 NULL,
1516 FileObject);
1517
1519
1520 if (!NT_SUCCESS(Status))
1521 {
1523 return Status;
1524 }
1525
1527
1529 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_CREATION;
1530
1531 if (SharedCacheMap->CreateEvent)
1532 {
1533 KeSetEvent(SharedCacheMap->CreateEvent, IO_NO_INCREMENT, FALSE);
1534 SharedCacheMap->CreateEvent = NULL;
1535 }
1536
1538 }
1539
1540 return STATUS_SUCCESS;
1541}
1542
1543/*
1544 * @implemented
1545 */
1547NTAPI
1549 IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
1550{
1551 PROS_SHARED_CACHE_MAP SharedCacheMap;
1552
1553 CCTRACE(CC_API_DEBUG, "SectionObjectPointers=%p\n", SectionObjectPointers);
1554
1555 if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
1556 {
1557 SharedCacheMap = SectionObjectPointers->SharedCacheMap;
1558 ASSERT(SharedCacheMap);
1559 return SharedCacheMap->FileObject;
1560 }
1561 return NULL;
1562}
1563
1564CODE_SEG("INIT")
1565VOID
1566NTAPI
1568 VOID)
1569{
1570 DPRINT("CcInitView()\n");
1571
1578 NULL,
1579 NULL,
1580 0,
1581 sizeof(INTERNAL_BCB),
1582 TAG_BCB,
1583 20);
1585 NULL,
1586 NULL,
1587 0,
1588 sizeof(ROS_SHARED_CACHE_MAP),
1590 20);
1592 NULL,
1593 NULL,
1594 0,
1595 sizeof(ROS_VACB),
1596 TAG_VACB,
1597 20);
1598
1600}
1601
1602#if DBG && defined(KDBG)
1603
1604#include <kdbg/kdb.h>
1605
1606BOOLEAN
1607ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[])
1608{
1609 PLIST_ENTRY ListEntry;
1610 UNICODE_STRING NoName = RTL_CONSTANT_STRING(L"No name for File");
1611
1612 KdbpPrint(" Usage Summary (in kb)\n");
1613 KdbpPrint("Shared\t\tMapped\tDirty\tName\n");
1614 /* No need to lock the spin lock here, we're in DBG */
1615 for (ListEntry = CcCleanSharedCacheMapList.Flink;
1616 ListEntry != &CcCleanSharedCacheMapList;
1617 ListEntry = ListEntry->Flink)
1618 {
1619 PLIST_ENTRY Vacbs;
1620 ULONG Mapped = 0, Dirty = 0;
1621 PROS_SHARED_CACHE_MAP SharedCacheMap;
1623 PWSTR Extra = L"";
1624
1625 SharedCacheMap = CONTAINING_RECORD(ListEntry, ROS_SHARED_CACHE_MAP, SharedCacheMapLinks);
1626
1627 /* Dirty size */
1628 Dirty = (SharedCacheMap->DirtyPages * PAGE_SIZE) / 1024;
1629
1630 /* First, count for all the associated VACB */
1631 for (Vacbs = SharedCacheMap->CacheMapVacbListHead.Flink;
1632 Vacbs != &SharedCacheMap->CacheMapVacbListHead;
1633 Vacbs = Vacbs->Flink)
1634 {
1635 Mapped += VACB_MAPPING_GRANULARITY / 1024;
1636 }
1637
1638 /* Setup name */
1639 if (SharedCacheMap->FileObject != NULL &&
1640 SharedCacheMap->FileObject->FileName.Length != 0)
1641 {
1642 FileName = &SharedCacheMap->FileObject->FileName;
1643 }
1644 else if (SharedCacheMap->FileObject != NULL &&
1645 SharedCacheMap->FileObject->FsContext != NULL &&
1646 ((PFSRTL_COMMON_FCB_HEADER)(SharedCacheMap->FileObject->FsContext))->NodeTypeCode == 0x0502 &&
1647 ((PFSRTL_COMMON_FCB_HEADER)(SharedCacheMap->FileObject->FsContext))->NodeByteSize == 0x1F8 &&
1648 ((PUNICODE_STRING)(((PUCHAR)SharedCacheMap->FileObject->FsContext) + 0x100))->Length != 0)
1649 {
1650 FileName = (PUNICODE_STRING)(((PUCHAR)SharedCacheMap->FileObject->FsContext) + 0x100);
1651 Extra = L" (FastFAT)";
1652 }
1653 else
1654 {
1655 FileName = &NoName;
1656 }
1657
1658 /* And print */
1659 KdbpPrint("%p\t%d\t%d\t%wZ%S\n", SharedCacheMap, Mapped, Dirty, FileName, Extra);
1660 }
1661
1662 return TRUE;
1663}
1664
1665BOOLEAN
1666ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[])
1667{
1668 KdbpPrint("CcTotalDirtyPages:\t%lu (%lu Kb)\n", CcTotalDirtyPages,
1669 (CcTotalDirtyPages * PAGE_SIZE) / 1024);
1670 KdbpPrint("CcDirtyPageThreshold:\t%lu (%lu Kb)\n", CcDirtyPageThreshold,
1671 (CcDirtyPageThreshold * PAGE_SIZE) / 1024);
1672 KdbpPrint("MmAvailablePages:\t%lu (%lu Kb)\n", MmAvailablePages,
1673 (MmAvailablePages * PAGE_SIZE) / 1024);
1674 KdbpPrint("MmThrottleTop:\t\t%lu (%lu Kb)\n", MmThrottleTop,
1675 (MmThrottleTop * PAGE_SIZE) / 1024);
1676 KdbpPrint("MmThrottleBottom:\t%lu (%lu Kb)\n", MmThrottleBottom,
1677 (MmThrottleBottom * PAGE_SIZE) / 1024);
1678 KdbpPrint("MmModifiedPageListHead.Total:\t%lu (%lu Kb)\n", MmModifiedPageListHead.Total,
1680
1682 {
1683 KdbpPrint("CcTotalDirtyPages above the threshold, writes should be throttled\n");
1684 }
1685 else if (CcTotalDirtyPages + 64 >= CcDirtyPageThreshold)
1686 {
1687 KdbpPrint("CcTotalDirtyPages within 64 (max charge) pages of the threshold, writes may be throttled\n");
1688 }
1689 else
1690 {
1691 KdbpPrint("CcTotalDirtyPages below the threshold, writes should not be throttled\n");
1692 }
1693
1694 return TRUE;
1695}
1696
1697#endif // DBG && defined(KDBG)
1698
1699/* EOF */
NTSTATUS NTAPI MmUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:2777
#define CODE_SEG(...)
void FreeList(LOCATIONITEM *pItems)
Definition: CSearchBar.cpp:95
static CC_FILE_SIZES FileSizes
ULONG_PTR PFN_NUMBER
unsigned char BOOLEAN
Definition: actypes.h:127
#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 RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#define Trace(x)
Definition: inflate.c:42
#define L(x)
Definition: resources.c:13
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:24
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 InterlockedCompareExchange
Definition: interlocked.h:119
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 _Pre_valid_ PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:412
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:1307
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1296
#define SEC_RESERVE
Definition: nt_native.h:1326
#define FILE_ALL_ACCESS
Definition: nt_native.h:651
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
_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:230
VOID CcRosMarkDirtyVacb(PROS_VACB Vacb)
Definition: view.c:724
NTSTATUS CcRosInitializeFileCache(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes, BOOLEAN PinAccess, PCACHE_MANAGER_CALLBACKS CallBacks, PVOID LazyWriterContext)
Definition: view.c:1376
LIST_ENTRY CcCleanSharedCacheMapList
Definition: view.c:60
BOOLEAN CcRosUnmarkDirtyVacb(PROS_VACB Vacb, BOOLEAN LockViews)
Definition: view.c:771
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:630
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:1185
NTSTATUS CcRosRequestVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:1112
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:1015
PROS_VACB CcRosLookupVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset)
Definition: view.c:681
NTSTATUS CcRosReleaseFileCache(PFILE_OBJECT FileObject)
Definition: view.c:1320
PFILE_OBJECT NTAPI CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
Definition: view.c:1548
VOID NTAPI CcInitView(VOID)
Definition: view.c:1567
VOID CcRosTrimCache(_In_ ULONG Target, _Out_ PULONG NrFreed)
Definition: view.c:495
LIST_ENTRY DirtyVacbListHead
Definition: view.c:42
static NPAGED_LOOKASIDE_LIST SharedCacheMapLookasideList
Definition: view.c:46
NTSTATUS CcRosInternalFreeVacb(PROS_VACB Vacb)
Definition: view.c:1136
NTSTATUS CcRosGetVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:1061
static NPAGED_LOOKASIDE_LIST VacbLookasideList
Definition: view.c:47
BOOLEAN CcRosFreeOneUnusedVacb(VOID)
Definition: view.c:821
ULONG CcDirtyPageThreshold
Definition: view.c:56
ULONG CcTotalDirtyPages
Definition: view.c:57
NTSTATUS CcRosFlushDirtyPages(ULONG Target, PULONG Count, BOOLEAN Wait, BOOLEAN CalledFromLazy)
Definition: view.c:347
static NTSTATUS CcRosCreateVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:881
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:397
MMPFNLIST MmModifiedPageListHead
Definition: pfnlist.c:45
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1305
BOOLEAN NTAPI MmIsDataSectionResident(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length)
Definition: section.c:5000
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:5119
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:5042
ULONG MmThrottleBottom
Definition: mminit.c:398
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:4517
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
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:380
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:603
#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:4677
#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:462
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
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:467
@ LockQueueMasterLock
Definition: ketypes.h:731
#define ObDereferenceObject
Definition: obfuncs.h:203
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3304