On Thu, Jun 17, 2021 at 12:07:10PM -0400, Dave Voutila wrote:
>
> Dave Voutila writes:
>
> > The virtio spec has had a de facto command for drivers to read the
> > serial number off a virtual block device. QEMU introduced this feature
> > years ago. Last November, the virtio governing group voted in favor of
> > adopting it officially into v1.2 (the next virtio spec) [1].
> >
> > The below diff adds the basics of handling the request returning an
> > empty serial number. (Serial numbers are limited to 20 bytes.) This
> > stops vmd from complaining about "unsupported command 0x8" when guests
> > send this command type.
>
> Got some feedback off-list from claudio@ that I think is sound. Instead
> of providing an "empty" serial id/number, simply return an UNSUPP status
> to indicate we don't support the value.
>
> I think this approach better than the approach I was suggesting that was
> based off QEMU's design of defaulting to "". (FreeBSD's Bhyve generates
> a serial like "BHYVE-1122-3344-5566" where the suffix is some truncated
> md5 of the backing filename. I'm not a fan of this approach.)
>
> >
> > secdata_desc{,idx} variables are renamed to just data_desc{,idx} to
> > semantically match the change since they're used for more than sector
> > data.
>
> I undid this renaming for now to reduce noise.
>
> > This is primarily part of my work to clean up and bring vmd's virtio
> > implementation more up to date and to align to our own
> > v{io,ioblk,ioscsi,etc.}(4) current capabilities. (vioblk(4) doesn't
> > support this yet, but Linux guests use it frequently.)
>
> While adding the BLK_ID support, I also switched the FLUSH/FLUSH_OUT
> response to be VIRTIO_BLK_S_UNSUPP as well since the device does not
> negotiate that feature. Any request from the guest to "flush" currently
> doesn't do anything (some hypervisors will fsync(2) the underlying fd)
> but for now I'm correcting the response code.
>
> I also noticed and added read/write checks prior to calls to
> {read,write}_mem. The virtio spec says a device MUST not write to a
> read-only descriptor and SHOULD NOT read a write-only descriptor with an
> exception being made for debugging. (See 2.6.5.1 Device requirements:
> The Virtqueue Descriptor Table.)
>
> Next steps in this are of code will be to properly implement the missing
> VIRTIO_BLK_S_IOERR results for failed i/o. Right now the device bails
> processing the command and doesn't reply to the driver, which is not
> conforming with virtio spec.
>
> > OK?
>
> Any other feedback? OK?
>

ok mlarkin

> >
> > -dv
> >
> > [1] https://www.oasis-open.org/committees/ballot.php?id=3536
>
>
> Index: virtio.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/vmd/virtio.c,v
> retrieving revision 1.89
> diff -u -p -r1.89 virtio.c
> --- virtio.c  16 Jun 2021 16:55:02 -0000      1.89
> +++ virtio.c  17 Jun 2021 15:57:56 -0000
> @@ -517,6 +517,11 @@ vioblk_notifyq(struct vioblk_dev *dev)
>               }
>
>               /* Read command from descriptor ring */
> +             if (cmd_desc->flags & VRING_DESC_F_WRITE) {
> +                     log_warnx("vioblk: unexpected writable cmd descriptor "
> +                         "%d", cmd_desc_idx);
> +                     goto out;
> +             }
>               if (read_mem(cmd_desc->addr, &cmd, sizeof(cmd))) {
>                       log_warnx("vioblk: command read_mem error @ 0x%llx",
>                           cmd_desc->addr);
> @@ -541,6 +546,13 @@ vioblk_notifyq(struct vioblk_dev *dev)
>                               struct ioinfo *info;
>                               const uint8_t *secdata;
>
> +                             if ((secdata_desc->flags & VRING_DESC_F_WRITE)
> +                                 == 0) {
> +                                     log_warnx("vioblk: unwritable data "
> +                                         "descriptor %d", secdata_desc_idx);
> +                                     goto out;
> +                             }
> +
>                               info = vioblk_start_read(dev,
>                                   cmd.sector + secbias, secdata_desc->len);
>
> @@ -607,6 +619,13 @@ vioblk_notifyq(struct vioblk_dev *dev)
>                       do {
>                               struct ioinfo *info;
>
> +                             if (secdata_desc->flags & VRING_DESC_F_WRITE) {
> +                                     log_warnx("wr vioblk: unexpected "
> +                                         "writable data descriptor %d",
> +                                         secdata_desc_idx);
> +                                     goto out;
> +                             }
> +
>                               info = vioblk_start_write(dev,
>                                   cmd.sector + secbias,
>                                   secdata_desc->addr, secdata_desc->len);
> @@ -654,7 +673,35 @@ vioblk_notifyq(struct vioblk_dev *dev)
>                       ds_desc_idx = cmd_desc->next & VIOBLK_QUEUE_MASK;
>                       ds_desc = &desc[ds_desc_idx];
>
> -                     ds = VIRTIO_BLK_S_OK;
> +                     ds = VIRTIO_BLK_S_UNSUPP;
> +                     break;
> +             case VIRTIO_BLK_T_GET_ID:
> +                     secdata_desc_idx = cmd_desc->next & VIOBLK_QUEUE_MASK;
> +                     secdata_desc = &desc[secdata_desc_idx];
> +
> +                     /*
> +                      * We don't support this command yet. While it's not
> +                      * officially part of the virtio spec (will be in v1.2)
> +                      * there's no feature to negotiate. Linux drivers will
> +                      * often send this command regardless.
> +                      *
> +                      * When the command is received, it should appear as a
> +                      * chain of 3 descriptors, similar to the IN/OUT
> +                      * commands. The middle descriptor should have have a
> +                      * length of VIRTIO_BLK_ID_BYTES bytes.
> +                      */
> +                     if ((secdata_desc->flags & VRING_DESC_F_NEXT) == 0) {
> +                             log_warnx("id vioblk: unchained vioblk data "
> +                                 "descriptor received (idx %d)",
> +                                 cmd_desc_idx);
> +                             goto out;
> +                     }
> +
> +                     /* Skip the data descriptor. */
> +                     ds_desc_idx = secdata_desc->next & VIOBLK_QUEUE_MASK;
> +                     ds_desc = &desc[ds_desc_idx];
> +
> +                     ds = VIRTIO_BLK_S_UNSUPP;
>                       break;
>               default:
>                       log_warnx("%s: unsupported command 0x%x", __func__,
> @@ -666,6 +713,11 @@ vioblk_notifyq(struct vioblk_dev *dev)
>                       break;
>               }
>
> +             if ((ds_desc->flags & VRING_DESC_F_WRITE) == 0) {
> +                     log_warnx("%s: ds descriptor %d unwritable", __func__,
> +                         ds_desc_idx);
> +                     goto out;
> +             }
>               if (write_mem(ds_desc->addr, &ds, ds_desc->len)) {
>                       log_warnx("%s: can't write device status data @ 0x%llx",
>                           __func__, ds_desc->addr);

Reply via email to