Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
---
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