From nobody Sun Feb 8 20:13:08 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.37 as permitted sender) client-ip=209.132.183.37; envelope-from=libvir-list-bounces@redhat.com; helo=mx5-phx2.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.37 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx5-phx2.redhat.com (mx5-phx2.redhat.com [209.132.183.37]) by mx.zohomail.com with SMTPS id 1487679535580514.2590444140019; Tue, 21 Feb 2017 04:18:55 -0800 (PST) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx5-phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1LCFRge020111; Tue, 21 Feb 2017 07:15:27 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v1LCFBgT022548 for ; Tue, 21 Feb 2017 07:15:11 -0500 Received: from antique-work.brq.redhat.com (dhcp129-175.brq.redhat.com [10.34.129.175]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1LCF9hE031008 for ; Tue, 21 Feb 2017 07:15:11 -0500 From: Pavel Hrdina To: libvir-list@redhat.com Date: Tue, 21 Feb 2017 13:14:57 +0100 Message-Id: <2c15c7d45e334334fb173ad13866b63ee470e812.1487678590.git.phrdina@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 01/12] conf: introduce domain XML element for iothread X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" QEMU 2.9.0 will introduce polling feature for AioContext that instead of blocking syscalls polls for events without blocking. This means that polling can be in most cases faster but it also increases CPU utilization. To address this issue QEMU implements self-tuning algorithm that modifies the current polling time to adapt to different workloads and it can also fallback to blocking syscalls. For each IOThread this all is controlled by three parameters, poll-max-ns, poll-grow and poll-shrink. If parameter poll-max-ns is set to 0 it disables the polling, if it is omitted the default behavior is used and any value more than 0 enables polling. Parameters poll-grow and poll-shrink configure how the self-tuning algorithm will adapt the current polling time. If they are omitted or set to 0 default values will be used. Signed-off-by: Pavel Hrdina --- docs/formatdomain.html.in | 19 ++- docs/schemas/domaincommon.rng | 24 +++ src/conf/domain_conf.c | 169 +++++++++++++++++= +++- src/conf/domain_conf.h | 8 + src/libvirt_private.syms | 1 + .../generic-iothreads-no-polling.xml | 22 +++ .../generic-iothreads-polling-disabled.xml | 24 +++ .../generic-iothreads-polling-enabled-fail.xml | 24 +++ .../generic-iothreads-polling-enabled.xml | 24 +++ tests/genericxml2xmltest.c | 6 + tests/testutils.c | 3 +- 11 files changed, 318 insertions(+), 6 deletions(-) create mode 100644 tests/genericxml2xmlindata/generic-iothreads-no-polling= .xml create mode 100644 tests/genericxml2xmlindata/generic-iothreads-polling-di= sabled.xml create mode 100644 tests/genericxml2xmlindata/generic-iothreads-polling-en= abled-fail.xml create mode 100644 tests/genericxml2xmlindata/generic-iothreads-polling-en= abled.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index b69bd4c44c..f01a11cf93 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -611,6 +611,7 @@ ... <iothreadids> <iothread id=3D"2"/> + <polling enabled=3D'yes' max_ns=3D"4000" grow=3D"2" shrink=3D"4"/= > <iothread id=3D"4"/> <iothread id=3D"6"/> <iothread id=3D"8"/> @@ -645,7 +646,23 @@ defined for the domain, then the iothreads value will be adjusted accordingly. Since 1.2.15 - + +
polling
+
+ The optional polling element provides the capability = to + enable/disable and configure polling mechanism for iothreads. Attr= ibute + max_ns specifies the maximum time in ns + between each poll requests and is mandatory if polling is explicit= ly + enabled. Attributes grow and shrink spec= ifies + time in ns that is used to configure how the polling + algorithm will adapt current polling time to different workloads. + If any of max_ns, grow and shrink<= /code> + is set to 0, it is the same as not providing it at al= l. + If this element is omitted the default behavior and values are set= by + hypervisor. Possible values for enabled are + yes and no. Available only for QEMU driv= er. + Since 3.1.0 +
=20

