ReactOS 0.4.17-dev-573-g8315b8c
view.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for view.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

VOID CcRosTraceCacheMap (PROS_SHARED_CACHE_MAP SharedCacheMap, BOOLEAN Trace)
 
NTSTATUS CcRosFlushVacb (_In_ PROS_VACB Vacb, _Out_opt_ PIO_STATUS_BLOCK Iosb)
 
static NTSTATUS CcRosDeleteFileCache (PFILE_OBJECT FileObject, PROS_SHARED_CACHE_MAP SharedCacheMap, PKIRQL OldIrql)
 
NTSTATUS CcRosFlushDirtyPages (ULONG Target, PULONG Count, BOOLEAN Wait, BOOLEAN CalledFromLazy)
 
VOID CcRosTrimCache (_In_ ULONG Target, _Out_ PULONG NrFreed)
 
NTSTATUS CcRosReleaseVacb (PROS_SHARED_CACHE_MAP SharedCacheMap, PROS_VACB Vacb, BOOLEAN Dirty, BOOLEAN Mapped)
 
PROS_VACB CcRosLookupVacb (PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset)
 
VOID CcRosMarkDirtyVacb (PROS_VACB Vacb)
 
BOOLEAN CcRosUnmarkDirtyVacb (PROS_VACB Vacb, BOOLEAN LockViews)
 
BOOLEAN CcRosFreeOneUnusedVacb (VOID)
 
static NTSTATUS CcRosCreateVacb (PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
 
BOOLEAN CcRosEnsureVacbResident (_In_ PROS_VACB Vacb, _In_ BOOLEAN Wait, _In_ BOOLEAN NoRead, _In_ ULONG Offset, _In_ ULONG Length)
 
NTSTATUS CcRosGetVacb (PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
 
NTSTATUS CcRosRequestVacb (PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
 
NTSTATUS CcRosInternalFreeVacb (PROS_VACB Vacb)
 
VOID NTAPI CcFlushCache (IN PSECTION_OBJECT_POINTERS SectionObjectPointers, IN PLARGE_INTEGER FileOffset OPTIONAL, IN ULONG Length, OUT PIO_STATUS_BLOCK IoStatus)
 
NTSTATUS CcRosReleaseFileCache (PFILE_OBJECT FileObject)
 
NTSTATUS CcRosInitializeFileCache (PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes, BOOLEAN PinAccess, PCACHE_MANAGER_CALLBACKS CallBacks, PVOID LazyWriterContext)
 
PFILE_OBJECT NTAPI CcGetFileObjectFromSectionPtrs (IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
 
VOID NTAPI CcInitView (VOID)
 

Variables

LIST_ENTRY DirtyVacbListHead
 
static LIST_ENTRY VacbLruListHead
 
NPAGED_LOOKASIDE_LIST iBcbLookasideList
 
static NPAGED_LOOKASIDE_LIST SharedCacheMapLookasideList
 
static NPAGED_LOOKASIDE_LIST VacbLookasideList
 
ULONG CcDirtyPageThreshold = 0
 
ULONG CcTotalDirtyPages = 0
 
LIST_ENTRY CcDeferredWrites
 
KSPIN_LOCK CcDeferredWriteSpinLock
 
LIST_ENTRY CcCleanSharedCacheMapList
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 37 of file view.c.

Function Documentation

◆ CcFlushCache()

VOID NTAPI CcFlushCache ( IN PSECTION_OBJECT_POINTERS  SectionObjectPointers,
IN PLARGE_INTEGER FileOffset  OPTIONAL,
IN ULONG  Length,
OUT PIO_STATUS_BLOCK  IoStatus 
)

Definition at line 1185 of file view.c.

1190{
1191 PROS_SHARED_CACHE_MAP SharedCacheMap;
1192 LONGLONG FlushStart, FlushEnd;
1194
1195 CCTRACE(CC_API_DEBUG, "SectionObjectPointers=%p FileOffset=0x%I64X Length=%lu\n",
1196 SectionObjectPointers, FileOffset ? FileOffset->QuadPart : 0LL, Length);
1197
1198 if (!SectionObjectPointers)
1199 {
1201 goto quit;
1202 }
1203
1204 if (!SectionObjectPointers->SharedCacheMap)
1205 {
1206 /* Forward this to Mm */
1207 MmFlushSegment(SectionObjectPointers, FileOffset, Length, IoStatus);
1208 return;
1209 }
1210
1211 SharedCacheMap = SectionObjectPointers->SharedCacheMap;
1212 ASSERT(SharedCacheMap);
1213 if (FileOffset)
1214 {
1215 FlushStart = FileOffset->QuadPart;
1216 Status = RtlLongLongAdd(FlushStart, Length, &FlushEnd);
1217 if (!NT_SUCCESS(Status))
1218 goto quit;
1219 }
1220 else
1221 {
1222 FlushStart = 0;
1223 FlushEnd = SharedCacheMap->FileSize.QuadPart;
1224 }
1225
1227 if (IoStatus)
1228 {
1229 IoStatus->Information = 0;
1230 }
1231
1232 KeAcquireGuardedMutex(&SharedCacheMap->FlushCacheLock);
1233
1234 /*
1235 * We flush the VACBs that we find here.
1236 * If there is no (dirty) VACB, it doesn't mean that there is no data to flush, so we call Mm to be sure.
1237 * This is suboptimal, but this is due to the lack of granularity of how we track dirty cache data
1238 */
1239 while (FlushStart < FlushEnd)
1240 {
1241 BOOLEAN DirtyVacb = FALSE;
1242 PROS_VACB vacb = CcRosLookupVacb(SharedCacheMap, FlushStart);
1243
1244 if (vacb != NULL)
1245 {
1246 /*
1247 * NOTE: vacb->Dirty is read here without holding the spinlock.
1248 * The lock was released by CcRosLookupVacb before returning. A
1249 * concurrent flush (lazy writer) may therefore clear Dirty between
1250 * this check and the CcRosFlushVacb call below. CcRosFlushVacb
1251 * handles this safely via the guarded CcRosUnmarkDirtyVacb path.
1252 */
1253 if (vacb->Dirty)
1254 {
1255 IO_STATUS_BLOCK VacbIosb = { 0 };
1256 Status = CcRosFlushVacb(vacb, &VacbIosb);
1257 if (!NT_SUCCESS(Status))
1258 {
1259 CcRosReleaseVacb(SharedCacheMap, vacb, FALSE, FALSE);
1260 break;
1261 }
1262 DirtyVacb = TRUE;
1263
1264 if (IoStatus)
1265 IoStatus->Information += VacbIosb.Information;
1266 }
1267
1268 CcRosReleaseVacb(SharedCacheMap, vacb, FALSE, FALSE);
1269 }
1270
1271 if (!DirtyVacb)
1272 {
1273 IO_STATUS_BLOCK MmIosb;
1274 LARGE_INTEGER MmOffset;
1275
1276 MmOffset.QuadPart = FlushStart;
1277
1278 if (FlushEnd - (FlushEnd % VACB_MAPPING_GRANULARITY) <= FlushStart)
1279 {
1280 /* The whole range fits within a VACB chunk. */
1281 Status = MmFlushSegment(SectionObjectPointers, &MmOffset, FlushEnd - FlushStart, &MmIosb);
1282 }
1283 else
1284 {
1285 ULONG MmLength = VACB_MAPPING_GRANULARITY - (FlushStart % VACB_MAPPING_GRANULARITY);
1286 Status = MmFlushSegment(SectionObjectPointers, &MmOffset, MmLength, &MmIosb);
1287 }
1288
1289 if (!NT_SUCCESS(Status))
1290 break;
1291
1292 if (IoStatus)
1293 IoStatus->Information += MmIosb.Information;
1294
1295 /* Update VDL */
1296 if (SharedCacheMap->ValidDataLength.QuadPart < FlushEnd)
1297 SharedCacheMap->ValidDataLength.QuadPart = FlushEnd;
1298 }
1299
1300 if (!NT_SUCCESS(RtlLongLongAdd(FlushStart, VACB_MAPPING_GRANULARITY, &FlushStart)))
1301 {
1302 /* We're at the end of file ! */
1303 break;
1304 }
1305
1306 /* Round down to next VACB start now */
1307 FlushStart -= FlushStart % VACB_MAPPING_GRANULARITY;
1308 }
1309
1310 KeReleaseGuardedMutex(&SharedCacheMap->FlushCacheLock);
1311
1312quit:
1313 if (IoStatus)
1314 {
1315 IoStatus->Status = Status;
1316 }
1317}
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
void quit(int argc, const char *argv[])
Definition: cmds.c:1606
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
Status
Definition: gdiplustypes.h:24
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
#define ASSERT(a)
Definition: mode.c:44
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSTATUS CcRosReleaseVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, PROS_VACB Vacb, BOOLEAN Dirty, BOOLEAN Mapped)
Definition: view.c:630
NTSTATUS CcRosFlushVacb(_In_ PROS_VACB Vacb, _Out_opt_ PIO_STATUS_BLOCK Iosb)
Definition: view.c:163
PROS_VACB CcRosLookupVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset)
Definition: view.c:681
#define CC_API_DEBUG
Definition: cc.h:11
#define CCTRACE(x, fmt,...)
Definition: cc.h:36
NTSTATUS NTAPI MmFlushSegment(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER Offset, _In_ ULONG Length, _Out_opt_ PIO_STATUS_BLOCK Iosb)
Definition: section.c:5119
#define STATUS_SUCCESS
Definition: shellext.h:65
LARGE_INTEGER FileSize
Definition: cc.h:175
LARGE_INTEGER ValidDataLength
Definition: cc.h:178
KGUARDED_MUTEX FlushCacheLock
Definition: cc.h:196
Definition: cc.h:208
BOOLEAN Dirty
Definition: cc.h:212
#define LL
Definition: tui.h:166
int64_t LONGLONG
Definition: typedefs.h:68
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONGLONG QuadPart
Definition: typedefs.h:114
#define VACB_MAPPING_GRANULARITY

◆ CcGetFileObjectFromSectionPtrs()

PFILE_OBJECT NTAPI CcGetFileObjectFromSectionPtrs ( IN PSECTION_OBJECT_POINTERS  SectionObjectPointers)

Definition at line 1548 of file view.c.

1550{
1551 PROS_SHARED_CACHE_MAP SharedCacheMap;
1552
1553 CCTRACE(CC_API_DEBUG, "SectionObjectPointers=%p\n", SectionObjectPointers);
1554
1555 if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
1556 {
1557 SharedCacheMap = SectionObjectPointers->SharedCacheMap;
1558 ASSERT(SharedCacheMap);
1559 return SharedCacheMap->FileObject;
1560 }
1561 return NULL;
1562}
PFILE_OBJECT FileObject
Definition: cc.h:179

◆ CcInitView()

VOID NTAPI CcInitView ( VOID  )

Definition at line 1567 of file view.c.

1569{
1570 DPRINT("CcInitView()\n");
1571
1578 NULL,
1579 NULL,
1580 0,
1581 sizeof(INTERNAL_BCB),
1582 TAG_BCB,
1583 20);
1585 NULL,
1586 NULL,
1587 0,
1588 sizeof(ROS_SHARED_CACHE_MAP),
1590 20);
1592 NULL,
1593 NULL,
1594 0,
1595 sizeof(ROS_VACB),
1596 TAG_VACB,
1597 20);
1598
1600}
#define TAG_BCB
Definition: nodetype.h:157
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
VOID NTAPI ExInitializeNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth)
Definition: lookas.c:218
VOID NTAPI CcInitCacheZeroPage(VOID)
Definition: copy.c:56
LIST_ENTRY CcCleanSharedCacheMapList
Definition: view.c:60
static LIST_ENTRY VacbLruListHead
Definition: view.c:43
KSPIN_LOCK CcDeferredWriteSpinLock
Definition: view.c:59
LIST_ENTRY CcDeferredWrites
Definition: view.c:58
NPAGED_LOOKASIDE_LIST iBcbLookasideList
Definition: view.c:45
LIST_ENTRY DirtyVacbListHead
Definition: view.c:42
static NPAGED_LOOKASIDE_LIST SharedCacheMapLookasideList
Definition: view.c:46
static NPAGED_LOOKASIDE_LIST VacbLookasideList
Definition: view.c:47
#define DPRINT
Definition: sndvol32.h:73
#define TAG_SHARED_CACHE_MAP
Definition: tag.h:16
#define TAG_VACB
Definition: tag.h:15

