[libvirt] [PATCH 0/3] Add vhost-user-scsi/blk support

The latest qemu has support the vhost-user-scsi and vhost-user-blk backend for better performance. This patch let the libvirt could manage the vhost-user disks. Usage in xml like this: <vhost-user-blk-pci type='unix'> <source type='bind' path='/tmp/vhost-blk.sock'> <reconnect enabled='yes' timeout='5' /> </source> <queue num='4'/> </vhost-user-blk-pci> Li Feng (3): qemu: Add vhost-user-scsi/blk support vhost-user-scsi/blk: add xml validation check qemu: Add multiqueue support for vhost-user-scsi/blk docs/schemas/domaincommon.rng | 48 ++++++++++ src/conf/device_conf.h | 5 + src/conf/domain_conf.c | 93 +++++++++++++++++- src/conf/domain_conf.h | 9 ++ src/qemu/qemu_alias.c | 16 ++++ src/qemu/qemu_command.c | 105 +++++++++++++++++++++ src/qemu/qemu_domain.c | 2 + .../vhost-user-blk.x86_64-latest.args | 37 ++++++++ tests/qemuxml2argvdata/vhost-user-blk.xml | 38 ++++++++ .../vhost-user-scsi.x86_64-latest.args | 37 ++++++++ tests/qemuxml2argvdata/vhost-user-scsi.xml | 37 ++++++++ tests/qemuxml2argvtest.c | 3 + 12 files changed, 429 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/vhost-user-blk.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/vhost-user-blk.xml create mode 100644 tests/qemuxml2argvdata/vhost-user-scsi.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/vhost-user-scsi.xml -- 2.11.0 -- The SmartX email address is only for business purpose. Any sent message that is not related to the business is not authorized or permitted by SmartX. 本邮箱为北京志凌海纳科技有限公司(SmartX)工作邮箱. 如本邮箱发出的邮件与工作无关,该邮件未得到本公司任何的明示或默示的授权.

