[libvirt PATCH 4/6] conf: implement support for vhostuser disk

Pavel Hrdina phrdina at redhat.com
Wed Feb 3 09:51:23 UTC 2021


On Wed, Feb 03, 2021 at 10:27:01AM +0100, Peter Krempa wrote:
> On Tue, Feb 02, 2021 at 16:04:10 +0100, Pavel Hrdina wrote:
> > Signed-off-by: Pavel Hrdina <phrdina at redhat.com>
> > ---
> > 
> > We need to find a better way to validate different combinations of XML
> > elements and attributes.
> > 
> >  src/conf/domain_conf.c                        |  85 ++++++++
> >  src/conf/domain_validate.c                    | 187 ++++++++++++++++++
> >  src/conf/storage_source_conf.c                |   3 +
> >  src/conf/storage_source_conf.h                |   4 +
> >  src/libxl/xen_xl.c                            |   1 +
> >  src/qemu/qemu_block.c                         |   4 +
> >  src/qemu/qemu_command.c                       |   1 +
> >  src/qemu/qemu_migration.c                     |   2 +
> >  src/qemu/qemu_snapshot.c                      |   4 +
> >  src/storage_file/storage_source.c             |   1 +
> >  tests/qemuxml2argvdata/disk-vhostuser.xml     |  29 +++
> >  .../disk-vhostuser.x86_64-latest.xml          |  48 +++++
> >  tests/qemuxml2xmltest.c                       |   1 +
> >  13 files changed, 370 insertions(+)
> >  create mode 100644 tests/qemuxml2argvdata/disk-vhostuser.xml
> >  create mode 100644 tests/qemuxml2xmloutdata/disk-vhostuser.x86_64-latest.xml
> > 
> > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> > index 97fa841bff..43552c36c3 100644
> > --- a/src/conf/domain_conf.c
> > +++ b/src/conf/domain_conf.c
> > @@ -5228,6 +5228,11 @@ virDomainDiskDefPostParse(virDomainDiskDefPtr disk,
> >              disk->src->nvme->managed = VIR_TRISTATE_BOOL_YES;
> >      }
> 
> 
> /* vhost-user doesn't allow us to snapshot, disable snapshots by default */
> 
> 
> > +    if (disk->src->type == VIR_STORAGE_TYPE_VHOST_USER &&
> > +        disk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_DEFAULT) {
> > +        disk->snapshot = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE;
> > +    }
> > +
> >      if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
> >          virDomainDiskDefAssignAddress(xmlopt, disk, def) < 0) {
> >          return -1;
> > @@ -8361,6 +8366,55 @@ virDomainDiskSourceNVMeParse(xmlNodePtr node,
> >  }
> >  
> >  
> > +static int
> > +virDomainChrSourceReconnectDefParseXML(virDomainChrSourceReconnectDefPtr def,
> > +                                       xmlNodePtr node,
> > +                                       xmlXPathContextPtr ctxt);
> 
> [... see below note on forward decls.]
> 
> > +
> > +
> > +static int
> > +virDomainDiskSourceVHostUserParse(xmlNodePtr node,
> > +                                  virStorageSourcePtr src,
> > +                                  virDomainXMLOptionPtr xmlopt,
> > +                                  xmlXPathContextPtr ctxt)
> > +{
> > +    g_autofree char *type = virXMLPropString(node, "type");
> > +    g_autofree char *path = virXMLPropString(node, "path");
> > +
> > +    if (!type) {
> > +        virReportError(VIR_ERR_XML_ERROR, "%s",
> > +                       _("missing 'type' attribute for vhostuser disk source"));
> > +        return -1;
> > +    }
> > +
> > +    if (STRNEQ(type, "unix")) {
> > +        virReportError(VIR_ERR_XML_ERROR, "%s",
> > +                       _("invalid 'type' attribute for vhostuser disk source"));
> > +        return -1;
> > +    }
> > +
> > +    if (!path) {
> > +        virReportError(VIR_ERR_XML_ERROR, "%s",
> > +                       _("missing 'path' attribute for vhostuser disk source"));
> > +        return -1;
> > +    }
> > +
> > +    if (!(src->vhostuser = virDomainChrSourceDefNew(xmlopt)))
> > +        return -1;
> > +
> > +    src->vhostuser->type = virDomainChrTypeFromString(type);
> > +    src->vhostuser->data.nix.path = g_steal_pointer(&path);
> 
> 'path' doesn't really need a temp variable.

True, but IMHO it makes the code more readable. Without the variable it
would look like this:

    g_autofree char *type = virXMLPropString(node, "type");

    if (!type) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing 'type' attribute for vhostuser disk source"));
        return -1;
    }

    if (STRNEQ(type, "unix")) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("invalid 'type' attribute for vhostuser disk source"));
        return -1;
    }

    if (!(src->vhostuser = virDomainChrSourceDefNew(xmlopt)))
        return -1;

    src->vhostuser->type = virDomainChrTypeFromString(type);
    src->vhostuser->data.nix.path = virXMLPropString(node, "path");

    if (!src->vhostuser->data.nix.path) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing 'path' attribute for vhostuser disk source"));
        return -1;
    }

    if (virDomainChrSourceReconnectDefParseXML(&src->vhostuser->data.nix.reconnect,
                                               node,
                                               ctxt) < 0) {
        return -1;
    }

    return 0;

which is mixing the checks and assignment together.

