|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 2/2] Clear SRB queue and Shutdown queue on reset
Fix a potential hang during TargetReset.
When the ring is disabled, any SRBs queued, but not submitted were left
in the queues. These SRBs would only be recovered when StorPort's internal
timeout triggered.
When the ring is scheduled and disabled, abort any SRBs that were not sent
to the backend, so that StorPort is responsible for requeueing any when the
ring is re-enabled. Disabling the ring will schedule the ring, aborting the
SRBs with SRB_STATUS_ABORTED, which will inform StorPort to re-issue the
requests when the target has recovered, rather than failing them.
Assisted-by: Claude:claude-opus-4.8
Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
src/xenvbd/ring.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 51 insertions(+), 1 deletion(-)
diff --git a/src/xenvbd/ring.c b/src/xenvbd/ring.c
index ffbd18a..0875ce9 100644
--- a/src/xenvbd/ring.c
+++ b/src/xenvbd/ring.c
@@ -1362,6 +1362,52 @@ BlkifRingSwizzle(
}
}
+static FORCEINLINE VOID
+__BlkifRingAbortQueues(
+ _In_ PXENVBD_BLKIF_RING BlkifRing
+ )
+{
+ ASSERT(!BlkifRing->Enabled);
+
+ // Complete any SRBs that were queued but never made it as far as the
+ // backend. Now that the ring is disabled the schedule thread will not
+ // run again, so without this these requests would be left stuck until
+ // StorPort times them out. First drain the atomic packet list into the
+ // SRB queue so that nothing accepted from a concurrent submitter is
+ // missed, then fail everything still pending. SRB_STATUS_ABORTED lets
+ // StorPort re-issue them once the target has recovered.
+
+ while (!IsListEmpty(&BlkifRing->SrbQueue)) {
+ PLIST_ENTRY ListEntry;
+ PXENVBD_SRBEXT SrbExt;
+ PSCSI_REQUEST_BLOCK Srb;
+
+ ListEntry = RemoveHeadList(&BlkifRing->SrbQueue);
+ ASSERT3P(ListEntry, !=, &BlkifRing->SrbQueue);
+
+ RtlZeroMemory(ListEntry, sizeof(LIST_ENTRY));
+
+ SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
+ Srb = SrbExt->Srb;
+ Srb->SrbStatus = SRB_STATUS_ABORTED;
+ __BlkifRingCompleteSrb(BlkifRing, SrbExt);
+ }
+
+ while (!IsListEmpty(&BlkifRing->ShutdownQueue)) {
+ PLIST_ENTRY ListEntry;
+ PXENVBD_SRBEXT SrbExt;
+ PSCSI_REQUEST_BLOCK Srb;
+
+ ListEntry = RemoveHeadList(&BlkifRing->ShutdownQueue);
+ ASSERT3P(ListEntry, !=, &BlkifRing->ShutdownQueue);
+
+ SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
+ Srb = SrbExt->Srb;
+ Srb->SrbStatus = SRB_STATUS_ABORTED;
+ __BlkifRingCompleteSrb(BlkifRing, SrbExt);
+ }
+}
+
static DECLSPEC_NOINLINE VOID
BlkifRingSchedule(
IN PXENVBD_BLKIF_RING BlkifRing
@@ -1369,8 +1415,10 @@ BlkifRingSchedule(
{
BOOLEAN Polled;
- if (!BlkifRing->Enabled)
+ if (!BlkifRing->Enabled) {
+ __BlkifRingAbortQueues(BlkifRing);
return;
+ }
Polled = FALSE;
@@ -2273,6 +2321,8 @@ BlkifRingDisable(
BlkifRing->Stopped = FALSE;
+ // __BlkifRingReleaseLock will call __BlkifRingAbortQueues now that
+ // Enabled = FALSE, completing unsubmitted SRBs with SRB_STATUS_ABORTED
__BlkifRingReleaseLock(BlkifRing);
Trace("<==== %u\n", BlkifRing->Index);
--
2.51.2.windows.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |