--- a/sys/dev/virtual/virtio/block/virtio_blk.c +++ b/sys/dev/virtual/virtio/block/virtio_blk.c @@ -750,7 +750,13 @@ vtblk_alloc_disk(struct vtblk_softc *sc, struct virtio_blk_config *blkcfg) sc->cdev->si_drv1 = sc; sc->cdev->si_iosize_max = MAXPHYS; + /* + * DF-4424: a negotiated SEG_MAX smaller than what a MAXPHYS + * transfer can span overflows the per-queue sglist (EFBIG, + * KASSERT panic under INVARIANTS, truncated descriptor chain + * otherwise). Clamp the maximum transfer accordingly. + */ + if (sc->vtblk_max_nsegs < MAXPHYS / PAGE_SIZE + 1 + VTBLK_MIN_SEGMENTS) + sc->cdev->si_iosize_max = + (sc->vtblk_max_nsegs - VTBLK_MIN_SEGMENTS) * PAGE_SIZE; disk_setdiskinfo(&sc->vtblk_disk, &info);