sys: FspVolumeTransact: upper bound on loop guarantees forward progress!

This commit is contained in:
Bill Zissimopoulos 2016-04-12 15:42:06 -07:00
parent 220208cf87
commit 7499c964b9
3 changed files with 46 additions and 2 deletions

View File

@ -571,7 +571,7 @@ typedef struct
LIST_ENTRY PendingIrpList, ProcessIrpList, RetriedIrpList;
IO_CSQ PendingIoCsq, ProcessIoCsq, RetriedIoCsq;
ULONG IrpTimeout;
ULONG PendingIrpCapacity, PendingIrpCount;
ULONG PendingIrpCapacity, PendingIrpCount, ProcessIrpCount, RetriedIrpCount;
VOID (*CompleteCanceledIrp)(PIRP Irp);
ULONG ProcessIrpBucketCount;
PVOID ProcessIrpBuckets[];
@ -586,10 +586,13 @@ VOID FspIoqRemoveExpired(FSP_IOQ *Ioq, UINT64 InterruptTime);
BOOLEAN FspIoqPostIrpEx(FSP_IOQ *Ioq, PIRP Irp, BOOLEAN BestEffort, NTSTATUS *PResult);
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp, PLARGE_INTEGER Timeout,
PIRP CancellableIrp);
ULONG FspIoqPendingIrpCount(FSP_IOQ *Ioq);
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp);
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint);
ULONG FspIoqProcessIrpCount(FSP_IOQ *Ioq);
BOOLEAN FspIoqRetryCompleteIrp(FSP_IOQ *Ioq, PIRP Irp, NTSTATUS *PResult);
PIRP FspIoqNextCompleteIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp);
ULONG FspIoqRetriedIrpCount(FSP_IOQ *Ioq);
/* meta cache */
typedef struct

View File

@ -270,6 +270,7 @@ static NTSTATUS FspIoqProcessInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertCo
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
if (Ioq->Stopped)
return STATUS_CANCELLED;
Ioq->ProcessIrpCount++;
InsertTailList(&Ioq->ProcessIrpList, &Irp->Tail.Overlay.ListEntry);
ULONG Index = FspHashMixPointer(Irp) % Ioq->ProcessIrpBucketCount;
#if DBG
@ -296,6 +297,7 @@ static VOID FspIoqProcessRemoveIrp(PIO_CSQ IoCsq, PIRP Irp)
break;
}
}
Ioq->ProcessIrpCount--;
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
}
@ -360,12 +362,15 @@ static NTSTATUS FspIoqRetriedInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertCo
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, RetriedIoCsq);
if (Ioq->Stopped)
return STATUS_CANCELLED;
Ioq->RetriedIrpCount++;
InsertTailList(&Ioq->RetriedIrpList, &Irp->Tail.Overlay.ListEntry);
return STATUS_SUCCESS;
}
static VOID FspIoqRetriedRemoveIrp(PIO_CSQ IoCsq, PIRP Irp)
{
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, RetriedIoCsq);
Ioq->RetriedIrpCount--;
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
}
@ -583,6 +588,16 @@ PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp, PLARGE_INTEGER Timeout
return PendingIrp;
}
ULONG FspIoqPendingIrpCount(FSP_IOQ *Ioq)
{
ULONG Result;
KIRQL Irql;
KeAcquireSpinLock(&Ioq->SpinLock, &Irql);
Result = Ioq->PendingIrpCount;
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
return Result;
}
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp)
{
NTSTATUS Result;
@ -606,6 +621,16 @@ PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint)
return FspCsqRemoveNextIrp(&Ioq->ProcessIoCsq, &PeekContext);
}
ULONG FspIoqProcessIrpCount(FSP_IOQ *Ioq)
{
ULONG Result;
KIRQL Irql;
KeAcquireSpinLock(&Ioq->SpinLock, &Irql);
Result = Ioq->ProcessIrpCount;
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
return Result;
}
BOOLEAN FspIoqRetryCompleteIrp(FSP_IOQ *Ioq, PIRP Irp, NTSTATUS *PResult)
{
NTSTATUS Result;
@ -637,3 +662,13 @@ PIRP FspIoqNextCompleteIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp)
PeekContext.ExpirationTime = 0;
return FspCsqRemoveNextIrp(&Ioq->RetriedIoCsq, &PeekContext);
}
ULONG FspIoqRetriedIrpCount(FSP_IOQ *Ioq)
{
ULONG Result;
KIRQL Irql;
KeAcquireSpinLock(&Ioq->SpinLock, &Irql);
Result = Ioq->RetriedIrpCount;
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
return Result;
}

View File

@ -546,6 +546,7 @@ NTSTATUS FspVolumeTransact(
FSP_FSCTL_TRANSACT_RSP *Response, *NextResponse;
FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest;
PIRP ProcessIrp, PendingIrp, RetriedIrp, RepostedIrp;
ULONG LoopCount;
LARGE_INTEGER Timeout;
PIRP TopLevelIrp = IoGetTopLevelIrp();
@ -587,7 +588,8 @@ NTSTATUS FspVolumeTransact(
}
/* process any retried IRP's */
for (;;)
LoopCount = FspIoqRetriedIrpCount(FsvolDeviceExtension->Ioq);
while (0 < LoopCount--) /* upper bound on loop guarantees forward progress! */
{
/* get the next retried IRP, but do not go beyond the first reposted IRP! */
RetriedIrp = FspIoqNextCompleteIrp(FsvolDeviceExtension->Ioq, RepostedIrp);
@ -656,6 +658,7 @@ NTSTATUS FspVolumeTransact(
Request = OutputBuffer;
BufferEnd = (PUINT8)OutputBuffer + OutputBufferLength;
ASSERT(FspFsctlTransactCanProduceRequest(Request, BufferEnd));
LoopCount = FspIoqPendingIrpCount(FsvolDeviceExtension->Ioq);
for (;;)
{
PendingIrpRequest = FspIrpRequest(PendingIrp);
@ -700,6 +703,9 @@ NTSTATUS FspVolumeTransact(
if (!FspFsctlTransactCanProduceRequest(Request, BufferEnd))
break;
}
if (0 >= LoopCount--) /* upper bound on loop guarantees forward progress! */
break;
/* get the next pending IRP, but do not go beyond the first reposted IRP! */
PendingIrp = FspIoqNextPendingIrp(FsvolDeviceExtension->Ioq, RepostedIrp, 0, Irp);