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
= CcRosAcquireVacbLock(current
,
203 Wait
? NULL
: &ZeroTimeout
);
204 if (Status
!= STATUS_SUCCESS
)
206 current
->SharedCacheMap
->Callbacks
->ReleaseFromLazyWrite(
207 current
->SharedCacheMap
->LazyWriteContext
);
208 CcRosVacbDecRefCount(current
);
212 ASSERT(current
->Dirty
);
214 /* One reference is added above */
215 if (current
->ReferenceCount
> 2)
217 CcRosReleaseVacbLock(current
);
218 current
->SharedCacheMap
->Callbacks
->ReleaseFromLazyWrite(
219 current
->SharedCacheMap
->LazyWriteContext
);
220 CcRosVacbDecRefCount(current
);
224 KeReleaseGuardedMutex(&ViewLock
);
226 Status
= CcRosFlushVacb(current
);
228 CcRosReleaseVacbLock(current
);
229 current
->SharedCacheMap
->Callbacks
->ReleaseFromLazyWrite(
230 current
->SharedCacheMap
->LazyWriteContext
);
232 KeAcquireGuardedMutex(&ViewLock
);
233 CcRosVacbDecRefCount(current
);
235 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_END_OF_FILE
) &&
236 (Status
!= STATUS_MEDIA_WRITE_PROTECTED
))
238 DPRINT1("CC: Failed to flush VACB.\n");
242 (*Count
) += VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
243 Target
-= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
246 current_entry
= DirtyVacbListHead
.Flink
;
249 KeReleaseGuardedMutex(&ViewLock
);
250 KeLeaveCriticalRegion();
252 DPRINT("CcRosFlushDirtyPages() finished\n");
253 return STATUS_SUCCESS
;
262 * FUNCTION: Try to free some memory from the file cache.
264 * Target - The number of pages to be freed.
265 * Priority - The priority of free (currently unused).
266 * NrFreed - Points to a variable where the number of pages
267 * actually freed is returned.
270 PLIST_ENTRY current_entry
;
277 BOOLEAN FlushedPages
= FALSE
;
279 DPRINT("CcRosTrimCache(Target %lu)\n", Target
);
281 InitializeListHead(&FreeList
);
286 KeAcquireGuardedMutex(&ViewLock
);
288 current_entry
= VacbLruListHead
.Flink
;
289 while (current_entry
!= &VacbLruListHead
)
291 current
= CONTAINING_RECORD(current_entry
,
294 current_entry
= current_entry
->Flink
;
296 KeAcquireSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, &oldIrql
);
298 /* Reference the VACB */
299 CcRosVacbIncRefCount(current
);
301 /* Check if it's mapped and not dirty */
302 if (current
->MappedCount
> 0 && !current
->Dirty
)
304 /* We have to break these locks because Cc sucks */
305 KeReleaseSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, oldIrql
);
306 KeReleaseGuardedMutex(&ViewLock
);
308 /* Page out the VACB */
309 for (i
= 0; i
< VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
; i
++)
311 Page
= (PFN_NUMBER
)(MmGetPhysicalAddress((PUCHAR
)current
->BaseAddress
+ (i
* PAGE_SIZE
)).QuadPart
>> PAGE_SHIFT
);
313 MmPageOutPhysicalAddress(Page
);
316 /* Reacquire the locks */
317 KeAcquireGuardedMutex(&ViewLock
);
318 KeAcquireSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, &oldIrql
);
321 /* Dereference the VACB */
322 CcRosVacbDecRefCount(current
);
324 /* Check if we can free this entry now */
325 if (current
->ReferenceCount
== 0)
327 ASSERT(!current
->Dirty
);
328 ASSERT(!current
->MappedCount
);
330 RemoveEntryList(¤t
->CacheMapVacbListEntry
);
331 RemoveEntryList(¤t
->VacbLruListEntry
);
332 InsertHeadList(&FreeList
, ¤t
->CacheMapVacbListEntry
);
334 /* Calculate how many pages we freed for Mm */
335 PagesFreed
= min(VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
, Target
);
336 Target
-= PagesFreed
;
337 (*NrFreed
) += PagesFreed
;
340 KeReleaseSpinLock(¤t
->SharedCacheMap
->CacheMapLock
, oldIrql
);
343 KeReleaseGuardedMutex(&ViewLock
);
345 /* Try flushing pages if we haven't met our target */
346 if ((Target
> 0) && !FlushedPages
)
348 /* Flush dirty pages to disk */
349 CcRosFlushDirtyPages(Target
, &PagesFreed
, FALSE
);
352 /* We can only swap as many pages as we flushed */
353 if (PagesFreed
< Target
) Target
= PagesFreed
;
355 /* Check if we flushed anything */
358 /* Try again after flushing dirty pages */
359 DPRINT("Flushed %lu dirty cache pages to disk\n", PagesFreed
);
364 while (!IsListEmpty(&FreeList
))
366 current_entry
= RemoveHeadList(&FreeList
);
367 current
= CONTAINING_RECORD(current_entry
,
369 CacheMapVacbListEntry
);
370 CcRosInternalFreeVacb(current
);
373 DPRINT("Evicted %lu cache pages\n", (*NrFreed
));
375 return STATUS_SUCCESS
;
381 PROS_SHARED_CACHE_MAP SharedCacheMap
,
390 ASSERT(SharedCacheMap
);
392 DPRINT("CcRosReleaseVacb(SharedCacheMap 0x%p, Vacb 0x%p, Valid %u)\n",
393 SharedCacheMap
, Vacb
, Valid
);
395 KeAcquireGuardedMutex(&ViewLock
);
396 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
400 WasDirty
= Vacb
->Dirty
;
401 Vacb
->Dirty
= Vacb
->Dirty
|| Dirty
;
403 if (!WasDirty
&& Vacb
->Dirty
)
405 InsertTailList(&DirtyVacbListHead
, &Vacb
->DirtyVacbListEntry
);
406 DirtyPageCount
+= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
413 CcRosVacbDecRefCount(Vacb
);
414 if (Mapped
&& (Vacb
->MappedCount
== 1))
416 CcRosVacbIncRefCount(Vacb
);
418 if (!WasDirty
&& Vacb
->Dirty
)
420 CcRosVacbIncRefCount(Vacb
);
423 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
424 KeReleaseGuardedMutex(&ViewLock
);
425 CcRosReleaseVacbLock(Vacb
);
427 return STATUS_SUCCESS
;
430 /* Returns with VACB Lock Held! */
434 PROS_SHARED_CACHE_MAP SharedCacheMap
,
437 PLIST_ENTRY current_entry
;
441 ASSERT(SharedCacheMap
);
443 DPRINT("CcRosLookupVacb(SharedCacheMap 0x%p, FileOffset %I64u)\n",
444 SharedCacheMap
, FileOffset
);
446 KeAcquireGuardedMutex(&ViewLock
);
447 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
449 current_entry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
450 while (current_entry
!= &SharedCacheMap
->CacheMapVacbListHead
)
452 current
= CONTAINING_RECORD(current_entry
,
454 CacheMapVacbListEntry
);
455 if (IsPointInRange(current
->FileOffset
.QuadPart
,
456 VACB_MAPPING_GRANULARITY
,
459 CcRosVacbIncRefCount(current
);
460 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
461 KeReleaseGuardedMutex(&ViewLock
);
462 CcRosAcquireVacbLock(current
, NULL
);
465 if (current
->FileOffset
.QuadPart
> FileOffset
)
467 current_entry
= current_entry
->Flink
;
470 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
471 KeReleaseGuardedMutex(&ViewLock
);
479 PROS_SHARED_CACHE_MAP SharedCacheMap
,
485 ASSERT(SharedCacheMap
);
487 DPRINT("CcRosMarkDirtyVacb(SharedCacheMap 0x%p, FileOffset %I64u)\n",
488 SharedCacheMap
, FileOffset
);
490 Vacb
= CcRosLookupVacb(SharedCacheMap
, FileOffset
);
493 KeBugCheck(CACHE_MANAGER
);
496 KeAcquireGuardedMutex(&ViewLock
);
497 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
501 InsertTailList(&DirtyVacbListHead
, &Vacb
->DirtyVacbListEntry
);
502 DirtyPageCount
+= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
506 CcRosVacbDecRefCount(Vacb
);
509 /* Move to the tail of the LRU list */
510 RemoveEntryList(&Vacb
->VacbLruListEntry
);
511 InsertTailList(&VacbLruListHead
, &Vacb
->VacbLruListEntry
);
515 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
516 KeReleaseGuardedMutex(&ViewLock
);
517 CcRosReleaseVacbLock(Vacb
);
519 return STATUS_SUCCESS
;
525 PROS_SHARED_CACHE_MAP SharedCacheMap
,
533 ASSERT(SharedCacheMap
);
535 DPRINT("CcRosUnmapVacb(SharedCacheMap 0x%p, FileOffset %I64u, NowDirty %u)\n",
536 SharedCacheMap
, FileOffset
, NowDirty
);
538 Vacb
= CcRosLookupVacb(SharedCacheMap
, FileOffset
);
541 return STATUS_UNSUCCESSFUL
;
544 KeAcquireGuardedMutex(&ViewLock
);
545 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
547 WasDirty
= Vacb
->Dirty
;
548 Vacb
->Dirty
= Vacb
->Dirty
|| NowDirty
;
552 if (!WasDirty
&& NowDirty
)
554 InsertTailList(&DirtyVacbListHead
, &Vacb
->DirtyVacbListEntry
);
555 DirtyPageCount
+= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
558 CcRosVacbDecRefCount(Vacb
);
559 if (!WasDirty
&& NowDirty
)
561 CcRosVacbIncRefCount(Vacb
);
563 if (Vacb
->MappedCount
== 0)
565 CcRosVacbDecRefCount(Vacb
);
568 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
569 KeReleaseGuardedMutex(&ViewLock
);
570 CcRosReleaseVacbLock(Vacb
);
572 return STATUS_SUCCESS
;
582 ULONG_PTR NumberOfPages
;
584 /* Create a memory area. */
585 MmLockAddressSpace(MmGetKernelAddressSpace());
586 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
587 0, // nothing checks for VACB mareas, so set to 0
589 VACB_MAPPING_GRANULARITY
,
591 (PMEMORY_AREA
*)&Vacb
->MemoryArea
,
594 MmUnlockAddressSpace(MmGetKernelAddressSpace());
595 if (!NT_SUCCESS(Status
))
597 DPRINT1("MmCreateMemoryArea failed with %lx for VACB %p\n", Status
, Vacb
);
601 ASSERT(((ULONG_PTR
)Vacb
->BaseAddress
% PAGE_SIZE
) == 0);
602 ASSERT((ULONG_PTR
)Vacb
->BaseAddress
> (ULONG_PTR
)MmSystemRangeStart
);
604 /* Create a virtual mapping for this memory area */
605 NumberOfPages
= BYTES_TO_PAGES(VACB_MAPPING_GRANULARITY
);
606 for (i
= 0; i
< NumberOfPages
; i
++)
608 PFN_NUMBER PageFrameNumber
;
610 Status
= MmRequestPageMemoryConsumer(MC_CACHE
, TRUE
, &PageFrameNumber
);
611 if (PageFrameNumber
== 0)
613 DPRINT1("Unable to allocate page\n");
614 KeBugCheck(MEMORY_MANAGEMENT
);
617 Status
= MmCreateVirtualMapping(NULL
,
618 (PVOID
)((ULONG_PTR
)Vacb
->BaseAddress
+ (i
* PAGE_SIZE
)),
622 if (!NT_SUCCESS(Status
))
624 DPRINT1("Unable to create virtual mapping\n");
625 KeBugCheck(MEMORY_MANAGEMENT
);
629 return STATUS_SUCCESS
;
635 PROS_SHARED_CACHE_MAP SharedCacheMap
,
641 PLIST_ENTRY current_entry
;
645 ASSERT(SharedCacheMap
);
647 DPRINT("CcRosCreateVacb()\n");
649 if (FileOffset
>= SharedCacheMap
->SectionSize
.QuadPart
)
652 return STATUS_INVALID_PARAMETER
;
655 current
= ExAllocateFromNPagedLookasideList(&VacbLookasideList
);
656 current
->BaseAddress
= NULL
;
657 current
->Valid
= FALSE
;
658 current
->Dirty
= FALSE
;
659 current
->PageOut
= FALSE
;
660 current
->FileOffset
.QuadPart
= ROUND_DOWN(FileOffset
, VACB_MAPPING_GRANULARITY
);
661 current
->SharedCacheMap
= SharedCacheMap
;
663 if (SharedCacheMap
->Trace
)
665 DPRINT1("CacheMap 0x%p: new VACB: 0x%p\n", SharedCacheMap
, current
);
668 current
->MappedCount
= 0;
669 current
->DirtyVacbListEntry
.Flink
= NULL
;
670 current
->DirtyVacbListEntry
.Blink
= NULL
;
671 current
->ReferenceCount
= 1;
672 current
->PinCount
= 0;
673 KeInitializeMutex(¤t
->Mutex
, 0);
674 CcRosAcquireVacbLock(current
, NULL
);
675 KeAcquireGuardedMutex(&ViewLock
);
678 /* There is window between the call to CcRosLookupVacb
679 * and CcRosCreateVacb. We must check if a VACB for the
680 * file offset exist. If there is a VACB, we release
681 * our newly created VACB and return the existing one.
683 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
684 current_entry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
686 while (current_entry
!= &SharedCacheMap
->CacheMapVacbListHead
)
688 current
= CONTAINING_RECORD(current_entry
,
690 CacheMapVacbListEntry
);
691 if (IsPointInRange(current
->FileOffset
.QuadPart
,
692 VACB_MAPPING_GRANULARITY
,
695 CcRosVacbIncRefCount(current
);
696 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
698 if (SharedCacheMap
->Trace
)
700 DPRINT1("CacheMap 0x%p: deleting newly created VACB 0x%p ( found existing one 0x%p )\n",
706 CcRosReleaseVacbLock(*Vacb
);
707 KeReleaseGuardedMutex(&ViewLock
);
708 ExFreeToNPagedLookasideList(&VacbLookasideList
, *Vacb
);
710 CcRosAcquireVacbLock(current
, NULL
);
711 return STATUS_SUCCESS
;
713 if (current
->FileOffset
.QuadPart
< FileOffset
)
715 ASSERT(previous
== NULL
||
716 previous
->FileOffset
.QuadPart
< current
->FileOffset
.QuadPart
);
719 if (current
->FileOffset
.QuadPart
> FileOffset
)
721 current_entry
= current_entry
->Flink
;
723 /* There was no existing VACB. */
727 InsertHeadList(&previous
->CacheMapVacbListEntry
, ¤t
->CacheMapVacbListEntry
);
731 InsertHeadList(&SharedCacheMap
->CacheMapVacbListHead
, ¤t
->CacheMapVacbListEntry
);
733 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
734 InsertTailList(&VacbLruListHead
, ¤t
->VacbLruListEntry
);
735 KeReleaseGuardedMutex(&ViewLock
);
737 MI_SET_USAGE(MI_USAGE_CACHE
);
739 if ((SharedCacheMap
->FileObject
) && (SharedCacheMap
->FileObject
->FileName
.Buffer
))
743 pos
= wcsrchr(SharedCacheMap
->FileObject
->FileName
.Buffer
, '\\');
744 len
= wcslen(pos
) * sizeof(WCHAR
);
745 if (pos
) snprintf(MI_PFN_CURRENT_PROCESS_NAME
, min(16, len
), "%S", pos
);
749 Status
= CcRosMapVacb(current
);
750 if (!NT_SUCCESS(Status
))
752 RemoveEntryList(¤t
->CacheMapVacbListEntry
);
753 RemoveEntryList(¤t
->VacbLruListEntry
);
754 CcRosReleaseVacbLock(current
);
755 ExFreeToNPagedLookasideList(&VacbLookasideList
, current
);
764 PROS_SHARED_CACHE_MAP SharedCacheMap
,
766 PLONGLONG BaseOffset
,
774 ASSERT(SharedCacheMap
);
776 DPRINT("CcRosGetVacb()\n");
779 * Look for a VACB already mapping the same data.
781 current
= CcRosLookupVacb(SharedCacheMap
, FileOffset
);
785 * Otherwise create a new VACB.
787 Status
= CcRosCreateVacb(SharedCacheMap
, FileOffset
, ¤t
);
788 if (!NT_SUCCESS(Status
))
794 KeAcquireGuardedMutex(&ViewLock
);
796 /* Move to the tail of the LRU list */
797 RemoveEntryList(¤t
->VacbLruListEntry
);
798 InsertTailList(&VacbLruListHead
, ¤t
->VacbLruListEntry
);
800 KeReleaseGuardedMutex(&ViewLock
);
803 * Return information about the VACB to the caller.
805 *UptoDate
= current
->Valid
;
806 *BaseAddress
= current
->BaseAddress
;
807 DPRINT("*BaseAddress %p\n", *BaseAddress
);
809 *BaseOffset
= current
->FileOffset
.QuadPart
;
810 return STATUS_SUCCESS
;
816 PROS_SHARED_CACHE_MAP SharedCacheMap
,
822 * FUNCTION: Request a page mapping for a shared cache map
827 ASSERT(SharedCacheMap
);
829 if (FileOffset
% VACB_MAPPING_GRANULARITY
!= 0)
831 DPRINT1("Bad fileoffset %I64x should be multiple of %x",
832 FileOffset
, VACB_MAPPING_GRANULARITY
);
833 KeBugCheck(CACHE_MANAGER
);
836 return CcRosGetVacb(SharedCacheMap
,
848 MEMORY_AREA
* MemoryArea
,
854 ASSERT(SwapEntry
== 0);
857 ASSERT(MmGetReferenceCountPage(Page
) == 1);
858 MmReleasePageMemoryConsumer(MC_CACHE
, Page
);
863 CcRosInternalFreeVacb (
866 * FUNCTION: Releases a VACB associated with a shared cache map
869 DPRINT("Freeing VACB 0x%p\n", Vacb
);
871 if (Vacb
->SharedCacheMap
->Trace
)
873 DPRINT1("CacheMap 0x%p: deleting VACB: 0x%p\n", Vacb
->SharedCacheMap
, Vacb
);
877 MmLockAddressSpace(MmGetKernelAddressSpace());
878 MmFreeMemoryArea(MmGetKernelAddressSpace(),
882 MmUnlockAddressSpace(MmGetKernelAddressSpace());
884 ExFreeToNPagedLookasideList(&VacbLookasideList
, Vacb
);
885 return STATUS_SUCCESS
;
894 IN PSECTION_OBJECT_POINTERS SectionObjectPointers
,
895 IN PLARGE_INTEGER FileOffset OPTIONAL
,
897 OUT PIO_STATUS_BLOCK IoStatus
)
899 PROS_SHARED_CACHE_MAP SharedCacheMap
;
900 LARGE_INTEGER Offset
;
901 LONGLONG RemainingLength
;
906 CCTRACE(CC_API_DEBUG
, "SectionObjectPointers=%p FileOffset=%p Length=%lu\n",
907 SectionObjectPointers
, FileOffset
, Length
);
909 DPRINT("CcFlushCache(SectionObjectPointers 0x%p, FileOffset 0x%p, Length %lu, IoStatus 0x%p)\n",
910 SectionObjectPointers
, FileOffset
, Length
, IoStatus
);
912 if (SectionObjectPointers
&& SectionObjectPointers
->SharedCacheMap
)
914 SharedCacheMap
= SectionObjectPointers
->SharedCacheMap
;
915 ASSERT(SharedCacheMap
);
918 Offset
= *FileOffset
;
919 RemainingLength
= Length
;
924 RemainingLength
= SharedCacheMap
->FileSize
.QuadPart
;
929 IoStatus
->Status
= STATUS_SUCCESS
;
930 IoStatus
->Information
= 0;
933 while (RemainingLength
> 0)
935 current
= CcRosLookupVacb(SharedCacheMap
, Offset
.QuadPart
);
940 Status
= CcRosFlushVacb(current
);
941 if (!NT_SUCCESS(Status
) && IoStatus
!= NULL
)
943 IoStatus
->Status
= Status
;
947 CcRosReleaseVacbLock(current
);
949 KeAcquireGuardedMutex(&ViewLock
);
950 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
951 CcRosVacbDecRefCount(current
);
952 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
953 KeReleaseGuardedMutex(&ViewLock
);
956 Offset
.QuadPart
+= VACB_MAPPING_GRANULARITY
;
957 RemainingLength
-= min(RemainingLength
, VACB_MAPPING_GRANULARITY
);
964 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
971 CcRosDeleteFileCache (
972 PFILE_OBJECT FileObject
,
973 PROS_SHARED_CACHE_MAP SharedCacheMap
)
975 * FUNCTION: Releases the shared cache map associated with a file object
978 PLIST_ENTRY current_entry
;
983 ASSERT(SharedCacheMap
);
985 SharedCacheMap
->OpenCount
++;
986 KeReleaseGuardedMutex(&ViewLock
);
988 CcFlushCache(FileObject
->SectionObjectPointer
, NULL
, 0, NULL
);
990 KeAcquireGuardedMutex(&ViewLock
);
991 SharedCacheMap
->OpenCount
--;
992 if (SharedCacheMap
->OpenCount
== 0)
994 FileObject
->SectionObjectPointer
->SharedCacheMap
= NULL
;
999 InitializeListHead(&FreeList
);
1000 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &oldIrql
);
1001 while (!IsListEmpty(&SharedCacheMap
->CacheMapVacbListHead
))
1003 current_entry
= RemoveTailList(&SharedCacheMap
->CacheMapVacbListHead
);
1004 current
= CONTAINING_RECORD(current_entry
, ROS_VACB
, CacheMapVacbListEntry
);
1005 RemoveEntryList(¤t
->VacbLruListEntry
);
1008 RemoveEntryList(¤t
->DirtyVacbListEntry
);
1009 DirtyPageCount
-= VACB_MAPPING_GRANULARITY
/ PAGE_SIZE
;
1010 DPRINT1("Freeing dirty VACB\n");
1012 InsertHeadList(&FreeList
, ¤t
->CacheMapVacbListEntry
);
1015 SharedCacheMap
->Trace
= FALSE
;
1017 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, oldIrql
);
1019 KeReleaseGuardedMutex(&ViewLock
);
1020 ObDereferenceObject(SharedCacheMap
->FileObject
);
1022 while (!IsListEmpty(&FreeList
))
1024 current_entry
= RemoveTailList(&FreeList
);
1025 current
= CONTAINING_RECORD(current_entry
, ROS_VACB
, CacheMapVacbListEntry
);
1026 CcRosInternalFreeVacb(current
);
1028 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList
, SharedCacheMap
);
1029 KeAcquireGuardedMutex(&ViewLock
);
1031 return STATUS_SUCCESS
;
1036 CcRosReferenceCache (
1037 PFILE_OBJECT FileObject
)
1039 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1040 KeAcquireGuardedMutex(&ViewLock
);
1041 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1042 ASSERT(SharedCacheMap
);
1043 ASSERT(SharedCacheMap
->OpenCount
!= 0);
1044 SharedCacheMap
->OpenCount
++;
1045 KeReleaseGuardedMutex(&ViewLock
);
1050 CcRosRemoveIfClosed (
1051 PSECTION_OBJECT_POINTERS SectionObjectPointer
)
1053 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1054 DPRINT("CcRosRemoveIfClosed()\n");
1055 KeAcquireGuardedMutex(&ViewLock
);
1056 SharedCacheMap
= SectionObjectPointer
->SharedCacheMap
;
1057 if (SharedCacheMap
&& SharedCacheMap
->OpenCount
== 0)
1059 CcRosDeleteFileCache(SharedCacheMap
->FileObject
, SharedCacheMap
);
1061 KeReleaseGuardedMutex(&ViewLock
);
1067 CcRosDereferenceCache (
1068 PFILE_OBJECT FileObject
)
1070 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1071 KeAcquireGuardedMutex(&ViewLock
);
1072 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1073 ASSERT(SharedCacheMap
);
1074 if (SharedCacheMap
->OpenCount
> 0)
1076 SharedCacheMap
->OpenCount
--;
1077 if (SharedCacheMap
->OpenCount
== 0)
1079 MmFreeSectionSegments(SharedCacheMap
->FileObject
);
1080 CcRosDeleteFileCache(FileObject
, SharedCacheMap
);
1083 KeReleaseGuardedMutex(&ViewLock
);
1088 CcRosReleaseFileCache (
1089 PFILE_OBJECT FileObject
)
1091 * FUNCTION: Called by the file system when a handle to a file object
1095 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1097 KeAcquireGuardedMutex(&ViewLock
);
1099 if (FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
1101 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1102 if (FileObject
->PrivateCacheMap
!= NULL
)
1104 FileObject
->PrivateCacheMap
= NULL
;
1105 if (SharedCacheMap
->OpenCount
> 0)
1107 SharedCacheMap
->OpenCount
--;
1108 if (SharedCacheMap
->OpenCount
== 0)
1110 MmFreeSectionSegments(SharedCacheMap
->FileObject
);
1111 CcRosDeleteFileCache(FileObject
, SharedCacheMap
);
1116 KeReleaseGuardedMutex(&ViewLock
);
1117 return STATUS_SUCCESS
;
1122 CcTryToInitializeFileCache (
1123 PFILE_OBJECT FileObject
)
1125 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1128 KeAcquireGuardedMutex(&ViewLock
);
1130 ASSERT(FileObject
->SectionObjectPointer
);
1131 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1132 if (SharedCacheMap
== NULL
)
1134 Status
= STATUS_UNSUCCESSFUL
;
1138 if (FileObject
->PrivateCacheMap
== NULL
)
1140 FileObject
->PrivateCacheMap
= SharedCacheMap
;
1141 SharedCacheMap
->OpenCount
++;
1143 Status
= STATUS_SUCCESS
;
1145 KeReleaseGuardedMutex(&ViewLock
);
1153 CcRosInitializeFileCache (
1154 PFILE_OBJECT FileObject
,
1155 PCC_FILE_SIZES FileSizes
,
1157 PCACHE_MANAGER_CALLBACKS CallBacks
,
1158 PVOID LazyWriterContext
)
1160 * FUNCTION: Initializes a shared cache map for a file object
1163 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1165 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
1166 DPRINT("CcRosInitializeFileCache(FileObject 0x%p, SharedCacheMap 0x%p)\n",
1167 FileObject
, SharedCacheMap
);
1169 KeAcquireGuardedMutex(&ViewLock
);
1170 if (SharedCacheMap
== NULL
)
1172 SharedCacheMap
= ExAllocateFromNPagedLookasideList(&SharedCacheMapLookasideList
);
1173 if (SharedCacheMap
== NULL
)
1175 KeReleaseGuardedMutex(&ViewLock
);
1176 return STATUS_INSUFFICIENT_RESOURCES
;
1178 RtlZeroMemory(SharedCacheMap
, sizeof(*SharedCacheMap
));
1179 ObReferenceObjectByPointer(FileObject
,
1183 SharedCacheMap
->FileObject
= FileObject
;
1184 SharedCacheMap
->Callbacks
= CallBacks
;
1185 SharedCacheMap
->LazyWriteContext
= LazyWriterContext
;
1186 SharedCacheMap
->SectionSize
= FileSizes
->AllocationSize
;
1187 SharedCacheMap
->FileSize
= FileSizes
->FileSize
;
1188 SharedCacheMap
->PinAccess
= PinAccess
;
1189 KeInitializeSpinLock(&SharedCacheMap
->CacheMapLock
);
1190 InitializeListHead(&SharedCacheMap
->CacheMapVacbListHead
);
1191 FileObject
->SectionObjectPointer
->SharedCacheMap
= SharedCacheMap
;
1193 if (FileObject
->PrivateCacheMap
== NULL
)
1195 FileObject
->PrivateCacheMap
= SharedCacheMap
;
1196 SharedCacheMap
->OpenCount
++;
1198 KeReleaseGuardedMutex(&ViewLock
);
1200 return STATUS_SUCCESS
;
1208 CcGetFileObjectFromSectionPtrs (
1209 IN PSECTION_OBJECT_POINTERS SectionObjectPointers
)
1211 PROS_SHARED_CACHE_MAP SharedCacheMap
;
1213 CCTRACE(CC_API_DEBUG
, "SectionObjectPointers=%p\n", SectionObjectPointers
);
1215 if (SectionObjectPointers
&& SectionObjectPointers
->SharedCacheMap
)
1217 SharedCacheMap
= SectionObjectPointers
->SharedCacheMap
;
1218 ASSERT(SharedCacheMap
);
1219 return SharedCacheMap
->FileObject
;
1230 DPRINT("CcInitView()\n");
1232 InitializeListHead(&DirtyVacbListHead
);
1233 InitializeListHead(&VacbLruListHead
);
1234 KeInitializeGuardedMutex(&ViewLock
);
1235 ExInitializeNPagedLookasideList(&iBcbLookasideList
,
1239 sizeof(INTERNAL_BCB
),
1242 ExInitializeNPagedLookasideList(&SharedCacheMapLookasideList
,
1246 sizeof(ROS_SHARED_CACHE_MAP
),
1247 TAG_SHARED_CACHE_MAP
,
1249 ExInitializeNPagedLookasideList(&VacbLookasideList
,
1257 MmInitializeMemoryConsumer(MC_CACHE
, CcRosTrimCache
);
1259 CcInitCacheZeroPage();