- Read all blocks at once for misaligned read.

svn path=/trunk/; revision=54273
This commit is contained in:
Jérôme Gardou 2011-10-30 00:58:21 +00:00
parent f39c8938c3
commit bfc68fc3a1

View file

@ -55,6 +55,7 @@ CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
{
NTSTATUS Status = STATUS_SUCCESS;
PFCB Fcb;
ULONG ToRead = Length;
DPRINT("CdfsReadFile(ReadOffset %lu Length %lu)\n", ReadOffset, Length);
@ -67,6 +68,9 @@ CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
if (ReadOffset >= Fcb->Entry.DataLengthL)
return(STATUS_END_OF_FILE);
if (ReadOffset + Length > Fcb->Entry.DataLengthL)
ToRead = Fcb->Entry.DataLengthL - ReadOffset;
DPRINT("Reading %d bytes at %d\n", Length, ReadOffset);
@ -78,9 +82,6 @@ CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
DPRINT("Using cache\n");
if (ReadOffset + Length > Fcb->Entry.DataLengthL)
Length = Fcb->Entry.DataLengthL - ReadOffset;
if (FileObject->PrivateCacheMap == NULL)
{
FileSizes.AllocationSize = Fcb->RFCB.AllocationSize;
@ -101,79 +102,56 @@ CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
FileOffset.QuadPart = (LONGLONG)ReadOffset;
CcCopyRead(FileObject,
&FileOffset,
Length,
ToRead,
TRUE,
Buffer,
&IoStatus);
*LengthRead = IoStatus.Information;
return(IoStatus.Status);
}
if ((ReadOffset % BLOCKSIZE) != 0 || (Length % BLOCKSIZE) != 0)
{
/* Then we need to do a partial or misaligned read ... */
PCHAR PageBuf = ExAllocatePool(NonPagedPool, BLOCKSIZE);
PCHAR TargetRead = (PCHAR)Buffer;
ULONG ActualReadOffset, EndOfExtent, ReadLen;
if (!PageBuf)
{
return STATUS_NO_MEMORY;
}
ActualReadOffset = ROUND_DOWN(ReadOffset, BLOCKSIZE);
EndOfExtent = ReadOffset + Length;
while (ActualReadOffset < EndOfExtent)
{
Status = CdfsReadSectors
(DeviceExt->StorageDevice,
Fcb->Entry.ExtentLocationL + (ActualReadOffset / BLOCKSIZE),
1,
(PVOID)PageBuf,
FALSE);
if (!NT_SUCCESS(Status))
break;
ReadLen = BLOCKSIZE - (ReadOffset - ActualReadOffset);
if (ReadLen > EndOfExtent - ReadOffset)
{
ReadLen = EndOfExtent - ReadOffset;
}
DPRINT("Copying %d bytes.\n", ReadLen);
RtlCopyMemory(TargetRead, PageBuf + (ReadOffset - ActualReadOffset), ReadLen);
ActualReadOffset += BLOCKSIZE;
TargetRead += ReadLen;
ReadOffset += ReadLen;
}
ExFreePool(PageBuf);
Status = IoStatus.Status;
}
else
{
if (ReadOffset + Length > ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE))
Length = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE) - ReadOffset;
Status = CdfsReadSectors(DeviceExt->StorageDevice,
Fcb->Entry.ExtentLocationL + (ReadOffset / BLOCKSIZE),
Length / BLOCKSIZE,
Buffer,
FALSE);
if (NT_SUCCESS(Status))
ULONG ActualReadOffset = ROUND_DOWN(ReadOffset, BLOCKSIZE);
ULONG nBlocks = (ROUND_UP(ReadOffset + ToRead, BLOCKSIZE) - ActualReadOffset) / BLOCKSIZE;
PUCHAR PageBuf;
BOOLEAN bFreeBuffer = FALSE;
if ((ReadOffset % BLOCKSIZE) != 0 || (ToRead % BLOCKSIZE) != 0)
{
*LengthRead = Length;
if (Length + ReadOffset > Fcb->Entry.DataLengthL)
PageBuf = ExAllocatePool(NonPagedPool, nBlocks * BLOCKSIZE);
if (!PageBuf)
{
memset(Buffer + Fcb->Entry.DataLengthL - ReadOffset,
0,
Length + ReadOffset - Fcb->Entry.DataLengthL);
return STATUS_NO_MEMORY;
}
bFreeBuffer = TRUE;
}
else
{
PageBuf = Buffer;
}
Status = CdfsReadSectors(DeviceExt->StorageDevice,
Fcb->Entry.ExtentLocationL + (ActualReadOffset / BLOCKSIZE),
nBlocks,
(PVOID)PageBuf,
FALSE);
if(NT_SUCCESS(Status))
{
*LengthRead = ToRead;
if(bFreeBuffer)
{
/* Copy what we've got */
RtlCopyMemory(Buffer, PageBuf + (ReadOffset - ActualReadOffset), ToRead);
}
/* Zero out the rest */
if(ToRead != Length)
RtlZeroMemory(Buffer + ToRead, Length - ToRead);
}
if(bFreeBuffer)
ExFreePool(PageBuf);
}
return Status;
}