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
This commit is contained in:
parent
5fcb5ae8dc
commit
e35816c1c9
@ -1864,6 +1864,15 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb)
|
|||||||
targ = &sassc->targets[csio->ccb_h.target_id];
|
targ = &sassc->targets[csio->ccb_h.target_id];
|
||||||
mpr_dprint(sc, MPR_TRACE, "ccb %p target flag %x\n", ccb, targ->flags);
|
mpr_dprint(sc, MPR_TRACE, "ccb %p target flag %x\n", ccb, targ->flags);
|
||||||
if (targ->handle == 0x0) {
|
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",
|
mpr_dprint(sc, MPR_ERROR, "%s NULL handle for target %u\n",
|
||||||
__func__, csio->ccb_h.target_id);
|
__func__, csio->ccb_h.target_id);
|
||||||
mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
|
mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
|
||||||
|
@ -1637,6 +1637,15 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
|
|||||||
targ = &sassc->targets[csio->ccb_h.target_id];
|
targ = &sassc->targets[csio->ccb_h.target_id];
|
||||||
mps_dprint(sc, MPS_TRACE, "ccb %p target flag %x\n", ccb, targ->flags);
|
mps_dprint(sc, MPS_TRACE, "ccb %p target flag %x\n", ccb, targ->flags);
|
||||||
if (targ->handle == 0x0) {
|
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",
|
mps_dprint(sc, MPS_ERROR, "%s NULL handle for target %u\n",
|
||||||
__func__, csio->ccb_h.target_id);
|
__func__, csio->ccb_h.target_id);
|
||||||
mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
|
mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
|
||||||
|
Loading…
Reference in New Issue
Block a user