Referenced by CcInitializeCacheManager().

◆ CcRosCreateVacb()

static NTSTATUS CcRosCreateVacb ( PROS_SHARED_CACHE_MAP  SharedCacheMap,
LONGLONG  FileOffset,
PROS_VACB Vacb 
)
static

Definition at line 881 of file view.c.

885{
887 PROS_VACB previous;
888 PLIST_ENTRY current_entry;
890 KIRQL oldIrql;
891 ULONG Refs;
893
894 ASSERT(SharedCacheMap);
895
896 DPRINT("CcRosCreateVacb()\n");
897
898 current = ExAllocateFromNPagedLookasideList(&VacbLookasideList);
899 if (!current)
900 {
902 }
903 current->BaseAddress = NULL;
904 current->Dirty = FALSE;
905 current->PageOut = FALSE;
906 current->FileOffset.QuadPart = ROUND_DOWN(FileOffset, VACB_MAPPING_GRANULARITY);
907 current->SharedCacheMap = SharedCacheMap;
908 current->MappedCount = 0;
909 current->ReferenceCount = 0;
910 InitializeListHead(&current->CacheMapVacbListEntry);
911 InitializeListHead(&current->DirtyVacbListEntry);
912 InitializeListHead(&current->VacbLruListEntry);
913
915
916 while (TRUE)
917 {
918 /* Map VACB in system space */
919 Status = MmMapViewInSystemSpaceEx(SharedCacheMap->Section, &current->BaseAddress, &ViewSize, &current->FileOffset, 0);
920 if (NT_SUCCESS(Status))
921 {
922 break;
923 }
924
925 /*
926 * If no space left, try to prune one unused VACB to recover space to map our VACB.
927 * If it succeeds, retry to map, otherwise just fail.
928 */
930 {
931 ExFreeToNPagedLookasideList(&VacbLookasideList, current);
932 return Status;
933 }
934 }
935
936#if DBG
937 if (SharedCacheMap->Trace)
938 {
939 DPRINT1("CacheMap 0x%p: new VACB: 0x%p, file offset %I64d, BaseAddress %p\n",
940 SharedCacheMap, current, current->FileOffset.QuadPart, current->BaseAddress);
941 }
942#endif
943
945
946 *Vacb = current;
947 /* There is window between the call to CcRosLookupVacb
948 * and CcRosCreateVacb. We must check if a VACB for the
949 * file offset exist. If there is a VACB, we release
950 * our newly created VACB and return the existing one.
951 */
953 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
954 previous = NULL;
955 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
956 {
957 current = CONTAINING_RECORD(current_entry,
958 ROS_VACB,
959 CacheMapVacbListEntry);
960 if (IsPointInRange(current->FileOffset.QuadPart,
962 FileOffset))
963 {
966#if DBG
967 if (SharedCacheMap->Trace)
968 {
969 DPRINT1("CacheMap 0x%p: deleting newly created VACB 0x%p ( found existing one 0x%p )\n",
970 SharedCacheMap,
971 (*Vacb),
972 current);
973 }
974#endif
976
977 Refs = CcRosVacbDecRefCount(*Vacb);
978 ASSERT(Refs == 0);
979
980 *Vacb = current;
981 return STATUS_SUCCESS;
982 }
983 if (current->FileOffset.QuadPart < FileOffset)
984 {
985 ASSERT(previous == NULL ||
986 previous->FileOffset.QuadPart < current->FileOffset.QuadPart);
987 previous = current;
988 }
989 if (current->FileOffset.QuadPart > FileOffset)
990 break;
991 current_entry = current_entry->Flink;
992 }
993 /* There was no existing VACB. */
994 current = *Vacb;
995 if (previous)
996 {
997 InsertHeadList(&previous->CacheMapVacbListEntry, &current->CacheMapVacbListEntry);
998 }
999 else
1000 {
1001 InsertHeadList(&SharedCacheMap->CacheMapVacbListHead, &current->CacheMapVacbListEntry);
1002 }
1004 InsertTailList(&VacbLruListHead, &current->VacbLruListEntry);
1005
1006 /* Reference it to allow release */
1008
1010
1011 return Status;
1012}
#define DPRINT1
Definition: precomp.h:8
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:33
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
struct task_struct * current
Definition: linux.c:32
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize _Pre_valid_ PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:412
BOOLEAN CcRosFreeOneUnusedVacb(VOID)
Definition: view.c:821
#define CcRosVacbIncRefCount(vacb)
Definition: cc.h:496
FORCEINLINE BOOLEAN IsPointInRange(_In_ LONGLONG Offset1, _In_ LONGLONG Length1, _In_ LONGLONG Point)
Definition: cc.h:462
FORCEINLINE ULONG CcRosVacbDecRefCount(PROS_VACB vacb)
Definition: cc.h:499
NTSTATUS NTAPI MmMapViewInSystemSpaceEx(_In_ PVOID Section, _Outptr_result_bytebuffer_(*ViewSize) PVOID *MappedBase, _Inout_ PSIZE_T ViewSize, _Inout_ PLARGE_INTEGER SectionOffset, _In_ ULONG_PTR Flags)
Definition: section.c:4517
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY CacheMapVacbListHead
Definition: cc.h:193
KSPIN_LOCK CacheMapLock
Definition: cc.h:195
LIST_ENTRY CacheMapVacbListEntry
Definition: cc.h:217
LARGE_INTEGER FileOffset
Definition: cc.h:223
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
@ LockQueueMasterLock
Definition: ketypes.h:731

Referenced by CcRosGetVacb().

◆ CcRosDeleteFileCache()

static NTSTATUS CcRosDeleteFileCache ( PFILE_OBJECT  FileObject,
PROS_SHARED_CACHE_MAP  SharedCacheMap,
PKIRQL  OldIrql 
)
static

Definition at line 230 of file view.c.

237{
238 LIST_ENTRY LocalVacbList;
239
240 ASSERT(SharedCacheMap);
241 ASSERT(SharedCacheMap == FileObject->SectionObjectPointer->SharedCacheMap);
242 ASSERT(SharedCacheMap->OpenCount == 0);
243
244 InitializeListHead(&LocalVacbList);
245
246 /*
247 * Remove all VACBs from the global lists while holding the lock. By also
248 * removing them from CacheMapVacbListHead here (under the lock), we ensure
249 * that a concurrent CcRosLookupVacb (which also holds the lock) cannot find
250 * any of these VACBs after we release the lock. Without this, a caller that
251 * already has a SharedCacheMap pointer (e.g. CcFlushCache) could look up a
252 * VACB between our lock release and the point where the second loop removes
253 * it from the list — leaving an outstanding reference that races with our
254 * CcRosVacbDecRefCount call below.
255 */
257 while (!IsListEmpty(&SharedCacheMap->CacheMapVacbListHead))
258 {
260 ROS_VACB, CacheMapVacbListEntry);
261
264
265 if (Vacb->Dirty)
266 {
268 /* Mark it as dirty again so we know that we have to flush before freeing it */
269 Vacb->Dirty = TRUE;
270 }
271
272 /*
273 * Move this VACB from the shared cache map list to our private local
274 * list. After the lock is released, CcRosLookupVacb can no longer find
275 * it, so no new lookup references can be created.
276 */
278 InsertTailList(&LocalVacbList, &Vacb->CacheMapVacbListEntry);
279 }
280
281 /* Make sure there is no trace anymore of this map */
282 FileObject->SectionObjectPointer->SharedCacheMap = NULL;
283 RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks);
284
287
288 /* Now that we're out of the locks, free everything for real */
289 while (!IsListEmpty(&LocalVacbList))
290 {
291 PROS_VACB Vacb = CONTAINING_RECORD(RemoveHeadList(&LocalVacbList), ROS_VACB, CacheMapVacbListEntry);
292 ULONG RefCount;
293
295
296 /* Flush to disk, if needed */
297 if (Vacb->Dirty)
298 {
301
302 Status = MmFlushSegment(FileObject->SectionObjectPointer, &Vacb->FileOffset, VACB_MAPPING_GRANULARITY, &Iosb);
303 if (!NT_SUCCESS(Status))
304 {
305 /* Complain. There's not much we can do */
306 DPRINT1("Failed to flush VACB to disk while deleting the cache entry. Status: 0x%08x\n", Status);
307 }
308 Vacb->Dirty = FALSE;
309 }
310
311 RefCount = CcRosVacbDecRefCount(Vacb);
312#if DBG // CORE-14578
313 if (RefCount != 0)
314 {
315 DPRINT1("Leaking VACB %p attached to %p (%I64d)\n", Vacb, FileObject, Vacb->FileOffset.QuadPart);
316 DPRINT1("There are: %d references left\n", RefCount);
317 DPRINT1("Map: %d\n", Vacb->MappedCount);
318 DPRINT1("Dirty: %d\n", Vacb->Dirty);
319 if (FileObject->FileName.Length != 0)
320 {
321 DPRINT1("File was: %wZ\n", &FileObject->FileName);
322 }
323 else
324 {
325 DPRINT1("No name for the file\n");
326 }
327 }
328#else
329 (void)RefCount;
330#endif
331 }
332
333 /* Release the references we own */
334 if(SharedCacheMap->Section)
335 ObDereferenceObject(SharedCacheMap->Section);
336 ObDereferenceObject(SharedCacheMap->FileObject);
337
338 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap);
339
340 /* Acquire the lock again for our caller */
342
343 return STATUS_SUCCESS;
344}
return Iosb
Definition: create.c:4403
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
BOOLEAN CcRosUnmarkDirtyVacb(PROS_VACB Vacb, BOOLEAN LockViews)
Definition: view.c:771
LIST_ENTRY SharedCacheMapLinks
Definition: cc.h:181
ULONG OpenCount
Definition: cc.h:174
ULONG MappedCount
Definition: cc.h:215
LIST_ENTRY VacbLruListEntry
Definition: cc.h:221
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by CcRosFlushDirtyPages(), and CcRosReleaseFileCache().

◆ CcRosEnsureVacbResident()

BOOLEAN CcRosEnsureVacbResident ( _In_ PROS_VACB  Vacb,
_In_ BOOLEAN  Wait,
_In_ BOOLEAN  NoRead,
_In_ ULONG  Offset,
_In_ ULONG  Length 
)

Definition at line 1015 of file view.c.

