DF-5057 / fix.diff
--- a/sys/dev/raid/mlx/mlx.c +++ b/sys/dev/raid/mlx/mlx.c @@ -783,6 +783,11 @@ error = EBUSY; goto detach_out; } + + /* DF-5057: block new opens while we flush/delete; mlx_flush sleeps + * (polled round-trip), so mlxd_open's MLX_STATE_SHUTDOWN gate must + * be raised for the whole window, not just around the delete. */ + sc->mlx_state |= MLX_STATE_SHUTDOWN; /* flush controller */ if (mlx_flush(sc)) { @@ -796,6 +801,9 @@ dr->ms_disk = NULL; detach_out: + /* single-drive detach: the controller keeps running afterwards */ + sc->mlx_state &= ~MLX_STATE_SHUTDOWN; + if (error) { kprintf("failed\n"); } else { --- a/sys/dev/raid/mlx/mlx_disk.c +++ b/sys/dev/raid/mlx/mlx_disk.c @@ -40,6 +40,7 @@ #include <sys/disk.h> #include <sys/dtype.h> #include <sys/rman.h> +#include <sys/thread2.h> #include "mlx_compat.h" #include "mlxio.h" @@ -294,6 +295,17 @@ debug_called(1); + /* DF-5057: last-chance gate. MLX_DETACH_DRIVE checks MLXD_OPEN and + * then sleeps in mlx_flush before device_delete_child; an open that + * lands in that window leaves si_drv1 dangling once the softc is + * freed. (Complete fix: also drain in-flight bios before destroy.) */ + crit_enter(); + if (sc->mlxd_flags & MLXD_OPEN) { + crit_exit(); + return (EBUSY); + } + crit_exit(); + devstat_remove_entry(&sc->mlxd_stats); disk_destroy(&sc->mlxd_disk); |