git: e35816c1c909 - main - mpr/mps: Fix a race in diagnostic reset
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 26 Jan 2022 02:16:11 UTC
The branch main has been updated by imp:
URL: https://cgit.FreeBSD.org/src/commit/?id=e35816c1c9094804f5a4b5f7b34f920f78cff5bd
commit e35816c1c9094804f5a4b5f7b34f920f78cff5bd
Author: Warner Losh <imp@FreeBSD.org>
AuthorDate: 2022-01-25 23:23:03 +0000
Commit: Warner Losh <imp@FreeBSD.org>
CommitDate: 2022-01-26 02:15:46 +0000
mpr/mps: Fix a race in diagnostic reset
There's a small race in freezing the simq when performing a diagnostic
reset. During this time, a transaction can slip through and encounter
the target id of 0. If we're still in diagnostic reset when we detect
this, return a CAM_DEVICE_NOT_THERE status. Instead, freeze the queue
and return a requeue status, similar to what we do when we're resetting
a target and a transaction get here. The race is unavoidable due to
separate locks for queue and SIM, but easy enough to detect and make
harmless.
Sponsored by: Netflix
Reviewed by: scottl, mav
Differential Revision: https://reviews.freebsd.org/D34017
---
sys/dev/mpr/mpr_sas.c | 9 +++++++++
sys/dev/mps/mps_sas.c | 9 +++++++++
2 files changed, 18 insertions(+)
diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c
index 4a8dccb18538..d40900e03108 100644
--- a/sys/dev/mpr/mpr_sas.c
+++ b/sys/dev/mpr/mpr_sas.c
@@ -1864,6 +1864,15 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb)
targ = &sassc->targets[csio->ccb_h.target_id];
mpr_dprint(sc, MPR_TRACE, "ccb %p target flag %x\n", ccb, targ->flags);
if (targ->handle == 0x0) {
+ if (targ->flags & MPRSAS_TARGET_INDIAGRESET) {
+ mpr_dprint(sc, MPR_ERROR,
+ "%s NULL handle for target %u in diag reset freezing queue\n",
+ __func__, csio->ccb_h.target_id);
+ ccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_DEV_QFRZN;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ xpt_done(ccb);
+ return;
+ }
mpr_dprint(sc, MPR_ERROR, "%s NULL handle for target %u\n",
__func__, csio->ccb_h.target_id);
mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c
index e55c4978208a..087988bedc6a 100644
--- a/sys/dev/mps/mps_sas.c
+++ b/sys/dev/mps/mps_sas.c
@@ -1637,6 +1637,15 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
targ = &sassc->targets[csio->ccb_h.target_id];
mps_dprint(sc, MPS_TRACE, "ccb %p target flag %x\n", ccb, targ->flags);
if (targ->handle == 0x0) {
+ if (targ->flags & MPSSAS_TARGET_INDIAGRESET) {
+ mps_dprint(sc, MPS_ERROR,
+ "%s NULL handle for target %u in diag reset freezing queue\n",
+ __func__, csio->ccb_h.target_id);
+ ccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_DEV_QFRZN;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ xpt_done(ccb);
+ return;
+ }
mps_dprint(sc, MPS_ERROR, "%s NULL handle for target %u\n",
__func__, csio->ccb_h.target_id);
mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);