1022{
1023 PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
1024
1026
1027#if 0
1028 if ((Vacb->FileOffset.QuadPart + Offset) > SharedCacheMap->SectionSize.QuadPart)
1029 {
1030 DPRINT1("Vacb read beyond the file size!\n");
1031 return FALSE;
1032 }
1033#endif
1034
1035 /* Check if the pages are resident */
1036 if (!MmIsDataSectionResident(SharedCacheMap->FileObject->SectionObjectPointer,
1037 Vacb->FileOffset.QuadPart + Offset,
1038 Length))
1039 {
1040 if (!Wait)
1041 {
1042 return FALSE;
1043 }
1044
1045 if (!NoRead)
1046 {
1047 NTSTATUS Status = MmMakeDataSectionResident(SharedCacheMap->FileObject->SectionObjectPointer,
1048 Vacb->FileOffset.QuadPart + Offset,
1049 Length,
1050 &SharedCacheMap->ValidDataLength);
1051 if (!NT_SUCCESS(Status))
1053 }
1054 }
1055
1056 return TRUE;
1057}
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
BOOLEAN NTAPI MmIsDataSectionResident(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length)
Definition: section.c:5000
NTSTATUS NTAPI MmMakeDataSectionResident(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length, _In_ PLARGE_INTEGER ValidDataLength)
Definition: section.c:5042
#define ExRaiseStatus
Definition: ntoskrnl.h:114
LARGE_INTEGER SectionSize
Definition: cc.h:177
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170

Referenced by CcCopyRead(), CcCopyWrite(), CcMapData(), CcPerformReadAhead(), CcpPinData(), and CcZeroData().

◆ CcRosFlushDirtyPages()

NTSTATUS CcRosFlushDirtyPages ( ULONG  Target,
PULONG  Count,
BOOLEAN  Wait,
BOOLEAN  CalledFromLazy 
)

Definition at line 347 of file view.c.

352{
353 PLIST_ENTRY current_entry;
356 BOOLEAN FlushAll = (Target == MAXULONG);
357
358 DPRINT("CcRosFlushDirtyPages(Target %lu)\n", Target);
359
360 (*Count) = 0;
361
364
365 current_entry = DirtyVacbListHead.Flink;
366 if (current_entry == &DirtyVacbListHead)
367 {
368 DPRINT("No Dirty pages\n");
369 }
370
371 while (((current_entry != &DirtyVacbListHead) && (Target > 0)) || FlushAll)
372 {
373 PROS_SHARED_CACHE_MAP SharedCacheMap;
376
377 if (current_entry == &DirtyVacbListHead)
378 {
379 ASSERT(FlushAll);
381 break;
382 current_entry = DirtyVacbListHead.Flink;
383 }
384
385 current = CONTAINING_RECORD(current_entry,
386 ROS_VACB,
387 DirtyVacbListEntry);
388 current_entry = current_entry->Flink;
389
391
392 SharedCacheMap = current->SharedCacheMap;
393
394 /* When performing lazy write, don't handle temporary files */
395 if (CalledFromLazy && BooleanFlagOn(SharedCacheMap->FileObject->Flags, FO_TEMPORARY_FILE))
396 {
398 continue;
399 }
400
401 /* Don't attempt to lazy write the files that asked not to */
402 if (CalledFromLazy && BooleanFlagOn(SharedCacheMap->Flags, WRITEBEHIND_DISABLED))
403 {
405 continue;
406 }
407
408 ASSERT(current->Dirty);
409
410 /* Do not lazy-write the same file concurrently. Fastfat ASSERTS on that */
411 if (SharedCacheMap->Flags & SHARED_CACHE_MAP_IN_LAZYWRITE)
412 {
414 continue;
415 }
416
417 SharedCacheMap->Flags |= SHARED_CACHE_MAP_IN_LAZYWRITE;
418
419 /* Keep a ref on the shared cache map */
420 SharedCacheMap->OpenCount++;
421
423
424 Locked = SharedCacheMap->Callbacks->AcquireForLazyWrite(SharedCacheMap->LazyWriteContext, Wait);
425 if (!Locked)
426 {
427 DPRINT("Not locked\n");
428 ASSERT(!Wait);
431 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;
432
433 if (--SharedCacheMap->OpenCount == 0)
434 CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);
435
436 continue;
437 }
438
441
442 SharedCacheMap->Callbacks->ReleaseFromLazyWrite(SharedCacheMap->LazyWriteContext);
443
444 /* We release the VACB before acquiring the lock again, because
445 * CcRosVacbDecRefCount might free the VACB, as CcRosFlushVacb dropped a
446 * Refcount. Freeing must be done outside of the lock.
447 * The refcount is decremented atomically. So this is OK. */
450
451 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_LAZYWRITE;
452
453 if (--SharedCacheMap->OpenCount == 0)
454 CcRosDeleteFileCache(SharedCacheMap->FileObject, SharedCacheMap, &OldIrql);
455
458 {
459 DPRINT1("CC: Failed to flush VACB.\n");
460 }
461 else
462 {
463 ULONG PagesFreed;
464
465 /* How many pages did we free? */
466 PagesFreed = Iosb.Information / PAGE_SIZE;
467 (*Count) += PagesFreed;
468
469 if (!Wait)
470 {
471 /* Make sure we don't overflow target! */
472 if (Target < PagesFreed)
473 {
474 /* If we would have, jump to zero directly */
475 Target = 0;
476 }
477 else
478 {
479 Target -= PagesFreed;
480 }
481 }
482 }
483
484 current_entry = DirtyVacbListHead.Flink;
485 }
486
489
490 DPRINT("CcRosFlushDirtyPages() finished\n");
491 return STATUS_SUCCESS;
492}
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:209
static NTSTATUS CcRosDeleteFileCache(PFILE_OBJECT FileObject, PROS_SHARED_CACHE_MAP SharedCacheMap, PKIRQL OldIrql)
Definition: view.c:230
#define WRITEBEHIND_DISABLED
Definition: cc.h:203
#define SHARED_CACHE_MAP_IN_LAZYWRITE
Definition: cc.h:205
#define STATUS_END_OF_FILE
Definition: shellext.h:67
PACQUIRE_FOR_LAZY_WRITE AcquireForLazyWrite
Definition: cctypes.h:39
PRELEASE_FROM_LAZY_WRITE ReleaseFromLazyWrite
Definition: cctypes.h:40
PCACHE_MANAGER_CALLBACKS Callbacks
Definition: cc.h:185
PVOID LazyWriteContext
Definition: cc.h:186
#define MAXULONG
Definition: typedefs.h:251
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
#define FO_TEMPORARY_FILE
Definition: iotypes.h:1791

Referenced by CcRosTrimCache(), CcWriteBehind(), and NtSetSystemPowerState().

◆ CcRosFlushVacb()

NTSTATUS CcRosFlushVacb ( _In_ PROS_VACB  Vacb,
_Out_opt_ PIO_STATUS_BLOCK  Iosb 
)

Definition at line 163 of file view.c.

