sys: FspIoqStop()

This commit is contained in:
Bill Zissimopoulos 2015-11-25 12:16:31 -08:00
parent 0f0b1f2c46
commit 6ba60198ab
3 changed files with 40 additions and 38 deletions

View File

@ -156,19 +156,18 @@ FAST_IO_RELEASE_FOR_CCFLUSH FspReleaseForCcFlush;
typedef struct typedef struct
{ {
KSPIN_LOCK SpinLock; KSPIN_LOCK SpinLock;
int Enabled; BOOLEAN Stopped;
KEVENT PendingIrpEvent; KEVENT PendingIrpEvent;
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);
BOOLEAN FspIoqEnabled(FSP_IOQ *Ioq); VOID FspIoqStop(FSP_IOQ *Ioq);
VOID FspIoqDisable(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, 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);
/* device extensions */ /* device extensions */
enum enum

View File

@ -151,10 +151,10 @@ static NTSTATUS FspFsvrtTransact(
Response = (PVOID)((PUINT8)Response + Response->Size); Response = (PVOID)((PUINT8)Response + Response->Size);
} }
/* wait for a pending IRP */ /* wait for an IRP to arrive */
while (0 == (PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, (ULONG)-1L))) while (0 == (PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, (ULONG)-1L)))
{ {
if (!FspIoqEnabled(&FsvrtDeviceExtension->Ioq)) if (FspIoqStopped(&FsvrtDeviceExtension->Ioq))
return STATUS_CANCELLED; return STATUS_CANCELLED;
} }
@ -169,10 +169,15 @@ static NTSTATUS FspFsvrtTransact(
if (!FspIoqStartProcessingIrp(&FsvrtDeviceExtension->Ioq, PendingIrp)) if (!FspIoqStartProcessingIrp(&FsvrtDeviceExtension->Ioq, PendingIrp))
{ {
/*
* This can only happen if the Ioq was stopped. Abandon everything
* and return STATUS_CANCELLED. Any IRP's in the Pending and Process
* queues of the Ioq will be cancelled during FspIoqStop(). We must
* also cancel the PendingIrp we have in our hands.
*/
ASSERT(FspIoqStopped(&FsvrtDeviceExtension->Ioq));
FspCompleteRequest(PendingIrp, STATUS_CANCELLED); FspCompleteRequest(PendingIrp, STATUS_CANCELLED);
if (!LoopedOnce) return STATUS_CANCELLED;
return STATUS_CANCELLED;
break;
} }
Request = PendingIrp->Tail.Overlay.DriverContext[0]; Request = PendingIrp->Tail.Overlay.DriverContext[0];

View File

@ -50,15 +50,15 @@
* *
* Event Object * Event Object
* *
* The FSP_IOQ includes a manual event object. The event object remains * The FSP_IOQ includes a manual event object. The event object becomes
* signaled when the FSP_IOQ object is disabled or when the Pending queue * signaled when the FSP_IOQ object is stopped or for as long as the Pending
* is not empty. * queue is not empty.
*/ */
static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext) static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext)
{ {
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq); FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq);
if (0 >= Ioq->Enabled) if (Ioq->Stopped)
return STATUS_ACCESS_DENIED; return STATUS_ACCESS_DENIED;
InsertTailList(&Ioq->PendingIrpList, &Irp->Tail.Overlay.ListEntry); InsertTailList(&Ioq->PendingIrpList, &Irp->Tail.Overlay.ListEntry);
/* list is not empty; wake up any waiters */ /* list is not empty; wake up any waiters */
@ -69,7 +69,7 @@ static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertCo
static VOID FspIoqPendingRemoveIrp(PIO_CSQ IoCsq, PIRP Irp) static VOID FspIoqPendingRemoveIrp(PIO_CSQ IoCsq, PIRP Irp)
{ {
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq); FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq);
if (RemoveEntryList(&Irp->Tail.Overlay.ListEntry) && 0 < Ioq->Enabled) if (RemoveEntryList(&Irp->Tail.Overlay.ListEntry) && !Ioq->Stopped)
/* list is empty; future threads should go to sleep */ /* list is empty; future threads should go to sleep */
KeClearEvent(&Ioq->PendingIrpEvent); KeClearEvent(&Ioq->PendingIrpEvent);
} }
@ -77,7 +77,7 @@ static VOID FspIoqPendingRemoveIrp(PIO_CSQ IoCsq, PIRP Irp)
static PIRP FspIoqPendingPeekNextIrp(PIO_CSQ IoCsq, PIRP Irp, PVOID PeekContext) static PIRP FspIoqPendingPeekNextIrp(PIO_CSQ IoCsq, PIRP Irp, PVOID PeekContext)
{ {
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq); FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq);
if (!PeekContext && 0 >= Ioq->Enabled) if (!PeekContext && Ioq->Stopped)
return 0; return 0;
PLIST_ENTRY Head = &Ioq->PendingIrpList; PLIST_ENTRY Head = &Ioq->PendingIrpList;
PLIST_ENTRY Entry = 0 == Irp ? Head->Flink : Irp->Tail.Overlay.ListEntry.Flink; PLIST_ENTRY Entry = 0 == Irp ? Head->Flink : Irp->Tail.Overlay.ListEntry.Flink;
@ -104,7 +104,7 @@ static VOID FspIoqPendingCompleteCanceledIrp(PIO_CSQ IoCsq, PIRP Irp)
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);
if (0 >= Ioq->Enabled) if (Ioq->Stopped)
return STATUS_ACCESS_DENIED; return STATUS_ACCESS_DENIED;
InsertTailList(&Ioq->ProcessIrpList, &Irp->Tail.Overlay.ListEntry); InsertTailList(&Ioq->ProcessIrpList, &Irp->Tail.Overlay.ListEntry);
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -118,10 +118,12 @@ static VOID FspIoqProcessRemoveIrp(PIO_CSQ IoCsq, PIRP Irp)
static PIRP FspIoqProcessPeekNextIrp(PIO_CSQ IoCsq, PIRP Irp, PVOID PeekContext) static PIRP FspIoqProcessPeekNextIrp(PIO_CSQ IoCsq, PIRP Irp, PVOID PeekContext)
{ {
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq); FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
if (!PeekContext && 0 >= Ioq->Enabled) if (!PeekContext && Ioq->Stopped)
return 0; return 0;
PLIST_ENTRY Head = &Ioq->ProcessIrpList; PLIST_ENTRY Head = &Ioq->ProcessIrpList;
PLIST_ENTRY Entry = 0 == Irp ? Head->Flink : Irp->Tail.Overlay.ListEntry.Flink; PLIST_ENTRY Entry = 0 == Irp ? Head->Flink : Irp->Tail.Overlay.ListEntry.Flink;
if (!PeekContext)
return Head != Entry ? CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry) : 0;
for (; Head != Entry; Entry = Entry->Flink) for (; Head != Entry; Entry = Entry->Flink)
{ {
Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
@ -169,28 +171,33 @@ VOID FspIoqInitialize(FSP_IOQ *Ioq)
FspIoqProcessAcquireLock, FspIoqProcessAcquireLock,
FspIoqProcessReleaseLock, FspIoqProcessReleaseLock,
FspIoqProcessCompleteCanceledIrp); FspIoqProcessCompleteCanceledIrp);
Ioq->Enabled = 1;
} }
BOOLEAN FspIoqEnabled(FSP_IOQ *Ioq) VOID FspIoqStop(FSP_IOQ *Ioq)
{
KIRQL Irql;
KeAcquireSpinLock(&Ioq->SpinLock, &Irql);
Ioq->Stopped = TRUE;
/* we are being stopped, permanently wake up waiters */
KeSetEvent(&Ioq->PendingIrpEvent, 1, FALSE);
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
PIRP Irp;
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, 0)))
FspIoqPendingCompleteCanceledIrp(&Ioq->PendingIoCsq, Irp);
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->ProcessIoCsq, 0)))
FspIoqProcessCompleteCanceledIrp(&Ioq->ProcessIoCsq, Irp);
}
BOOLEAN FspIoqStopped(FSP_IOQ *Ioq)
{ {
BOOLEAN Result; BOOLEAN Result;
KIRQL Irql; KIRQL Irql;
KeAcquireSpinLock(&Ioq->SpinLock, &Irql); KeAcquireSpinLock(&Ioq->SpinLock, &Irql);
Result = 0 < Ioq->Enabled; Result = Ioq->Stopped;
KeReleaseSpinLock(&Ioq->SpinLock, Irql); KeReleaseSpinLock(&Ioq->SpinLock, Irql);
return Result; return Result;
} }
VOID FspIoqDisable(FSP_IOQ *Ioq)
{
KIRQL Irql;
KeAcquireSpinLock(&Ioq->SpinLock, &Irql);
Ioq->Enabled = 0;
KeSetEvent(&Ioq->PendingIrpEvent, 1, FALSE);
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
}
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp) BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp)
{ {
NTSTATUS Result; NTSTATUS Result;
@ -224,12 +231,3 @@ PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint)
{ {
return IoCsqRemoveNextIrp(&Ioq->ProcessIoCsq, (PVOID)IrpHint); return IoCsqRemoveNextIrp(&Ioq->ProcessIoCsq, (PVOID)IrpHint);
} }
VOID FspIoqCancelAll(FSP_IOQ *Ioq)
{
PIRP Irp;
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, 0)))
FspIoqPendingCompleteCanceledIrp(&Ioq->PendingIoCsq, Irp);
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->ProcessIoCsq, 0)))
FspIoqProcessCompleteCanceledIrp(&Ioq->ProcessIoCsq, Irp);
}