From nobody Thu May 2 15:54:52 2024 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; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1529056380308218.66171544857514; Fri, 15 Jun 2018 02:53:00 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C69D5308FB8B; Fri, 15 Jun 2018 09:52:58 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8E1A996F6B; Fri, 15 Jun 2018 09:52:58 +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 40D7F4CA87; Fri, 15 Jun 2018 09:52:58 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w5F9qi5w007036 for ; Fri, 15 Jun 2018 05:52:44 -0400 Received: by smtp.corp.redhat.com (Postfix) id A68102618E; Fri, 15 Jun 2018 09:52:44 +0000 (UTC) Received: from mx1.redhat.com (ext-mx09.extmail.prod.ext.phx2.redhat.com [10.5.110.38]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A05CD834D3 for ; Fri, 15 Jun 2018 09:52:42 +0000 (UTC) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 074591A9E2D for ; Fri, 15 Jun 2018 09:52:41 +0000 (UTC) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Jun 2018 02:52:40 -0700 Received: from bing-i9.bj.intel.com ([172.16.182.85]) by orsmga001.jf.intel.com with ESMTP; 15 Jun 2018 02:52:38 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,226,1526367600"; d="scan'208";a="64805849" From: bing.niu@intel.com To: libvir-list@redhat.com Date: Fri, 15 Jun 2018 17:29:25 +0800 Message-Id: <1529054969-68474-2-git-send-email-bing.niu@intel.com> In-Reply-To: <1529054969-68474-1-git-send-email-bing.niu@intel.com> References: <1529054969-68474-1-git-send-email-bing.niu@intel.com> X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 207 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 15 Jun 2018 09:52:41 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 15 Jun 2018 09:52:41 +0000 (UTC) for IP:'134.134.136.31' DOMAIN:'mga06.intel.com' HELO:'mga06.intel.com' FROM:'bing.niu@intel.com' RCPT:'' X-RedHat-Spam-Score: -2.301 (RCVD_IN_DNSWL_MED, SPF_PASS) 134.134.136.31 mga06.intel.com 134.134.136.31 mga06.intel.com X-Scanned-By: MIMEDefang 2.78 on 10.5.110.38 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-loop: libvir-list@redhat.com Cc: shaohe.feng@intel.com, huaqiang.wang@intel.com, Bing Niu , jian-feng.ding@intel.com, rui.zang@yandex.com Subject: [libvirt] [RFCv2 PATCH 1/5] util: Rename and packing parts of virresctrl 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.84 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Fri, 15 Jun 2018 09:52:59 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Bing Niu Renaming some functions and packing some CAT logic into functions Signed-off-by: Bing Niu --- src/conf/domain_conf.c | 2 +- src/libvirt_private.syms | 2 +- src/util/virresctrl.c | 93 +++++++++++++++++++++++++++++++-------------= ---- src/util/virresctrl.h | 16 ++++----- 4 files changed, 70 insertions(+), 43 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 522e0c2..62c412e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -26882,7 +26882,7 @@ virDomainCachetuneDefFormat(virBufferPtr buf, int ret =3D -1; =20 virBufferSetChildIndent(&childrenBuf, buf); - virResctrlAllocForeachSize(cachetune->alloc, + virResctrlAllocForeachCache(cachetune->alloc, virDomainCachetuneDefFormatHelper, &childrenBuf); =20 diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ea24f28..fc17059 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2627,7 +2627,7 @@ virCacheTypeToString; virResctrlAllocAddPID; virResctrlAllocCreate; virResctrlAllocDeterminePath; -virResctrlAllocForeachSize; +virResctrlAllocForeachCache; virResctrlAllocFormat; virResctrlAllocGetID; virResctrlAllocGetUnused; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index e492a63..e62061f 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -316,11 +316,9 @@ virResctrlUnlock(int fd) } =20 =20 -/* virResctrlInfo-related definitions */ static int -virResctrlGetInfo(virResctrlInfoPtr resctrl) +virResctrlGetCacheInfo(virResctrlInfoPtr resctrl, DIR *dirp) { - DIR *dirp =3D NULL; char *endptr =3D NULL; char *tmp_str =3D NULL; int ret =3D -1; @@ -332,12 +330,6 @@ virResctrlGetInfo(virResctrlInfoPtr resctrl) virResctrlInfoPerLevelPtr i_level =3D NULL; virResctrlInfoPerTypePtr i_type =3D NULL; =20 - rv =3D virDirOpenIfExists(&dirp, SYSFS_RESCTRL_PATH "/info"); - if (rv <=3D 0) { - ret =3D rv; - goto cleanup; - } - while ((rv =3D virDirRead(dirp, &ent, SYSFS_RESCTRL_PATH "/info")) > 0= ) { VIR_DEBUG("Parsing info type '%s'", ent->d_name); if (ent->d_name[0] !=3D 'L') @@ -443,12 +435,33 @@ virResctrlGetInfo(virResctrlInfoPtr resctrl) =20 ret =3D 0; cleanup: - VIR_DIR_CLOSE(dirp); VIR_FREE(i_type); return ret; } =20 =20 +/* virResctrlInfo-related definitions */ +static int +virResctrlGetInfo(virResctrlInfoPtr resctrl) +{ + DIR *dirp =3D NULL; + int ret =3D -1; + + ret =3D virDirOpenIfExists(&dirp, SYSFS_RESCTRL_PATH "/info"); + if (ret <=3D 0) + goto cleanup; + + ret =3D virResctrlGetCacheInfo(resctrl, dirp); + if (ret < 0) + goto cleanup; + + ret =3D 0; + cleanup: + VIR_DIR_CLOSE(dirp); + return ret; +} + + virResctrlInfoPtr virResctrlInfoNew(void) { @@ -773,8 +786,8 @@ virResctrlAllocSetSize(virResctrlAllocPtr alloc, =20 =20 int -virResctrlAllocForeachSize(virResctrlAllocPtr alloc, - virResctrlAllocForeachSizeCallback cb, +virResctrlAllocForeachCache(virResctrlAllocPtr alloc, + virResctrlAllocForeachCacheCallback cb, void *opaque) { int ret =3D 0; @@ -835,17 +848,14 @@ virResctrlAllocGetID(virResctrlAllocPtr alloc) } =20 =20 -char * -virResctrlAllocFormat(virResctrlAllocPtr alloc) +static int +virResctrlAllocFormatCache(virResctrlAllocPtr alloc, virBufferPtr buf) { - virBuffer buf =3D VIR_BUFFER_INITIALIZER; + int ret =3D -1; unsigned int level =3D 0; unsigned int type =3D 0; unsigned int cache =3D 0; =20 - if (!alloc) - return NULL; - for (level =3D 0; level < alloc->nlevels; level++) { virResctrlAllocPerLevelPtr a_level =3D alloc->levels[level]; =20 @@ -858,7 +868,7 @@ virResctrlAllocFormat(virResctrlAllocPtr alloc) if (!a_type) continue; =20 - virBufferAsprintf(&buf, "L%u%s:", level, virResctrlTypeToStrin= g(type)); + virBufferAsprintf(buf, "L%u%s:", level, virResctrlTypeToString= (type)); =20 for (cache =3D 0; cache < a_type->nmasks; cache++) { virBitmapPtr mask =3D a_type->masks[cache]; @@ -868,20 +878,37 @@ virResctrlAllocFormat(virResctrlAllocPtr alloc) continue; =20 mask_str =3D virBitmapToString(mask, false, true); - if (!mask_str) { - virBufferFreeAndReset(&buf); - return NULL; - } + if (!mask_str) + return ret; =20 - virBufferAsprintf(&buf, "%u=3D%s;", cache, mask_str); + virBufferAsprintf(buf, "%u=3D%s;", cache, mask_str); VIR_FREE(mask_str); } =20 - virBufferTrim(&buf, ";", 1); - virBufferAddChar(&buf, '\n'); + virBufferTrim(buf, ";", 1); + virBufferAddChar(buf, '\n'); } } =20 + ret =3D 0; + virBufferCheckError(buf); + return ret; +} + + +char * +virResctrlAllocFormat(virResctrlAllocPtr alloc) +{ + virBuffer buf =3D VIR_BUFFER_INITIALIZER; + + if (!alloc) + return NULL; + + if (virResctrlAllocFormatCache(alloc, &buf) < 0) { + virBufferFreeAndReset(&buf); + return NULL; + } + virBufferCheckError(&buf); return virBufferContentAndReset(&buf); } @@ -939,9 +966,9 @@ virResctrlAllocParseProcessCache(virResctrlInfoPtr resc= trl, =20 =20 static int -virResctrlAllocParseProcessLine(virResctrlInfoPtr resctrl, - virResctrlAllocPtr alloc, - char *line) +virResctrlAllocParseCacheLine(virResctrlInfoPtr resctrl, + virResctrlAllocPtr alloc, + char *line) { char **caches =3D NULL; char *tmp =3D NULL; @@ -1009,7 +1036,7 @@ virResctrlAllocParse(virResctrlInfoPtr resctrl, =20 lines =3D virStringSplitCount(schemata, "\n", 0, &nlines); for (i =3D 0; i < nlines; i++) { - if (virResctrlAllocParseProcessLine(resctrl, alloc, lines[i]) < 0) + if (virResctrlAllocParseCacheLine(resctrl, alloc, lines[i]) < 0) goto cleanup; } =20 @@ -1401,8 +1428,8 @@ virResctrlAllocCopyMasks(virResctrlAllocPtr dst, * transforming `sizes` into `masks`. */ static int -virResctrlAllocMasksAssign(virResctrlInfoPtr resctrl, - virResctrlAllocPtr alloc) +virResctrlAllocAssign(virResctrlInfoPtr resctrl, + virResctrlAllocPtr alloc) { int ret =3D -1; unsigned int level =3D 0; @@ -1526,7 +1553,7 @@ virResctrlAllocCreate(virResctrlInfoPtr resctrl, if (lockfd < 0) goto cleanup; =20 - if (virResctrlAllocMasksAssign(resctrl, alloc) < 0) + if (virResctrlAllocAssign(resctrl, alloc) < 0) goto cleanup; =20 alloc_str =3D virResctrlAllocFormat(alloc); diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 9052a2b..26c5f3b 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -67,11 +67,11 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl, typedef struct _virResctrlAlloc virResctrlAlloc; typedef virResctrlAlloc *virResctrlAllocPtr; =20 -typedef int virResctrlAllocForeachSizeCallback(unsigned int level, - virCacheType type, - unsigned int cache, - unsigned long long size, - void *opaque); +typedef int virResctrlAllocForeachCacheCallback(unsigned int level, + virCacheType type, + unsigned int cache, + unsigned long long size, + void *opaque); =20 virResctrlAllocPtr virResctrlAllocNew(void); @@ -87,9 +87,9 @@ virResctrlAllocSetSize(virResctrlAllocPtr alloc, unsigned long long size); =20 int -virResctrlAllocForeachSize(virResctrlAllocPtr alloc, - virResctrlAllocForeachSizeCallback cb, - void *opaque); +virResctrlAllocForeachCache(virResctrlAllocPtr alloc, + virResctrlAllocForeachCacheCallback cb, + void *opaque); =20 int virResctrlAllocSetID(virResctrlAllocPtr alloc, --=20 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Thu May 2 15:54:52 2024 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; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1529056369914989.3735114824517; Fri, 15 Jun 2018 02:52:49 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6424581E07; Fri, 15 Jun 2018 09:52:48 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 08C2595A7F; Fri, 15 Jun 2018 09:52:48 +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 A9E774CA83; Fri, 15 Jun 2018 09:52:47 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w5F9qk5E007043 for ; Fri, 15 Jun 2018 05:52:46 -0400 Received: by smtp.corp.redhat.com (Postfix) id 5B4A730A3742; Fri, 15 Jun 2018 09:52:46 +0000 (UTC) Received: from mx1.redhat.com (ext-mx07.extmail.prod.ext.phx2.redhat.com [10.5.110.31]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 52CA730A3757 for ; Fri, 15 Jun 2018 09:52:44 +0000 (UTC) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EE307C04F4C2 for ; Fri, 15 Jun 2018 09:52:42 +0000 (UTC) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Jun 2018 02:52:42 -0700 Received: from bing-i9.bj.intel.com ([172.16.182.85]) by orsmga001.jf.intel.com with ESMTP; 15 Jun 2018 02:52:40 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,226,1526367600"; d="scan'208";a="64805864" From: bing.niu@intel.com To: libvir-list@redhat.com Date: Fri, 15 Jun 2018 17:29:26 +0800 Message-Id: <1529054969-68474-3-git-send-email-bing.niu@intel.com> In-Reply-To: <1529054969-68474-1-git-send-email-bing.niu@intel.com> References: <1529054969-68474-1-git-send-email-bing.niu@intel.com> X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 207 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 15 Jun 2018 09:52:43 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 15 Jun 2018 09:52:43 +0000 (UTC) for IP:'134.134.136.31' DOMAIN:'mga06.intel.com' HELO:'mga06.intel.com' FROM:'bing.niu@intel.com' RCPT:'' X-RedHat-Spam-Score: -2.301 (RCVD_IN_DNSWL_MED, SPF_PASS) 134.134.136.31 mga06.intel.com 134.134.136.31 mga06.intel.com X-Scanned-By: MIMEDefang 2.78 on 10.5.110.31 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.24 X-loop: libvir-list@redhat.com Cc: shaohe.feng@intel.com, huaqiang.wang@intel.com, Bing Niu , jian-feng.ding@intel.com, rui.zang@yandex.com Subject: [libvirt] [RFCv2 PATCH 2/5] util: Add memory bandwidth support to resctrl 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.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Fri, 15 Jun 2018 09:52:49 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Bing Niu Add memory bandwidth allocation support basing on existing virresctrl implementation. Two new structures virResctrlInfoMB and virResctrlAllocMB are introduced. virResctrlInfoMB is used to record host system MBA supporting information, e.g., minimum bandwidth allowed, bandwidth granularity, number of bandwidth controller (same as number of last level cache). virResctrlAllocMB is used for allocating memory bandwidth. Following virResctrlAllocPerType, it also employs a nested sparse array to indicate whether allocation is available for particular llc. Overall, the memory bandwidth allocation follows the same sequence as existing virresctrl cache allocation model. It exposes interfaces for probing host's memory bandwidth capability on initialization time and memory bandwidth allocation on runtime. Signed-off-by: Bing Niu --- src/libvirt_private.syms | 2 + src/util/virresctrl.c | 383 +++++++++++++++++++++++++++++++++++++++++++= +++- src/util/virresctrl.h | 14 ++ 3 files changed, 397 insertions(+), 2 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fc17059..6925062 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2628,6 +2628,7 @@ virResctrlAllocAddPID; virResctrlAllocCreate; virResctrlAllocDeterminePath; virResctrlAllocForeachCache; +virResctrlAllocForeachMemory; virResctrlAllocFormat; virResctrlAllocGetID; virResctrlAllocGetUnused; @@ -2635,6 +2636,7 @@ virResctrlAllocNew; virResctrlAllocRemove; virResctrlAllocSetID; virResctrlAllocSetSize; +virResctrlSetMemoryBandwidth; virResctrlInfoGetCache; virResctrlInfoNew; =20 diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index e62061f..de736b0 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -80,18 +80,21 @@ typedef virResctrlInfoPerType *virResctrlInfoPerTypePtr; typedef struct _virResctrlInfoPerLevel virResctrlInfoPerLevel; typedef virResctrlInfoPerLevel *virResctrlInfoPerLevelPtr; =20 +typedef struct _virResctrlInfoMB virResctrlInfoMB; +typedef virResctrlInfoMB *virResctrlInfoMBPtr; + typedef struct _virResctrlAllocPerType virResctrlAllocPerType; typedef virResctrlAllocPerType *virResctrlAllocPerTypePtr; =20 typedef struct _virResctrlAllocPerLevel virResctrlAllocPerLevel; typedef virResctrlAllocPerLevel *virResctrlAllocPerLevelPtr; =20 - +typedef struct _virResctrlAllocMB virResctrlAllocMB; +typedef virResctrlAllocMB *virResctrlAllocMBPtr; /* Class definitions and initializations */ static virClassPtr virResctrlInfoClass; static virClassPtr virResctrlAllocClass; =20 - /* virResctrlInfo */ struct _virResctrlInfoPerType { /* Kernel-provided information */ @@ -116,11 +119,29 @@ struct _virResctrlInfoPerLevel { virResctrlInfoPerTypePtr *types; }; =20 +/* Information about memory bandwidth allocation */ +struct _virResctrlInfoMB { + /* minimum memory bandwidth allowed*/ + unsigned int min_bandwidth; + /* bandwidth granularity */ + unsigned int bandwidth_granularity; + /* Maximum number of simultaneous allocations */ + unsigned int max_allocation; + /* level number of last level cache*/ + unsigned int last_level_cache; + /* max id of last level cache, this is used to track + * how many last level cache available in host system + * */ + unsigned int max_id; +}; + struct _virResctrlInfo { virObject parent; =20 virResctrlInfoPerLevelPtr *levels; size_t nlevels; + + virResctrlInfoMBPtr mb_info; }; =20 =20 @@ -146,6 +167,7 @@ virResctrlInfoDispose(void *obj) VIR_FREE(level); } =20 + VIR_FREE(resctrl->mb_info); VIR_FREE(resctrl->levels); } =20 @@ -202,12 +224,23 @@ struct _virResctrlAllocPerLevel { * VIR_CACHE_TYPE_LAST number of items */ }; =20 +/* + * virResctrlAllocMB represents one memory bandwidth allocation. Since it = can have + * multiple last level caches in a NUMA system, it is also represented as = a nested + * sparse arrays as virRestrlAllocPerLevel + */ +struct _virResctrlAllocMB { + unsigned int **bandwidth; + size_t nsizes; +}; + struct _virResctrlAlloc { virObject parent; =20 virResctrlAllocPerLevelPtr *levels; size_t nlevels; =20 + virResctrlAllocMBPtr mba; /* The identifier (any unique string for now) */ char *id; /* libvirt-generated path in /sys/fs/resctrl for this particular @@ -251,6 +284,13 @@ virResctrlAllocDispose(void *obj) VIR_FREE(level); } =20 + if (alloc->mba) { + virResctrlAllocMBPtr mba =3D alloc->mba; + for (i =3D 0; i < mba->nsizes; i++) + VIR_FREE(mba->bandwidth[i]); + } + + VIR_FREE(alloc->mba); VIR_FREE(alloc->id); VIR_FREE(alloc->path); VIR_FREE(alloc->levels); @@ -440,6 +480,61 @@ virResctrlGetCacheInfo(virResctrlInfoPtr resctrl, DIR = *dirp) } =20 =20 +static int +virResctrlGetMemoryBandwidthInfo(virResctrlInfoPtr resctrl) +{ + int ret =3D -1; + int rv =3D -1; + virResctrlInfoMBPtr i_mb =3D NULL; + + /* query memory bandwidth allocation info */ + if (VIR_ALLOC(i_mb) < 0) + goto cleanup; + rv =3D virFileReadValueUint(&i_mb->bandwidth_granularity, + SYSFS_RESCTRL_PATH "/info/MB/bandwidth_gran"= ); + if (rv =3D=3D -2) { + /* The file doesn't exist, so it's unusable for us, + * properly mba unsupported */ + VIR_WARN("The path '" SYSFS_RESCTRL_PATH "/info/MB/bandwidth_gran'" + "does not exist"); + ret =3D 0; + goto cleanup; + } else if (rv < 0) { + /* Other failures are fatal, so just quit */ + goto cleanup; + } + + rv =3D virFileReadValueUint(&i_mb->min_bandwidth, + SYSFS_RESCTRL_PATH "/info/MB/min_bandwidth"); + if (rv =3D=3D -2) { + /* If the previous file exists, so should this one. Hence -2 is + * fatal in this case as well (errors out in next condition) - the + * kernel interface might've changed too much or something else is + * wrong. */ + + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot get min bandwidth from resctrl cache info= ")); + } + if (rv < 0) + goto cleanup; + + rv =3D virFileReadValueUint(&i_mb->max_allocation, + SYSFS_RESCTRL_PATH "/info/MB/num_closids"); + if (rv =3D=3D -2) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot get max allocation from resctrl cache inf= o")); + } + if (rv < 0) + goto cleanup; + + VIR_STEAL_PTR(resctrl->mb_info, i_mb); + ret =3D 0; + cleanup: + VIR_FREE(i_mb); + return ret; +} + + /* virResctrlInfo-related definitions */ static int virResctrlGetInfo(virResctrlInfoPtr resctrl) @@ -451,6 +546,10 @@ virResctrlGetInfo(virResctrlInfoPtr resctrl) if (ret <=3D 0) goto cleanup; =20 + ret =3D virResctrlGetMemoryBandwidthInfo(resctrl); + if (ret < 0) + goto cleanup; + ret =3D virResctrlGetCacheInfo(resctrl, dirp); if (ret < 0) goto cleanup; @@ -492,6 +591,9 @@ virResctrlInfoIsEmpty(virResctrlInfoPtr resctrl) if (!resctrl) return true; =20 + if (resctrl->mb_info) + return false; + for (i =3D 0; i < resctrl->nlevels; i++) { virResctrlInfoPerLevelPtr i_level =3D resctrl->levels[i]; =20 @@ -517,12 +619,26 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl, { virResctrlInfoPerLevelPtr i_level =3D NULL; virResctrlInfoPerTypePtr i_type =3D NULL; + virResctrlInfoMBPtr mb_info =3D NULL; size_t i =3D 0; int ret =3D -1; =20 if (virResctrlInfoIsEmpty(resctrl)) return 0; =20 + /* Let's take the opportunity to update the number of + * last level cache. This number is used to calculate + * free memory bandwidth */ + if (resctrl->mb_info) { + mb_info =3D resctrl->mb_info; + if (level > mb_info->last_level_cache) { + mb_info->last_level_cache =3D level; + mb_info->max_id =3D 0; + } else if (mb_info->last_level_cache =3D=3D level) { + mb_info->max_id++; + } + } + if (level >=3D resctrl->nlevels) return 0; =20 @@ -593,6 +709,9 @@ virResctrlAllocIsEmpty(virResctrlAllocPtr alloc) if (!alloc) return true; =20 + if (alloc->mba) + return false; + for (i =3D 0; i < alloc->nlevels; i++) { virResctrlAllocPerLevelPtr a_level =3D alloc->levels[i]; =20 @@ -786,6 +905,27 @@ virResctrlAllocSetSize(virResctrlAllocPtr alloc, =20 =20 int +virResctrlAllocForeachMemory(virResctrlAllocPtr alloc, + virResctrlAllocForeachMemoryCallback cb, + void *opaque) +{ + unsigned int id =3D 0; + + if (!alloc) + return 0; + + if (alloc->mba) { + virResctrlAllocMBPtr mba =3D alloc->mba; + for (id =3D 0; id < mba->nsizes; id++) + if (mba->bandwidth[id]) + cb(id, *mba->bandwidth[id], opaque); + } + + return 0; +} + + +int virResctrlAllocForeachCache(virResctrlAllocPtr alloc, virResctrlAllocForeachCacheCallback cb, void *opaque) @@ -848,6 +988,217 @@ virResctrlAllocGetID(virResctrlAllocPtr alloc) } =20 =20 +static void +virResctrlMemoryBandwidthSubstract(virResctrlAllocPtr free, + virResctrlAllocPtr used) +{ + size_t i; + + if (used->mba) { + for (i =3D 0; i < used->mba->nsizes; i++) { + if (used->mba->bandwidth[i]) + *(free->mba->bandwidth[i]) -=3D *(used->mba->bandwidth[i]); + } + } +} + + +int +virResctrlSetMemoryBandwidth(virResctrlAllocPtr alloc, + unsigned int id, + unsigned int memory_bandwidth) +{ + virResctrlAllocMBPtr mba =3D alloc->mba; + + if (!mba) { + if (VIR_ALLOC(mba) < 0) + return -1; + alloc->mba =3D mba; + } + + if (mba->nsizes <=3D id && + VIR_EXPAND_N(mba->bandwidth, mba->nsizes, + id - mba->nsizes + 1) < 0) + return -1; + + if (mba->bandwidth[id]) { + virReportError(VIR_ERR_XML_ERROR, + _("Collision Memory Bandwidth on node %d"), + id); + return -1; + } + + if (VIR_ALLOC(mba->bandwidth[id]) < 0) + return -1; + + *(mba->bandwidth[id]) =3D memory_bandwidth; + return 0; +} + + +static int +virResctrlAllocMemoryBandwidthFormat(virResctrlAllocPtr alloc, virBufferPt= r buf) +{ + int id; + + if (!alloc->mba) + return 0; + + virBufferAddLit(buf, "MB:"); + + for (id =3D 0; id < alloc->mba->nsizes; id++) { + if (alloc->mba->bandwidth[id]) { + virBufferAsprintf(buf, "%u=3D%u;", id, + *(alloc->mba->bandwidth[id])); + } + } + + virBufferTrim(buf, ";", 1); + virBufferAddChar(buf, '\n'); + virBufferCheckError(buf); + return 0; +} + + +static int +virResctrlAllocMemoryBandwidth(virResctrlInfoPtr resctrl, + virResctrlAllocPtr alloc, virResctrlAllocPt= r free) +{ + int id; + int ret =3D -1; + virResctrlAllocMBPtr mb_alloc =3D alloc->mba; + virResctrlAllocMBPtr mb_free =3D free->mba; + virResctrlInfoMBPtr mb_info =3D resctrl->mb_info; + + if (!mb_alloc) { + ret =3D 0; + return ret; + } + + if (mb_alloc && !mb_info) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("RDT Memory Bandwidth allocation" + " unsupported")); + return ret; + } + + for (id =3D 0; id < mb_alloc->nsizes; id ++) { + if (!mb_alloc->bandwidth[id]) + continue; + + if (*(mb_alloc->bandwidth[id]) % mb_info->bandwidth_granularity) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Memory Bandwidth allocation of size " + "%u is not divisible by granularity %u"), + *(mb_alloc->bandwidth[id]), + mb_info->bandwidth_granularity); + return ret; + } + if (*(mb_alloc->bandwidth[id]) < mb_info->min_bandwidth) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Memory Bandwidth allocation of size " + "%u is smaller than the minimum " + "allowed allocation %u"), + *(mb_alloc->bandwidth[id]), + mb_info->min_bandwidth); + return ret; + } + if (id > mb_info->max_id) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("bandwidth controller %u not exist," + " max controller id %u"), + id, mb_info->max_id); + return ret; + } + if (*(mb_alloc->bandwidth[id]) > *(mb_free->bandwidth[id])) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Not enough room for allocation of %u " + "bandwidth for node %u%%, freed %u%%"), + id, *(mb_alloc->bandwidth[id]), + *(mb_free->bandwidth[id])); + return ret; + } + } + ret =3D 0; + return ret; +} + + +static int +virResctrlAllocParseMemoryBandwidthLine(virResctrlInfoPtr resctrl, + virResctrlAllocPtr alloc, + char *line) +{ + char **mbs =3D NULL; + char *tmp =3D NULL; + unsigned int bandwidth; + size_t nmb =3D 0; + unsigned int id; + size_t i; + int ret =3D -1; + + /* For no reason there can be spaces */ + virSkipSpaces((const char **) &line); + + if (STRNEQLEN(line, "MB", 2)) + return 0; + + if (!resctrl || !resctrl->mb_info + || !resctrl->mb_info->min_bandwidth + || !resctrl->mb_info->bandwidth_granularity) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing or inconsistent resctrl info for " + "memory bandwidth allocation")); + } + + if (!alloc->mba) { + if (VIR_ALLOC(alloc->mba) < 0) + return -1; + } + + tmp =3D strchr(line, ':'); + if (!tmp) + return 0; + tmp++; + + mbs =3D virStringSplitCount(tmp, ";", 0, &nmb); + if (!nmb) + return 0; + + for (i =3D 0; i < nmb; i++) { + tmp =3D strchr(mbs[i], '=3D'); + *tmp =3D '\0'; + tmp++; + + if (virStrToLong_uip(mbs[i], NULL, 10, &id) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid node id %u "), id); + goto cleanup; + } + if (virStrToLong_uip(tmp, NULL, 10, &bandwidth) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid bandwidth %u"), bandwidth); + goto cleanup; + } + if (alloc->mba->nsizes <=3D id && + VIR_EXPAND_N(alloc->mba->bandwidth, alloc->mba->nsizes, + id - alloc->mba->nsizes + 1) < 0) { + goto cleanup; + } + if (!alloc->mba->bandwidth[id]) { + if (VIR_ALLOC(alloc->mba->bandwidth[id]) < 0) + goto cleanup; + } + + *(alloc->mba->bandwidth[id]) =3D bandwidth; + } + ret =3D 0; + cleanup: + virStringListFree(mbs); + return ret; +} + + static int virResctrlAllocFormatCache(virResctrlAllocPtr alloc, virBufferPtr buf) { @@ -909,6 +1260,11 @@ virResctrlAllocFormat(virResctrlAllocPtr alloc) return NULL; } =20 + if (virResctrlAllocMemoryBandwidthFormat(alloc, &buf) < 0) { + virBufferFreeAndReset(&buf); + return NULL; + } + virBufferCheckError(&buf); return virBufferContentAndReset(&buf); } @@ -1036,6 +1392,9 @@ virResctrlAllocParse(virResctrlInfoPtr resctrl, =20 lines =3D virStringSplitCount(schemata, "\n", 0, &nlines); for (i =3D 0; i < nlines; i++) { + if (virResctrlAllocParseMemoryBandwidthLine(resctrl, alloc, lines[= i]) < 0) + goto cleanup; + if (virResctrlAllocParseCacheLine(resctrl, alloc, lines[i]) < 0) goto cleanup; } @@ -1170,6 +1529,22 @@ virResctrlAllocNewFromInfo(virResctrlInfoPtr info) } } =20 + /* set default free memory bandwidth to 100%*/ + if (info->mb_info) { + if (VIR_ALLOC(ret->mba) < 0) + goto error; + + if (VIR_EXPAND_N(ret->mba->bandwidth, ret->mba->nsizes, + info->mb_info->max_id - ret->mba->nsizes + 1) < 0) + goto error; + + for (i =3D 0; i < ret->mba->nsizes; i++) { + if (VIR_ALLOC(ret->mba->bandwidth[i]) < 0) + goto error; + *(ret->mba->bandwidth[i]) =3D 100; + } + } + cleanup: virBitmapFree(mask); return ret; @@ -1233,6 +1608,7 @@ virResctrlAllocGetUnused(virResctrlInfoPtr resctrl) goto error; } =20 + virResctrlMemoryBandwidthSubstract(ret, alloc); virResctrlAllocSubtract(ret, alloc); virObjectUnref(alloc); alloc =3D NULL; @@ -1444,6 +1820,9 @@ virResctrlAllocAssign(virResctrlInfoPtr resctrl, if (!alloc_default) goto cleanup; =20 + if (virResctrlAllocMemoryBandwidth(resctrl, alloc, alloc_free) < 0) + goto cleanup; + if (virResctrlAllocCopyMasks(alloc, alloc_default) < 0) goto cleanup; =20 diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 26c5f3b..5e78334 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -73,6 +73,10 @@ typedef int virResctrlAllocForeachCacheCallback(unsigned= int level, unsigned long long size, void *opaque); =20 +typedef int virResctrlAllocForeachMemoryCallback(unsigned int id, + unsigned int size, + void *opaque); + virResctrlAllocPtr virResctrlAllocNew(void); =20 @@ -92,6 +96,16 @@ virResctrlAllocForeachCache(virResctrlAllocPtr alloc, void *opaque); =20 int +virResctrlAllocForeachMemory(virResctrlAllocPtr resctrl, + virResctrlAllocForeachMemoryCallback cb, + void *opaque); + +int +virResctrlSetMemoryBandwidth(virResctrlAllocPtr alloc, + unsigned int id, + unsigned int memory_bandwidth); + +int virResctrlAllocSetID(virResctrlAllocPtr alloc, const char *id); const char * --=20 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Thu May 2 15:54:52 2024 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; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1529056377517687.6005355089897; Fri, 15 Jun 2018 02:52:57 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E107582C6; Fri, 15 Jun 2018 09:52:55 +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 9788D821D2; Fri, 15 Jun 2018 09:52:55 +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 33800180BACA; Fri, 15 Jun 2018 09:52:55 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w5F9qmuE007056 for ; Fri, 15 Jun 2018 05:52:48 -0400 Received: by smtp.corp.redhat.com (Postfix) id 36283604D9; Fri, 15 Jun 2018 09:52:48 +0000 (UTC) Received: from mx1.redhat.com (ext-mx07.extmail.prod.ext.phx2.redhat.com [10.5.110.31]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 2A8D111A270 for ; Fri, 15 Jun 2018 09:52:45 +0000 (UTC) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A99E0C0021D9 for ; Fri, 15 Jun 2018 09:52:44 +0000 (UTC) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Jun 2018 02:52:44 -0700 Received: from bing-i9.bj.intel.com ([172.16.182.85]) by orsmga001.jf.intel.com with ESMTP; 15 Jun 2018 02:52:42 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,226,1526367600"; d="scan'208";a="64805871" From: bing.niu@intel.com To: libvir-list@redhat.com Date: Fri, 15 Jun 2018 17:29:27 +0800 Message-Id: <1529054969-68474-4-git-send-email-bing.niu@intel.com> In-Reply-To: <1529054969-68474-1-git-send-email-bing.niu@intel.com> References: <1529054969-68474-1-git-send-email-bing.niu@intel.com> X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 207 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 15 Jun 2018 09:52:44 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 15 Jun 2018 09:52:44 +0000 (UTC) for IP:'134.134.136.31' DOMAIN:'mga06.intel.com' HELO:'mga06.intel.com' FROM:'bing.niu@intel.com' RCPT:'' X-RedHat-Spam-Score: -2.301 (RCVD_IN_DNSWL_MED, SPF_PASS) 134.134.136.31 mga06.intel.com 134.134.136.31 mga06.intel.com X-Scanned-By: MIMEDefang 2.78 on 10.5.110.31 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com Cc: shaohe.feng@intel.com, huaqiang.wang@intel.com, Bing Niu , jian-feng.ding@intel.com, rui.zang@yandex.com Subject: [libvirt] [RFCv2 PATCH 3/5] conf: rename cachetune to restune 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.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 15 Jun 2018 09:52:56 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Bing Niu resctrl not only supports cache tuning, but also memory bandwidth tuning. Rename cachetune to restune(resource tuning) to reflect that. Signed-off-by: Bing Niu --- src/conf/domain_conf.c | 44 ++++++++++++++++++++++---------------------- src/conf/domain_conf.h | 10 +++++----- src/qemu/qemu_process.c | 18 +++++++++--------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 62c412e..b3543f3 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2950,14 +2950,14 @@ virDomainLoaderDefFree(virDomainLoaderDefPtr loader) =20 =20 static void -virDomainCachetuneDefFree(virDomainCachetuneDefPtr cachetune) +virDomainRestuneDefFree(virDomainRestuneDefPtr restune) { - if (!cachetune) + if (!restune) return; =20 - virObjectUnref(cachetune->alloc); - virBitmapFree(cachetune->vcpus); - VIR_FREE(cachetune); + virObjectUnref(restune->alloc); + virBitmapFree(restune->vcpus); + VIR_FREE(restune); } =20 =20 @@ -3147,9 +3147,9 @@ 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); + for (i =3D 0; i < def->nrestunes; i++) + virDomainRestuneDefFree(def->restunes[i]); + VIR_FREE(def->restunes); =20 VIR_FREE(def->keywrap); =20 @@ -18971,7 +18971,7 @@ virDomainCachetuneDefParse(virDomainDefPtr def, xmlNodePtr *nodes =3D NULL; virBitmapPtr vcpus =3D NULL; virResctrlAllocPtr alloc =3D virResctrlAllocNew(); - virDomainCachetuneDefPtr tmp_cachetune =3D NULL; + virDomainRestuneDefPtr tmp_restune =3D NULL; char *tmp =3D NULL; char *vcpus_str =3D NULL; char *alloc_id =3D NULL; @@ -18984,7 +18984,7 @@ virDomainCachetuneDefParse(virDomainDefPtr def, if (!alloc) goto cleanup; =20 - if (VIR_ALLOC(tmp_cachetune) < 0) + if (VIR_ALLOC(tmp_restune) < 0) goto cleanup; =20 vcpus_str =3D virXMLPropString(node, "vcpus"); @@ -19025,8 +19025,8 @@ virDomainCachetuneDefParse(virDomainDefPtr def, goto cleanup; } =20 - for (i =3D 0; i < def->ncachetunes; i++) { - if (virBitmapOverlaps(def->cachetunes[i]->vcpus, vcpus)) { + for (i =3D 0; i < def->nrestunes; i++) { + if (virBitmapOverlaps(def->restunes[i]->vcpus, vcpus)) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Overlapping vcpus in cachetunes")); goto cleanup; @@ -19056,16 +19056,16 @@ virDomainCachetuneDefParse(virDomainDefPtr def, if (virResctrlAllocSetID(alloc, alloc_id) < 0) goto cleanup; =20 - VIR_STEAL_PTR(tmp_cachetune->vcpus, vcpus); - VIR_STEAL_PTR(tmp_cachetune->alloc, alloc); + VIR_STEAL_PTR(tmp_restune->vcpus, vcpus); + VIR_STEAL_PTR(tmp_restune->alloc, alloc); =20 - if (VIR_APPEND_ELEMENT(def->cachetunes, def->ncachetunes, tmp_cachetun= e) < 0) + if (VIR_APPEND_ELEMENT(def->restunes, def->nrestunes, tmp_restune) < 0) goto cleanup; =20 ret =3D 0; cleanup: ctxt->node =3D oldnode; - virDomainCachetuneDefFree(tmp_cachetune); + virDomainRestuneDefFree(tmp_restune); virObjectUnref(alloc); virBitmapFree(vcpus); VIR_FREE(alloc_id); @@ -26874,7 +26874,7 @@ virDomainCachetuneDefFormatHelper(unsigned int leve= l, =20 static int virDomainCachetuneDefFormat(virBufferPtr buf, - virDomainCachetuneDefPtr cachetune, + virDomainRestuneDefPtr restune, unsigned int flags) { virBuffer childrenBuf =3D VIR_BUFFER_INITIALIZER; @@ -26882,7 +26882,7 @@ virDomainCachetuneDefFormat(virBufferPtr buf, int ret =3D -1; =20 virBufferSetChildIndent(&childrenBuf, buf); - virResctrlAllocForeachCache(cachetune->alloc, + virResctrlAllocForeachCache(restune->alloc, virDomainCachetuneDefFormatHelper, &childrenBuf); =20 @@ -26895,14 +26895,14 @@ virDomainCachetuneDefFormat(virBufferPtr buf, goto cleanup; } =20 - vcpus =3D virBitmapFormat(cachetune->vcpus); + vcpus =3D virBitmapFormat(restune->vcpus); if (!vcpus) goto cleanup; =20 virBufferAsprintf(buf, "alloc); + const char *alloc_id =3D virResctrlAllocGetID(restune->alloc); if (!alloc_id) goto cleanup; =20 @@ -27023,8 +27023,8 @@ virDomainCputuneDefFormat(virBufferPtr buf, def->iothreadids[i]->iothread_id); } =20 - for (i =3D 0; i < def->ncachetunes; i++) - virDomainCachetuneDefFormat(&childrenBuf, def->cachetunes[i], flag= s); + for (i =3D 0; i < def->nrestunes; i++) + virDomainCachetuneDefFormat(&childrenBuf, def->restunes[i], flags); =20 if (virBufferCheckError(&childrenBuf) < 0) return -1; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6344c02..9e71a0b 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2228,10 +2228,10 @@ struct _virDomainCputune { }; =20 =20 -typedef struct _virDomainCachetuneDef virDomainCachetuneDef; -typedef virDomainCachetuneDef *virDomainCachetuneDefPtr; +typedef struct _virDomainRestuneDef virDomainRestuneDef; +typedef virDomainRestuneDef *virDomainRestuneDefPtr; =20 -struct _virDomainCachetuneDef { +struct _virDomainRestuneDef { virBitmapPtr vcpus; virResctrlAllocPtr alloc; }; @@ -2409,8 +2409,8 @@ struct _virDomainDef { =20 virDomainCputune cputune; =20 - virDomainCachetuneDefPtr *cachetunes; - size_t ncachetunes; + virDomainRestuneDefPtr *restunes; + size_t nrestunes; =20 virDomainNumaPtr numa; virDomainResourceDefPtr resource; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 93fd6ba..0659c06 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2447,7 +2447,7 @@ qemuProcessResctrlCreate(virQEMUDriverPtr driver, virCapsPtr caps =3D NULL; qemuDomainObjPrivatePtr priv =3D vm->privateData; =20 - if (!vm->def->ncachetunes) + if (!vm->def->nrestunes) return 0; =20 /* Force capability refresh since resctrl info can change @@ -2456,9 +2456,9 @@ qemuProcessResctrlCreate(virQEMUDriverPtr driver, if (!caps) return -1; =20 - for (i =3D 0; i < vm->def->ncachetunes; i++) { + for (i =3D 0; i < vm->def->nrestunes; i++) { if (virResctrlAllocCreate(caps->host.resctrl, - vm->def->cachetunes[i]->alloc, + vm->def->restunes[i]->alloc, priv->machineName) < 0) goto cleanup; } @@ -5259,8 +5259,8 @@ qemuProcessSetupVcpu(virDomainObjPtr vm, &vcpu->sched) < 0) return -1; =20 - for (i =3D 0; i < vm->def->ncachetunes; i++) { - virDomainCachetuneDefPtr ct =3D vm->def->cachetunes[i]; + for (i =3D 0; i < vm->def->nrestunes; i++) { + virDomainRestuneDefPtr ct =3D vm->def->restunes[i]; =20 if (virBitmapIsBitSet(ct->vcpus, vcpuid)) { if (virResctrlAllocAddPID(ct->alloc, vcpupid) < 0) @@ -6955,8 +6955,8 @@ void qemuProcessStop(virQEMUDriverPtr driver, /* Remove resctrl allocation after cgroups are cleaned up which makes = it * kind of safer (although removing the allocation should work even wi= th * pids in tasks file */ - for (i =3D 0; i < vm->def->ncachetunes; i++) - virResctrlAllocRemove(vm->def->cachetunes[i]->alloc); + for (i =3D 0; i < vm->def->nrestunes; i++) + virResctrlAllocRemove(vm->def->restunes[i]->alloc); =20 qemuProcessRemoveDomainStatus(driver, vm); =20 @@ -7676,8 +7676,8 @@ qemuProcessReconnect(void *opaque) if (qemuConnectAgent(driver, obj) < 0) goto error; =20 - for (i =3D 0; i < obj->def->ncachetunes; i++) { - if (virResctrlAllocDeterminePath(obj->def->cachetunes[i]->alloc, + for (i =3D 0; i < obj->def->nrestunes; i++) { + if (virResctrlAllocDeterminePath(obj->def->restunes[i]->alloc, priv->machineName) < 0) goto error; } --=20 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Thu May 2 15:54:52 2024 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; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1529056373206983.263921200361; Fri, 15 Jun 2018 02:52:53 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.25]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EBDF030001DA; Fri, 15 Jun 2018 09:52:51 +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 B5CB520D7440; Fri, 15 Jun 2018 09:52:51 +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 5B51C1800538; Fri, 15 Jun 2018 09:52:51 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w5F9qmFL007051 for ; Fri, 15 Jun 2018 05:52:48 -0400 Received: by smtp.corp.redhat.com (Postfix) id 07A4010843F7; Fri, 15 Jun 2018 09:52:48 +0000 (UTC) Received: from mx1.redhat.com (ext-mx02.extmail.prod.ext.phx2.redhat.com [10.5.110.26]) by smtp.corp.redhat.com (Postfix) with ESMTPS id F394E1092020 for ; Fri, 15 Jun 2018 09:52:47 +0000 (UTC) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8E6988762D for ; Fri, 15 Jun 2018 09:52:46 +0000 (UTC) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Jun 2018 02:52:46 -0700 Received: from bing-i9.bj.intel.com ([172.16.182.85]) by orsmga001.jf.intel.com with ESMTP; 15 Jun 2018 02:52:44 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,226,1526367600"; d="scan'208";a="64805882" From: bing.niu@intel.com To: libvir-list@redhat.com Date: Fri, 15 Jun 2018 17:29:28 +0800 Message-Id: <1529054969-68474-5-git-send-email-bing.niu@intel.com> In-Reply-To: <1529054969-68474-1-git-send-email-bing.niu@intel.com> References: <1529054969-68474-1-git-send-email-bing.niu@intel.com> X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 207 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 15 Jun 2018 09:52:46 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 15 Jun 2018 09:52:46 +0000 (UTC) for IP:'134.134.136.31' DOMAIN:'mga06.intel.com' HELO:'mga06.intel.com' FROM:'bing.niu@intel.com' RCPT:'' X-RedHat-Spam-Score: -2.301 (RCVD_IN_DNSWL_MED, SPF_PASS) 134.134.136.31 mga06.intel.com 134.134.136.31 mga06.intel.com X-Scanned-By: MIMEDefang 2.78 on 10.5.110.26 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-loop: libvir-list@redhat.com Cc: shaohe.feng@intel.com, huaqiang.wang@intel.com, Bing Niu , jian-feng.ding@intel.com, rui.zang@yandex.com Subject: [libvirt] [RFCv2 PATCH 4/5] conf: Introduce cputune/memorytune to support memory bandwidth allocation 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.84 on 10.5.11.25 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Fri, 15 Jun 2018 09:52:52 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Bing Niu Introduce a new section memorytune to support memory bandwidth allocation. This is consistent with existing cachetune . As the example below: id --- on which node memory bandwidth to be set bandwidth --- the memory bandwidth percent to set. Signed-off-by: Bing Niu --- src/conf/domain_conf.c | 260 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 260 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b3543f3..dbfd69f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -19076,6 +19076,189 @@ virDomainCachetuneDefParse(virDomainDefPtr def, } =20 =20 +static int +virDomainMemorytuneDefParseMemory(xmlXPathContextPtr ctxt, + xmlNodePtr node, + virResctrlAllocPtr alloc) +{ + xmlNodePtr oldnode =3D ctxt->node; + unsigned int id; + unsigned int bandwidth; + 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 memorytune attribute 'id'")); + goto cleanup; + } + if (virStrToLong_uip(tmp, NULL, 10, &id) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid memorytune attribute 'id' value '%s'"), + tmp); + goto cleanup; + } + VIR_FREE(tmp); + + tmp =3D virXMLPropString(node, "bandwidth"); + if (!tmp) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing memorytune attribute 'bandwidth'")); + goto cleanup; + } + if (virStrToLong_uip(tmp, NULL, 10, &bandwidth) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid memorytune attribute 'bandwidth' value '= %s'"), + tmp); + goto cleanup; + } + VIR_FREE(tmp); + if (virResctrlSetMemoryBandwidth(alloc, id, bandwidth) < 0) + goto cleanup; + + ret =3D 0; + cleanup: + ctxt->node =3D oldnode; + VIR_FREE(tmp); + return ret; +} + + +static int +virDomainMemorytuneDefParse(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 NULL; + virDomainRestuneDefPtr 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; + bool new_alloc =3D false; + + ctxt->node =3D node; + + if (VIR_ALLOC(tmp_cachetune) < 0) + goto cleanup; + + vcpus_str =3D virXMLPropString(node, "vcpus"); + if (!vcpus_str) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing memorytune attribute 'vcpus'")); + goto cleanup; + } + if (virBitmapParse(vcpus_str, &vcpus, VIR_DOMAIN_CPUMASK_LEN) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid memorytune 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("./node", ctxt, &nodes)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot extract memory nodes under memorytune")); + goto cleanup; + } + for (i =3D 0; i < def->nrestunes; i++) { + /* vcpus group has been created, directly use the existing one. + * Just updating memory allocation information of that group + * */ + if (virBitmapEqual(def->restunes[i]->vcpus, vcpus)) { + alloc =3D def->restunes[i]->alloc; + break; + } + + /* vcpus can not overlapping */ + if (virBitmapOverlaps(def->restunes[i]->vcpus, vcpus)) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Overlapping vcpus in memorytunes")); + goto cleanup; + } + } + + if (!alloc) { + alloc =3D virResctrlAllocNew(); + new_alloc =3D true; + } + + for (i =3D 0; i < n; i++) { + if (virDomainMemorytuneDefParseMemory(ctxt, nodes[i], alloc) < 0) + goto cleanup; + } + /* + * If this is a new allocation, format ID and append to restune, other= wise + * just update the existing alloc information + * */ + if (new_alloc) { + if (virResctrlAllocIsEmpty(alloc)) { + ret =3D 0; + goto cleanup; + } + + + /* We need to format it back because we need to be consistent in t= he naming + * 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 allocations is limited and the directory stru= cture is flat, + * not hierarchical, so we need to have all same allocations i= n one + * directory, so it's nice to have it named appropriately. Fo= r now it's + * 'vcpus_...' but it's designed in order for it to be changea= ble 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->restunes, def->nrestunes, tmp_cachetun= e) < 0) + goto cleanup; + } + ret =3D 0; + cleanup: + ctxt->node =3D oldnode; + virDomainRestuneDefFree(tmp_cachetune); + if (new_alloc) + 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, @@ -19671,6 +19854,18 @@ virDomainDefParseXML(xmlDocPtr xml, } VIR_FREE(nodes); =20 + if ((n =3D virXPathNodeSet("./cputune/memorytune", ctxt, &nodes)) < 0)= { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot extract memorytune nodes")); + goto error; + } + + for (i =3D 0; i < n; i++) { + if (virDomainMemorytuneDefParse(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 @@ -26922,6 +27117,68 @@ virDomainCachetuneDefFormat(virBufferPtr buf, =20 =20 static int +virDomainMemorytuneDefFormatHelper(unsigned int id, + unsigned int bandwidth, + void *opaque) +{ + virBufferPtr buf =3D opaque; + + virBufferAsprintf(buf, + "\n", + id, bandwidth); + return 0; +} + + +static int +virDomainMemorytuneDefFormat(virBufferPtr buf, + virDomainRestuneDefPtr restune, + unsigned int flags) +{ + virBuffer childrenBuf =3D VIR_BUFFER_INITIALIZER; + char *vcpus =3D NULL; + int ret =3D -1; + + virBufferSetChildIndent(&childrenBuf, buf); + virResctrlAllocForeachMemory(restune->alloc, + virDomainMemorytuneDefFormatHelper, + &childrenBuf); + + + if (virBufferCheckError(&childrenBuf) < 0) + goto cleanup; + + if (!virBufferUse(&childrenBuf)) { + ret =3D 0; + goto cleanup; + } + + vcpus =3D virBitmapFormat(restune->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, unsigned int flags) @@ -27026,6 +27283,9 @@ virDomainCputuneDefFormat(virBufferPtr buf, for (i =3D 0; i < def->nrestunes; i++) virDomainCachetuneDefFormat(&childrenBuf, def->restunes[i], flags); =20 + for (i =3D 0; i < def->nrestunes; i++) + virDomainMemorytuneDefFormat(&childrenBuf, def->restunes[i], flags= ); + if (virBufferCheckError(&childrenBuf) < 0) return -1; =20 --=20 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Thu May 2 15:54:52 2024 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; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1529056381152645.4246351486871; Fri, 15 Jun 2018 02:53:01 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 17F0B30D296D; Fri, 15 Jun 2018 09:53:00 +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 C5D6595A67; Fri, 15 Jun 2018 09:52:59 +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 6B293180053D; Fri, 15 Jun 2018 09:52:59 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w5F9qnZC007068 for ; Fri, 15 Jun 2018 05:52:49 -0400 Received: by smtp.corp.redhat.com (Postfix) id 641BF261A6; Fri, 15 Jun 2018 09:52:49 +0000 (UTC) Received: from mx1.redhat.com (ext-mx02.extmail.prod.ext.phx2.redhat.com [10.5.110.26]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 5E7EF2618E for ; Fri, 15 Jun 2018 09:52:49 +0000 (UTC) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 017D087631 for ; Fri, 15 Jun 2018 09:52:48 +0000 (UTC) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Jun 2018 02:52:47 -0700 Received: from bing-i9.bj.intel.com ([172.16.182.85]) by orsmga001.jf.intel.com with ESMTP; 15 Jun 2018 02:52:46 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,226,1526367600"; d="scan'208";a="64805895" From: bing.niu@intel.com To: libvir-list@redhat.com Date: Fri, 15 Jun 2018 17:29:29 +0800 Message-Id: <1529054969-68474-6-git-send-email-bing.niu@intel.com> In-Reply-To: <1529054969-68474-1-git-send-email-bing.niu@intel.com> References: <1529054969-68474-1-git-send-email-bing.niu@intel.com> X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 207 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 15 Jun 2018 09:52:48 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 15 Jun 2018 09:52:48 +0000 (UTC) for IP:'134.134.136.31' DOMAIN:'mga06.intel.com' HELO:'mga06.intel.com' FROM:'bing.niu@intel.com' RCPT:'' X-RedHat-Spam-Score: -2.301 (RCVD_IN_DNSWL_MED, SPF_PASS) 134.134.136.31 mga06.intel.com 134.134.136.31 mga06.intel.com X-Scanned-By: MIMEDefang 2.78 on 10.5.110.26 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-loop: libvir-list@redhat.com Cc: shaohe.feng@intel.com, huaqiang.wang@intel.com, Bing Niu , jian-feng.ding@intel.com, rui.zang@yandex.com Subject: [libvirt] [RFCv2 PATCH 5/5] conf: add memory bandwidth allocation capability of host 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.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Fri, 15 Jun 2018 09:53:00 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Bing Niu Add new XML section to report host's memory bandwidth allocation capability. The format as below example: ..... granularity ---- granularity of memory bandwidth, unit percentage. min ---- minimum memory bandwidth allowed, unit percentage. maxAllocs ---- maximum memory bandwidth allocation group supported. Signed-off-by: Bing Niu --- src/conf/capabilities.c | 108 ++++++++++++++++++++++++++++++++++++++++++++= ++++ src/conf/capabilities.h | 11 +++++ src/util/virresctrl.c | 20 +++++++++ src/util/virresctrl.h | 15 +++++++ 4 files changed, 154 insertions(+) diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index 7a810ef..3bba153 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c @@ -198,6 +198,16 @@ virCapabilitiesFreeNUMAInfo(virCapsPtr caps) } =20 static void +virCapsHostMemoryNodeFree(virCapsHostMemoryNodePtr ptr) +{ + if (!ptr) + return; + + virBitmapFree(ptr->cpus); + VIR_FREE(ptr); +} + +static void virCapabilitiesClearSecModel(virCapsHostSecModelPtr secmodel) { size_t i; @@ -239,6 +249,11 @@ virCapsDispose(void *object) virCapsHostCacheBankFree(caps->host.caches[i]); VIR_FREE(caps->host.caches); =20 + for (i =3D 0; i < caps->host.nnodes; i++) + virCapsHostMemoryNodeFree(caps->host.nodes[i]); + VIR_FREE(caps->host.nodes); + + VIR_FREE(caps->host.netprefix); VIR_FREE(caps->host.pagesSize); virCPUDefFree(caps->host.cpu); @@ -957,6 +972,58 @@ virCapabilitiesFormatCaches(virBufferPtr buf, return 0; } =20 +static int +virCapabilitiesFormatMemory(virBufferPtr buf, + size_t nnodes, + virCapsHostMemoryNodePtr *nodes) +{ + size_t i =3D 0; + virBuffer controlBuf =3D VIR_BUFFER_INITIALIZER; + + if (!nnodes) + return 0; + + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + + for (i =3D 0; i < nnodes; i++) { + virCapsHostMemoryNodePtr node =3D nodes[i]; + virResctrlInfoPerNodePtr control =3D &node->control; + char *cpus_str =3D virBitmapFormat(node->cpus); + + if (!cpus_str) + return -1; + + virBufferAsprintf(buf, + "id, cpus_str); + VIR_FREE(cpus_str); + + virBufferSetChildIndent(&controlBuf, buf); + virBufferAsprintf(&controlBuf, + "\n", + control->granularity, control->min, + control->max_allocation); + + if (virBufferCheckError(&controlBuf) < 0) + return -1; + + if (virBufferUse(&controlBuf)) { + virBufferAddLit(buf, ">\n"); + virBufferAddBuffer(buf, &controlBuf); + virBufferAddLit(buf, "\n"); + } else { + virBufferAddLit(buf, "/>\n"); + } + } + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + + return 0; +} + /** * virCapabilitiesFormatXML: * @caps: capabilities to format @@ -1060,6 +1127,10 @@ virCapabilitiesFormatXML(virCapsPtr caps) caps->host.caches) < 0) goto error; =20 + if (virCapabilitiesFormatMemory(&buf, caps->host.nnodes, + caps->host.nodes) < 0) + goto error; + for (i =3D 0; i < caps->host.nsecModels; i++) { virBufferAddLit(&buf, "\n"); virBufferAdjustIndent(&buf, 2); @@ -1602,6 +1673,40 @@ virCapabilitiesInitResctrl(virCapsPtr caps) } =20 =20 +static int +virCapabilitiesInitResctrlMemory(virCapsPtr caps) +{ + virCapsHostMemoryNodePtr node =3D NULL; + size_t i =3D 0; + int ret =3D -1; + + for (i =3D 0; i < caps->host.ncaches; i++) { + virCapsHostCacheBankPtr bank =3D caps->host.caches[i]; + if (VIR_ALLOC(node) < 0) + goto cleanup; + + if (virResctrlInfoGetMemory(caps->host.resctrl, bank->level, &node= ->control) > 0) { + node->id =3D bank->id; + if (!(node->cpus =3D virBitmapNewCopy(bank->cpus))) + goto cleanup; + + if (VIR_APPEND_ELEMENT(caps->host.nodes, + caps->host.nnodes, + node) < 0) { + goto cleanup; + } + } + virCapsHostMemoryNodeFree(node); + node =3D NULL; + } + + ret =3D 0; + cleanup: + virCapsHostMemoryNodeFree(node); + return ret; +} + + int virCapabilitiesInitCaches(virCapsPtr caps) { @@ -1731,6 +1836,9 @@ virCapabilitiesInitCaches(virCapsPtr caps) qsort(caps->host.caches, caps->host.ncaches, sizeof(*caps->host.caches), virCapsHostCacheBankSorter); =20 + if (virCapabilitiesInitResctrlMemory(caps) < 0) + goto cleanup; + ret =3D 0; cleanup: VIR_FREE(type); diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h index fe1b9ea..73e165e 100644 --- a/src/conf/capabilities.h +++ b/src/conf/capabilities.h @@ -151,6 +151,14 @@ struct _virCapsHostCacheBank { virResctrlInfoPerCachePtr *controls; }; =20 +typedef struct _virCapsHostMemoryNode virCapsHostMemoryNode; +typedef virCapsHostMemoryNode *virCapsHostMemoryNodePtr; +struct _virCapsHostMemoryNode { + unsigned int id; + virBitmapPtr cpus; /* All CPUs that belong to this node*/ + virResctrlInfoPerNode control; +}; + typedef struct _virCapsHost virCapsHost; typedef virCapsHost *virCapsHostPtr; struct _virCapsHost { @@ -175,6 +183,9 @@ struct _virCapsHost { size_t ncaches; virCapsHostCacheBankPtr *caches; =20 + size_t nnodes; + virCapsHostMemoryNodePtr *nodes; + size_t nsecModels; virCapsHostSecModelPtr secModels; =20 diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index de736b0..17f0a58 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -611,6 +611,26 @@ virResctrlInfoIsEmpty(virResctrlInfoPtr resctrl) =20 =20 int +virResctrlInfoGetMemory(virResctrlInfoPtr resctrl, + unsigned int level, + virResctrlInfoPerNodePtr control) +{ + virResctrlInfoMBPtr mb_info =3D resctrl->mb_info; + + if (!mb_info) + return 0; + + if (mb_info->last_level_cache !=3D level) + return 0; + + control->granularity =3D mb_info->bandwidth_granularity; + control->min =3D mb_info->min_bandwidth; + control->max_allocation =3D mb_info->max_allocation; + return 1; +} + + +int virResctrlInfoGetCache(virResctrlInfoPtr resctrl, unsigned int level, unsigned long long size, diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 5e78334..01fcade 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -50,6 +50,17 @@ struct _virResctrlInfoPerCache { unsigned int max_allocation; }; =20 +typedef struct _virResctrlInfoPerNode virResctrlInfoPerNode; +typedef virResctrlInfoPerNode *virResctrlInfoPerNodePtr; +struct _virResctrlInfoPerNode { + /* Smallest possible increase of the allocation bandwidth in percentag= e */ + unsigned int granularity; + /* Minimal allocatable bandwidth in percentage */ + unsigned int min; + /* Maximum number of simultaneous allocations */ + unsigned int max_allocation; +}; + typedef struct _virResctrlInfo virResctrlInfo; typedef virResctrlInfo *virResctrlInfoPtr; =20 @@ -63,6 +74,10 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl, size_t *ncontrols, virResctrlInfoPerCachePtr **controls); =20 +int +virResctrlInfoGetMemory(virResctrlInfoPtr resctrl, + unsigned int level, + virResctrlInfoPerNodePtr control); /* Alloc-related things */ typedef struct _virResctrlAlloc virResctrlAlloc; typedef virResctrlAlloc *virResctrlAllocPtr; --=20 2.7.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list