Requires recent qemu with support for the virtio-blk-vhost-vdpa device and the ability to pass a /dev/fdset/N path for the vdpa path (8.1.0)
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1900770 --- src/qemu/qemu_block.c | 20 ++++++++-- src/qemu/qemu_domain.c | 25 ++++++++++++ src/qemu/qemu_validate.c | 44 +++++++++++++++++++--- tests/qemuxml2argvdata/disk-vhostvdpa.args | 35 +++++++++++++++++ tests/qemuxml2argvdata/disk-vhostvdpa.xml | 21 +++++++++++ tests/qemuxml2argvtest.c | 2 + 6 files changed, 139 insertions(+), 8 deletions(-) create mode 100644 tests/qemuxml2argvdata/disk-vhostvdpa.args create mode 100644 tests/qemuxml2argvdata/disk-vhostvdpa.xml diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 35312fb7d4..78f6e63aad 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -778,6 +778,20 @@ qemuBlockStorageSourceGetNVMeProps(virStorageSource *src) } +static virJSONValue * +qemuBlockStorageSourceGetVhostVdpaProps(virStorageSource *src) +{ + virJSONValue *ret = NULL; + qemuDomainStorageSourcePrivate *srcpriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src); + + ignore_value(virJSONValueObjectAdd(&ret, + "s:driver", "virtio-blk-vhost-vdpa", + "s:path", qemuFDPassGetPath(srcpriv->fdpass), + NULL)); + return ret; +} + + static int qemuBlockStorageSourceGetBlockdevGetCacheProps(virStorageSource *src, virJSONValue *props) @@ -874,9 +888,9 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource *src, break; case VIR_STORAGE_TYPE_VHOST_VDPA: - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("vhostvdpa disk type not yet supported")); - return NULL; + if (!(fileprops = qemuBlockStorageSourceGetVhostVdpaProps(src))) + return NULL; + break; case VIR_STORAGE_TYPE_VHOST_USER: virReportError(VIR_ERR_INTERNAL_ERROR, "%s", diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 2f6b32e394..119e52a7d7 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -11157,6 +11157,28 @@ qemuDomainPrepareStorageSourceFDs(virStorageSource *src, } +static int +qemuDomainPrepareStorageSourceVDPA(virStorageSource *src, + qemuDomainObjPrivate *priv) +{ + qemuDomainStorageSourcePrivate *srcpriv = NULL; + virStorageType actualType = virStorageSourceGetActualType(src); + int vdpafd = -1; + + if (actualType != VIR_STORAGE_TYPE_VHOST_VDPA) + return 0; + + if ((vdpafd = qemuVDPAConnect(src->path)) < 0) + return -1; + + srcpriv = qemuDomainStorageSourcePrivateFetch(src); + + srcpriv->fdpass = qemuFDPassNew(src->nodestorage, priv); + qemuFDPassAddFD(srcpriv->fdpass, &vdpafd, "-vdpa"); + return 0; +} + + int qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk, virStorageSource *src, @@ -11197,6 +11219,9 @@ qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk, if (qemuDomainPrepareStorageSourceFDs(src, priv) < 0) return -1; + if (qemuDomainPrepareStorageSourceVDPA(src, priv) < 0) + return -1; + return 0; } diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 9dce908cfe..67b0944162 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -3220,6 +3220,28 @@ qemuValidateDomainDeviceDefDiskTransient(const virDomainDiskDef *disk, } +static int +qemuValidateDomainDeviceDefDiskVhost(const virDomainDef *def, + virStorageType storagetype, + virQEMUCapsFlags flag, + virQEMUCaps *qemuCaps) +{ + const char *vhosttype = virStorageTypeToString(storagetype); + + if (!virQEMUCapsGet(qemuCaps, flag)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("%1$s disk is not supported with this QEMU binary"), + vhosttype); + return -1; + } + + if (qemuValidateDomainDefVhostUserRequireSharedMemory(def, vhosttype) < 0) + return -1; + + return 0; +} + + int qemuValidateDomainDeviceDefDisk(const virDomainDiskDef *disk, const virDomainDef *def, @@ -3281,13 +3303,25 @@ qemuValidateDomainDeviceDefDisk(const virDomainDiskDef *disk, } if (disk->src->type == VIR_STORAGE_TYPE_VHOST_USER) { - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VHOST_USER_BLK)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("vhostuser disk is not supported with this QEMU binary")); + if (qemuValidateDomainDeviceDefDiskVhost(def, disk->src->type, + QEMU_CAPS_DEVICE_VHOST_USER_BLK, + qemuCaps) < 0) return -1; - } + } - if (qemuValidateDomainDefVhostUserRequireSharedMemory(def, "vhostuser") < 0) { + if (disk->src->type == VIR_STORAGE_TYPE_VHOST_VDPA) { + if (qemuValidateDomainDeviceDefDiskVhost(def, disk->src->type, + QEMU_CAPS_DEVICE_VIRTIO_BLK_VHOST_VDPA, + qemuCaps) < 0) + return -1; + + if (disk->cachemode != VIR_DOMAIN_DISK_CACHE_DIRECTSYNC && + disk->cachemode != VIR_DOMAIN_DISK_CACHE_DISABLE) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk type '%1$s' requires cache mode '%2$s' or '%3$s'"), + virStorageTypeToString(disk->src->type), + virDomainDiskCacheTypeToString(VIR_DOMAIN_DISK_CACHE_DIRECTSYNC), + virDomainDiskCacheTypeToString(VIR_DOMAIN_DISK_CACHE_DISABLE)); return -1; } } diff --git a/tests/qemuxml2argvdata/disk-vhostvdpa.args b/tests/qemuxml2argvdata/disk-vhostvdpa.args new file mode 100644 index 0000000000..878f3b5fce --- /dev/null +++ b/tests/qemuxml2argvdata/disk-vhostvdpa.args @@ -0,0 +1,35 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes \ +-machine pc,usb=off,dump-guest-core=off \ +-accel tcg \ +-m 214 \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot strict=on \ +-usb \ +-add-fd set=0,fd=1732,opaque=libvirt-1-storage-vdpa \ +-blockdev '{"driver":"virtio-blk-vhost-vdpa","path":"/dev/fdset/0","node-name":"libvirt-1-storage","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-1-format","read-only":false,"cache":{"direct":true,"no-flush":false},"driver":"raw","file":"libvirt-1-storage"}' \ +-device virtio-blk-pci,bus=pci.0,addr=0x2,drive=libvirt-1-format,id=virtio-disk0,bootindex=1,write-cache=on \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/disk-vhostvdpa.xml b/tests/qemuxml2argvdata/disk-vhostvdpa.xml new file mode 100644 index 0000000000..0ac3899a34 --- /dev/null +++ b/tests/qemuxml2argvdata/disk-vhostvdpa.xml @@ -0,0 +1,21 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <memoryBacking> + <access mode='shared'/> + </memoryBacking> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='vhostvdpa' device='disk'> + <driver name='qemu' type='raw' cache='none'/> + <source dev='/dev/vhost-vdpa-0'/> + <target dev='vda' bus='virtio'/> + </disk> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index d914d8cbea..928375c173 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1224,6 +1224,8 @@ mymain(void) DO_TEST_CAPS_VER("disk-vhostuser-numa", "4.2.0"); DO_TEST_CAPS_LATEST("disk-vhostuser-numa"); DO_TEST_CAPS_LATEST("disk-vhostuser"); + DO_TEST("disk-vhostvdpa", + QEMU_CAPS_DEVICE_VIRTIO_BLK_VHOST_VDPA); DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-device-lun-type-invalid"); DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-attaching-partition-nosupport"); DO_TEST_CAPS_LATEST("disk-usb-device"); -- 2.40.1