166{
168 BOOLEAN HaveLock = FALSE;
169 BOOLEAN WasMarked;
170 PROS_SHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
171
172 /*
173 * Remove the VACB from the dirty list before flushing. The return value
174 * tells us whether the VACB was actually dirty at this point.
175 * If WasMarked is FALSE a concurrent flush already removed it from the
176 * dirty list. We still call MmFlushSegment because the caller expects a
177 * reliable status: if we returned STATUS_SUCCESS immediately, the caller
178 * would believe the data was safely written when in fact the concurrent
179 * flush may have failed. We must not re-mark dirty on failure in this
180 * case, however, as we were not the one who removed the VACB from the list.
181 */
182 WasMarked = CcRosUnmarkDirtyVacb(Vacb, TRUE);
183
184 /* Lock for flush, if we are not already the top-level */
186 {
187 Status = FsRtlAcquireFileForCcFlushEx(Vacb->SharedCacheMap->FileObject);
188 if (!NT_SUCCESS(Status))
189 goto quit;
190 HaveLock = TRUE;
191 }
192
193 Status = MmFlushSegment(SharedCacheMap->FileObject->SectionObjectPointer,
194 &Vacb->FileOffset,
196 Iosb);
197
198 if (HaveLock)
199 {
200 FsRtlReleaseFileForCcFlush(Vacb->SharedCacheMap->FileObject);
201 }
202
203quit:
204 if (!NT_SUCCESS(Status))
205 {
206 /*
207 * Only re-mark dirty if we were the thread that removed it from the
208 * dirty list. If WasMarked is FALSE, another thread already removed it,
209 * so we must not change dirty tracking here (that thread will re-mark on failure).
210 * CcRosMarkDirtyVacb itself guards against double-insertion should
211 * another thread have concurrently re-marked the VACB dirty.
212 */
213 if (WasMarked)
214 CcRosMarkDirtyVacb(Vacb);
215 }
216 else
217 {
218 /* Update VDL */
219 if (SharedCacheMap->ValidDataLength.QuadPart < (Vacb->FileOffset.QuadPart + VACB_MAPPING_GRANULARITY))
220 {
221 SharedCacheMap->ValidDataLength.QuadPart = Vacb->FileOffset.QuadPart + VACB_MAPPING_GRANULARITY;
222 }
223 }
224
225 return Status;
226}
#define FSRTL_CACHE_TOP_LEVEL_IRP
Definition: fsrtltypes.h:60
VOID CcRosMarkDirtyVacb(PROS_VACB Vacb)
Definition: view.c:724
NTSTATUS NTAPI FsRtlAcquireFileForCcFlushEx(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1698
VOID NTAPI FsRtlReleaseFileForCcFlush(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1771
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843

Referenced by CcFlushCache(), and CcRosFlushDirtyPages().

◆ CcRosFreeOneUnusedVacb()

BOOLEAN CcRosFreeOneUnusedVacb ( VOID  )

Definition at line 821 of file view.c.

823{
824 KIRQL oldIrql;
825 PLIST_ENTRY current_entry;
826 PROS_VACB to_free = NULL;
827
829
830 /* Browse all the available VACB */
831 current_entry = VacbLruListHead.Flink;
832 while ((current_entry != &VacbLruListHead) && (to_free == NULL))
833 {
834 ULONG Refs;
836
837 current = CONTAINING_RECORD(current_entry,
838 ROS_VACB,
839 VacbLruListEntry);
840
841 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
842
843 /* Only deal with unused VACB, we will free them */
845 if (Refs < 2)
846 {
847 ASSERT(!current->Dirty);
848 ASSERT(!current->MappedCount);
849 ASSERT(Refs == 1);
850
851 /* Reset it, this is the one we want to free */
852 RemoveEntryList(&current->CacheMapVacbListEntry);
853 InitializeListHead(&current->CacheMapVacbListEntry);
854 RemoveEntryList(&current->VacbLruListEntry);
855 InitializeListHead(&current->VacbLruListEntry);
856
857 to_free = current;
858 }
859
860 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
861
862 current_entry = current_entry->Flink;
863 }
864
866
867 /* And now, free the VACB that we found, if any. */
868 if (to_free == NULL)
869 {
870 return FALSE;
871 }
872
873 /* This must be its last ref */
874 NT_VERIFY(CcRosVacbDecRefCount(to_free) == 0);
875
876 return TRUE;
877}
#define CcRosVacbGetRefCount(vacb)
Definition: cc.h:511
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3304

Referenced by CcRosCreateVacb(), and CcWriteBehind().

◆ CcRosGetVacb()

NTSTATUS CcRosGetVacb ( PROS_SHARED_CACHE_MAP  SharedCacheMap,
LONGLONG  FileOffset,
PROS_VACB Vacb 
)

Definition at line 1061 of file view.c.

1065{
1068 ULONG Refs;
1069 KIRQL OldIrql;
1070
1071 ASSERT(SharedCacheMap);
1072
1073 DPRINT("CcRosGetVacb()\n");
1074
1075 /*
1076 * Look for a VACB already mapping the same data.
1077 */
1078 current = CcRosLookupVacb(SharedCacheMap, FileOffset);
1079 if (current == NULL)
1080 {
1081 /*
1082 * Otherwise create a new VACB.
1083 */
1084 Status = CcRosCreateVacb(SharedCacheMap, FileOffset, &current);
1085 if (!NT_SUCCESS(Status))
1086 {
1087 return Status;
1088 }
1089 }
1090
1092
1094
1095 /* Move to the tail of the LRU list */
1096 RemoveEntryList(&current->VacbLruListEntry);
1097 InsertTailList(&VacbLruListHead, &current->VacbLruListEntry);
1098
1100
1101 /*
1102 * Return the VACB to the caller.
1103 */
1104 *Vacb = current;
1105
1106 ASSERT(Refs > 1);
1107
1108 return STATUS_SUCCESS;
1109}
static NTSTATUS CcRosCreateVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:881

Referenced by CcCopyRead(), CcCopyWrite(), CcMapData(), CcpPinData(), CcRosRequestVacb(), and CcZeroData().

◆ CcRosInitializeFileCache()

NTSTATUS CcRosInitializeFileCache ( PFILE_OBJECT  FileObject,
PCC_FILE_SIZES  FileSizes,
BOOLEAN  PinAccess,
PCACHE_MANAGER_CALLBACKS  CallBacks,
PVOID  LazyWriterContext 
)

Definition at line 1376 of file view.c.

1385{
1386 KIRQL OldIrql;
1388 PROS_SHARED_CACHE_MAP SharedCacheMap;
1389
1390 DPRINT("CcRosInitializeFileCache(FileObject 0x%p)\n", FileObject);
1391
1393
1394 Allocated = FALSE;
1395 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
1396 if (SharedCacheMap == NULL)
1397 {
1398 SharedCacheMap = ExAllocateFromNPagedLookasideList(&SharedCacheMapLookasideList);
1399 if (SharedCacheMap == NULL)
1400 {
1403 }
1404 RtlZeroMemory(SharedCacheMap, sizeof(*SharedCacheMap));
1405 SharedCacheMap->NodeTypeCode = NODE_TYPE_SHARED_MAP;
1406 SharedCacheMap->NodeByteSize = sizeof(*SharedCacheMap);
1407 SharedCacheMap->FileObject = FileObject;
1408 SharedCacheMap->Callbacks = CallBacks;
1409 SharedCacheMap->LazyWriteContext = LazyWriterContext;
1410 SharedCacheMap->SectionSize = FileSizes->AllocationSize;
1411 SharedCacheMap->FileSize = FileSizes->FileSize;
1412 SharedCacheMap->ValidDataLength = FileSizes->ValidDataLength;
1413 SharedCacheMap->PinAccess = PinAccess;
1414 SharedCacheMap->DirtyPageThreshold = 0;
1415 SharedCacheMap->DirtyPages = 0;
1416 InitializeListHead(&SharedCacheMap->PrivateList);
1417 KeInitializeSpinLock(&SharedCacheMap->CacheMapLock);
1418 InitializeListHead(&SharedCacheMap->CacheMapVacbListHead);
1419 InitializeListHead(&SharedCacheMap->BcbList);
1420 KeInitializeGuardedMutex(&SharedCacheMap->FlushCacheLock);
1421
1422 SharedCacheMap->Flags = SHARED_CACHE_MAP_IN_CREATION;
1423
1426 NULL,
1427 KernelMode);
1428
1429 Allocated = TRUE;
1430 FileObject->SectionObjectPointer->SharedCacheMap = SharedCacheMap;
1431
1432 //CcRosTraceCacheMap(SharedCacheMap, TRUE);
1433 }
1434 else if (SharedCacheMap->Flags & SHARED_CACHE_MAP_IN_CREATION)
1435 {
1436 /* The shared cache map is being created somewhere else. Wait for that to happen */
1437 KEVENT Waiter;
1438 PKEVENT PreviousWaiter = SharedCacheMap->CreateEvent;
1439
1441 SharedCacheMap->CreateEvent = &Waiter;
1442
1444
1446
1447 if (PreviousWaiter)
1448 KeSetEvent(PreviousWaiter, IO_NO_INCREMENT, FALSE);
1449
1451 }
1452
1453 if (FileObject->PrivateCacheMap == NULL)
1454 {
1455 PPRIVATE_CACHE_MAP PrivateMap;
1456
1457 /* Allocate the private cache map for this handle */
1458 if (SharedCacheMap->PrivateCacheMap.NodeTypeCode != 0)
1459 {
1461 }
1462 else
1463 {
1464 PrivateMap = &SharedCacheMap->PrivateCacheMap;
1465 }
1466
1467 if (PrivateMap == NULL)
1468 {
1469 /* If we also allocated the shared cache map for this file, kill it */
1470 if (Allocated)
1471 {
1472 RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks);
1473
1474 FileObject->SectionObjectPointer->SharedCacheMap = NULL;
1476 ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap);
1477 }
1478
1481 }
1482
1483 /* Initialize it */
1484 RtlZeroMemory(PrivateMap, sizeof(PRIVATE_CACHE_MAP));
1485 PrivateMap->NodeTypeCode = NODE_TYPE_PRIVATE_MAP;
1486 PrivateMap->ReadAheadMask = PAGE_SIZE - 1;
1487 PrivateMap->FileObject = FileObject;
1489
1490 /* Link it to the file */
1491 KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock);
1492 InsertTailList(&SharedCacheMap->PrivateList, &PrivateMap->PrivateLinks);
1494
1495 FileObject->PrivateCacheMap = PrivateMap;
1496 SharedCacheMap->OpenCount++;
1497 }
1498
1500
1501 /* Create the section */
1502 if (Allocated)
1503 {
1505
1506 ASSERT(SharedCacheMap->Section == NULL);
1507
1509 &SharedCacheMap->Section,
1511 NULL,
1512 &SharedCacheMap->SectionSize,
1515 NULL,
1516 FileObject);
1517
1519
1520 if (!NT_SUCCESS(Status))
1521 {
1523 return Status;
1524 }
1525
1527
1529 SharedCacheMap->Flags &= ~SHARED_CACHE_MAP_IN_CREATION;
1530
1531 if (SharedCacheMap->CreateEvent)
1532 {
1533 KeSetEvent(SharedCacheMap->CreateEvent, IO_NO_INCREMENT, FALSE);
1534 SharedCacheMap->CreateEvent = NULL;
1535 }
1536
1538 }
1539
1540 return STATUS_SUCCESS;
1541}
static CC_FILE_SIZES FileSizes
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define NonPagedPool
Definition: env_spec_w32.h:307
IN PFCB IN VBO OUT PLBO OUT PULONG OUT PBOOLEAN Allocated
Definition: fatprocs.h:311
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
#define KernelMode
Definition: asm.h:38
#define PAGE_READWRITE
Definition: nt_native.h:1307
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1296
#define SEC_RESERVE
Definition: nt_native.h:1326
#define FILE_ALL_ACCESS
Definition: nt_native.h:651
@ NotificationEvent
NTSTATUS CcRosReleaseFileCache(PFILE_OBJECT FileObject)
Definition: view.c:1320
#define NODE_TYPE_PRIVATE_MAP
Definition: cc.h:288
#define SHARED_CACHE_MAP_IN_CREATION
Definition: cc.h:204
#define NODE_TYPE_SHARED_MAP
Definition: cc.h:289
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:380
NTSTATUS NTAPI MmCreateSection(OUT PVOID *Section, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL, IN PFILE_OBJECT FileObject OPTIONAL)
Definition: section.c:4677
LARGE_INTEGER FileSize
Definition: cctypes.h:16
LARGE_INTEGER ValidDataLength
Definition: cctypes.h:17
LARGE_INTEGER AllocationSize
Definition: cctypes.h:15
PFILE_OBJECT FileObject
Definition: cctypes.h:76
ULONG ReadAheadMask
Definition: cctypes.h:75
KSPIN_LOCK ReadAheadSpinLock
Definition: cctypes.h:83
CSHORT NodeTypeCode
Definition: cctypes.h:71
LIST_ENTRY PrivateLinks
Definition: cctypes.h:84
PRIVATE_CACHE_MAP PrivateCacheMap
Definition: cc.h:190
PKEVENT CreateEvent
Definition: cc.h:184
CSHORT NodeTypeCode
Definition: cc.h:172
ULONG DirtyPageThreshold
Definition: cc.h:188
ULONG DirtyPages
Definition: cc.h:180
LIST_ENTRY PrivateList
Definition: cc.h:187
CSHORT NodeByteSize
Definition: cc.h:173
BOOLEAN PinAccess
Definition: cc.h:194
LIST_ENTRY BcbList
Definition: cc.h:176
#define TAG_PRIVATE_CACHE_MAP
Definition: tag.h:17
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IO_NO_INCREMENT
Definition: iotypes.h:598
@ Executive
Definition: ketypes.h:467

