From 02565aca5158fb4d9870546ea29be85278649511 Mon Sep 17 00:00:00 2001 From: Luo Yifan Date: Wed, 30 Nov 2022 18:13:36 +0800 Subject: [PATCH 15/24] conf: implement support for vhostuser disk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pavel Hrdina Reviewed-by: Ján Tomko Reviewed-by: Peter Krempa (cherry picked from commit f00fe96eb045eed2b6b40d5046449bec6d495875) Signed-off-by: Luo Yifan --- src/conf/domain_conf.c | 254 ++++++++++++++++++ src/libxl/xen_xl.c | 1 + src/qemu/qemu_block.c | 6 + src/qemu/qemu_command.c | 1 + src/qemu/qemu_driver.c | 4 + src/qemu/qemu_migration.c | 2 + src/util/virstoragefile.c | 4 + src/util/virstoragefile.h | 4 + tests/qemuxml2argvdata/disk-vhostuser.xml | 30 +++ .../disk-vhostuser.x86_64-latest.xml | 48 ++++ tests/qemuxml2xmltest.c | 1 + 11 files changed, 355 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 b60b9d31a1..8b1ca76d39 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1278,6 +1278,17 @@ static virClassPtr virDomainXMLOptionClass; static void virDomainObjDispose(void *obj); static void virDomainXMLOptionDispose(void *obj); +static int +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())) @@ -5200,6 +5211,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; @@ -5995,6 +6012,174 @@ virDomainDiskAddressDiskBusCompatibility(virDomainDiskBus bus, return true; } +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; + } + } + + /* 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; +} static int virSecurityDeviceLabelDefValidateXML(virSecurityDeviceLabelDefPtr *seclabels, @@ -6095,6 +6280,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 (virSecurityDeviceLabelDefValidateXML(next->seclabels, next->nseclabels, @@ -9530,6 +9720,47 @@ virDomainDiskSourceNetworkParse(xmlNodePtr node, return 0; } +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 virDomainDiskSourceNVMeParse(xmlNodePtr node, @@ -9746,6 +9977,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, @@ -24682,6 +24917,21 @@ virDomainDiskSourceNVMeFormat(virBufferPtr attrBuf, virPCIDeviceAddressFormat(childBuf, nvme->pciAddr, false); } +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, @@ -24796,6 +25046,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/libxl/xen_xl.c b/src/libxl/xen_xl.c index 91b1825399..08eea48d6c 100644 --- a/src/libxl/xen_xl.c +++ b/src/libxl/xen_xl.c @@ -1641,6 +1641,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 d32277d7fd..8bd6238238 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -1108,6 +1108,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"), @@ -2491,6 +2496,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 9157008b73..bc62843783 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1166,6 +1166,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_driver.c b/src/qemu/qemu_driver.c index 854b56a563..b2ad021e4d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -14536,6 +14536,7 @@ qemuDomainSnapshotPrepareDiskExternalInactive(virDomainSnapshotDiskDefPtr snapdi 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, @@ -14553,6 +14554,7 @@ qemuDomainSnapshotPrepareDiskExternalInactive(virDomainSnapshotDiskDefPtr snapdi 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, @@ -14621,6 +14623,7 @@ qemuDomainSnapshotPrepareDiskExternalActive(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, @@ -14749,6 +14752,7 @@ qemuDomainSnapshotPrepareDiskInternal(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/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 1c48138ce3..faf4e223a8 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -228,6 +228,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, @@ -1358,6 +1359,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/util/virstoragefile.c b/src/util/virstoragefile.c index ffc8bdb344..2515dbf5ed 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -56,6 +56,7 @@ VIR_ENUM_IMPL(virStorage, "network", "volume", "nvme", + "vhostuser", ); VIR_ENUM_IMPL(virStorageFileFormat, @@ -2617,6 +2618,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; @@ -4164,6 +4166,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; @@ -4610,6 +4613,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/util/virstoragefile.h b/src/util/virstoragefile.h index 7939c09cd5..f2096b8705 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -28,6 +28,7 @@ #include "virseclabel.h" #include "virstorageencryption.h" #include "virsecret.h" +#include "../conf/virconftypes.h" #include "virenum.h" #include "virpci.h" @@ -52,6 +53,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; @@ -302,6 +304,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/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 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + + + + + 1 + + hvm + + + /usr/bin/qemu-system-x86_64 + + + + + + + + + + + + + + + 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 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + + + + + 1 + + hvm + + + qemu64 + + + destroy + restart + destroy + + /usr/bin/qemu-system-x86_64 + + + + + +
+ + + + + + + +
+ + +
+ + + + + +
+ + + diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 3a2539596b..2569c27261 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -338,6 +338,7 @@ mymain(void) DO_TEST("disk-network-vxhs", NONE); DO_TEST("disk-network-tlsx509", NONE); DO_TEST("disk-nvme", QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_QCOW2_LUKS); + DO_TEST_CAPS_LATEST("disk-vhostuser"); DO_TEST("disk-scsi", QEMU_CAPS_SCSI_LSI, QEMU_CAPS_SCSI_MEGASAS, QEMU_CAPS_SCSI_MPTSAS1068, QEMU_CAPS_SCSI_DISK_WWN); DO_TEST("disk-virtio-scsi-reservations", -- 2.27.0