mirror of
https://github.com/winfsp/winfsp.git
synced 2025-06-14 15:52:47 -05:00
sys: FspFsvrtTransact: now has timeout
This commit is contained in:
@ -246,6 +246,7 @@ FAST_IO_ACQUIRE_FOR_CCFLUSH FspAcquireForCcFlush;
|
||||
FAST_IO_RELEASE_FOR_CCFLUSH FspReleaseForCcFlush;
|
||||
|
||||
/* I/O queue */
|
||||
#define FspIoqTimeout ((PIRP)1)
|
||||
typedef struct
|
||||
{
|
||||
KSPIN_LOCK SpinLock;
|
||||
@ -258,7 +259,7 @@ VOID FspIoqInitialize(FSP_IOQ *Ioq);
|
||||
VOID FspIoqStop(FSP_IOQ *Ioq);
|
||||
BOOLEAN FspIoqStopped(FSP_IOQ *Ioq);
|
||||
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp);
|
||||
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, ULONG millis);
|
||||
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout);
|
||||
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp);
|
||||
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint);
|
||||
|
||||
|
@ -353,6 +353,8 @@ static NTSTATUS FspFsvrtTransact(
|
||||
FSP_FSCTL_TRANSACT_RSP *Response, *NextResponse;
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest;
|
||||
PIRP ProcessIrp, PendingIrp;
|
||||
ULONG TransactTimeout;
|
||||
LARGE_INTEGER Timeout;
|
||||
|
||||
/* access check */
|
||||
Result = FspSecuritySubjectContextAccessCheck(
|
||||
@ -380,12 +382,21 @@ static NTSTATUS FspFsvrtTransact(
|
||||
}
|
||||
|
||||
/* wait for an IRP to arrive */
|
||||
retry:
|
||||
while (0 == (PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, (ULONG)-1L)))
|
||||
TransactTimeout = FsvrtDeviceExtension->VolumeParams.TransactTimeout;
|
||||
if (FspFsctlTransactTimeoutMinimum > TransactTimeout || TransactTimeout > FspFsctlTransactTimeoutMaximum)
|
||||
TransactTimeout = FspFsctlTransactTimeoutDefault;
|
||||
KeQuerySystemTime(&Timeout);
|
||||
Timeout.QuadPart += TransactTimeout * 10000; /* convert millis to nanos and add to absolute time */
|
||||
while (0 == (PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, &Timeout)))
|
||||
{
|
||||
if (FspIoqStopped(&FsvrtDeviceExtension->Ioq))
|
||||
return STATUS_CANCELLED;
|
||||
}
|
||||
if (FspIoqTimeout == PendingIrp)
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* send any pending IRP's to the user-mode file system */
|
||||
Request = SystemBuffer;
|
||||
@ -426,10 +437,6 @@ retry:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (Request == SystemBuffer)
|
||||
goto retry;
|
||||
|
||||
Irp->IoStatus.Information = (PUINT8)Request - (PUINT8)SystemBuffer;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -209,17 +209,17 @@ BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp)
|
||||
return NT_SUCCESS(Result);
|
||||
}
|
||||
|
||||
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, ULONG millis)
|
||||
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout)
|
||||
{
|
||||
if (0 != millis)
|
||||
/* timeout of 0 normally means infinite wait; for us it means do not do any wait at all! */
|
||||
if (0 != Timeout)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
LARGE_INTEGER Timeout;
|
||||
Timeout.QuadPart = (LONGLONG)millis * 10000;
|
||||
Result = KeWaitForSingleObject(&Ioq->PendingIrpEvent, Executive, KernelMode, FALSE,
|
||||
-1 == millis ? 0 : &Timeout);
|
||||
if (STATUS_SUCCESS != Result)
|
||||
return 0;
|
||||
Timeout);
|
||||
ASSERT(STATUS_SUCCESS == Result || STATUS_TIMEOUT == Result);
|
||||
if (STATUS_TIMEOUT == Result)
|
||||
return FspIoqTimeout;
|
||||
}
|
||||
return IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, (PVOID)1);
|
||||
}
|
||||
|
Reference in New Issue
Block a user