From nobody Thu May 15 03:46:38 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1516730745541274.0719111540335; Tue, 23 Jan 2018 10:05:45 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 29C94A3290; Tue, 23 Jan 2018 18:05:44 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id F34FF18526; Tue, 23 Jan 2018 18:05:43 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id BA17F18033EB; Tue, 23 Jan 2018 18:05:43 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w0NI5W9o021602 for ; Tue, 23 Jan 2018 13:05:32 -0500 Received: by smtp.corp.redhat.com (Postfix) id 1D197171C3; Tue, 23 Jan 2018 18:05:32 +0000 (UTC) Received: from caroline.localdomain (unknown [10.43.2.67]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7EA967BB66; Tue, 23 Jan 2018 18:05:28 +0000 (UTC) Received: from caroline.brq.redhat.com (caroline.usersys.redhat.com [127.0.0.1]) by caroline.localdomain (Postfix) with ESMTP id 8501812043C; Tue, 23 Jan 2018 19:05:23 +0100 (CET) From: Martin Kletzander To: libvir-list@redhat.com Date: Tue, 23 Jan 2018 19:05:15 +0100 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-loop: libvir-list@redhat.com Cc: Chris Friesen , Eli Qiao Subject: [libvirt] [PATCH 06/10] conf: Add support for cputune/cachetune 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-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Tue, 23 Jan 2018 18:05:44 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" More info in the documentation, this is basically the XML parsing/formatting support, schemas, tests and documentation for the new cputune/cachetune ele= ment that will get used by following patches. Signed-off-by: Martin Kletzander Reviewed-by: Pavel Hrdina --- docs/formatdomain.html.in | 54 ++++ docs/schemas/domaincommon.rng | 32 +++ src/conf/domain_conf.c | 295 +++++++++++++++++= +++- src/conf/domain_conf.h | 13 + tests/genericxml2xmlindata/cachetune-cdp.xml | 36 +++ .../cachetune-colliding-allocs.xml | 30 +++ .../cachetune-colliding-tunes.xml | 32 +++ .../cachetune-colliding-types.xml | 30 +++ tests/genericxml2xmlindata/cachetune-small.xml | 29 ++ tests/genericxml2xmlindata/cachetune.xml | 33 +++ tests/genericxml2xmltest.c | 10 + 11 files changed, 592 insertions(+), 2 deletions(-) create mode 100644 tests/genericxml2xmlindata/cachetune-cdp.xml create mode 100644 tests/genericxml2xmlindata/cachetune-colliding-allocs.x= ml create mode 100644 tests/genericxml2xmlindata/cachetune-colliding-tunes.xml create mode 100644 tests/genericxml2xmlindata/cachetune-colliding-types.xml create mode 100644 tests/genericxml2xmlindata/cachetune-small.xml create mode 100644 tests/genericxml2xmlindata/cachetune.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index d272cc1ba698..7b4d9051a551 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -689,6 +689,10 @@ <iothread_quota>-1</iothread_quota> <vcpusched vcpus=3D'0-4,^3' scheduler=3D'fifo' priority=3D'1'/> <iothreadsched iothreads=3D'2' scheduler=3D'batch'/> + <cachetune vcpus=3D'0-3'> + <cache id=3D'0' level=3D'3' type=3D'both' size=3D'3' unit=3D'MiB'= /> + <cache id=3D'1' level=3D'3' type=3D'both' size=3D'3' unit=3D'MiB'= /> + </cachetune> </cputune> ... </domain> @@ -834,6 +838,56 @@ Since 1.2.13 =20 +
cachetuneSince 4.1.0 +
+ Optional cachetune element can control allocations fo= r CPU + caches using the resctrl on the host. Whether or not is this suppo= rted + can be gathered from capabilities where some limitations like mini= mum + size and required granularity are reported as well. The required + attribute vcpus specifies to which vCPUs this allocat= ion + applies. A vCPU can only be member of one cachetune e= lement + allocations. Supported subelements are: +
+
cache
+
+ This element controls the allocation of CPU cache and has the + following attributes: +
+
level
+
+ Host cache level from which to allocate. +
+
id
+
+ Host cache id from which to allocate. +
+
type
+
+ Type of allocation. Can be code for code + (instructions), data for data or both + for both code and data (unified). Currently the allocatio= n can + be done only with the same type as the host supports, mean= ing + you cannot request both for host with CDP + (code/data prioritization) enabled. +
+
size
+
+ The size of the region to allocate. The value by default i= s in + bytes, but the unit attribute can be used to = scale + the value. +
+
unit (optional)
+
+ If specified it is the unit such as KiB, MiB, GiB, or TiB + (described in the memory element + for Memory Allocatio= n) + in which size is specified, defaults to bytes. +
+
+
+
+ +
=20 =20 diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index f22c932f6c09..252f58f4379c 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -900,6 +900,38 @@ + + + + + + + + + + + + + + + + both + code + data + + + + + + + + + + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index a1c25060f9e9..27665d0372a7 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2883,6 +2883,19 @@ virDomainLoaderDefFree(virDomainLoaderDefPtr loader) VIR_FREE(loader); } =20 + +static void +virDomainCachetuneDefFree(virDomainCachetuneDefPtr cachetune) +{ + if (!cachetune) + return; + + virObjectUnref(cachetune->alloc); + virBitmapFree(cachetune->vcpus); + VIR_FREE(cachetune); +} + + void virDomainDefFree(virDomainDefPtr def) { size_t i; @@ -3055,6 +3068,10 @@ void virDomainDefFree(virDomainDefPtr def) virDomainShmemDefFree(def->shmems[i]); VIR_FREE(def->shmems); =20 + for (i =3D 0; i < def->ncachetunes; i++) + virDomainCachetuneDefFree(def->cachetunes[i]); + VIR_FREE(def->cachetunes); + VIR_FREE(def->keywrap); =20 if (def->namespaceData && def->ns.free) @@ -18247,6 +18264,194 @@ virDomainDefParseBootOptions(virDomainDefPtr def, } =20 =20 +static int +virDomainCachetuneDefParseCache(xmlXPathContextPtr ctxt, + xmlNodePtr node, + virResctrlAllocPtr alloc) +{ + xmlNodePtr oldnode =3D ctxt->node; + unsigned int level; + unsigned int cache; + int type; + unsigned long long size; + char *tmp =3D NULL; + int ret =3D -1; + + ctxt->node =3D node; + + tmp =3D virXMLPropString(node, "id"); + if (!tmp) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing cachetune attribute 'id'")); + goto cleanup; + } + if (virStrToLong_uip(tmp, NULL, 10, &cache) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid cachetune attribute 'id' value '%s'"), + tmp); + goto cleanup; + } + VIR_FREE(tmp); + + tmp =3D virXMLPropString(node, "level"); + if (!tmp) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing cachetune attribute 'level'")); + goto cleanup; + } + if (virStrToLong_uip(tmp, NULL, 10, &level) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid cachetune attribute 'level' value '%s'"), + tmp); + goto cleanup; + } + VIR_FREE(tmp); + + tmp =3D virXMLPropString(node, "type"); + if (!tmp) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing cachetune attribute 'type'")); + goto cleanup; + } + type =3D virCacheTypeFromString(tmp); + if (type < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid cachetune attribute 'type' value '%s'"), + tmp); + goto cleanup; + } + VIR_FREE(tmp); + + if (virDomainParseScaledValue("./@size", "./@unit", + ctxt, &size, 1024, + ULLONG_MAX, true) < 0) + goto cleanup; + + if (virResctrlAllocSetSize(alloc, level, type, cache, size) < 0) + goto cleanup; + + ret =3D 0; + cleanup: + ctxt->node =3D oldnode; + VIR_FREE(tmp); + return ret; +} + + +static int +virDomainCachetuneDefParse(virDomainDefPtr def, + xmlXPathContextPtr ctxt, + xmlNodePtr node, + unsigned int flags) +{ + xmlNodePtr oldnode =3D ctxt->node; + xmlNodePtr *nodes =3D NULL; + virBitmapPtr vcpus =3D NULL; + virResctrlAllocPtr alloc =3D virResctrlAllocNew(); + virDomainCachetuneDefPtr tmp_cachetune =3D NULL; + char *tmp =3D NULL; + char *vcpus_str =3D NULL; + char *alloc_id =3D NULL; + ssize_t i =3D 0; + int n; + int ret =3D -1; + + ctxt->node =3D node; + + if (!alloc) + goto cleanup; + + if (VIR_ALLOC(tmp_cachetune) < 0) + goto cleanup; + + vcpus_str =3D virXMLPropString(node, "vcpus"); + if (!vcpus_str) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing cachetune attribute 'vcpus'")); + goto cleanup; + } + if (virBitmapParse(vcpus_str, &vcpus, VIR_DOMAIN_CPUMASK_LEN) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid cachetune attribute 'vcpus' value '%s'"), + vcpus_str); + goto cleanup; + } + + /* We need to limit the bitmap to number of vCPUs. If there's nothing= left, + * then we can just clean up and return 0 immediately */ + virBitmapShrink(vcpus, def->maxvcpus); + if (virBitmapIsAllClear(vcpus)) { + ret =3D 0; + goto cleanup; + } + + if ((n =3D virXPathNodeSet("./cache", ctxt, &nodes)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot extract cache nodes under cachetune")); + goto cleanup; + } + + for (i =3D 0; i < n; i++) { + if (virDomainCachetuneDefParseCache(ctxt, nodes[i], alloc) < 0) + goto cleanup; + } + + if (virResctrlAllocIsEmpty(alloc)) { + ret =3D 0; + goto cleanup; + } + + for (i =3D 0; i < def->ncachetunes; i++) { + if (virBitmapOverlaps(def->cachetunes[i]->vcpus, vcpus)) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Overlapping vcpus in cachetunes")); + goto cleanup; + } + } + + /* We need to format it back because we need to be consistent in the n= aming + * even when users specify some "sub-optimal" string there. */ + VIR_FREE(vcpus_str); + vcpus_str =3D virBitmapFormat(vcpus); + if (!vcpus_str) + goto cleanup; + + if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) + alloc_id =3D virXMLPropString(node, "id"); + + if (!alloc_id) { + /* The number of allocatios is limited and the directory structure= is flat, + * not hierarchical, so we need to have all same allocations in one + * directory, so it's nice to have it named appropriately. For no= w it's + * 'vcpus_...' but it's designed in order for it to be changeable = in the + * future (it's part of the status XML). */ + if (virAsprintf(&alloc_id, "vcpus_%s", vcpus_str) < 0) + goto cleanup; + } + + if (virResctrlAllocSetID(alloc, alloc_id) < 0) + goto cleanup; + + VIR_STEAL_PTR(tmp_cachetune->vcpus, vcpus); + VIR_STEAL_PTR(tmp_cachetune->alloc, alloc); + + if (VIR_APPEND_ELEMENT(def->cachetunes, def->ncachetunes, tmp_cachetun= e) < 0) + goto cleanup; + + ret =3D 0; + cleanup: + ctxt->node =3D oldnode; + virDomainCachetuneDefFree(tmp_cachetune); + virObjectUnref(alloc); + virBitmapFree(vcpus); + VIR_FREE(alloc_id); + VIR_FREE(vcpus_str); + VIR_FREE(nodes); + VIR_FREE(tmp); + return ret; +} + + static virDomainDefPtr virDomainDefParseXML(xmlDocPtr xml, xmlNodePtr root, @@ -18799,6 +19004,18 @@ virDomainDefParseXML(xmlDocPtr xml, } VIR_FREE(nodes); =20 + if ((n =3D virXPathNodeSet("./cputune/cachetune", ctxt, &nodes)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot extract cachetune nodes")); + goto error; + } + + for (i =3D 0; i < n; i++) { + if (virDomainCachetuneDefParse(def, ctxt, nodes[i], flags) < 0) + goto error; + } + VIR_FREE(nodes); + if (virCPUDefParseXML(ctxt, "./cpu[1]", VIR_CPU_TYPE_GUEST, &def->cpu)= < 0) goto error; =20 @@ -25750,9 +25967,80 @@ virDomainSchedulerFormat(virBufferPtr buf, } =20 =20 +static int +virDomainCachetuneDefFormatHelper(unsigned int level, + virCacheType type, + unsigned int cache, + unsigned long long size, + void *opaque) +{ + const char *unit; + virBufferPtr buf =3D opaque; + unsigned long long short_size =3D virFormatIntPretty(size, &unit); + + virBufferAsprintf(buf, + "\n", + cache, level, virCacheTypeToString(type), + short_size, unit); + + return 0; +} + + +static int +virDomainCachetuneDefFormat(virBufferPtr buf, + virDomainCachetuneDefPtr cachetune, + unsigned int flags) +{ + virBuffer childrenBuf =3D VIR_BUFFER_INITIALIZER; + char *vcpus =3D NULL; + int ret =3D -1; + + virBufferSetChildIndent(&childrenBuf, buf); + virResctrlAllocForeachSize(cachetune->alloc, + virDomainCachetuneDefFormatHelper, + &childrenBuf); + + + if (virBufferCheckError(&childrenBuf) < 0) + goto cleanup; + + if (!virBufferUse(&childrenBuf)) { + ret =3D 0; + goto cleanup; + } + + vcpus =3D virBitmapFormat(cachetune->vcpus); + if (!vcpus) + goto cleanup; + + virBufferAsprintf(buf, "alloc); + if (!alloc_id) + goto cleanup; + + virBufferAsprintf(buf, " id=3D'%s'", alloc_id); + } + virBufferAddLit(buf, ">\n"); + + virBufferAddBuffer(buf, &childrenBuf); + virBufferAddLit(buf, "\n"); + + ret =3D 0; + cleanup: + virBufferFreeAndReset(&childrenBuf); + VIR_FREE(vcpus); + return ret; +} + + static int virDomainCputuneDefFormat(virBufferPtr buf, - virDomainDefPtr def) + virDomainDefPtr def, + unsigned int flags) { size_t i; virBuffer childrenBuf =3D VIR_BUFFER_INITIALIZER; @@ -25851,6 +26139,9 @@ virDomainCputuneDefFormat(virBufferPtr buf, def->iothreadids[i]->iothread_id); } =20 + for (i =3D 0; i < def->ncachetunes; i++) + virDomainCachetuneDefFormat(&childrenBuf, def->cachetunes[i], flag= s); + if (virBufferCheckError(&childrenBuf) < 0) return -1; =20 @@ -26188,7 +26479,7 @@ virDomainDefFormatInternal(virDomainDefPtr def, } } =20 - if (virDomainCputuneDefFormat(buf, def) < 0) + if (virDomainCputuneDefFormat(buf, def, flags) < 0) goto error; =20 if (virDomainNumatuneFormatXML(buf, def->numa) < 0) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6f7f96b3ddea..ed85260926de 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -56,6 +56,7 @@ # include "virperf.h" # include "virtypedparam.h" # include "virsavecookie.h" +# include "virresctrl.h" =20 /* forward declarations of all device types, required by * virDomainDeviceDef @@ -2194,6 +2195,15 @@ struct _virDomainCputune { }; =20 =20 +typedef struct _virDomainCachetuneDef virDomainCachetuneDef; +typedef virDomainCachetuneDef *virDomainCachetuneDefPtr; + +struct _virDomainCachetuneDef { + virBitmapPtr vcpus; + virResctrlAllocPtr alloc; +}; + + typedef struct _virDomainVcpuDef virDomainVcpuDef; typedef virDomainVcpuDef *virDomainVcpuDefPtr; =20 @@ -2322,6 +2332,9 @@ struct _virDomainDef { =20 virDomainCputune cputune; =20 + virDomainCachetuneDefPtr *cachetunes; + size_t ncachetunes; + virDomainNumaPtr numa; virDomainResourceDefPtr resource; virDomainIdMapDef idmap; diff --git a/tests/genericxml2xmlindata/cachetune-cdp.xml b/tests/genericxm= l2xmlindata/cachetune-cdp.xml new file mode 100644 index 000000000000..9718f060987a --- /dev/null +++ b/tests/genericxml2xmlindata/cachetune-cdp.xml @@ -0,0 +1,36 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 4 + + + + + + + + + + + + + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu-system-i686 + + + + + + + + diff --git a/tests/genericxml2xmlindata/cachetune-colliding-allocs.xml b/te= sts/genericxml2xmlindata/cachetune-colliding-allocs.xml new file mode 100644 index 000000000000..82c9176cbafa --- /dev/null +++ b/tests/genericxml2xmlindata/cachetune-colliding-allocs.xml @@ -0,0 +1,30 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 4 + + + + + + + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu-system-i686 + + + + + + + + diff --git a/tests/genericxml2xmlindata/cachetune-colliding-tunes.xml b/tes= ts/genericxml2xmlindata/cachetune-colliding-tunes.xml new file mode 100644 index 000000000000..a0f37028c98c --- /dev/null +++ b/tests/genericxml2xmlindata/cachetune-colliding-tunes.xml @@ -0,0 +1,32 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 4 + + + + + + + + + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu-system-i686 + + + + + + + + diff --git a/tests/genericxml2xmlindata/cachetune-colliding-types.xml b/tes= ts/genericxml2xmlindata/cachetune-colliding-types.xml new file mode 100644 index 000000000000..c229eccee4b6 --- /dev/null +++ b/tests/genericxml2xmlindata/cachetune-colliding-types.xml @@ -0,0 +1,30 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 4 + + + + + + + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu-system-i686 + + + + + + + + diff --git a/tests/genericxml2xmlindata/cachetune-small.xml b/tests/generic= xml2xmlindata/cachetune-small.xml new file mode 100644 index 000000000000..ab2d9cf8856a --- /dev/null +++ b/tests/genericxml2xmlindata/cachetune-small.xml @@ -0,0 +1,29 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 4 + + + + + + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu-system-i686 + + + + + + + + diff --git a/tests/genericxml2xmlindata/cachetune.xml b/tests/genericxml2xm= lindata/cachetune.xml new file mode 100644 index 000000000000..645cab7771cf --- /dev/null +++ b/tests/genericxml2xmlindata/cachetune.xml @@ -0,0 +1,33 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 4 + + + + + + + + + + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu-system-i686 + + + + + + + + diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c index deaf5bd9b823..496e9260fa86 100644 --- a/tests/genericxml2xmltest.c +++ b/tests/genericxml2xmltest.c @@ -130,6 +130,16 @@ mymain(void) DO_TEST_FULL("chardev-reconnect-invalid-mode", 0, false, TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE); =20 + DO_TEST("cachetune"); + DO_TEST("cachetune-small"); + DO_TEST("cachetune-cdp"); + DO_TEST_FULL("cachetune-colliding-allocs", false, true, + TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE); + DO_TEST_FULL("cachetune-colliding-tunes", false, true, + TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE); + DO_TEST_FULL("cachetune-colliding-types", false, true, + TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE); + virObjectUnref(caps); virObjectUnref(xmlopt); =20 --=20 2.16.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list