From 9b93df1788a1c0ed30f8715fed43d0d114c36969 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Tue, 5 Jan 2016 17:10:44 -0800 Subject: [PATCH] sys: FspIoqNextPendingIrp: add BoundaryIrp parameter --- src/sys/driver.h | 2 +- src/sys/ioq.c | 8 ++++++-- src/sys/volume.c | 18 ++++++++++++++---- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/sys/driver.h b/src/sys/driver.h index adb60b85..0d590f7d 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -359,7 +359,7 @@ VOID FspIoqStop(FSP_IOQ *Ioq); BOOLEAN FspIoqStopped(FSP_IOQ *Ioq); VOID FspIoqRemoveExpired(FSP_IOQ *Ioq); BOOLEAN FspIoqPostIrpEx(FSP_IOQ *Ioq, PIRP Irp, BOOLEAN CheckCapacity, NTSTATUS *PResult); -PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout); +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); diff --git a/src/sys/ioq.c b/src/sys/ioq.c index 6cc91148..69131675 100644 --- a/src/sys/ioq.c +++ b/src/sys/ioq.c @@ -107,7 +107,11 @@ static PIRP FspIoqPendingPeekNextIrp(PIO_CSQ IoCsq, PIRP Irp, PVOID PeekContext) return FspIrpTimestamp(Irp) <= ExpirationTime ? Irp : 0; } else + { + if (Irp == IrpHint) + return 0; return Irp; + } } _IRQL_raises_(DISPATCH_LEVEL) @@ -311,7 +315,7 @@ BOOLEAN FspIoqPostIrpEx(FSP_IOQ *Ioq, PIRP Irp, BOOLEAN CheckCapacity, NTSTATUS return FALSE; } -PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout) +PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp, PLARGE_INTEGER Timeout) { /* timeout of 0 normally means infinite wait; for us it means do not do any wait at all! */ if (0 != Timeout) @@ -324,7 +328,7 @@ PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout) return FspIoqTimeout; } FSP_IOQ_PEEK_CONTEXT PeekContext; - PeekContext.IrpHint = (PVOID)1; + PeekContext.IrpHint = 0 != BoundaryIrp ? BoundaryIrp : (PVOID)1; PeekContext.ExpirationTime = 0; return IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, &PeekContext); } diff --git a/src/sys/volume.c b/src/sys/volume.c index e4cb25a0..df07099e 100644 --- a/src/sys/volume.c +++ b/src/sys/volume.c @@ -510,7 +510,7 @@ NTSTATUS FspVolumeTransact( PUINT8 BufferEnd; FSP_FSCTL_TRANSACT_RSP *Response, *NextResponse; FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest; - PIRP ProcessIrp, PendingIrp; + PIRP ProcessIrp, PendingIrp, RepostedIrp = 0; LARGE_INTEGER Timeout; /* process any user-mode file system responses */ @@ -545,7 +545,7 @@ NTSTATUS FspVolumeTransact( KeQuerySystemTime(&Timeout); Timeout.QuadPart += FsvolDeviceExtension->VolumeParams.TransactTimeout * 10000; /* convert millis to nanos and add to absolute time */ - while (0 == (PendingIrp = FspIoqNextPendingIrp(FsvolDeviceExtension->Ioq, &Timeout))) + while (0 == (PendingIrp = FspIoqNextPendingIrp(FsvolDeviceExtension->Ioq, 0, &Timeout))) { if (FspIoqStopped(FsvolDeviceExtension->Ioq)) return STATUS_CANCELLED; @@ -565,7 +565,16 @@ NTSTATUS FspVolumeTransact( PendingIrpRequest = FspIrpRequest(PendingIrp); Result = FspIopDispatchPrepare(PendingIrp, PendingIrpRequest); - if (!NT_SUCCESS(Result)) + 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 = PendingIrp; + } + else if (!NT_SUCCESS(Result)) FspIopCompleteIrp(PendingIrp, Result); else { @@ -590,7 +599,8 @@ NTSTATUS FspVolumeTransact( break; } - PendingIrp = FspIoqNextPendingIrp(FsvolDeviceExtension->Ioq, 0); + /* get the next pending IRP, but do not go beyond the first reposted IRP! */ + PendingIrp = FspIoqNextPendingIrp(FsvolDeviceExtension->Ioq, RepostedIrp, 0); if (0 == PendingIrp) break; }