diff --git a/sys/dev/raid/mps/mps_sas.c b/sys/dev/raid/mps/mps_sas.c index 1111111..2222222 100644 --- a/sys/dev/raid/mps/mps_sas.c +++ b/sys/dev/raid/mps/mps_sas.c @@ -1300,10 +1300,24 @@ mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type) int err; target = tm->cm_targ; if (target->handle == 0) { mps_printf(sc, "%s null devhandle for target_id %d\n", __func__, target->tid); + /* DF-3895: unwinding is mandatory — returning without it + * wedges the target forever (targ->tm stays set, timedout + * commands are never completed) and leaks the TM. */ + target->tm = NULL; + mpssas_free_tm(sc, tm); + { + struct mps_command *tcm, *tnext; + TAILQ_FOREACH_MUTABLE(tcm, &target->timedout_commands, + cm_recovery, tnext) { + union ccb *tccb = tcm->cm_complete_data; + TAILQ_REMOVE(&target->timedout_commands, tcm, + cm_recovery); + tcm->cm_state = MPS_CM_STATE_BUSY; + tccb->ccb_h.status = CAM_DEV_NOT_THERE; + mpssas_scsiio_complete(sc, tcm); + } + } return -1; } req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; diff --git a/sys/dev/raid/mps/mps_sas.c b/sys/dev/raid/mps/mps_sas.c index 1111111..3333333 100644 --- a/sys/dev/raid/mps/mps_sas.c +++ b/sys/dev/raid/mps/mps_sas.c @@ -1440,10 +1440,25 @@ mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm) int err; targ = cm->cm_targ; if (targ->handle == 0) { mps_printf(sc, "%s null devhandle for target_id %d\n", __func__, cm->cm_ccb->ccb_h.target_id); + /* DF-3895: same unwind as mpssas_send_reset. */ + targ->tm = NULL; + mpssas_free_tm(sc, tm); + { + struct mps_command *tcm, *tnext; + TAILQ_FOREACH_MUTABLE(tcm, &targ->timedout_commands, + cm_recovery, tnext) { + union ccb *tccb = tcm->cm_complete_data; + TAILQ_REMOVE(&targ->timedout_commands, tcm, + cm_recovery); + tcm->cm_state = MPS_CM_STATE_BUSY; + tccb->ccb_h.status = CAM_DEV_NOT_THERE; + mpssas_scsiio_complete(sc, tcm); + } + } return -1; } req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; diff --git a/sys/dev/raid/mps/mps_sas.c b/sys/dev/raid/mps/mps_sas.c index 1111111..4444444 100644 --- a/sys/dev/raid/mps/mps_sas.c +++ b/sys/dev/raid/mps/mps_sas.c @@ -384,6 +384,19 @@ mpssas_remove_volume(struct mps_softc *sc, struct mps_command *tm) targ->linkrate = 0x0; targ->devinfo = 0x0; targ->flags = 0x0; + + /* DF-3895: drain outstanding commands exactly like + * mpssas_remove_device does; otherwise later timeouts on + * this dead volume wedge error recovery in + * mpssas_send_abort's handle==0 path. */ + TAILQ_FOREACH_MUTABLE(cm, &targ->commands, cm_link, next_cm) { + union ccb *ccb; + + ccb = cm->cm_complete_data; + ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mpssas_scsiio_complete(sc, cm); + } } mpssas_free_tm(sc, tm); *** NOTE: the third hunk requires promoting `next_cm` in *** mpssas_remove_volume's declarations *** (struct mps_command *next_cm, *cm;) — mps_sas.c:350-352 currently *** declares only `reply`/`targ`/`handle`; the function-local shadow of the *** remove_device pattern (cf. mps_sas.c:592-599) is intended.