[PATCH v2 0/7] qemu: add poll-weight support for iothreads
This series adds support for the QEMU iothread poll-weight property, which controls the weight of the most recent event interval in the adaptive polling duration calculation. The valid range is [0, 63]; a value of 0 lets QEMU use its default weight. Changes in v2: - Move the formatdomain docs patch right after the XML parser/formatter patch - Fix the docs description: "If omitted, the value is not changed" rather than "If omitted or set to 0, the hypervisor selects a default" - Split the getter/stats path (patch 4) from the setter/cmdline path (patch 5), and drop the qemuBuildIOThreadCommandLine qemuCaps parameter since CAPS validation is handled by qemuValidateDomainDefIOThreads - Separate the test driver changes into its own patch (patch 6) with the corresponding iothreads.out updates split accordingly - Move the domstats documentation hunk into the stats patch (patch 4) - Add a qemuxmlconf parse-error test for out-of-range weight values - Fix Since version: 12.6.0 -> 12.7.0 (Peter Krempa) - Drop the docs: fix typos patch (already applied upstream) The series was validated with: meson test -C build virschematest meson test -C build qemucapabilitiestest meson test -C build qemuxmlconftest meson test -C build virshtest meson test -C build genericxml2xmltest QEMU commits: 9fea80ddf0 qapi/iothread: introduce poll-weight parameter for aio-poll 9563d0b5e2 aio-poll: refine iothread polling using weighted handler intervals ed21d9d65c aio-poll: avoid unnecessary polling time computation Jaehoon Kim (7): conf: add iothread poll-weight XML support docs: formatdomain: document iothread poll-weight qemu: capabilities: add capability for iothread poll-weight qemu: add poll-weight getter and stats support qemu: support iothread poll-weight test: add poll-weight support to the test driver virsh: add iothreadset --poll-weight support docs/formatdomain.rst | 8 ++- docs/manpages/virsh.rst | 18 ++++-- include/libvirt/libvirt-domain.h | 25 ++++++++ src/conf/domain_conf.c | 14 ++++- src/conf/domain_conf.h | 2 + src/conf/domain_validate.c | 7 +++ src/conf/schemas/domaincommon.rng | 5 ++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 6 ++ src/qemu/qemu_driver.c | 38 ++++++++++++ src/qemu/qemu_monitor.h | 2 + src/qemu/qemu_monitor_json.c | 18 ++++++ src/qemu/qemu_validate.c | 10 +++- src/test/test_driver.c | 12 ++++ tests/genericxml2xmlindata/iothreadids.xml | 2 +- .../caps_11.1.0_aarch64.xml | 1 + .../caps_11.1.0_x86_64.xml | 1 + ...s-poll-weight-outofrange.x86_64-latest.err | 1 + .../iothreads-ids-poll-weight-outofrange.xml | 58 +++++++++++++++++++ ...threads-ids-poll-weight.x86_64-latest.args | 40 +++++++++++++ ...othreads-ids-poll-weight.x86_64-latest.xml | 58 +++++++++++++++++++ .../iothreads-ids-poll-weight.xml | 58 +++++++++++++++++++ tests/qemuxmlconftest.c | 2 + tests/virshtestdata/iothreads.in | 2 + tests/virshtestdata/iothreads.out | 18 ++++++ tools/virsh-domain.c | 17 ++++++ 27 files changed, 415 insertions(+), 11 deletions(-) create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight-outofrange.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight-outofrange.xml create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight.xml -- 2.54.0
Add support for the iothread poll-weight XML attribute. Store the value in the internal iothread definition, parse it from the <poll/> element, and format it back into domain XML. Also extend the schema to accept the new attribute and enforce the accepted range of [0, 63] in the domain validator. Signed-off-by: Jaehoon Kim <jhkim@linux.ibm.com> --- src/conf/domain_conf.c | 14 +++++++++++++- src/conf/domain_conf.h | 2 ++ src/conf/domain_validate.c | 7 +++++++ src/conf/schemas/domaincommon.rng | 5 +++++ tests/genericxml2xmlindata/iothreadids.xml | 2 +- 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 45235d74bc..0cd0a22708 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -16988,7 +16988,9 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt, * * <iothreads>4</iothreads> * <iothreadids> - * <iothread id='1' thread_pool_min="0" thread_pool_max="60"/> + * <iothread id='1' thread_pool_min="0" thread_pool_max="60"> + * <poll max='32000' grow='2' shrink='2' weight='3'/> + * </iothread> * <iothread id='3'/> * <iothread id='5'/> * <iothread id='7'/> @@ -17036,6 +17038,12 @@ virDomainIOThreadIDDefParseXML(xmlNodePtr node) return NULL; iothrid->set_poll_shrink = rc == 1; + + if ((rc = virXMLPropUInt(pollNode, "weight", 10, VIR_XML_PROP_NONE, + &iothrid->poll_weight)) < 0) + return NULL; + + iothrid->set_poll_weight = rc == 1; } return g_steal_pointer(&iothrid); @@ -29015,6 +29023,7 @@ virDomainDefIothreadShouldFormat(const virDomainDef *def) def->iothreadids[i]->set_poll_max_ns || def->iothreadids[i]->set_poll_grow || def->iothreadids[i]->set_poll_shrink || + def->iothreadids[i]->set_poll_weight || def->iothreadids[i]->thread_pool_min >= 0 || def->iothreadids[i]->thread_pool_max >= 0) return true; @@ -29088,6 +29097,9 @@ virDomainDefIOThreadsFormat(virBuffer *buf, if (iothread->set_poll_shrink) virBufferAsprintf(&pollAttrBuf, " shrink='%llu'", iothread->poll_shrink); + if (iothread->set_poll_weight) + virBufferAsprintf(&pollAttrBuf, " weight='%u'", iothread->poll_weight); + virXMLFormatElement(&iothreadChildBuf, "poll", &pollAttrBuf, NULL); virXMLFormatElement(&childrenBuf, "iothread", &attrBuf, &iothreadChildBuf); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 91f57de0f1..57c26d4070 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2902,6 +2902,8 @@ struct _virDomainIOThreadIDDef { bool set_poll_grow; unsigned long long poll_shrink; bool set_poll_shrink; + unsigned int poll_weight; + bool set_poll_weight; int thread_pool_min; int thread_pool_max; diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index 3946f92182..ab998de716 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -1931,6 +1931,13 @@ virDomainDefValidateIOThreads(const virDomainDef *def) if (virDomainDefValidateIOThreadsThreadPool(iothread->thread_pool_min, iothread->thread_pool_max) < 0) return -1; + + if (iothread->set_poll_weight && iothread->poll_weight > 63) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("poll weight %1$u is out of range [0, 63]"), + iothread->poll_weight); + return -1; + } } if (def->defaultIOThread && diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 81ffbfc2fa..1b6f972cec 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -990,6 +990,11 @@ <ref name="unsignedLong"/> </attribute> </optional> + <optional> + <attribute name="weight"> + <ref name="unsignedInt"/> + </attribute> + </optional> </element> </optional> </element> diff --git a/tests/genericxml2xmlindata/iothreadids.xml b/tests/genericxml2xmlindata/iothreadids.xml index 671a467295..e9814854eb 100644 --- a/tests/genericxml2xmlindata/iothreadids.xml +++ b/tests/genericxml2xmlindata/iothreadids.xml @@ -7,7 +7,7 @@ <iothreads>1</iothreads> <iothreadids> <iothread id='8' thread_pool_min='2147483647' thread_pool_max='2147483647'> - <poll max='9223372036854775807' grow='456' shrink='789'/> + <poll max='9223372036854775807' grow='456' shrink='789' weight='3'/> </iothread> </iothreadids> <os> -- 2.54.0
Document the iothread poll-weight XML attribute in formatdomain. Extend the description of iothread polling controls to cover the new poll-weight attribute and how it relates to the existing poll-max, poll-grow, and poll-shrink settings. Also document the accepted range and the meaning of zero as a request for the hypervisor default. Signed-off-by: Jaehoon Kim <jhkim@linux.ibm.com> --- docs/formatdomain.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 28c9170a37..7d2440abc6 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -815,7 +815,7 @@ host/guest with many LUNs. :since:`Since 1.2.8 (QEMU only)` <iothread id="4"/> <iothread id="6"/> <iothread id="8" thread_pool_min="2" thread_pool_max="32"> - <poll max='123' grow='456' shrink='789'/> + <poll max='123' grow='456' shrink='789' weight='3'/> </iothread> </iothreadids> <defaultiothread thread_pool_min="8" thread_pool_max="16"/> @@ -849,6 +849,12 @@ host/guest with many LUNs. :since:`Since 1.2.8 (QEMU only)` polling. Attributes ``grow`` and ``shrink`` override (or disable when set to ``0``) the default steps for increasing/decreasing the polling interval if the set interval is deemed insufficient or excessive. + :since:`Since 12.7.0` the optional attribute ``weight`` sets the shift value + for the adaptive polling algorithm, controlling how much the most recent + event interval affects the next polling duration calculation. Larger values + decrease the weight of recent events, producing more gradual adjustments. + Valid range is ``[0, 63]``. Omitting ``weight`` or setting it to ``0`` lets + the hypervisor select its default value. ``defaultiothread`` This element represents the default event loop within hypervisor, where I/O requests from devices not assigned to a specific IOThread are processed. -- 2.54.0
Add a capability flag for the iothread poll-weight property. Detect support for the property from the QMP schema so that libvirt can conditionally expose and use poll-weight only with QEMU binaries that support it. Signed-off-by: Jaehoon Kim <jhkim@linux.ibm.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml | 1 + 4 files changed, 5 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 61e44b398a..d5ebd4a1f7 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -768,6 +768,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 495 */ "blockdev-mirror.target-is-zero", /* QEMU_CAPS_BLOCKDEV_MIRROR_TARGET_IS_ZERO */ "object-monitor-qmp", /* QEMU_CAPS_OBJECT_MONITOR_QMP */ + "iothread.poll-weight", /* QEMU_CAPS_IOTHREAD_POLL_WEIGHT */ ); @@ -1670,6 +1671,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = { { "netdev_add/arg-type/+stream/reconnect-ms", QEMU_CAPS_NETDEV_STREAM_RECONNECT_MILISECONDS }, { "object-add/arg-type/+sev-guest/kernel-hashes", QEMU_CAPS_SEV_GUEST_KERNEL_HASHES }, { "object-add/arg-type/+iothread/thread-pool-max", QEMU_CAPS_IOTHREAD_THREAD_POOL_MAX }, + { "object-add/arg-type/+iothread/poll-weight", QEMU_CAPS_IOTHREAD_POLL_WEIGHT }, { "query-block/arg-type/flat", QEMU_CAPS_QUERY_BLOCK_FLAT }, { "query-display-options/ret-type/+egl-headless/rendernode", QEMU_CAPS_EGL_HEADLESS_RENDERNODE }, { "query-display-options/ret-type/+sdl", QEMU_CAPS_SDL }, diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index c846771d50..a4404a5ded 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -742,6 +742,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 495 */ QEMU_CAPS_BLOCKDEV_MIRROR_TARGET_IS_ZERO, /* 'blockdev-mirror' supports 'target-is-zero' */ QEMU_CAPS_OBJECT_MONITOR_QMP, /* 'monitor-qmp' -object */ + QEMU_CAPS_IOTHREAD_POLL_WEIGHT, /* -object iothread.poll-weight */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml index 9e14171d64..0f555665be 100644 --- a/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml @@ -188,6 +188,7 @@ <flag name='query-block-flat'/> <flag name='blockdev-mirror.target-is-zero'/> <flag name='object-monitor-qmp'/> + <flag name='iothread.poll-weight'/> <version>11000090</version> <microcodeVersion>61700287</microcodeVersion> <package>v11.1.0-rc0</package> diff --git a/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml index e32cedca2f..c1df633822 100644 --- a/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml @@ -222,6 +222,7 @@ <flag name='amd-iommu.xtsup'/> <flag name='blockdev-mirror.target-is-zero'/> <flag name='object-monitor-qmp'/> + <flag name='iothread.poll-weight'/> <version>11000090</version> <microcodeVersion>43100287</microcodeVersion> <package>v11.1.0-rc0</package> -- 2.54.0
Add support for reading the iothread poll-weight value from QEMU and exposing it via domain stats. Add poll_weight and set_poll_weight fields to qemuMonitorIOThreadInfo and parse the poll-weight property from the QMP query-iothreads response. The property is optional and only present on newer QEMU binaries. Expose the fetched value through the domain stats interface by adding VIR_DOMAIN_STATS_IOTHREAD_SUFFIX_POLL_WEIGHT and reporting it in qemuDomainGetStatsIOThread when the value is available. Signed-off-by: Jaehoon Kim <jhkim@linux.ibm.com> --- docs/manpages/virsh.rst | 2 ++ include/libvirt/libvirt-domain.h | 10 ++++++++++ src/qemu/qemu_driver.c | 5 +++++ src/qemu/qemu_monitor.h | 2 ++ src/qemu/qemu_monitor_json.c | 5 +++++ 5 files changed, 24 insertions(+) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index a10d29e0ea..8465f19c12 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -2905,6 +2905,8 @@ not available for statistical purposes. growth is managed by the hypervisor. * ``iothread.<id>.poll-shrink`` - polling time shrink value. A value of (zero) indicates shrink is managed by hypervisor. +* ``iothread.<id>.poll-weight`` - polling weight shift value. A value of 0 + (zero) indicates the hypervisor's default weight is used. *--memory* returns: diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index f4dfe9fb1a..bb524f41ee 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -4330,6 +4330,16 @@ struct _virDomainStatsRecord { */ # define VIR_DOMAIN_STATS_IOTHREAD_SUFFIX_POLL_SHRINK ".poll-shrink" +/** + * VIR_DOMAIN_STATS_IOTHREAD_SUFFIX_POLL_WEIGHT: + * + * Polling weight factor as an unsigned int. This shift value controls how + * much the most recent event interval affects adaptive polling calculations. + * A 0 (zero) indicates the hypervisor's default weight is used. + * + * Since: 12.7.0 + */ +# define VIR_DOMAIN_STATS_IOTHREAD_SUFFIX_POLL_WEIGHT ".poll-weight" /** * VIR_DOMAIN_STATS_MEMORY_BANDWIDTH_MONITOR_COUNT: diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 44b41726fb..842b56a2c2 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -18411,6 +18411,11 @@ qemuDomainGetStatsIOThread(virQEMUDriver *driver G_GNUC_UNUSED, VIR_DOMAIN_STATS_IOTHREAD_PREFIX "%u" VIR_DOMAIN_STATS_IOTHREAD_SUFFIX_POLL_SHRINK, iothreads[i]->iothread_id); } + if (iothreads[i]->set_poll_weight) { + virTypedParamListAddUInt(params, iothreads[i]->poll_weight, + VIR_DOMAIN_STATS_IOTHREAD_PREFIX "%u" VIR_DOMAIN_STATS_IOTHREAD_SUFFIX_POLL_WEIGHT, + iothreads[i]->iothread_id); + } } for (i = 0; i < niothreads; i++) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 3298095e9c..e560618bf4 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1583,11 +1583,13 @@ struct _qemuMonitorIOThreadInfo { unsigned long long poll_max_ns; unsigned long long poll_grow; unsigned long long poll_shrink; + unsigned int poll_weight; int thread_pool_min; int thread_pool_max; bool set_poll_max_ns; bool set_poll_grow; bool set_poll_shrink; + bool set_poll_weight; bool set_thread_pool_min; bool set_thread_pool_max; }; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index af9a77ed3b..b02c0722d9 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7202,6 +7202,11 @@ qemuMonitorJSONGetIOThreads(qemuMonitor *mon, virJSONValueObjectGetNumberUlong(child, "poll-shrink", &info->poll_shrink) == 0) info->poll_valid = true; + + /* poll-weight is optional, only present on newer QEMU */ + if (virJSONValueObjectGetNumberUint(child, "poll-weight", + &info->poll_weight) == 0) + info->set_poll_weight = true; } *niothreads = n; -- 2.54.0
Wire the poll-weight setting into the QEMU command line, monitor, and driver-side parameter handling. Add poll-weight to the iothread object properties when building the QEMU command line. Add the live setter in the monitor JSON layer using a new VIR_IOTHREAD_SET_PROP_UINT macro consistent with the existing UL variant. Wire up typed parameter parsing with an explicit range check for [0, 63] and propagate the value into the persistent domain definition on hotplug. Guard the live path with a capability check. Add a CAPS check in the domain validator and remove the now-unnecessary break from the thread pool validation loop since the loop must continue to check poll-weight on every iothread. Also add VIR_DOMAIN_IOTHREAD_POLL_WEIGHT typed parameter constant and a qemuxmlconf test case for the new functionality. Signed-off-by: Jaehoon Kim <jhkim@linux.ibm.com> --- include/libvirt/libvirt-domain.h | 15 +++++ src/qemu/qemu_command.c | 6 ++ src/qemu/qemu_driver.c | 33 +++++++++++ src/qemu/qemu_monitor_json.c | 13 +++++ src/qemu/qemu_validate.c | 10 +++- ...s-poll-weight-outofrange.x86_64-latest.err | 1 + .../iothreads-ids-poll-weight-outofrange.xml | 58 +++++++++++++++++++ ...threads-ids-poll-weight.x86_64-latest.args | 40 +++++++++++++ ...othreads-ids-poll-weight.x86_64-latest.xml | 58 +++++++++++++++++++ .../iothreads-ids-poll-weight.xml | 58 +++++++++++++++++++ tests/qemuxmlconftest.c | 2 + 11 files changed, 292 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight-outofrange.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight-outofrange.xml create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight.xml diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index bb524f41ee..33dc700755 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -2748,6 +2748,21 @@ int virDomainDelIOThread(virDomainPtr domain, */ # define VIR_DOMAIN_IOTHREAD_POLL_SHRINK "poll_shrink" +/** + * VIR_DOMAIN_IOTHREAD_POLL_WEIGHT: + * + * This provides a shift value for the adaptive polling algorithm to control + * how much the most recent event interval affects the next polling duration + * calculation. Larger values decrease the weight of the current interval, + * enabling more gradual adjustments. Valid range is [0, 63]. A value of 0 + * lets the hypervisor select a default weight. + * + * Accepted type is VIR_TYPED_PARAM_UINT. + * + * Since: 12.7.0 + */ +# define VIR_DOMAIN_IOTHREAD_POLL_WEIGHT "poll_weight" + /** * VIR_DOMAIN_IOTHREAD_THREAD_POOL_MIN: * diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index a76a034158..19c57eb09a 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7687,6 +7687,12 @@ qemuBuildIOThreadCommandLine(virCommand *cmd, NULL) < 0) return -1; + if (iothread->set_poll_weight && + virJSONValueObjectAdd(&props, + "u:poll-weight", iothread->poll_weight, + NULL) < 0) + return -1; + if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0) return -1; } diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 842b56a2c2..e973c91efd 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5292,6 +5292,11 @@ qemuDomainHotplugModIOThreadIDDef(virDomainIOThreadIDDef *def, def->set_poll_shrink = true; } + if (mondef.set_poll_weight) { + def->poll_weight = mondef.poll_weight; + def->set_poll_weight = true; + } + if (mondef.set_thread_pool_min) def->thread_pool_min = mondef.thread_pool_min; @@ -5384,6 +5389,11 @@ qemuDomainHotplugDelIOThread(virDomainObj *vm, * necessary. If a 0 (zero) value is provided, QEMU resets the polling * interval to 0 (zero) allowing the poll-grow to manipulate the time. * + * - "poll-weight" - weight shift value used by the adaptive polling algorithm + * to determine how much the most recent event interval influences the + * next interval calculation. Accepted range is [0, 63]. If a 0 (zero) + * value is provided, QEMU uses its default weight. + * * QEMU keeps track of the polling time elapsed and may grow or shrink the * its polling interval based upon its heuristic algorithm. It is possible * that calculations determine that it has found a "sweet spot" and no @@ -5419,6 +5429,20 @@ qemuDomainIOThreadParseParams(virTypedParameterPtr params, if (rc == 1) iothread->set_poll_shrink = true; + if ((rc = virTypedParamsGetUInt(params, nparams, + VIR_DOMAIN_IOTHREAD_POLL_WEIGHT, + &iothread->poll_weight)) < 0) + return -1; + if (rc == 1) { + if (iothread->poll_weight > 63) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("poll-weight value %1$u is out of range [0, 63]"), + iothread->poll_weight); + return -1; + } + iothread->set_poll_weight = true; + } + if ((rc = virTypedParamsGetInt(params, nparams, VIR_DOMAIN_IOTHREAD_THREAD_POOL_MIN, &iothread->thread_pool_min)) < 0) @@ -5617,6 +5641,13 @@ qemuDomainChgIOThread(virQEMUDriver *driver, if (qemuDomainIOThreadValidate(iothreaddef, iothread, true) < 0) goto endjob; + if (iothread.set_poll_weight && + !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_IOTHREAD_POLL_WEIGHT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("poll-weight is not supported by this QEMU binary")); + goto endjob; + } + if (qemuDomainHotplugModIOThread(vm, iothread) < 0) goto endjob; @@ -5747,6 +5778,8 @@ qemuDomainSetIOThreadParams(virDomainPtr dom, VIR_TYPED_PARAM_UNSIGNED, VIR_DOMAIN_IOTHREAD_POLL_SHRINK, VIR_TYPED_PARAM_UNSIGNED, + VIR_DOMAIN_IOTHREAD_POLL_WEIGHT, + VIR_TYPED_PARAM_UINT, VIR_DOMAIN_IOTHREAD_THREAD_POOL_MIN, VIR_TYPED_PARAM_INT, VIR_DOMAIN_IOTHREAD_THREAD_POOL_MAX, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index b02c0722d9..7e3249cd47 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7248,6 +7248,19 @@ qemuMonitorJSONSetIOThread(qemuMonitor *mon, #undef VIR_IOTHREAD_SET_PROP_UL +#define VIR_IOTHREAD_SET_PROP_UINT(propName, propVal) \ + if (iothreadInfo->set_##propVal) { \ + memset(&prop, 0, sizeof(prop)); \ + prop.type = QEMU_MONITOR_OBJECT_PROPERTY_UINT; \ + prop.val.ui = iothreadInfo->propVal; \ + if (qemuMonitorJSONSetObjectProperty(mon, path, propName, &prop) < 0) \ + return -1; \ + } + + VIR_IOTHREAD_SET_PROP_UINT("poll-weight", poll_weight); + +#undef VIR_IOTHREAD_SET_PROP_UINT + if (iothreadInfo->set_thread_pool_min && iothreadInfo->set_thread_pool_max) { int curr_max = -1; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index ae1edf435a..40be2e957e 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -500,9 +500,15 @@ qemuValidateDomainDefIOThreads(const virDomainDef *def, for (i = 0; i < def->niothreadids; i++) { virDomainIOThreadIDDef *iothread = def->iothreadids[i]; - if (iothread->thread_pool_min != -1 || iothread->thread_pool_max != -1) { + if (iothread->thread_pool_min != -1 || iothread->thread_pool_max != -1) needsThreadPoolCap = true; - break; + + /* poll-weight requires QEMU_CAPS_IOTHREAD_POLL_WEIGHT */ + if (iothread->set_poll_weight && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_IOTHREAD_POLL_WEIGHT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("poll-weight is not supported by this QEMU binary")); + return -1; } } diff --git a/tests/qemuxmlconfdata/iothreads-ids-poll-weight-outofrange.x86_64-latest.err b/tests/qemuxmlconfdata/iothreads-ids-poll-weight-outofrange.x86_64-latest.err new file mode 100644 index 0000000000..d3dbab3e50 --- /dev/null +++ b/tests/qemuxmlconfdata/iothreads-ids-poll-weight-outofrange.x86_64-latest.err @@ -0,0 +1 @@ +unsupported configuration: poll weight 64 is out of range [0, 63] diff --git a/tests/qemuxmlconfdata/iothreads-ids-poll-weight-outofrange.xml b/tests/qemuxmlconfdata/iothreads-ids-poll-weight-outofrange.xml new file mode 100644 index 0000000000..26bbd8ee45 --- /dev/null +++ b/tests/qemuxmlconfdata/iothreads-ids-poll-weight-outofrange.xml @@ -0,0 +1,58 @@ +<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'>4</vcpu> + <iothreads>4</iothreads> + <iothreadids> + <iothread id='1'> + <poll max='123000' grow='456' shrink='789' weight='64'/> + </iothread> + <iothread id='2'> + <poll weight='0'/> + </iothread> + <iothread id='3'> + <poll max='32000' weight='63'/> + </iothread> + <iothread id='4'> + <poll max='32000' grow='2' shrink='2'/> + </iothread> + </iothreadids> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='1' port='0x8'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/> + </controller> + <controller type='pci' index='2' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='2' port='0x9'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='usb' index='0' model='qemu-xhci'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </controller> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <watchdog model='itco' action='reset'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/iothreads-ids-poll-weight.x86_64-latest.args b/tests/qemuxmlconfdata/iothreads-ids-poll-weight.x86_64-latest.args new file mode 100644 index 0000000000..d73060ad46 --- /dev/null +++ b/tests/qemuxmlconfdata/iothreads-ids-poll-weight.x86_64-latest.args @@ -0,0 +1,40 @@ +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 '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine q35,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ +-accel tcg \ +-cpu qemu64 \ +-m size=219136k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 4,sockets=4,cores=1,threads=1 \ +-object '{"qom-type":"iothread","id":"iothread1","poll-max-ns":123000,"poll-grow":456,"poll-shrink":789,"poll-weight":3}' \ +-object '{"qom-type":"iothread","id":"iothread2","poll-weight":0}' \ +-object '{"qom-type":"iothread","id":"iothread3","poll-max-ns":32000,"poll-weight":63}' \ +-object '{"qom-type":"iothread","id":"iothread4","poll-max-ns":32000,"poll-grow":2,"poll-shrink":2}' \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=@mon-fd@,server=on,wait=off \ +-object '{"qom-type":"monitor-qmp","id":"monitor","chardev":"charmonitor"}' \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"pcie-root-port","port":8,"chassis":1,"id":"pci.1","bus":"pcie.0","multifunction":true,"addr":"0x1"}' \ +-device '{"driver":"pcie-root-port","port":9,"chassis":2,"id":"pci.2","bus":"pcie.0","addr":"0x1.0x1"}' \ +-device '{"driver":"qemu-xhci","id":"usb","bus":"pci.1","addr":"0x0"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-global ICH9-LPC.noreboot=off \ +-watchdog-action reset \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/iothreads-ids-poll-weight.x86_64-latest.xml b/tests/qemuxmlconfdata/iothreads-ids-poll-weight.x86_64-latest.xml new file mode 100644 index 0000000000..1134d9ffdd --- /dev/null +++ b/tests/qemuxmlconfdata/iothreads-ids-poll-weight.x86_64-latest.xml @@ -0,0 +1,58 @@ +<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'>4</vcpu> + <iothreads>4</iothreads> + <iothreadids> + <iothread id='1'> + <poll max='123000' grow='456' shrink='789' weight='3'/> + </iothread> + <iothread id='2'> + <poll weight='0'/> + </iothread> + <iothread id='3'> + <poll max='32000' weight='63'/> + </iothread> + <iothread id='4'> + <poll max='32000' grow='2' shrink='2'/> + </iothread> + </iothreadids> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='1' port='0x8'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/> + </controller> + <controller type='pci' index='2' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='2' port='0x9'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='usb' index='0' model='qemu-xhci'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </controller> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <watchdog model='itco' action='reset'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/iothreads-ids-poll-weight.xml b/tests/qemuxmlconfdata/iothreads-ids-poll-weight.xml new file mode 100644 index 0000000000..1134d9ffdd --- /dev/null +++ b/tests/qemuxmlconfdata/iothreads-ids-poll-weight.xml @@ -0,0 +1,58 @@ +<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'>4</vcpu> + <iothreads>4</iothreads> + <iothreadids> + <iothread id='1'> + <poll max='123000' grow='456' shrink='789' weight='3'/> + </iothread> + <iothread id='2'> + <poll weight='0'/> + </iothread> + <iothread id='3'> + <poll max='32000' weight='63'/> + </iothread> + <iothread id='4'> + <poll max='32000' grow='2' shrink='2'/> + </iothread> + </iothreadids> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='1' port='0x8'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/> + </controller> + <controller type='pci' index='2' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='2' port='0x9'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='usb' index='0' model='qemu-xhci'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </controller> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <watchdog model='itco' action='reset'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index f9e426f4eb..298dded032 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -2333,6 +2333,8 @@ mymain(void) DO_TEST_CAPS_LATEST("iothreads-ids"); DO_TEST_CAPS_LATEST("iothreads-ids-partial"); DO_TEST_CAPS_LATEST("iothreads-ids-pool-sizes"); + DO_TEST_CAPS_LATEST("iothreads-ids-poll-weight"); + DO_TEST_CAPS_LATEST_PARSE_ERROR("iothreads-ids-poll-weight-outofrange"); DO_TEST_CAPS_LATEST("iothreads-disk"); DO_TEST_CAPS_LATEST("iothreads-virtio-scsi-pci"); DO_TEST_CAPS_LATEST("iothreads-virtio-scsi-mapping"); -- 2.54.0
Add poll-weight support to the test driver so that the virsh test suite can exercise the iothreadset --poll-weight path end-to-end. Add a poll_weight field to the testIOThreadInfo struct and initialise it to 0 in both testDomainGenerateIOThreadInfos and testDomainAddIOThread. Extend testDomainIOThreadParseParams to accept and store VIR_DOMAIN_IOTHREAD_POLL_WEIGHT, and extend testDomainGetStatsIOThread to emit the value via domstats. Update the expected iothreads.out output to include the poll-weight=0 field in the existing domstats blocks now that the test driver reports it unconditionally. Signed-off-by: Jaehoon Kim <jhkim@linux.ibm.com> --- src/test/test_driver.c | 12 ++++++++++++ tests/virshtestdata/iothreads.out | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 536e291861..8546c3e251 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -189,6 +189,7 @@ struct _testIOThreadInfo { unsigned long long poll_max_ns; unsigned int poll_grow; unsigned int poll_shrink; + unsigned int poll_weight; }; static void @@ -749,6 +750,7 @@ testDomainGenerateIOThreadInfos(virDomainObj *obj) iothread.poll_max_ns = 32768; iothread.poll_grow = 0; iothread.poll_shrink = 0; + iothread.poll_weight = 0; g_array_append_val(priv->iothreads, iothread); } } @@ -9681,6 +9683,7 @@ testDomainAddIOThread(virDomainPtr dom, iothread.poll_max_ns = 32768; iothread.poll_grow = 0; iothread.poll_shrink = 0; + iothread.poll_weight = 0; g_array_append_val(priv->iothreads, iothread); @@ -9795,6 +9798,8 @@ testDomainIOThreadParseParams(virTypedParameterPtr params, VIR_TYPED_PARAM_UINT, VIR_DOMAIN_IOTHREAD_POLL_SHRINK, VIR_TYPED_PARAM_UINT, + VIR_DOMAIN_IOTHREAD_POLL_WEIGHT, + VIR_TYPED_PARAM_UINT, NULL) < 0) return -1; @@ -9813,6 +9818,11 @@ testDomainIOThreadParseParams(virTypedParameterPtr params, &iothread->poll_shrink) < 0) return -1; + if (virTypedParamsGetUInt(params, nparams, + VIR_DOMAIN_IOTHREAD_POLL_WEIGHT, + &iothread->poll_weight) < 0) + return -1; + return 0; } @@ -9899,6 +9909,8 @@ testDomainGetStatsIOThread(virDomainObj *dom, "iothread.%u.poll-grow", iothread.iothread_id); virTypedParamListAddUInt(params, iothread.poll_shrink, "iothread.%u.poll-shrink", iothread.iothread_id); + virTypedParamListAddUInt(params, iothread.poll_weight, + "iothread.%u.poll-weight", iothread.iothread_id); } return 0; diff --git a/tests/virshtestdata/iothreads.out b/tests/virshtestdata/iothreads.out index 1e38733bcf..4526a00313 100644 --- a/tests/virshtestdata/iothreads.out +++ b/tests/virshtestdata/iothreads.out @@ -23,9 +23,11 @@ Domain: 'fc4' iothread.4.poll-max-ns=32768 iothread.4.poll-grow=0 iothread.4.poll-shrink=0 + iothread.4.poll-weight=0 iothread.6.poll-max-ns=32768 iothread.6.poll-grow=0 iothread.6.poll-shrink=0 + iothread.6.poll-weight=0 Domain: 'fc4' @@ -35,9 +37,11 @@ Domain: 'fc4' iothread.4.poll-max-ns=32768 iothread.4.poll-grow=0 iothread.4.poll-shrink=0 + iothread.4.poll-weight=0 iothread.6.poll-max-ns=100 iothread.6.poll-grow=10 iothread.6.poll-shrink=10 + iothread.6.poll-weight=0 IOThread ID CPU Affinity -- 2.54.0
Extend iothreadset to allow configuring the iothread poll-weight value from the command line. Add a --poll-weight option to opts_iothreadset and wire it up in cmdIOThreadSet. The value is validated against the accepted range [0, 63] before being passed to the backend as VIR_DOMAIN_IOTHREAD_POLL_WEIGHT. If the option is omitted the parameter is not added to the list and the backend leaves the value unchanged. Document --poll-weight in the iothreadset section of the virsh manpage and update the syntax synopsis to include the new option. Extend the virsh test suite with an iothreadset --poll-weight 3 call followed by a domstats check that confirms the updated value is reflected. Signed-off-by: Jaehoon Kim <jhkim@linux.ibm.com> --- docs/manpages/virsh.rst | 16 ++++++++++------ tests/virshtestdata/iothreads.in | 2 ++ tests/virshtestdata/iothreads.out | 14 ++++++++++++++ tools/virsh-domain.c | 17 +++++++++++++++++ 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 8465f19c12..e1b08a299a 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -3500,8 +3500,8 @@ iothreadset :: iothreadset domain iothread_id [[--poll-max-ns ns] [--poll-grow factor] - [--poll-shrink divisor] [--thread-pool-min value] - [--thread-pool-max value]] + [--poll-shrink divisor] [--poll-weight factor] + [--thread-pool-min value] [--thread-pool-max value]] [[--config] [--live] | [--current]] Modifies an existing iothread of the domain using the specified @@ -3513,10 +3513,14 @@ reach the maximum polling time. If a 0 (zero) is provided, then the default factor will be used. The *--poll-shrink* is the quotient by which the current polling time will be reduced in order to get below the maximum polling interval. If a 0 (zero) is provided, then -the default quotient will be used. The polling values are purely dynamic -for a running guest. Saving, destroying, stopping, etc. the guest will -result in the polling values returning to hypervisor defaults at the -next start, restore, etc. +the default quotient will be used. The *--poll-weight* sets the weight +shift value for adaptive polling, determining how much the most recent +event interval affects the next polling duration calculation. Larger +values reduce the weight of recent events. Valid range is [0, 63]. +If omitted, the value is not changed. The polling values are purely +dynamic for a running guest. Saving, destroying, stopping, etc. the +guest will result in the polling values returning to hypervisor defaults +at the next start, restore, etc. The *--thread-pool-min* and *--thread-pool-max* options then set lower and upper bound, respectively of number of threads in worker pool of given diff --git a/tests/virshtestdata/iothreads.in b/tests/virshtestdata/iothreads.in index 25ebcb5cda..b5aed83bba 100644 --- a/tests/virshtestdata/iothreads.in +++ b/tests/virshtestdata/iothreads.in @@ -7,6 +7,8 @@ iothreadinfo --domain fc4 domstats --domain fc4 iothreadset --domain fc4 --id 6 --poll-max-ns 100 --poll-shrink 10 --poll-grow 10 domstats --domain fc4 +iothreadset --domain fc4 --id 6 --poll-weight 3 +domstats --domain fc4 iothreadadd --domain fc5 --id 2 iothreadinfo --domain fc5 diff --git a/tests/virshtestdata/iothreads.out b/tests/virshtestdata/iothreads.out index 4526a00313..a51593d765 100644 --- a/tests/virshtestdata/iothreads.out +++ b/tests/virshtestdata/iothreads.out @@ -44,6 +44,20 @@ Domain: 'fc4' iothread.6.poll-weight=0 +Domain: 'fc4' + state.state=1 + state.reason=0 + iothread.count=2 + iothread.4.poll-max-ns=32768 + iothread.4.poll-grow=0 + iothread.4.poll-shrink=0 + iothread.4.poll-weight=0 + iothread.6.poll-max-ns=100 + iothread.6.poll-grow=10 + iothread.6.poll-shrink=10 + iothread.6.poll-weight=3 + + IOThread ID CPU Affinity ----------------------------- 2 0-3 diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 0f177fb69a..c5158889cc 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -8271,6 +8271,11 @@ static const vshCmdOptDef opts_iothreadset[] = { .unwanted_positional = true, .help = N_("set the value for reduction of the IOThread polling time") }, + {.name = "poll-weight", + .type = VSH_OT_INT, + .unwanted_positional = true, + .help = N_("set the adaptive polling weight factor") + }, {.name = "thread-pool-min", .type = VSH_OT_INT, .unwanted_positional = true, @@ -8300,6 +8305,7 @@ cmdIOThreadSet(vshControl *ctl, const vshCmd *cmd) virTypedParameterPtr par; size_t npar = 0; unsigned long long poll_val; + unsigned int poll_weight; int thread_val; int rc; @@ -8336,6 +8342,17 @@ cmdIOThreadSet(vshControl *ctl, const vshCmd *cmd) if (rc > 0) virTypedParamListAddUnsigned(params, poll_val, VIR_DOMAIN_IOTHREAD_POLL_SHRINK); + if ((rc = vshCommandOptUInt(ctl, cmd, "poll-weight", &poll_weight)) < 0) + return false; + if (rc > 0) { + if (poll_weight > 63) { + vshError(ctl, _("poll-weight value %1$u is out of range [0, 63]"), + poll_weight); + return false; + } + virTypedParamListAddUInt(params, poll_weight, VIR_DOMAIN_IOTHREAD_POLL_WEIGHT); + } + if ((rc = vshCommandOptInt(ctl, cmd, "thread-pool-min", &thread_val)) < 0) return false; if (rc > 0) -- 2.54.0
Hi, Just a gentle ping on this v2 series. Any feedback would be appreciated. Thanks, Jaehoon On 8/1/2026 12:04 PM, Jaehoon Kim wrote:
This series adds support for the QEMU iothread poll-weight property, which controls the weight of the most recent event interval in the adaptive polling duration calculation. The valid range is [0, 63]; a value of 0 lets QEMU use its default weight.
Changes in v2: - Move the formatdomain docs patch right after the XML parser/formatter patch - Fix the docs description: "If omitted, the value is not changed" rather than "If omitted or set to 0, the hypervisor selects a default" - Split the getter/stats path (patch 4) from the setter/cmdline path (patch 5), and drop the qemuBuildIOThreadCommandLine qemuCaps parameter since CAPS validation is handled by qemuValidateDomainDefIOThreads - Separate the test driver changes into its own patch (patch 6) with the corresponding iothreads.out updates split accordingly - Move the domstats documentation hunk into the stats patch (patch 4) - Add a qemuxmlconf parse-error test for out-of-range weight values - Fix Since version: 12.6.0 -> 12.7.0 (Peter Krempa) - Drop the docs: fix typos patch (already applied upstream)
The series was validated with: meson test -C build virschematest meson test -C build qemucapabilitiestest meson test -C build qemuxmlconftest meson test -C build virshtest meson test -C build genericxml2xmltest
QEMU commits: 9fea80ddf0 qapi/iothread: introduce poll-weight parameter for aio-poll 9563d0b5e2 aio-poll: refine iothread polling using weighted handler intervals ed21d9d65c aio-poll: avoid unnecessary polling time computation
Jaehoon Kim (7): conf: add iothread poll-weight XML support docs: formatdomain: document iothread poll-weight qemu: capabilities: add capability for iothread poll-weight qemu: add poll-weight getter and stats support qemu: support iothread poll-weight test: add poll-weight support to the test driver virsh: add iothreadset --poll-weight support
docs/formatdomain.rst | 8 ++- docs/manpages/virsh.rst | 18 ++++-- include/libvirt/libvirt-domain.h | 25 ++++++++ src/conf/domain_conf.c | 14 ++++- src/conf/domain_conf.h | 2 + src/conf/domain_validate.c | 7 +++ src/conf/schemas/domaincommon.rng | 5 ++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 6 ++ src/qemu/qemu_driver.c | 38 ++++++++++++ src/qemu/qemu_monitor.h | 2 + src/qemu/qemu_monitor_json.c | 18 ++++++ src/qemu/qemu_validate.c | 10 +++- src/test/test_driver.c | 12 ++++ tests/genericxml2xmlindata/iothreadids.xml | 2 +- .../caps_11.1.0_aarch64.xml | 1 + .../caps_11.1.0_x86_64.xml | 1 + ...s-poll-weight-outofrange.x86_64-latest.err | 1 + .../iothreads-ids-poll-weight-outofrange.xml | 58 +++++++++++++++++++ ...threads-ids-poll-weight.x86_64-latest.args | 40 +++++++++++++ ...othreads-ids-poll-weight.x86_64-latest.xml | 58 +++++++++++++++++++ .../iothreads-ids-poll-weight.xml | 58 +++++++++++++++++++ tests/qemuxmlconftest.c | 2 + tests/virshtestdata/iothreads.in | 2 + tests/virshtestdata/iothreads.out | 18 ++++++ tools/virsh-domain.c | 17 ++++++ 27 files changed, 415 insertions(+), 11 deletions(-) create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight-outofrange.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight-outofrange.xml create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/iothreads-ids-poll-weight.xml
participants (2)
-
JAEHOON KIM -
Jaehoon Kim