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

Pavel Hrdina phrdina at redhat.com
Wed Feb 3 15:25:57 UTC 2021


Signed-off-by: Pavel Hrdina <phrdina at redhat.com>
Reviewed-by: Ján Tomko <jtomko at redhat.com>
Reviewed-by: Peter Krempa <pkrempa at redhat.com>
---

Changes in v2:
    - added comment about snapshots not supported
    - moved forward declarations to the top of the file
    - fixed typos
    - added proper error message to qemuBlockStorageSourceGetBackendProps
    - added check for blkdeviotune.group_name in virDomainDiskVhostUserValidate
    - added <boot order> into one disk in tests

 src/conf/domain_conf.c                        |  87 ++++++++
 src/conf/domain_validate.c                    | 188 ++++++++++++++++++
 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                         |   6 +
 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     |  30 +++
 .../disk-vhostuser.x86_64-latest.xml          |  48 +++++
 tests/qemuxml2xmltest.c                       |   1 +
 13 files changed, 376 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 69b2841924..8dc5aecbf4 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1338,6 +1338,19 @@ static virClassPtr virDomainXMLOptionClass;
 static void virDomainObjDispose(void *obj);
 static void virDomainXMLOptionDispose(void *obj);
 
+
+static void
+virDomainChrSourceDefFormat(virBufferPtr buf,
+                            virDomainChrSourceDefPtr def,
+                            unsigned int flags);
+
+
+static int
+virDomainChrSourceReconnectDefParseXML(virDomainChrSourceReconnectDefPtr def,
+                                       xmlNodePtr node,
+                                       xmlXPathContextPtr ctxt);
+
+
 static int virDomainObjOnceInit(void)
 {
     if (!VIR_CLASS_NEW(virDomainObj, virClassForObjectLockable()))
@@ -5229,6 +5242,12 @@ 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;
@@ -8362,6 +8381,49 @@ virDomainDiskSourceNVMeParse(xmlNodePtr node,
 }
 
 
+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);
+
+    if (virDomainChrSourceReconnectDefParseXML(&src->vhostuser->data.nix.reconnect,
+                                               node,
+                                               ctxt) < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+
 static int
 virDomainDiskSourcePRParse(xmlNodePtr node,
                            xmlXPathContextPtr ctxt,
@@ -8513,6 +8575,10 @@ virDomainStorageSourceParse(xmlNodePtr node,
         if (virDomainDiskSourceNVMeParse(node, ctxt, src) < 0)
             return -1;
         break;
+    case VIR_STORAGE_TYPE_VHOST_USER:
+        if (virDomainDiskSourceVHostUserParse(node, src, xmlopt, ctxt) < 0)
+            return -1;
+        break;
     case VIR_STORAGE_TYPE_NONE:
     case VIR_STORAGE_TYPE_LAST:
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -23940,6 +24006,23 @@ virDomainDiskSourceNVMeFormat(virBufferPtr attrBuf,
 }
 
 
+static void
+virDomainChrSourceReconnectDefFormat(virBufferPtr buf,
+                                     virDomainChrSourceReconnectDefPtr def);
+
+
+static void
+virDomainDiskSourceVhostuserFormat(virBufferPtr attrBuf,
+                                   virBufferPtr childBuf,
+                                   virDomainChrSourceDefPtr vhostuser)
+{
+    virBufferAddLit(attrBuf, " type='unix'");
+    virBufferAsprintf(attrBuf, " path='%s'", vhostuser->data.nix.path);
+
+    virDomainChrSourceReconnectDefFormat(childBuf, &vhostuser->data.nix.reconnect);
+}
+
+
 static int
 virDomainDiskSourceFormatPrivateData(virBufferPtr buf,
                                      virStorageSourcePtr src,
@@ -24053,6 +24136,10 @@ virDomainDiskSourceFormat(virBufferPtr buf,
         virDomainDiskSourceNVMeFormat(&attrBuf, &childBuf, src->nvme);
         break;
 
+    case VIR_STORAGE_TYPE_VHOST_USER:
+        virDomainDiskSourceVhostuserFormat(&attrBuf, &childBuf, src->vhostuser);
+        break;
+
     case VIR_STORAGE_TYPE_NONE:
     case VIR_STORAGE_TYPE_LAST:
         virReportError(VIR_ERR_INTERNAL_ERROR,
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index c56b03ff3a..222a9386f6 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -22,6 +22,7 @@
 
 #include "domain_validate.h"
 #include "domain_conf.h"
+#include "snapshot_conf.h"
 #include "virconftypes.h"
 #include "virlog.h"
 #include "virutil.h"
@@ -254,6 +255,188 @@ 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 driver attributes */
+
+    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;
+    }
+
+    /* Unsupported driver elements */
+
+    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;
+        }
+    }
+
+    if (disk->src->metadataCacheMaxSize > 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("metadata_cache is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    /* Unsupported disk elements */
+
+    if (disk->blkdeviotune.group_name ||
+        virDomainBlockIoTuneInfoHasAny(&disk->blkdeviotune)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("iotune is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    if (disk->src->backingStore) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("backingStore is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    if (disk->src->encryption) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("encryption is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    if (disk->src->readonly) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("readonly is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    if (disk->src->shared) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("shareable is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    if (disk->transient) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("transient is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    if (disk->serial) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("serial is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    if (disk->wwn) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("wwn is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    if (disk->vendor) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("vendor is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    if (disk->product) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("product is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    if (disk->src->auth) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("auth is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    if (disk->geometry.cylinders > 0 ||
+        disk->geometry.heads > 0 ||
+        disk->geometry.sectors > 0 ||
+        disk->geometry.trans != VIR_DOMAIN_DISK_TRANS_DEFAULT) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("geometry is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    if (disk->blockio.logical_block_size > 0 ||
+        disk->blockio.physical_block_size > 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("blockio is not supported with vhostuser disk"));
+        return -1;
+    }
+
+    return 0;
+}
+
+
 #define VENDOR_LEN  8
 #define PRODUCT_LEN 16
 
@@ -329,6 +512,11 @@ virDomainDiskDefValidate(const virDomainDef *def,
         }
     }
 
+    if (disk->src->type == VIR_STORAGE_TYPE_VHOST_USER &&
+        virDomainDiskVhostUserValidate(disk) < 0) {
+        return -1;
+    }
+
     for (next = disk->src; next; next = next->backingStore) {
         if (virSecurityDeviceLabelDefValidate(next->seclabels,
                                               next->nseclabels,
diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c
index 3eaf05fe52..7706bbd8da 100644
--- a/src/conf/storage_source_conf.c
+++ b/src/conf/storage_source_conf.c
@@ -46,6 +46,7 @@ VIR_ENUM_IMPL(virStorage,
               "network",
               "volume",
               "nvme",
+              "vhostuser"
 );
 
 
@@ -1035,6 +1036,7 @@ virStorageSourceIsLocalStorage(const virStorageSource *src)
         /* While NVMe disks are local, they are not accessible via src->path.
          * Therefore, we have to return false here. */
     case VIR_STORAGE_TYPE_NVME:
+    case VIR_STORAGE_TYPE_VHOST_USER:
     case VIR_STORAGE_TYPE_LAST:
     case VIR_STORAGE_TYPE_NONE:
         return false;
@@ -1215,6 +1217,7 @@ virStorageSourceIsRelative(virStorageSourcePtr src)
     case VIR_STORAGE_TYPE_NETWORK:
     case VIR_STORAGE_TYPE_VOLUME:
     case VIR_STORAGE_TYPE_NVME:
+    case VIR_STORAGE_TYPE_VHOST_USER:
     case VIR_STORAGE_TYPE_NONE:
     case VIR_STORAGE_TYPE_LAST:
         return false;
diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h
index e66ccdedef..f42bb1c67d 100644
--- a/src/conf/storage_source_conf.h
+++ b/src/conf/storage_source_conf.h
@@ -23,6 +23,7 @@
 
 #include "storage_encryption_conf.h"
 #include "virbitmap.h"
+#include "virconftypes.h"
 #include "virenum.h"
 #include "virobject.h"
 #include "virpci.h"
@@ -41,6 +42,7 @@ typedef enum {
     VIR_STORAGE_TYPE_NETWORK,
     VIR_STORAGE_TYPE_VOLUME,
     VIR_STORAGE_TYPE_NVME,
+    VIR_STORAGE_TYPE_VHOST_USER,
 
     VIR_STORAGE_TYPE_LAST
 } virStorageType;
@@ -300,6 +302,8 @@ struct _virStorageSource {
 
     virStorageSourceNVMeDefPtr nvme; /* type == VIR_STORAGE_TYPE_NVME */
 
+    virDomainChrSourceDefPtr vhostuser; /* type == VIR_STORAGE_TYPE_VHOST_USER */
+
     virStorageSourceInitiatorDef initiator;
 
     virObjectPtr privateData;
diff --git a/src/libxl/xen_xl.c b/src/libxl/xen_xl.c
index 6dcba43fe0..941832ce4e 100644
--- a/src/libxl/xen_xl.c
+++ b/src/libxl/xen_xl.c
@@ -1668,6 +1668,7 @@ xenFormatXLDiskSrc(virStorageSourcePtr src, char **srcstr)
 
     case VIR_STORAGE_TYPE_VOLUME:
     case VIR_STORAGE_TYPE_NVME:
+    case VIR_STORAGE_TYPE_VHOST_USER:
     case VIR_STORAGE_TYPE_NONE:
     case VIR_STORAGE_TYPE_LAST:
         break;
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 6456100170..4ae736d553 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1173,6 +1173,11 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src,
             return NULL;
         break;
 
+    case VIR_STORAGE_TYPE_VHOST_USER:
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("unable to create blockdev props for vhostuser disk type"));
+        return NULL;
+
     case VIR_STORAGE_TYPE_VOLUME:
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("storage source pool '%s' volume '%s' is not translated"),
@@ -2599,6 +2604,7 @@ qemuBlockStorageSourceCreateGetStorageProps(virStorageSourcePtr src,
     case VIR_STORAGE_TYPE_DIR:
     case VIR_STORAGE_TYPE_VOLUME:
     case VIR_STORAGE_TYPE_NVME:
+    case VIR_STORAGE_TYPE_VHOST_USER:
         return 0;
 
     case VIR_STORAGE_TYPE_NONE:
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index c30e5a6c83..5501f90221 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1087,6 +1087,7 @@ qemuGetDriveSourceString(virStorageSourcePtr src,
 
     case VIR_STORAGE_TYPE_VOLUME:
     case VIR_STORAGE_TYPE_NVME:
+    case VIR_STORAGE_TYPE_VHOST_USER:
     case VIR_STORAGE_TYPE_NONE:
     case VIR_STORAGE_TYPE_LAST:
         break;
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 0adfdb9351..f44d31c971 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -238,6 +238,7 @@ qemuMigrationDstPrecreateDisk(virConnectPtr *conn,
     case VIR_STORAGE_TYPE_BLOCK:
     case VIR_STORAGE_TYPE_DIR:
     case VIR_STORAGE_TYPE_NVME:
+    case VIR_STORAGE_TYPE_VHOST_USER:
     case VIR_STORAGE_TYPE_NONE:
     case VIR_STORAGE_TYPE_LAST:
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -1479,6 +1480,7 @@ qemuMigrationSrcIsSafe(virDomainDefPtr def,
             unsafe = true;
             break;
 
+        case VIR_STORAGE_TYPE_VHOST_USER:
         case VIR_STORAGE_TYPE_NONE:
         case VIR_STORAGE_TYPE_BLOCK:
         case VIR_STORAGE_TYPE_DIR:
diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
index 39445738a2..115c2fc91b 100644
--- a/src/qemu/qemu_snapshot.c
+++ b/src/qemu/qemu_snapshot.c
@@ -428,6 +428,7 @@ qemuSnapshotPrepareDiskExternalInactive(virDomainSnapshotDiskDefPtr snapdisk,
     case VIR_STORAGE_TYPE_DIR:
     case VIR_STORAGE_TYPE_VOLUME:
     case VIR_STORAGE_TYPE_NVME:
+    case VIR_STORAGE_TYPE_VHOST_USER:
     case VIR_STORAGE_TYPE_NONE:
     case VIR_STORAGE_TYPE_LAST:
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -445,6 +446,7 @@ qemuSnapshotPrepareDiskExternalInactive(virDomainSnapshotDiskDefPtr snapdisk,
     case VIR_STORAGE_TYPE_DIR:
     case VIR_STORAGE_TYPE_VOLUME:
     case VIR_STORAGE_TYPE_NVME:
+    case VIR_STORAGE_TYPE_VHOST_USER:
     case VIR_STORAGE_TYPE_NONE:
     case VIR_STORAGE_TYPE_LAST:
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -518,6 +520,7 @@ qemuSnapshotPrepareDiskExternalActive(virDomainObjPtr vm,
     case VIR_STORAGE_TYPE_DIR:
     case VIR_STORAGE_TYPE_VOLUME:
     case VIR_STORAGE_TYPE_NVME:
+    case VIR_STORAGE_TYPE_VHOST_USER:
     case VIR_STORAGE_TYPE_NONE:
     case VIR_STORAGE_TYPE_LAST:
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -648,6 +651,7 @@ qemuSnapshotPrepareDiskInternal(virDomainDiskDefPtr disk,
     case VIR_STORAGE_TYPE_DIR:
     case VIR_STORAGE_TYPE_VOLUME:
     case VIR_STORAGE_TYPE_NVME:
+    case VIR_STORAGE_TYPE_VHOST_USER:
     case VIR_STORAGE_TYPE_NONE:
     case VIR_STORAGE_TYPE_LAST:
         virReportError(VIR_ERR_INTERNAL_ERROR,
diff --git a/src/storage_file/storage_source.c b/src/storage_file/storage_source.c
index 4b46cc4e84..ffe150a9b0 100644
--- a/src/storage_file/storage_source.c
+++ b/src/storage_file/storage_source.c
@@ -545,6 +545,7 @@ virStorageSourceUpdatePhysicalSize(virStorageSourcePtr src,
     /* We shouldn't get VOLUME, but the switch requires all cases */
     case VIR_STORAGE_TYPE_VOLUME:
     case VIR_STORAGE_TYPE_NVME:
+    case VIR_STORAGE_TYPE_VHOST_USER:
     case VIR_STORAGE_TYPE_NONE:
     case VIR_STORAGE_TYPE_LAST:
         return -1;
diff --git a/tests/qemuxml2argvdata/disk-vhostuser.xml b/tests/qemuxml2argvdata/disk-vhostuser.xml
new file mode 100644
index 0000000000..c96ef9119c
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-vhostuser.xml
@@ -0,0 +1,30 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <memoryBacking>
+    <source type='memfd'/>
+    <access mode='shared'/>
+  </memoryBacking>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+  </os>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='vhostuser' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source type='unix' path='/tmp/vhost1.sock'/>
+      <target dev='vda' bus='virtio'/>
+      <boot order='1'/>
+    </disk>
+    <disk type='vhostuser' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source type='unix' path='/tmp/vhost1.sock'>
+        <reconnect enabled='yes' timeout='10'/>
+      </source>
+      <target dev='vdb' bus='virtio'/>
+    </disk>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/disk-vhostuser.x86_64-latest.xml b/tests/qemuxml2xmloutdata/disk-vhostuser.x86_64-latest.xml
new file mode 100644
index 0000000000..9712dc0b12
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/disk-vhostuser.x86_64-latest.xml
@@ -0,0 +1,48 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <memoryBacking>
+    <source type='memfd'/>
+    <access mode='shared'/>
+  </memoryBacking>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+  </os>
+  <cpu mode='custom' match='exact' check='none'>
+    <model fallback='forbid'>qemu64</model>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='vhostuser' device='disk' snapshot='no'>
+      <driver name='qemu' type='raw'/>
+      <source type='unix' path='/tmp/vhost1.sock'/>
+      <target dev='vda' bus='virtio'/>
+      <boot order='1'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+    </disk>
+    <disk type='vhostuser' device='disk' snapshot='no'>
+      <driver name='qemu' type='raw'/>
+      <source type='unix' path='/tmp/vhost1.sock'>
+        <reconnect enabled='yes' timeout='10'/>
+      </source>
+      <target dev='vdb' bus='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+    </disk>
+    <controller type='usb' index='0' model='piix3-uhci'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+    </memballoon>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 342d70935f..a00ebd7d76 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -308,6 +308,7 @@ mymain(void)
     DO_TEST("disk-network-tlsx509-nbd", NONE);
     DO_TEST("disk-network-tlsx509-vxhs", NONE);
     DO_TEST("disk-nvme", QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_QCOW2_LUKS);
+    DO_TEST_CAPS_LATEST("disk-vhostuser");
     DO_TEST_CAPS_LATEST("disk-scsi");
     DO_TEST("disk-virtio-scsi-reservations",
             QEMU_CAPS_VIRTIO_SCSI,
-- 
2.29.2




More information about the libvir-list mailing list