Signed-off-by: Pavel Hrdina <phrdina@xxxxxxxxxx> --- src/qemu/qemu_command.c | 78 ++++++++++++++++++++-- src/qemu/qemu_command.h | 5 +- src/qemu/qemu_domain.c | 23 ++++++- src/qemu/qemu_domain.h | 6 ++ src/qemu/qemu_driver.c | 6 +- src/qemu/qemu_process.c | 14 +++- .../qemuxml2argv-iothreads-polling-disabled.args | 23 +++++++ .../qemuxml2argv-iothreads-polling-disabled.xml | 36 ++++++++++ .../qemuxml2argv-iothreads-polling-enabled.args | 23 +++++++ .../qemuxml2argv-iothreads-polling-enabled.xml | 36 ++++++++++ ...emuxml2argv-iothreads-polling-not-supported.xml | 1 + tests/qemuxml2argvtest.c | 8 +++ 12 files changed, 248 insertions(+), 11 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-disabled.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-disabled.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-enabled.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-enabled.xml create mode 120000 tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-not-supported.xml diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 552fdcf05e..1a189459a4 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7277,11 +7277,59 @@ qemuBuildMemCommandLine(virCommandPtr cmd, } +int +qemuBuildIOThreadProps(const virDomainIOThreadIDDef *def, + virQEMUCapsPtr qemuCaps, + virJSONValuePtr *props) +{ + virJSONValuePtr newProps = NULL; + + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_IOTHREAD_POLLING)) { + switch (def->poll_enabled) { + case VIR_TRISTATE_BOOL_YES: + if (virJSONValueObjectCreate(&newProps, "u:poll-max-ns", + def->poll_max_ns, NULL) < 0) + goto error; + + if (def->poll_grow && + virJSONValueObjectAdd(newProps, "u:poll-grow", + def->poll_grow, NULL) < 0) + goto error; + + if (def->poll_shrink && + virJSONValueObjectAdd(newProps, "u:poll-shrink", + def->poll_shrink, NULL) < 0) + goto error; + break; + case VIR_TRISTATE_BOOL_NO: + if (virJSONValueObjectCreate(&newProps, "u:poll-max-ns", 0, NULL) < 0) + goto error; + break; + case VIR_TRISTATE_BOOL_ABSENT: + case VIR_TRISTATE_BOOL_LAST: + break; + } + } + + *props = newProps; + return 0; + + error: + virJSONValueFree(newProps); + return -1; +} + + static int qemuBuildIOThreadCommandLine(virCommandPtr cmd, - const virDomainDef *def) + const virDomainDef *def, + virQEMUCapsPtr qemuCaps) { size_t i; + int ret = -1; + char *alias = NULL; + char *propsCmd = NULL; + virJSONValuePtr props = NULL; if (def->niothreadids == 0) return 0; @@ -7293,11 +7341,31 @@ qemuBuildIOThreadCommandLine(virCommandPtr cmd, */ for (i = 0; i < def->niothreadids; i++) { virCommandAddArg(cmd, "-object"); - virCommandAddArgFormat(cmd, "iothread,id=iothread%u", - def->iothreadids[i]->iothread_id); + + if (virAsprintf(&alias, "iothread%u", def->iothreadids[i]->iothread_id) < 0) + goto cleanup; + + if (qemuBuildIOThreadProps(def->iothreadids[i], qemuCaps, &props) < 0) + goto cleanup; + + if (!(propsCmd = virQEMUBuildObjectCommandlineFromJSON("iothread", + alias, props))) + goto cleanup; + + virCommandAddArg(cmd, propsCmd); + + virJSONValueFree(props); + VIR_FREE(propsCmd); + VIR_FREE(alias); } - return 0; + ret = 0; + + cleanup: + virJSONValueFree(props); + VIR_FREE(propsCmd); + VIR_FREE(alias); + return ret; } @@ -9598,7 +9666,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, if (qemuBuildSmpCommandLine(cmd, def) < 0) goto error; - if (qemuBuildIOThreadCommandLine(cmd, def) < 0) + if (qemuBuildIOThreadCommandLine(cmd, def, qemuCaps) < 0) goto error; if (virDomainNumaGetNodeCount(def->numa) && diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 69fe846139..84e8099bfe 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -202,6 +202,9 @@ char *qemuBuildShmemDevStr(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); - +int qemuBuildIOThreadProps(const virDomainIOThreadIDDef *def, + virQEMUCapsPtr qemuCaps, + virJSONValuePtr *props) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); #endif /* __QEMU_COMMAND_H__*/ diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index ea4b28288e..009c93a15e 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3283,7 +3283,8 @@ virDomainDefParserConfig virQEMUDriverDomainDefParserConfig = { .features = VIR_DOMAIN_DEF_FEATURE_MEMORY_HOTPLUG | VIR_DOMAIN_DEF_FEATURE_OFFLINE_VCPUPIN | - VIR_DOMAIN_DEF_FEATURE_INDIVIDUAL_VCPUS, + VIR_DOMAIN_DEF_FEATURE_INDIVIDUAL_VCPUS | + VIR_DOMAIN_DEF_FEATURE_IOTHREAD_POLLING, }; @@ -8280,3 +8281,23 @@ qemuDomainNamespaceTeardownRNG(virQEMUDriverPtr driver, cleanup: return ret; } + + +void +qemuDomainIOThreadUpdate(virDomainIOThreadIDDefPtr iothread, + qemuMonitorIOThreadInfoPtr iothread_info, + bool supportPolling) +{ + iothread->thread_id = iothread_info->thread_id; + + if (supportPolling && iothread->poll_enabled == VIR_TRISTATE_BOOL_ABSENT) { + iothread->poll_max_ns = iothread_info->poll_max_ns; + iothread->poll_grow = iothread_info->poll_grow; + iothread->poll_shrink = iothread_info->poll_shrink; + + if (iothread->poll_max_ns == 0) + iothread->poll_enabled = VIR_TRISTATE_BOOL_NO; + else + iothread->poll_enabled = VIR_TRISTATE_BOOL_YES; + } +} diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 8ba807c656..900b689411 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -848,4 +848,10 @@ int qemuDomainNamespaceSetupRNG(virQEMUDriverPtr driver, int qemuDomainNamespaceTeardownRNG(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainRNGDefPtr rng); + +void qemuDomainIOThreadUpdate(virDomainIOThreadIDDefPtr iothread, + qemuMonitorIOThreadInfoPtr iothread_info, + bool supportPolling) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + #endif /* __QEMU_DOMAIN_H__ */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ff610a7692..9e3691b575 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5581,6 +5581,7 @@ qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver, unsigned int orig_niothreads = vm->def->niothreadids; unsigned int exp_niothreads = vm->def->niothreadids; int new_niothreads = 0; + bool supportPolling = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_IOTHREAD_POLLING); qemuMonitorIOThreadInfoPtr *new_iothreads = NULL; virDomainIOThreadIDDefPtr iothrid; @@ -5599,7 +5600,8 @@ qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver, * and add the thread_id to the vm->def->iothreadids list. */ if ((new_niothreads = qemuMonitorGetIOThreads(priv->mon, - &new_iothreads, false)) < 0) + &new_iothreads, + supportPolling)) < 0) goto exit_monitor; if (qemuDomainObjExitMonitor(driver, vm) < 0) @@ -5632,7 +5634,7 @@ qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver, if (!(iothrid = virDomainIOThreadIDAdd(vm->def, iothread_id))) goto cleanup; - iothrid->thread_id = new_iothreads[idx]->thread_id; + qemuDomainIOThreadUpdate(iothrid, new_iothreads[idx], supportPolling); if (qemuProcessSetupIOThread(vm, iothrid) < 0) goto cleanup; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 9eb4dfd5fa..4f64c0e7d6 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2100,11 +2100,12 @@ qemuProcessDetectIOThreadPIDs(virQEMUDriverPtr driver, int niothreads = 0; int ret = -1; size_t i; + bool supportPolling = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_IOTHREAD_POLLING); /* Get the list of IOThreads from qemu */ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) goto cleanup; - niothreads = qemuMonitorGetIOThreads(priv->mon, &iothreads, false); + niothreads = qemuMonitorGetIOThreads(priv->mon, &iothreads, supportPolling); if (qemuDomainObjExitMonitor(driver, vm) < 0) goto cleanup; if (niothreads < 0) @@ -2134,7 +2135,7 @@ qemuProcessDetectIOThreadPIDs(virQEMUDriverPtr driver, iothreads[i]->iothread_id); goto cleanup; } - iothrid->thread_id = iothreads[i]->thread_id; + qemuDomainIOThreadUpdate(iothrid, iothreads[i], supportPolling); } ret = 0; @@ -4571,6 +4572,15 @@ qemuProcessStartValidateIOThreads(virDomainObjPtr vm, return -1; } + for (i = 0; i < vm->def->niothreadids; i++) { + if (vm->def->iothreadids[i]->poll_enabled != VIR_TRISTATE_BOOL_ABSENT && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_IOTHREAD_POLLING)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("IOThreads polling is not supported for this QEMU")); + return -1; + } + } + for (i = 0; i < vm->def->ncontrollers; i++) { virDomainControllerDefPtr cont = vm->def->controllers[i]; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-disabled.args b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-disabled.args new file mode 100644 index 0000000000..e9b53f0976 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-disabled.args @@ -0,0 +1,23 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu \ +-name QEMUGuest1 \ +-S \ +-M pc \ +-m 214 \ +-smp 2,sockets=2,cores=1,threads=1 \ +-object iothread,id=iothread1,poll-max-ns=0 \ +-object iothread,id=iothread2 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-QEMUGuest1/monitor.sock,server,nowait \ +-no-acpi \ +-boot c \ +-usb \ +-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \ +-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-disabled.xml b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-disabled.xml new file mode 100644 index 0000000000..f9d769f860 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-disabled.xml @@ -0,0 +1,36 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>2</vcpu> + <iothreads>2</iothreads> + <iothreadids> + <iothread id='1'> + <polling enabled='no'/> + </iothread> + </iothreadids> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-enabled.args b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-enabled.args new file mode 100644 index 0000000000..b3495dfe9c --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-enabled.args @@ -0,0 +1,23 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu \ +-name QEMUGuest1 \ +-S \ +-M pc \ +-m 214 \ +-smp 2,sockets=2,cores=1,threads=1 \ +-object iothread,id=iothread1,poll-max-ns=4000 \ +-object iothread,id=iothread2 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-QEMUGuest1/monitor.sock,server,nowait \ +-no-acpi \ +-boot c \ +-usb \ +-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \ +-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-enabled.xml b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-enabled.xml new file mode 100644 index 0000000000..44b6e2e219 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-enabled.xml @@ -0,0 +1,36 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>2</vcpu> + <iothreads>2</iothreads> + <iothreadids> + <iothread id='1'> + <polling enabled='yes' max_ns='4000'/> + </iothread> + </iothreadids> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-not-supported.xml b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-not-supported.xml new file mode 120000 index 0000000000..5b40c52a2d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-polling-not-supported.xml @@ -0,0 +1 @@ +qemuxml2argv-iothreads-polling-enabled.xml \ No newline at end of file diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index f55b04b057..603e43d295 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1507,6 +1507,14 @@ mymain(void) DO_TEST("iothreads-virtio-scsi-ccw", QEMU_CAPS_OBJECT_IOTHREAD, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_VIRTIO_SCSI_IOTHREAD, QEMU_CAPS_VIRTIO_CCW, QEMU_CAPS_VIRTIO_S390); + DO_TEST("iothreads-polling-enabled", + QEMU_CAPS_OBJECT_IOTHREAD, + QEMU_CAPS_IOTHREAD_POLLING); + DO_TEST("iothreads-polling-disabled", + QEMU_CAPS_OBJECT_IOTHREAD, + QEMU_CAPS_IOTHREAD_POLLING); + DO_TEST_FAILURE("iothreads-polling-not-supported", + QEMU_CAPS_OBJECT_IOTHREAD); DO_TEST("cpu-topology1", NONE); DO_TEST("cpu-topology2", NONE); -- 2.11.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list