mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-26 02:12:45 -05:00
sys: ioq: control pending queue with semaphore
This commit is contained in:
parent
50f2ba8cee
commit
e688a98ca9
@ -149,13 +149,14 @@ typedef struct
|
|||||||
{
|
{
|
||||||
KSPIN_LOCK SpinLock;
|
KSPIN_LOCK SpinLock;
|
||||||
int Enabled;
|
int Enabled;
|
||||||
|
KSEMAPHORE PendingSemaphore;
|
||||||
LIST_ENTRY PendingIrpList, ProcessIrpList;
|
LIST_ENTRY PendingIrpList, ProcessIrpList;
|
||||||
IO_CSQ PendingIoCsq, ProcessIoCsq;
|
IO_CSQ PendingIoCsq, ProcessIoCsq;
|
||||||
} FSP_IOQ;
|
} FSP_IOQ;
|
||||||
VOID FspIoqInitialize(FSP_IOQ *Ioq);
|
VOID FspIoqInitialize(FSP_IOQ *Ioq);
|
||||||
VOID FspIoqEnable(FSP_IOQ *Ioq, int Delta);
|
VOID FspIoqEnable(FSP_IOQ *Ioq, int Delta);
|
||||||
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp);
|
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp);
|
||||||
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq);
|
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, ULONG millis);
|
||||||
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);
|
||||||
VOID FspIoqCancelAll(FSP_IOQ *Ioq);
|
VOID FspIoqCancelAll(FSP_IOQ *Ioq);
|
||||||
|
@ -8,20 +8,20 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* An FSP_IOQ encapsulates the main FSP mechanism for handling IRP's.
|
* An FSP_IOQ encapsulates the main FSP mechanism for handling IRP's.
|
||||||
* It has two queues: a "pending" queue for managing newly arrived IRP's
|
* It has two queues: a "Pending" queue for managing newly arrived IRP's
|
||||||
* and a "processing" queue for managing IRP's currently being processed
|
* and a "Processing" queue for managing IRP's currently being processed
|
||||||
* (i.e. sent to the user-mode file system for further processing).
|
* (i.e. sent to the user-mode file system for further processing).
|
||||||
*
|
*
|
||||||
* IRP's arrive at a MajorFunction (MJ) and are then posted to the device's
|
* IRP's arrive at a MajorFunction (MJ) and are then posted to the device's
|
||||||
* FSP_IOQ and marked pending. When the user-mode file system performs
|
* FSP_IOQ and marked pending. When the user-mode file system performs
|
||||||
* FSP_FSCTL_TRANSACT, the IRP's are removed from the pending queue and
|
* FSP_FSCTL_TRANSACT, the IRP's are removed from the Pending queue and
|
||||||
* are then marshalled to the user process; prior to that they are added
|
* are then marshalled to the user process; prior to that they are added
|
||||||
* to the processing queue. At a later time the user-mode will perform
|
* to the Processing queue. At a later time the user-mode will perform
|
||||||
* another FSP_FSCTL_TRANSACT at which time any processed IRP's will be
|
* another FSP_FSCTL_TRANSACT at which time any processed IRP's will be
|
||||||
* marshalled back to us and will be then removed from the processing queue
|
* marshalled back to us and will be then removed from the Processing queue
|
||||||
* and completed.
|
* and completed.
|
||||||
*
|
*
|
||||||
* State diagram:
|
* IRP State diagram:
|
||||||
* +--------------------+
|
* +--------------------+
|
||||||
* | | | StartProcessingIrp
|
* | | | StartProcessingIrp
|
||||||
* v | v
|
* v | v
|
||||||
@ -36,13 +36,18 @@
|
|||||||
* +------------+ | | IN |
|
* +------------+ | | IN |
|
||||||
* | | +------------+
|
* | | +------------+
|
||||||
* | NextPendingIrp | |
|
* | NextPendingIrp | |
|
||||||
* v | | CompleteIrp
|
* v | | CompleteRequest
|
||||||
* +------------+ | v
|
* +------------+ | v
|
||||||
* | TRANSACT | | +------------+
|
* | TRANSACT | | +------------+
|
||||||
* | OUT | | | Completed |
|
* | OUT | | | Completed |
|
||||||
* +------------+ | +------------+
|
* +------------+ | +------------+
|
||||||
* | |
|
* | |
|
||||||
* +---------------------+
|
* +---------------------+
|
||||||
|
*
|
||||||
|
* Note that the Pending queue is controlled by a semaphore object, which
|
||||||
|
* counts how many IRP's are in the queue. The semaphore is incremented for
|
||||||
|
* every IRP that is inserted into the Pending queue and decremented every
|
||||||
|
* time an IRP is removed from the Pending queue.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext)
|
static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext)
|
||||||
@ -52,7 +57,11 @@ static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertCo
|
|||||||
if (0 > Ioq->Enabled)
|
if (0 > Ioq->Enabled)
|
||||||
return STATUS_ACCESS_DENIED;
|
return STATUS_ACCESS_DENIED;
|
||||||
|
|
||||||
|
/* SpinLock: acquired, IRQL: DISPATCH_LEVEL */
|
||||||
InsertTailList(&Ioq->PendingIrpList, &Irp->Tail.Overlay.ListEntry);
|
InsertTailList(&Ioq->PendingIrpList, &Irp->Tail.Overlay.ListEntry);
|
||||||
|
KeReleaseSemaphore(&Ioq->PendingSemaphore, FSP_IO_INCREMENT, 1, FALSE);
|
||||||
|
/* KeReleaseSemaphore allowed at DISPATCH_LEVEL with Wait==FALSE */
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +99,16 @@ static VOID FspIoqPendingReleaseLock(PIO_CSQ IoCsq, KIRQL Irql)
|
|||||||
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
|
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID FspIoqPendingCompleteCanceledIrp(PIO_CSQ IoCsq, PIRP Irp)
|
||||||
|
{
|
||||||
|
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq);
|
||||||
|
LARGE_INTEGER Timeout = { 0 };
|
||||||
|
|
||||||
|
/* SpinLock: not acquired */
|
||||||
|
KeWaitForSingleObject(&Ioq->PendingSemaphore, Executive, KernelMode, FALSE, &Timeout);
|
||||||
|
FspCompleteRequest(Irp, STATUS_CANCELLED);
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspIoqProcessInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext)
|
static NTSTATUS FspIoqProcessInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext)
|
||||||
{
|
{
|
||||||
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
|
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
|
||||||
@ -142,7 +161,7 @@ static VOID FspIoqProcessReleaseLock(PIO_CSQ IoCsq, KIRQL Irql)
|
|||||||
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
|
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID FspIoqCompleteCanceledIrp(PIO_CSQ IoCsq, PIRP Irp)
|
static VOID FspIoqProcessCompleteCanceledIrp(PIO_CSQ IoCsq, PIRP Irp)
|
||||||
{
|
{
|
||||||
FspCompleteRequest(Irp, STATUS_CANCELLED);
|
FspCompleteRequest(Irp, STATUS_CANCELLED);
|
||||||
}
|
}
|
||||||
@ -151,6 +170,7 @@ VOID FspIoqInitialize(FSP_IOQ *Ioq)
|
|||||||
{
|
{
|
||||||
RtlZeroMemory(Ioq, sizeof *Ioq);
|
RtlZeroMemory(Ioq, sizeof *Ioq);
|
||||||
KeInitializeSpinLock(&Ioq->SpinLock);
|
KeInitializeSpinLock(&Ioq->SpinLock);
|
||||||
|
KeInitializeSemaphore(&Ioq->PendingSemaphore, 0, 1000000000);
|
||||||
InitializeListHead(&Ioq->PendingIrpList);
|
InitializeListHead(&Ioq->PendingIrpList);
|
||||||
InitializeListHead(&Ioq->ProcessIrpList);
|
InitializeListHead(&Ioq->ProcessIrpList);
|
||||||
IoCsqInitializeEx(&Ioq->PendingIoCsq,
|
IoCsqInitializeEx(&Ioq->PendingIoCsq,
|
||||||
@ -159,14 +179,14 @@ VOID FspIoqInitialize(FSP_IOQ *Ioq)
|
|||||||
FspIoqPendingPeekNextIrp,
|
FspIoqPendingPeekNextIrp,
|
||||||
FspIoqPendingAcquireLock,
|
FspIoqPendingAcquireLock,
|
||||||
FspIoqPendingReleaseLock,
|
FspIoqPendingReleaseLock,
|
||||||
FspIoqCompleteCanceledIrp);
|
FspIoqPendingCompleteCanceledIrp);
|
||||||
IoCsqInitializeEx(&Ioq->ProcessIoCsq,
|
IoCsqInitializeEx(&Ioq->ProcessIoCsq,
|
||||||
FspIoqProcessInsertIrpEx,
|
FspIoqProcessInsertIrpEx,
|
||||||
FspIoqProcessRemoveIrp,
|
FspIoqProcessRemoveIrp,
|
||||||
FspIoqProcessPeekNextIrp,
|
FspIoqProcessPeekNextIrp,
|
||||||
FspIoqProcessAcquireLock,
|
FspIoqProcessAcquireLock,
|
||||||
FspIoqProcessReleaseLock,
|
FspIoqProcessReleaseLock,
|
||||||
FspIoqCompleteCanceledIrp);
|
FspIoqProcessCompleteCanceledIrp);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID FspIoqEnable(FSP_IOQ *Ioq, int Delta)
|
VOID FspIoqEnable(FSP_IOQ *Ioq, int Delta)
|
||||||
@ -179,29 +199,49 @@ VOID FspIoqEnable(FSP_IOQ *Ioq, int Delta)
|
|||||||
|
|
||||||
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp)
|
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp)
|
||||||
{
|
{
|
||||||
return STATUS_SUCCESS == IoCsqInsertIrpEx(&Ioq->PendingIoCsq, Irp, 0, 0);
|
NTSTATUS Result;
|
||||||
|
Result = IoCsqInsertIrpEx(&Ioq->PendingIoCsq, Irp, 0, 0);
|
||||||
|
return NT_SUCCESS(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq)
|
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, ULONG millis)
|
||||||
{
|
{
|
||||||
return IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, (PVOID)1);
|
NTSTATUS Result;
|
||||||
|
LARGE_INTEGER Timeout;
|
||||||
|
PIRP Irp;
|
||||||
|
|
||||||
|
Timeout.QuadPart = (LONGLONG)millis * 10000;
|
||||||
|
Result = KeWaitForSingleObject(&Ioq->PendingSemaphore, Executive, KernelMode, FALSE,
|
||||||
|
-1 == millis ? 0 : &Timeout);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Irp = IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, (PVOID)1);
|
||||||
|
|
||||||
|
if (0 == Irp)
|
||||||
|
/* signal the semaphore again; turns out we did not get an IRP! */
|
||||||
|
KeReleaseSemaphore(&Ioq->PendingSemaphore, FSP_IO_INCREMENT, 1, FALSE);
|
||||||
|
|
||||||
|
return Irp;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp)
|
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp)
|
||||||
{
|
{
|
||||||
return STATUS_SUCCESS == IoCsqInsertIrpEx(&Ioq->ProcessIoCsq, Irp, 0, 0);
|
NTSTATUS Result;
|
||||||
|
Result = IoCsqInsertIrpEx(&Ioq->ProcessIoCsq, Irp, 0, 0);
|
||||||
|
return NT_SUCCESS(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint)
|
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint)
|
||||||
{
|
{
|
||||||
return IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, (PVOID)IrpHint);
|
return IoCsqRemoveNextIrp(&Ioq->ProcessIoCsq, (PVOID)IrpHint);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID FspIoqCancelAll(FSP_IOQ *Ioq)
|
VOID FspIoqCancelAll(FSP_IOQ *Ioq)
|
||||||
{
|
{
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, 0)))
|
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, 0)))
|
||||||
FspCompleteRequest(Irp, STATUS_CANCELLED);
|
FspIoqPendingCompleteCanceledIrp(&Ioq->PendingIoCsq, Irp);
|
||||||
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->ProcessIoCsq, 0)))
|
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->ProcessIoCsq, 0)))
|
||||||
FspCompleteRequest(Irp, STATUS_CANCELLED);
|
FspIoqProcessCompleteCanceledIrp(&Ioq->ProcessIoCsq, Irp);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user