diff --git a/src/sys/create.c b/src/sys/create.c index ab6fee34..51b7b85e 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -14,6 +14,7 @@ static NTSTATUS FspFsvolCreate( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); FSP_IOPREP_DISPATCH FspFsvolCreatePrepare; FSP_IOCMPL_DISPATCH FspFsvolCreateComplete; +FSP_IORETR_DISPATCH FspFsvolCreateRetryComplete; static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FILE_NODE *FileNode, FSP_FILE_DESC *FileDesc, PFILE_OBJECT FileObject); static VOID FspFsvolCreatePostClose(FSP_FILE_DESC *FileDesc); @@ -28,6 +29,7 @@ FSP_DRIVER_DISPATCH FspCreate; #pragma alloc_text(PAGE, FspFsvolCreate) #pragma alloc_text(PAGE, FspFsvolCreatePrepare) #pragma alloc_text(PAGE, FspFsvolCreateComplete) +#pragma alloc_text(PAGE, FspFsvolCreateRetryComplete) #pragma alloc_text(PAGE, FspFsvolCreateTryOpen) #pragma alloc_text(PAGE, FspFsvolCreatePostClose) #pragma alloc_text(PAGE, FspFsvolCreateRequestFini) @@ -711,6 +713,14 @@ VOID FspFsvolCreateComplete( IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName); } +NTSTATUS FspFsvolCreateRetryComplete( + PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request) +{ + PAGED_CODE(); + + return STATUS_NOT_IMPLEMENTED; +} + static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FILE_NODE *FileNode, FSP_FILE_DESC *FileDesc, PFILE_OBJECT FileObject) { diff --git a/src/sys/driver.c b/src/sys/driver.c index b9b0cff3..2b94c4f5 100644 --- a/src/sys/driver.c +++ b/src/sys/driver.c @@ -66,11 +66,10 @@ NTSTATUS DriverEntry( DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = FspQuerySecurity; DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = FspSetSecurity; - /* setup the I/O preparation functions */ + /* setup the I/O prepare/complete functions */ FspIopPrepareFunction[IRP_MJ_CREATE] = FspFsvolCreatePrepare; - - /* setup the I/O completion functions */ FspIopCompleteFunction[IRP_MJ_CREATE] = FspFsvolCreateComplete; + FspIopRetryCompleteFunction[IRP_MJ_CREATE] = FspFsvolCreateRetryComplete; FspIopCompleteFunction[IRP_MJ_CLOSE] = FspFsvolCloseComplete; FspIopCompleteFunction[IRP_MJ_READ] = FspFsvolReadComplete; FspIopCompleteFunction[IRP_MJ_WRITE] = FspFsvolWriteComplete; diff --git a/src/sys/driver.h b/src/sys/driver.h index 386c6b51..1a744e82 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -225,10 +225,15 @@ _IRQL_requires_max_(APC_LEVEL) _IRQL_requires_same_ typedef VOID FSP_IOCMPL_DISPATCH( _Inout_ PIRP Irp, _In_ const FSP_FSCTL_TRANSACT_RSP *Response); -FSP_IOPREP_DISPATCH FspFsvolCreatePrepare; +_IRQL_requires_max_(APC_LEVEL) +_IRQL_requires_same_ +typedef NTSTATUS FSP_IORETR_DISPATCH( + _Inout_ PIRP Irp, _Inout_ FSP_FSCTL_TRANSACT_REQ *Request); FSP_IOCMPL_DISPATCH FspFsvolCleanupComplete; FSP_IOCMPL_DISPATCH FspFsvolCloseComplete; +FSP_IOPREP_DISPATCH FspFsvolCreatePrepare; FSP_IOCMPL_DISPATCH FspFsvolCreateComplete; +FSP_IORETR_DISPATCH FspFsvolCreateRetryComplete; FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete; FSP_IOCMPL_DISPATCH FspFsvolDirectoryControlComplete; FSP_IOCMPL_DISPATCH FspFsvolFileSystemControlComplete; @@ -385,7 +390,7 @@ BOOLEAN FspIoqPostIrpEx(FSP_IOQ *Ioq, PIRP Irp, BOOLEAN BestEffort, NTSTATUS *PR PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp, PLARGE_INTEGER Timeout); BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp); PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint); -BOOLEAN FspIoqRetryCompleteIrp(FSP_IOQ *Ioq, PIRP Irp); +BOOLEAN FspIoqRetryCompleteIrp(FSP_IOQ *Ioq, PIRP Irp, NTSTATUS *PResult); PIRP FspIoqNextCompleteIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp); /* I/O processing */ @@ -418,6 +423,7 @@ VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceDereference); VOID FspIopCompleteCanceledIrp(PIRP Irp); NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request); VOID FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response); +NTSTATUS FspIopDispatchRetryComplete(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request); /* device management */ #define FSP_DEVICE_VOLUME_NAME_LENMAX (FSP_FSCTL_VOLUME_NAME_SIZEMAX - sizeof(WCHAR)) @@ -654,5 +660,6 @@ extern PDEVICE_OBJECT FspFsctlDiskDeviceObject; extern PDEVICE_OBJECT FspFsctlNetDeviceObject; extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[]; extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[]; +extern FSP_IORETR_DISPATCH *FspIopRetryCompleteFunction[]; #endif diff --git a/src/sys/iop.c b/src/sys/iop.c index 4c10898f..8dc86c27 100644 --- a/src/sys/iop.c +++ b/src/sys/iop.c @@ -19,6 +19,7 @@ VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceDereference); VOID FspIopCompleteCanceledIrp(PIRP Irp); NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request); VOID FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response); +NTSTATUS FspIopDispatchRetryComplete(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request); #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, FspIopCreateRequestFunnel) @@ -29,6 +30,7 @@ VOID FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response); #pragma alloc_text(PAGE, FspIopCompleteCanceledIrp) #pragma alloc_text(PAGE, FspIopDispatchPrepare) #pragma alloc_text(PAGE, FspIopDispatchComplete) +#pragma alloc_text(PAGE, FspIopDispatchRetryComplete) #endif static const LONG Delays[] = @@ -268,5 +270,19 @@ VOID FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) FspIopCompleteFunction[IrpSp->MajorFunction](Irp, Response); } +NTSTATUS FspIopDispatchRetryComplete(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request) +{ + PAGED_CODE(); + + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + + ASSERT(IRP_MJ_MAXIMUM_FUNCTION >= IrpSp->MajorFunction); + if (0 != FspIopRetryCompleteFunction[IrpSp->MajorFunction]) + return FspIopRetryCompleteFunction[IrpSp->MajorFunction](Irp, Request); + else + return STATUS_SUCCESS; +} + FSP_IOPREP_DISPATCH *FspIopPrepareFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; +FSP_IORETR_DISPATCH *FspIopRetryCompleteFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; diff --git a/src/sys/ioq.c b/src/sys/ioq.c index bc13d318..eb8b1b80 100644 --- a/src/sys/ioq.c +++ b/src/sys/ioq.c @@ -518,7 +518,7 @@ PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint) return FspCsqRemoveNextIrp(&Ioq->ProcessIoCsq, &PeekContext); } -BOOLEAN FspIoqRetryCompleteIrp(FSP_IOQ *Ioq, PIRP Irp) +BOOLEAN FspIoqRetryCompleteIrp(FSP_IOQ *Ioq, PIRP Irp, NTSTATUS *PResult) { NTSTATUS Result; #if defined(FSP_IOQ_PROCESS_NO_CANCEL) @@ -528,7 +528,18 @@ BOOLEAN FspIoqRetryCompleteIrp(FSP_IOQ *Ioq, PIRP Irp) FspIrpTimestamp(Irp) = QueryInterruptTimeInSec() + Ioq->IrpTimeout; #endif Result = FspCsqInsertIrpEx(&Ioq->RetriedIoCsq, Irp, 0, 0); - return NT_SUCCESS(Result); + if (NT_SUCCESS(Result)) + { + if (0 != PResult) + *PResult = STATUS_PENDING; + return TRUE; + } + else + { + if (0 != PResult) + *PResult = Result; + return FALSE; + } } PIRP FspIoqNextCompleteIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp) @@ -536,5 +547,5 @@ PIRP FspIoqNextCompleteIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp) FSP_IOQ_PEEK_CONTEXT PeekContext; PeekContext.IrpHint = 0 != BoundaryIrp ? BoundaryIrp : (PVOID)1; PeekContext.ExpirationTime = 0; - return IoCsqRemoveNextIrp(&Ioq->RetriedIoCsq, &PeekContext); + return FspCsqRemoveNextIrp(&Ioq->RetriedIoCsq, &PeekContext); } diff --git a/src/sys/volume.c b/src/sys/volume.c index 9e3ca313..49b82680 100644 --- a/src/sys/volume.c +++ b/src/sys/volume.c @@ -517,7 +517,7 @@ NTSTATUS FspVolumeTransact( PUINT8 BufferEnd; FSP_FSCTL_TRANSACT_RSP *Response, *NextResponse; FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest; - PIRP ProcessIrp, PendingIrp, RepostedIrp = 0; + PIRP ProcessIrp, PendingIrp, RetriedIrp, RepostedIrp; LARGE_INTEGER Timeout; /* process any user-mode file system responses */ @@ -539,6 +539,27 @@ NTSTATUS FspVolumeTransact( Response = NextResponse; } + /* process any retried IRP's */ + RepostedIrp = 0; + for (;;) + { + /* get the next retried IRP, but do not go beyond the first reposted IRP! */ + RetriedIrp = FspIoqNextCompleteIrp(FsvolDeviceExtension->Ioq, RepostedIrp); + if (0 == RetriedIrp) + break; + + Result = FspIopDispatchRetryComplete(RetriedIrp, FspIrpRequest(RetriedIrp)); + if (STATUS_PENDING == Result) + { + /* + * The IRP has been reposted to our Ioq. Remember the first such IRP, + * so that we know to break the loop if we see it again. + */ + if (0 == RepostedIrp) + RepostedIrp = RetriedIrp; + } + } + /* were we sent an output buffer? */ if (0 == Irp->MdlAddress) { @@ -564,6 +585,7 @@ NTSTATUS FspVolumeTransact( } /* send any pending IRP's to the user-mode file system */ + RepostedIrp = 0; Request = MdlBuffer; BufferEnd = (PUINT8)MdlBuffer + OutputBufferLength; ASSERT(FspFsctlTransactCanProduceRequest(Request, BufferEnd));