sys: FspFsvrtTransact: now has timeout

This commit is contained in:
Bill Zissimopoulos 2015-12-14 12:36:40 -08:00
parent 5d6d938039
commit aee12e1c5f
5 changed files with 32 additions and 22 deletions

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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);
} }

View File

@ -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)