2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cc/view.c
5 * PURPOSE: Cache manager
7 * PROGRAMMERS: David Welch (welch@mcmail.com)
8 * Pierre Schweitzer (pierre@reactos.org)
11 /* NOTES **********************************************************************
13 * This is not the NT implementation of a file cache nor anything much like
16 * The general procedure for a filesystem to implement a read or write
17 * dispatch routine is as follows
19 * (1) If caching for the FCB hasn't been initiated then so do by calling
20 * CcInitializeFileCache.
22 * (2) For each 4k region which is being read or written obtain a cache page
23 * by calling CcRequestCachePage.
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.
29 * (4) Copy the data into or out of the page as necessary.
31 * (5) Release the cache page
33 /* INCLUDES ******************************************************************/
39 #if defined (ALLOC_PRAGMA)
40 #pragma alloc_text(INIT, CcInitView)
43 /* GLOBALS *******************************************************************/
45 LIST_ENTRY DirtyVacbListHead
;
46 static LIST_ENTRY VacbLruListHead
;
48 KGUARDED_MUTEX ViewLock
;
50 NPAGED_LOOKASIDE_LIST iBcbLookasideList
;
51 static NPAGED_LOOKASIDE_LIST SharedCacheMapLookasideList
;
52 static NPAGED_LOOKASIDE_LIST VacbLookasideList
;
54 /* Internal vars (MS):
55 * - Threshold above which lazy writer will start action
56 * - Amount of dirty pages
57 * - List for deferred writes
58 * - Spinlock when dealing with the deferred list
59 * - List for "clean" shared cache maps
61 ULONG CcDirtyPageThreshold
= 0;
62 ULONG CcTotalDirtyPages
= 0;
63 LIST_ENTRY CcDeferredWrites
;
64 KSPIN_LOCK CcDeferredWriteSpinLock
;
65 LIST_ENTRY CcCleanSharedCacheMapList
;
68 ULONG
CcRosVacbIncRefCount_(PROS_VACB vacb
, PCSTR file
, INT line
)
72 Refs
= InterlockedIncrement((PLONG
)&vacb
->ReferenceCount
);
73 if (vacb
->SharedCacheMap
->Trace
)
75 DbgPrint("(%s:%i) VACB %p ++RefCount=%lu, Dirty %u, PageOut %lu\n",
76 file
, line
, vacb
, Refs
, vacb
->Dirty
, vacb
->PageOut
);
81 ULONG
CcRosVacbDecRefCount_(PROS_VACB vacb
, PCSTR file
, INT line
)
85 Refs
= InterlockedDecrement((PLONG
)&vacb
->ReferenceCount
);
86 ASSERT(!(Refs
== 0 && vacb
->Dirty
));
87 if (vacb
->SharedCacheMap
->Trace
)
89 DbgPrint("(%s:%i) VACB %p --RefCount=%lu, Dirty %u, PageOut %lu\n",
90 file
, line
, vacb
, Refs
, vacb
->Dirty
, vacb
->PageOut
);
95 CcRosInternalFreeVacb(vacb
);
100 ULONG
CcRosVacbGetRefCount_(PROS_VACB vacb
, PCSTR file
, INT line
)
104 Refs
= InterlockedCompareExchange((PLONG
)&vacb
->ReferenceCount
, 0, 0);
105 if (vacb
->SharedCacheMap
->Trace
)
107 DbgPrint("(%s:%i) VACB %p ==RefCount=%lu, Dirty %u, PageOut %lu\n",
108 file
, line
, vacb
, Refs
, vacb
->Dirty
, vacb
->PageOut
);
116 /* FUNCTIONS *****************************************************************/
121 PROS_SHARED_CACHE_MAP SharedCacheMap
,
126 PLIST_ENTRY current_entry
;
132 SharedCacheMap
->Trace
= Trace
;
136 DPRINT1("Enabling Tracing for CacheMap 0x%p:\n", SharedCacheMap
);
138 KeAcquireGuardedMutex(&ViewLock
);
139 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldirql
);
141 current_entry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
142 while (current_entry
!= &SharedCacheMap
->CacheMapVacbListHead
)
144 current
= CONTAINING_RECORD(current_entry
, ROS_VACB
, CacheMapVacbListEntry
);
145 current_entry
= current_entry
->Flink
;
147 DPRINT1(" VACB 0x%p enabled, RefCount %lu, Dirty %u, PageOut %lu\n",
148 current
, current
->ReferenceCount
, current
->Dirty
, current
->PageOut
);
150 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldirql
);
151 KeReleaseGuardedMutex(&ViewLock
);
155 DPRINT1("Disabling Tracing for CacheMap 0x%p:\n", SharedCacheMap
);
159 UNREFERENCED_PARAMETER(SharedCacheMap
);
160 UNREFERENCED_PARAMETER(Trace
);
171 CcRosUnmarkDirtyVacb(Vacb
, TRUE
);
173 Status
= CcWriteVirtualAddress(Vacb
);
174 if (!NT_SUCCESS(Status
))
176 CcRosMarkDirtyVacb(Vacb
);
184 CcRosFlushDirtyPages (
188 BOOLEAN CalledFromLazy
)
190 PLIST_ENTRY current_entry
;
195 DPRINT("CcRosFlushDirtyPages(Target %lu)\n", Target
);
199 KeEnterCriticalRegion();
200 KeAcquireGuardedMutex(&ViewLock
);
202 current_entry
= DirtyVacbListHead
.Flink
;
203 if (current_entry
== &DirtyVacbListHead
)
205 DPRINT("No Dirty pages\n");
208 while ((current_entry
!= &DirtyVacbListHead
) && (Target
> 0))
210 current
= CONTAINING_RECORD(current_entry
,
213 current_entry
= current_entry
->Flink
;
215 CcRosVacbIncRefCount(current
);
217 /* When performing lazy write, don't handle temporary files */
218 if (CalledFromLazy
&&
219 BooleanFlagOn(current
->SharedCacheMap
->FileObject
->Flags
, FO_TEMPORARY_FILE
))
221 CcRosVacbDecRefCount(current
);
225 Locked
= current
->SharedCacheMap
->Callbacks
->AcquireForLazyWrite(
226 current
->SharedCacheMap
->LazyWriteContext
, Wait
);
229 CcRosVacbDecRefCount(current
);
233 ASSERT(current
->Dirty
);
235 KeReleaseGuardedMutex(&ViewLock
);
237 Status
= CcRosFlushVacb(current
);
239 current
->SharedCacheMap
->Callbacks
->ReleaseFromLazyWrite(
240 current
->SharedCacheMap
->LazyWriteContext
);
242 KeAcquireGuardedMutex(&ViewLock
);
243 CcRosVacbDecRefCount(current
);
245 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_END_OF_FILE
) &&
246 (Status
!= STATUS_MEDIA_WRITE_PROTECTED
))
248 DPRINT1("CC: Failed to flush VACB.\n");
254 /* How many pages did we free? */
255 PagesFreed
= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
256 (*Count
) += PagesFreed
;
258 /* Make sure we don't overflow target! */
259 if (Target
< PagesFreed
)
261 /* If we would have, jump to zero directly */
266 Target
-= PagesFreed
;
270 current_entry
= DirtyVacbListHead
.Flink
;
273 KeReleaseGuardedMutex(&ViewLock
);
274 KeLeaveCriticalRegion();
276 DPRINT("CcRosFlushDirtyPages() finished\n");
277 return STATUS_SUCCESS
;
286 * FUNCTION: Try to free some memory from the file cache.
288 * Target - The number of pages to be freed.
289 * Priority - The priority of free (currently unused).
290 * NrFreed - Points to a variable where the number of pages
291 * actually freed is returned.
294 PLIST_ENTRY current_entry
;
301 BOOLEAN FlushedPages
= FALSE
;
303 DPRINT("CcRosTrimCache(Target %lu)\n", Target
);
305 InitializeListHead(&FreeList
);
310 KeAcquireGuardedMutex(&ViewLock
);
312 current_entry
= VacbLruListHead
.Flink
;
313 while (current_entry
!= &VacbLruListHead
)
317 current
= CONTAINING_RECORD(current_entry
,
320 current_entry
= current_entry
->Flink
;
322 KeAcquireSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, &oldIrql
);
324 /* Reference the VACB */
325 CcRosVacbIncRefCount(current
);
327 /* Check if it's mapped and not dirty */
328 if (InterlockedCompareExchange((PLONG
)¤t
->MappedCount
, 0, 0) > 0 && !current
->Dirty
)
330 /* We have to break these locks because Cc sucks */
331 KeReleaseSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, oldIrql
);
332 KeReleaseGuardedMutex(&ViewLock
);
334 /* Page out the VACB */
335 for (i
= 0; i
< VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
; i
++)
337 Page
= (PFN_NUMBER
)(MmGetPhysicalAddress((PUCHAR
)current
->BaseAddress
+ (i
* PAGE_SIZE
)).QuadPart
>> PAGE_SHIFT
);
339 MmPageOutPhysicalAddress(Page
);
342 /* Reacquire the locks */
343 KeAcquireGuardedMutex(&ViewLock
);
344 KeAcquireSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, &oldIrql
);
347 /* Dereference the VACB */
348 Refs
= CcRosVacbDecRefCount(current
);
350 /* Check if we can free this entry now */
353 ASSERT(!current
->Dirty
);
354 ASSERT(!current
->MappedCount
);
357 RemoveEntryList(¤t
->CacheMapVacbListEntry
);
358 RemoveEntryList(¤t
->VacbLruListEntry
);
359 InitializeListHead(¤t
->VacbLruListEntry
);
360 InsertHeadList(&FreeList
, ¤t
->CacheMapVacbListEntry
);
362 /* Calculate how many pages we freed for Mm */
363 PagesFreed
= min(VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
, Target
);
364 Target
-= PagesFreed
;
365 (*NrFreed
) += PagesFreed
;
368 KeReleaseSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, oldIrql
);
371 KeReleaseGuardedMutex(&ViewLock
);
373 /* Try flushing pages if we haven't met our target */
374 if ((Target
> 0) && !FlushedPages
)
376 /* Flush dirty pages to disk */
377 CcRosFlushDirtyPages(Target
, &PagesFreed
, FALSE
, FALSE
);
380 /* We can only swap as many pages as we flushed */
381 if (PagesFreed
< Target
) Target
= PagesFreed
;
383 /* Check if we flushed anything */
386 /* Try again after flushing dirty pages */
387 DPRINT("Flushed %lu dirty cache pages to disk\n", PagesFreed
);
392 while (!IsListEmpty(&FreeList
))
396 current_entry
= RemoveHeadList(&FreeList
);
397 current
= CONTAINING_RECORD(current_entry
,
399 CacheMapVacbListEntry
);
400 InitializeListHead(¤t
->CacheMapVacbListEntry
);
401 Refs
= CcRosVacbDecRefCount(current
);
405 DPRINT("Evicted %lu cache pages\n", (*NrFreed
));
407 return STATUS_SUCCESS
;
413 PROS_SHARED_CACHE_MAP SharedCacheMap
,
420 ASSERT(SharedCacheMap
);
422 DPRINT("CcRosReleaseVacb(SharedCacheMap 0x%p, Vacb 0x%p, Valid %u)\n",
423 SharedCacheMap
, Vacb
, Valid
);
427 if (Dirty
&& !Vacb
->Dirty
)
429 CcRosMarkDirtyVacb(Vacb
);
434 if (InterlockedIncrement((PLONG
)&Vacb
->MappedCount
) == 1)
436 CcRosVacbIncRefCount(Vacb
);
440 Refs
= CcRosVacbDecRefCount(Vacb
);
443 return STATUS_SUCCESS
;
446 /* Returns with VACB Lock Held! */
450 PROS_SHARED_CACHE_MAP SharedCacheMap
,
453 PLIST_ENTRY current_entry
;
457 ASSERT(SharedCacheMap
);
459 DPRINT("CcRosLookupVacb(SharedCacheMap 0x%p, FileOffset %I64u)\n",
460 SharedCacheMap
, FileOffset
);
462 KeAcquireGuardedMutex(&ViewLock
);
463 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
465 current_entry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
466 while (current_entry
!= &SharedCacheMap
->CacheMapVacbListHead
)
468 current
= CONTAINING_RECORD(current_entry
,
470 CacheMapVacbListEntry
);
471 if (IsPointInRange(current
->FileOffset
.QuadPart
,
472 VACB_MAPPING_GRANULARITY
,
475 CcRosVacbIncRefCount(current
);
476 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
477 KeReleaseGuardedMutex(&ViewLock
);
480 if (current
->FileOffset
.QuadPart
> FileOffset
)
482 current_entry
= current_entry
->Flink
;
485 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
486 KeReleaseGuardedMutex(&ViewLock
);
497 PROS_SHARED_CACHE_MAP SharedCacheMap
;
499 SharedCacheMap
= Vacb
->SharedCacheMap
;
501 KeAcquireGuardedMutex(&ViewLock
);
502 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
504 ASSERT(!Vacb
->Dirty
);
506 InsertTailList(&DirtyVacbListHead
, &Vacb
->DirtyVacbListEntry
);
507 CcTotalDirtyPages
+= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
508 Vacb
->SharedCacheMap
->DirtyPages
+= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
509 CcRosVacbIncRefCount(Vacb
);
511 /* Move to the tail of the LRU list */
512 RemoveEntryList(&Vacb
->VacbLruListEntry
);
513 InsertTailList(&VacbLruListHead
, &Vacb
->VacbLruListEntry
);
517 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
518 KeReleaseGuardedMutex(&ViewLock
);
520 /* Schedule a lazy writer run to now that we have dirty VACB */
521 oldIrql
= KeAcquireQueuedSpinLock(LockQueueMasterLock
);
522 if (!LazyWriter
.ScanActive
)
524 CcScheduleLazyWriteScan(FALSE
);
526 KeReleaseQueuedSpinLock(LockQueueMasterLock
, oldIrql
);
531 CcRosUnmarkDirtyVacb (
536 PROS_SHARED_CACHE_MAP SharedCacheMap
;
538 SharedCacheMap
= Vacb
->SharedCacheMap
;
542 KeAcquireGuardedMutex(&ViewLock
);
543 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
550 RemoveEntryList(&Vacb
->DirtyVacbListEntry
);
551 InitializeListHead(&Vacb
->DirtyVacbListEntry
);
552 CcTotalDirtyPages
-= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
553 Vacb
->SharedCacheMap
->DirtyPages
-= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
554 CcRosVacbDecRefCount(Vacb
);
558 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
559 KeReleaseGuardedMutex(&ViewLock
);
566 PROS_SHARED_CACHE_MAP SharedCacheMap
,
571 ASSERT(SharedCacheMap
);
573 DPRINT("CcRosMarkDirtyVacb(SharedCacheMap 0x%p, FileOffset %I64u)\n",
574 SharedCacheMap
, FileOffset
);
576 Vacb
= CcRosLookupVacb(SharedCacheMap
, FileOffset
);
579 KeBugCheck(CACHE_MANAGER
);
582 CcRosReleaseVacb(SharedCacheMap
, Vacb
, Vacb
->Valid
, TRUE
, FALSE
);
584 return STATUS_SUCCESS
;
588 * Note: this is not the contrary function of
589 * CcRosMapVacbInKernelSpace()
594 PROS_SHARED_CACHE_MAP SharedCacheMap
,
600 ASSERT(SharedCacheMap
);
602 DPRINT("CcRosUnmapVacb(SharedCacheMap 0x%p, FileOffset %I64u, NowDirty %u)\n",
603 SharedCacheMap
, FileOffset
, NowDirty
);
605 Vacb
= CcRosLookupVacb(SharedCacheMap
, FileOffset
);
608 return STATUS_UNSUCCESSFUL
;
611 ASSERT(Vacb
->MappedCount
!= 0);
612 if (InterlockedDecrement((PLONG
)&Vacb
->MappedCount
) == 0)
614 CcRosVacbDecRefCount(Vacb
);
617 CcRosReleaseVacb(SharedCacheMap
, Vacb
, Vacb
->Valid
, NowDirty
, FALSE
);
619 return STATUS_SUCCESS
;
624 CcRosMapVacbInKernelSpace(
629 ULONG_PTR NumberOfPages
;
630 PVOID BaseAddress
= NULL
;
632 /* Create a memory area. */
633 MmLockAddressSpace(MmGetKernelAddressSpace());
634 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
635 0, // nothing checks for VACB mareas, so set to 0
637 VACB_MAPPING_GRANULARITY
,
639 (PMEMORY_AREA
*)&Vacb
->MemoryArea
,
642 ASSERT(Vacb
->BaseAddress
== NULL
);
643 Vacb
->BaseAddress
= BaseAddress
;
644 MmUnlockAddressSpace(MmGetKernelAddressSpace());
645 if (!NT_SUCCESS(Status
))
647 DPRINT1("MmCreateMemoryArea failed with %lx for VACB %p\n", Status
, Vacb
);
651 ASSERT(((ULONG_PTR
)Vacb
->BaseAddress
% PAGE_SIZE
) == 0);
652 ASSERT((ULONG_PTR
)Vacb
->BaseAddress
> (ULONG_PTR
)MmSystemRangeStart
);
653 ASSERT((ULONG_PTR
)Vacb
->BaseAddress
+ VACB_MAPPING_GRANULARITY
- 1 > (ULONG_PTR
)MmSystemRangeStart
);
655 /* Create a virtual mapping for this memory area */
656 NumberOfPages
= BYTES_TO_PAGES(VACB_MAPPING_GRANULARITY
);
657 for (i
= 0; i
< NumberOfPages
; i
++)
659 PFN_NUMBER PageFrameNumber
;
661 MI_SET_USAGE(MI_USAGE_CACHE
);
662 Status
= MmRequestPageMemoryConsumer(MC_CACHE
, TRUE
, &PageFrameNumber
);
663 if (PageFrameNumber
== 0)
665 DPRINT1("Unable to allocate page\n");
666 KeBugCheck(MEMORY_MANAGEMENT
);
669 ASSERT(BaseAddress
== Vacb
->BaseAddress
);
670 ASSERT(i
* PAGE_SIZE
< VACB_MAPPING_GRANULARITY
);
671 ASSERT((ULONG_PTR
)Vacb
->BaseAddress
+ (i
* PAGE_SIZE
) >= (ULONG_PTR
)BaseAddress
);
672 ASSERT((ULONG_PTR
)Vacb
->BaseAddress
+ (i
* PAGE_SIZE
) > (ULONG_PTR
)MmSystemRangeStart
);
674 Status
= MmCreateVirtualMapping(NULL
,
675 (PVOID
)((ULONG_PTR
)Vacb
->BaseAddress
+ (i
* PAGE_SIZE
)),
679 if (!NT_SUCCESS(Status
))
681 DPRINT1("Unable to create virtual mapping\n");
682 KeBugCheck(MEMORY_MANAGEMENT
);
686 return STATUS_SUCCESS
;
691 CcRosFreeUnusedVacb (
699 PLIST_ENTRY current_entry
;
703 InitializeListHead(&FreeList
);
705 KeAcquireGuardedMutex(&ViewLock
);
707 /* Browse all the available VACB */
708 current_entry
= VacbLruListHead
.Flink
;
709 while (current_entry
!= &VacbLruListHead
)
713 current
= CONTAINING_RECORD(current_entry
,
716 current_entry
= current_entry
->Flink
;
718 KeAcquireSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, &oldIrql
);
720 /* Only deal with unused VACB, we will free them */
721 Refs
= CcRosVacbGetRefCount(current
);
724 ASSERT(!current
->Dirty
);
725 ASSERT(!current
->MappedCount
);
728 /* Reset and move to free list */
729 RemoveEntryList(¤t
->CacheMapVacbListEntry
);
730 RemoveEntryList(¤t
->VacbLruListEntry
);
731 InitializeListHead(¤t
->VacbLruListEntry
);
732 InsertHeadList(&FreeList
, ¤t
->CacheMapVacbListEntry
);
735 KeReleaseSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, oldIrql
);
739 KeReleaseGuardedMutex(&ViewLock
);
741 /* And now, free any of the found VACB, that'll free memory! */
742 while (!IsListEmpty(&FreeList
))
746 current_entry
= RemoveHeadList(&FreeList
);
747 current
= CONTAINING_RECORD(current_entry
,
749 CacheMapVacbListEntry
);
750 InitializeListHead(¤t
->CacheMapVacbListEntry
);
751 Refs
= CcRosVacbDecRefCount(current
);
756 /* If we freed at least one VACB, return success */
762 /* If caller asked for free count, return it */
774 PROS_SHARED_CACHE_MAP SharedCacheMap
,
780 PLIST_ENTRY current_entry
;
786 ASSERT(SharedCacheMap
);
788 DPRINT("CcRosCreateVacb()\n");
790 if (FileOffset
>= SharedCacheMap
->SectionSize
.QuadPart
)
793 return STATUS_INVALID_PARAMETER
;
796 current
= ExAllocateFromNPagedLookasideList(&VacbLookasideList
);
797 current
->BaseAddress
= NULL
;
798 current
->Valid
= FALSE
;
799 current
->Dirty
= FALSE
;
800 current
->PageOut
= FALSE
;
801 current
->FileOffset
.QuadPart
= ROUND_DOWN(FileOffset
, VACB_MAPPING_GRANULARITY
);
802 current
->SharedCacheMap
= SharedCacheMap
;
804 if (SharedCacheMap
->Trace
)
806 DPRINT1("CacheMap 0x%p: new VACB: 0x%p\n", SharedCacheMap
, current
);
809 current
->MappedCount
= 0;
810 current
->ReferenceCount
= 0;
811 current
->PinCount
= 0;
812 InitializeListHead(¤t
->CacheMapVacbListEntry
);
813 InitializeListHead(¤t
->DirtyVacbListEntry
);
814 InitializeListHead(¤t
->VacbLruListEntry
);
816 CcRosVacbIncRefCount(current
);
820 /* Map VACB in kernel space */
821 Status
= CcRosMapVacbInKernelSpace(current
);
822 if (!NT_SUCCESS(Status
))
825 /* If no space left, try to prune unused VACB
826 * to recover space to map our VACB
827 * If it succeed, retry to map, otherwise
830 if (!Retried
&& CcRosFreeUnusedVacb(&Freed
))
832 DPRINT("Prunned %d VACB, trying again\n", Freed
);
837 CcRosVacbDecRefCount(current
);
838 ExFreeToNPagedLookasideList(&VacbLookasideList
, current
);
842 KeAcquireGuardedMutex(&ViewLock
);
845 /* There is window between the call to CcRosLookupVacb
846 * and CcRosCreateVacb. We must check if a VACB for the
847 * file offset exist. If there is a VACB, we release
848 * our newly created VACB and return the existing one.
850 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
851 current_entry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
853 while (current_entry
!= &SharedCacheMap
->CacheMapVacbListHead
)
855 current
= CONTAINING_RECORD(current_entry
,
857 CacheMapVacbListEntry
);
858 if (IsPointInRange(current
->FileOffset
.QuadPart
,
859 VACB_MAPPING_GRANULARITY
,
862 CcRosVacbIncRefCount(current
);
863 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
865 if (SharedCacheMap
->Trace
)
867 DPRINT1("CacheMap 0x%p: deleting newly created VACB 0x%p ( found existing one 0x%p )\n",
873 KeReleaseGuardedMutex(&ViewLock
);
875 Refs
= CcRosVacbDecRefCount(*Vacb
);
879 return STATUS_SUCCESS
;
881 if (current
->FileOffset
.QuadPart
< FileOffset
)
883 ASSERT(previous
== NULL
||
884 previous
->FileOffset
.QuadPart
< current
->FileOffset
.QuadPart
);
887 if (current
->FileOffset
.QuadPart
> FileOffset
)
889 current_entry
= current_entry
->Flink
;
891 /* There was no existing VACB. */
895 InsertHeadList(&previous
->CacheMapVacbListEntry
, ¤t
->CacheMapVacbListEntry
);
899 InsertHeadList(&SharedCacheMap
->CacheMapVacbListHead
, ¤t
->CacheMapVacbListEntry
);
901 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
902 InsertTailList(&VacbLruListHead
, ¤t
->VacbLruListEntry
);
903 KeReleaseGuardedMutex(&ViewLock
);
905 MI_SET_USAGE(MI_USAGE_CACHE
);
907 if ((SharedCacheMap
->FileObject
) && (SharedCacheMap
->FileObject
->FileName
.Buffer
))
911 pos
= wcsrchr(SharedCacheMap
->FileObject
->FileName
.Buffer
, '\\');
914 len
= wcslen(pos
) * sizeof(WCHAR
);
915 snprintf(MI_PFN_CURRENT_PROCESS_NAME
, min(16, len
), "%S", pos
);
919 snprintf(MI_PFN_CURRENT_PROCESS_NAME
, min(16, len
), "%wZ", &SharedCacheMap
->FileObject
->FileName
);
924 /* Reference it to allow release */
925 CcRosVacbIncRefCount(current
);
933 PROS_SHARED_CACHE_MAP SharedCacheMap
,
935 PLONGLONG BaseOffset
,
944 ASSERT(SharedCacheMap
);
946 DPRINT("CcRosGetVacb()\n");
949 * Look for a VACB already mapping the same data.
951 current
= CcRosLookupVacb(SharedCacheMap
, FileOffset
);
955 * Otherwise create a new VACB.
957 Status
= CcRosCreateVacb(SharedCacheMap
, FileOffset
, ¤t
);
958 if (!NT_SUCCESS(Status
))
964 Refs
= CcRosVacbGetRefCount(current
);
966 KeAcquireGuardedMutex(&ViewLock
);
968 /* Move to the tail of the LRU list */
969 RemoveEntryList(¤t
->VacbLruListEntry
);
970 InsertTailList(&VacbLruListHead
, ¤t
->VacbLruListEntry
);
972 KeReleaseGuardedMutex(&ViewLock
);
975 * Return information about the VACB to the caller.
977 *UptoDate
= current
->Valid
;
978 *BaseAddress
= current
->BaseAddress
;
979 DPRINT("*BaseAddress %p\n", *BaseAddress
);
981 *BaseOffset
= current
->FileOffset
.QuadPart
;
985 return STATUS_SUCCESS
;
991 PROS_SHARED_CACHE_MAP SharedCacheMap
,
997 * FUNCTION: Request a page mapping for a shared cache map
1000 LONGLONG BaseOffset
;
1002 ASSERT(SharedCacheMap
);
1004 if (FileOffset
% VACB_MAPPING_GRANULARITY
!= 0)
1006 DPRINT1("Bad fileoffset %I64x should be multiple of %x",
1007 FileOffset
, VACB_MAPPING_GRANULARITY
);
1008 KeBugCheck(CACHE_MANAGER
);
1011 return CcRosGetVacb(SharedCacheMap
,
1023 MEMORY_AREA
* MemoryArea
,
1026 SWAPENTRY SwapEntry
,
1029 ASSERT(SwapEntry
== 0);
1032 ASSERT(MmGetReferenceCountPage(Page
) == 1);
1033 MmReleasePageMemoryConsumer(MC_CACHE
, Page
);
1038 CcRosInternalFreeVacb (
1041 * FUNCTION: Releases a VACB associated with a shared cache map
1044 DPRINT("Freeing VACB 0x%p\n", Vacb
);
1046 if (Vacb
->SharedCacheMap
->Trace
)
1048 DPRINT1("CacheMap 0x%p: deleting VACB: 0x%p\n", Vacb
->SharedCacheMap
, Vacb
);
1052 MmLockAddressSpace(MmGetKernelAddressSpace());
1053 MmFreeMemoryArea(MmGetKernelAddressSpace(),
1057 MmUnlockAddressSpace(MmGetKernelAddressSpace());
1059 if (Vacb
->PinCount
!= 0 || Vacb
->ReferenceCount
!= 0)
1061 DPRINT1("Invalid free: %ld, %ld\n", Vacb
->ReferenceCount
, Vacb
->PinCount
);
1062 if (Vacb
->SharedCacheMap
->FileObject
&& Vacb
->SharedCacheMap
->FileObject
->FileName
.Length
)
1064 DPRINT1("For file: %wZ\n", &Vacb
->SharedCacheMap
->FileObject
->FileName
);
1068 ASSERT(Vacb
->PinCount
== 0);
1069 ASSERT(Vacb
->ReferenceCount
== 0);
1070 ASSERT(IsListEmpty(&Vacb
->CacheMapVacbListEntry
));
1071 ASSERT(IsListEmpty(&Vacb
->DirtyVacbListEntry
));
1072 ASSERT(IsListEmpty(&Vacb
->VacbLruListEntry
));
1073 RtlFillMemory(Vacb
, sizeof(*Vacb
), 0xfd);
1074 ExFreeToNPagedLookasideList(&VacbLookasideList
, Vacb
);
1075 return STATUS_SUCCESS
;
1084 IN PSECTION_OBJECT_POINTERS SectionObjectPointers
,
1085 IN PLARGE_INTEGER FileOffset OPTIONAL
,
1087 OUT PIO_STATUS_BLOCK IoStatus
)
1089 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1090 LARGE_INTEGER Offset
;
1091 LONGLONG RemainingLength
;
1095 CCTRACE(CC_API_DEBUG
, "SectionObjectPointers=%p FileOffset=%p Length=%lu\n",
1096 SectionObjectPointers
, FileOffset
, Length
);
1098 DPRINT("CcFlushCache(SectionObjectPointers 0x%p, FileOffset 0x%p, Length %lu, IoStatus 0x%p)\n",
1099 SectionObjectPointers
, FileOffset
, Length
, IoStatus
);
1101 if (SectionObjectPointers
&& SectionObjectPointers
->SharedCacheMap
)
1103 SharedCacheMap
= SectionObjectPointers
->SharedCacheMap
;
1104 ASSERT(SharedCacheMap
);
1107 Offset
= *FileOffset
;
1108 RemainingLength
= Length
;
1112 Offset
.QuadPart
= 0;
1113 RemainingLength
= SharedCacheMap
->FileSize
.QuadPart
;
1118 IoStatus
->Status
= STATUS_SUCCESS
;
1119 IoStatus
->Information
= 0;
1122 while (RemainingLength
> 0)
1124 current
= CcRosLookupVacb(SharedCacheMap
, Offset
.QuadPart
);
1125 if (current
!= NULL
)
1129 Status
= CcRosFlushVacb(current
);
1130 if (!NT_SUCCESS(Status
) && IoStatus
!= NULL
)
1132 IoStatus
->Status
= Status
;
1136 CcRosReleaseVacb(SharedCacheMap
, current
, current
->Valid
, current
->Dirty
, FALSE
);
1139 Offset
.QuadPart
+= VACB_MAPPING_GRANULARITY
;
1140 RemainingLength
-= min(RemainingLength
, VACB_MAPPING_GRANULARITY
);
1147 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
1154 CcRosDeleteFileCache (
1155 PFILE_OBJECT FileObject
,
1156 PROS_SHARED_CACHE_MAP SharedCacheMap
)
1158 * FUNCTION: Releases the shared cache map associated with a file object
1161 PLIST_ENTRY current_entry
;
1163 LIST_ENTRY FreeList
;
1166 ASSERT(SharedCacheMap
);
1168 SharedCacheMap
->OpenCount
++;
1169 KeReleaseGuardedMutex(&ViewLock
);
1171 CcFlushCache(FileObject
->SectionObjectPointer
, NULL
, 0, NULL
);
1173 KeAcquireGuardedMutex(&ViewLock
);
1174 SharedCacheMap
->OpenCount
--;
1175 if (SharedCacheMap
->OpenCount
== 0)
1179 FileObject
->SectionObjectPointer
->SharedCacheMap
= NULL
;
1184 InitializeListHead(&FreeList
);
1185 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
1186 while (!IsListEmpty(&SharedCacheMap
->CacheMapVacbListHead
))
1188 current_entry
= RemoveTailList(&SharedCacheMap
->CacheMapVacbListHead
);
1189 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
1191 current
= CONTAINING_RECORD(current_entry
, ROS_VACB
, CacheMapVacbListEntry
);
1192 RemoveEntryList(¤t
->VacbLruListEntry
);
1193 InitializeListHead(¤t
->VacbLruListEntry
);
1196 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
1197 CcRosUnmarkDirtyVacb(current
, FALSE
);
1198 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
1199 DPRINT1("Freeing dirty VACB\n");
1201 if (current
->MappedCount
!= 0)
1203 current
->MappedCount
= 0;
1204 NT_VERIFY(CcRosVacbDecRefCount(current
) > 0);
1205 DPRINT1("Freeing mapped VACB\n");
1207 InsertHeadList(&FreeList
, ¤t
->CacheMapVacbListEntry
);
1209 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
1212 SharedCacheMap
->Trace
= FALSE
;
1214 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
1216 KeReleaseGuardedMutex(&ViewLock
);
1217 ObDereferenceObject(SharedCacheMap
->FileObject
);
1219 while (!IsListEmpty(&FreeList
))
1223 current_entry
= RemoveTailList(&FreeList
);
1224 current
= CONTAINING_RECORD(current_entry
, ROS_VACB
, CacheMapVacbListEntry
);
1225 InitializeListHead(¤t
->CacheMapVacbListEntry
);
1226 Refs
= CcRosVacbDecRefCount(current
);
1227 #if DBG // CORE-14578
1230 DPRINT1("Leaking VACB %p attached to %p (%I64d)\n", current
, FileObject
, current
->FileOffset
.QuadPart
);
1231 DPRINT1("There are: %d references left\n", Refs
);
1232 DPRINT1("Pin: %d, Map: %d\n", current
->PinCount
, current
->MappedCount
);
1233 DPRINT1("Dirty: %d\n", current
->Dirty
);
1234 if (FileObject
->FileName
.Length
!= 0)
1236 DPRINT1("File was: %wZ\n", &FileObject
->FileName
);
1238 else if (FileObject
->FsContext
!= NULL
&&
1239 ((PFSRTL_COMMON_FCB_HEADER
)(FileObject
->FsContext
))->NodeTypeCode
== 0x0502 &&
1240 ((PFSRTL_COMMON_FCB_HEADER
)(FileObject
->FsContext
))->NodeByteSize
== 0x1F8 &&
1241 ((PUNICODE_STRING
)(((PUCHAR
)FileObject
->FsContext
) + 0x100))->Length
!= 0)
1243 DPRINT1("File was: %wZ (FastFAT)\n", (PUNICODE_STRING
)(((PUCHAR
)FileObject
->FsContext
) + 0x100));
1247 DPRINT1("No name for the file\n");
1255 OldIrql
= KeAcquireQueuedSpinLock(LockQueueMasterLock
);
1256 RemoveEntryList(&SharedCacheMap
->SharedCacheMapLinks
);
1257 KeReleaseQueuedSpinLock(LockQueueMasterLock
, OldIrql
);
1259 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList
, SharedCacheMap
);
1260 KeAcquireGuardedMutex(&ViewLock
);
1262 return STATUS_SUCCESS
;
1267 CcRosReferenceCache (
1268 PFILE_OBJECT FileObject
)
1270 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1271 KeAcquireGuardedMutex(&ViewLock
);
1272 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1273 ASSERT(SharedCacheMap
);
1274 ASSERT(SharedCacheMap
->OpenCount
!= 0);
1275 SharedCacheMap
->OpenCount
++;
1276 KeReleaseGuardedMutex(&ViewLock
);
1281 CcRosRemoveIfClosed (
1282 PSECTION_OBJECT_POINTERS SectionObjectPointer
)
1284 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1285 DPRINT("CcRosRemoveIfClosed()\n");
1286 KeAcquireGuardedMutex(&ViewLock
);
1287 SharedCacheMap
= SectionObjectPointer
->SharedCacheMap
;
1288 if (SharedCacheMap
&& SharedCacheMap
->OpenCount
== 0)
1290 CcRosDeleteFileCache(SharedCacheMap
->FileObject
, SharedCacheMap
);
1292 KeReleaseGuardedMutex(&ViewLock
);
1298 CcRosDereferenceCache (
1299 PFILE_OBJECT FileObject
)
1301 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1302 KeAcquireGuardedMutex(&ViewLock
);
1303 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1304 ASSERT(SharedCacheMap
);
1305 if (SharedCacheMap
->OpenCount
> 0)
1307 SharedCacheMap
->OpenCount
--;
1308 if (SharedCacheMap
->OpenCount
== 0)
1310 MmFreeSectionSegments(SharedCacheMap
->FileObject
);
1311 CcRosDeleteFileCache(FileObject
, SharedCacheMap
);
1314 KeReleaseGuardedMutex(&ViewLock
);
1319 CcRosReleaseFileCache (
1320 PFILE_OBJECT FileObject
)
1322 * FUNCTION: Called by the file system when a handle to a file object
1327 PPRIVATE_CACHE_MAP PrivateMap
;
1328 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1330 KeAcquireGuardedMutex(&ViewLock
);
1332 if (FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
1334 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1336 /* Closing the handle, so kill the private cache map
1337 * Before you event try to remove it from FO, always
1338 * lock the master lock, to be sure not to race
1339 * with a potential read ahead ongoing!
1341 OldIrql
= KeAcquireQueuedSpinLock(LockQueueMasterLock
);
1342 PrivateMap
= FileObject
->PrivateCacheMap
;
1343 FileObject
->PrivateCacheMap
= NULL
;
1344 KeReleaseQueuedSpinLock(LockQueueMasterLock
, OldIrql
);
1346 if (PrivateMap
!= NULL
)
1348 /* Remove it from the file */
1349 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &OldIrql
);
1350 RemoveEntryList(&PrivateMap
->PrivateLinks
);
1351 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, OldIrql
);
1354 if (PrivateMap
!= &SharedCacheMap
->PrivateCacheMap
)
1356 ExFreePoolWithTag(PrivateMap
, TAG_PRIVATE_CACHE_MAP
);
1360 PrivateMap
->NodeTypeCode
= 0;
1363 if (SharedCacheMap
->OpenCount
> 0)
1365 SharedCacheMap
->OpenCount
--;
1366 if (SharedCacheMap
->OpenCount
== 0)
1368 MmFreeSectionSegments(SharedCacheMap
->FileObject
);
1369 CcRosDeleteFileCache(FileObject
, SharedCacheMap
);
1374 KeReleaseGuardedMutex(&ViewLock
);
1375 return STATUS_SUCCESS
;
1380 CcRosInitializeFileCache (
1381 PFILE_OBJECT FileObject
,
1382 PCC_FILE_SIZES FileSizes
,
1384 PCACHE_MANAGER_CALLBACKS CallBacks
,
1385 PVOID LazyWriterContext
)
1387 * FUNCTION: Initializes a shared cache map for a file object
1392 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1394 DPRINT("CcRosInitializeFileCache(FileObject 0x%p)\n", FileObject
);
1397 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1398 if (SharedCacheMap
== NULL
)
1401 SharedCacheMap
= ExAllocateFromNPagedLookasideList(&SharedCacheMapLookasideList
);
1402 if (SharedCacheMap
== NULL
)
1404 return STATUS_INSUFFICIENT_RESOURCES
;
1406 RtlZeroMemory(SharedCacheMap
, sizeof(*SharedCacheMap
));
1407 SharedCacheMap
->NodeTypeCode
= NODE_TYPE_SHARED_MAP
;
1408 SharedCacheMap
->NodeByteSize
= sizeof(*SharedCacheMap
);
1409 SharedCacheMap
->FileObject
= FileObject
;
1410 SharedCacheMap
->Callbacks
= CallBacks
;
1411 SharedCacheMap
->LazyWriteContext
= LazyWriterContext
;
1412 SharedCacheMap
->SectionSize
= FileSizes
->AllocationSize
;
1413 SharedCacheMap
->FileSize
= FileSizes
->FileSize
;
1414 SharedCacheMap
->PinAccess
= PinAccess
;
1415 SharedCacheMap
->DirtyPageThreshold
= 0;
1416 SharedCacheMap
->DirtyPages
= 0;
1417 InitializeListHead(&SharedCacheMap
->PrivateList
);
1418 KeInitializeSpinLock(&SharedCacheMap
->CacheMapLock
);
1419 InitializeListHead(&SharedCacheMap
->CacheMapVacbListHead
);
1420 InitializeListHead(&SharedCacheMap
->BcbList
);
1423 KeAcquireGuardedMutex(&ViewLock
);
1426 if (FileObject
->SectionObjectPointer
->SharedCacheMap
== NULL
)
1428 ObReferenceObjectByPointer(FileObject
,
1432 FileObject
->SectionObjectPointer
->SharedCacheMap
= SharedCacheMap
;
1434 OldIrql
= KeAcquireQueuedSpinLock(LockQueueMasterLock
);
1435 InsertTailList(&CcCleanSharedCacheMapList
, &SharedCacheMap
->SharedCacheMapLinks
);
1436 KeReleaseQueuedSpinLock(LockQueueMasterLock
, OldIrql
);
1440 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList
, SharedCacheMap
);
1441 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1444 if (FileObject
->PrivateCacheMap
== NULL
)
1446 PPRIVATE_CACHE_MAP PrivateMap
;
1448 /* Allocate the private cache map for this handle */
1449 if (SharedCacheMap
->PrivateCacheMap
.NodeTypeCode
!= 0)
1451 PrivateMap
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(PRIVATE_CACHE_MAP
), TAG_PRIVATE_CACHE_MAP
);
1455 PrivateMap
= &SharedCacheMap
->PrivateCacheMap
;
1458 if (PrivateMap
== NULL
)
1460 /* If we also allocated the shared cache map for this file, kill it */
1463 OldIrql
= KeAcquireQueuedSpinLock(LockQueueMasterLock
);
1464 RemoveEntryList(&SharedCacheMap
->SharedCacheMapLinks
);
1465 KeReleaseQueuedSpinLock(LockQueueMasterLock
, OldIrql
);
1467 FileObject
->SectionObjectPointer
->SharedCacheMap
= NULL
;
1468 ObDereferenceObject(FileObject
);
1469 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList
, SharedCacheMap
);
1472 KeReleaseGuardedMutex(&ViewLock
);
1473 return STATUS_INSUFFICIENT_RESOURCES
;
1477 RtlZeroMemory(PrivateMap
, sizeof(PRIVATE_CACHE_MAP
));
1478 PrivateMap
->NodeTypeCode
= NODE_TYPE_PRIVATE_MAP
;
1479 PrivateMap
->ReadAheadMask
= PAGE_SIZE
- 1;
1480 PrivateMap
->FileObject
= FileObject
;
1481 KeInitializeSpinLock(&PrivateMap
->ReadAheadSpinLock
);
1483 /* Link it to the file */
1484 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &OldIrql
);
1485 InsertTailList(&SharedCacheMap
->PrivateList
, &PrivateMap
->PrivateLinks
);
1486 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, OldIrql
);
1488 FileObject
->PrivateCacheMap
= PrivateMap
;
1489 SharedCacheMap
->OpenCount
++;
1491 KeReleaseGuardedMutex(&ViewLock
);
1493 return STATUS_SUCCESS
;
1501 CcGetFileObjectFromSectionPtrs (
1502 IN PSECTION_OBJECT_POINTERS SectionObjectPointers
)
1504 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1506 CCTRACE(CC_API_DEBUG
, "SectionObjectPointers=%p\n", SectionObjectPointers
);
1508 if (SectionObjectPointers
&& SectionObjectPointers
->SharedCacheMap
)
1510 SharedCacheMap
= SectionObjectPointers
->SharedCacheMap
;
1511 ASSERT(SharedCacheMap
);
1512 return SharedCacheMap
->FileObject
;
1523 DPRINT("CcInitView()\n");
1525 InitializeListHead(&DirtyVacbListHead
);
1526 InitializeListHead(&VacbLruListHead
);
1527 InitializeListHead(&CcDeferredWrites
);
1528 InitializeListHead(&CcCleanSharedCacheMapList
);
1529 KeInitializeSpinLock(&CcDeferredWriteSpinLock
);
1530 KeInitializeGuardedMutex(&ViewLock
);
1531 ExInitializeNPagedLookasideList(&iBcbLookasideList
,
1535 sizeof(INTERNAL_BCB
),
1538 ExInitializeNPagedLookasideList(&SharedCacheMapLookasideList
,
1542 sizeof(ROS_SHARED_CACHE_MAP
),
1543 TAG_SHARED_CACHE_MAP
,
1545 ExInitializeNPagedLookasideList(&VacbLookasideList
,
1553 MmInitializeMemoryConsumer(MC_CACHE
, CcRosTrimCache
);
1555 CcInitCacheZeroPage();
1558 #if DBG && defined(KDBG)
1560 ExpKdbgExtFileCache(ULONG Argc
, PCHAR Argv
[])
1562 PLIST_ENTRY ListEntry
;
1563 UNICODE_STRING NoName
= RTL_CONSTANT_STRING(L
"No name for File");
1565 KdbpPrint(" Usage Summary (in kb)\n");
1566 KdbpPrint("Shared\t\tValid\tDirty\tName\n");
1567 /* No need to lock the spin lock here, we're in DBG */
1568 for (ListEntry
= CcCleanSharedCacheMapList
.Flink
;
1569 ListEntry
!= &CcCleanSharedCacheMapList
;
1570 ListEntry
= ListEntry
->Flink
)
1573 ULONG Valid
= 0, Dirty
= 0;
1574 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1575 PUNICODE_STRING FileName
;
1578 SharedCacheMap
= CONTAINING_RECORD(ListEntry
, ROS_SHARED_CACHE_MAP
, SharedCacheMapLinks
);
1581 Dirty
= (SharedCacheMap
->DirtyPages
* PAGE_SIZE
) / 1024;
1583 /* First, count for all the associated VACB */
1584 for (Vacbs
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
1585 Vacbs
!= &SharedCacheMap
->CacheMapVacbListHead
;
1586 Vacbs
= Vacbs
->Flink
)
1590 Vacb
= CONTAINING_RECORD(Vacbs
, ROS_VACB
, CacheMapVacbListEntry
);
1593 Valid
+= VACB_MAPPING_GRANULARITY
/ 1024;
1598 if (SharedCacheMap
->FileObject
!= NULL
&&
1599 SharedCacheMap
->FileObject
->FileName
.Length
!= 0)
1601 FileName
= &SharedCacheMap
->FileObject
->FileName
;
1603 else if (SharedCacheMap
->FileObject
!= NULL
&&
1604 SharedCacheMap
->FileObject
->FsContext
!= NULL
&&
1605 ((PFSRTL_COMMON_FCB_HEADER
)(SharedCacheMap
->FileObject
->FsContext
))->NodeTypeCode
== 0x0502 &&
1606 ((PFSRTL_COMMON_FCB_HEADER
)(SharedCacheMap
->FileObject
->FsContext
))->NodeByteSize
== 0x1F8 &&
1607 ((PUNICODE_STRING
)(((PUCHAR
)SharedCacheMap
->FileObject
->FsContext
) + 0x100))->Length
!= 0)
1609 FileName
= (PUNICODE_STRING
)(((PUCHAR
)SharedCacheMap
->FileObject
->FsContext
) + 0x100);
1610 Extra
= L
" (FastFAT)";
1618 KdbpPrint("%p\t%d\t%d\t%wZ%S\n", SharedCacheMap
, Valid
, Dirty
, FileName
, Extra
);
1625 ExpKdbgExtDefWrites(ULONG Argc
, PCHAR Argv
[])
1627 KdbpPrint("CcTotalDirtyPages:\t%lu (%lu Kb)\n", CcTotalDirtyPages
,
1628 (CcTotalDirtyPages
* PAGE_SIZE
) / 1024);
1629 KdbpPrint("CcDirtyPageThreshold:\t%lu (%lu Kb)\n", CcDirtyPageThreshold
,
1630 (CcDirtyPageThreshold
* PAGE_SIZE
) / 1024);
1631 KdbpPrint("MmAvailablePages:\t%lu (%lu Kb)\n", MmAvailablePages
,
1632 (MmAvailablePages
* PAGE_SIZE
) / 1024);
1633 KdbpPrint("MmThrottleTop:\t\t%lu (%lu Kb)\n", MmThrottleTop
,
1634 (MmThrottleTop
* PAGE_SIZE
) / 1024);
1635 KdbpPrint("MmThrottleBottom:\t%lu (%lu Kb)\n", MmThrottleBottom
,
1636 (MmThrottleBottom
* PAGE_SIZE
) / 1024);
1637 KdbpPrint("MmModifiedPageListHead.Total:\t%lu (%lu Kb)\n", MmModifiedPageListHead
.Total
,
1638 (MmModifiedPageListHead
.Total
* PAGE_SIZE
) / 1024);
1640 if (CcTotalDirtyPages
>= CcDirtyPageThreshold
)
1642 KdbpPrint("CcTotalDirtyPages above the threshold, writes should be throttled\n");
1644 else if (CcTotalDirtyPages
+ 64 >= CcDirtyPageThreshold
)
1646 KdbpPrint("CcTotalDirtyPages within 64 (max charge) pages of the threshold, writes may be throttled\n");
1650 KdbpPrint("CcTotalDirtyPages below the threshold, writes should not be throttled\n");