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
;
170 DPRINT("CcRosFlushDirtyPages(Target %lu)\n", Target
);
174 KeEnterCriticalRegion();
175 KeAcquireGuardedMutex(&ViewLock
);
177 current_entry
= DirtyVacbListHead
.Flink
;
178 if (current_entry
== &DirtyVacbListHead
)
180 DPRINT("No Dirty pages\n");
183 while ((current_entry
!= &DirtyVacbListHead
) && (Target
> 0))
185 current
= CONTAINING_RECORD(current_entry
,
188 current_entry
= current_entry
->Flink
;
190 CcRosVacbIncRefCount(current
);
192 Locked
= current
->SharedCacheMap
->Callbacks
->AcquireForLazyWrite(
193 current
->SharedCacheMap
->LazyWriteContext
, Wait
);
196 CcRosVacbDecRefCount(current
);
200 Locked
= ExAcquireResourceExclusiveLite(¤t
->Lock
, Wait
);
203 current
->SharedCacheMap
->Callbacks
->ReleaseFromLazyWrite(
204 current
->SharedCacheMap
->LazyWriteContext
);
205 CcRosVacbDecRefCount(current
);
209 ASSERT(current
->Dirty
);
211 /* One reference is added above */
212 if (current
->ReferenceCount
> 2)
214 ExReleaseResourceLite(¤t
->Lock
);
215 current
->SharedCacheMap
->Callbacks
->ReleaseFromLazyWrite(
216 current
->SharedCacheMap
->LazyWriteContext
);
217 CcRosVacbDecRefCount(current
);
221 KeReleaseGuardedMutex(&ViewLock
);
223 Status
= CcRosFlushVacb(current
);
225 ExReleaseResourceLite(¤t
->Lock
);
226 current
->SharedCacheMap
->Callbacks
->ReleaseFromLazyWrite(
227 current
->SharedCacheMap
->LazyWriteContext
);
229 KeAcquireGuardedMutex(&ViewLock
);
230 CcRosVacbDecRefCount(current
);
232 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_END_OF_FILE
) &&
233 (Status
!= STATUS_MEDIA_WRITE_PROTECTED
))
235 DPRINT1("CC: Failed to flush VACB.\n");
239 (*Count
) += VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
240 Target
-= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
243 current_entry
= DirtyVacbListHead
.Flink
;
246 KeReleaseGuardedMutex(&ViewLock
);
247 KeLeaveCriticalRegion();
249 DPRINT("CcRosFlushDirtyPages() finished\n");
250 return STATUS_SUCCESS
;
259 * FUNCTION: Try to free some memory from the file cache.
261 * Target - The number of pages to be freed.
262 * Priority - The priority of free (currently unused).
263 * NrFreed - Points to a variable where the number of pages
264 * actually freed is returned.
267 PLIST_ENTRY current_entry
;
274 BOOLEAN FlushedPages
= FALSE
;
276 DPRINT("CcRosTrimCache(Target %lu)\n", Target
);
278 InitializeListHead(&FreeList
);
283 KeAcquireGuardedMutex(&ViewLock
);
285 current_entry
= VacbLruListHead
.Flink
;
286 while (current_entry
!= &VacbLruListHead
)
288 current
= CONTAINING_RECORD(current_entry
,
291 current_entry
= current_entry
->Flink
;
293 KeAcquireSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, &oldIrql
);
295 /* Reference the VACB */
296 CcRosVacbIncRefCount(current
);
298 /* Check if it's mapped and not dirty */
299 if (current
->MappedCount
> 0 && !current
->Dirty
)
301 /* We have to break these locks because Cc sucks */
302 KeReleaseSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, oldIrql
);
303 KeReleaseGuardedMutex(&ViewLock
);
305 /* Page out the VACB */
306 for (i
= 0; i
< VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
; i
++)
308 Page
= (PFN_NUMBER
)(MmGetPhysicalAddress((PUCHAR
)current
->BaseAddress
+ (i
* PAGE_SIZE
)).QuadPart
>> PAGE_SHIFT
);
310 MmPageOutPhysicalAddress(Page
);
313 /* Reacquire the locks */
314 KeAcquireGuardedMutex(&ViewLock
);
315 KeAcquireSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, &oldIrql
);
318 /* Dereference the VACB */
319 CcRosVacbDecRefCount(current
);
321 /* Check if we can free this entry now */
322 if (current
->ReferenceCount
== 0)
324 ASSERT(!current
->Dirty
);
325 ASSERT(!current
->MappedCount
);
327 RemoveEntryList(¤t
->CacheMapVacbListEntry
);
328 RemoveEntryList(¤t
->VacbLruListEntry
);
329 InsertHeadList(&FreeList
, ¤t
->CacheMapVacbListEntry
);
331 /* Calculate how many pages we freed for Mm */
332 PagesFreed
= min(VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
, Target
);
333 Target
-= PagesFreed
;
334 (*NrFreed
) += PagesFreed
;
337 KeReleaseSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, oldIrql
);
340 KeReleaseGuardedMutex(&ViewLock
);
342 /* Try flushing pages if we haven't met our target */
343 if ((Target
> 0) && !FlushedPages
)
345 /* Flush dirty pages to disk */
346 CcRosFlushDirtyPages(Target
, &PagesFreed
, FALSE
);
349 /* We can only swap as many pages as we flushed */
350 if (PagesFreed
< Target
) Target
= PagesFreed
;
352 /* Check if we flushed anything */
355 /* Try again after flushing dirty pages */
356 DPRINT("Flushed %lu dirty cache pages to disk\n", PagesFreed
);
361 while (!IsListEmpty(&FreeList
))
363 current_entry
= RemoveHeadList(&FreeList
);
364 current
= CONTAINING_RECORD(current_entry
,
366 CacheMapVacbListEntry
);
367 CcRosInternalFreeVacb(current
);
370 DPRINT("Evicted %lu cache pages\n", (*NrFreed
));
372 return STATUS_SUCCESS
;
378 PROS_SHARED_CACHE_MAP SharedCacheMap
,
387 ASSERT(SharedCacheMap
);
389 DPRINT("CcRosReleaseVacb(SharedCacheMap 0x%p, Vacb 0x%p, Valid %u)\n",
390 SharedCacheMap
, Vacb
, Valid
);
392 KeAcquireGuardedMutex(&ViewLock
);
393 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
397 WasDirty
= Vacb
->Dirty
;
398 Vacb
->Dirty
= Vacb
->Dirty
|| Dirty
;
400 if (!WasDirty
&& Vacb
->Dirty
)
402 InsertTailList(&DirtyVacbListHead
, &Vacb
->DirtyVacbListEntry
);
403 DirtyPageCount
+= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
410 CcRosVacbDecRefCount(Vacb
);
411 if (Mapped
&& (Vacb
->MappedCount
== 1))
413 CcRosVacbIncRefCount(Vacb
);
415 if (!WasDirty
&& Vacb
->Dirty
)
417 CcRosVacbIncRefCount(Vacb
);
420 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
421 KeReleaseGuardedMutex(&ViewLock
);
422 ExReleaseResourceLite(&Vacb
->Lock
);
424 return STATUS_SUCCESS
;
427 /* Returns with VACB Lock Held! */
431 PROS_SHARED_CACHE_MAP SharedCacheMap
,
434 PLIST_ENTRY current_entry
;
438 ASSERT(SharedCacheMap
);
440 DPRINT("CcRosLookupVacb(SharedCacheMap 0x%p, FileOffset %I64u)\n",
441 SharedCacheMap
, FileOffset
);
443 KeAcquireGuardedMutex(&ViewLock
);
444 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
446 current_entry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
447 while (current_entry
!= &SharedCacheMap
->CacheMapVacbListHead
)
449 current
= CONTAINING_RECORD(current_entry
,
451 CacheMapVacbListEntry
);
452 if (IsPointInRange(current
->FileOffset
.QuadPart
,
453 VACB_MAPPING_GRANULARITY
,
456 CcRosVacbIncRefCount(current
);
457 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
458 KeReleaseGuardedMutex(&ViewLock
);
459 ExAcquireResourceExclusiveLite(¤t
->Lock
, TRUE
);
462 if (current
->FileOffset
.QuadPart
> FileOffset
)
464 current_entry
= current_entry
->Flink
;
467 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
468 KeReleaseGuardedMutex(&ViewLock
);
476 PROS_SHARED_CACHE_MAP SharedCacheMap
,
482 ASSERT(SharedCacheMap
);
484 DPRINT("CcRosMarkDirtyVacb(SharedCacheMap 0x%p, FileOffset %I64u)\n",
485 SharedCacheMap
, FileOffset
);
487 Vacb
= CcRosLookupVacb(SharedCacheMap
, FileOffset
);
490 KeBugCheck(CACHE_MANAGER
);
493 KeAcquireGuardedMutex(&ViewLock
);
494 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
498 InsertTailList(&DirtyVacbListHead
, &Vacb
->DirtyVacbListEntry
);
499 DirtyPageCount
+= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
503 CcRosVacbDecRefCount(Vacb
);
506 /* Move to the tail of the LRU list */
507 RemoveEntryList(&Vacb
->VacbLruListEntry
);
508 InsertTailList(&VacbLruListHead
, &Vacb
->VacbLruListEntry
);
512 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
513 KeReleaseGuardedMutex(&ViewLock
);
514 ExReleaseResourceLite(&Vacb
->Lock
);
516 return STATUS_SUCCESS
;
522 PROS_SHARED_CACHE_MAP SharedCacheMap
,
530 ASSERT(SharedCacheMap
);
532 DPRINT("CcRosUnmapVacb(SharedCacheMap 0x%p, FileOffset %I64u, NowDirty %u)\n",
533 SharedCacheMap
, FileOffset
, NowDirty
);
535 Vacb
= CcRosLookupVacb(SharedCacheMap
, FileOffset
);
538 return STATUS_UNSUCCESSFUL
;
541 KeAcquireGuardedMutex(&ViewLock
);
542 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
544 WasDirty
= Vacb
->Dirty
;
545 Vacb
->Dirty
= Vacb
->Dirty
|| NowDirty
;
549 if (!WasDirty
&& NowDirty
)
551 InsertTailList(&DirtyVacbListHead
, &Vacb
->DirtyVacbListEntry
);
552 DirtyPageCount
+= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
555 CcRosVacbDecRefCount(Vacb
);
556 if (!WasDirty
&& NowDirty
)
558 CcRosVacbIncRefCount(Vacb
);
560 if (Vacb
->MappedCount
== 0)
562 CcRosVacbDecRefCount(Vacb
);
565 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
566 KeReleaseGuardedMutex(&ViewLock
);
567 ExReleaseResourceLite(&Vacb
->Lock
);
569 return STATUS_SUCCESS
;
579 ULONG_PTR NumberOfPages
;
581 /* Create a memory area. */
582 MmLockAddressSpace(MmGetKernelAddressSpace());
583 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
584 0, // nothing checks for VACB mareas, so set to 0
586 VACB_MAPPING_GRANULARITY
,
588 (PMEMORY_AREA
*)&Vacb
->MemoryArea
,
591 MmUnlockAddressSpace(MmGetKernelAddressSpace());
592 if (!NT_SUCCESS(Status
))
594 KeBugCheck(CACHE_MANAGER
);
597 ASSERT(((ULONG_PTR
)Vacb
->BaseAddress
% PAGE_SIZE
) == 0);
598 ASSERT((ULONG_PTR
)Vacb
->BaseAddress
> (ULONG_PTR
)MmSystemRangeStart
);
600 /* Create a virtual mapping for this memory area */
601 NumberOfPages
= BYTES_TO_PAGES(VACB_MAPPING_GRANULARITY
);
602 for (i
= 0; i
< NumberOfPages
; i
++)
604 PFN_NUMBER PageFrameNumber
;
606 Status
= MmRequestPageMemoryConsumer(MC_CACHE
, TRUE
, &PageFrameNumber
);
607 if (PageFrameNumber
== 0)
609 DPRINT1("Unable to allocate page\n");
610 KeBugCheck(MEMORY_MANAGEMENT
);
613 Status
= MmCreateVirtualMapping(NULL
,
614 (PVOID
)((ULONG_PTR
)Vacb
->BaseAddress
+ (i
* PAGE_SIZE
)),
618 if (!NT_SUCCESS(Status
))
620 DPRINT1("Unable to create virtual mapping\n");
621 KeBugCheck(MEMORY_MANAGEMENT
);
625 return STATUS_SUCCESS
;
631 PROS_SHARED_CACHE_MAP SharedCacheMap
,
637 PLIST_ENTRY current_entry
;
641 ASSERT(SharedCacheMap
);
643 DPRINT("CcRosCreateVacb()\n");
645 if (FileOffset
>= SharedCacheMap
->FileSize
.QuadPart
)
648 return STATUS_INVALID_PARAMETER
;
651 current
= ExAllocateFromNPagedLookasideList(&VacbLookasideList
);
652 current
->BaseAddress
= NULL
;
653 current
->Valid
= FALSE
;
654 current
->Dirty
= FALSE
;
655 current
->PageOut
= FALSE
;
656 current
->FileOffset
.QuadPart
= ROUND_DOWN(FileOffset
, VACB_MAPPING_GRANULARITY
);
657 current
->SharedCacheMap
= SharedCacheMap
;
659 if (SharedCacheMap
->Trace
)
661 DPRINT1("CacheMap 0x%p: new VACB: 0x%p\n", SharedCacheMap
, current
);
664 current
->MappedCount
= 0;
665 current
->DirtyVacbListEntry
.Flink
= NULL
;
666 current
->DirtyVacbListEntry
.Blink
= NULL
;
667 current
->ReferenceCount
= 1;
668 ExInitializeResourceLite(¤t
->Lock
);
669 ExAcquireResourceExclusiveLite(¤t
->Lock
, TRUE
);
670 KeAcquireGuardedMutex(&ViewLock
);
673 /* There is window between the call to CcRosLookupVacb
674 * and CcRosCreateVacb. We must check if a VACB for the
675 * file offset exist. If there is a VACB, we release
676 * our newly created VACB and return the existing one.
678 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
679 current_entry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
681 while (current_entry
!= &SharedCacheMap
->CacheMapVacbListHead
)
683 current
= CONTAINING_RECORD(current_entry
,
685 CacheMapVacbListEntry
);
686 if (IsPointInRange(current
->FileOffset
.QuadPart
,
687 VACB_MAPPING_GRANULARITY
,
690 CcRosVacbIncRefCount(current
);
691 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
693 if (SharedCacheMap
->Trace
)
695 DPRINT1("CacheMap 0x%p: deleting newly created VACB 0x%p ( found existing one 0x%p )\n",
701 ExReleaseResourceLite(&(*Vacb
)->Lock
);
702 KeReleaseGuardedMutex(&ViewLock
);
703 ExFreeToNPagedLookasideList(&VacbLookasideList
, *Vacb
);
705 ExAcquireResourceExclusiveLite(¤t
->Lock
, TRUE
);
706 return STATUS_SUCCESS
;
708 if (current
->FileOffset
.QuadPart
< FileOffset
)
710 ASSERT(previous
== NULL
||
711 previous
->FileOffset
.QuadPart
< current
->FileOffset
.QuadPart
);
714 if (current
->FileOffset
.QuadPart
> FileOffset
)
716 current_entry
= current_entry
->Flink
;
718 /* There was no existing VACB. */
722 InsertHeadList(&previous
->CacheMapVacbListEntry
, ¤t
->CacheMapVacbListEntry
);
726 InsertHeadList(&SharedCacheMap
->CacheMapVacbListHead
, ¤t
->CacheMapVacbListEntry
);
728 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
729 InsertTailList(&VacbLruListHead
, ¤t
->VacbLruListEntry
);
730 KeReleaseGuardedMutex(&ViewLock
);
732 MI_SET_USAGE(MI_USAGE_CACHE
);
734 if ((SharedCacheMap
->FileObject
) && (SharedCacheMap
->FileObject
->FileName
.Buffer
))
738 pos
= wcsrchr(SharedCacheMap
->FileObject
->FileName
.Buffer
, '\\');
739 len
= wcslen(pos
) * sizeof(WCHAR
);
740 if (pos
) snprintf(MI_PFN_CURRENT_PROCESS_NAME
, min(16, len
), "%S", pos
);
744 Status
= CcRosMapVacb(current
);
752 PROS_SHARED_CACHE_MAP SharedCacheMap
,
754 PLONGLONG BaseOffset
,
762 ASSERT(SharedCacheMap
);
764 DPRINT("CcRosGetVacb()\n");
767 * Look for a VACB already mapping the same data.
769 current
= CcRosLookupVacb(SharedCacheMap
, FileOffset
);
773 * Otherwise create a new VACB.
775 Status
= CcRosCreateVacb(SharedCacheMap
, FileOffset
, ¤t
);
776 if (!NT_SUCCESS(Status
))
782 KeAcquireGuardedMutex(&ViewLock
);
784 /* Move to the tail of the LRU list */
785 RemoveEntryList(¤t
->VacbLruListEntry
);
786 InsertTailList(&VacbLruListHead
, ¤t
->VacbLruListEntry
);
788 KeReleaseGuardedMutex(&ViewLock
);
791 * Return information about the VACB to the caller.
793 *UptoDate
= current
->Valid
;
794 *BaseAddress
= current
->BaseAddress
;
795 DPRINT("*BaseAddress %p\n", *BaseAddress
);
797 *BaseOffset
= current
->FileOffset
.QuadPart
;
798 return STATUS_SUCCESS
;
804 PROS_SHARED_CACHE_MAP SharedCacheMap
,
810 * FUNCTION: Request a page mapping for a shared cache map
815 ASSERT(SharedCacheMap
);
817 if (FileOffset
% VACB_MAPPING_GRANULARITY
!= 0)
819 DPRINT1("Bad fileoffset %I64x should be multiple of %x",
820 FileOffset
, VACB_MAPPING_GRANULARITY
);
821 KeBugCheck(CACHE_MANAGER
);
824 return CcRosGetVacb(SharedCacheMap
,
836 MEMORY_AREA
* MemoryArea
,
842 ASSERT(SwapEntry
== 0);
845 ASSERT(MmGetReferenceCountPage(Page
) == 1);
846 MmReleasePageMemoryConsumer(MC_CACHE
, Page
);
851 CcRosInternalFreeVacb (
854 * FUNCTION: Releases a VACB associated with a shared cache map
857 DPRINT("Freeing VACB 0x%p\n", Vacb
);
859 if (Vacb
->SharedCacheMap
->Trace
)
861 DPRINT1("CacheMap 0x%p: deleting VACB: 0x%p\n", Vacb
->SharedCacheMap
, Vacb
);
865 MmLockAddressSpace(MmGetKernelAddressSpace());
866 MmFreeMemoryArea(MmGetKernelAddressSpace(),
870 MmUnlockAddressSpace(MmGetKernelAddressSpace());
871 ExDeleteResourceLite(&Vacb
->Lock
);
873 ExFreeToNPagedLookasideList(&VacbLookasideList
, Vacb
);
874 return STATUS_SUCCESS
;
883 IN PSECTION_OBJECT_POINTERS SectionObjectPointers
,
884 IN PLARGE_INTEGER FileOffset OPTIONAL
,
886 OUT PIO_STATUS_BLOCK IoStatus
)
888 PROS_SHARED_CACHE_MAP SharedCacheMap
;
889 LARGE_INTEGER Offset
;
890 LONGLONG RemainingLength
;
895 CCTRACE(CC_API_DEBUG
, "SectionObjectPointers=%p FileOffset=%p Length=%lu\n",
896 SectionObjectPointers
, FileOffset
, Length
);
898 DPRINT("CcFlushCache(SectionObjectPointers 0x%p, FileOffset 0x%p, Length %lu, IoStatus 0x%p)\n",
899 SectionObjectPointers
, FileOffset
, Length
, IoStatus
);
901 if (SectionObjectPointers
&& SectionObjectPointers
->SharedCacheMap
)
903 SharedCacheMap
= SectionObjectPointers
->SharedCacheMap
;
904 ASSERT(SharedCacheMap
);
907 Offset
= *FileOffset
;
908 RemainingLength
= Length
;
913 RemainingLength
= SharedCacheMap
->FileSize
.QuadPart
;
918 IoStatus
->Status
= STATUS_SUCCESS
;
919 IoStatus
->Information
= 0;
922 while (RemainingLength
> 0)
924 current
= CcRosLookupVacb(SharedCacheMap
, Offset
.QuadPart
);
929 Status
= CcRosFlushVacb(current
);
930 if (!NT_SUCCESS(Status
) && IoStatus
!= NULL
)
932 IoStatus
->Status
= Status
;
935 ExReleaseResourceLite(¤t
->Lock
);
937 KeAcquireGuardedMutex(&ViewLock
);
938 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
939 CcRosVacbDecRefCount(current
);
940 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
941 KeReleaseGuardedMutex(&ViewLock
);
944 Offset
.QuadPart
+= VACB_MAPPING_GRANULARITY
;
945 RemainingLength
-= min(RemainingLength
, VACB_MAPPING_GRANULARITY
);
952 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
959 CcRosDeleteFileCache (
960 PFILE_OBJECT FileObject
,
961 PROS_SHARED_CACHE_MAP SharedCacheMap
)
963 * FUNCTION: Releases the shared cache map associated with a file object
966 PLIST_ENTRY current_entry
;
971 ASSERT(SharedCacheMap
);
973 SharedCacheMap
->RefCount
++;
974 KeReleaseGuardedMutex(&ViewLock
);
976 CcFlushCache(FileObject
->SectionObjectPointer
, NULL
, 0, NULL
);
978 KeAcquireGuardedMutex(&ViewLock
);
979 SharedCacheMap
->RefCount
--;
980 if (SharedCacheMap
->RefCount
== 0)
982 FileObject
->SectionObjectPointer
->SharedCacheMap
= NULL
;
987 InitializeListHead(&FreeList
);
988 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
989 while (!IsListEmpty(&SharedCacheMap
->CacheMapVacbListHead
))
991 current_entry
= RemoveTailList(&SharedCacheMap
->CacheMapVacbListHead
);
992 current
= CONTAINING_RECORD(current_entry
, ROS_VACB
, CacheMapVacbListEntry
);
993 RemoveEntryList(¤t
->VacbLruListEntry
);
996 RemoveEntryList(¤t
->DirtyVacbListEntry
);
997 DirtyPageCount
-= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
998 DPRINT1("Freeing dirty VACB\n");
1000 InsertHeadList(&FreeList
, ¤t
->CacheMapVacbListEntry
);
1003 SharedCacheMap
->Trace
= FALSE
;
1005 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
1007 KeReleaseGuardedMutex(&ViewLock
);
1008 ObDereferenceObject(SharedCacheMap
->FileObject
);
1010 while (!IsListEmpty(&FreeList
))
1012 current_entry
= RemoveTailList(&FreeList
);
1013 current
= CONTAINING_RECORD(current_entry
, ROS_VACB
, CacheMapVacbListEntry
);
1014 CcRosInternalFreeVacb(current
);
1016 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList
, SharedCacheMap
);
1017 KeAcquireGuardedMutex(&ViewLock
);
1019 return STATUS_SUCCESS
;
1024 CcRosReferenceCache (
1025 PFILE_OBJECT FileObject
)
1027 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1028 KeAcquireGuardedMutex(&ViewLock
);
1029 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1030 ASSERT(SharedCacheMap
);
1031 ASSERT(SharedCacheMap
->RefCount
!= 0);
1032 SharedCacheMap
->RefCount
++;
1033 KeReleaseGuardedMutex(&ViewLock
);
1038 CcRosRemoveIfClosed (
1039 PSECTION_OBJECT_POINTERS SectionObjectPointer
)
1041 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1042 DPRINT("CcRosRemoveIfClosed()\n");
1043 KeAcquireGuardedMutex(&ViewLock
);
1044 SharedCacheMap
= SectionObjectPointer
->SharedCacheMap
;
1045 if (SharedCacheMap
&& SharedCacheMap
->RefCount
== 0)
1047 CcRosDeleteFileCache(SharedCacheMap
->FileObject
, SharedCacheMap
);
1049 KeReleaseGuardedMutex(&ViewLock
);
1055 CcRosDereferenceCache (
1056 PFILE_OBJECT FileObject
)
1058 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1059 KeAcquireGuardedMutex(&ViewLock
);
1060 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1061 ASSERT(SharedCacheMap
);
1062 if (SharedCacheMap
->RefCount
> 0)
1064 SharedCacheMap
->RefCount
--;
1065 if (SharedCacheMap
->RefCount
== 0)
1067 MmFreeSectionSegments(SharedCacheMap
->FileObject
);
1068 CcRosDeleteFileCache(FileObject
, SharedCacheMap
);
1071 KeReleaseGuardedMutex(&ViewLock
);
1076 CcRosReleaseFileCache (
1077 PFILE_OBJECT FileObject
)
1079 * FUNCTION: Called by the file system when a handle to a file object
1083 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1085 KeAcquireGuardedMutex(&ViewLock
);
1087 if (FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
1089 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1090 if (FileObject
->PrivateCacheMap
!= NULL
)
1092 FileObject
->PrivateCacheMap
= NULL
;
1093 if (SharedCacheMap
->RefCount
> 0)
1095 SharedCacheMap
->RefCount
--;
1096 if (SharedCacheMap
->RefCount
== 0)
1098 MmFreeSectionSegments(SharedCacheMap
->FileObject
);
1099 CcRosDeleteFileCache(FileObject
, SharedCacheMap
);
1104 KeReleaseGuardedMutex(&ViewLock
);
1105 return STATUS_SUCCESS
;
1110 CcTryToInitializeFileCache (
1111 PFILE_OBJECT FileObject
)
1113 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1116 KeAcquireGuardedMutex(&ViewLock
);
1118 ASSERT(FileObject
->SectionObjectPointer
);
1119 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1120 if (SharedCacheMap
== NULL
)
1122 Status
= STATUS_UNSUCCESSFUL
;
1126 if (FileObject
->PrivateCacheMap
== NULL
)
1128 FileObject
->PrivateCacheMap
= SharedCacheMap
;
1129 SharedCacheMap
->RefCount
++;
1131 Status
= STATUS_SUCCESS
;
1133 KeReleaseGuardedMutex(&ViewLock
);
1141 CcRosInitializeFileCache (
1142 PFILE_OBJECT FileObject
,
1143 PCC_FILE_SIZES FileSizes
,
1144 PCACHE_MANAGER_CALLBACKS CallBacks
,
1145 PVOID LazyWriterContext
)
1147 * FUNCTION: Initializes a shared cache map for a file object
1150 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1152 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1153 DPRINT("CcRosInitializeFileCache(FileObject 0x%p, SharedCacheMap 0x%p)\n",
1154 FileObject
, SharedCacheMap
);
1156 KeAcquireGuardedMutex(&ViewLock
);
1157 if (SharedCacheMap
== NULL
)
1159 SharedCacheMap
= ExAllocateFromNPagedLookasideList(&SharedCacheMapLookasideList
);
1160 if (SharedCacheMap
== NULL
)
1162 KeReleaseGuardedMutex(&ViewLock
);
1163 return STATUS_INSUFFICIENT_RESOURCES
;
1165 RtlZeroMemory(SharedCacheMap
, sizeof(*SharedCacheMap
));
1166 ObReferenceObjectByPointer(FileObject
,
1170 SharedCacheMap
->FileObject
= FileObject
;
1171 SharedCacheMap
->Callbacks
= CallBacks
;
1172 SharedCacheMap
->LazyWriteContext
= LazyWriterContext
;
1173 SharedCacheMap
->SectionSize
= FileSizes
->AllocationSize
;
1174 SharedCacheMap
->FileSize
= FileSizes
->FileSize
;
1175 KeInitializeSpinLock(&SharedCacheMap
->CacheMapLock
);
1176 InitializeListHead(&SharedCacheMap
->CacheMapVacbListHead
);
1177 FileObject
->SectionObjectPointer
->SharedCacheMap
= SharedCacheMap
;
1179 if (FileObject
->PrivateCacheMap
== NULL
)
1181 FileObject
->PrivateCacheMap
= SharedCacheMap
;
1182 SharedCacheMap
->RefCount
++;
1184 KeReleaseGuardedMutex(&ViewLock
);
1186 return STATUS_SUCCESS
;
1194 CcGetFileObjectFromSectionPtrs (
1195 IN PSECTION_OBJECT_POINTERS SectionObjectPointers
)
1197 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1199 CCTRACE(CC_API_DEBUG
, "SectionObjectPointers=%p\n", SectionObjectPointers
);
1201 if (SectionObjectPointers
&& SectionObjectPointers
->SharedCacheMap
)
1203 SharedCacheMap
= SectionObjectPointers
->SharedCacheMap
;
1204 ASSERT(SharedCacheMap
);
1205 return SharedCacheMap
->FileObject
;
1216 DPRINT("CcInitView()\n");
1218 InitializeListHead(&DirtyVacbListHead
);
1219 InitializeListHead(&VacbLruListHead
);
1220 KeInitializeGuardedMutex(&ViewLock
);
1221 ExInitializeNPagedLookasideList(&iBcbLookasideList
,
1225 sizeof(INTERNAL_BCB
),
1228 ExInitializeNPagedLookasideList(&SharedCacheMapLookasideList
,
1232 sizeof(ROS_SHARED_CACHE_MAP
),
1233 TAG_SHARED_CACHE_MAP
,
1235 ExInitializeNPagedLookasideList(&VacbLookasideList
,
1243 MmInitializeMemoryConsumer(MC_CACHE
, CcRosTrimCache
);
1245 CcInitCacheZeroPage();