mirror of
https://github.com/winfsp/winfsp.git
synced 2025-06-15 00:02:46 -05:00
sys: ioq: implement IRP capacity
This commit is contained in:
@ -289,7 +289,8 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
/* setup our Ioq and expiration fields */
|
||||
IrpTimeout.QuadPart = FsvolDeviceExtension->VolumeParams.IrpTimeout * 10000;
|
||||
/* convert millis to nanos */
|
||||
FspIoqInitialize(&FsvolDeviceExtension->Ioq, &IrpTimeout, FspIopCompleteCanceledIrp);
|
||||
FspIoqInitialize(&FsvolDeviceExtension->Ioq,
|
||||
&IrpTimeout, FsvolDeviceExtension->VolumeParams.IrpCapacity, FspIopCompleteCanceledIrp);
|
||||
KeInitializeSpinLock(&FsvolDeviceExtension->ExpirationLock);
|
||||
ExInitializeWorkItem(&FsvolDeviceExtension->ExpirationWorkItem,
|
||||
FspFsvolDeviceExpirationRoutine, DeviceObject);
|
||||
|
@ -127,12 +127,8 @@ extern __declspec(selectany) int bpglobal = 1;
|
||||
/* if the IRP has not been marked pending already */\
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =\
|
||||
FspFsvolDeviceExtension(DeviceObject);\
|
||||
if (!FspIoqPostIrp(&FsvolDeviceExtension->Ioq, Irp))\
|
||||
{ \
|
||||
/* this can only happen if the Ioq was stopped */\
|
||||
ASSERT(FspIoqStopped(&FsvolDeviceExtension->Ioq));\
|
||||
FspIopCompleteIrp(Irp, Result = STATUS_CANCELLED);\
|
||||
} \
|
||||
if (!FspIoqPostIrp(&FsvolDeviceExtension->Ioq, Irp, &Result))\
|
||||
FspIopCompleteIrp(Irp, Result);\
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
@ -306,14 +302,15 @@ typedef struct
|
||||
LIST_ENTRY PendingIrpList, ProcessIrpList;
|
||||
IO_CSQ PendingIoCsq, ProcessIoCsq;
|
||||
LARGE_INTEGER IrpTimeout;
|
||||
ULONG PendingIrpCapacity, PendingIrpCount;
|
||||
VOID (*CompleteCanceledIrp)(PIRP Irp);
|
||||
} FSP_IOQ;
|
||||
VOID FspIoqInitialize(FSP_IOQ *Ioq,
|
||||
PLARGE_INTEGER IrpTimeout, VOID (*CompleteCanceledIrp)(PIRP Irp));
|
||||
PLARGE_INTEGER IrpTimeout, ULONG IrpCapacity, VOID (*CompleteCanceledIrp)(PIRP Irp));
|
||||
VOID FspIoqStop(FSP_IOQ *Ioq);
|
||||
BOOLEAN FspIoqStopped(FSP_IOQ *Ioq);
|
||||
VOID FspIoqRemoveExpired(FSP_IOQ *Ioq);
|
||||
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp);
|
||||
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp, NTSTATUS *PResult);
|
||||
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout);
|
||||
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp);
|
||||
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint);
|
||||
|
@ -65,7 +65,10 @@ static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertCo
|
||||
{
|
||||
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq);
|
||||
if (Ioq->Stopped)
|
||||
return STATUS_ACCESS_DENIED;
|
||||
return STATUS_CANCELLED;
|
||||
if (InsertContext && Ioq->PendingIrpCapacity <= Ioq->PendingIrpCount)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
Ioq->PendingIrpCount++;
|
||||
InsertTailList(&Ioq->PendingIrpList, &Irp->Tail.Overlay.ListEntry);
|
||||
/* list is not empty; wake up any waiters */
|
||||
KeSetEvent(&Ioq->PendingIrpEvent, 1, FALSE);
|
||||
@ -75,6 +78,7 @@ static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertCo
|
||||
static VOID FspIoqPendingRemoveIrp(PIO_CSQ IoCsq, PIRP Irp)
|
||||
{
|
||||
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq);
|
||||
Ioq->PendingIrpCount--;
|
||||
if (RemoveEntryList(&Irp->Tail.Overlay.ListEntry) && !Ioq->Stopped)
|
||||
/* list is empty; future threads should go to sleep */
|
||||
KeClearEvent(&Ioq->PendingIrpEvent);
|
||||
@ -128,7 +132,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_ACCESS_DENIED;
|
||||
return STATUS_CANCELLED;
|
||||
InsertTailList(&Ioq->ProcessIrpList, &Irp->Tail.Overlay.ListEntry);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@ -189,7 +193,7 @@ static VOID FspIoqProcessCompleteCanceledIrp(PIO_CSQ IoCsq, PIRP Irp)
|
||||
}
|
||||
|
||||
VOID FspIoqInitialize(FSP_IOQ *Ioq,
|
||||
PLARGE_INTEGER IrpTimeout, VOID (*CompleteCanceledIrp)(PIRP Irp))
|
||||
PLARGE_INTEGER IrpTimeout, ULONG IrpCapacity, VOID (*CompleteCanceledIrp)(PIRP Irp))
|
||||
{
|
||||
ASSERT(0 != CompleteCanceledIrp);
|
||||
|
||||
@ -213,6 +217,7 @@ VOID FspIoqInitialize(FSP_IOQ *Ioq,
|
||||
FspIoqProcessReleaseLock,
|
||||
FspIoqProcessCompleteCanceledIrp);
|
||||
Ioq->IrpTimeout = *IrpTimeout;
|
||||
Ioq->PendingIrpCapacity = IrpCapacity;
|
||||
Ioq->CompleteCanceledIrp = CompleteCanceledIrp;
|
||||
}
|
||||
|
||||
@ -253,13 +258,16 @@ VOID FspIoqRemoveExpired(FSP_IOQ *Ioq)
|
||||
Ioq->CompleteCanceledIrp(Irp);
|
||||
}
|
||||
|
||||
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp)
|
||||
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp, NTSTATUS *PResult)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
if (0 == FspIrpTimestamp(Irp))
|
||||
FspIrpTimestamp(Irp) = KeQueryInterruptTime() + Ioq->IrpTimeout.QuadPart;
|
||||
Result = IoCsqInsertIrpEx(&Ioq->PendingIoCsq, Irp, 0, 0);
|
||||
return NT_SUCCESS(Result);
|
||||
FspIrpTimestamp(Irp) = KeQueryInterruptTime() + Ioq->IrpTimeout.QuadPart;
|
||||
Result = IoCsqInsertIrpEx(&Ioq->PendingIoCsq, Irp, 0, (PVOID)1);
|
||||
if (NT_SUCCESS(Result))
|
||||
return TRUE;
|
||||
if (0 != PResult)
|
||||
*PResult = Result;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout)
|
||||
@ -283,8 +291,6 @@ PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout)
|
||||
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
if (0 == FspIrpTimestamp(Irp))
|
||||
FspIrpTimestamp(Irp) = KeQueryInterruptTime() + Ioq->IrpTimeout.QuadPart;
|
||||
Result = IoCsqInsertIrpEx(&Ioq->ProcessIoCsq, Irp, 0, 0);
|
||||
return NT_SUCCESS(Result);
|
||||
}
|
||||
|
@ -58,6 +58,9 @@ NTSTATUS FspVolumeCreate(
|
||||
ASSERT(0 == FileObject->RelatedFileObject);
|
||||
ASSERT(PREFIXW_SIZE <= FileObject->FileName.Length &&
|
||||
RtlEqualMemory(PREFIXW, FileObject->FileName.Buffer, PREFIXW_SIZE));
|
||||
ASSERT(
|
||||
FILE_DEVICE_DISK_FILE_SYSTEM == FsctlDeviceObject->DeviceType ||
|
||||
FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType);
|
||||
|
||||
/* check parameters */
|
||||
if (PREFIXW_SIZE + sizeof(FSP_FSCTL_VOLUME_PARAMS) * sizeof(WCHAR) > FileObject->FileName.Length)
|
||||
@ -73,6 +76,9 @@ NTSTATUS FspVolumeCreate(
|
||||
}
|
||||
|
||||
/* check the VolumeParams */
|
||||
if (FspFsctlTransactTimeoutMinimum > VolumeParams.TransactTimeout ||
|
||||
VolumeParams.TransactTimeout > FspFsctlTransactTimeoutMaximum)
|
||||
VolumeParams.TransactTimeout = FspFsctlTransactTimeoutDefault;
|
||||
if (FspFsctlIrpTimeoutMinimum > VolumeParams.IrpTimeout ||
|
||||
VolumeParams.IrpTimeout > FspFsctlIrpTimeoutMaximum)
|
||||
{
|
||||
@ -82,16 +88,18 @@ NTSTATUS FspVolumeCreate(
|
||||
#endif
|
||||
VolumeParams.IrpTimeout = FspFsctlIrpTimeoutDefault;
|
||||
}
|
||||
if (FspFsctlTransactTimeoutMinimum > VolumeParams.TransactTimeout ||
|
||||
VolumeParams.TransactTimeout > FspFsctlTransactTimeoutMaximum)
|
||||
VolumeParams.TransactTimeout = FspFsctlTransactTimeoutDefault;
|
||||
if (FspFsctlIrpCapacityMinimum > VolumeParams.IrpCapacity ||
|
||||
VolumeParams.IrpCapacity > FspFsctlIrpCapacityMaximum)
|
||||
VolumeParams.IrpCapacity = FspFsctlIrpCapacityDefault;
|
||||
VolumeParams.Prefix[sizeof VolumeParams.Prefix / 2 - 1] = L'\0';
|
||||
while (L'\0' != VolumeParams.Prefix[PrefixLength++])
|
||||
;
|
||||
while (0 < PrefixLength && L'\\' == VolumeParams.Prefix[--PrefixLength])
|
||||
;
|
||||
VolumeParams.Prefix[PrefixLength] = L'\0';
|
||||
if (0 == PrefixLength)
|
||||
if (FILE_DEVICE_DISK_FILE_SYSTEM == FsctlDeviceObject->DeviceType && 0 != PrefixLength)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType && 0 == PrefixLength)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* create volume guid */
|
||||
@ -575,15 +583,10 @@ NTSTATUS FspVolumeWork(
|
||||
* so that we can disassociate the Request on failure and release ownership
|
||||
* back to the caller.
|
||||
*/
|
||||
if (!FspIoqPostIrp(&FsvolDeviceExtension->Ioq, Irp))
|
||||
if (!FspIoqPostIrp(&FsvolDeviceExtension->Ioq, Irp, &Result))
|
||||
{
|
||||
/* this can only happen if the Ioq was stopped */
|
||||
ASSERT(FspIoqStopped(&FsvolDeviceExtension->Ioq));
|
||||
|
||||
Request->Hint = 0;
|
||||
FspIrpRequest(Irp) = 0;
|
||||
|
||||
Result = STATUS_CANCELLED;
|
||||
}
|
||||
else
|
||||
Result = STATUS_PENDING;
|
||||
|
Reference in New Issue
Block a user