DF-4562 / fix.diff
--- a/sys/dev/raid/mps/mps_sas_lsi.c +++ b/sys/dev/raid/mps/mps_sas_lsi.c @@ -650,6 +650,18 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ if (id == MPS_MAP_BAD_ID) { ... } targ = &sassc->targets[id]; + /* + * DF-4562 hardening: never re-initialize a target slot that is still + * being removed asynchronously (mpssas_prepare_remove's TM has not + * completed) or that still owns commands — TAILQ_INIT would orphan + * them and the completion path would corrupt the re-initialized list. + */ + if (targ->handle != 0 && + ((targ->flags & MPSSAS_TARGET_INREMOVAL) || + !TAILQ_EMPTY(&targ->commands) || + !TAILQ_EMPTY(&targ->timedout_commands) || + targ->tm != NULL)) { + kprintf("%s: target id %d busy (removal in flight); refusing " + "re-add of handle 0x%04x\n", __func__, id, handle); + error = EBUSY; + goto out; + } targ->devinfo = device_info; @@ -845,6 +857,14 @@ mpssas_volume_add(struct mps_softc *sc, u16 handle) targ = &sassc->targets[id]; + if (targ->handle != 0 && + ((targ->flags & MPSSAS_TARGET_INREMOVAL) || + !TAILQ_EMPTY(&targ->commands) || + !TAILQ_EMPTY(&targ->timedout_commands) || + targ->tm != NULL)) { + error = EBUSY; + goto out; + } targ->tid = id; NOTE: defensive sketch only (speculative finding DF-4562) — context lines are abbreviated; not applied to sys/. |