Vhost-user-scsi and vhost-user-blk is supported in Qemu, this patch add support in libvirt. Hotplug is also support here. Usage like this: <vhost-user-scsi-pci type='unix'> <source type='bind' path='/tmp/unix/vhost-scsi.0'/> </vhost-user-scsi-pci> <vhost-user-blk-pci type='unix'> <source type='bind' path='/tmp/unix/vhost-blk.0'/> </vhost-user-blk-pci> Signed-off-by: Li Feng <fengli@smartx.com> --- src/conf/domain_conf.c | 79 ++++++++++++++++- src/conf/domain_conf.h | 9 ++ src/qemu/qemu_alias.c | 16 ++++ src/qemu/qemu_command.c | 98 ++++++++++++++++++++++ src/qemu/qemu_domain.c | 2 + .../vhost-user-blk.x86_64-latest.args | 37 ++++++++ tests/qemuxml2argvdata/vhost-user-blk.xml | 37 ++++++++ .../vhost-user-scsi.x86_64-latest.args | 37 ++++++++ tests/qemuxml2argvdata/vhost-user-scsi.xml | 37 ++++++++ tests/qemuxml2argvtest.c | 3 + 10 files changed, 354 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/vhost-user-blk.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/vhost-user-blk.xml create mode 100644 tests/qemuxml2argvdata/vhost-user-scsi.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/vhost-user-scsi.xml diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5d090876f8..fd53fab271 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -619,6 +619,8 @@ VIR_ENUM_IMPL(virDomainChrDevice, "serial", "console", "channel", + "vhost-user-scsi-pci", + "vhost-user-blk-pci", ); VIR_ENUM_IMPL(virDomainChr, @@ -4182,6 +4184,16 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def, if ((rc = cb(def, &device, &def->channels[i]->info, opaque)) != 0) return rc; } + for (i = 0; i < def->n_vhost_user_blk; i++) { + device.data.chr = def->vhost_user_blk[i]; + if ((rc = cb(def, &device, &def->vhost_user_blk[i]->info, opaque)) != 0) + return rc; + } + for (i = 0; i < def->n_vhost_user_scsi; i++) { + device.data.chr = def->vhost_user_scsi[i]; + if ((rc = cb(def, &device, &def->vhost_user_scsi[i]->info, opaque)) != 0) + return rc; + } for (i = 0; i < def->nconsoles; i++) { bool all = iteratorFlags & DOMAIN_DEVICE_ITERATE_ALL_CONSOLES; @@ -12284,6 +12296,8 @@ virDomainChrDefaultTargetType(int devtype) case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL: return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE; + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_SCSI: + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_BLK: case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL: case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST: /* No target type yet*/ @@ -12315,6 +12329,8 @@ virDomainChrTargetTypeFromString(int devtype, ret = virDomainChrSerialTargetTypeFromString(targetType); break; + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_SCSI: + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_BLK: case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL: case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST: /* No target type yet*/ @@ -12339,6 +12355,8 @@ virDomainChrTargetModelFromString(int devtype, ret = virDomainChrSerialTargetModelTypeFromString(targetModel); break; + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_SCSI: + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_BLK: case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL: case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE: case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL: @@ -16410,7 +16428,9 @@ virDomainDeviceDefParse(const char *xmlStr, if (virXMLNodeNameEqual(node, "channel") || virXMLNodeNameEqual(node, "console") || virXMLNodeNameEqual(node, "parallel") || - virXMLNodeNameEqual(node, "serial")) { + virXMLNodeNameEqual(node, "serial") || + virXMLNodeNameEqual(node, "vhost-user-blk-pci") || + virXMLNodeNameEqual(node, "vhost-user-scsi-pci")) { dev->type = VIR_DOMAIN_DEVICE_CHR; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -17486,6 +17506,11 @@ virDomainChrEquals(virDomainChrDefPtr src, ATTRIBUTE_FALLTHROUGH; + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_SCSI: + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_BLK: + return STREQ_NULLABLE(src->source->data.nix.path, + tgt->source->data.nix.path); + case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE: case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL: return src->target.port == tgt->target.port; @@ -17545,6 +17570,14 @@ virDomainChrGetDomainPtrsInternal(virDomainDefPtr vmdef, *arrPtr = &vmdef->channels; *cntPtr = &vmdef->nchannels; return 0; + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_BLK: + *arrPtr = &vmdef->vhost_user_blk; + *cntPtr = &vmdef->n_vhost_user_blk; + return 0; + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_SCSI: + *arrPtr = &vmdef->vhost_user_scsi; + *cntPtr = &vmdef->n_vhost_user_scsi; + return 0; case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST: break; @@ -21045,6 +21078,46 @@ virDomainDefParseXML(xmlDocPtr xml, } VIR_FREE(nodes); + if ((n = virXPathNodeSet("./devices/vhost-user-blk-pci", ctxt, &nodes)) < 0) + goto error; + + if (n && VIR_ALLOC_N(def->vhost_user_blk, n) < 0) + goto error; + + for (i = 0; i < n; i++) { + virDomainChrDefPtr chr = virDomainChrDefParseXML(xmlopt, + ctxt, + nodes[i], + def->seclabels, + def->nseclabels, + flags); + if (!chr) + goto error; + + def->vhost_user_blk[def->n_vhost_user_blk++] = chr; + } + VIR_FREE(nodes); + + if ((n = virXPathNodeSet("./devices/vhost-user-scsi-pci", ctxt, &nodes)) < 0) + goto error; + + if (n && VIR_ALLOC_N(def->vhost_user_scsi, n) < 0) + goto error; + + for (i = 0; i < n; i++) { + virDomainChrDefPtr chr = virDomainChrDefParseXML(xmlopt, + ctxt, + nodes[i], + def->seclabels, + def->nseclabels, + flags); + if (!chr) + goto error; + + def->vhost_user_scsi[def->n_vhost_user_scsi++] = chr; + } + VIR_FREE(nodes); + /* analysis of the input devices */ if ((n = virXPathNodeSet("./devices/input", ctxt, &nodes)) < 0) @@ -26008,6 +26081,10 @@ virDomainChrTargetDefFormat(virBufferPtr buf, def->target.port); break; + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_SCSI: + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_BLK: + break; + case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST: virReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected char device type %d"), diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 2884af49d8..d05c1e0e1a 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1038,6 +1038,9 @@ typedef enum { VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE, VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL, + VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_SCSI, + VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_BLK, + VIR_DOMAIN_CHR_DEVICE_TYPE_LAST } virDomainChrDeviceType; @@ -2475,6 +2478,12 @@ struct _virDomainDef { size_t nconsoles; virDomainChrDefPtr *consoles; + size_t n_vhost_user_blk; + virDomainChrDefPtr *vhost_user_blk; + + size_t n_vhost_user_scsi; + virDomainChrDefPtr *vhost_user_scsi; + size_t nleases; virDomainLeaseDefPtr *leases; diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index d294963d35..0aa48eb5ed 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -107,6 +107,14 @@ qemuAssignDeviceChrAlias(virDomainDefPtr def, prefix = "channel"; break; + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_SCSI: + prefix = "vhost-user-scsi-disk"; + break; + + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_BLK: + prefix = "vhost-user-blk-disk"; + break; + case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST: return -1; } @@ -642,6 +650,14 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) if (qemuAssignDeviceChrAlias(def, def->consoles[i], i) < 0) return -1; } + for (i = 0; i < def->n_vhost_user_blk; i++) { + if (qemuAssignDeviceChrAlias(def, def->vhost_user_blk[i], i) < 0) + return -1; + } + for (i = 0; i < def->n_vhost_user_scsi; i++) { + if (qemuAssignDeviceChrAlias(def, def->vhost_user_scsi[i], i) < 0) + return -1; + } for (i = 0; i < def->nhubs; i++) { if (qemuAssignDeviceHubAlias(def->hubs[i], i) < 0) return -1; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 77470a6037..336ca3f729 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9397,6 +9397,60 @@ qemuBuildConsoleCommandLine(virLogManagerPtr logManager, return 0; } +static int +qemuBuildVhostUserDisksCommandLine(virLogManagerPtr logManager, + virSecurityManagerPtr secManager, + virCommandPtr cmd, + virQEMUDriverConfigPtr cfg, + const virDomainDef *def, + virQEMUCapsPtr qemuCaps, + bool chardevStdioLogd) +{ + size_t i; + unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT | + QEMU_BUILD_CHARDEV_UNIX_FD_PASS; + if (chardevStdioLogd) + cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD; + + for (i = 0; i < def->n_vhost_user_blk; i++) { + virDomainChrDefPtr vhostuserdisk = def->vhost_user_blk[i]; + char *devstr; + + + if (!(devstr = qemuBuildChrChardevStr(logManager, secManager, + cmd, cfg, def, + vhostuserdisk->source, + vhostuserdisk->info.alias, + qemuCaps, cdevflags))) + return -1; + virCommandAddArg(cmd, "-chardev"); + virCommandAddArg(cmd, devstr); + VIR_FREE(devstr); + + if (qemuBuildChrDeviceCommandLine(cmd, def, vhostuserdisk, qemuCaps) < 0) + return -1; + } + + for (i = 0; i < def->n_vhost_user_scsi; i++) { + virDomainChrDefPtr vhostuserdisk = def->vhost_user_scsi[i]; + char *devstr; + + + if (!(devstr = qemuBuildChrChardevStr(logManager, secManager, + cmd, cfg, def, + vhostuserdisk->source, + vhostuserdisk->info.alias, + qemuCaps, cdevflags))) + return -1; + virCommandAddArg(cmd, "-chardev"); + virCommandAddArg(cmd, devstr); + VIR_FREE(devstr); + + if (qemuBuildChrDeviceCommandLine(cmd, def, vhostuserdisk, qemuCaps) < 0) + return -1; + } + return 0; +} char * qemuBuildRedirdevDevStr(const virDomainDef *def, @@ -10430,6 +10484,11 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, chardevStdioLogd) < 0) return NULL; + if (qemuBuildVhostUserDisksCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps, + chardevStdioLogd) < 0) + return NULL; + + if (qemuBuildTPMCommandLine(cmd, def, qemuCaps) < 0) return NULL; @@ -10656,6 +10715,40 @@ qemuBuildConsoleChrDeviceStr(char **deviceStr, return 0; } +/* This function generates the correct '-device' string for character + * devices of each architecture. + */ +static int +qemuBuildVhostUserChrDeviceStr(char **deviceStr, + const virDomainDef *def, + virDomainChrDefPtr vhostuser, + virQEMUCapsPtr qemuCaps) +{ + VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER; + const char* device_type; + + if ((virDomainChrDeviceType)vhostuser->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_SCSI) { + device_type = "vhost-user-scsi-pci"; + } else if ((virDomainChrDeviceType)vhostuser->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_BLK) { + device_type = "vhost-user-blk-pci"; + } else { + return -1; + } + virBufferAsprintf(&buf, "%s,chardev=char%s,id=%s", + device_type, + vhostuser->info.alias, vhostuser->info.alias); + + if (qemuBuildDeviceAddressStr(&buf, def, &vhostuser->info, qemuCaps) < 0) + return -1; + + if (virBufferCheckError(&buf) < 0) + return -1; + + *deviceStr = virBufferContentAndReset(&buf); + return 0; +} + + int qemuBuildChrDeviceStr(char **deviceStr, const virDomainDef *vmdef, @@ -10681,6 +10774,11 @@ qemuBuildChrDeviceStr(char **deviceStr, ret = qemuBuildConsoleChrDeviceStr(deviceStr, vmdef, chr); break; + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_SCSI: + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_BLK: + ret = qemuBuildVhostUserChrDeviceStr(deviceStr, vmdef, chr, qemuCaps); + break; + case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST: return ret; } diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index e8e895d9aa..f107cf2601 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5220,6 +5220,8 @@ qemuDomainChrTargetDefValidate(const virDomainChrDef *chr) } break; + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_SCSI: + case VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_BLK: case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE: case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL: case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL: diff --git a/tests/qemuxml2argvdata/vhost-user-blk.x86_64-latest.args b/tests/qemuxml2argvdata/vhost-user-blk.x86_64-latest.args new file mode 100644 index 0000000000..4c67be1863 --- /dev/null +++ b/tests/qemuxml2argvdata/vhost-user-blk.x86_64-latest.args @@ -0,0 +1,37 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-test \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-test/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-test/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-test/.config \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name guest=test,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,\ +file=/tmp/lib/domain--1-test/master-key.aes \ +-machine pc-0.13,accel=tcg,usb=off,dump-guest-core=off \ +-m 1024 \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid bba65c0e-c049-934f-b6aa-4e2c0582acdf \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot menu=on,strict=on \ +-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \ +-device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x6 \ +-chardev socket,id=charvhost-user-blk-disk0,path=/tmp/vhost-blk.sock,\ +reconnect=1 \ +-device vhost-user-blk-pci,chardev=charvhost-user-blk-disk0,\ +id=vhost-user-blk-disk0 \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ +resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/vhost-user-blk.xml b/tests/qemuxml2argvdata/vhost-user-blk.xml new file mode 100644 index 0000000000..c9ff7650cb --- /dev/null +++ b/tests/qemuxml2argvdata/vhost-user-blk.xml @@ -0,0 +1,37 @@ +<domain type='qemu'> + <name>test</name> + <uuid>bba65c0e-c049-934f-b6aa-4e2c0582acdf</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-0.13'>hvm</type> + <boot dev='hd'/> + <bootmenu enable='yes'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='virtio-serial' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + <vhost-user-blk-pci type='unix'> + <source type='bind' path='/tmp/vhost-blk.sock'> + <reconnect enabled='yes' timeout='1' /> + </source> + </vhost-user-blk-pci> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/vhost-user-scsi.x86_64-latest.args b/tests/qemuxml2argvdata/vhost-user-scsi.x86_64-latest.args new file mode 100644 index 0000000000..78da36da85 --- /dev/null +++ b/tests/qemuxml2argvdata/vhost-user-scsi.x86_64-latest.args @@ -0,0 +1,37 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-test \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-test/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-test/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-test/.config \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name guest=test,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,\ +file=/tmp/lib/domain--1-test/master-key.aes \ +-machine pc-0.13,accel=tcg,usb=off,dump-guest-core=off \ +-m 1024 \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid bba65c0e-c049-934f-b6aa-4e2c0582acdf \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot menu=on,strict=on \ +-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \ +-device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x6 \ +-chardev socket,id=charvhost-user-scsi-disk0,path=/tmp/vhost-scsi.sock,\ +reconnect=0 \ +-device vhost-user-scsi-pci,chardev=charvhost-user-scsi-disk0,\ +id=vhost-user-scsi-disk0 \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ +resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/vhost-user-scsi.xml b/tests/qemuxml2argvdata/vhost-user-scsi.xml new file mode 100644 index 0000000000..ca0f719ff5 --- /dev/null +++ b/tests/qemuxml2argvdata/vhost-user-scsi.xml @@ -0,0 +1,37 @@ +<domain type='qemu'> + <name>test</name> + <uuid>bba65c0e-c049-934f-b6aa-4e2c0582acdf</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-0.13'>hvm</type> + <boot dev='hd'/> + <bootmenu enable='yes'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='virtio-serial' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + <vhost-user-scsi-pci type='unix'> + <source type='bind' path='/tmp/vhost-scsi.sock'> + <reconnect enabled='no' /> + </source> + </vhost-user-scsi-pci> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 5bbac1c8b8..93c6a487b3 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2981,6 +2981,9 @@ mymain(void) DO_TEST_CAPS_ARCH_LATEST("vhost-vsock-ccw", "s390x"); DO_TEST_CAPS_ARCH_LATEST("vhost-vsock-ccw-auto", "s390x"); + DO_TEST_CAPS_LATEST("vhost-user-blk"); + DO_TEST_CAPS_LATEST("vhost-user-scsi"); + DO_TEST_CAPS_VER("launch-security-sev", "2.12.0"); DO_TEST("riscv64-virt", -- 2.11.0 -- The SmartX email address is only for business purpose. Any sent message that is not related to the business is not authorized or permitted by SmartX. 本邮箱为北京志凌海纳科技有限公司(SmartX)工作邮箱. 如本邮箱发出的邮件与工作无关,该邮件未得到本公司任何的明示或默示的授权.

Add vhost-user-scsi/blk xml schema to validate the correctness when editing the xml for the new chardev. Signed-off-by: Li Feng <fengli@smartx.com> --- docs/schemas/domaincommon.rng | 48 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 40eb4a2d75..63c629d117 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4375,6 +4375,52 @@ </optional> </define> + <define name="vhost-user-blk-pci"> + <element name="vhost-user-blk-pci"> + <optional> + <attribute name="type"> + <choice> + <value>unix</value> + </choice> + </attribute> + </optional> + <interleave> + <optional> + <ref name="unixSocketSource"/> + </optional> + <optional> + <ref name="address"/> + </optional> + <optional> + <ref name="alias"/> + </optional> + </interleave> + </element> + </define> + + <define name="vhost-user-scsi-pci"> + <element name="vhost-user-scsi-pci"> + <optional> + <attribute name="type"> + <choice> + <value>unix</value> + </choice> + </attribute> + </optional> + <interleave> + <optional> + <ref name="unixSocketSource"/> + </optional> + <optional> + <ref name="address"/> + </optional> + <optional> + <ref name="alias"/> + </optional> + </interleave> + </element> + </define> + <define name="vsock"> <element name="vsock"> <optional> @@ -4973,6 +5019,8 @@ <ref name="tpm"/> <ref name="shmem"/> <ref name="memorydev"/> + <ref name="vhost-user-blk-pci"/> + <ref name="vhost-user-scsi-pci"/> </choice> </zeroOrMore> <optional> -- 2.11.0 -- The SmartX email address is only for business purpose. Any sent message that is not related to the business is not authorized or permitted by SmartX. 本邮箱为北京志凌海纳科技有限公司(SmartX)工作邮箱. 如本邮箱发出的邮件与工作无关,该邮件未得到本公司任何的明示或默示的授权.

The format like this: <vhost-user-blk-pci type='unix'> <source type='bind' path='/tmp/vhost-blk.sock'> <reconnect enabled='yes' timeout='5' /> </source> <queue num='4'/> </vhost-user-blk-pci> Signed-off-by: Li Feng <fengli@smartx.com> --- src/conf/device_conf.h | 5 +++++ src/conf/domain_conf.c | 14 ++++++++++++++ src/qemu/qemu_command.c | 7 +++++++ tests/qemuxml2argvdata/vhost-user-blk.x86_64-latest.args | 2 +- tests/qemuxml2argvdata/vhost-user-blk.xml | 1 + 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h index d0854925e3..c3c722edd3 100644 --- a/src/conf/device_conf.h +++ b/src/conf/device_conf.h @@ -179,6 +179,11 @@ struct _virDomainDeviceInfo { * cases we might want to prevent that from happening by * locking the isolation group */ bool isolationGroupLocked; + + /* vhost-user-scsi/blk/nvme support multiqueue, parse the queue + * num from xml. + */ + unsigned int num_queues; }; void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index fd53fab271..eeed88e41e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -7483,10 +7483,12 @@ virDomainDeviceInfoParseXML(virDomainXMLOptionPtr xmlopt ATTRIBUTE_UNUSED, xmlNodePtr alias = NULL; xmlNodePtr boot = NULL; xmlNodePtr rom = NULL; + xmlNodePtr queue = NULL; int ret = -1; VIR_AUTOFREE(char *) romenabled = NULL; VIR_AUTOFREE(char *) rombar = NULL; VIR_AUTOFREE(char *) aliasStr = NULL; + VIR_AUTOFREE(char *) queueStr = NULL; virDomainDeviceInfoClear(info); @@ -7510,6 +7512,9 @@ virDomainDeviceInfoParseXML(virDomainXMLOptionPtr xmlopt ATTRIBUTE_UNUSED, (flags & VIR_DOMAIN_DEF_PARSE_ALLOW_ROM) && virXMLNodeNameEqual(cur, "rom")) { rom = cur; + } else if (queue == NULL && + virXMLNodeNameEqual(cur, "queue")) { + queue = cur; } } cur = cur->next; @@ -7563,6 +7568,15 @@ virDomainDeviceInfoParseXML(virDomainXMLOptionPtr xmlopt ATTRIBUTE_UNUSED, virDomainDeviceAddressParseXML(address, info) < 0) goto cleanup; + if (queue) { + queueStr = virXMLPropString(queue, "num"); + if (virStrToLong_uip(queueStr, NULL, 10, &info->num_queues) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Cannot parse <queue> 'num' attribute '%s'"), queueStr); + + goto cleanup; + } + } ret = 0; cleanup: diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 336ca3f729..7a3c695ac1 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -10737,6 +10737,13 @@ qemuBuildVhostUserChrDeviceStr(char **deviceStr, virBufferAsprintf(&buf, "%s,chardev=char%s,id=%s", device_type, vhostuser->info.alias, vhostuser->info.alias); + if (vhostuser->info.num_queues > 0) { + if ((virDomainChrDeviceType)vhostuser->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_SCSI) { + virBufferAsprintf(&buf, ",num_queues=%d", vhostuser->info.num_queues); + } else if ((virDomainChrDeviceType)vhostuser->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_VHOST_USER_BLK) { + virBufferAsprintf(&buf, ",num-queues=%d", vhostuser->info.num_queues); + } + } if (qemuBuildDeviceAddressStr(&buf, def, &vhostuser->info, qemuCaps) < 0) return -1; diff --git a/tests/qemuxml2argvdata/vhost-user-blk.x86_64-latest.args b/tests/qemuxml2argvdata/vhost-user-blk.x86_64-latest.args index 4c67be1863..ea99f5949d 100644 --- a/tests/qemuxml2argvdata/vhost-user-blk.x86_64-latest.args +++ b/tests/qemuxml2argvdata/vhost-user-blk.x86_64-latest.args @@ -31,7 +31,7 @@ file=/tmp/lib/domain--1-test/master-key.aes \ -chardev socket,id=charvhost-user-blk-disk0,path=/tmp/vhost-blk.sock,\ reconnect=1 \ -device vhost-user-blk-pci,chardev=charvhost-user-blk-disk0,\ -id=vhost-user-blk-disk0 \ +id=vhost-user-blk-disk0,num-queues=4 \ -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ resourcecontrol=deny \ -msg timestamp=on diff --git a/tests/qemuxml2argvdata/vhost-user-blk.xml b/tests/qemuxml2argvdata/vhost-user-blk.xml index c9ff7650cb..276fea14b5 100644 --- a/tests/qemuxml2argvdata/vhost-user-blk.xml +++ b/tests/qemuxml2argvdata/vhost-user-blk.xml @@ -32,6 +32,7 @@ <source type='bind' path='/tmp/vhost-blk.sock'> <reconnect enabled='yes' timeout='1' /> </source> + <queue num='4'/> </vhost-user-blk-pci> </devices> </domain> -- 2.11.0 -- The SmartX email address is only for business purpose. Any sent message that is not related to the business is not authorized or permitted by SmartX. 本邮箱为北京志凌海纳科技有限公司(SmartX)工作邮箱. 如本邮箱发出的邮件与工作无关,该邮件未得到本公司任何的明示或默示的授权.

On 9/30/19 8:54 AM, Li Feng wrote:
The latest qemu has support the vhost-user-scsi and vhost-user-blk backend for better performance.
This patch let the libvirt could manage the vhost-user disks.
Usage in xml like this: <vhost-user-blk-pci type='unix'> <source type='bind' path='/tmp/vhost-blk.sock'> <reconnect enabled='yes' timeout='5' /> </source> <queue num='4'/> </vhost-user-blk-pci>
This is not so nice XML. We tend to hide these implementation details from users. We already have <drive/> element which has <driver name=''/> sub-element. Maybe we can use that somehow? It's better to create the abstraction at libvirt layer instead of blindly exposing qemu's features. For instance, recently vhost-user-vga and vhost-user-gpu-pci was introduced into libvirt and it's hidden under <video/> element: fc91a182d7cc78fe5ce0e03ef709c834035e0f33 and friends
Li Feng (3): qemu: Add vhost-user-scsi/blk support vhost-user-scsi/blk: add xml validation check qemu: Add multiqueue support for vhost-user-scsi/blk
docs/schemas/domaincommon.rng | 48 ++++++++++
And you want to document every new feature that's added (and also mention it in docs/news.xml).
src/conf/device_conf.h | 5 + src/conf/domain_conf.c | 93 +++++++++++++++++- src/conf/domain_conf.h | 9 ++ src/qemu/qemu_alias.c | 16 ++++ src/qemu/qemu_command.c | 105 +++++++++++++++++++++ src/qemu/qemu_domain.c | 2 + .../vhost-user-blk.x86_64-latest.args | 37 ++++++++ tests/qemuxml2argvdata/vhost-user-blk.xml | 38 ++++++++ .../vhost-user-scsi.x86_64-latest.args | 37 ++++++++ tests/qemuxml2argvdata/vhost-user-scsi.xml | 37 ++++++++ tests/qemuxml2argvtest.c | 3 + 12 files changed, 429 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/vhost-user-blk.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/vhost-user-blk.xml create mode 100644 tests/qemuxml2argvdata/vhost-user-scsi.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/vhost-user-scsi.xml
I haven't looked at any code, because we need to figure out XML design first. Michal
participants (2)
-
Li Feng
-
Michal Privoznik