Referenced by CcInitializeCacheMap().

◆ CcRosInternalFreeVacb()

NTSTATUS CcRosInternalFreeVacb ( PROS_VACB  Vacb)

Definition at line 1136 of file view.c.

1141{
1143
1144 DPRINT("Freeing VACB 0x%p\n", Vacb);
1145#if DBG
1146 if (Vacb->SharedCacheMap->Trace)
1147 {
1148 DPRINT1("CacheMap 0x%p: deleting VACB: 0x%p\n", Vacb->SharedCacheMap, Vacb);
1149 }
1150#endif
1151
1152 if (Vacb->ReferenceCount != 0)
1153 {
1154 DPRINT1("Invalid free: %ld\n", Vacb->ReferenceCount);
1155 if (Vacb->SharedCacheMap->FileObject && Vacb->SharedCacheMap->FileObject->FileName.Length)
1156 {
1157 DPRINT1("For file: %wZ\n", &Vacb->SharedCacheMap->FileObject->FileName);
1158 }
1159 }
1160
1161 ASSERT(Vacb->ReferenceCount == 0);
1165
1166 /* Delete the mapping */
1168 if (!NT_SUCCESS(Status))
1169 {
1170 DPRINT1("Failed to unmap VACB from System address space! Status 0x%08X\n", Status);
1171 ASSERT(FALSE);
1172 /* Proceed with the deĺetion anyway */
1173 }
1174
1175 RtlFillMemory(Vacb, sizeof(*Vacb), 0xfd);
1176 ExFreeToNPagedLookasideList(&VacbLookasideList, Vacb);
1177 return STATUS_SUCCESS;
1178}
NTSTATUS NTAPI MmUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:2777
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:603
PROS_SHARED_CACHE_MAP SharedCacheMap
Definition: cc.h:227
PVOID BaseAddress
Definition: cc.h:210
volatile ULONG ReferenceCount
Definition: cc.h:225
LIST_ENTRY DirtyVacbListEntry
Definition: cc.h:219

◆ CcRosLookupVacb()

PROS_VACB CcRosLookupVacb ( PROS_SHARED_CACHE_MAP  SharedCacheMap,
LONGLONG  FileOffset 
)

Definition at line 681 of file view.c.

684{
685 PLIST_ENTRY current_entry;
687 KIRQL oldIrql;
688
689 ASSERT(SharedCacheMap);
690
691 DPRINT("CcRosLookupVacb(SharedCacheMap 0x%p, FileOffset %I64u)\n",
692 SharedCacheMap, FileOffset);
693
696
697 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
698 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
699 {
700 current = CONTAINING_RECORD(current_entry,
701 ROS_VACB,
702 CacheMapVacbListEntry);
703 if (IsPointInRange(current->FileOffset.QuadPart,
705 FileOffset))
706 {
710 return current;
711 }
712 if (current->FileOffset.QuadPart > FileOffset)
713 break;
714 current_entry = current_entry->Flink;
715 }
716
719
720 return NULL;
721}

