mirror of
https://github.com/reactos/reactos.git
synced 2024-09-29 05:54:05 +00:00
[NTOSKRNL] Rewrite the way we create BCB for pinning
We won't reuse a BCB created for mapping, we will now have our own dedicated BCB. This allows having a bit more cleaner implementation of CcPinMappedData()
This commit is contained in:
parent
2d47c3be29
commit
1afcbbd125
|
@ -73,17 +73,14 @@ CcpMapData(
|
||||||
IN PLARGE_INTEGER FileOffset,
|
IN PLARGE_INTEGER FileOffset,
|
||||||
IN ULONG Length,
|
IN ULONG Length,
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
IN BOOLEAN ToPin,
|
OUT PROS_VACB *pVacb,
|
||||||
OUT PVOID *pBcb,
|
|
||||||
OUT PVOID *pBuffer)
|
OUT PVOID *pBuffer)
|
||||||
{
|
{
|
||||||
LONGLONG ReadOffset;
|
LONGLONG ReadOffset;
|
||||||
BOOLEAN Valid;
|
BOOLEAN Valid;
|
||||||
PROS_VACB Vacb;
|
PROS_VACB Vacb;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PINTERNAL_BCB iBcb, DupBcb;
|
|
||||||
LONGLONG ROffset;
|
LONGLONG ROffset;
|
||||||
KIRQL OldIrql;
|
|
||||||
|
|
||||||
ReadOffset = FileOffset->QuadPart;
|
ReadOffset = FileOffset->QuadPart;
|
||||||
|
|
||||||
|
@ -146,14 +143,30 @@ CcpMapData(
|
||||||
}
|
}
|
||||||
|
|
||||||
*pBuffer = (PUCHAR)*pBuffer + ReadOffset % VACB_MAPPING_GRANULARITY;
|
*pBuffer = (PUCHAR)*pBuffer + ReadOffset % VACB_MAPPING_GRANULARITY;
|
||||||
|
*pVacb = Vacb;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
PVOID
|
||||||
|
CcpGetAppropriateBcb(
|
||||||
|
IN PROS_SHARED_CACHE_MAP SharedCacheMap,
|
||||||
|
IN PROS_VACB Vacb,
|
||||||
|
IN PLARGE_INTEGER FileOffset,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN ULONG PinFlags,
|
||||||
|
IN BOOLEAN ToPin)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
BOOLEAN Result;
|
||||||
|
PINTERNAL_BCB iBcb, DupBcb;
|
||||||
|
|
||||||
iBcb = ExAllocateFromNPagedLookasideList(&iBcbLookasideList);
|
iBcb = ExAllocateFromNPagedLookasideList(&iBcbLookasideList);
|
||||||
if (iBcb == NULL)
|
if (iBcb == NULL)
|
||||||
{
|
{
|
||||||
CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
|
CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
|
||||||
CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
|
return NULL;
|
||||||
SharedCacheMap->FileObject, FileOffset, Length, Flags);
|
|
||||||
ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlZeroMemory(iBcb, sizeof(*iBcb));
|
RtlZeroMemory(iBcb, sizeof(*iBcb));
|
||||||
|
@ -166,44 +179,147 @@ CcpMapData(
|
||||||
iBcb->PinCount = 0;
|
iBcb->PinCount = 0;
|
||||||
iBcb->RefCount = 1;
|
iBcb->RefCount = 1;
|
||||||
ExInitializeResourceLite(&iBcb->Lock);
|
ExInitializeResourceLite(&iBcb->Lock);
|
||||||
*pBcb = (PVOID)iBcb;
|
|
||||||
|
|
||||||
/* Only insert if we're not to pin data */
|
KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql);
|
||||||
if (!ToPin)
|
|
||||||
|
/* Check if we raced with another BCB creation */
|
||||||
|
DupBcb = CcpFindBcb(SharedCacheMap, FileOffset, Length, ToPin);
|
||||||
|
/* Yes, and we've lost */
|
||||||
|
if (DupBcb != NULL)
|
||||||
{
|
{
|
||||||
KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql);
|
Result = TRUE;
|
||||||
|
|
||||||
/* Check if we raced with another BCB creation */
|
if (ToPin)
|
||||||
DupBcb = CcpFindBcb(SharedCacheMap, FileOffset, Length, FALSE);
|
{
|
||||||
/* Yes, and we've lost */
|
DupBcb->PinCount++;
|
||||||
if (DupBcb != NULL)
|
|
||||||
|
if (BooleanFlagOn(PinFlags, PIN_EXCLUSIVE))
|
||||||
|
{
|
||||||
|
Result = ExAcquireResourceExclusiveLite(&iBcb->Lock, BooleanFlagOn(PinFlags, PIN_WAIT));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Result = ExAcquireSharedStarveExclusive(&iBcb->Lock, BooleanFlagOn(PinFlags, PIN_WAIT));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Result)
|
||||||
|
{
|
||||||
|
DupBcb->PinCount--;
|
||||||
|
DupBcb = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Result)
|
||||||
{
|
{
|
||||||
/* We'll return that BCB */
|
/* We'll return that BCB */
|
||||||
++DupBcb->RefCount;
|
++DupBcb->RefCount;
|
||||||
|
|
||||||
/* Delete the loser */
|
|
||||||
CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
|
|
||||||
ExDeleteResourceLite(&iBcb->Lock);
|
|
||||||
ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
|
|
||||||
|
|
||||||
/* Return the winner - no need to update buffer address, it's
|
|
||||||
* relative to the VACB, which is unchanged.
|
|
||||||
*/
|
|
||||||
*pBcb = DupBcb;
|
|
||||||
}
|
}
|
||||||
/* Nope, insert ourselves */
|
|
||||||
|
/* Delete the loser */
|
||||||
|
CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
|
||||||
|
ExDeleteResourceLite(&iBcb->Lock);
|
||||||
|
ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
|
||||||
|
|
||||||
|
/* Return the winner - no need to update buffer address, it's
|
||||||
|
* relative to the VACB, which is unchanged.
|
||||||
|
*/
|
||||||
|
iBcb = DupBcb;
|
||||||
|
}
|
||||||
|
/* Nope, insert ourselves */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ToPin)
|
||||||
|
{
|
||||||
|
iBcb->PinCount++;
|
||||||
|
|
||||||
|
if (BooleanFlagOn(PinFlags, PIN_EXCLUSIVE))
|
||||||
|
{
|
||||||
|
Result = ExAcquireResourceExclusiveLite(&iBcb->Lock, BooleanFlagOn(PinFlags, PIN_WAIT));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Result = ExAcquireSharedStarveExclusive(&iBcb->Lock, BooleanFlagOn(PinFlags, PIN_WAIT));
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
InsertTailList(&SharedCacheMap->BcbList, &iBcb->BcbEntry);
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
||||||
|
|
||||||
|
return iBcb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
BOOLEAN
|
||||||
|
CcpPinData(
|
||||||
|
IN PROS_SHARED_CACHE_MAP SharedCacheMap,
|
||||||
|
IN PLARGE_INTEGER FileOffset,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN ULONG Flags,
|
||||||
|
OUT PVOID * Bcb,
|
||||||
|
OUT PVOID * Buffer)
|
||||||
|
{
|
||||||
|
PINTERNAL_BCB NewBcb;
|
||||||
|
BOOLEAN Result;
|
||||||
|
PROS_VACB Vacb;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql);
|
||||||
|
NewBcb = CcpFindBcb(SharedCacheMap, FileOffset, Length, TRUE);
|
||||||
|
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
||||||
|
|
||||||
|
if (NewBcb != NULL)
|
||||||
|
{
|
||||||
|
NewBcb->PinCount++;
|
||||||
|
|
||||||
|
if (BooleanFlagOn(Flags, PIN_EXCLUSIVE))
|
||||||
|
{
|
||||||
|
Result = ExAcquireResourceExclusiveLite(&NewBcb->Lock, BooleanFlagOn(Flags, PIN_WAIT));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
InsertTailList(&SharedCacheMap->BcbList, &iBcb->BcbEntry);
|
Result = ExAcquireSharedStarveExclusive(&NewBcb->Lock, BooleanFlagOn(Flags, PIN_WAIT));
|
||||||
}
|
}
|
||||||
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
|
||||||
|
if (!Result)
|
||||||
|
{
|
||||||
|
NewBcb->PinCount--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NewBcb->RefCount++;
|
||||||
|
*Bcb = NewBcb;
|
||||||
|
*Buffer = (PUCHAR)NewBcb->Vacb->BaseAddress + FileOffset->QuadPart % VACB_MAPPING_GRANULARITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
InitializeListHead(&iBcb->BcbEntry);
|
if (BooleanFlagOn(Flags, PIN_IF_BCB))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = CcpMapData(SharedCacheMap, FileOffset, Length, Flags, &Vacb, Buffer);
|
||||||
|
if (Result)
|
||||||
|
{
|
||||||
|
NewBcb = CcpGetAppropriateBcb(SharedCacheMap, Vacb, FileOffset, Length, Flags, TRUE);
|
||||||
|
if (NewBcb == NULL)
|
||||||
|
{
|
||||||
|
CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
|
||||||
|
Result = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*Bcb = NewBcb;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -222,6 +338,7 @@ CcMapData (
|
||||||
BOOLEAN Ret;
|
BOOLEAN Ret;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PINTERNAL_BCB iBcb;
|
PINTERNAL_BCB iBcb;
|
||||||
|
PROS_VACB Vacb;
|
||||||
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
||||||
|
|
||||||
DPRINT("CcMapData(FileObject 0x%p, FileOffset %I64x, Length %lu, Flags 0x%lx,"
|
DPRINT("CcMapData(FileObject 0x%p, FileOffset %I64x, Length %lu, Flags 0x%lx,"
|
||||||
|
@ -250,7 +367,20 @@ CcMapData (
|
||||||
|
|
||||||
if (iBcb == NULL)
|
if (iBcb == NULL)
|
||||||
{
|
{
|
||||||
Ret = CcpMapData(SharedCacheMap, FileOffset, Length, Flags, FALSE, pBcb, pBuffer);
|
Ret = CcpMapData(SharedCacheMap, FileOffset, Length, Flags, &Vacb, pBuffer);
|
||||||
|
if (Ret)
|
||||||
|
{
|
||||||
|
iBcb = CcpGetAppropriateBcb(SharedCacheMap, Vacb, FileOffset, Length, 0, FALSE);
|
||||||
|
if (iBcb == NULL)
|
||||||
|
{
|
||||||
|
CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
|
||||||
|
Ret = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*pBcb = iBcb;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -278,6 +408,7 @@ CcPinMappedData (
|
||||||
OUT PVOID * Bcb)
|
OUT PVOID * Bcb)
|
||||||
{
|
{
|
||||||
BOOLEAN Result;
|
BOOLEAN Result;
|
||||||
|
PVOID Buffer;
|
||||||
PINTERNAL_BCB iBcb;
|
PINTERNAL_BCB iBcb;
|
||||||
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
||||||
|
|
||||||
|
@ -297,22 +428,11 @@ CcPinMappedData (
|
||||||
}
|
}
|
||||||
|
|
||||||
iBcb = *Bcb;
|
iBcb = *Bcb;
|
||||||
ASSERT(iBcb->PinCount == 0);
|
|
||||||
|
|
||||||
iBcb->PinCount++;
|
Result = CcpPinData(SharedCacheMap, FileOffset, Length, Flags, Bcb, &Buffer);
|
||||||
|
if (Result)
|
||||||
if (BooleanFlagOn(Flags, PIN_EXCLUSIVE))
|
|
||||||
{
|
{
|
||||||
Result = ExAcquireResourceExclusiveLite(&iBcb->Lock, BooleanFlagOn(Flags, PIN_WAIT));
|
CcUnpinData(iBcb);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Result = ExAcquireSharedStarveExclusive(&iBcb->Lock, BooleanFlagOn(Flags, PIN_WAIT));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Result)
|
|
||||||
{
|
|
||||||
iBcb->PinCount--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -331,9 +451,6 @@ CcPinRead (
|
||||||
OUT PVOID * Bcb,
|
OUT PVOID * Bcb,
|
||||||
OUT PVOID * Buffer)
|
OUT PVOID * Buffer)
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
|
||||||
BOOLEAN Result;
|
|
||||||
PINTERNAL_BCB iBcb;
|
|
||||||
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
||||||
|
|
||||||
CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
|
CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
|
||||||
|
@ -345,6 +462,11 @@ CcPinRead (
|
||||||
|
|
||||||
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
|
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
|
||||||
ASSERT(SharedCacheMap);
|
ASSERT(SharedCacheMap);
|
||||||
|
if (!SharedCacheMap->PinAccess)
|
||||||
|
{
|
||||||
|
DPRINT1("FIXME: Pinning a file with no pin access!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (Flags & PIN_WAIT)
|
if (Flags & PIN_WAIT)
|
||||||
{
|
{
|
||||||
|
@ -355,95 +477,7 @@ CcPinRead (
|
||||||
++CcPinReadNoWait;
|
++CcPinReadNoWait;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql);
|
return CcpPinData(SharedCacheMap, FileOffset, Length, Flags, Bcb, Buffer);
|
||||||
iBcb = CcpFindBcb(SharedCacheMap, FileOffset, Length, TRUE);
|
|
||||||
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
|
||||||
|
|
||||||
if (iBcb == NULL)
|
|
||||||
{
|
|
||||||
/* We failed to find an already existing BCB */
|
|
||||||
if (BooleanFlagOn(Flags, PIN_IF_BCB))
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Map first */
|
|
||||||
if (!CcpMapData(SharedCacheMap, FileOffset, Length, Flags, TRUE, Bcb, Buffer))
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pin then */
|
|
||||||
if (!CcPinMappedData(FileObject, FileOffset, Length, Flags, Bcb))
|
|
||||||
{
|
|
||||||
CcUnpinData(*Bcb);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Did we race for the BCB creation? */
|
|
||||||
KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql);
|
|
||||||
iBcb = CcpFindBcb(SharedCacheMap, FileOffset, Length, TRUE);
|
|
||||||
if (iBcb != NULL)
|
|
||||||
{
|
|
||||||
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
|
||||||
|
|
||||||
/* Free our now unused BCB */
|
|
||||||
CcUnpinData(*Bcb);
|
|
||||||
|
|
||||||
/* Lock the found BCB and return it */
|
|
||||||
if (BooleanFlagOn(Flags, PIN_EXCLUSIVE))
|
|
||||||
{
|
|
||||||
Result = ExAcquireResourceExclusiveLite(&iBcb->Lock, BooleanFlagOn(Flags, PIN_WAIT));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Result = ExAcquireSharedStarveExclusive(&iBcb->Lock, BooleanFlagOn(Flags, PIN_WAIT));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Result)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
++iBcb->PinCount;
|
|
||||||
++iBcb->RefCount;
|
|
||||||
|
|
||||||
*Bcb = iBcb;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iBcb = *Bcb;
|
|
||||||
|
|
||||||
/* Insert ourselves in the linked list */
|
|
||||||
InsertTailList(&SharedCacheMap->BcbList, &iBcb->BcbEntry);
|
|
||||||
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* We found a BCB, lock it and return it */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (BooleanFlagOn(Flags, PIN_EXCLUSIVE))
|
|
||||||
{
|
|
||||||
Result = ExAcquireResourceExclusiveLite(&iBcb->Lock, BooleanFlagOn(Flags, PIN_WAIT));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Result = ExAcquireSharedStarveExclusive(&iBcb->Lock, BooleanFlagOn(Flags, PIN_WAIT));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Result)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
++iBcb->PinCount;
|
|
||||||
++iBcb->RefCount;
|
|
||||||
|
|
||||||
*Bcb = iBcb;
|
|
||||||
*Buffer = (PUCHAR)iBcb->Vacb->BaseAddress + FileOffset->QuadPart % VACB_MAPPING_GRANULARITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue