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)
10 /* NOTES **********************************************************************
12 * This is not the NT implementation of a file cache nor anything much like
15 * The general procedure for a filesystem to implement a read or write
16 * dispatch routine is as follows
18 * (1) If caching for the FCB hasn't been initiated then so do by calling
19 * CcInitializeFileCache.
21 * (2) For each 4k region which is being read or written obtain a cache page
22 * by calling CcRequestCachePage.
24 * (3) If either the page is being read or not completely written, and it is
25 * not up to date then read its data from the underlying medium. If the read
26 * fails then call CcReleaseCachePage with VALID as FALSE and return a error.
28 * (4) Copy the data into or out of the page as necessary.
30 * (5) Release the cache page
32 /* INCLUDES ******************************************************************/
38 #if defined (ALLOC_PRAGMA)
39 #pragma alloc_text(INIT, CcInitView)
42 /* GLOBALS *******************************************************************/
44 static LIST_ENTRY DirtyVacbListHead
;
45 static LIST_ENTRY VacbLruListHead
;
46 ULONG DirtyPageCount
= 0;
48 KGUARDED_MUTEX ViewLock
;
50 NPAGED_LOOKASIDE_LIST iBcbLookasideList
;
51 static NPAGED_LOOKASIDE_LIST SharedCacheMapLookasideList
;
52 static NPAGED_LOOKASIDE_LIST VacbLookasideList
;
55 static void CcRosVacbIncRefCount_(PROS_VACB vacb
, const char* file
, int line
)
57 ++vacb
->ReferenceCount
;
58 if (vacb
->SharedCacheMap
->Trace
)
60 DbgPrint("(%s:%i) VACB %p ++RefCount=%lu, Dirty %u, PageOut %lu\n",
61 file
, line
, vacb
, vacb
->ReferenceCount
, vacb
->Dirty
, vacb
->PageOut
);
64 static void CcRosVacbDecRefCount_(PROS_VACB vacb
, const char* file
, int line
)
66 --vacb
->ReferenceCount
;
67 if (vacb
->SharedCacheMap
->Trace
)
69 DbgPrint("(%s:%i) VACB %p --RefCount=%lu, Dirty %u, PageOut %lu\n",
70 file
, line
, vacb
, vacb
->ReferenceCount
, vacb
->Dirty
, vacb
->PageOut
);
73 #define CcRosVacbIncRefCount(vacb) CcRosVacbIncRefCount_(vacb,__FILE__,__LINE__)
74 #define CcRosVacbDecRefCount(vacb) CcRosVacbDecRefCount_(vacb,__FILE__,__LINE__)
76 #define CcRosVacbIncRefCount(vacb) (++((vacb)->ReferenceCount))
77 #define CcRosVacbDecRefCount(vacb) (--((vacb)->ReferenceCount))
81 CcRosInternalFreeVacb(PROS_VACB Vacb
);
84 /* FUNCTIONS *****************************************************************/
89 PROS_SHARED_CACHE_MAP SharedCacheMap
,
94 PLIST_ENTRY current_entry
;
100 SharedCacheMap
->Trace
= Trace
;
104 DPRINT1("Enabling Tracing for CacheMap 0x%p:\n", SharedCacheMap
);
106 KeAcquireGuardedMutex(&ViewLock
);
107 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldirql
);
109 current_entry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
110 while (current_entry
!= &SharedCacheMap
->CacheMapVacbListHead
)
112 current
= CONTAINING_RECORD(current_entry
, ROS_VACB
, CacheMapVacbListEntry
);
113 current_entry
= current_entry
->Flink
;
115 DPRINT1(" VACB 0x%p enabled, RefCount %lu, Dirty %u, PageOut %lu\n",
116 current
, current
->ReferenceCount
, current
->Dirty
, current
->PageOut
);
118 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldirql
);
119 KeReleaseGuardedMutex(&ViewLock
);
123 DPRINT1("Disabling Tracing for CacheMap 0x%p:\n", SharedCacheMap
);
127 UNREFERENCED_PARAMETER(SharedCacheMap
);
128 UNREFERENCED_PARAMETER(Trace
);
140 Status
= CcWriteVirtualAddress(Vacb
);
141 if (NT_SUCCESS(Status
))
143 KeAcquireGuardedMutex(&ViewLock
);
144 KeAcquireSpinLock(&Vacb
->SharedCacheMap
->CacheMapLock
, &oldIrql
);
147 RemoveEntryList(&Vacb
->DirtyVacbListEntry
);
148 DirtyPageCount
-= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
149 CcRosVacbDecRefCount(Vacb
);
151 KeReleaseSpinLock(&Vacb
->SharedCacheMap
->CacheMapLock
, oldIrql
);
152 KeReleaseGuardedMutex(&ViewLock
);
160 CcRosFlushDirtyPages (
165 PLIST_ENTRY current_entry
;
169 LARGE_INTEGER ZeroTimeout
;
171 DPRINT("CcRosFlushDirtyPages(Target %lu)\n", Target
);
174 ZeroTimeout
.QuadPart
= 0;
176 KeEnterCriticalRegion();
177 KeAcquireGuardedMutex(&ViewLock
);
179 current_entry
= DirtyVacbListHead
.Flink
;
180 if (current_entry
== &DirtyVacbListHead
)
182 DPRINT("No Dirty pages\n");
185 while ((current_entry
!= &DirtyVacbListHead
) && (Target
> 0))
187 current
= CONTAINING_RECORD(current_entry
,
190 current_entry
= current_entry
->Flink
;
192 CcRosVacbIncRefCount(current
);
194 Locked
= current
->SharedCacheMap
->Callbacks
->AcquireForLazyWrite(
195 current
->SharedCacheMap
->LazyWriteContext
, Wait
);
198 CcRosVacbDecRefCount(current
);
202 Status
= KeWaitForSingleObject(¤t
->Mutex
,
206 Wait
? NULL
: &ZeroTimeout
);
207 if (Status
!= STATUS_SUCCESS
)
209 current
->SharedCacheMap
->Callbacks
->ReleaseFromLazyWrite(
210 current
->SharedCacheMap
->LazyWriteContext
);
211 CcRosVacbDecRefCount(current
);
215 ASSERT(current
->Dirty
);
217 /* One reference is added above */
218 if (current
->ReferenceCount
> 2)
220 KeReleaseMutex(¤t
->Mutex
, FALSE
);
221 current
->SharedCacheMap
->Callbacks
->ReleaseFromLazyWrite(
222 current
->SharedCacheMap
->LazyWriteContext
);
223 CcRosVacbDecRefCount(current
);
227 KeReleaseGuardedMutex(&ViewLock
);
229 Status
= CcRosFlushVacb(current
);
231 KeReleaseMutex(¤t
->Mutex
, FALSE
);
232 current
->SharedCacheMap
->Callbacks
->ReleaseFromLazyWrite(
233 current
->SharedCacheMap
->LazyWriteContext
);
235 KeAcquireGuardedMutex(&ViewLock
);
236 CcRosVacbDecRefCount(current
);
238 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_END_OF_FILE
))
240 DPRINT1("CC: Failed to flush VACB.\n");
244 (*Count
) += VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
245 Target
-= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
248 current_entry
= DirtyVacbListHead
.Flink
;
251 KeReleaseGuardedMutex(&ViewLock
);
252 KeLeaveCriticalRegion();
254 DPRINT("CcRosFlushDirtyPages() finished\n");
255 return STATUS_SUCCESS
;
264 * FUNCTION: Try to free some memory from the file cache.
266 * Target - The number of pages to be freed.
267 * Priority - The priority of free (currently unused).
268 * NrFreed - Points to a variable where the number of pages
269 * actually freed is returned.
272 PLIST_ENTRY current_entry
;
279 BOOLEAN FlushedPages
= FALSE
;
281 DPRINT("CcRosTrimCache(Target %lu)\n", Target
);
283 InitializeListHead(&FreeList
);
288 KeAcquireGuardedMutex(&ViewLock
);
290 current_entry
= VacbLruListHead
.Flink
;
291 while (current_entry
!= &VacbLruListHead
)
293 current
= CONTAINING_RECORD(current_entry
,
296 current_entry
= current_entry
->Flink
;
298 KeAcquireSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, &oldIrql
);
300 /* Reference the VACB */
301 CcRosVacbIncRefCount(current
);
303 /* Check if it's mapped and not dirty */
304 if (current
->MappedCount
> 0 && !current
->Dirty
)
306 /* We have to break these locks because Cc sucks */
307 KeReleaseSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, oldIrql
);
308 KeReleaseGuardedMutex(&ViewLock
);
310 /* Page out the VACB */
311 for (i
= 0; i
< VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
; i
++)
313 Page
= (PFN_NUMBER
)(MmGetPhysicalAddress((PUCHAR
)current
->BaseAddress
+ (i
* PAGE_SIZE
)).QuadPart
>> PAGE_SHIFT
);
315 MmPageOutPhysicalAddress(Page
);
318 /* Reacquire the locks */
319 KeAcquireGuardedMutex(&ViewLock
);
320 KeAcquireSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, &oldIrql
);
323 /* Dereference the VACB */
324 CcRosVacbDecRefCount(current
);
326 /* Check if we can free this entry now */
327 if (current
->ReferenceCount
== 0)
329 ASSERT(!current
->Dirty
);
330 ASSERT(!current
->MappedCount
);
332 RemoveEntryList(¤t
->CacheMapVacbListEntry
);
333 RemoveEntryList(¤t
->VacbLruListEntry
);
334 InsertHeadList(&FreeList
, ¤t
->CacheMapVacbListEntry
);
336 /* Calculate how many pages we freed for Mm */
337 PagesFreed
= min(VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
, Target
);
338 Target
-= PagesFreed
;
339 (*NrFreed
) += PagesFreed
;
342 KeReleaseSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, oldIrql
);
345 KeReleaseGuardedMutex(&ViewLock
);
347 /* Try flushing pages if we haven't met our target */
348 if ((Target
> 0) && !FlushedPages
)
350 /* Flush dirty pages to disk */
351 CcRosFlushDirtyPages(Target
, &PagesFreed
, FALSE
);
354 /* We can only swap as many pages as we flushed */
355 if (PagesFreed
< Target
) Target
= PagesFreed
;
357 /* Check if we flushed anything */
360 /* Try again after flushing dirty pages */
361 DPRINT("Flushed %lu dirty cache pages to disk\n", PagesFreed
);
366 while (!IsListEmpty(&FreeList
))
368 current_entry
= RemoveHeadList(&FreeList
);
369 current
= CONTAINING_RECORD(current_entry
,
371 CacheMapVacbListEntry
);
372 CcRosInternalFreeVacb(current
);
375 DPRINT("Evicted %lu cache pages\n", (*NrFreed
));
377 return STATUS_SUCCESS
;
383 PROS_SHARED_CACHE_MAP SharedCacheMap
,
392 ASSERT(SharedCacheMap
);
394 DPRINT("CcRosReleaseVacb(SharedCacheMap 0x%p, Vacb 0x%p, Valid %u)\n",
395 SharedCacheMap
, Vacb
, Valid
);
397 KeAcquireGuardedMutex(&ViewLock
);
398 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
402 WasDirty
= Vacb
->Dirty
;
403 Vacb
->Dirty
= Vacb
->Dirty
|| Dirty
;
405 if (!WasDirty
&& Vacb
->Dirty
)
407 InsertTailList(&DirtyVacbListHead
, &Vacb
->DirtyVacbListEntry
);
408 DirtyPageCount
+= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
415 CcRosVacbDecRefCount(Vacb
);
416 if (Mapped
&& (Vacb
->MappedCount
== 1))
418 CcRosVacbIncRefCount(Vacb
);
420 if (!WasDirty
&& Vacb
->Dirty
)
422 CcRosVacbIncRefCount(Vacb
);
425 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
426 KeReleaseGuardedMutex(&ViewLock
);
427 KeReleaseMutex(&Vacb
->Mutex
, FALSE
);
429 return STATUS_SUCCESS
;
432 /* Returns with VACB Lock Held! */
436 PROS_SHARED_CACHE_MAP SharedCacheMap
,
439 PLIST_ENTRY current_entry
;
443 ASSERT(SharedCacheMap
);
445 DPRINT("CcRosLookupVacb(SharedCacheMap 0x%p, FileOffset %lu)\n",
446 SharedCacheMap
, FileOffset
);
448 KeAcquireGuardedMutex(&ViewLock
);
449 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
451 current_entry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
452 while (current_entry
!= &SharedCacheMap
->CacheMapVacbListHead
)
454 current
= CONTAINING_RECORD(current_entry
,
456 CacheMapVacbListEntry
);
457 if (IsPointInRange(current
->FileOffset
.QuadPart
,
458 VACB_MAPPING_GRANULARITY
,
461 CcRosVacbIncRefCount(current
);
462 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
463 KeReleaseGuardedMutex(&ViewLock
);
464 KeWaitForSingleObject(¤t
->Mutex
,
471 if (current
->FileOffset
.QuadPart
> FileOffset
)
473 current_entry
= current_entry
->Flink
;
476 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
477 KeReleaseGuardedMutex(&ViewLock
);
485 PROS_SHARED_CACHE_MAP SharedCacheMap
,
491 ASSERT(SharedCacheMap
);
493 DPRINT("CcRosMarkDirtyVacb(SharedCacheMap 0x%p, FileOffset %lu)\n",
494 SharedCacheMap
, FileOffset
);
496 Vacb
= CcRosLookupVacb(SharedCacheMap
, FileOffset
);
499 KeBugCheck(CACHE_MANAGER
);
502 KeAcquireGuardedMutex(&ViewLock
);
503 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
507 InsertTailList(&DirtyVacbListHead
, &Vacb
->DirtyVacbListEntry
);
508 DirtyPageCount
+= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
512 CcRosVacbDecRefCount(Vacb
);
515 /* Move to the tail of the LRU list */
516 RemoveEntryList(&Vacb
->VacbLruListEntry
);
517 InsertTailList(&VacbLruListHead
, &Vacb
->VacbLruListEntry
);
521 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
522 KeReleaseGuardedMutex(&ViewLock
);
523 KeReleaseMutex(&Vacb
->Mutex
, FALSE
);
525 return STATUS_SUCCESS
;
531 PROS_SHARED_CACHE_MAP SharedCacheMap
,
539 ASSERT(SharedCacheMap
);
541 DPRINT("CcRosUnmapVacb(SharedCacheMap 0x%p, FileOffset %lu, NowDirty %u)\n",
542 SharedCacheMap
, FileOffset
, NowDirty
);
544 Vacb
= CcRosLookupVacb(SharedCacheMap
, FileOffset
);
547 return STATUS_UNSUCCESSFUL
;
550 KeAcquireGuardedMutex(&ViewLock
);
551 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
553 WasDirty
= Vacb
->Dirty
;
554 Vacb
->Dirty
= Vacb
->Dirty
|| NowDirty
;
558 if (!WasDirty
&& NowDirty
)
560 InsertTailList(&DirtyVacbListHead
, &Vacb
->DirtyVacbListEntry
);
561 DirtyPageCount
+= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
564 CcRosVacbDecRefCount(Vacb
);
565 if (!WasDirty
&& NowDirty
)
567 CcRosVacbIncRefCount(Vacb
);
569 if (Vacb
->MappedCount
== 0)
571 CcRosVacbDecRefCount(Vacb
);
574 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
575 KeReleaseGuardedMutex(&ViewLock
);
576 KeReleaseMutex(&Vacb
->Mutex
, FALSE
);
578 return STATUS_SUCCESS
;
584 PROS_SHARED_CACHE_MAP SharedCacheMap
,
590 PLIST_ENTRY current_entry
;
594 ASSERT(SharedCacheMap
);
596 DPRINT("CcRosCreateVacb()\n");
598 if (FileOffset
>= SharedCacheMap
->FileSize
.u
.LowPart
)
601 return STATUS_INVALID_PARAMETER
;
604 current
= ExAllocateFromNPagedLookasideList(&VacbLookasideList
);
605 current
->Valid
= FALSE
;
606 current
->Dirty
= FALSE
;
607 current
->PageOut
= FALSE
;
608 current
->FileOffset
.QuadPart
= ROUND_DOWN(FileOffset
, VACB_MAPPING_GRANULARITY
);
609 current
->SharedCacheMap
= SharedCacheMap
;
611 if (SharedCacheMap
->Trace
)
613 DPRINT1("CacheMap 0x%p: new VACB: 0x%p\n", SharedCacheMap
, current
);
616 current
->MappedCount
= 0;
617 current
->DirtyVacbListEntry
.Flink
= NULL
;
618 current
->DirtyVacbListEntry
.Blink
= NULL
;
619 current
->ReferenceCount
= 1;
620 KeInitializeMutex(¤t
->Mutex
, 0);
621 KeWaitForSingleObject(¤t
->Mutex
,
626 KeAcquireGuardedMutex(&ViewLock
);
629 /* There is window between the call to CcRosLookupVacb
630 * and CcRosCreateVacb. We must check if a VACB for the
631 * file offset exist. If there is a VACB, we release
632 * our newly created VACB and return the existing one.
634 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
635 current_entry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
637 while (current_entry
!= &SharedCacheMap
->CacheMapVacbListHead
)
639 current
= CONTAINING_RECORD(current_entry
,
641 CacheMapVacbListEntry
);
642 if (IsPointInRange(current
->FileOffset
.QuadPart
,
643 VACB_MAPPING_GRANULARITY
,
646 CcRosVacbIncRefCount(current
);
647 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
649 if (SharedCacheMap
->Trace
)
651 DPRINT1("CacheMap 0x%p: deleting newly created VACB 0x%p ( found existing one 0x%p )\n",
657 KeReleaseMutex(&(*Vacb
)->Mutex
, FALSE
);
658 KeReleaseGuardedMutex(&ViewLock
);
659 ExFreeToNPagedLookasideList(&VacbLookasideList
, *Vacb
);
661 KeWaitForSingleObject(¤t
->Mutex
,
666 return STATUS_SUCCESS
;
668 if (current
->FileOffset
.QuadPart
< FileOffset
)
670 ASSERT(previous
== NULL
||
671 previous
->FileOffset
.QuadPart
< current
->FileOffset
.QuadPart
);
674 if (current
->FileOffset
.QuadPart
> FileOffset
)
676 current_entry
= current_entry
->Flink
;
678 /* There was no existing VACB. */
682 InsertHeadList(&previous
->CacheMapVacbListEntry
, ¤t
->CacheMapVacbListEntry
);
686 InsertHeadList(&SharedCacheMap
->CacheMapVacbListHead
, ¤t
->CacheMapVacbListEntry
);
688 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
689 InsertTailList(&VacbLruListHead
, ¤t
->VacbLruListEntry
);
690 KeReleaseGuardedMutex(&ViewLock
);
692 MmLockAddressSpace(MmGetKernelAddressSpace());
693 current
->BaseAddress
= NULL
;
694 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
695 0, // nothing checks for VACB mareas, so set to 0
696 ¤t
->BaseAddress
,
697 VACB_MAPPING_GRANULARITY
,
699 (PMEMORY_AREA
*)¤t
->MemoryArea
,
703 MmUnlockAddressSpace(MmGetKernelAddressSpace());
704 if (!NT_SUCCESS(Status
))
706 KeBugCheck(CACHE_MANAGER
);
709 /* Create a virtual mapping for this memory area */
710 MI_SET_USAGE(MI_USAGE_CACHE
);
714 if ((SharedCacheMap
->FileObject
) && (SharedCacheMap
->FileObject
->FileName
.Buffer
))
716 pos
= wcsrchr(SharedCacheMap
->FileObject
->FileName
.Buffer
, '\\');
717 len
= wcslen(pos
) * sizeof(WCHAR
);
718 if (pos
) snprintf(MI_PFN_CURRENT_PROCESS_NAME
, min(16, len
), "%S", pos
);
722 MmMapMemoryArea(current
->BaseAddress
, VACB_MAPPING_GRANULARITY
,
723 MC_CACHE
, PAGE_READWRITE
);
725 return STATUS_SUCCESS
;
731 PROS_SHARED_CACHE_MAP SharedCacheMap
,
733 PULONGLONG BaseOffset
,
741 ASSERT(SharedCacheMap
);
743 DPRINT("CcRosGetVacb()\n");
746 * Look for a VACB already mapping the same data.
748 current
= CcRosLookupVacb(SharedCacheMap
, FileOffset
);
752 * Otherwise create a new VACB.
754 Status
= CcRosCreateVacb(SharedCacheMap
, FileOffset
, ¤t
);
755 if (!NT_SUCCESS(Status
))
761 KeAcquireGuardedMutex(&ViewLock
);
763 /* Move to the tail of the LRU list */
764 RemoveEntryList(¤t
->VacbLruListEntry
);
765 InsertTailList(&VacbLruListHead
, ¤t
->VacbLruListEntry
);
767 KeReleaseGuardedMutex(&ViewLock
);
770 * Return information about the VACB to the caller.
772 *UptoDate
= current
->Valid
;
773 *BaseAddress
= current
->BaseAddress
;
774 DPRINT("*BaseAddress %p\n", *BaseAddress
);
776 *BaseOffset
= current
->FileOffset
.QuadPart
;
777 return STATUS_SUCCESS
;
783 PROS_SHARED_CACHE_MAP SharedCacheMap
,
789 * FUNCTION: Request a page mapping for a shared cache map
792 ULONGLONG BaseOffset
;
794 ASSERT(SharedCacheMap
);
796 if (FileOffset
% VACB_MAPPING_GRANULARITY
!= 0)
798 DPRINT1("Bad fileoffset %x should be multiple of %x",
799 FileOffset
, VACB_MAPPING_GRANULARITY
);
800 KeBugCheck(CACHE_MANAGER
);
803 return CcRosGetVacb(SharedCacheMap
,
815 MEMORY_AREA
* MemoryArea
,
821 ASSERT(SwapEntry
== 0);
824 ASSERT(MmGetReferenceCountPage(Page
) == 1);
825 MmReleasePageMemoryConsumer(MC_CACHE
, Page
);
830 CcRosInternalFreeVacb (
833 * FUNCTION: Releases a VACB associated with a shared cache map
836 DPRINT("Freeing VACB 0x%p\n", Vacb
);
838 if (Vacb
->SharedCacheMap
->Trace
)
840 DPRINT1("CacheMap 0x%p: deleting VACB: 0x%p\n", Vacb
->SharedCacheMap
, Vacb
);
844 MmLockAddressSpace(MmGetKernelAddressSpace());
845 MmFreeMemoryArea(MmGetKernelAddressSpace(),
849 MmUnlockAddressSpace(MmGetKernelAddressSpace());
851 ExFreeToNPagedLookasideList(&VacbLookasideList
, Vacb
);
852 return STATUS_SUCCESS
;
861 IN PSECTION_OBJECT_POINTERS SectionObjectPointers
,
862 IN PLARGE_INTEGER FileOffset OPTIONAL
,
864 OUT PIO_STATUS_BLOCK IoStatus
)
866 PROS_SHARED_CACHE_MAP SharedCacheMap
;
867 LARGE_INTEGER Offset
;
872 DPRINT("CcFlushCache(SectionObjectPointers 0x%p, FileOffset 0x%p, Length %lu, IoStatus 0x%p)\n",
873 SectionObjectPointers
, FileOffset
, Length
, IoStatus
);
875 if (SectionObjectPointers
&& SectionObjectPointers
->SharedCacheMap
)
877 SharedCacheMap
= SectionObjectPointers
->SharedCacheMap
;
878 ASSERT(SharedCacheMap
);
881 Offset
= *FileOffset
;
885 Offset
.QuadPart
= (LONGLONG
)0;
886 Length
= SharedCacheMap
->FileSize
.u
.LowPart
;
891 IoStatus
->Status
= STATUS_SUCCESS
;
892 IoStatus
->Information
= 0;
897 current
= CcRosLookupVacb(SharedCacheMap
, Offset
.u
.LowPart
);
902 Status
= CcRosFlushVacb(current
);
903 if (!NT_SUCCESS(Status
) && IoStatus
!= NULL
)
905 IoStatus
->Status
= Status
;
908 KeReleaseMutex(¤t
->Mutex
, FALSE
);
910 KeAcquireGuardedMutex(&ViewLock
);
911 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
912 CcRosVacbDecRefCount(current
);
913 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
914 KeReleaseGuardedMutex(&ViewLock
);
917 Offset
.QuadPart
+= VACB_MAPPING_GRANULARITY
;
918 if (Length
> VACB_MAPPING_GRANULARITY
)
920 Length
-= VACB_MAPPING_GRANULARITY
;
932 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
939 CcRosDeleteFileCache (
940 PFILE_OBJECT FileObject
,
941 PROS_SHARED_CACHE_MAP SharedCacheMap
)
943 * FUNCTION: Releases the shared cache map associated with a file object
946 PLIST_ENTRY current_entry
;
951 ASSERT(SharedCacheMap
);
953 SharedCacheMap
->RefCount
++;
954 KeReleaseGuardedMutex(&ViewLock
);
956 CcFlushCache(FileObject
->SectionObjectPointer
, NULL
, 0, NULL
);
958 KeAcquireGuardedMutex(&ViewLock
);
959 SharedCacheMap
->RefCount
--;
960 if (SharedCacheMap
->RefCount
== 0)
962 FileObject
->SectionObjectPointer
->SharedCacheMap
= NULL
;
967 InitializeListHead(&FreeList
);
968 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
969 while (!IsListEmpty(&SharedCacheMap
->CacheMapVacbListHead
))
971 current_entry
= RemoveTailList(&SharedCacheMap
->CacheMapVacbListHead
);
972 current
= CONTAINING_RECORD(current_entry
, ROS_VACB
, CacheMapVacbListEntry
);
973 RemoveEntryList(¤t
->VacbLruListEntry
);
976 RemoveEntryList(¤t
->DirtyVacbListEntry
);
977 DirtyPageCount
-= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
978 DPRINT1("Freeing dirty VACB\n");
980 InsertHeadList(&FreeList
, ¤t
->CacheMapVacbListEntry
);
983 SharedCacheMap
->Trace
= FALSE
;
985 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
987 KeReleaseGuardedMutex(&ViewLock
);
988 ObDereferenceObject(SharedCacheMap
->FileObject
);
990 while (!IsListEmpty(&FreeList
))
992 current_entry
= RemoveTailList(&FreeList
);
993 current
= CONTAINING_RECORD(current_entry
, ROS_VACB
, CacheMapVacbListEntry
);
994 CcRosInternalFreeVacb(current
);
996 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList
, SharedCacheMap
);
997 KeAcquireGuardedMutex(&ViewLock
);
999 return STATUS_SUCCESS
;
1004 CcRosReferenceCache (
1005 PFILE_OBJECT FileObject
)
1007 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1008 KeAcquireGuardedMutex(&ViewLock
);
1009 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1010 ASSERT(SharedCacheMap
);
1011 ASSERT(SharedCacheMap
->RefCount
!= 0);
1012 SharedCacheMap
->RefCount
++;
1013 KeReleaseGuardedMutex(&ViewLock
);
1018 CcRosRemoveIfClosed (
1019 PSECTION_OBJECT_POINTERS SectionObjectPointer
)
1021 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1022 DPRINT("CcRosRemoveIfClosed()\n");
1023 KeAcquireGuardedMutex(&ViewLock
);
1024 SharedCacheMap
= SectionObjectPointer
->SharedCacheMap
;
1025 if (SharedCacheMap
&& SharedCacheMap
->RefCount
== 0)
1027 CcRosDeleteFileCache(SharedCacheMap
->FileObject
, SharedCacheMap
);
1029 KeReleaseGuardedMutex(&ViewLock
);
1035 CcRosDereferenceCache (
1036 PFILE_OBJECT FileObject
)
1038 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1039 KeAcquireGuardedMutex(&ViewLock
);
1040 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1041 ASSERT(SharedCacheMap
);
1042 if (SharedCacheMap
->RefCount
> 0)
1044 SharedCacheMap
->RefCount
--;
1045 if (SharedCacheMap
->RefCount
== 0)
1047 MmFreeSectionSegments(SharedCacheMap
->FileObject
);
1048 CcRosDeleteFileCache(FileObject
, SharedCacheMap
);
1051 KeReleaseGuardedMutex(&ViewLock
);
1056 CcRosReleaseFileCache (
1057 PFILE_OBJECT FileObject
)
1059 * FUNCTION: Called by the file system when a handle to a file object
1063 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1065 KeAcquireGuardedMutex(&ViewLock
);
1067 if (FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
1069 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1070 if (FileObject
->PrivateCacheMap
!= NULL
)
1072 FileObject
->PrivateCacheMap
= NULL
;
1073 if (SharedCacheMap
->RefCount
> 0)
1075 SharedCacheMap
->RefCount
--;
1076 if (SharedCacheMap
->RefCount
== 0)
1078 MmFreeSectionSegments(SharedCacheMap
->FileObject
);
1079 CcRosDeleteFileCache(FileObject
, SharedCacheMap
);
1084 KeReleaseGuardedMutex(&ViewLock
);
1085 return STATUS_SUCCESS
;
1090 CcTryToInitializeFileCache (
1091 PFILE_OBJECT FileObject
)
1093 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1096 KeAcquireGuardedMutex(&ViewLock
);
1098 ASSERT(FileObject
->SectionObjectPointer
);
1099 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1100 if (SharedCacheMap
== NULL
)
1102 Status
= STATUS_UNSUCCESSFUL
;
1106 if (FileObject
->PrivateCacheMap
== NULL
)
1108 FileObject
->PrivateCacheMap
= SharedCacheMap
;
1109 SharedCacheMap
->RefCount
++;
1111 Status
= STATUS_SUCCESS
;
1113 KeReleaseGuardedMutex(&ViewLock
);
1121 CcRosInitializeFileCache (
1122 PFILE_OBJECT FileObject
,
1123 PCC_FILE_SIZES FileSizes
,
1124 PCACHE_MANAGER_CALLBACKS CallBacks
,
1125 PVOID LazyWriterContext
)
1127 * FUNCTION: Initializes a shared cache map for a file object
1130 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1132 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1133 DPRINT("CcRosInitializeFileCache(FileObject 0x%p, SharedCacheMap 0x%p)\n",
1134 FileObject
, SharedCacheMap
);
1136 KeAcquireGuardedMutex(&ViewLock
);
1137 if (SharedCacheMap
== NULL
)
1139 SharedCacheMap
= ExAllocateFromNPagedLookasideList(&SharedCacheMapLookasideList
);
1140 if (SharedCacheMap
== NULL
)
1142 KeReleaseGuardedMutex(&ViewLock
);
1143 return STATUS_UNSUCCESSFUL
;
1145 RtlZeroMemory(SharedCacheMap
, sizeof(*SharedCacheMap
));
1146 ObReferenceObjectByPointer(FileObject
,
1150 SharedCacheMap
->FileObject
= FileObject
;
1151 SharedCacheMap
->Callbacks
= CallBacks
;
1152 SharedCacheMap
->LazyWriteContext
= LazyWriterContext
;
1153 SharedCacheMap
->SectionSize
= FileSizes
->AllocationSize
;
1154 SharedCacheMap
->FileSize
= FileSizes
->FileSize
;
1155 KeInitializeSpinLock(&SharedCacheMap
->CacheMapLock
);
1156 InitializeListHead(&SharedCacheMap
->CacheMapVacbListHead
);
1157 FileObject
->SectionObjectPointer
->SharedCacheMap
= SharedCacheMap
;
1159 if (FileObject
->PrivateCacheMap
== NULL
)
1161 FileObject
->PrivateCacheMap
= SharedCacheMap
;
1162 SharedCacheMap
->RefCount
++;
1164 KeReleaseGuardedMutex(&ViewLock
);
1166 return STATUS_SUCCESS
;
1174 CcGetFileObjectFromSectionPtrs (
1175 IN PSECTION_OBJECT_POINTERS SectionObjectPointers
)
1177 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1178 if (SectionObjectPointers
&& SectionObjectPointers
->SharedCacheMap
)
1180 SharedCacheMap
= SectionObjectPointers
->SharedCacheMap
;
1181 ASSERT(SharedCacheMap
);
1182 return SharedCacheMap
->FileObject
;
1193 DPRINT("CcInitView()\n");
1195 InitializeListHead(&DirtyVacbListHead
);
1196 InitializeListHead(&VacbLruListHead
);
1197 KeInitializeGuardedMutex(&ViewLock
);
1198 ExInitializeNPagedLookasideList(&iBcbLookasideList
,
1202 sizeof(INTERNAL_BCB
),
1205 ExInitializeNPagedLookasideList(&SharedCacheMapLookasideList
,
1209 sizeof(ROS_SHARED_CACHE_MAP
),
1210 TAG_SHARED_CACHE_MAP
,
1212 ExInitializeNPagedLookasideList(&VacbLookasideList
,
1220 MmInitializeMemoryConsumer(MC_CACHE
, CcRosTrimCache
);
1222 CcInitCacheZeroPage();