mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-24 01:13:04 -05:00
sys: FspFsvrtTransact: now has timeout
This commit is contained in:
parent
5d6d938039
commit
aee12e1c5f
@ -70,11 +70,18 @@ enum
|
|||||||
FspFsctlTransactQuerySecurityKind = 'S',
|
FspFsctlTransactQuerySecurityKind = 'S',
|
||||||
FspFsctlTransactSetSecurityKind = 's',
|
FspFsctlTransactSetSecurityKind = 's',
|
||||||
};
|
};
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FspFsctlTransactTimeoutMinimum = 1000,
|
||||||
|
FspFsctlTransactTimeoutMaximum = 10000,
|
||||||
|
FspFsctlTransactTimeoutDefault = 1000,
|
||||||
|
};
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UINT16 Version;
|
UINT16 Version;
|
||||||
UINT16 SectorSize;
|
UINT16 SectorSize;
|
||||||
UINT32 SerialNumber;
|
UINT32 SerialNumber;
|
||||||
|
UINT32 TransactTimeout; /* milliseconds; values between 1000ms and 10000ms */
|
||||||
UINT32 EaSupported:1; /* supports extended attributes (unimplemented; set to 0) */
|
UINT32 EaSupported:1; /* supports extended attributes (unimplemented; set to 0) */
|
||||||
UINT32 FileNameRequired:1; /* FileName required for all operations (not just Create) */
|
UINT32 FileNameRequired:1; /* FileName required for all operations (not just Create) */
|
||||||
UINT32 NoSystemAccessCheck:1; /* if set the user-mode flie system performs access checks */
|
UINT32 NoSystemAccessCheck:1; /* if set the user-mode flie system performs access checks */
|
||||||
|
@ -246,6 +246,7 @@ FAST_IO_ACQUIRE_FOR_CCFLUSH FspAcquireForCcFlush;
|
|||||||
FAST_IO_RELEASE_FOR_CCFLUSH FspReleaseForCcFlush;
|
FAST_IO_RELEASE_FOR_CCFLUSH FspReleaseForCcFlush;
|
||||||
|
|
||||||
/* I/O queue */
|
/* I/O queue */
|
||||||
|
#define FspIoqTimeout ((PIRP)1)
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
KSPIN_LOCK SpinLock;
|
KSPIN_LOCK SpinLock;
|
||||||
@ -258,7 +259,7 @@ VOID FspIoqInitialize(FSP_IOQ *Ioq);
|
|||||||
VOID FspIoqStop(FSP_IOQ *Ioq);
|
VOID FspIoqStop(FSP_IOQ *Ioq);
|
||||||
BOOLEAN FspIoqStopped(FSP_IOQ *Ioq);
|
BOOLEAN FspIoqStopped(FSP_IOQ *Ioq);
|
||||||
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp);
|
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);
|
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp);
|
||||||
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint);
|
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint);
|
||||||
|
|
||||||
|
@ -353,6 +353,8 @@ static NTSTATUS FspFsvrtTransact(
|
|||||||
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;
|
PIRP ProcessIrp, PendingIrp;
|
||||||
|
ULONG TransactTimeout;
|
||||||
|
LARGE_INTEGER Timeout;
|
||||||
|
|
||||||
/* access check */
|
/* access check */
|
||||||
Result = FspSecuritySubjectContextAccessCheck(
|
Result = FspSecuritySubjectContextAccessCheck(
|
||||||
@ -380,12 +382,21 @@ static NTSTATUS FspFsvrtTransact(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* wait for an IRP to arrive */
|
/* wait for an IRP to arrive */
|
||||||
retry:
|
TransactTimeout = FsvrtDeviceExtension->VolumeParams.TransactTimeout;
|
||||||
while (0 == (PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, (ULONG)-1L)))
|
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))
|
if (FspIoqStopped(&FsvrtDeviceExtension->Ioq))
|
||||||
return STATUS_CANCELLED;
|
return STATUS_CANCELLED;
|
||||||
}
|
}
|
||||||
|
if (FspIoqTimeout == PendingIrp)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* send any pending IRP's to the user-mode file system */
|
/* send any pending IRP's to the user-mode file system */
|
||||||
Request = SystemBuffer;
|
Request = SystemBuffer;
|
||||||
@ -426,10 +437,6 @@ retry:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Request == SystemBuffer)
|
|
||||||
goto retry;
|
|
||||||
|
|
||||||
Irp->IoStatus.Information = (PUINT8)Request - (PUINT8)SystemBuffer;
|
Irp->IoStatus.Information = (PUINT8)Request - (PUINT8)SystemBuffer;
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
@ -209,17 +209,17 @@ BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp)
|
|||||||
return NT_SUCCESS(Result);
|
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;
|
NTSTATUS Result;
|
||||||
LARGE_INTEGER Timeout;
|
|
||||||
Timeout.QuadPart = (LONGLONG)millis * 10000;
|
|
||||||
Result = KeWaitForSingleObject(&Ioq->PendingIrpEvent, Executive, KernelMode, FALSE,
|
Result = KeWaitForSingleObject(&Ioq->PendingIrpEvent, Executive, KernelMode, FALSE,
|
||||||
-1 == millis ? 0 : &Timeout);
|
Timeout);
|
||||||
if (STATUS_SUCCESS != Result)
|
ASSERT(STATUS_SUCCESS == Result || STATUS_TIMEOUT == Result);
|
||||||
return 0;
|
if (STATUS_TIMEOUT == Result)
|
||||||
|
return FspIoqTimeout;
|
||||||
}
|
}
|
||||||
return IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, (PVOID)1);
|
return IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, (PVOID)1);
|
||||||
}
|
}
|
||||||
|
@ -194,13 +194,8 @@ void mount_volume_transact_dotest(PWSTR DeviceName)
|
|||||||
Response->Size = sizeof *Response;
|
Response->Size = sizeof *Response;
|
||||||
Response->Hint = Request->Hint;
|
Response->Hint = Request->Hint;
|
||||||
Response->Kind = Request->Kind;
|
Response->Kind = Request->Kind;
|
||||||
Response->IoStatus.Status = STATUS_SUCCESS;
|
Response->IoStatus.Status = STATUS_ACCESS_DENIED;
|
||||||
Response->IoStatus.Information = FILE_CREATED;
|
Response->IoStatus.Information = 0;
|
||||||
Response->Rsp.Create.Opened.UserContext = 41;
|
|
||||||
Response->Rsp.Create.Opened.UserContext2 = 42;
|
|
||||||
Response->Rsp.Create.Opened.FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
|
||||||
Response->Rsp.Create.Opened.SecurityDescriptor.Offset = 0;
|
|
||||||
Response->Rsp.Create.Opened.SecurityDescriptor.Size = 0;
|
|
||||||
|
|
||||||
Response = FspFsctlTransactProduceResponse(Response, Response->Size);
|
Response = FspFsctlTransactProduceResponse(Response, Response->Size);
|
||||||
ASSERT(0 != Response);
|
ASSERT(0 != Response);
|
||||||
@ -224,7 +219,7 @@ void mount_volume_transact_dotest(PWSTR DeviceName)
|
|||||||
GetExitCodeThread(Thread, &ExitCode);
|
GetExitCodeThread(Thread, &ExitCode);
|
||||||
CloseHandle(Thread);
|
CloseHandle(Thread);
|
||||||
|
|
||||||
ASSERT(0 == ExitCode);
|
ASSERT(ERROR_ACCESS_DENIED == ExitCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mount_volume_transact_test(void)
|
void mount_volume_transact_test(void)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user