> 
> > +
> > +    if (virDomainChrSourceReconnectDefParseXML(&src->vhostuser->data.nix.reconnect,
> > +                                               node,
> > +                                               ctxt) < 0) {
> > +        return -1;
> > +    }
> > +
> > +    return 0;
> > +}
> 
> [...]
> 
> > @@ -23939,6 +23997,23 @@ virDomainDiskSourceNVMeFormat(virBufferPtr attrBuf,
> >  }
> >  
> >  
> > +static void
> > +virDomainChrSourceReconnectDefFormat(virBufferPtr buf,
> > +                                     virDomainChrSourceReconnectDefPtr def);
> > +
> > +
> 
> [...]
> 
> > @@ -23989,6 +24064,12 @@ virDomainDiskSourceFormatSlices(virBufferPtr buf,
> >  }
> >  
> >  
> > +static void
> > +virDomainChrSourceDefFormat(virBufferPtr buf,
> > +                            virDomainChrSourceDefPtr def,
> > +                            unsigned int flags);
> > +
> > +
> 
> Preferably put the forward declarations at the top of the file.
> 
> [...]
> 
> > diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
> > index c56b03ff3a..c60300e750 100644
> > --- a/src/conf/domain_validate.c
> > +++ b/src/conf/domain_validate.c
> 
> [...]
> 
> > @@ -254,6 +255,187 @@ virDomainCheckVirtioOptionsAreAbsent(virDomainVirtioOptionsPtr virtio)
> >  }
> >  
> >  
> > +static int
> > +virDomainDiskVhostUserValidate(const virDomainDiskDef *disk)
> > +{
> > +    if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO) {
> > +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                       _("vhostuser disk supports only virtio bus"));
> > +        return -1;
> > +    }
> > +
> > +    if (disk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_NONE) {
> > +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                       _("only snapshot=no is supported with vhostuser disk"));
> > +        return -1;
> > +    }
> > +
> > +    /* Unsupported drive attributes */
> 
> s/drive/dirver/

Fixed, thanks.

> 
> > +
> > +    if (disk->cachemode != VIR_DOMAIN_DISK_CACHE_DEFAULT) {
> > +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                       _("cache is not supported with vhostuser disk"));
> > +        return -1;
> > +    }
> > +
> > +    if (disk->error_policy || disk->rerror_policy) {
> > +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                       _("error_policy is not supported with vhostuser disk"));
> > +        return -1;
> > +    }
> > +
> > +    if (disk->iomode) {
> > +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                       _("io is not supported with vhostuser disk"));
> > +        return -1;
> > +    }
> > +
> > +    if (disk->ioeventfd != VIR_TRISTATE_SWITCH_ABSENT) {
> > +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                       _("ioeventfd is not supported with vhostuser disk"));
> > +        return -1;
> > +    }
> > +
> > +    if (disk->copy_on_read) {
> > +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                       _("copy_on_read is not supported with vhostuser disk"));
> > +        return -1;
> > +    }
> > +
> > +    if (disk->discard) {
> > +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                       _("discard is not supported with vhostuser disk"));
> > +        return -1;
> > +    }
> > +
> > +    if (disk->iothread) {
> > +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                       _("iothread is not supported with vhostuser disk"));
> > +        return -1;
> > +    }
> > +
> > +    if (disk->detect_zeroes) {
> > +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                       _("detect_zeroes is not supported with vhostuser disk"));
> > +        return -1;
> > +    }
> > +
> > +    if (disk->src->metadataCacheMaxSize > 0) {
> > +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                       _("metadata_cache is not supported with vhostuser disk"));
> > +        return -1;
> > +    }
> > +
> > +    /* Unsupported driver elements */
> 
> s/driver/virtio/ ?

This was future proofing the comment :) currently there is only single
child element <virtio>. So I would be OK with both versions:

    /* Unsupported driver child elements */

    /* Unsupported virtio element */

> 
> > +
> > +    if (disk->virtio) {
> > +        if (disk->virtio->iommu != VIR_TRISTATE_SWITCH_ABSENT) {
> > +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                           _("iommu is not supported with vhostuser disk"));
> > +            return -1;
> > +        }
> > +
> > +        if (disk->virtio->ats != VIR_TRISTATE_SWITCH_ABSENT) {
> > +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                           _("ats is not supported with vhostuser disk"));
> > +            return -1;
> > +        }
> > +
> > +        if (disk->virtio->packed != VIR_TRISTATE_SWITCH_ABSENT) {
> > +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> > +                           _("packed is not supported with vhostuser disk"));
> > +            return -1;
> > +        }
> > +    }
> 
> [...]
> 
> > diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
> > index 6456100170..f6e81a7503 100644
> > --- a/src/qemu/qemu_block.c
> > +++ b/src/qemu/qemu_block.c
> > @@ -1173,6 +1173,9 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src,
> >              return NULL;
> >          break;
> >  
> > +    case VIR_STORAGE_TYPE_VHOST_USER:
> > +        break;
> 
> This case must return NULL and an error per API contract of the function.

Fixed. It should never happen but I agree that we should make sure to
error out if it happens.

Pavel

> 
> > +
> >      case VIR_STORAGE_TYPE_VOLUME:
> >          virReportError(VIR_ERR_INTERNAL_ERROR,
> >                         _("storage source pool '%s' volume '%s' is not translated"),
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20210203/f1fcf809/attachment-0001.sig>


More information about the libvir-list mailing list