2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cc/pin.c
5 * PURPOSE: Implements cache managers pinning interface
8 Pierre Schweitzer (pierre@reactos.org)
11 /* INCLUDES ******************************************************************/
17 /* GLOBALS *******************************************************************/
19 extern NPAGED_LOOKASIDE_LIST iBcbLookasideList
;
22 * - Number of calls to CcMapData that could wait
23 * - Number of calls to CcMapData that couldn't wait
24 * - Number of calls to CcPinRead that could wait
25 * - Number of calls to CcPinRead that couldn't wait
27 ULONG CcMapDataWait
= 0;
28 ULONG CcMapDataNoWait
= 0;
29 ULONG CcPinReadWait
= 0;
30 ULONG CcPinReadNoWait
= 0;
32 /* FUNCTIONS *****************************************************************/
38 IN PROS_SHARED_CACHE_MAP SharedCacheMap
,
39 IN PLARGE_INTEGER FileOffset
,
53 ReadOffset
= FileOffset
->QuadPart
;
55 DPRINT("SectionSize %I64x, FileSize %I64x\n",
56 SharedCacheMap
->SectionSize
.QuadPart
,
57 SharedCacheMap
->FileSize
.QuadPart
);
59 if (ReadOffset
% VACB_MAPPING_GRANULARITY
+ Length
> VACB_MAPPING_GRANULARITY
)
61 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
62 SharedCacheMap
->FileObject
, FileOffset
, Length
, Flags
);
66 if (!BooleanFlagOn(Flags
, MAP_NO_READ
))
68 static int Warned
= 0;
70 SetFlag(Flags
, MAP_NO_READ
);
73 DPRINT1("Mapping/pinning with no read not implemented. Forcing read, might fail if wait not allowed\n");
78 ROffset
= ROUND_DOWN(ReadOffset
, VACB_MAPPING_GRANULARITY
);
79 Status
= CcRosRequestVacb(SharedCacheMap
,
84 if (!NT_SUCCESS(Status
))
86 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
87 SharedCacheMap
->FileObject
, FileOffset
, Length
, Flags
);
88 ExRaiseStatus(Status
);
92 if (!Valid
&& BooleanFlagOn(Flags
, MAP_NO_READ
))
94 if (!BooleanFlagOn(Flags
, MAP_WAIT
))
96 CcRosReleaseVacb(SharedCacheMap
, Vacb
, FALSE
, FALSE
, FALSE
);
97 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
98 SharedCacheMap
->FileObject
, FileOffset
, Length
, Flags
);
102 Status
= CcReadVirtualAddress(Vacb
);
103 if (!NT_SUCCESS(Status
))
105 CcRosReleaseVacb(SharedCacheMap
, Vacb
, FALSE
, FALSE
, FALSE
);
106 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
107 SharedCacheMap
->FileObject
, FileOffset
, Length
, Flags
);
108 ExRaiseStatus(Status
);
113 *pBuffer
= (PUCHAR
)*pBuffer
+ ReadOffset
% VACB_MAPPING_GRANULARITY
;
114 iBcb
= ExAllocateFromNPagedLookasideList(&iBcbLookasideList
);
117 CcRosReleaseVacb(SharedCacheMap
, Vacb
, TRUE
, FALSE
, FALSE
);
118 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
119 SharedCacheMap
->FileObject
, FileOffset
, Length
, Flags
);
120 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
124 RtlZeroMemory(iBcb
, sizeof(*iBcb
));
125 iBcb
->PFCB
.NodeTypeCode
= 0xDE45; /* Undocumented (CAPTIVE_PUBLIC_BCB_NODETYPECODE) */
126 iBcb
->PFCB
.NodeByteSize
= sizeof(PUBLIC_BCB
);
127 iBcb
->PFCB
.MappedLength
= Length
;
128 iBcb
->PFCB
.MappedFileOffset
= *FileOffset
;
133 ExInitializeResourceLite(&iBcb
->Lock
);
136 KeAcquireSpinLock(&SharedCacheMap
->BcbSpinLock
, &OldIrql
);
137 InsertTailList(&SharedCacheMap
->BcbList
, &iBcb
->BcbEntry
);
138 KeReleaseSpinLock(&SharedCacheMap
->BcbSpinLock
, OldIrql
);
147 IN PROS_SHARED_CACHE_MAP SharedCacheMap
,
148 IN PLARGE_INTEGER FileOffset
,
153 BOOLEAN Found
= FALSE
;
154 PLIST_ENTRY NextEntry
;
156 for (NextEntry
= SharedCacheMap
->BcbList
.Flink
;
157 NextEntry
!= &SharedCacheMap
->BcbList
;
158 NextEntry
= NextEntry
->Flink
)
160 Bcb
= CONTAINING_RECORD(NextEntry
, INTERNAL_BCB
, BcbEntry
);
162 if (Bcb
->PFCB
.MappedFileOffset
.QuadPart
<= FileOffset
->QuadPart
&&
163 (Bcb
->PFCB
.MappedFileOffset
.QuadPart
+ Bcb
->PFCB
.MappedLength
) >=
164 (FileOffset
->QuadPart
+ Length
))
166 if ((Pinned
&& Bcb
->PinCount
> 0) || (!Pinned
&& Bcb
->PinCount
== 0))
174 return (Found
? Bcb
: NULL
);
183 IN PFILE_OBJECT FileObject
,
184 IN PLARGE_INTEGER FileOffset
,
193 PROS_SHARED_CACHE_MAP SharedCacheMap
;
195 DPRINT("CcMapData(FileObject 0x%p, FileOffset %I64x, Length %lu, Flags 0x%lx,"
196 " pBcb 0x%p, pBuffer 0x%p)\n", FileObject
, FileOffset
->QuadPart
,
197 Length
, Flags
, pBcb
, pBuffer
);
200 ASSERT(FileObject
->SectionObjectPointer
);
201 ASSERT(FileObject
->SectionObjectPointer
->SharedCacheMap
);
203 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
204 ASSERT(SharedCacheMap
);
206 if (Flags
& MAP_WAIT
)
215 KeAcquireSpinLock(&SharedCacheMap
->BcbSpinLock
, &OldIrql
);
216 iBcb
= CcpFindBcb(SharedCacheMap
, FileOffset
, Length
, FALSE
);
217 KeReleaseSpinLock(&SharedCacheMap
->BcbSpinLock
, OldIrql
);
221 Ret
= CcpMapData(SharedCacheMap
, FileOffset
, Length
, Flags
, pBcb
, pBuffer
);
227 *pBuffer
= (PUCHAR
)iBcb
->Vacb
->BaseAddress
+ FileOffset
->QuadPart
% VACB_MAPPING_GRANULARITY
;
231 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> %d Bcb=%p\n",
232 FileObject
, FileOffset
, Length
, Flags
, Ret
, *pBcb
);
242 IN PFILE_OBJECT FileObject
,
243 IN PLARGE_INTEGER FileOffset
,
250 PROS_SHARED_CACHE_MAP SharedCacheMap
;
252 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
253 FileObject
, FileOffset
, Length
, Flags
);
256 ASSERT(FileObject
->SectionObjectPointer
);
257 ASSERT(FileObject
->SectionObjectPointer
->SharedCacheMap
);
259 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
260 ASSERT(SharedCacheMap
);
261 if (!SharedCacheMap
->PinAccess
)
263 DPRINT1("FIXME: Pinning a file with no pin access!\n");
268 ASSERT(iBcb
->PinCount
== 0);
272 if (BooleanFlagOn(Flags
, PIN_EXCLUSIVE
))
274 Result
= ExAcquireResourceExclusiveLite(&iBcb
->Lock
, BooleanFlagOn(Flags
, PIN_WAIT
));
278 Result
= ExAcquireSharedStarveExclusive(&iBcb
->Lock
, BooleanFlagOn(Flags
, PIN_WAIT
));
295 IN PFILE_OBJECT FileObject
,
296 IN PLARGE_INTEGER FileOffset
,
302 PROS_SHARED_CACHE_MAP SharedCacheMap
;
304 CCTRACE(CC_API_DEBUG
, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
305 FileObject
, FileOffset
, Length
, Flags
);
308 ASSERT(FileObject
->SectionObjectPointer
);
309 ASSERT(FileObject
->SectionObjectPointer
->SharedCacheMap
);
311 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
312 ASSERT(SharedCacheMap
);
314 if (Flags
& PIN_WAIT
)
324 if (!CcpMapData(SharedCacheMap
, FileOffset
, Length
, Flags
, Bcb
, Buffer
))
330 if (!CcPinMappedData(FileObject
, FileOffset
, Length
, Flags
, Bcb
))
345 IN PFILE_OBJECT FileObject
,
346 IN PLARGE_INTEGER FileOffset
,
353 CCTRACE(CC_API_DEBUG
, "FileOffset=%p FileOffset=%p Length=%lu Zero=%d Flags=0x%lx\n",
354 FileObject
, FileOffset
, Length
, Zero
, Flags
);
357 * FIXME: This is function is similar to CcPinRead, but doesn't
358 * read the data if they're not present. Instead it should just
359 * prepare the VACBs and zero them out if Zero != FALSE.
361 * For now calling CcPinRead is better than returning error or
362 * just having UNIMPLEMENTED here.
364 return CcPinRead(FileObject
, FileOffset
, Length
, Flags
, Bcb
, Buffer
);
371 CcSetDirtyPinnedData (
373 IN PLARGE_INTEGER Lsn
)
375 PINTERNAL_BCB iBcb
= Bcb
;
377 CCTRACE(CC_API_DEBUG
, "Bcb=%p Lsn=%p\n",
381 if (!iBcb
->Vacb
->Dirty
)
383 CcRosMarkDirtyVacb(iBcb
->Vacb
);
395 CCTRACE(CC_API_DEBUG
, "Bcb=%p\n", Bcb
);
397 CcUnpinDataForThread(Bcb
, (ERESOURCE_THREAD
)PsGetCurrentThread());
405 CcUnpinDataForThread (
407 IN ERESOURCE_THREAD ResourceThreadId
)
409 PINTERNAL_BCB iBcb
= Bcb
;
411 CCTRACE(CC_API_DEBUG
, "Bcb=%p ResourceThreadId=%lu\n", Bcb
, ResourceThreadId
);
413 if (iBcb
->PinCount
!= 0)
415 ExReleaseResourceForThreadLite(&iBcb
->Lock
, ResourceThreadId
);
419 if (--iBcb
->RefCount
== 0)
422 PROS_SHARED_CACHE_MAP SharedCacheMap
;
424 ASSERT(iBcb
->PinCount
== 0);
425 SharedCacheMap
= iBcb
->Vacb
->SharedCacheMap
;
426 CcRosReleaseVacb(SharedCacheMap
,
432 KeAcquireSpinLock(&SharedCacheMap
->BcbSpinLock
, &OldIrql
);
433 RemoveEntryList(&iBcb
->BcbEntry
);
434 KeReleaseSpinLock(&SharedCacheMap
->BcbSpinLock
, OldIrql
);
436 ExDeleteResourceLite(&iBcb
->Lock
);
437 ExFreeToNPagedLookasideList(&iBcbLookasideList
, iBcb
);
449 PINTERNAL_BCB iBcb
= Bcb
;
451 CCTRACE(CC_API_DEBUG
, "Bcb=%p\n", Bcb
);
463 IN BOOLEAN WriteThrough
,
464 IN PIO_STATUS_BLOCK IoStatus
)
466 PINTERNAL_BCB iBcb
= Bcb
;
468 PROS_SHARED_CACHE_MAP SharedCacheMap
;
470 CCTRACE(CC_API_DEBUG
, "Bcb=%p WriteThrough=%d\n", Bcb
, WriteThrough
);
472 IoStatus
->Status
= STATUS_SUCCESS
;
473 if (--iBcb
->RefCount
== 0)
475 IoStatus
->Information
= 0;
478 if (iBcb
->Vacb
->Dirty
)
480 IoStatus
->Status
= CcRosFlushVacb(iBcb
->Vacb
);
484 IoStatus
->Status
= STATUS_SUCCESS
;
489 IoStatus
->Status
= STATUS_SUCCESS
;
492 if (iBcb
->PinCount
!= 0)
494 ExReleaseResourceLite(&iBcb
->Lock
);
496 ASSERT(iBcb
->PinCount
== 0);
499 SharedCacheMap
= iBcb
->Vacb
->SharedCacheMap
;
500 CcRosReleaseVacb(iBcb
->Vacb
->SharedCacheMap
,
506 KeAcquireSpinLock(&SharedCacheMap
->BcbSpinLock
, &OldIrql
);
507 RemoveEntryList(&iBcb
->BcbEntry
);
508 KeReleaseSpinLock(&SharedCacheMap
->BcbSpinLock
, OldIrql
);
510 ExDeleteResourceLite(&iBcb
->Lock
);
511 ExFreeToNPagedLookasideList(&iBcbLookasideList
, iBcb
);