mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-31 12:08:41 -05:00 
			
		
		
		
	sys: FspVolumeTransact: upper bound on loop guarantees forward progress!
This commit is contained in:
		| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user