sys: IRP_MJ_READ: implementation

This commit is contained in:
Bill Zissimopoulos 2016-03-04 19:20:41 -08:00
parent c7c367ccc8
commit bf02a601b2
5 changed files with 175 additions and 31 deletions

View File

@ -184,6 +184,10 @@ typedef struct
{ {
UINT64 UserContext; UINT64 UserContext;
UINT64 UserContext2; UINT64 UserContext2;
UINT64 Address;
UINT64 Offset;
UINT32 Length;
UINT32 Key;
} Read; } Read;
struct struct
{ {

View File

@ -70,6 +70,7 @@ NTSTATUS DriverEntry(
FspIopPrepareFunction[IRP_MJ_CREATE] = FspFsvolCreatePrepare; FspIopPrepareFunction[IRP_MJ_CREATE] = FspFsvolCreatePrepare;
FspIopCompleteFunction[IRP_MJ_CREATE] = FspFsvolCreateComplete; FspIopCompleteFunction[IRP_MJ_CREATE] = FspFsvolCreateComplete;
FspIopCompleteFunction[IRP_MJ_CLOSE] = FspFsvolCloseComplete; FspIopCompleteFunction[IRP_MJ_CLOSE] = FspFsvolCloseComplete;
FspIopPrepareFunction[IRP_MJ_READ] = FspFsvolReadPrepare;
FspIopCompleteFunction[IRP_MJ_READ] = FspFsvolReadComplete; FspIopCompleteFunction[IRP_MJ_READ] = FspFsvolReadComplete;
FspIopPrepareFunction[IRP_MJ_WRITE] = FspFsvolWritePrepare; FspIopPrepareFunction[IRP_MJ_WRITE] = FspFsvolWritePrepare;
FspIopCompleteFunction[IRP_MJ_WRITE] = FspFsvolWriteComplete; FspIopCompleteFunction[IRP_MJ_WRITE] = FspFsvolWriteComplete;

View File

@ -262,6 +262,7 @@ FSP_IOCMPL_DISPATCH FspFsvolQueryEaComplete;
FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete; FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete;
FSP_IOCMPL_DISPATCH FspFsvolQuerySecurityComplete; FSP_IOCMPL_DISPATCH FspFsvolQuerySecurityComplete;
FSP_IOCMPL_DISPATCH FspFsvolQueryVolumeInformationComplete; FSP_IOCMPL_DISPATCH FspFsvolQueryVolumeInformationComplete;
FSP_IOPREP_DISPATCH FspFsvolReadPrepare;
FSP_IOCMPL_DISPATCH FspFsvolReadComplete; FSP_IOCMPL_DISPATCH FspFsvolReadComplete;
FSP_IOCMPL_DISPATCH FspFsvolSetEaComplete; FSP_IOCMPL_DISPATCH FspFsvolSetEaComplete;
FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete; FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete;

View File

@ -13,6 +13,7 @@ static NTSTATUS FspFsvolReadCached(
BOOLEAN CanWait); BOOLEAN CanWait);
static NTSTATUS FspFsvolReadNonCached( static NTSTATUS FspFsvolReadNonCached(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_IOPREP_DISPATCH FspFsvolReadPrepare;
FSP_IOCMPL_DISPATCH FspFsvolReadComplete; FSP_IOCMPL_DISPATCH FspFsvolReadComplete;
static FSP_IOP_REQUEST_FINI FspFsvolReadNonCachedRequestFini; static FSP_IOP_REQUEST_FINI FspFsvolReadNonCachedRequestFini;
FSP_DRIVER_DISPATCH FspRead; FSP_DRIVER_DISPATCH FspRead;
@ -21,11 +22,21 @@ FSP_DRIVER_DISPATCH FspRead;
#pragma alloc_text(PAGE, FspFsvolRead) #pragma alloc_text(PAGE, FspFsvolRead)
#pragma alloc_text(PAGE, FspFsvolReadCached) #pragma alloc_text(PAGE, FspFsvolReadCached)
#pragma alloc_text(PAGE, FspFsvolReadNonCached) #pragma alloc_text(PAGE, FspFsvolReadNonCached)
#pragma alloc_text(PAGE, FspFsvolReadPrepare)
#pragma alloc_text(PAGE, FspFsvolReadComplete) #pragma alloc_text(PAGE, FspFsvolReadComplete)
#pragma alloc_text(PAGE, FspFsvolReadNonCachedRequestFini) #pragma alloc_text(PAGE, FspFsvolReadNonCachedRequestFini)
#pragma alloc_text(PAGE, FspRead) #pragma alloc_text(PAGE, FspRead)
#endif #endif
enum
{
/* ReadNonCached */
RequestIrp = 0,
RequestSafeMdl = 1,
RequestAddress = 2,
RequestProcess = 3,
};
static NTSTATUS FspFsvolRead( static NTSTATUS FspFsvolRead(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{ {
@ -164,7 +175,101 @@ static NTSTATUS FspFsvolReadNonCached(
{ {
PAGED_CODE(); PAGED_CODE();
return STATUS_INVALID_DEVICE_REQUEST; NTSTATUS Result;
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;
ULONG ReadKey = IrpSp->Parameters.Read.Key;
FSP_FSCTL_TRANSACT_REQ *Request;
ASSERT(FileNode == FileDesc->FileNode);
/* no MDL requests on the non-cached path */
if (FlagOn(IrpSp->MinorFunction, IRP_MN_MDL))
return STATUS_INVALID_PARAMETER;
/* probe and lock the user buffer */
if (0 == Irp->MdlAddress)
{
Result = FspLockUserBuffer(Irp->UserBuffer, ReadLength,
Irp->RequestorMode, IoReadAccess, &Irp->MdlAddress);
if (!NT_SUCCESS(Result))
return Result;
}
/* create request */
Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolReadNonCachedRequestFini, &Request);
if (!NT_SUCCESS(Result))
return Result;
Request->Kind = FspFsctlTransactReadKind;
Request->Req.Read.UserContext = FileNode->UserContext;
Request->Req.Read.UserContext2 = FileDesc->UserContext2;
Request->Req.Read.Offset = ReadOffset.QuadPart;
Request->Req.Read.Length = ReadLength;
Request->Req.Read.Key = ReadKey;
return FSP_STATUS_IOQ_POST;
}
NTSTATUS FspFsvolReadPrepare(
PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request)
{
PAGED_CODE();
NTSTATUS Result;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FSP_SAFE_MDL *SafeMdl = 0;
PVOID Address;
PEPROCESS Process;
BOOLEAN Success;
Success = DEBUGTEST(90, TRUE) && FspFileNodeTryAcquireShared(FileNode, Full);
if (!Success)
{
FspIopRetryPrepareIrp(Irp, &Result);
return Result;
}
/* create a "safe" MDL if necessary */
if (!FspSafeMdlCheck(Irp->MdlAddress))
{
Result = FspSafeMdlCreate(Irp->MdlAddress, IoWriteAccess, &SafeMdl);
if (!NT_SUCCESS(Result))
{
FspFileNodeRelease(FileNode, Full);
return STATUS_INSUFFICIENT_RESOURCES;
}
}
/* map the MDL into user-mode */
Result = FspMapLockedPagesInUserMode(0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress, &Address);
if (!NT_SUCCESS(Result))
{
if (0 != SafeMdl)
FspSafeMdlDelete(SafeMdl);
FspFileNodeRelease(FileNode, Full);
return Result;
}
/* get a pointer to the current process so that we can unmap the address later */
Process = PsGetCurrentProcess();
ObReferenceObject(Process);
Request->Req.Read.Address = (UINT64)(UINT_PTR)Address;
FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestIrp) = Irp;
FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl;
FspIopRequestContext(Request, RequestAddress) = Address;
FspIopRequestContext(Request, RequestProcess) = Process;
return STATUS_SUCCESS;
} }
NTSTATUS FspFsvolReadComplete( NTSTATUS FspFsvolReadComplete(
@ -172,6 +277,29 @@ NTSTATUS FspFsvolReadComplete(
{ {
FSP_ENTER_IOC(PAGED_CODE()); FSP_ENTER_IOC(PAGED_CODE());
PFILE_OBJECT FileObject = IrpSp->FileObject;
LARGE_INTEGER ReadOffset = IrpSp->Parameters.Read.ByteOffset;
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
BOOLEAN SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
if (!NT_SUCCESS(Response->IoStatus.Status))
{
Irp->IoStatus.Information = 0;
Result = Response->IoStatus.Status;
FSP_RETURN();
}
if (!PagingIo)
{
/* update the current file offset if synchronous I/O (and not paging I/O) */
if (SynchronousIo)
FileObject->CurrentByteOffset.QuadPart =
ReadOffset.QuadPart + Response->IoStatus.Information;
}
Irp->IoStatus.Information = Response->IoStatus.Information;
Result = STATUS_SUCCESS;
FSP_LEAVE_IOC( FSP_LEAVE_IOC(
"FileObject=%p, UserBuffer=%p, MdlAddress=%p, " "FileObject=%p, UserBuffer=%p, MdlAddress=%p, "
"Key=%#lx, ByteOffset=%#lx:%#lx, Length=%ld", "Key=%#lx, ByteOffset=%#lx:%#lx, Length=%ld",
@ -181,6 +309,44 @@ NTSTATUS FspFsvolReadComplete(
IrpSp->Parameters.Read.Length); IrpSp->Parameters.Read.Length);
} }
static VOID FspFsvolReadNonCachedRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4])
{
PAGED_CODE();
PIRP Irp = Context[RequestIrp];
FSP_SAFE_MDL *SafeMdl = Context[RequestSafeMdl];
PVOID Address = Context[RequestAddress];
PEPROCESS Process = Context[RequestProcess];
if (0 != Address)
{
KAPC_STATE ApcState;
BOOLEAN Attach;
ASSERT(0 != Process);
Attach = Process != PsGetCurrentProcess();
if (Attach)
KeStackAttachProcess(Process, &ApcState);
MmUnmapLockedPages(Address, 0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress);
if (Attach)
KeUnstackDetachProcess(&ApcState);
ObDereferenceObject(Process);
}
if (0 != SafeMdl)
FspSafeMdlDelete(SafeMdl);
if (0 != Irp)
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
FSP_FILE_NODE *FileNode = IrpSp->FileObject->FsContext;
FspFileNodeReleaseOwner(FileNode, Full, Request);
}
}
NTSTATUS FspRead( NTSTATUS FspRead(
PDEVICE_OBJECT DeviceObject, PIRP Irp) PDEVICE_OBJECT DeviceObject, PIRP Irp)
{ {

View File

@ -251,38 +251,10 @@ static NTSTATUS FspFsvolWriteNonCached(
if (PagingIo && WriteToEndOfFile) if (PagingIo && WriteToEndOfFile)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
/* if non-cached I/O check the offset/length alignment */
/*
* We are going to avoid doing this test, because we don't really need to restrict
* ourselves for non-cached I/O, but also because we do not always know the correct
* file size for our alignment test. The file size is needed, because the alignment
* test is:
*
* if WriteOffset is sector aligned
* and (WriteLength is sector aligned or WriteOffset + WriteLength >= FileSize)
*
* This means that the user-mode file system must be able to deal with variable size
* I/O, but this was the case anyway because of the following part of the test:
*
* WriteOffset + WriteLength >= FileSize
*
* In any case the user-mode file system can enforce this rule if it wants!
*/
#if 0
if (!PagingIo)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
FspFsvolDeviceExtension(FsvolDeviceObject);
if (0 != WriteOffset.QuadPart % FsvolDeviceExtension->VolumeParams.SectorSize ||
0 != WriteLength % FsvolDeviceExtension->VolumeParams.SectorSize)
return STATUS_NOT_IMPLEMENTED; /* FastFat does this! */
}
#endif
/* probe and lock the user buffer */ /* probe and lock the user buffer */
if (0 == Irp->MdlAddress) if (0 == Irp->MdlAddress)
{ {
Result = FspLockUserBuffer(Irp->UserBuffer, IrpSp->Parameters.Write.Length, Result = FspLockUserBuffer(Irp->UserBuffer, WriteLength,
Irp->RequestorMode, IoReadAccess, &Irp->MdlAddress); Irp->RequestorMode, IoReadAccess, &Irp->MdlAddress);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return Result; return Result;
@ -382,7 +354,7 @@ NTSTATUS FspFsvolWritePrepare(
Request->Req.Write.Address = (UINT64)(UINT_PTR)Address; Request->Req.Write.Address = (UINT64)(UINT_PTR)Address;
FspFileNodeSetOwner(FileNode, Pgio, Request); FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestIrp) = Irp; FspIopRequestContext(Request, RequestIrp) = Irp;
FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl; FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl;
FspIopRequestContext(Request, RequestAddress) = Address; FspIopRequestContext(Request, RequestAddress) = Address;