Index: usr.sbin/bhyve/block_if.h =================================================================== --- usr.sbin/bhyve/block_if.h +++ usr.sbin/bhyve/block_if.h @@ -41,7 +41,7 @@ #include #include -#define BLOCKIF_IOV_MAX 33 /* not practical to be IOV_MAX */ +#define BLOCKIF_IOV_MAX 128 /* not practical to be IOV_MAX */ struct blockif_req { struct iovec br_iov[BLOCKIF_IOV_MAX]; Index: usr.sbin/bhyve/block_if.c =================================================================== --- usr.sbin/bhyve/block_if.c +++ usr.sbin/bhyve/block_if.c @@ -62,7 +62,7 @@ #define BLOCKIF_SIG 0xb109b109 #define BLOCKIF_NUMTHR 8 -#define BLOCKIF_MAXREQ (64 + BLOCKIF_NUMTHR) +#define BLOCKIF_MAXREQ (128 + BLOCKIF_NUMTHR) enum blockop { BOP_READ, Index: usr.sbin/bhyve/pci_virtio_block.c =================================================================== --- usr.sbin/bhyve/pci_virtio_block.c +++ usr.sbin/bhyve/pci_virtio_block.c @@ -55,7 +55,7 @@ #include "virtio.h" #include "block_if.h" -#define VTBLK_RINGSZ 64 +#define VTBLK_RINGSZ 128 #define VTBLK_S_OK 0 #define VTBLK_S_IOERR 1 @@ -350,7 +350,14 @@ /* setup virtio block config space */ sc->vbsc_cfg.vbc_capacity = size / DEV_BSIZE; /* 512-byte units */ sc->vbsc_cfg.vbc_size_max = 0; /* not negotiated */ - sc->vbsc_cfg.vbc_seg_max = BLOCKIF_IOV_MAX; + /* + * If Linux is presented with a seg_max greater than the virtio queue + * size, it can stumble into situations where it violates its own + * invariants and panics. For safety, we keep seg_max clamped, paying + * heed to the two extra descriptors needed for the header and status + * of a request. + */ + sc->vbsc_cfg.vbc_seg_max = MIN(VTBLK_RINGSZ - 2, BLOCKIF_IOV_MAX); sc->vbsc_cfg.vbc_geometry.cylinders = 0; /* no geometry */ sc->vbsc_cfg.vbc_geometry.heads = 0; sc->vbsc_cfg.vbc_geometry.sectors = 0;