Referenced by CcFlushCache(), and CcRosGetVacb().

◆ CcRosMarkDirtyVacb()

VOID CcRosMarkDirtyVacb ( PROS_VACB  Vacb)

Definition at line 724 of file view.c.

726{
727 KIRQL oldIrql;
728 PROS_SHARED_CACHE_MAP SharedCacheMap;
729
730 SharedCacheMap = Vacb->SharedCacheMap;
731
734
735 if (Vacb->Dirty)
736 {
737 /*
738 * The VACB was already re-marked dirty by another thread between
739 * CcRosUnmarkDirtyVacb and this call (e.g. a concurrent writer via
740 * CcRosReleaseVacb) and the VACB has already been inserted into
741 * the dirty list.
742 */
745 return;
746 }
747
749 /* FIXME: There is no reason to account for the whole VACB. */
753
754 /* Move to the tail of the LRU list */
757
758 Vacb->Dirty = TRUE;
759
761
762 /* Schedule a lazy writer run to now that we have dirty VACB */
764 {
766 }
768}
VOID CcScheduleLazyWriteScan(IN BOOLEAN NoDelay)
Definition: lazywrite.c:210
LAZY_WRITER LazyWriter
Definition: lazywrite.c:37
ULONG CcTotalDirtyPages
Definition: view.c:57
BOOLEAN ScanActive
Definition: cc.h:247

Referenced by CcRosFlushVacb(), CcRosReleaseVacb(), and CcSetDirtyPinnedData().

◆ CcRosReleaseFileCache()

NTSTATUS CcRosReleaseFileCache ( PFILE_OBJECT  FileObject)

Definition at line 1320 of file view.c.

1326{
1327 KIRQL OldIrql;
1328 PPRIVATE_CACHE_MAP PrivateMap;
1329 PROS_SHARED_CACHE_MAP SharedCacheMap;
1330
1332
1333 if (FileObject->SectionObjectPointer->SharedCacheMap != NULL)
1334 {
1335 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
1336
1337 /* Closing the handle, so kill the private cache map
1338 * Before you event try to remove it from FO, always
1339 * lock the master lock, to be sure not to race
1340 * with a potential read ahead ongoing!
1341 */
1342 PrivateMap = FileObject->PrivateCacheMap;
1343 FileObject->PrivateCacheMap = NULL;
1344
1345 if (PrivateMap != NULL)
1346 {
1347 /* Remove it from the file */
1348 KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->CacheMapLock);
1349 RemoveEntryList(&PrivateMap->PrivateLinks);
1351
1352 /* And free it. */
1353 if (PrivateMap != &SharedCacheMap->PrivateCacheMap)
1354 {
1356 }
1357 else
1358 {
1359 PrivateMap->NodeTypeCode = 0;
1360 }
1361
1362 ASSERT(SharedCacheMap->OpenCount > 0);
1363
1364 SharedCacheMap->OpenCount--;
1365 if (SharedCacheMap->OpenCount == 0)
1366 {
1367 CcRosDeleteFileCache(FileObject, SharedCacheMap, &OldIrql);
1368 }
1369 }
1370 }
1372 return STATUS_SUCCESS;
1373}
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109

Referenced by CcRosInitializeFileCache(), and CcUninitializeCacheMap().

◆ CcRosReleaseVacb()

NTSTATUS CcRosReleaseVacb ( PROS_SHARED_CACHE_MAP  SharedCacheMap,
PROS_VACB  Vacb,
BOOLEAN  Dirty,
BOOLEAN  Mapped 
)

Definition at line 630 of file view.c.

635{
636 ASSERT(SharedCacheMap);
637
638 DPRINT("CcRosReleaseVacb(SharedCacheMap 0x%p, Vacb 0x%p)\n", SharedCacheMap, Vacb);
639
640 /*
641 * NOTE: Vacb->Dirty is read here without holding the spinlock as an
642 * optimisation to avoid an unnecessary lock acquisition. The check may
643 * race with a concurrent CcRosUnmarkDirtyVacb; however CcRosMarkDirtyVacb
644 * re-checks Dirty under the lock and is a safe no-op if the VACB has
645 * already been re-marked dirty by another thread in the meantime.
646 * If Vacb->Dirty is TRUE at the check (so we skip marking) and a concurrent
647 * flush then immediately unmarks it, that flush's MmFlushSegment call covers
648 * all dirty section pages, including those written by the caller of this
649 * function. Should that flush fail, CcRosFlushVacb re-marks the VACB dirty
650 * (WasMarked == TRUE path), ensuring those pages are retried. No dirty data
651 * can be silently lost through this race.
652 */
653 if (Dirty && !Vacb->Dirty)
654 {
655 CcRosMarkDirtyVacb(Vacb);
656 }
657
658 if (Mapped)
659 {
660 if (InterlockedIncrement((PLONG)&Vacb->MappedCount) == 1)
661 {
663 }
664 }
665
666 /*
667 * Release the caller's reference. The return value may legitimately be 0
668 * when CcRosDeleteFileCache has concurrently removed the cache-map-list
669 * reference while we held a lookup reference: our decrement is then the
670 * last one and CcRosVacbDecRefCount frees the VACB. That is safe because
671 * callers (e.g. CcFlushCache) do not access the VACB pointer after this
672 * call. Do NOT assert the result is > 0 here.
673 */
675
676 return STATUS_SUCCESS;
677}
#define InterlockedIncrement
Definition: armddk.h:53
int32_t * PLONG
Definition: typedefs.h:58

Referenced by CcCopyRead(), CcCopyWrite(), CcFlushCache(), CcMapData(), CcpDereferenceBcb(), CcPerformReadAhead(), CcpGetAppropriateBcb(), CcpPinData(), CcUnpinRepinnedBcb(), and CcZeroData().

◆ CcRosRequestVacb()

NTSTATUS CcRosRequestVacb ( PROS_SHARED_CACHE_MAP  SharedCacheMap,
LONGLONG  FileOffset,
PROS_VACB Vacb 
)

Definition at line 1112 of file view.c.

1119{
1120
1121 ASSERT(SharedCacheMap);
1122
1124 {
1125 DPRINT1("Bad FileOffset %I64x: should be multiple of %x\n",
1127 KeBugCheck(CACHE_MANAGER);
1128 }
1129
1130 return CcRosGetVacb(SharedCacheMap,
1131 FileOffset,
1132 Vacb);
1133}
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1434
NTSTATUS CcRosGetVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:1061

Referenced by CcPerformReadAhead().

◆ CcRosTraceCacheMap()

VOID CcRosTraceCacheMap ( PROS_SHARED_CACHE_MAP  SharedCacheMap,
BOOLEAN  Trace 
)

Definition at line 117 of file view.c.

120{
121#if DBG
122 KIRQL oldirql;
123 PLIST_ENTRY current_entry;
125
126 if (!SharedCacheMap)
127 return;
128
129 SharedCacheMap->Trace = Trace;
130
131 if (Trace)
132 {
133 DPRINT1("Enabling Tracing for CacheMap 0x%p:\n", SharedCacheMap);
134
137
138 current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
139 while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
140 {
141 current = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry);
142 current_entry = current_entry->Flink;
143
144 DPRINT1(" VACB 0x%p enabled, RefCount %lu, Dirty %u, PageOut %lu, BaseAddress %p, FileOffset %I64d\n",
145 current, current->ReferenceCount, current->Dirty, current->PageOut, current->BaseAddress, current->FileOffset.QuadPart);
146 }
147
150 }
151 else
152 {
153 DPRINT1("Disabling Tracing for CacheMap 0x%p:\n", SharedCacheMap);
154 }
155
156#else
157 UNREFERENCED_PARAMETER(SharedCacheMap);
159#endif
160}
#define Trace(x)
Definition: inflate.c:42
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329

