mirror of
https://github.com/reactos/reactos.git
synced 2024-11-18 13:01:40 +00:00
ca74467904
Also add a check in fastfat, that asserts, when CcMapData returns FALSE.
672 lines
18 KiB
C
672 lines
18 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* FILE: ntoskrnl/cc/pin.c
|
|
* PURPOSE: Implements cache managers pinning interface
|
|
*
|
|
* PROGRAMMERS: ?
|
|
Pierre Schweitzer (pierre@reactos.org)
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <ntoskrnl.h>
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
extern NPAGED_LOOKASIDE_LIST iBcbLookasideList;
|
|
|
|
/* Counters:
|
|
* - Number of calls to CcMapData that could wait
|
|
* - Number of calls to CcMapData that couldn't wait
|
|
* - Number of calls to CcPinRead that could wait
|
|
* - Number of calls to CcPinRead that couldn't wait
|
|
* - Number of calls to CcPinMappedDataCount
|
|
*/
|
|
ULONG CcMapDataWait = 0;
|
|
ULONG CcMapDataNoWait = 0;
|
|
ULONG CcPinReadWait = 0;
|
|
ULONG CcPinReadNoWait = 0;
|
|
ULONG CcPinMappedDataCount = 0;
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
static
|
|
PINTERNAL_BCB
|
|
NTAPI
|
|
CcpFindBcb(
|
|
IN PROS_SHARED_CACHE_MAP SharedCacheMap,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Pinned)
|
|
{
|
|
PINTERNAL_BCB Bcb;
|
|
BOOLEAN Found = FALSE;
|
|
PLIST_ENTRY NextEntry;
|
|
|
|
for (NextEntry = SharedCacheMap->BcbList.Flink;
|
|
NextEntry != &SharedCacheMap->BcbList;
|
|
NextEntry = NextEntry->Flink)
|
|
{
|
|
Bcb = CONTAINING_RECORD(NextEntry, INTERNAL_BCB, BcbEntry);
|
|
|
|
if (Bcb->PFCB.MappedFileOffset.QuadPart <= FileOffset->QuadPart &&
|
|
(Bcb->PFCB.MappedFileOffset.QuadPart + Bcb->PFCB.MappedLength) >=
|
|
(FileOffset->QuadPart + Length))
|
|
{
|
|
if ((Pinned && Bcb->PinCount > 0) || (!Pinned && Bcb->PinCount == 0))
|
|
{
|
|
Found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (Found ? Bcb : NULL);
|
|
}
|
|
|
|
static
|
|
VOID
|
|
CcpDereferenceBcb(
|
|
IN PROS_SHARED_CACHE_MAP SharedCacheMap,
|
|
IN PINTERNAL_BCB Bcb)
|
|
{
|
|
ULONG RefCount;
|
|
KIRQL OldIrql;
|
|
|
|
KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql);
|
|
RefCount = --Bcb->RefCount;
|
|
if (RefCount == 0)
|
|
{
|
|
RemoveEntryList(&Bcb->BcbEntry);
|
|
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
|
|
|
ASSERT(Bcb->PinCount == 0);
|
|
/*
|
|
* Don't mark dirty, if it was dirty,
|
|
* the VACB was already marked as such
|
|
* following the call to CcSetDirtyPinnedData
|
|
*/
|
|
CcRosReleaseVacb(SharedCacheMap,
|
|
Bcb->Vacb,
|
|
FALSE,
|
|
FALSE);
|
|
|
|
ExDeleteResourceLite(&Bcb->Lock);
|
|
ExFreeToNPagedLookasideList(&iBcbLookasideList, Bcb);
|
|
}
|
|
else
|
|
{
|
|
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
|
}
|
|
}
|
|
|
|
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);
|
|
if (iBcb == NULL)
|
|
{
|
|
CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
RtlZeroMemory(iBcb, sizeof(*iBcb));
|
|
iBcb->PFCB.NodeTypeCode = 0x2FD; /* As per KMTests */
|
|
iBcb->PFCB.NodeByteSize = 0;
|
|
iBcb->PFCB.MappedLength = Length;
|
|
iBcb->PFCB.MappedFileOffset = *FileOffset;
|
|
iBcb->Vacb = Vacb;
|
|
iBcb->PinCount = 0;
|
|
iBcb->RefCount = 1;
|
|
ExInitializeResourceLite(&iBcb->Lock);
|
|
|
|
KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql);
|
|
|
|
/* Check if we raced with another BCB creation */
|
|
DupBcb = CcpFindBcb(SharedCacheMap, FileOffset, Length, ToPin);
|
|
/* Yes, and we've lost */
|
|
if (DupBcb != NULL)
|
|
{
|
|
/* We will return that BCB */
|
|
++DupBcb->RefCount;
|
|
Result = TRUE;
|
|
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
|
|
|
if (ToPin)
|
|
{
|
|
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++;
|
|
}
|
|
else
|
|
{
|
|
CcpDereferenceBcb(SharedCacheMap, DupBcb);
|
|
DupBcb = NULL;
|
|
}
|
|
}
|
|
|
|
if (DupBcb != NULL)
|
|
{
|
|
/* Delete the loser */
|
|
CcRosReleaseVacb(SharedCacheMap, Vacb, 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;
|
|
KIRQL OldIrql;
|
|
ULONG VacbOffset;
|
|
NTSTATUS Status;
|
|
BOOLEAN Result;
|
|
|
|
VacbOffset = (ULONG)(FileOffset->QuadPart % VACB_MAPPING_GRANULARITY);
|
|
|
|
if ((VacbOffset + Length) > VACB_MAPPING_GRANULARITY)
|
|
{
|
|
/* Complain loudly, we shoud pin the whole range */
|
|
DPRINT1("TRUNCATING DATA PIN FROM %lu to %lu!\n", Length, VACB_MAPPING_GRANULARITY - VacbOffset);
|
|
Length = VACB_MAPPING_GRANULARITY - VacbOffset;
|
|
}
|
|
|
|
KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql);
|
|
NewBcb = CcpFindBcb(SharedCacheMap, FileOffset, Length, TRUE);
|
|
|
|
if (NewBcb != NULL)
|
|
{
|
|
BOOLEAN Result;
|
|
|
|
++NewBcb->RefCount;
|
|
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
|
|
|
if (BooleanFlagOn(Flags, PIN_EXCLUSIVE))
|
|
Result = ExAcquireResourceExclusiveLite(&NewBcb->Lock, BooleanFlagOn(Flags, PIN_WAIT));
|
|
else
|
|
Result = ExAcquireSharedStarveExclusive(&NewBcb->Lock, BooleanFlagOn(Flags, PIN_WAIT));
|
|
|
|
if (!Result)
|
|
{
|
|
CcpDereferenceBcb(SharedCacheMap, NewBcb);
|
|
return FALSE;
|
|
}
|
|
|
|
NewBcb->PinCount++;
|
|
}
|
|
else
|
|
{
|
|
LONGLONG ROffset;
|
|
PROS_VACB Vacb;
|
|
|
|
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
|
|
|
if (BooleanFlagOn(Flags, PIN_IF_BCB))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Properly round offset and call internal helper for getting a VACB */
|
|
ROffset = ROUND_DOWN(FileOffset->QuadPart, VACB_MAPPING_GRANULARITY);
|
|
Status = CcRosGetVacb(SharedCacheMap, ROffset, &Vacb);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
|
|
SharedCacheMap->FileObject, FileOffset, Length, Flags);
|
|
ExRaiseStatus(Status);
|
|
return FALSE;
|
|
}
|
|
|
|
NewBcb = CcpGetAppropriateBcb(SharedCacheMap, Vacb, FileOffset, Length, Flags, TRUE);
|
|
if (NewBcb == NULL)
|
|
{
|
|
CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
Result = FALSE;
|
|
_SEH2_TRY
|
|
{
|
|
/* Ensure the pages are resident */
|
|
Result = CcRosEnsureVacbResident(NewBcb->Vacb,
|
|
BooleanFlagOn(Flags, PIN_WAIT),
|
|
BooleanFlagOn(Flags, PIN_NO_READ),
|
|
VacbOffset, Length);
|
|
}
|
|
_SEH2_FINALLY
|
|
{
|
|
if (!Result)
|
|
{
|
|
CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
|
|
SharedCacheMap->FileObject, FileOffset, Length, Flags);
|
|
CcUnpinData(&NewBcb->PFCB);
|
|
return FALSE;
|
|
}
|
|
}
|
|
_SEH2_END;
|
|
|
|
*Bcb = &NewBcb->PFCB;
|
|
*Buffer = (PVOID)((ULONG_PTR)NewBcb->Vacb->BaseAddress + VacbOffset);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOLEAN
|
|
NTAPI
|
|
CcMapData (
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG Flags,
|
|
OUT PVOID *pBcb,
|
|
OUT PVOID *pBuffer)
|
|
{
|
|
KIRQL OldIrql;
|
|
PINTERNAL_BCB iBcb;
|
|
PROS_VACB Vacb;
|
|
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
|
ULONG VacbOffset;
|
|
NTSTATUS Status;
|
|
BOOLEAN Result;
|
|
|
|
CCTRACE(CC_API_DEBUG, "CcMapData(FileObject 0x%p, FileOffset 0x%I64x, Length %lu, Flags 0x%lx,"
|
|
" pBcb 0x%p, pBuffer 0x%p)\n", FileObject, FileOffset->QuadPart,
|
|
Length, Flags, pBcb, pBuffer);
|
|
|
|
ASSERT(FileObject);
|
|
ASSERT(FileObject->SectionObjectPointer);
|
|
ASSERT(FileObject->SectionObjectPointer->SharedCacheMap);
|
|
|
|
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
|
|
ASSERT(SharedCacheMap);
|
|
|
|
if (Flags & MAP_WAIT)
|
|
{
|
|
++CcMapDataWait;
|
|
}
|
|
else
|
|
{
|
|
++CcMapDataNoWait;
|
|
}
|
|
|
|
VacbOffset = (ULONG)(FileOffset->QuadPart % VACB_MAPPING_GRANULARITY);
|
|
/* KMTests seem to show that it is allowed to call accross mapping granularity */
|
|
if ((VacbOffset + Length) > VACB_MAPPING_GRANULARITY)
|
|
{
|
|
DPRINT1("TRUNCATING DATA MAP FROM %lu to %lu!\n", Length, VACB_MAPPING_GRANULARITY - VacbOffset);
|
|
Length = VACB_MAPPING_GRANULARITY - VacbOffset;
|
|
}
|
|
|
|
KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql);
|
|
iBcb = CcpFindBcb(SharedCacheMap, FileOffset, Length, FALSE);
|
|
|
|
if (iBcb == NULL)
|
|
{
|
|
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
|
|
|
/* Call internal helper for getting a VACB */
|
|
Status = CcRosGetVacb(SharedCacheMap, FileOffset->QuadPart, &Vacb);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
|
|
SharedCacheMap->FileObject, FileOffset, Length, Flags);
|
|
ExRaiseStatus(Status);
|
|
}
|
|
|
|
iBcb = CcpGetAppropriateBcb(SharedCacheMap, Vacb, FileOffset, Length, 0, FALSE);
|
|
if (iBcb == NULL)
|
|
{
|
|
CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
|
|
CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
|
|
SharedCacheMap->FileObject, FileOffset, Length, Flags);
|
|
*pBcb = NULL; // If you ever remove this for compat, make sure to review all callers for using an unititialized value
|
|
ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
++iBcb->RefCount;
|
|
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
|
}
|
|
|
|
_SEH2_TRY
|
|
{
|
|
Result = FALSE;
|
|
/* Ensure the pages are resident */
|
|
Result = CcRosEnsureVacbResident(iBcb->Vacb, BooleanFlagOn(Flags, MAP_WAIT),
|
|
BooleanFlagOn(Flags, MAP_NO_READ), VacbOffset, Length);
|
|
}
|
|
_SEH2_FINALLY
|
|
{
|
|
if (!Result)
|
|
{
|
|
CcpDereferenceBcb(SharedCacheMap, iBcb);
|
|
return FALSE;
|
|
}
|
|
}
|
|
_SEH2_END;
|
|
|
|
*pBcb = &iBcb->PFCB;
|
|
*pBuffer = (PVOID)((ULONG_PTR)iBcb->Vacb->BaseAddress + VacbOffset);
|
|
|
|
CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> TRUE Bcb=%p, Buffer %p\n",
|
|
FileObject, FileOffset, Length, Flags, *pBcb, *pBuffer);
|
|
return Result;
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
BOOLEAN
|
|
NTAPI
|
|
CcPinMappedData (
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG Flags,
|
|
OUT PVOID * Bcb)
|
|
{
|
|
BOOLEAN Result;
|
|
PVOID Buffer;
|
|
PINTERNAL_BCB iBcb;
|
|
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
|
|
|
CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
|
|
FileObject, FileOffset, Length, Flags);
|
|
|
|
ASSERT(FileObject);
|
|
ASSERT(FileObject->SectionObjectPointer);
|
|
ASSERT(FileObject->SectionObjectPointer->SharedCacheMap);
|
|
|
|
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
|
|
ASSERT(SharedCacheMap);
|
|
if (!SharedCacheMap->PinAccess)
|
|
{
|
|
DPRINT1("FIXME: Pinning a file with no pin access!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
iBcb = *Bcb ? CONTAINING_RECORD(*Bcb, INTERNAL_BCB, PFCB) : NULL;
|
|
|
|
++CcPinMappedDataCount;
|
|
|
|
Result = CcpPinData(SharedCacheMap, FileOffset, Length, Flags, Bcb, &Buffer);
|
|
if (Result)
|
|
{
|
|
CcUnpinData(&iBcb->PFCB);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
BOOLEAN
|
|
NTAPI
|
|
CcPinRead (
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN ULONG Flags,
|
|
OUT PVOID * Bcb,
|
|
OUT PVOID * Buffer)
|
|
{
|
|
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
|
|
|
CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
|
|
FileObject, FileOffset, Length, Flags);
|
|
|
|
ASSERT(FileObject);
|
|
ASSERT(FileObject->SectionObjectPointer);
|
|
ASSERT(FileObject->SectionObjectPointer->SharedCacheMap);
|
|
|
|
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
|
|
ASSERT(SharedCacheMap);
|
|
if (!SharedCacheMap->PinAccess)
|
|
{
|
|
DPRINT1("FIXME: Pinning a file with no pin access!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (Flags & PIN_WAIT)
|
|
{
|
|
++CcPinReadWait;
|
|
}
|
|
else
|
|
{
|
|
++CcPinReadNoWait;
|
|
}
|
|
|
|
return CcpPinData(SharedCacheMap, FileOffset, Length, Flags, Bcb, Buffer);
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
BOOLEAN
|
|
NTAPI
|
|
CcPreparePinWrite (
|
|
IN PFILE_OBJECT FileObject,
|
|
IN PLARGE_INTEGER FileOffset,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Zero,
|
|
IN ULONG Flags,
|
|
OUT PVOID * Bcb,
|
|
OUT PVOID * Buffer)
|
|
{
|
|
CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Zero=%d Flags=0x%lx\n",
|
|
FileObject, FileOffset, Length, Zero, Flags);
|
|
|
|
/*
|
|
* FIXME: This is function is similar to CcPinRead, but doesn't
|
|
* read the data if they're not present. Instead it should just
|
|
* prepare the VACBs and zero them out if Zero != FALSE.
|
|
*
|
|
* For now calling CcPinRead is better than returning error or
|
|
* just having UNIMPLEMENTED here.
|
|
*/
|
|
return CcPinRead(FileObject, FileOffset, Length, Flags, Bcb, Buffer);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID NTAPI
|
|
CcSetDirtyPinnedData (
|
|
IN PVOID Bcb,
|
|
IN PLARGE_INTEGER Lsn)
|
|
{
|
|
PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB);
|
|
|
|
CCTRACE(CC_API_DEBUG, "Bcb=%p Lsn=%p\n", Bcb, Lsn);
|
|
|
|
/* Tell Mm */
|
|
MmMakePagesDirty(NULL,
|
|
Add2Ptr(iBcb->Vacb->BaseAddress, iBcb->PFCB.MappedFileOffset.QuadPart - iBcb->Vacb->FileOffset.QuadPart),
|
|
iBcb->PFCB.MappedLength);
|
|
|
|
if (!iBcb->Vacb->Dirty)
|
|
{
|
|
CcRosMarkDirtyVacb(iBcb->Vacb);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID NTAPI
|
|
CcUnpinData (
|
|
IN PVOID Bcb)
|
|
{
|
|
CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
|
|
|
|
CcUnpinDataForThread(Bcb, (ERESOURCE_THREAD)PsGetCurrentThread());
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
VOID
|
|
NTAPI
|
|
CcUnpinDataForThread (
|
|
IN PVOID Bcb,
|
|
IN ERESOURCE_THREAD ResourceThreadId)
|
|
{
|
|
PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB);
|
|
|
|
CCTRACE(CC_API_DEBUG, "Bcb=%p ResourceThreadId=%lu\n", Bcb, ResourceThreadId);
|
|
|
|
if (iBcb->PinCount != 0)
|
|
{
|
|
ExReleaseResourceForThreadLite(&iBcb->Lock, ResourceThreadId);
|
|
iBcb->PinCount--;
|
|
}
|
|
|
|
CcpDereferenceBcb(iBcb->Vacb->SharedCacheMap, iBcb);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID
|
|
NTAPI
|
|
CcRepinBcb (
|
|
IN PVOID Bcb)
|
|
{
|
|
PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB);
|
|
|
|
CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
|
|
|
|
iBcb->RefCount++;
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
VOID
|
|
NTAPI
|
|
CcUnpinRepinnedBcb (
|
|
IN PVOID Bcb,
|
|
IN BOOLEAN WriteThrough,
|
|
IN PIO_STATUS_BLOCK IoStatus)
|
|
{
|
|
PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB);
|
|
KIRQL OldIrql;
|
|
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
|
|
|
CCTRACE(CC_API_DEBUG, "Bcb=%p WriteThrough=%d\n", Bcb, WriteThrough);
|
|
|
|
SharedCacheMap = iBcb->Vacb->SharedCacheMap;
|
|
IoStatus->Status = STATUS_SUCCESS;
|
|
|
|
if (WriteThrough)
|
|
{
|
|
CcFlushCache(iBcb->Vacb->SharedCacheMap->FileObject->SectionObjectPointer,
|
|
&iBcb->PFCB.MappedFileOffset,
|
|
iBcb->PFCB.MappedLength,
|
|
IoStatus);
|
|
}
|
|
else
|
|
{
|
|
IoStatus->Status = STATUS_SUCCESS;
|
|
IoStatus->Information = 0;
|
|
}
|
|
|
|
KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql);
|
|
if (--iBcb->RefCount == 0)
|
|
{
|
|
RemoveEntryList(&iBcb->BcbEntry);
|
|
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
|
|
|
if (iBcb->PinCount != 0)
|
|
{
|
|
ExReleaseResourceLite(&iBcb->Lock);
|
|
iBcb->PinCount--;
|
|
ASSERT(iBcb->PinCount == 0);
|
|
}
|
|
|
|
/*
|
|
* Don't mark dirty, if it was dirty,
|
|
* the VACB was already marked as such
|
|
* following the call to CcSetDirtyPinnedData
|
|
*/
|
|
CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap,
|
|
iBcb->Vacb,
|
|
FALSE,
|
|
FALSE);
|
|
|
|
ExDeleteResourceLite(&iBcb->Lock);
|
|
ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
|
|
}
|
|
else
|
|
{
|
|
KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
|
|
}
|
|
}
|