reactos/ntoskrnl/cc/pin.c
Art Yerkes c501d8112c Create a branch for network fixes.
svn path=/branches/aicom-network-fixes/; revision=34994
2008-08-01 11:32:26 +00:00

261 lines
5.5 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:
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS *******************************************************************/
extern NPAGED_LOOKASIDE_LIST iBcbLookasideList;
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
BOOLEAN STDCALL
CcMapData (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG Flags,
OUT PVOID *pBcb,
OUT PVOID *pBuffer)
{
ULONG ReadOffset;
BOOLEAN Valid;
PBCB Bcb;
PCACHE_SEGMENT CacheSeg;
NTSTATUS Status;
PINTERNAL_BCB iBcb;
ULONG ROffset;
DPRINT("CcMapData(FileObject 0x%p, FileOffset %I64x, Length %d, Flags %d,"
" pBcb 0x%p, pBuffer 0x%p)\n", FileObject, FileOffset->QuadPart,
Length, Flags, pBcb, pBuffer);
ReadOffset = (ULONG)FileOffset->QuadPart;
ASSERT(FileObject);
ASSERT(FileObject->SectionObjectPointer);
ASSERT(FileObject->SectionObjectPointer->SharedCacheMap);
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
ASSERT(Bcb);
DPRINT("AllocationSize %I64x, FileSize %I64x\n",
Bcb->AllocationSize.QuadPart,
Bcb->FileSize.QuadPart);
if (ReadOffset % Bcb->CacheSegmentSize + Length > Bcb->CacheSegmentSize)
{
return(FALSE);
}
ROffset = ROUND_DOWN (ReadOffset, Bcb->CacheSegmentSize);
Status = CcRosRequestCacheSegment(Bcb,
ROffset,
pBuffer,
&Valid,
&CacheSeg);
if (!NT_SUCCESS(Status))
{
return(FALSE);
}
if (!Valid)
{
if (!(Flags & MAP_WAIT))
{
CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
return(FALSE);
}
if (!NT_SUCCESS(ReadCacheSegment(CacheSeg)))
{
CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
return(FALSE);
}
}
*pBuffer = (PVOID)((ULONG_PTR)(*pBuffer) + (ReadOffset % Bcb->CacheSegmentSize));
iBcb = ExAllocateFromNPagedLookasideList(&iBcbLookasideList);
if (iBcb == NULL)
{
CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
return FALSE;
}
memset(iBcb, 0, sizeof(INTERNAL_BCB));
iBcb->PFCB.NodeTypeCode = 0xDE45; /* Undocumented (CAPTIVE_PUBLIC_BCB_NODETYPECODE) */
iBcb->PFCB.NodeByteSize = sizeof(PUBLIC_BCB);
iBcb->PFCB.MappedLength = Length;
iBcb->PFCB.MappedFileOffset = *FileOffset;
iBcb->CacheSegment = CacheSeg;
iBcb->Dirty = FALSE;
iBcb->RefCount = 1;
*pBcb = (PVOID)iBcb;
return(TRUE);
}
/*
* @unimplemented
*/
BOOLEAN
STDCALL
CcPinMappedData (
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG Flags,
OUT PVOID * Bcb
)
{
/* no-op for current implementation. */
return TRUE;
}
/*
* @unimplemented
*/
BOOLEAN
STDCALL
CcPinRead (
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG Flags,
OUT PVOID * Bcb,
OUT PVOID * Buffer
)
{
if (CcMapData(FileObject, FileOffset, Length, Flags, Bcb, Buffer))
{
if (CcPinMappedData(FileObject, FileOffset, Length, Flags, Bcb))
return TRUE;
else
CcUnpinData(Bcb);
}
return FALSE;
}
/*
* @unimplemented
*/
BOOLEAN
STDCALL
CcPreparePinWrite (
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Zero,
IN ULONG Flags,
OUT PVOID * Bcb,
OUT PVOID * Buffer
)
{
/*
* 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 cache segments and zero them out if Zero == TRUE.
*
* For now calling CcPinRead is better than returning error or
* just having UNIMPLEMENTED here.
*/
return CcPinRead(FileObject, FileOffset, Length, Flags, Bcb, Buffer);
}
/*
* @implemented
*/
VOID STDCALL
CcSetDirtyPinnedData (IN PVOID Bcb,
IN PLARGE_INTEGER Lsn)
{
PINTERNAL_BCB iBcb = Bcb;
iBcb->Dirty = TRUE;
}
/*
* @implemented
*/
VOID STDCALL
CcUnpinData (IN PVOID Bcb)
{
PINTERNAL_BCB iBcb = Bcb;
CcRosReleaseCacheSegment(iBcb->CacheSegment->Bcb, iBcb->CacheSegment, TRUE,
iBcb->Dirty, FALSE);
if (--iBcb->RefCount == 0)
{
ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
}
}
/*
* @unimplemented
*/
VOID
STDCALL
CcUnpinDataForThread (
IN PVOID Bcb,
IN ERESOURCE_THREAD ResourceThreadId
)
{
UNIMPLEMENTED;
}
/*
* @implemented
*/
VOID
STDCALL
CcRepinBcb (
IN PVOID Bcb
)
{
PINTERNAL_BCB iBcb = Bcb;
iBcb->RefCount++;
}
/*
* @unimplemented
*/
VOID
STDCALL
CcUnpinRepinnedBcb (
IN PVOID Bcb,
IN BOOLEAN WriteThrough,
IN PIO_STATUS_BLOCK IoStatus
)
{
PINTERNAL_BCB iBcb = Bcb;
if (--iBcb->RefCount == 0)
{
IoStatus->Information = 0;
if (WriteThrough)
{
ExAcquirePushLockExclusive(&iBcb->CacheSegment->Lock);
if (iBcb->CacheSegment->Dirty)
{
IoStatus->Status = CcRosFlushCacheSegment(iBcb->CacheSegment);
}
else
{
IoStatus->Status = STATUS_SUCCESS;
}
ExReleasePushLockExclusive(&iBcb->CacheSegment->Lock);
}
else
{
IoStatus->Status = STATUS_SUCCESS;
}
ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
}
}