CPU Tuning

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index c5f101325e..11aecbaa6e 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -661,6 +661,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 79bdbdf50c..4b552a9175 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1228,6 +1228,30 @@ virDomainDeviceDefCheckUnsupportedMemoryDevice(virDo= mainDeviceDefPtr dev) } =20 =20 +/** + * virDomainDefCheckUnsupportedIOThreadPolling: + * @def: domain definition + * + * Returns -1 if the domain definition would configure IOThread polling + * and reports an error, otherwise returns 0. + */ +static int +virDomainDefCheckUnsupportedIOThreadPolling(virDomainDefPtr def) +{ + size_t i; + + for (i =3D 0; i < def->niothreadids; i++) { + if (def->iothreadids[i]->poll_enabled !=3D VIR_TRISTATE_BOOL_ABSEN= T) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("IOThread polling is not supported by this dr= iver")); + return -1; + } + } + + return 0; +} + + bool virDomainObjTaint(virDomainObjPtr obj, virDomainTaintFlags taint) { @@ -4467,6 +4491,10 @@ virDomainDefPostParseCheckFeatures(virDomainDefPtr d= ef, return -1; } =20 + if (UNSUPPORTED(VIR_DOMAIN_DEF_FEATURE_IOTHREAD_POLLING) && + virDomainDefCheckUnsupportedIOThreadPolling(def) < 0) + return -1; + return 0; } =20 @@ -4585,6 +4613,60 @@ virDomainVcpuDefPostParse(virDomainDefPtr def) } =20 =20 +int +virDomainIOThreadDefPostParse(virDomainIOThreadIDDefPtr iothread) +{ + if ((iothread->poll_grow > 0 || iothread->poll_shrink > 0) && + iothread->poll_max_ns =3D=3D 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("polling grow or shrink is set for iothread id " + "'%u' but max_ns is not set"), + iothread->iothread_id); + return -1; + } + + switch (iothread->poll_enabled) { + case VIR_TRISTATE_BOOL_ABSENT: + if (iothread->poll_max_ns > 0) + iothread->poll_enabled =3D VIR_TRISTATE_BOOL_YES; + break; + + case VIR_TRISTATE_BOOL_NO: + iothread->poll_max_ns =3D 0; + iothread->poll_grow =3D 0; + iothread->poll_shrink =3D 0; + break; + + case VIR_TRISTATE_BOOL_YES: + if (iothread->poll_max_ns =3D=3D 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("polling is enabled for iothread id '%u' but " + "max_ns is not set"), iothread->iothread_id); + return -1; + } + break; + + case VIR_TRISTATE_BOOL_LAST: + break; + } + + return 0; +} + + +static int +virDomainDefPostParseIOThreads(virDomainDefPtr def) +{ + size_t i; + + for (i =3D 0; i < def->niothreadids; i++) + if (virDomainIOThreadDefPostParse(def->iothreadids[i]) < 0) + return -1; + + return 0; +} + + static int virDomainDefPostParseInternal(virDomainDefPtr def, struct virDomainDefPostParseDeviceIteratorDa= ta *data) @@ -4599,6 +4681,9 @@ virDomainDefPostParseInternal(virDomainDefPtr def, if (virDomainVcpuDefPostParse(def) < 0) return -1; =20 + if (virDomainDefPostParseIOThreads(def) < 0) + return -1; + if (virDomainDefPostParseMemory(def, data->parseFlags) < 0) return -1; =20 @@ -15574,7 +15659,9 @@ virDomainIdmapDefParseXML(xmlXPathContextPtr ctxt, * * 4 * - * + * + * + * * * * @@ -15587,6 +15674,7 @@ virDomainIOThreadIDDefParseXML(xmlNodePtr node, virDomainIOThreadIDDefPtr iothrid; xmlNodePtr oldnode =3D ctxt->node; char *tmp =3D NULL; + int npoll =3D 0; =20 if (VIR_ALLOC(iothrid) < 0) return NULL; @@ -15604,6 +15692,58 @@ virDomainIOThreadIDDefParseXML(xmlNodePtr node, _("invalid iothread 'id' value '%s'"), tmp); goto error; } + VIR_FREE(tmp); + + if ((npoll =3D virXPathNodeSet("./polling", ctxt, NULL)) < 0) + goto error; + + if (npoll > 1) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("only one polling element is allowed for each " + " element")); + goto error; + } + + if (npoll > 0) { + if ((tmp =3D virXPathString("string(./polling/@enabled)", ctxt))) { + int enabled =3D virTristateBoolTypeFromString(tmp); + if (enabled < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid polling 'enabled' value '%s'"), = tmp); + goto error; + } + iothrid->poll_enabled =3D enabled; + } else { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing 'enabled' attribute in ele= ment")); + goto error; + } + VIR_FREE(tmp); + + if ((tmp =3D virXPathString("string(./polling/@max_ns)", ctxt)) && + virStrToLong_uip(tmp, NULL, 10, &iothrid->poll_max_ns) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid polling 'max_ns' value '%s'"), tmp); + goto error; + } + VIR_FREE(tmp); + + if ((tmp =3D virXPathString("string(./polling/@grow)", ctxt)) && + virStrToLong_uip(tmp, NULL, 10, &iothrid->poll_grow) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid polling 'grow' value '%s'"), tmp); + goto error; + } + VIR_FREE(tmp); + + if ((tmp =3D virXPathString("string(./polling/@shrink)", ctxt)) && + virStrToLong_uip(tmp, NULL, 10, &iothrid->poll_shrink) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid polling 'shrink' value '%s'"), tmp); + goto error; + } + VIR_FREE(tmp); + } =20 cleanup: VIR_FREE(tmp); @@ -23713,7 +23853,8 @@ virDomainDefIothreadShouldFormat(virDomainDefPtr de= f) size_t i; =20 for (i =3D 0; i < def->niothreadids; i++) { - if (!def->iothreadids[i]->autofill) + if (!def->iothreadids[i]->autofill || + def->iothreadids[i]->poll_enabled !=3D VIR_TRISTATE_BOOL_ABSEN= T) return true; } =20 @@ -23918,8 +24059,28 @@ virDomainDefFormatInternal(virDomainDefPtr def, virBufferAddLit(buf, "\n"); virBufferAdjustIndent(buf, 2); for (i =3D 0; i < def->niothreadids; i++) { - virBufferAsprintf(buf, "\n", - def->iothreadids[i]->iothread_id); + virDomainIOThreadIDDefPtr iothread =3D def->iothreadids[i]; + virBufferAsprintf(buf, "io= thread_id); + if (iothread->poll_enabled !=3D VIR_TRISTATE_BOOL_ABSENT) { + virBufferAddLit(buf, ">\n"); + virBufferAdjustIndent(buf, 2); + virBufferAsprintf(buf, "poll_enabled)); + if (iothread->poll_max_ns) + virBufferAsprintf(buf, " max_ns=3D'%u'", + iothread->poll_max_ns); + if (iothread->poll_grow) + virBufferAsprintf(buf, " grow=3D'%u'", + iothread->poll_grow); + if (iothread->poll_shrink) + virBufferAsprintf(buf, " shrink=3D'%u'", + iothread->poll_shrink); + virBufferAddLit(buf, "/>\n"); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + } else { + virBufferAddLit(buf, "/>\n"); + } } virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "\n"); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 1e53cc3280..8ac1d8a409 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2074,11 +2074,18 @@ struct _virDomainIOThreadIDDef { int thread_id; virBitmapPtr cpumask; =20 + virTristateBool poll_enabled; + unsigned int poll_max_ns; + unsigned int poll_grow; + unsigned int poll_shrink; + virDomainThreadSchedParam sched; }; =20 void virDomainIOThreadIDDefFree(virDomainIOThreadIDDefPtr def); =20 +int virDomainIOThreadDefPostParse(virDomainIOThreadIDDefPtr iothread); + =20 typedef struct _virDomainCputune virDomainCputune; typedef virDomainCputune *virDomainCputunePtr; @@ -2410,6 +2417,7 @@ typedef enum { VIR_DOMAIN_DEF_FEATURE_OFFLINE_VCPUPIN =3D (1 << 2), VIR_DOMAIN_DEF_FEATURE_NAME_SLASH =3D (1 << 3), VIR_DOMAIN_DEF_FEATURE_INDIVIDUAL_VCPUS =3D (1 << 4), + VIR_DOMAIN_DEF_FEATURE_IOTHREAD_POLLING =3D (1 << 5), } virDomainDefFeatures; =20 =20 diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e6ccd697d2..97aee9c0e3 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -371,6 +371,7 @@ virDomainHypervTypeToString; virDomainInputDefFree; virDomainIOMMUModelTypeFromString; virDomainIOMMUModelTypeToString; +virDomainIOThreadDefPostParse; virDomainIOThreadIDAdd; virDomainIOThreadIDDefFree; virDomainIOThreadIDDel; diff --git a/tests/genericxml2xmlindata/generic-iothreads-no-polling.xml b/= tests/genericxml2xmlindata/generic-iothreads-no-polling.xml new file mode 100644 index 0000000000..b7e5a11c06 --- /dev/null +++ b/tests/genericxml2xmlindata/generic-iothreads-no-polling.xml @@ -0,0 +1,22 @@ + + foo + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + 2 + + + + + + hvm + + + + destroy + restart + destroy + + + diff --git a/tests/genericxml2xmlindata/generic-iothreads-polling-disabled.= xml b/tests/genericxml2xmlindata/generic-iothreads-polling-disabled.xml new file mode 100644 index 0000000000..0352a80900 --- /dev/null +++ b/tests/genericxml2xmlindata/generic-iothreads-polling-disabled.xml @@ -0,0 +1,24 @@ + + foo + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + 2 + + + + + + + + hvm + + + + destroy + restart + destroy + + + diff --git a/tests/genericxml2xmlindata/generic-iothreads-polling-enabled-f= ail.xml b/tests/genericxml2xmlindata/generic-iothreads-polling-enabled-fail= .xml new file mode 100644 index 0000000000..6f77922e7a --- /dev/null +++ b/tests/genericxml2xmlindata/generic-iothreads-polling-enabled-fail.xml @@ -0,0 +1,24 @@ + + foo + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + 2 + + + + + + + + hvm + + + + destroy + restart + destroy + + + diff --git a/tests/genericxml2xmlindata/generic-iothreads-polling-enabled.x= ml b/tests/genericxml2xmlindata/generic-iothreads-polling-enabled.xml new file mode 100644 index 0000000000..ef9161f367 --- /dev/null +++ b/tests/genericxml2xmlindata/generic-iothreads-polling-enabled.xml @@ -0,0 +1,24 @@ + + foo + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + 2 + + + + + + + + hvm + + + + destroy + restart + destroy + + + diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c index 488190270f..c3a9586eab 100644 --- a/tests/genericxml2xmltest.c +++ b/tests/genericxml2xmltest.c @@ -100,6 +100,12 @@ mymain(void) =20 DO_TEST("vcpus-individual"); =20 + DO_TEST("iothreads-no-polling"); + DO_TEST("iothreads-polling-enabled"); + DO_TEST("iothreads-polling-disabled"); + DO_TEST_FULL("iothreads-polling-enabled-fail", 0, false, + TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE); + virObjectUnref(caps); virObjectUnref(xmlopt); =20 diff --git a/tests/testutils.c b/tests/testutils.c index a596a83a96..93a12bcc76 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -1101,7 +1101,8 @@ virCapsPtr virTestGenericCapsInit(void) } =20 static virDomainDefParserConfig virTestGenericDomainDefParserConfig =3D { - .features =3D VIR_DOMAIN_DEF_FEATURE_INDIVIDUAL_VCPUS, + .features =3D VIR_DOMAIN_DEF_FEATURE_INDIVIDUAL_VCPUS | + VIR_DOMAIN_DEF_FEATURE_IOTHREAD_POLLING, }; static virDomainXMLPrivateDataCallbacks virTestGenericPrivateDataCallbacks; =20 --=20 2.11.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list