[libvirt] [PATCH 09/12] qemu: implement iothread polling

Pavel Hrdina phrdina at redhat.com
Tue Feb 21 12:15:05 UTC 2017


Signed-off-by: Pavel Hrdina <phrdina at 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




More information about the libvir-list mailing list