Date: Wed, 3 Jul 2019 19:52:25 +0000 (UTC) From: Eric van Gyzen <vangyzen@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r349691 - stable/12/sys/dev/virtio/scsi Message-ID: <201907031952.x63JqPPi079880@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: vangyzen Date: Wed Jul 3 19:52:24 2019 New Revision: 349691 URL: https://svnweb.freebsd.org/changeset/base/349691 Log: MFC r349285 VirtIO SCSI: validate seg_max on attach Until head r349278 (stable/12 r349690), bhyve presented a seg_max to the guest that was too large. Detect this case and clamp it to the virtqueue size. Otherwise, we would fail the "too many segments to enqueue" assertion in virtqueue_enqueue(). I hit this by running a guest with a MAXPHYS of 256 KB. Reviewed by: bryanv cem Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D20703 Modified: stable/12/sys/dev/virtio/scsi/virtio_scsi.c Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/dev/virtio/scsi/virtio_scsi.c ============================================================================== --- stable/12/sys/dev/virtio/scsi/virtio_scsi.c Wed Jul 3 19:50:22 2019 (r349690) +++ stable/12/sys/dev/virtio/scsi/virtio_scsi.c Wed Jul 3 19:52:24 2019 (r349691) @@ -81,6 +81,7 @@ static void vtscsi_read_config(struct vtscsi_softc *, struct virtio_scsi_config *); static int vtscsi_maximum_segments(struct vtscsi_softc *, int); static int vtscsi_alloc_virtqueues(struct vtscsi_softc *); +static void vtscsi_check_sizes(struct vtscsi_softc *); static void vtscsi_write_device_config(struct vtscsi_softc *); static int vtscsi_reinit(struct vtscsi_softc *); @@ -314,6 +315,8 @@ vtscsi_attach(device_t dev) goto fail; } + vtscsi_check_sizes(sc); + error = vtscsi_init_event_vq(sc); if (error) { device_printf(dev, "cannot populate the eventvq\n"); @@ -478,6 +481,26 @@ vtscsi_alloc_virtqueues(struct vtscsi_softc *sc) "%s request", device_get_nameunit(dev)); return (virtio_alloc_virtqueues(dev, 0, nvqs, vq_info)); +} + +static void +vtscsi_check_sizes(struct vtscsi_softc *sc) +{ + int rqsize; + + if ((sc->vtscsi_flags & VTSCSI_FLAG_INDIRECT) == 0) { + /* + * Ensure the assertions in virtqueue_enqueue(), + * even if the hypervisor reports a bad seg_max. + */ + rqsize = virtqueue_size(sc->vtscsi_request_vq); + if (sc->vtscsi_max_nsegs > rqsize) { + device_printf(sc->vtscsi_dev, + "clamping seg_max (%d %d)\n", sc->vtscsi_max_nsegs, + rqsize); + sc->vtscsi_max_nsegs = rqsize; + } + } } static void
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201907031952.x63JqPPi079880>