◆ CcRosTrimCache()

VOID CcRosTrimCache ( _In_ ULONG  Target,
_Out_ PULONG  NrFreed 
)

Definition at line 495 of file view.c.

505{
506 PLIST_ENTRY current_entry;
508 ULONG PagesFreed;
509 KIRQL oldIrql;
511 BOOLEAN FlushedPages = FALSE;
512
513 DPRINT("CcRosTrimCache(Target %lu)\n", Target);
514
516
517 *NrFreed = 0;
518
519retry:
521
522 current_entry = VacbLruListHead.Flink;
523 while (current_entry != &VacbLruListHead)
524 {
525 ULONG Refs;
526
527 current = CONTAINING_RECORD(current_entry,
528 ROS_VACB,
529 VacbLruListEntry);
530
531 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
532
533 /* Reference the VACB */
535
536 /* Check if it's mapped and not dirty */
537 if (InterlockedCompareExchange((PLONG)&current->MappedCount, 0, 0) > 0 && !current->Dirty)
538 {
539 /* This code is never executed. It is left for reference only. */
540#if 1
541 DPRINT1("MmPageOutPhysicalAddress unexpectedly called\n");
542 ASSERT(FALSE);
543#else
544 ULONG i;
546
547 /* We have to break these locks to call MmPageOutPhysicalAddress */
548 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
550
551 /* Page out the VACB */
552 for (i = 0; i < VACB_MAPPING_GRANULARITY / PAGE_SIZE; i++)
553 {
555
557 }
558
559 /* Reacquire the locks */
561 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
562#endif
563 }
564
565 /* Only keep iterating though the loop while the lock is held */
566 current_entry = current_entry->Flink;
567
568 /* Dereference the VACB */
570
571 /* Check if we can free this entry now */
572 if (Refs < 2)
573 {
574 ASSERT(!current->Dirty);
575 ASSERT(!current->MappedCount);
576 ASSERT(Refs == 1);
577
578 RemoveEntryList(&current->CacheMapVacbListEntry);
579 RemoveEntryList(&current->VacbLruListEntry);
580 InitializeListHead(&current->VacbLruListEntry);
581 InsertHeadList(&FreeList, &current->CacheMapVacbListEntry);
582
583 /* Calculate how many pages we freed for Mm */
585 Target -= PagesFreed;
586 (*NrFreed) += PagesFreed;
587 }
588
589 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
590 }
591
593
594 /* Try flushing pages if we haven't met our target */
595 if ((Target > 0) && !FlushedPages)
596 {
597 /* Flush dirty pages to disk */
598 CcRosFlushDirtyPages(Target, &PagesFreed, FALSE, FALSE);
599 FlushedPages = TRUE;
600
601 /* We can only swap as many pages as we flushed */
602 if (PagesFreed < Target) Target = PagesFreed;
603
604 /* Check if we flushed anything */
605 if (PagesFreed != 0)
606 {
607 /* Try again after flushing dirty pages */
608 DPRINT("Flushed %lu dirty cache pages to disk\n", PagesFreed);
609 goto retry;
610 }
611 }
612
613 while (!IsListEmpty(&FreeList))
614 {
615 ULONG Refs;
616
617 current_entry = RemoveHeadList(&FreeList);
618 current = CONTAINING_RECORD(current_entry,
619 ROS_VACB,
620 CacheMapVacbListEntry);
621 InitializeListHead(&current->CacheMapVacbListEntry);
623 ASSERT(Refs == 0);
624 }
625
626 DPRINT("Evicted %lu cache pages\n", (*NrFreed));
627}
void FreeList(LOCATIONITEM *pItems)
Definition: CSearchBar.cpp:95
ULONG_PTR PFN_NUMBER
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define InterlockedCompareExchange
Definition: interlocked.h:119
#define min(a, b)
Definition: monoChain.cc:55
NTSTATUS CcRosFlushDirtyPages(ULONG Target, PULONG Count, BOOLEAN Wait, BOOLEAN CalledFromLazy)
Definition: view.c:347
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1305
NTSTATUS NTAPI MmPageOutPhysicalAddress(PFN_NUMBER Page)
Definition: rmap.c:51
PHYSICAL_ADDRESS NTAPI MmGetPhysicalAddress(IN PVOID Address)
Definition: stubs.c:685
unsigned char * PUCHAR
Definition: typedefs.h:53

Referenced by MiBalancerThread().

◆ CcRosUnmarkDirtyVacb()

BOOLEAN CcRosUnmarkDirtyVacb ( PROS_VACB  Vacb,
BOOLEAN  LockViews 
)

Definition at line 771 of file view.c.

774{
775 KIRQL oldIrql;
776 PROS_SHARED_CACHE_MAP SharedCacheMap;
777
778 SharedCacheMap = Vacb->SharedCacheMap;
779
780 if (LockViews)
781 {
784 }
785
786 if (!Vacb->Dirty)
787 {
788 ASSERT(LockViews);
789 /*
790 * The VACB was already unmarked by a concurrent flush (e.g. the lazy
791 * writer) between the caller's lockless Dirty check and this call.
792 * Proceeding would underflow CcTotalDirtyPages/DirtyPages, drop an
793 * extra refcount, and could ultimately free the VACB prematurely.
794 */
797
798 return FALSE;
799 }
800
801 Vacb->Dirty = FALSE;
802
805
808
810
811 if (LockViews)
812 {
815 }
816
817 return TRUE;
818}

Referenced by CcPurgeCacheSection(), CcRosDeleteFileCache(), and CcRosFlushVacb().

Variable Documentation

◆ CcCleanSharedCacheMapList

LIST_ENTRY CcCleanSharedCacheMapList

Definition at line 60 of file view.c.

Referenced by CcInitView(), and CcRosInitializeFileCache().

◆ CcDeferredWrites

LIST_ENTRY CcDeferredWrites

◆ CcDeferredWriteSpinLock

KSPIN_LOCK CcDeferredWriteSpinLock

Definition at line 59 of file view.c.

Referenced by CcCanIWrite(), CcDeferWrite(), CcInitView(), and CcPostDeferredWrites().

◆ CcDirtyPageThreshold

ULONG CcDirtyPageThreshold = 0

Definition at line 56 of file view.c.

Referenced by CcCanIWrite(), and CcInitializeCacheManager().

◆ CcTotalDirtyPages

ULONG CcTotalDirtyPages = 0

◆ DirtyVacbListHead

LIST_ENTRY DirtyVacbListHead

Definition at line 42 of file view.c.

Referenced by CcInitView(), CcIsThereDirtyData(), CcRosFlushDirtyPages(), and CcRosMarkDirtyVacb().

◆ iBcbLookasideList

NPAGED_LOOKASIDE_LIST iBcbLookasideList

Definition at line 45 of file view.c.

Referenced by CcInitView(), CcpDereferenceBcb(), CcpGetAppropriateBcb(), and CcUnpinRepinnedBcb().

◆ SharedCacheMapLookasideList

NPAGED_LOOKASIDE_LIST SharedCacheMapLookasideList
static

Definition at line 46 of file view.c.

Referenced by CcInitView(), CcRosDeleteFileCache(), and CcRosInitializeFileCache().

◆ VacbLookasideList

NPAGED_LOOKASIDE_LIST VacbLookasideList
static

Definition at line 47 of file view.c.

Referenced by CcInitView(), CcRosCreateVacb(), and CcRosInternalFreeVacb().

◆ VacbLruListHead

LIST_ENTRY VacbLruListHead
static