DF-5058 / fix.diff
--- a/sys/dev/raid/mlx/mlx.c +++ b/sys/dev/raid/mlx/mlx.c @@ -684,6 +684,14 @@ { debug_called(1); + /* DF-5058: once declared wedged, fail new arrivals immediately. */ + if (sc->mlx_stall_ticks >= 60) { + bio->bio_buf->b_flags |= B_ERROR; + bio->bio_buf->b_error = ETIMEDOUT; + biodone(bio); + return(0); + } + crit_enter(); bioqdisksort(&sc->mlx_bioq, bio); sc->mlx_waitbufs++; @@ -1037,7 +1045,37 @@ mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild); /* deal with possibly-missed interrupts and timed-out commands */ - mlx_done(sc); + if (mlx_done(sc) != 0) + sc->mlx_stall_ticks = 0; /* DF-5058: progress made */ + + /* + * DF-5058: bios park forever on mlx_bioq once the controller stops + * delivering completions (all command slots stuck BUSY; mc_timeout + * is never enforced). If work has been pending continuously for 60 + * seconds with zero completions, declare the controller wedged and + * fail everything queued so issuers become killable and the queue + * cannot grow without bound. + */ + if (sc->mlx_waitbufs == 0) { + sc->mlx_stall_ticks = 0; + } else if (++sc->mlx_stall_ticks >= 60) { + struct bio *bio; + + device_printf(sc->mlx_dev, + "no completion progress in 60s, failing queued I/O\n"); + crit_enter(); + while ((bio = bioq_first(&sc->mlx_bioq)) != NULL) { + bioq_remove(&sc->mlx_bioq, bio); + sc->mlx_waitbufs--; + crit_exit(); + bio->bio_buf->b_flags |= B_ERROR; + bio->bio_buf->b_error = ETIMEDOUT; + biodone(bio); + crit_enter(); + } + crit_exit(); + sc->mlx_stall_ticks = 60; /* keep failing new arrivals */ + } /* reschedule another poll next second or so */ callout_reset(&sc->mlx_timeout, hz, mlx_periodic, sc); --- a/sys/dev/raid/mlx/mlxvar.h +++ b/sys/dev/raid/mlx/mlxvar.h @@ -137,6 +137,7 @@ struct mlx_sysdrive mlx_sysdrive[MLX_MAXDRIVES]; /* system drives */ mlx_bioq mlx_bioq; /* outstanding I/O operations */ int mlx_waitbufs; /* number of bufs awaiting commands */ + int mlx_stall_ticks; /* DF-5058: no-progress seconds */ /* controller status */ int mlx_geom; |