From c7c367ccc82d107576d9215ed8e32b7b3985e0fe Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Fri, 4 Mar 2016 17:08:46 -0800 Subject: [PATCH] sys: IRP_MJ_READ: implementation --- src/sys/driver.h | 5 ++ src/sys/read.c | 162 +++++++++++++++++++++++++++++++++++++++++++++-- src/sys/util.c | 83 ++++++++++++++++++++++++ src/sys/write.c | 6 +- 4 files changed, 249 insertions(+), 7 deletions(-) diff --git a/src/sys/driver.h b/src/sys/driver.h index 8e6dbed1..ff95e529 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -380,8 +380,13 @@ NTSTATUS FspMapLockedPagesInUserMode(PMDL Mdl, PVOID *PAddress); NTSTATUS FspCcInitializeCacheMap(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes, BOOLEAN PinAccess, PCACHE_MANAGER_CALLBACKS Callbacks, PVOID CallbackContext); NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes); +NTSTATUS FspCcCopyRead(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, + BOOLEAN Wait, PVOID Buffer, PIO_STATUS_BLOCK IoStatus); NTSTATUS FspCcCopyWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, PVOID Buffer); +NTSTATUS FspCcMdlRead(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, + PMDL *PMdlChain, PIO_STATUS_BLOCK IoStatus); +NTSTATUS FspCcMdlReadComplete(PFILE_OBJECT FileObject, PMDL MdlChain); NTSTATUS FspCcPrepareMdlWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, PMDL *PMdlChain, PIO_STATUS_BLOCK IoStatus); NTSTATUS FspCcMdlWriteComplete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PMDL MdlChain); diff --git a/src/sys/read.c b/src/sys/read.c index 6a23d242..e3662a32 100644 --- a/src/sys/read.c +++ b/src/sys/read.c @@ -7,18 +7,160 @@ #include static NTSTATUS FspFsvolRead( - PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); + PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); +static NTSTATUS FspFsvolReadCached( + PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, + BOOLEAN CanWait); +static NTSTATUS FspFsvolReadNonCached( + PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); FSP_IOCMPL_DISPATCH FspFsvolReadComplete; +static FSP_IOP_REQUEST_FINI FspFsvolReadNonCachedRequestFini; FSP_DRIVER_DISPATCH FspRead; #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, FspFsvolRead) +#pragma alloc_text(PAGE, FspFsvolReadCached) +#pragma alloc_text(PAGE, FspFsvolReadNonCached) #pragma alloc_text(PAGE, FspFsvolReadComplete) +#pragma alloc_text(PAGE, FspFsvolReadNonCachedRequestFini) #pragma alloc_text(PAGE, FspRead) #endif static NTSTATUS FspFsvolRead( - PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) + PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) +{ + PAGED_CODE(); + + /* is this a valid FileObject? */ + if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext)) + return STATUS_INVALID_DEVICE_REQUEST; + + NTSTATUS Result; + PFILE_OBJECT FileObject = IrpSp->FileObject; + FSP_FILE_NODE *FileNode = FileObject->FsContext; + + /* is this an MDL complete request? */ + if (FlagOn(IrpSp->MinorFunction, IRP_MN_COMPLETE)) + { + Result = FspCcMdlReadComplete(FileObject, Irp->MdlAddress); + Irp->MdlAddress = 0; + return Result; + } + + /* only regular files can be read */ + if (FileNode->IsDirectory) + return STATUS_INVALID_PARAMETER; + + /* do we have anything to read? */ + if (0 == IrpSp->Parameters.Read.Length) + { + Irp->IoStatus.Information = 0; + return STATUS_SUCCESS; + } + + /* are we doing cached or non-cached I/O? */ + if (FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) && + !FlagOn(Irp->Flags, IRP_PAGING_IO | IRP_NOCACHE)) + Result = FspFsvolReadCached(FsvolDeviceObject, Irp, IrpSp, IoIsOperationSynchronous(Irp)); + else + Result = FspFsvolReadNonCached(FsvolDeviceObject, Irp, IrpSp); + + return Result; +} + +static NTSTATUS FspFsvolReadCached( + PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, + BOOLEAN CanWait) +{ + PAGED_CODE(); + + NTSTATUS Result; + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); + PFILE_OBJECT FileObject = IrpSp->FileObject; + FSP_FILE_NODE *FileNode = FileObject->FsContext; + FSP_FILE_DESC *FileDesc = FileObject->FsContext2; + LARGE_INTEGER ReadOffset = IrpSp->Parameters.Read.ByteOffset; + ULONG ReadLength = IrpSp->Parameters.Read.Length; +#if 0 + /* !!!: lock support! */ + ULONG ReadKey = IrpSp->Parameters.Read.Key; +#endif + BOOLEAN SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); + FSP_FSCTL_FILE_INFO FileInfo; + CC_FILE_SIZES FileSizes; + BOOLEAN Success; + + ASSERT(FileNode == FileDesc->FileNode); + + /* try to acquire the FileNode Main shared */ + Success = DEBUGTEST(90, TRUE) && + FspFileNodeTryAcquireSharedF(FileNode, FspFileNodeAcquireMain, CanWait); + if (!Success) + return FspWqRepostIrpWorkItem(Irp, FspFsvolReadCached, 0); + + /* initialize cache if not already initialized! */ + if (0 == FileObject->PrivateCacheMap) + { + ASSERT(FspTimeoutInfinity32 == FsvolDeviceExtension->VolumeParams.FileInfoTimeout); + FspFileNodeGetFileInfo(FileNode, &FileInfo); + FileSizes.AllocationSize.QuadPart = FileInfo.AllocationSize; + FileSizes.FileSize.QuadPart = FileInfo.FileSize; + FileSizes.ValidDataLength.QuadPart = MAXLONGLONG; + + Result = FspCcInitializeCacheMap(FileObject, &FileSizes, FALSE, + &FspCacheManagerCallbacks, FileNode); + if (!NT_SUCCESS(Result)) + { + FspFileNodeRelease(FileNode, Main); + return Result; + } + } + + /* are we using the copy or MDL interface? */ + if (!FlagOn(IrpSp->MinorFunction, IRP_MN_MDL)) + { + PVOID Buffer; + + Buffer = 0 == Irp->MdlAddress ? + Irp->UserBuffer : MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); + if (0 == Buffer) + { + FspFileNodeRelease(FileNode, Main); + return STATUS_INSUFFICIENT_RESOURCES; + } + + Result = FspCcCopyRead(FileObject, &ReadOffset, ReadLength, CanWait, Buffer, + &Irp->IoStatus); + if (STATUS_PENDING == Result) + { + FspFileNodeRelease(FileNode, Main); + return FspWqRepostIrpWorkItem(Irp, FspFsvolReadCached, 0); + } + } + else + { + ASSERT(0 == Irp->MdlAddress); + + Result = FspCcMdlRead(FileObject, &ReadOffset, ReadLength, &Irp->MdlAddress, + &Irp->IoStatus); + if (!NT_SUCCESS(Result)) + { + FspFileNodeRelease(FileNode, Main); + return Result; + } + } + + /* update the current file offset if synchronous I/O */ + if (SynchronousIo) + FileObject->CurrentByteOffset.QuadPart = ReadOffset.QuadPart + Irp->IoStatus.Information; + + FspFileNodeRelease(FileNode, Main); + + return STATUS_SUCCESS; +} + +static NTSTATUS FspFsvolReadNonCached( + PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { PAGED_CODE(); @@ -30,7 +172,13 @@ NTSTATUS FspFsvolReadComplete( { FSP_ENTER_IOC(PAGED_CODE()); - FSP_LEAVE_IOC("%s", ""); + FSP_LEAVE_IOC( + "FileObject=%p, UserBuffer=%p, MdlAddress=%p, " + "Key=%#lx, ByteOffset=%#lx:%#lx, Length=%ld", + IrpSp->FileObject, Irp->UserBuffer, Irp->MdlAddress, + IrpSp->Parameters.Read.Key, + IrpSp->Parameters.Read.ByteOffset.HighPart, IrpSp->Parameters.Read.ByteOffset.LowPart, + IrpSp->Parameters.Read.Length); } NTSTATUS FspRead( @@ -46,5 +194,11 @@ NTSTATUS FspRead( FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST); } - FSP_LEAVE_MJ("%s", ""); + FSP_LEAVE_MJ( + "FileObject=%p, UserBuffer=%p, MdlAddress=%p, " + "Key=%#lx, ByteOffset=%#lx:%#lx, Length=%ld", + IrpSp->FileObject, Irp->UserBuffer, Irp->MdlAddress, + IrpSp->Parameters.Read.Key, + IrpSp->Parameters.Read.ByteOffset.HighPart, IrpSp->Parameters.Read.ByteOffset.LowPart, + IrpSp->Parameters.Read.Length); } diff --git a/src/sys/util.c b/src/sys/util.c index c850f679..167a8c17 100644 --- a/src/sys/util.c +++ b/src/sys/util.c @@ -15,8 +15,13 @@ NTSTATUS FspMapLockedPagesInUserMode(PMDL Mdl, PVOID *PAddress); NTSTATUS FspCcInitializeCacheMap(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes, BOOLEAN PinAccess, PCACHE_MANAGER_CALLBACKS Callbacks, PVOID CallbackContext); NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes); +NTSTATUS FspCcCopyRead(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, + BOOLEAN Wait, PVOID Buffer, PIO_STATUS_BLOCK IoStatus); NTSTATUS FspCcCopyWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, PVOID Buffer); +NTSTATUS FspCcMdlRead(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, + PMDL *PMdlChain, PIO_STATUS_BLOCK IoStatus); +NTSTATUS FspCcMdlReadComplete(PFILE_OBJECT FileObject, PMDL MdlChain); NTSTATUS FspCcPrepareMdlWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, PMDL *PMdlChain, PIO_STATUS_BLOCK IoStatus); NTSTATUS FspCcMdlWriteComplete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PMDL MdlChain); @@ -44,7 +49,10 @@ VOID FspSafeMdlDelete(FSP_SAFE_MDL *SafeMdl); #pragma alloc_text(PAGE, FspMapLockedPagesInUserMode) #pragma alloc_text(PAGE, FspCcInitializeCacheMap) #pragma alloc_text(PAGE, FspCcSetFileSizes) +#pragma alloc_text(PAGE, FspCcCopyRead) #pragma alloc_text(PAGE, FspCcCopyWrite) +#pragma alloc_text(PAGE, FspCcMdlRead) +#pragma alloc_text(PAGE, FspCcMdlReadComplete) #pragma alloc_text(PAGE, FspCcPrepareMdlWrite) #pragma alloc_text(PAGE, FspCcMdlWriteComplete) #pragma alloc_text(PAGE, FspQuerySecurityDescriptorInfo) @@ -249,6 +257,32 @@ NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes) } } +NTSTATUS FspCcCopyRead(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, + BOOLEAN Wait, PVOID Buffer, PIO_STATUS_BLOCK IoStatus) +{ + PAGED_CODE(); + + NTSTATUS Result; + + try + { + BOOLEAN Success = CcCopyRead(FileObject, FileOffset, Length, Wait, Buffer, IoStatus); + Result = Success ? STATUS_SUCCESS : STATUS_PENDING; + } + except (EXCEPTION_EXECUTE_HANDLER) + { + Result = GetExceptionCode(); + } + + if (!NT_SUCCESS(Result)) + { + IoStatus->Information = 0; + IoStatus->Status = Result; + } + + return Result; +} + NTSTATUS FspCcCopyWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, PVOID Buffer) { @@ -265,6 +299,55 @@ NTSTATUS FspCcCopyWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULON } } +NTSTATUS FspCcMdlRead(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, + PMDL *PMdlChain, PIO_STATUS_BLOCK IoStatus) +{ + PAGED_CODE(); + + NTSTATUS Result; + + *PMdlChain = 0; + + try + { + CcMdlRead(FileObject, FileOffset, Length, PMdlChain, IoStatus); + Result = IoStatus->Status; + } + except(EXCEPTION_EXECUTE_HANDLER) + { + Result = GetExceptionCode(); + } + + if (!NT_SUCCESS(Result)) + { + if (0 != *PMdlChain) + { + CcMdlReadComplete(FileObject, *PMdlChain); + *PMdlChain = 0; + } + + IoStatus->Information = 0; + IoStatus->Status = Result; + } + + return Result; +} + +NTSTATUS FspCcMdlReadComplete(PFILE_OBJECT FileObject, PMDL MdlChain) +{ + PAGED_CODE(); + + try + { + CcMdlReadComplete(FileObject, MdlChain); + return STATUS_SUCCESS; + } + except (EXCEPTION_EXECUTE_HANDLER) + { + return GetExceptionCode(); + } +} + NTSTATUS FspCcPrepareMdlWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, PMDL *PMdlChain, PIO_STATUS_BLOCK IoStatus) { diff --git a/src/sys/write.c b/src/sys/write.c index d21fea7e..c5b1dfac 100644 --- a/src/sys/write.c +++ b/src/sys/write.c @@ -188,7 +188,7 @@ static NTSTATUS FspFsvolWriteCached( return STATUS_INSUFFICIENT_RESOURCES; } - Result = FspCcCopyWrite(FileObject, &WriteOffset, WriteLength, CanWait || Retrying, Buffer); + Result = FspCcCopyWrite(FileObject, &WriteOffset, WriteLength, CanWait, Buffer); if (STATUS_PENDING == Result) { FspFileNodeRelease(FileNode, Main); @@ -201,8 +201,8 @@ static NTSTATUS FspFsvolWriteCached( { ASSERT(0 == Irp->MdlAddress); - Result = FspCcPrepareMdlWrite(FileObject, &WriteOffset, WriteLength, - &Irp->MdlAddress, &Irp->IoStatus); + Result = FspCcPrepareMdlWrite(FileObject, &WriteOffset, WriteLength, &Irp->MdlAddress, + &Irp->IoStatus); if (!NT_SUCCESS(Result)) { FspFileNodeRelease(FileNode, Main);