mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 08:53:01 -05:00
sys: FspVolumeTransact: upper bound on loop guarantees forward progress!
This commit is contained in:
parent
220208cf87
commit
7499c964b9
@ -571,7 +571,7 @@ typedef struct
|
|||||||
LIST_ENTRY PendingIrpList, ProcessIrpList, RetriedIrpList;
|
LIST_ENTRY PendingIrpList, ProcessIrpList, RetriedIrpList;
|
||||||
IO_CSQ PendingIoCsq, ProcessIoCsq, RetriedIoCsq;
|
IO_CSQ PendingIoCsq, ProcessIoCsq, RetriedIoCsq;
|
||||||
ULONG IrpTimeout;
|
ULONG IrpTimeout;
|
||||||
ULONG PendingIrpCapacity, PendingIrpCount;
|
ULONG PendingIrpCapacity, PendingIrpCount, ProcessIrpCount, RetriedIrpCount;
|
||||||
VOID (*CompleteCanceledIrp)(PIRP Irp);
|
VOID (*CompleteCanceledIrp)(PIRP Irp);
|
||||||
ULONG ProcessIrpBucketCount;
|
ULONG ProcessIrpBucketCount;
|
||||||
PVOID ProcessIrpBuckets[];
|
PVOID ProcessIrpBuckets[];
|
||||||
@ -586,10 +586,13 @@ VOID FspIoqRemoveExpired(FSP_IOQ *Ioq, UINT64 InterruptTime);
|
|||||||
BOOLEAN FspIoqPostIrpEx(FSP_IOQ *Ioq, PIRP Irp, BOOLEAN BestEffort, NTSTATUS *PResult);
|
BOOLEAN FspIoqPostIrpEx(FSP_IOQ *Ioq, PIRP Irp, BOOLEAN BestEffort, NTSTATUS *PResult);
|
||||||
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp, PLARGE_INTEGER Timeout,
|
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp, PLARGE_INTEGER Timeout,
|
||||||
PIRP CancellableIrp);
|
PIRP CancellableIrp);
|
||||||
|
ULONG FspIoqPendingIrpCount(FSP_IOQ *Ioq);
|
||||||
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp);
|
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp);
|
||||||
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint);
|
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint);
|
||||||
|
ULONG FspIoqProcessIrpCount(FSP_IOQ *Ioq);
|
||||||
BOOLEAN FspIoqRetryCompleteIrp(FSP_IOQ *Ioq, PIRP Irp, NTSTATUS *PResult);
|
BOOLEAN FspIoqRetryCompleteIrp(FSP_IOQ *Ioq, PIRP Irp, NTSTATUS *PResult);
|
||||||
PIRP FspIoqNextCompleteIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp);
|
PIRP FspIoqNextCompleteIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp);
|
||||||
|
ULONG FspIoqRetriedIrpCount(FSP_IOQ *Ioq);
|
||||||
|
|
||||||
/* meta cache */
|
/* meta cache */
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -270,6 +270,7 @@ static NTSTATUS FspIoqProcessInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertCo
|
|||||||
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
|
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
|
||||||
if (Ioq->Stopped)
|
if (Ioq->Stopped)
|
||||||
return STATUS_CANCELLED;
|
return STATUS_CANCELLED;
|
||||||
|
Ioq->ProcessIrpCount++;
|
||||||
InsertTailList(&Ioq->ProcessIrpList, &Irp->Tail.Overlay.ListEntry);
|
InsertTailList(&Ioq->ProcessIrpList, &Irp->Tail.Overlay.ListEntry);
|
||||||
ULONG Index = FspHashMixPointer(Irp) % Ioq->ProcessIrpBucketCount;
|
ULONG Index = FspHashMixPointer(Irp) % Ioq->ProcessIrpBucketCount;
|
||||||
#if DBG
|
#if DBG
|
||||||
@ -296,6 +297,7 @@ static VOID FspIoqProcessRemoveIrp(PIO_CSQ IoCsq, PIRP Irp)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ioq->ProcessIrpCount--;
|
||||||
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
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);
|
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, RetriedIoCsq);
|
||||||
if (Ioq->Stopped)
|
if (Ioq->Stopped)
|
||||||
return STATUS_CANCELLED;
|
return STATUS_CANCELLED;
|
||||||
|
Ioq->RetriedIrpCount++;
|
||||||
InsertTailList(&Ioq->RetriedIrpList, &Irp->Tail.Overlay.ListEntry);
|
InsertTailList(&Ioq->RetriedIrpList, &Irp->Tail.Overlay.ListEntry);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID FspIoqRetriedRemoveIrp(PIO_CSQ IoCsq, PIRP Irp)
|
static VOID FspIoqRetriedRemoveIrp(PIO_CSQ IoCsq, PIRP Irp)
|
||||||
{
|
{
|
||||||
|
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, RetriedIoCsq);
|
||||||
|
Ioq->RetriedIrpCount--;
|
||||||
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,6 +588,16 @@ PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp, PLARGE_INTEGER Timeout
|
|||||||
return PendingIrp;
|
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)
|
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp)
|
||||||
{
|
{
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
@ -606,6 +621,16 @@ PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint)
|
|||||||
return FspCsqRemoveNextIrp(&Ioq->ProcessIoCsq, &PeekContext);
|
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)
|
BOOLEAN FspIoqRetryCompleteIrp(FSP_IOQ *Ioq, PIRP Irp, NTSTATUS *PResult)
|
||||||
{
|
{
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
@ -637,3 +662,13 @@ PIRP FspIoqNextCompleteIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp)
|
|||||||
PeekContext.ExpirationTime = 0;
|
PeekContext.ExpirationTime = 0;
|
||||||
return FspCsqRemoveNextIrp(&Ioq->RetriedIoCsq, &PeekContext);
|
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;
|
||||||
|
}
|
||||||
|
@ -546,6 +546,7 @@ NTSTATUS FspVolumeTransact(
|
|||||||
FSP_FSCTL_TRANSACT_RSP *Response, *NextResponse;
|
FSP_FSCTL_TRANSACT_RSP *Response, *NextResponse;
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest;
|
FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest;
|
||||||
PIRP ProcessIrp, PendingIrp, RetriedIrp, RepostedIrp;
|
PIRP ProcessIrp, PendingIrp, RetriedIrp, RepostedIrp;
|
||||||
|
ULONG LoopCount;
|
||||||
LARGE_INTEGER Timeout;
|
LARGE_INTEGER Timeout;
|
||||||
PIRP TopLevelIrp = IoGetTopLevelIrp();
|
PIRP TopLevelIrp = IoGetTopLevelIrp();
|
||||||
|
|
||||||
@ -587,7 +588,8 @@ NTSTATUS FspVolumeTransact(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* process any retried IRP's */
|
/* 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! */
|
/* get the next retried IRP, but do not go beyond the first reposted IRP! */
|
||||||
RetriedIrp = FspIoqNextCompleteIrp(FsvolDeviceExtension->Ioq, RepostedIrp);
|
RetriedIrp = FspIoqNextCompleteIrp(FsvolDeviceExtension->Ioq, RepostedIrp);
|
||||||
@ -656,6 +658,7 @@ NTSTATUS FspVolumeTransact(
|
|||||||
Request = OutputBuffer;
|
Request = OutputBuffer;
|
||||||
BufferEnd = (PUINT8)OutputBuffer + OutputBufferLength;
|
BufferEnd = (PUINT8)OutputBuffer + OutputBufferLength;
|
||||||
ASSERT(FspFsctlTransactCanProduceRequest(Request, BufferEnd));
|
ASSERT(FspFsctlTransactCanProduceRequest(Request, BufferEnd));
|
||||||
|
LoopCount = FspIoqPendingIrpCount(FsvolDeviceExtension->Ioq);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
PendingIrpRequest = FspIrpRequest(PendingIrp);
|
PendingIrpRequest = FspIrpRequest(PendingIrp);
|
||||||
@ -701,6 +704,9 @@ NTSTATUS FspVolumeTransact(
|
|||||||
break;
|
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! */
|
/* get the next pending IRP, but do not go beyond the first reposted IRP! */
|
||||||
PendingIrp = FspIoqNextPendingIrp(FsvolDeviceExtension->Ioq, RepostedIrp, 0, Irp);
|
PendingIrp = FspIoqNextPendingIrp(FsvolDeviceExtension->Ioq, RepostedIrp, 0, Irp);
|
||||||
if (0 == PendingIrp)
|
if (0 == PendingIrp)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user