summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/bhyve/block_if.c5
-rw-r--r--usr/src/cmd/bhyve/block_if.h7
-rw-r--r--usr/src/cmd/bhyve/pci_virtio_block.c16
3 files changed, 27 insertions, 1 deletions
diff --git a/usr/src/cmd/bhyve/block_if.c b/usr/src/cmd/bhyve/block_if.c
index c8ec96690c..010f010c38 100644
--- a/usr/src/cmd/bhyve/block_if.c
+++ b/usr/src/cmd/bhyve/block_if.c
@@ -66,7 +66,12 @@ __FBSDID("$FreeBSD$");
#define BLOCKIF_SIG 0xb109b109
#define BLOCKIF_NUMTHR 8
+#ifdef __FreeBSD__
#define BLOCKIF_MAXREQ (64 + BLOCKIF_NUMTHR)
+#else
+/* Enlarge to keep pace with the virtio-block ring size */
+#define BLOCKIF_MAXREQ (128 + BLOCKIF_NUMTHR)
+#endif
enum blockop {
BOP_READ,
diff --git a/usr/src/cmd/bhyve/block_if.h b/usr/src/cmd/bhyve/block_if.h
index 930cd62e83..265048d90f 100644
--- a/usr/src/cmd/bhyve/block_if.h
+++ b/usr/src/cmd/bhyve/block_if.h
@@ -44,7 +44,12 @@
#ifdef __FreeBSD__
#define BLOCKIF_IOV_MAX 33 /* not practical to be IOV_MAX */
#else
-#define BLOCKIF_IOV_MAX 17 /* not practical to be IOV_MAX */
+/*
+ * Upstream is in the process of bumping this up to 128 for several reasons,
+ * including Windows compatibility. For the sake of our Windows support, we
+ * will use the higher value now.
+ */
+#define BLOCKIF_IOV_MAX 128
#endif
struct blockif_req {
diff --git a/usr/src/cmd/bhyve/pci_virtio_block.c b/usr/src/cmd/bhyve/pci_virtio_block.c
index 63f59e6468..d2f6ac7785 100644
--- a/usr/src/cmd/bhyve/pci_virtio_block.c
+++ b/usr/src/cmd/bhyve/pci_virtio_block.c
@@ -68,7 +68,12 @@ __FBSDID("$FreeBSD$");
#include "virtio.h"
#include "block_if.h"
+#ifdef __FreeBSD__
#define VTBLK_RINGSZ 64
+#else
+/* Enlarge to match bigger BLOCKIF_IOV_MAX */
+#define VTBLK_RINGSZ 128
+#endif
#define VTBLK_S_OK 0
#define VTBLK_S_IOERR 1
@@ -376,7 +381,18 @@ pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
/* 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 */
+#ifdef __FreeBSD__
sc->vbsc_cfg.vbc_seg_max = BLOCKIF_IOV_MAX;
+#else
+ /*
+ * 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);
+#endif
sc->vbsc_cfg.vbc_geometry.cylinders = 0; /* no geometry */
sc->vbsc_cfg.vbc_geometry.heads = 0;
sc->vbsc_cfg.vbc_geometry.sectors = 0;