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
,
44 BOOLEAN Found
= FALSE
;
45 PLIST_ENTRY NextEntry
;
47 for (NextEntry
= SharedCacheMap
->BcbList
.Flink
;
48 NextEntry
!= &SharedCacheMap
->BcbList
;
49 NextEntry
= NextEntry
->Flink
)
51 Bcb
= CONTAINING_RECORD(NextEntry
, INTERNAL_BCB
, BcbEntry
);
53 if (Bcb
->PFCB
.MappedFileOffset
.QuadPart
<= FileOffset
->QuadPart
&&
54 (Bcb
->PFCB
.MappedFileOffset
.QuadPart
+ Bcb
->PFCB
.MappedLength
) >=
55 (FileOffset
->QuadPart
+ Length
))
57 if ((Pinned
&& Bcb
->PinCount
> 0) || (!Pinned
&& Bcb
->PinCount
== 0))
65 return (Found
? Bcb
: NULL
);
72 IN PROS_SHARED_CACHE_MAP SharedCacheMap
,
73 IN PLARGE_INTEGER FileOffset
,
85 ReadOffset
= FileOffset
->QuadPart
;
87 DPRINT("SectionSize %I64x, FileSize %I64x\n",
88 SharedCacheMap
->SectionSize
.QuadPart
,
89 SharedCacheMap
->FileSize
.QuadPart
);
91 if (ReadOffset
% VACB_MAPPING_GRANULARITY
+ Length
> VACB_MAPPING_GRANULARITY
)
93 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
94 SharedCacheMap
->FileObject
, FileOffset
, Length
, Flags
);
98 if (!BooleanFlagOn(Flags
, MAP_NO_READ
))
100 static int Warned
= 0;
102 SetFlag(Flags
, MAP_NO_READ
);
105 DPRINT1("Mapping/pinning with no read not implemented. Forcing read, might fail if wait not allowed\n");
110 ROffset
= ROUND_DOWN(ReadOffset
, VACB_MAPPING_GRANULARITY
);
111 Status
= CcRosRequestVacb(SharedCacheMap
,
116 if (!NT_SUCCESS(Status
))
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
);
124 if (!Valid
&& BooleanFlagOn(Flags
, MAP_NO_READ
))
126 if (!BooleanFlagOn(Flags
, MAP_WAIT
))
128 CcRosReleaseVacb(SharedCacheMap
, Vacb
, FALSE
, FALSE
, FALSE
);
129 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
130 SharedCacheMap
->FileObject
, FileOffset
, Length
, Flags
);
134 Status
= CcReadVirtualAddress(Vacb
);
135 if (!NT_SUCCESS(Status
))
137 CcRosReleaseVacb(SharedCacheMap
, Vacb
, FALSE
, FALSE
, FALSE
);
138 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
139 SharedCacheMap
->FileObject
, FileOffset
, Length
, Flags
);
140 ExRaiseStatus(Status
);
145 *pBuffer
= (PUCHAR
)*pBuffer
+ ReadOffset
% VACB_MAPPING_GRANULARITY
;
153 CcpGetAppropriateBcb(
154 IN PROS_SHARED_CACHE_MAP SharedCacheMap
,
156 IN PLARGE_INTEGER FileOffset
,
163 PINTERNAL_BCB iBcb
, DupBcb
;
165 iBcb
= ExAllocateFromNPagedLookasideList(&iBcbLookasideList
);
168 CcRosReleaseVacb(SharedCacheMap
, Vacb
, TRUE
, FALSE
, FALSE
);
172 RtlZeroMemory(iBcb
, sizeof(*iBcb
));
173 iBcb
->PFCB
.NodeTypeCode
= 0xDE45; /* Undocumented (CAPTIVE_PUBLIC_BCB_NODETYPECODE) */
174 iBcb
->PFCB
.NodeByteSize
= sizeof(PUBLIC_BCB
);
175 iBcb
->PFCB
.MappedLength
= Length
;
176 iBcb
->PFCB
.MappedFileOffset
= *FileOffset
;
181 ExInitializeResourceLite(&iBcb
->Lock
);
183 KeAcquireSpinLock(&SharedCacheMap
->BcbSpinLock
, &OldIrql
);
185 /* Check if we raced with another BCB creation */
186 DupBcb
= CcpFindBcb(SharedCacheMap
, FileOffset
, Length
, ToPin
);
187 /* Yes, and we've lost */
196 if (BooleanFlagOn(PinFlags
, PIN_EXCLUSIVE
))
198 Result
= ExAcquireResourceExclusiveLite(&iBcb
->Lock
, BooleanFlagOn(PinFlags
, PIN_WAIT
));
202 Result
= ExAcquireSharedStarveExclusive(&iBcb
->Lock
, BooleanFlagOn(PinFlags
, PIN_WAIT
));
214 /* We'll return that BCB */
218 /* Delete the loser */
219 CcRosReleaseVacb(SharedCacheMap
, Vacb
, TRUE
, FALSE
, FALSE
);
220 ExDeleteResourceLite(&iBcb
->Lock
);
221 ExFreeToNPagedLookasideList(&iBcbLookasideList
, iBcb
);
223 /* Return the winner - no need to update buffer address, it's
224 * relative to the VACB, which is unchanged.
228 /* Nope, insert ourselves */
235 if (BooleanFlagOn(PinFlags
, PIN_EXCLUSIVE
))
237 Result
= ExAcquireResourceExclusiveLite(&iBcb
->Lock
, BooleanFlagOn(PinFlags
, PIN_WAIT
));
241 Result
= ExAcquireSharedStarveExclusive(&iBcb
->Lock
, BooleanFlagOn(PinFlags
, PIN_WAIT
));
247 InsertTailList(&SharedCacheMap
->BcbList
, &iBcb
->BcbEntry
);
249 KeReleaseSpinLock(&SharedCacheMap
->BcbSpinLock
, OldIrql
);
257 IN PROS_SHARED_CACHE_MAP SharedCacheMap
,
258 IN PLARGE_INTEGER FileOffset
,
264 PINTERNAL_BCB NewBcb
;
269 KeAcquireSpinLock(&SharedCacheMap
->BcbSpinLock
, &OldIrql
);
270 NewBcb
= CcpFindBcb(SharedCacheMap
, FileOffset
, Length
, TRUE
);
271 KeReleaseSpinLock(&SharedCacheMap
->BcbSpinLock
, OldIrql
);
277 if (BooleanFlagOn(Flags
, PIN_EXCLUSIVE
))
279 Result
= ExAcquireResourceExclusiveLite(&NewBcb
->Lock
, BooleanFlagOn(Flags
, PIN_WAIT
));
283 Result
= ExAcquireSharedStarveExclusive(&NewBcb
->Lock
, BooleanFlagOn(Flags
, PIN_WAIT
));
294 *Buffer
= (PUCHAR
)NewBcb
->Vacb
->BaseAddress
+ FileOffset
->QuadPart
% VACB_MAPPING_GRANULARITY
;
301 if (BooleanFlagOn(Flags
, PIN_IF_BCB
))
306 Result
= CcpMapData(SharedCacheMap
, FileOffset
, Length
, Flags
, &Vacb
, Buffer
);
309 NewBcb
= CcpGetAppropriateBcb(SharedCacheMap
, Vacb
, FileOffset
, Length
, Flags
, TRUE
);
312 CcRosReleaseVacb(SharedCacheMap
, Vacb
, TRUE
, FALSE
, FALSE
);
331 IN PFILE_OBJECT FileObject
,
332 IN PLARGE_INTEGER FileOffset
,
342 PROS_SHARED_CACHE_MAP SharedCacheMap
;
344 DPRINT("CcMapData(FileObject 0x%p, FileOffset %I64x, Length %lu, Flags 0x%lx,"
345 " pBcb 0x%p, pBuffer 0x%p)\n", FileObject
, FileOffset
->QuadPart
,
346 Length
, Flags
, pBcb
, pBuffer
);
349 ASSERT(FileObject
->SectionObjectPointer
);
350 ASSERT(FileObject
->SectionObjectPointer
->SharedCacheMap
);
352 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
353 ASSERT(SharedCacheMap
);
355 if (Flags
& MAP_WAIT
)
364 KeAcquireSpinLock(&SharedCacheMap
->BcbSpinLock
, &OldIrql
);
365 iBcb
= CcpFindBcb(SharedCacheMap
, FileOffset
, Length
, FALSE
);
366 KeReleaseSpinLock(&SharedCacheMap
->BcbSpinLock
, OldIrql
);
370 Ret
= CcpMapData(SharedCacheMap
, FileOffset
, Length
, Flags
, &Vacb
, pBuffer
);
373 iBcb
= CcpGetAppropriateBcb(SharedCacheMap
, Vacb
, FileOffset
, Length
, 0, FALSE
);
376 CcRosReleaseVacb(SharedCacheMap
, Vacb
, TRUE
, FALSE
, FALSE
);
389 *pBuffer
= (PUCHAR
)iBcb
->Vacb
->BaseAddress
+ FileOffset
->QuadPart
% VACB_MAPPING_GRANULARITY
;
393 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> %d Bcb=%p\n",
394 FileObject
, FileOffset
, Length
, Flags
, Ret
, *pBcb
);
404 IN PFILE_OBJECT FileObject
,
405 IN PLARGE_INTEGER FileOffset
,
413 PROS_SHARED_CACHE_MAP SharedCacheMap
;
415 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
416 FileObject
, FileOffset
, Length
, Flags
);
419 ASSERT(FileObject
->SectionObjectPointer
);
420 ASSERT(FileObject
->SectionObjectPointer
->SharedCacheMap
);
422 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
423 ASSERT(SharedCacheMap
);
424 if (!SharedCacheMap
->PinAccess
)
426 DPRINT1("FIXME: Pinning a file with no pin access!\n");
432 Result
= CcpPinData(SharedCacheMap
, FileOffset
, Length
, Flags
, Bcb
, &Buffer
);
447 IN PFILE_OBJECT FileObject
,
448 IN PLARGE_INTEGER FileOffset
,
454 PROS_SHARED_CACHE_MAP SharedCacheMap
;
456 CCTRACE(CC_API_DEBUG
, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
457 FileObject
, FileOffset
, Length
, Flags
);
460 ASSERT(FileObject
->SectionObjectPointer
);
461 ASSERT(FileObject
->SectionObjectPointer
->SharedCacheMap
);
463 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
464 ASSERT(SharedCacheMap
);
465 if (!SharedCacheMap
->PinAccess
)
467 DPRINT1("FIXME: Pinning a file with no pin access!\n");
471 if (Flags
& PIN_WAIT
)
480 return CcpPinData(SharedCacheMap
, FileOffset
, Length
, Flags
, Bcb
, Buffer
);
489 IN PFILE_OBJECT FileObject
,
490 IN PLARGE_INTEGER FileOffset
,
497 CCTRACE(CC_API_DEBUG
, "FileOffset=%p FileOffset=%p Length=%lu Zero=%d Flags=0x%lx\n",
498 FileObject
, FileOffset
, Length
, Zero
, Flags
);
501 * FIXME: This is function is similar to CcPinRead, but doesn't
502 * read the data if they're not present. Instead it should just
503 * prepare the VACBs and zero them out if Zero != FALSE.
505 * For now calling CcPinRead is better than returning error or
506 * just having UNIMPLEMENTED here.
508 return CcPinRead(FileObject
, FileOffset
, Length
, Flags
, Bcb
, Buffer
);
515 CcSetDirtyPinnedData (
517 IN PLARGE_INTEGER Lsn
)
519 PINTERNAL_BCB iBcb
= Bcb
;
521 CCTRACE(CC_API_DEBUG
, "Bcb=%p Lsn=%p\n",
525 if (!iBcb
->Vacb
->Dirty
)
527 CcRosMarkDirtyVacb(iBcb
->Vacb
);
539 CCTRACE(CC_API_DEBUG
, "Bcb=%p\n", Bcb
);
541 CcUnpinDataForThread(Bcb
, (ERESOURCE_THREAD
)PsGetCurrentThread());
549 CcUnpinDataForThread (
551 IN ERESOURCE_THREAD ResourceThreadId
)
553 PINTERNAL_BCB iBcb
= Bcb
;
555 CCTRACE(CC_API_DEBUG
, "Bcb=%p ResourceThreadId=%lu\n", Bcb
, ResourceThreadId
);
557 if (iBcb
->PinCount
!= 0)
559 ExReleaseResourceForThreadLite(&iBcb
->Lock
, ResourceThreadId
);
563 if (--iBcb
->RefCount
== 0)
566 PROS_SHARED_CACHE_MAP SharedCacheMap
;
568 ASSERT(iBcb
->PinCount
== 0);
569 SharedCacheMap
= iBcb
->Vacb
->SharedCacheMap
;
570 CcRosReleaseVacb(SharedCacheMap
,
576 KeAcquireSpinLock(&SharedCacheMap
->BcbSpinLock
, &OldIrql
);
577 if (!IsListEmpty(&iBcb
->BcbEntry
))
579 RemoveEntryList(&iBcb
->BcbEntry
);
581 KeReleaseSpinLock(&SharedCacheMap
->BcbSpinLock
, OldIrql
);
583 ExDeleteResourceLite(&iBcb
->Lock
);
584 ExFreeToNPagedLookasideList(&iBcbLookasideList
, iBcb
);
596 PINTERNAL_BCB iBcb
= Bcb
;
598 CCTRACE(CC_API_DEBUG
, "Bcb=%p\n", Bcb
);
610 IN BOOLEAN WriteThrough
,
611 IN PIO_STATUS_BLOCK IoStatus
)
613 PINTERNAL_BCB iBcb
= Bcb
;
615 PROS_SHARED_CACHE_MAP SharedCacheMap
;
617 CCTRACE(CC_API_DEBUG
, "Bcb=%p WriteThrough=%d\n", Bcb
, WriteThrough
);
619 IoStatus
->Status
= STATUS_SUCCESS
;
620 if (--iBcb
->RefCount
== 0)
622 IoStatus
->Information
= 0;
625 if (iBcb
->Vacb
->Dirty
)
627 IoStatus
->Status
= CcRosFlushVacb(iBcb
->Vacb
);
631 IoStatus
->Status
= STATUS_SUCCESS
;
636 IoStatus
->Status
= STATUS_SUCCESS
;
639 if (iBcb
->PinCount
!= 0)
641 ExReleaseResourceLite(&iBcb
->Lock
);
643 ASSERT(iBcb
->PinCount
== 0);
646 SharedCacheMap
= iBcb
->Vacb
->SharedCacheMap
;
647 CcRosReleaseVacb(iBcb
->Vacb
->SharedCacheMap
,
653 KeAcquireSpinLock(&SharedCacheMap
->BcbSpinLock
, &OldIrql
);
654 if (!IsListEmpty(&iBcb
->BcbEntry
))
656 RemoveEntryList(&iBcb
->BcbEntry
);
658 KeReleaseSpinLock(&SharedCacheMap
->BcbSpinLock
, OldIrql
);
660 ExDeleteResourceLite(&iBcb
->Lock
);
661 ExFreeToNPagedLookasideList(&iBcbLookasideList
, iBcb
);