From nobody Mon Apr 29 11:47: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 Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1516730734592295.44477111175763; Tue, 23 Jan 2018 10:05:34 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8A033A3260; Tue, 23 Jan 2018 18:05:33 +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 55A111915F; Tue, 23 Jan 2018 18:05:33 +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 1248E410B7; Tue, 23 Jan 2018 18:05:33 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w0NI5Sjm021548 for ; Tue, 23 Jan 2018 13:05:28 -0500 Received: by smtp.corp.redhat.com (Postfix) id 35B7DBA7C; Tue, 23 Jan 2018 18:05:28 +0000 (UTC) Received: from caroline.localdomain (unknown [10.43.2.67]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 95FE360F81; Tue, 23 Jan 2018 18:05:24 +0000 (UTC) Received: from caroline.brq.redhat.com (caroline.usersys.redhat.com [127.0.0.1]) by caroline.localdomain (Postfix) with ESMTP id 4A89B120437; Tue, 23 Jan 2018 19:05:23 +0100 (CET) From: Martin Kletzander To: libvir-list@redhat.com Date: Tue, 23 Jan 2018 19:05:10 +0100 Message-Id: <7a0b7eeecf3439972509fc44e16e221e8f34a77e.1516730683.git.mkletzan@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com Cc: Chris Friesen , Eli Qiao Subject: [libvirt] [PATCH 01/10] Rename virResctrlInfo to virResctrlInfoPerCache 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.11 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:34 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Just to ease the review of following patches. Signed-off-by: Martin Kletzander Reviewed-by: Pavel Hrdina --- src/conf/capabilities.c | 2 +- src/conf/capabilities.h | 2 +- src/util/virresctrl.c | 4 ++-- src/util/virresctrl.h | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index 798c9bdaeaf3..e93eaed2f0e0 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c @@ -904,7 +904,7 @@ virCapabilitiesFormatCaches(virBufferPtr buf, virBufferSetChildIndent(&controlBuf, buf); for (j =3D 0; j < bank->ncontrols; j++) { const char *min_unit; - virResctrlInfoPtr controls =3D bank->controls[j]; + virResctrlInfoPerCachePtr controls =3D bank->controls[j]; unsigned long long gran_short_size =3D controls->granularity; unsigned long long min_short_size =3D controls->min; =20 diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h index 5048fa819d95..27b88cb5edfa 100644 --- a/src/conf/capabilities.h +++ b/src/conf/capabilities.h @@ -148,7 +148,7 @@ struct _virCapsHostCacheBank { virCacheType type; /* Data, Instruction or Unified */ virBitmapPtr cpus; /* All CPUs that share this bank */ size_t ncontrols; - virResctrlInfoPtr *controls; + virResctrlInfoPerCachePtr *controls; }; =20 typedef struct _virCapsHost virCapsHost; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 2a11825a52dc..050a08178e24 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -59,7 +59,7 @@ int virResctrlGetCacheInfo(unsigned int level, unsigned long long size, virCacheType scope, - virResctrlInfoPtr **controls, + virResctrlInfoPerCachePtr **controls, size_t *ncontrols) { int ret =3D -1; @@ -69,7 +69,7 @@ virResctrlGetCacheInfo(unsigned int level, char *type_upper =3D NULL; unsigned int bits =3D 0; unsigned int min_cbm_bits =3D 0; - virResctrlInfoPtr control; + virResctrlInfoPerCachePtr control; =20 if (VIR_ALLOC(control) < 0) goto cleanup; diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 848b13e98aa3..42e852780318 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -36,9 +36,9 @@ typedef enum { VIR_ENUM_DECL(virCache); =20 =20 -typedef struct _virResctrlInfo virResctrlInfo; -typedef virResctrlInfo *virResctrlInfoPtr; -struct _virResctrlInfo { +typedef struct _virResctrlInfoPerCache virResctrlInfoPerCache; +typedef virResctrlInfoPerCache *virResctrlInfoPerCachePtr; +struct _virResctrlInfoPerCache { /* Smallest possible increase of the allocation size in bytes */ unsigned long long granularity; /* Minimal allocatable size in bytes (if different from granularity) */ @@ -54,7 +54,7 @@ int virResctrlGetCacheInfo(unsigned int level, unsigned long long size, virCacheType scope, - virResctrlInfoPtr **controls, + virResctrlInfoPerCachePtr **controls, size_t *ncontrols); =20 int --=20 2.16.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Mon Apr 29 11:47: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 Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1516730732125589.4463628632136; Tue, 23 Jan 2018 10:05:32 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9AAD86929; Tue, 23 Jan 2018 18:05:30 +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 70E17176CB; Tue, 23 Jan 2018 18:05:30 +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 3133618033DA; Tue, 23 Jan 2018 18:05:30 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w0NI5SgP021547 for ; Tue, 23 Jan 2018 13:05:28 -0500 Received: by smtp.corp.redhat.com (Postfix) id 3562DBA66; Tue, 23 Jan 2018 18:05:28 +0000 (UTC) Received: from caroline.localdomain (unknown [10.43.2.67]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A1B28BA92; Tue, 23 Jan 2018 18:05:24 +0000 (UTC) Received: from caroline.brq.redhat.com (caroline.usersys.redhat.com [127.0.0.1]) by caroline.localdomain (Postfix) with ESMTP id 56857120438; Tue, 23 Jan 2018 19:05:23 +0100 (CET) From: Martin Kletzander To: libvir-list@redhat.com Date: Tue, 23 Jan 2018 19:05:11 +0100 Message-Id: <18b5452a44ef8c58bd75df1beee4341264cd3935.1516730683.git.mkletzan@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com Cc: Chris Friesen , Eli Qiao Subject: [libvirt] [PATCH 02/10] util: Add virResctrlInfo 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.15 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:31 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This will make the current functions obsolete and it will provide more information to the virresctrl module so that it can be used later. Signed-off-by: Martin Kletzander Reviewed-by: Pavel Hrdina --- po/POTFILES.in | 1 + src/libvirt_private.syms | 3 + src/util/virresctrl.c | 305 +++++++++++++++++++++++++++++++++++++++++++= ++++ src/util/virresctrl.h | 19 +++ 4 files changed, 328 insertions(+) diff --git a/po/POTFILES.in b/po/POTFILES.in index c1fa23427eff..8382ee633621 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -252,6 +252,7 @@ src/util/virportallocator.c src/util/virprocess.c src/util/virqemu.c src/util/virrandom.c +src/util/virresctrl.c src/util/virrotatingfile.c src/util/virscsi.c src/util/virscsihost.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index bc8cc1fba9e3..e951a5495b3f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2554,6 +2554,9 @@ virCacheTypeFromString; virCacheTypeToString; virResctrlGetCacheControlType; virResctrlGetCacheInfo; +virResctrlGetInfo; +virResctrlInfoGetCache; +virResctrlInfoNew; =20 =20 # util/virrotatingfile.h diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 050a08178e24..25c11a1314dc 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -25,12 +25,15 @@ #include "viralloc.h" #include "virfile.h" #include "virlog.h" +#include "virobject.h" #include "virstring.h" =20 #define VIR_FROM_THIS VIR_FROM_RESCTRL =20 VIR_LOG_INIT("util.virresctrl") =20 + +/* Common definitions */ #define SYSFS_RESCTRL_PATH "/sys/fs/resctrl" =20 /* Resctrl is short for Resource Control. It might be implemented for var= ious @@ -55,6 +58,308 @@ VIR_ENUM_IMPL(virResctrl, VIR_CACHE_TYPE_LAST, "CODE", "DATA") =20 + +/* Info-related definitions and InfoClass-related functions */ +typedef struct _virResctrlInfoPerType virResctrlInfoPerType; +typedef virResctrlInfoPerType *virResctrlInfoPerTypePtr; +struct _virResctrlInfoPerType { + /* Kernel-provided information */ + char *cbm_mask; + unsigned int min_cbm_bits; + + /* Our computed information from the above */ + unsigned int bits; + unsigned int max_cache_id; + + /* In order to be self-sufficient we need size information per cache. + * Funnily enough, one of the outcomes of the resctrlfs design is that= it + * does not account for different sizes per cache on the same level. = So + * for the sake of easiness, let's copy that, for now. */ + unsigned long long size; + + /* Information that we will return upon request (this is public struct= ) as + * until now all the above is internal to this module */ + virResctrlInfoPerCache control; +}; + +typedef struct _virResctrlInfoPerLevel virResctrlInfoPerLevel; +typedef virResctrlInfoPerLevel *virResctrlInfoPerLevelPtr; +struct _virResctrlInfoPerLevel { + virResctrlInfoPerTypePtr *types; +}; + +struct _virResctrlInfo { + virObject parent; + + virResctrlInfoPerLevelPtr *levels; + size_t nlevels; +}; + +static virClassPtr virResctrlInfoClass; + +static void +virResctrlInfoDispose(void *obj) +{ + size_t i =3D 0; + size_t j =3D 0; + + virResctrlInfoPtr resctrl =3D obj; + + for (i =3D 0; i < resctrl->nlevels; i++) { + virResctrlInfoPerLevelPtr level =3D resctrl->levels[i]; + + if (!level) + continue; + + if (level->types) { + for (j =3D 0; j < VIR_CACHE_TYPE_LAST; j++) { + if (level->types[j]) + VIR_FREE(level->types[j]->cbm_mask); + VIR_FREE(level->types[j]); + } + } + VIR_FREE(level->types); + VIR_FREE(level); + } + + VIR_FREE(resctrl->levels); +} + + +static int +virResctrlInfoOnceInit(void) +{ + if (!(virResctrlInfoClass =3D virClassNew(virClassForObject(), + "virResctrlInfo", + sizeof(virResctrlInfo), + virResctrlInfoDispose))) + return -1; + + return 0; +} + + +VIR_ONCE_GLOBAL_INIT(virResctrlInfo) + + +virResctrlInfoPtr +virResctrlInfoNew(void) +{ + if (virResctrlInfoInitialize() < 0) + return NULL; + + return virObjectNew(virResctrlInfoClass); +} + + +/* Info-related functions */ +bool +virResctrlInfoIsEmpty(virResctrlInfoPtr resctrl) +{ + size_t i =3D 0; + size_t j =3D 0; + + if (!resctrl) + return true; + + for (i =3D 0; i < resctrl->nlevels; i++) { + virResctrlInfoPerLevelPtr i_level =3D resctrl->levels[i]; + + if (!i_level) + continue; + + for (j =3D 0; j < VIR_CACHE_TYPE_LAST; j++) { + if (i_level->types[j]) + return false; + } + } + + return true; +} + + +int +virResctrlGetInfo(virResctrlInfoPtr resctrl) +{ + DIR *dirp =3D NULL; + char *info_path =3D NULL; + char *endptr =3D NULL; + char *tmp_str =3D NULL; + int ret =3D -1; + int rv =3D -1; + int type =3D 0; + struct dirent *ent =3D NULL; + unsigned int level =3D 0; + virResctrlInfoPerLevelPtr i_level =3D NULL; + virResctrlInfoPerTypePtr i_type =3D NULL; + + 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= ) { + if (ent->d_type !=3D DT_DIR) + continue; + + if (ent->d_name[0] !=3D 'L') + continue; + + if (virStrToLong_uip(ent->d_name + 1, &endptr, 10, &level) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse resctrl cache info level")); + goto cleanup; + } + + type =3D virResctrlTypeFromString(endptr); + if (type < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse resctrl cache info type")); + goto cleanup; + } + + if (VIR_ALLOC(i_type) < 0) + goto cleanup; + + i_type->control.scope =3D type; + + rv =3D virFileReadValueUint(&i_type->control.max_allocation, + SYSFS_RESCTRL_PATH "/info/%s/num_closids= ", + ent->d_name); + if (rv =3D=3D -2) + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot get num_closids from resctrl cache in= fo")); + if (rv < 0) + goto cleanup; + + rv =3D virFileReadValueString(&i_type->cbm_mask, + SYSFS_RESCTRL_PATH + "/info/%s/cbm_mask", + ent->d_name); + if (rv =3D=3D -2) + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot get cbm_mask from resctrl cache info"= )); + if (rv < 0) + goto cleanup; + + virStringTrimOptionalNewline(i_type->cbm_mask); + + rv =3D virFileReadValueUint(&i_type->min_cbm_bits, + SYSFS_RESCTRL_PATH "/info/%s/min_cbm_bit= s", + ent->d_name); + if (rv =3D=3D -2) + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot get min_cbm_bits from resctrl cache i= nfo")); + if (rv < 0) + goto cleanup; + + if (resctrl->nlevels <=3D level && + VIR_EXPAND_N(resctrl->levels, resctrl->nlevels, + level - resctrl->nlevels + 1) < 0) + goto cleanup; + + if (!resctrl->levels[level] && + (VIR_ALLOC(resctrl->levels[level]) < 0 || + VIR_ALLOC_N(resctrl->levels[level]->types, VIR_CACHE_TYPE_LAS= T) < 0)) + goto cleanup; + i_level =3D resctrl->levels[level]; + + if (i_level->types[type]) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Duplicate cache type in resctrlfs for level = %u"), + level); + goto cleanup; + } + + for (tmp_str =3D i_type->cbm_mask; *tmp_str !=3D '\0'; tmp_str++) { + if (!c_isxdigit(*tmp_str)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse cbm_mask from resctrl cache= info")); + goto cleanup; + } + + i_type->bits +=3D count_one_bits(virHexToBin(*tmp_str)); + } + + VIR_STEAL_PTR(i_level->types[type], i_type); + } + + ret =3D 0; + cleanup: + VIR_DIR_CLOSE(dirp); + VIR_FREE(info_path); + if (i_type) + VIR_FREE(i_type->cbm_mask); + VIR_FREE(i_type); + return ret; +} + + +int +virResctrlInfoGetCache(virResctrlInfoPtr resctrl, + unsigned int level, + unsigned long long size, + size_t *ncontrols, + virResctrlInfoPerCachePtr **controls) +{ + virResctrlInfoPerLevelPtr i_level =3D NULL; + virResctrlInfoPerTypePtr i_type =3D NULL; + size_t i =3D 0; + int ret =3D -1; + + if (virResctrlInfoIsEmpty(resctrl)) + return 0; + + if (level >=3D resctrl->nlevels) + return 0; + + i_level =3D resctrl->levels[level]; + if (!i_level) + return 0; + + for (i =3D 0; i < VIR_CACHE_TYPE_LAST; i++) { + i_type =3D i_level->types[i]; + if (!i_type) + continue; + + /* Let's take the opportunity to update our internal information a= bout + * the cache size */ + if (!i_type->size) { + i_type->size =3D size; + i_type->control.granularity =3D size / i_type->bits; + if (i_type->min_cbm_bits !=3D 1) + i_type->control.min =3D i_type->min_cbm_bits * i_type->con= trol.granularity; + } else { + if (i_type->size !=3D size) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("level %u cache size %llu doesn not match= " + "expected size %llu"), + level, i_type->size, size); + goto error; + } + i_type->max_cache_id++; + } + + if (VIR_EXPAND_N(*controls, *ncontrols, 1) < 0) + goto error; + if (VIR_ALLOC((*controls)[*ncontrols - 1]) < 0) + goto error; + + memcpy((*controls)[*ncontrols - 1], &i_type->control, sizeof(i_typ= e->control)); + } + + ret =3D 0; + cleanup: + return ret; + error: + while (*ncontrols) + VIR_FREE((*controls)[--*ncontrols]); + VIR_FREE(*controls); + goto cleanup; +} + + int virResctrlGetCacheInfo(unsigned int level, unsigned long long size, diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 42e852780318..43063903730b 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -49,7 +49,26 @@ struct _virResctrlInfoPerCache { unsigned int max_allocation; }; =20 +typedef struct _virResctrlInfo virResctrlInfo; +typedef virResctrlInfo *virResctrlInfoPtr; =20 +virResctrlInfoPtr +virResctrlInfoNew(void); + +bool +virResctrlInfoIsEmpty(virResctrlInfoPtr resctrl); + +int +virResctrlGetInfo(virResctrlInfoPtr resctrl); + +int +virResctrlInfoGetCache(virResctrlInfoPtr resctrl, + unsigned int level, + unsigned long long size, + size_t *ncontrols, + virResctrlInfoPerCachePtr **controls); + +/* To be removed */ int virResctrlGetCacheInfo(unsigned int level, unsigned long long size, --=20 2.16.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Mon Apr 29 11:47: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 Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1516730731471202.62940549499035; Tue, 23 Jan 2018 10:05:31 -0800 (PST) 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 404BC81DF1; Tue, 23 Jan 2018 18:05:29 +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 0AB8860BE1; Tue, 23 Jan 2018 18:05:29 +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 B67EE18033D9; Tue, 23 Jan 2018 18:05:28 +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 w0NI5RXE021524 for ; Tue, 23 Jan 2018 13:05:27 -0500 Received: by smtp.corp.redhat.com (Postfix) id 2ED0718B45; Tue, 23 Jan 2018 18:05:27 +0000 (UTC) Received: from caroline.localdomain (unknown [10.43.2.67]) by smtp.corp.redhat.com (Postfix) with ESMTPS id AB59F1915F; Tue, 23 Jan 2018 18:05:24 +0000 (UTC) Received: from caroline.brq.redhat.com (caroline.usersys.redhat.com [127.0.0.1]) by caroline.localdomain (Postfix) with ESMTP id 62A0C120439; Tue, 23 Jan 2018 19:05:23 +0100 (CET) From: Martin Kletzander To: libvir-list@redhat.com Date: Tue, 23 Jan 2018 19:05:12 +0100 Message-Id: <8155b85cc4f9e227f98ae478439d877ff47e12c2.1516730683.git.mkletzan@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com Cc: Chris Friesen , Eli Qiao Subject: [libvirt] [PATCH 03/10] conf: Use virResctrlInfo in capabilities 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.25]); Tue, 23 Jan 2018 18:05:29 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Martin Kletzander Reviewed-by: Pavel Hrdina --- src/conf/capabilities.c | 53 ++++++++++++++++++++++++---------------------= ---- src/conf/capabilities.h | 2 ++ 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index e93eaed2f0e0..edf9f54f7710 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c @@ -245,6 +245,7 @@ virCapabilitiesDispose(void *object) VIR_FREE(caps->host.netprefix); VIR_FREE(caps->host.pagesSize); virCPUDefFree(caps->host.cpu); + virObjectUnref(caps->host.resctrl); } =20 /** @@ -1592,6 +1593,20 @@ virCapsHostCacheBankSorter(const void *a, } =20 =20 +static int +virCapabilitiesInitResctrl(virCapsPtr caps) +{ + if (caps->host.resctrl) + return 0; + + caps->host.resctrl =3D virResctrlInfoNew(); + if (!caps->host.resctrl) + return -1; + + return virResctrlGetInfo(caps->host.resctrl); +} + + int virCapabilitiesInitCaches(virCapsPtr caps) { @@ -1600,7 +1615,6 @@ virCapabilitiesInitCaches(virCapsPtr caps) ssize_t pos =3D -1; DIR *dirp =3D NULL; int ret =3D -1; - int typeret; char *path =3D NULL; char *type =3D NULL; struct dirent *ent =3D NULL; @@ -1611,6 +1625,9 @@ virCapabilitiesInitCaches(virCapsPtr caps) * lose information. */ const int cache_min_level =3D 3; =20 + if (virCapabilitiesInitResctrl(caps) < 0) + return -1; + /* offline CPUs don't provide cache info */ if (virFileReadValueBitmap(&cpus, "%s/cpu/online", SYSFS_SYSTEM_PATH) = < 0) return -1; @@ -1676,32 +1693,6 @@ virCapabilitiesInitCaches(virCapsPtr caps) SYSFS_SYSTEM_PATH, pos, ent->d_name= ) < 0) goto cleanup; =20 - typeret =3D virResctrlGetCacheControlType(bank->level); - if (typeret < 0) - goto cleanup; - - if (typeret =3D=3D 1) { - if (virResctrlGetCacheInfo(bank->level, - bank->size, - VIR_CACHE_TYPE_BOTH, - &bank->controls, - &bank->ncontrols) < 0) - goto cleanup; - } else if (typeret =3D=3D 2) { - if (virResctrlGetCacheInfo(bank->level, - bank->size, - VIR_CACHE_TYPE_CODE, - &bank->controls, - &bank->ncontrols) < 0) - goto cleanup; - if (virResctrlGetCacheInfo(bank->level, - bank->size, - VIR_CACHE_TYPE_DATA, - &bank->controls, - &bank->ncontrols) < 0) - goto cleanup; - } - kernel_type =3D virCacheKernelTypeFromString(type); if (kernel_type < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -1717,6 +1708,14 @@ virCapabilitiesInitCaches(virCapsPtr caps) break; } if (i =3D=3D caps->host.ncaches) { + /* If it is a new cache, then update its resctrl informati= on. */ + if (virResctrlInfoGetCache(caps->host.resctrl, + bank->level, + bank->size, + &bank->ncontrols, + &bank->controls) < 0) + goto cleanup; + if (VIR_APPEND_ELEMENT(caps->host.caches, caps->host.ncaches, bank) < 0) { diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h index 27b88cb5edfa..694a3590bf83 100644 --- a/src/conf/capabilities.h +++ b/src/conf/capabilities.h @@ -170,6 +170,8 @@ struct _virCapsHost { size_t nnumaCell_max; virCapsHostNUMACellPtr *numaCell; =20 + virResctrlInfoPtr resctrl; + size_t ncaches; virCapsHostCacheBankPtr *caches; =20 --=20 2.16.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Mon Apr 29 11:47: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 Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1516730738801620.5622410120105; Tue, 23 Jan 2018 10:05:38 -0800 (PST) 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 20405A3296; Tue, 23 Jan 2018 18:05:37 +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 ECA64BA7D; Tue, 23 Jan 2018 18:05:36 +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 B3E2618033DF; Tue, 23 Jan 2018 18:05:36 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w0NI5SZS021554 for ; Tue, 23 Jan 2018 13:05:28 -0500 Received: by smtp.corp.redhat.com (Postfix) id 442E15D960; Tue, 23 Jan 2018 18:05:28 +0000 (UTC) Received: from caroline.localdomain (unknown [10.43.2.67]) by smtp.corp.redhat.com (Postfix) with ESMTPS id B966F18E47; Tue, 23 Jan 2018 18:05:24 +0000 (UTC) Received: from caroline.brq.redhat.com (caroline.usersys.redhat.com [127.0.0.1]) by caroline.localdomain (Postfix) with ESMTP id 6E35312043A; Tue, 23 Jan 2018 19:05:23 +0100 (CET) From: Martin Kletzander To: libvir-list@redhat.com Date: Tue, 23 Jan 2018 19:05:13 +0100 Message-Id: <9da2b0a0511a70e23b3881423c294768112b0bd8.1516730683.git.mkletzan@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-loop: libvir-list@redhat.com Cc: Chris Friesen , Eli Qiao Subject: [libvirt] [PATCH 04/10] util: Remove now-unneeded resctrl functions 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.39]); Tue, 23 Jan 2018 18:05:37 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Martin Kletzander Reviewed-by: Pavel Hrdina --- src/libvirt_private.syms | 2 - src/util/virresctrl.c | 132 -------------------------------------------= ---- src/util/virresctrl.h | 11 ---- 3 files changed, 145 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e951a5495b3f..d63474e0fc20 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2552,8 +2552,6 @@ virRandomInt; # util/virresctrl.h virCacheTypeFromString; virCacheTypeToString; -virResctrlGetCacheControlType; -virResctrlGetCacheInfo; virResctrlGetInfo; virResctrlInfoGetCache; virResctrlInfoNew; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 25c11a1314dc..f32929468c80 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -358,135 +358,3 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl, VIR_FREE(*controls); goto cleanup; } - - -int -virResctrlGetCacheInfo(unsigned int level, - unsigned long long size, - virCacheType scope, - virResctrlInfoPerCachePtr **controls, - size_t *ncontrols) -{ - int ret =3D -1; - char *tmp =3D NULL; - char *path =3D NULL; - char *cbm_mask =3D NULL; - char *type_upper =3D NULL; - unsigned int bits =3D 0; - unsigned int min_cbm_bits =3D 0; - virResctrlInfoPerCachePtr control; - - if (VIR_ALLOC(control) < 0) - goto cleanup; - - if (scope !=3D VIR_CACHE_TYPE_BOTH && - virStringToUpper(&type_upper, virCacheTypeToString(scope)) < 0) - goto cleanup; - - if (virFileReadValueUint(&control->max_allocation, - SYSFS_RESCTRL_PATH "/info/L%u%s/num_closids", - level, - type_upper ? type_upper : "") < 0) - goto cleanup; - - if (virFileReadValueString(&cbm_mask, - SYSFS_RESCTRL_PATH - "/info/L%u%s/cbm_mask", - level, - type_upper ? type_upper: "") < 0) - goto cleanup; - - if (virFileReadValueUint(&min_cbm_bits, - SYSFS_RESCTRL_PATH "/info/L%u%s/min_cbm_bits", - level, - type_upper ? type_upper : "") < 0) - goto cleanup; - - virStringTrimOptionalNewline(cbm_mask); - - for (tmp =3D cbm_mask; *tmp !=3D '\0'; tmp++) { - if (c_isxdigit(*tmp)) - bits +=3D count_one_bits(virHexToBin(*tmp)); - } - - control->granularity =3D size / bits; - if (min_cbm_bits !=3D 1) - control->min =3D min_cbm_bits * control->granularity; - - control->scope =3D scope; - - if (VIR_APPEND_ELEMENT(*controls, *ncontrols, control) < 0) - goto cleanup; - - ret =3D 0; - - cleanup: - VIR_FREE(path); - VIR_FREE(cbm_mask); - VIR_FREE(type_upper); - VIR_FREE(control); - return ret; -} - - -static inline int -virResctrlGetCacheDir(char **path, - const char *prefix, - unsigned int level, - virCacheType type) -{ - return virAsprintf(path, - SYSFS_RESCTRL_PATH "%s/L%u%s", - prefix ? prefix : "", - level, - virResctrlTypeToString(type)); -} - - -/* - * This function tests whether TYPE of cache control is supported or not. - * - * Returns 0 if not, 1 if yes and negative value on error. - */ -static int -virResctrlGetCacheSupport(unsigned int level, virCacheType type) -{ - int ret =3D -1; - char *path =3D NULL; - - if (virResctrlGetCacheDir(&path, "/info", level, type) < 0) - return -1; - - ret =3D virFileExists(path); - VIR_FREE(path); - return ret; -} - - -/* - * This function tests which TYPE of cache control is supported - * Return values are: - * -1: error - * 0: none - * 1: CAT - * 2: CDP - */ -int -virResctrlGetCacheControlType(unsigned int level) -{ - int rv =3D -1; - - rv =3D virResctrlGetCacheSupport(level, VIR_CACHE_TYPE_BOTH); - if (rv < 0) - return -1; - if (rv) - return 1; - - rv =3D virResctrlGetCacheSupport(level, VIR_CACHE_TYPE_CODE); - if (rv < 0) - return -1; - if (rv) - return 2; - - return 0; -} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 43063903730b..471c02f28dcd 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -68,15 +68,4 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl, size_t *ncontrols, virResctrlInfoPerCachePtr **controls); =20 -/* To be removed */ -int -virResctrlGetCacheInfo(unsigned int level, - unsigned long long size, - virCacheType scope, - virResctrlInfoPerCachePtr **controls, - size_t *ncontrols); - -int -virResctrlGetCacheControlType(unsigned int level); - #endif /* __VIR_RESCTRL_H__ */ --=20 2.16.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Mon Apr 29 11:47: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 Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1516730736773630.3144517459277; Tue, 23 Jan 2018 10:05:36 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 239316AAF5; Tue, 23 Jan 2018 18:05:35 +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 E47CF176DC; Tue, 23 Jan 2018 18:05:34 +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 99174410BB; Tue, 23 Jan 2018 18:05:34 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w0NI5WT1021604 for ; Tue, 23 Jan 2018 13:05:32 -0500 Received: by smtp.corp.redhat.com (Postfix) id 22AF117AF8; 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 7CC6E5D960; 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 79CA612043B; Tue, 23 Jan 2018 19:05:23 +0100 (CET) From: Martin Kletzander To: libvir-list@redhat.com Date: Tue, 23 Jan 2018 19:05:14 +0100 Message-Id: <5e353e4fa282e350bfaae23bc7ee2a651ed29c92.1516730683.git.mkletzan@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-loop: libvir-list@redhat.com Cc: Chris Friesen , Eli Qiao Subject: [libvirt] [PATCH 05/10] resctrl: Add functions to work with resctrl allocations 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.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Tue, 23 Jan 2018 18:05:35 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" With this commit we finally have a way to read and manipulate basic resctrl settings. Locking is done only on exposed functions that read/write from/to resctrlfs. Not in functions that are exposed in virresctrlpriv.h as those = are only supposed to be used from tests. More information about how resctrl works: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/D= ocumentation/x86/intel_rdt_ui.txt Signed-off-by: Martin Kletzander Reviewed-by: Pavel Hrdina --- src/Makefile.am | 2 +- src/libvirt_private.syms | 10 + src/util/virresctrl.c | 1211 +++++++++++++++++++++++++++++++++++++++++= +++- src/util/virresctrl.h | 49 ++ src/util/virresctrlpriv.h | 27 + 5 files changed, 1288 insertions(+), 11 deletions(-) create mode 100644 src/util/virresctrlpriv.h diff --git a/src/Makefile.am b/src/Makefile.am index 166c9a8e9199..289b03747212 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -167,7 +167,7 @@ UTIL_SOURCES =3D \ util/virprocess.c util/virprocess.h \ util/virqemu.c util/virqemu.h \ util/virrandom.h util/virrandom.c \ - util/virresctrl.h util/virresctrl.c \ + util/virresctrl.h util/virresctrl.c util/virresctrlpriv.h \ util/virrotatingfile.h util/virrotatingfile.c \ util/virscsi.c util/virscsi.h \ util/virscsihost.c util/virscsihost.h \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d63474e0fc20..f2a2c8650d97 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2552,6 +2552,16 @@ virRandomInt; # util/virresctrl.h virCacheTypeFromString; virCacheTypeToString; +virResctrlAllocAddPID; +virResctrlAllocCreate; +virResctrlAllocForeachSize; +virResctrlAllocFormat; +virResctrlAllocGetID; +virResctrlAllocGetUnused; +virResctrlAllocNew; +virResctrlAllocRemove; +virResctrlAllocSetID; +virResctrlAllocSetSize; virResctrlGetInfo; virResctrlInfoGetCache; virResctrlInfoNew; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index f32929468c80..b5c0ea338830 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -18,8 +18,12 @@ =20 #include =20 -#include "virresctrl.h" +#include +#include +#include +#include =20 +#include "virresctrlpriv.h" #include "c-ctype.h" #include "count-one-bits.h" #include "viralloc.h" @@ -152,6 +156,195 @@ virResctrlInfoNew(void) } =20 =20 +/* Alloc-related definitions and AllocClass-related functions */ + +/* + * virResctrlAlloc represents one allocation (in XML under cputune/cachetu= ne and + * consequently a directory under /sys/fs/resctrl). Since it can have mul= tiple + * parts of multiple caches allocated it is represented as bunch of nested + * sparse arrays (by sparse I mean array of pointers so that each might be= NULL + * in case there is no allocation for that particular one (level, cache, .= ..)). + * + * Since one allocation can be made for caches on different levels, the fi= rst + * nested sparse array is of types virResctrlAllocPerLevel. For example i= f you + * have allocation for level 3 cache, there will be three NULL pointers an= d then + * allocated pointer to virResctrlAllocPerLevel. That way you can access = it by + * `alloc[level]` as O(1) is desired instead of crawling through normal ar= rays + * or lists in three nested loops. The code uses a lot of direct accesses. + * + * Each virResctrlAllocPerLevel can have allocations for different cache + * allocation types. You can allocate instruction cache (VIR_CACHE_TYPE_C= ODE), + * data cache (VIR_CACHE_TYPE_DATA) or unified cache (VIR_CACHE_TYPE_BOTH). + * Those allocations are kept in sparse array of virResctrlAllocPerType po= inters. + * + * For each virResctrlAllocPerType users can request some size of the cach= e to + * be allocated. That's what the sparse array `sizes` is for. Non-NULL + * pointers represent requested size allocations. The array is indexed by= host + * cache id (gotten from `/sys/devices/system/cpu/cpuX/cache/indexY/id`). = Users + * can see this information e.g. in the output of `virsh capabilities` (fo= r that + * information there's the other struct, namely `virResctrlInfo`). + * + * When allocation is being created we need to find unused part of the cac= he for + * all of them. While doing that we store the bitmask in a sparse array of + * virBitmaps named `masks` indexed the same way as `sizes`. The upper bo= unds + * of the sparse arrays are stored in nmasks or nsizes, respectively. + */ + +/* virResctrlAllocPerType represents */ +typedef struct _virResctrlAllocPerType virResctrlAllocPerType; +typedef virResctrlAllocPerType *virResctrlAllocPerTypePtr; +struct _virResctrlAllocPerType { + /* There could be bool saying whether this is set or not, but since ev= erything + * in virResctrlAlloc (and most of libvirt) goes with pointer arrays w= e would + * have to have one more level of allocation anyway, so this stays fai= thful to + * the concept */ + unsigned long long **sizes; + size_t nsizes; + + /* Mask for each cache */ + virBitmapPtr *masks; + size_t nmasks; +}; + +typedef struct _virResctrlAllocPerLevel virResctrlAllocPerLevel; +typedef virResctrlAllocPerLevel *virResctrlAllocPerLevelPtr; +struct _virResctrlAllocPerLevel { + virResctrlAllocPerTypePtr *types; /* Indexed with enum virCacheType */ + /* There is no `ntypes` member variable as it is always allocated for + * VIR_CACHE_TYPE_LAST number of items */ +}; + +struct _virResctrlAlloc { + virObject parent; + + virResctrlAllocPerLevelPtr *levels; + size_t nlevels; + + /* The identifier (any unique string for now) */ + char *id; + /* libvirt-generated path in /sys/fs/resctrl for this particular + * allocation */ + char *path; +}; + +static virClassPtr virResctrlAllocClass; + +static void +virResctrlAllocDispose(void *obj) +{ + size_t i =3D 0; + size_t j =3D 0; + size_t k =3D 0; + + virResctrlAllocPtr resctrl =3D obj; + + for (i =3D 0; i < resctrl->nlevels; i++) { + virResctrlAllocPerLevelPtr level =3D resctrl->levels[i]; + + if (!level) + continue; + + for (j =3D 0; j < VIR_CACHE_TYPE_LAST; j++) { + virResctrlAllocPerTypePtr type =3D level->types[j]; + + if (!type) + continue; + + for (k =3D 0; k < type->nsizes; k++) + VIR_FREE(type->sizes[k]); + + for (k =3D 0; k < type->nmasks; k++) + virBitmapFree(type->masks[k]); + + VIR_FREE(type->sizes); + VIR_FREE(type->masks); + VIR_FREE(type); + } + VIR_FREE(level->types); + VIR_FREE(level); + } + + VIR_FREE(resctrl->id); + VIR_FREE(resctrl->path); + VIR_FREE(resctrl->levels); +} + + +static int +virResctrlAllocOnceInit(void) +{ + if (!(virResctrlAllocClass =3D virClassNew(virClassForObject(), + "virResctrlAlloc", + sizeof(virResctrlAlloc), + virResctrlAllocDispose))) + return -1; + + return 0; +} + + +VIR_ONCE_GLOBAL_INIT(virResctrlAlloc) + + +virResctrlAllocPtr +virResctrlAllocNew(void) +{ + if (virResctrlAllocInitialize() < 0) + return NULL; + + return virObjectNew(virResctrlAllocClass); +} + + +/* Common functions */ +static int +virResctrlLockInternal(int op) +{ + int fd =3D open(SYSFS_RESCTRL_PATH, O_DIRECTORY | O_CLOEXEC); + + if (fd < 0) { + virReportSystemError(errno, "%s", _("Cannot open resctrlfs")); + return -1; + } + + if (flock(fd, op) < 0) { + virReportSystemError(errno, "%s", _("Cannot lock resctrlfs")); + VIR_FORCE_CLOSE(fd); + return -1; + } + + return fd; +} + + +static inline int +virResctrlLockWrite(void) +{ + return virResctrlLockInternal(LOCK_EX); +} + + +static int +virResctrlUnlock(int fd) +{ + if (fd =3D=3D -1) + return 0; + + /* The lock gets unlocked by closing the fd, which we need to do anywa= y in + * order to clean up properly */ + if (VIR_CLOSE(fd) < 0) { + virReportSystemError(errno, "%s", _("Cannot close resctrlfs")); + + /* Trying to save the already broken */ + if (flock(fd, LOCK_UN) < 0) + virReportSystemError(errno, "%s", _("Cannot unlock resctrlfs")= ); + return -1; + } + + return 0; +} + + /* Info-related functions */ bool virResctrlInfoIsEmpty(virResctrlInfoPtr resctrl) @@ -200,6 +393,8 @@ virResctrlGetInfo(virResctrlInfoPtr resctrl) } =20 while ((rv =3D virDirRead(dirp, &ent, SYSFS_RESCTRL_PATH "/info")) > 0= ) { + VIR_DEBUG("Parsing info type '%s'", ent->d_name); + if (ent->d_type !=3D DT_DIR) continue; =20 @@ -207,16 +402,14 @@ virResctrlGetInfo(virResctrlInfoPtr resctrl) continue; =20 if (virStrToLong_uip(ent->d_name + 1, &endptr, 10, &level) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot parse resctrl cache info level")); + VIR_DEBUG("Cannot parse resctrl cache info level '%s'", ent->d= _name + 1); goto cleanup; } =20 type =3D virResctrlTypeFromString(endptr); if (type < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot parse resctrl cache info type")); - goto cleanup; + VIR_DEBUG("Cannot parse resctrl cache info type '%s'", endptr); + continue; } =20 if (VIR_ALLOC(i_type) < 0) @@ -259,10 +452,19 @@ virResctrlGetInfo(virResctrlInfoPtr resctrl) level - resctrl->nlevels + 1) < 0) goto cleanup; =20 - if (!resctrl->levels[level] && - (VIR_ALLOC(resctrl->levels[level]) < 0 || - VIR_ALLOC_N(resctrl->levels[level]->types, VIR_CACHE_TYPE_LAS= T) < 0)) - goto cleanup; + if (!resctrl->levels[level]) { + virResctrlInfoPerTypePtr *types =3D NULL; + + if (VIR_ALLOC_N(types, VIR_CACHE_TYPE_LAST) < 0) + goto cleanup; + + if (VIR_ALLOC(resctrl->levels[level]) < 0) { + VIR_FREE(types); + goto cleanup; + } + resctrl->levels[level]->types =3D types; + } + i_level =3D resctrl->levels[level]; =20 if (i_level->types[type]) { @@ -358,3 +560,992 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl, VIR_FREE(*controls); goto cleanup; } + + +/* Alloc-related functions */ +bool +virResctrlAllocIsEmpty(virResctrlAllocPtr resctrl) +{ + size_t i =3D 0; + size_t j =3D 0; + size_t k =3D 0; + + if (!resctrl) + return true; + + for (i =3D 0; i < resctrl->nlevels; i++) { + virResctrlAllocPerLevelPtr a_level =3D resctrl->levels[i]; + + if (!a_level) + continue; + + for (j =3D 0; j < VIR_CACHE_TYPE_LAST; j++) { + virResctrlAllocPerTypePtr a_type =3D a_level->types[j]; + + if (!a_type) + continue; + + for (k =3D 0; k < a_type->nsizes; k++) { + if (a_type->sizes[k]) + return false; + } + + for (k =3D 0; k < a_type->nmasks; k++) { + if (a_type->masks[k]) + return false; + } + } + } + + return true; +} + + +static virResctrlAllocPerTypePtr +virResctrlAllocGetType(virResctrlAllocPtr resctrl, + unsigned int level, + virCacheType type) +{ + virResctrlAllocPerLevelPtr a_level =3D NULL; + + if (resctrl->nlevels <=3D level && + VIR_EXPAND_N(resctrl->levels, resctrl->nlevels, level - resctrl->n= levels + 1) < 0) + return NULL; + + if (!resctrl->levels[level]) { + virResctrlAllocPerTypePtr *types =3D NULL; + + if (VIR_ALLOC_N(types, VIR_CACHE_TYPE_LAST) < 0) + return NULL; + + if (VIR_ALLOC(resctrl->levels[level]) < 0) { + VIR_FREE(types); + return NULL; + } + resctrl->levels[level]->types =3D types; + } + + a_level =3D resctrl->levels[level]; + + if (!a_level->types[type] && VIR_ALLOC(a_level->types[type]) < 0) + return NULL; + + return a_level->types[type]; +} + + +static int +virResctrlAllocUpdateMask(virResctrlAllocPtr resctrl, + unsigned int level, + virCacheType type, + unsigned int cache, + virBitmapPtr mask) +{ + virResctrlAllocPerTypePtr a_type =3D virResctrlAllocGetType(resctrl, l= evel, type); + + if (!a_type) + return -1; + + if (a_type->nmasks <=3D cache && + VIR_EXPAND_N(a_type->masks, a_type->nmasks, + cache - a_type->nmasks + 1) < 0) + return -1; + + if (!a_type->masks[cache]) { + a_type->masks[cache] =3D virBitmapNew(virBitmapSize(mask)); + + if (!a_type->masks[cache]) + return -1; + } + + return virBitmapCopy(a_type->masks[cache], mask); +} + + +static int +virResctrlAllocUpdateSize(virResctrlAllocPtr resctrl, + unsigned int level, + virCacheType type, + unsigned int cache, + unsigned long long size) +{ + virResctrlAllocPerTypePtr a_type =3D virResctrlAllocGetType(resctrl, l= evel, type); + + if (!a_type) + return -1; + + if (a_type->nsizes <=3D cache && + VIR_EXPAND_N(a_type->sizes, a_type->nsizes, + cache - a_type->nsizes + 1) < 0) + return -1; + + if (!a_type->sizes[cache] && VIR_ALLOC(a_type->sizes[cache]) < 0) + return -1; + + *(a_type->sizes[cache]) =3D size; + + return 0; +} + + +/* + * Check if there is an allocation for this level/type/cache already. Cal= led + * before updating the structure. VIR_CACHE_TYPE_BOTH collides with any t= ype, + * the other types collide with itself. This code basically checks if eit= her: + * `alloc[level]->types[type]->sizes[cache]` + * or + * `alloc[level]->types[VIR_CACHE_TYPE_BOTH]->sizes[cache]` + * is non-NULL. All the fuzz around it is checking for NULL pointers along + * the way. + */ +static bool +virResctrlAllocCheckCollision(virResctrlAllocPtr alloc, + unsigned int level, + virCacheType type, + unsigned int cache) +{ + virResctrlAllocPerLevelPtr a_level =3D NULL; + virResctrlAllocPerTypePtr a_type =3D NULL; + + if (!alloc) + return false; + + if (alloc->nlevels <=3D level) + return false; + + a_level =3D alloc->levels[level]; + + if (!a_level) + return false; + + a_type =3D a_level->types[VIR_CACHE_TYPE_BOTH]; + + /* If there is an allocation for type 'both', there can be no other + * allocation for the same cache */ + if (a_type && a_type->nsizes > cache && a_type->sizes[cache]) + return true; + + if (type =3D=3D VIR_CACHE_TYPE_BOTH) { + a_type =3D a_level->types[VIR_CACHE_TYPE_CODE]; + + if (a_type && a_type->nsizes > cache && a_type->sizes[cache]) + return true; + + a_type =3D a_level->types[VIR_CACHE_TYPE_DATA]; + + if (a_type && a_type->nsizes > cache && a_type->sizes[cache]) + return true; + } else { + a_type =3D a_level->types[type]; + + if (a_type && a_type->nsizes > cache && a_type->sizes[cache]) + return true; + } + + return false; +} + + +int +virResctrlAllocSetSize(virResctrlAllocPtr resctrl, + unsigned int level, + virCacheType type, + unsigned int cache, + unsigned long long size) +{ + if (virResctrlAllocCheckCollision(resctrl, level, type, cache)) { + virReportError(VIR_ERR_XML_ERROR, + _("Colliding cache allocations for cache " + "level '%u' id '%u', type '%s'"), + level, cache, virCacheTypeToString(type)); + return -1; + } + + return virResctrlAllocUpdateSize(resctrl, level, type, cache, size); +} + + +int +virResctrlAllocForeachSize(virResctrlAllocPtr resctrl, + virResctrlAllocForeachSizeCallback cb, + void *opaque) +{ + int ret =3D 0; + unsigned int level =3D 0; + unsigned int type =3D 0; + unsigned int cache =3D 0; + + if (!resctrl) + return 0; + + for (level =3D 0; level < resctrl->nlevels; level++) { + virResctrlAllocPerLevelPtr a_level =3D resctrl->levels[level]; + + if (!a_level) + continue; + + for (type =3D 0; type < VIR_CACHE_TYPE_LAST; type++) { + virResctrlAllocPerTypePtr a_type =3D a_level->types[type]; + + if (!a_type) + continue; + + for (cache =3D 0; cache < a_type->nsizes; cache++) { + unsigned long long *size =3D a_type->sizes[cache]; + + if (!size) + continue; + + ret =3D cb(level, type, cache, *size, opaque); + if (ret < 0) + return ret; + } + } + } + + return 0; +} + + +int +virResctrlAllocSetID(virResctrlAllocPtr alloc, + const char *id) +{ + if (!id) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Resctrl allocation 'id' cannot be NULL")); + return -1; + } + + return VIR_STRDUP(alloc->id, id); +} + + +const char * +virResctrlAllocGetID(virResctrlAllocPtr alloc) +{ + return alloc->id; +} + + +char * +virResctrlAllocFormat(virResctrlAllocPtr resctrl) +{ + virBuffer buf =3D VIR_BUFFER_INITIALIZER; + unsigned int level =3D 0; + unsigned int type =3D 0; + unsigned int cache =3D 0; + + if (!resctrl) + return NULL; + + for (level =3D 0; level < resctrl->nlevels; level++) { + virResctrlAllocPerLevelPtr a_level =3D resctrl->levels[level]; + + if (!a_level) + continue; + + for (type =3D 0; type < VIR_CACHE_TYPE_LAST; type++) { + virResctrlAllocPerTypePtr a_type =3D a_level->types[type]; + + if (!a_type) + continue; + + virBufferAsprintf(&buf, "L%u%s:", level, virResctrlTypeToStrin= g(type)); + + for (cache =3D 0; cache < a_type->nmasks; cache++) { + virBitmapPtr mask =3D a_type->masks[cache]; + char *mask_str =3D NULL; + + if (!mask) + continue; + + mask_str =3D virBitmapToString(mask, false, true); + if (!mask_str) { + virBufferFreeAndReset(&buf); + return NULL; + } + + virBufferAsprintf(&buf, "%u=3D%s;", cache, mask_str); + VIR_FREE(mask_str); + } + + virBufferTrim(&buf, ";", 1); + virBufferAddChar(&buf, '\n'); + } + } + + virBufferCheckError(&buf); + return virBufferContentAndReset(&buf); +} + + +static int +virResctrlAllocParseProcessCache(virResctrlInfoPtr resctrl, + virResctrlAllocPtr alloc, + unsigned int level, + virCacheType type, + char *cache) +{ + char *tmp =3D strchr(cache, '=3D'); + unsigned int cache_id =3D 0; + virBitmapPtr mask =3D NULL; + int ret =3D -1; + + if (!tmp) + return 0; + + *tmp =3D '\0'; + tmp++; + + if (virStrToLong_uip(cache, NULL, 10, &cache_id) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid cache id '%s'"), cache); + return -1; + } + + mask =3D virBitmapNewString(tmp); + if (!mask) + return -1; + + virBitmapShrink(mask, resctrl->levels[level]->types[type]->bits); + + /* Guess what! All bits set mean there is no allocation and it uses o= nly + * unallocated parts of the cache. */ + if (!virBitmapIsAllSet(mask) && + virResctrlAllocUpdateMask(alloc, level, type, cache_id, mask) < 0) + goto cleanup; + + ret =3D 0; + cleanup: + virBitmapFree(mask); + return ret; +} + + +static int +virResctrlAllocParseProcessLine(virResctrlInfoPtr resctrl, + virResctrlAllocPtr alloc, + char *line) +{ + char **caches =3D NULL; + char *tmp =3D NULL; + unsigned int level =3D 0; + int type =3D -1; + size_t ncaches =3D 0; + size_t i =3D 0; + int ret =3D -1; + + /* For no reason there can be spaces */ + virSkipSpaces((const char **) &line); + + /* Skip lines that don't concern caches, e.g. MB: etc. */ + if (line[0] !=3D 'L') + return 0; + + /* And lines that we can't parse too */ + tmp =3D strchr(line, ':'); + if (!tmp) + return 0; + + *tmp =3D '\0'; + tmp++; + + if (virStrToLong_uip(line + 1, &line, 10, &level) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cannot parse resctrl schema level '%s'"), + line + 1); + return -1; + } + + type =3D virResctrlTypeFromString(line); + if (type < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cannot parse resctrl schema level '%s'"), + line + 1); + return -1; + } + + caches =3D virStringSplitCount(tmp, ";", 0, &ncaches); + if (!caches) + return 0; + + for (i =3D 0; i < ncaches; i++) { + if (virResctrlAllocParseProcessCache(resctrl, alloc, level, type, = caches[i]) < 0) + goto cleanup; + } + + ret =3D 0; + cleanup: + virStringListFree(caches); + return ret; +} + + +static int +virResctrlAllocParse(virResctrlInfoPtr resctrl, + virResctrlAllocPtr alloc, + const char *schemata) +{ + char **lines =3D NULL; + size_t nlines =3D 0; + size_t i =3D 0; + int ret =3D -1; + + lines =3D virStringSplitCount(schemata, "\n", 0, &nlines); + for (i =3D 0; i < nlines; i++) { + if (virResctrlAllocParseProcessLine(resctrl, alloc, lines[i]) < 0) + goto cleanup; + } + + ret =3D 0; + cleanup: + virStringListFree(lines); + return ret; +} + + +static void +virResctrlAllocSubtractPerType(virResctrlAllocPerTypePtr dst, + virResctrlAllocPerTypePtr src) +{ + size_t i =3D 0; + + if (!dst || !src) + return; + + for (i =3D 0; i < dst->nmasks && i < src->nmasks; i++) { + if (dst->masks[i] && src->masks[i]) + virBitmapSubtract(dst->masks[i], src->masks[i]); + } +} + + +static void +virResctrlAllocSubtract(virResctrlAllocPtr dst, + virResctrlAllocPtr src) +{ + size_t i =3D 0; + size_t j =3D 0; + + if (!src) + return; + + for (i =3D 0; i < dst->nlevels && i < src->nlevels; i++) { + if (dst->levels[i] && src->levels[i]) { + for (j =3D 0; j < VIR_CACHE_TYPE_LAST; j++) { + virResctrlAllocSubtractPerType(dst->levels[i]->types[j], + src->levels[i]->types[j]); + } + } + } +} + + +static virResctrlAllocPtr +virResctrlAllocNewFromInfo(virResctrlInfoPtr info) +{ + size_t i =3D 0; + size_t j =3D 0; + size_t k =3D 0; + virResctrlAllocPtr ret =3D virResctrlAllocNew(); + virBitmapPtr mask =3D NULL; + + if (!ret) + return NULL; + + for (i =3D 0; i < info->nlevels; i++) { + virResctrlInfoPerLevelPtr i_level =3D info->levels[i]; + + if (!i_level) + continue; + + for (j =3D 0; j < VIR_CACHE_TYPE_LAST; j++) { + virResctrlInfoPerTypePtr i_type =3D i_level->types[j]; + + if (!i_type) + continue; + + virBitmapFree(mask); + mask =3D virBitmapNew(i_type->bits); + if (!mask) + goto error; + virBitmapSetAll(mask); + + for (k =3D 0; k <=3D i_type->max_cache_id; k++) { + if (virResctrlAllocUpdateMask(ret, i, j, k, mask) < 0) + goto error; + } + } + } + + cleanup: + virBitmapFree(mask); + return ret; + error: + virObjectUnref(ret); + ret =3D NULL; + goto cleanup; +} + +/* + * This function creates an allocation that represents all unused parts of= all + * caches in the system. It uses virResctrlInfo for creating a new full + * allocation with all bits set (using virResctrlAllocNewFromInfo()) and t= hen + * scans for all allocations under /sys/fs/resctrl and subtracts each one = of + * them from it. That way it can then return an allocation with only bit = set + * being those that are not mentioned in any other allocation. It is used= for + * two things, a) calculating the masks when creating allocations and b) f= rom + * tests. + */ +virResctrlAllocPtr +virResctrlAllocGetUnused(virResctrlInfoPtr resctrl) +{ + virResctrlAllocPtr ret =3D NULL; + virResctrlAllocPtr alloc =3D NULL; + struct dirent *ent =3D NULL; + DIR *dirp =3D NULL; + char *schemata =3D NULL; + int rv =3D -1; + + if (virResctrlInfoIsEmpty(resctrl)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Resource control is not supported on this host")= ); + return NULL; + } + + ret =3D virResctrlAllocNewFromInfo(resctrl); + if (!ret) + return NULL; + + if (virFileReadValueString(&schemata, + SYSFS_RESCTRL_PATH + "/schemata") < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not read schemata file for the default gro= up")); + goto error; + } + + alloc =3D virResctrlAllocNew(); + if (!alloc) + goto error; + + if (virResctrlAllocParse(resctrl, alloc, schemata) < 0) + goto error; + if (!virResctrlAllocIsEmpty(alloc)) + virResctrlAllocSubtract(ret, alloc); + + if (virDirOpen(&dirp, SYSFS_RESCTRL_PATH) < 0) + goto error; + + while ((rv =3D virDirRead(dirp, &ent, SYSFS_RESCTRL_PATH)) > 0) { + if (ent->d_type !=3D DT_DIR) + continue; + + if (STREQ(ent->d_name, "info")) + continue; + + VIR_FREE(schemata); + rv =3D virFileReadValueString(&schemata, + SYSFS_RESCTRL_PATH + "/%s/schemata", + ent->d_name); + if (rv =3D=3D -2) + continue; + + if (rv < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not read schemata file for group %s"), + ent->d_name); + goto error; + } + + virObjectUnref(alloc); + alloc =3D virResctrlAllocNew(); + if (!alloc) + goto error; + + if (virResctrlAllocParse(resctrl, alloc, schemata) < 0) + goto error; + + virResctrlAllocSubtract(ret, alloc); + } + if (rv < 0) + goto error; + + cleanup: + virObjectUnref(alloc); + VIR_DIR_CLOSE(dirp); + VIR_FREE(schemata); + return ret; + + error: + virObjectUnref(ret); + ret =3D NULL; + goto cleanup; +} + + + +static int +virResctrlAllocSetMask(virResctrlAllocPerTypePtr a_type, + unsigned int cache, + virBitmapPtr mask) +{ + if (a_type->nmasks <=3D cache && + VIR_EXPAND_N(a_type->masks, a_type->nmasks, + cache - a_type->nmasks + 1) < 0) + return -1; + + a_type->masks[cache] =3D mask; + + return 0; +} + + +/* + * Given the information about requested allocation type `a_type`, the host + * cache for a particular type `i_type` and unused bits in the system `f_t= ype` + * this function tries to find the smallest free space in which the alloca= tion + * for cache id `cache` would fit. We're looking for the smallest place in + * order to minimize fragmentation and maximize the possibility of succeed= ing. + */ +static int +virResctrlAllocFindUnused(virResctrlAllocPerTypePtr a_type, + virResctrlInfoPerTypePtr i_type, + virResctrlAllocPerTypePtr f_type, + unsigned int level, + unsigned int type, + unsigned int cache) +{ + unsigned long long *size =3D a_type->sizes[cache]; + virBitmapPtr a_mask =3D NULL; + virBitmapPtr f_mask =3D NULL; + unsigned long long granularity; + unsigned long long need_bits; + size_t i =3D 0; + ssize_t pos =3D -1; + ssize_t last_bits =3D 0; + ssize_t last_pos =3D -1; + + /* If there is no reservation requested we need to set all bits. That= 's due + * to weird interface of the resctrl sysfs. It's also the reason why = we + * cannot reserve the whole cache in one allocation. */ + if (!size) { + a_mask =3D virBitmapNew(i_type->bits); + if (!a_mask) + return -1; + + virBitmapSetAll(a_mask); + + if (virResctrlAllocSetMask(a_type, cache, a_mask) < 0) { + virBitmapFree(a_mask); + return -1; + } + + return 0; + } + + if (cache >=3D f_type->nmasks) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Cache with id %u does not exists for level %d"), + cache, level); + return -1; + } + + f_mask =3D f_type->masks[cache]; + if (!f_mask) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Cache level %d id %u does not support tuning for= " + "scope type '%s'"), + level, cache, virCacheTypeToString(type)); + return -1; + } + + if (*size =3D=3D i_type->size) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Cache allocation for the whole cache is not " + "possible, specify size smaller than %llu"), + i_type->size); + return -1; + } + + granularity =3D i_type->size / i_type->bits; + need_bits =3D *size / granularity; + + if (*size % granularity) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Cache allocation of size %llu is not " + "divisible by granularity %llu"), + *size, granularity); + return -1; + } + + if (need_bits < i_type->min_cbm_bits) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Cache allocation of size %llu is smaller " + "than the minimum allowed allocation %llu"), + *size, granularity * i_type->min_cbm_bits); + return -1; + } + + while ((pos =3D virBitmapNextSetBit(f_mask, pos)) >=3D 0) { + ssize_t pos_clear =3D virBitmapNextClearBit(f_mask, pos); + ssize_t bits; + + if (pos_clear < 0) + pos_clear =3D virBitmapSize(f_mask); + + bits =3D pos_clear - pos; + + /* Not enough bits, move on and skip all of them */ + if (bits < need_bits) { + pos =3D pos_clear; + continue; + } + + /* This fits perfectly */ + if (bits =3D=3D need_bits) { + last_pos =3D pos; + break; + } + + /* Remember the smaller region if we already found on before */ + if (last_pos < 0 || (last_bits && bits < last_bits)) { + last_bits =3D bits; + last_pos =3D pos; + } + + pos =3D pos_clear; + } + + if (last_pos < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Not enough room for allocation of " + "%llu bytes for level %u cache %u " + "scope type '%s'"), + *size, level, cache, + virCacheTypeToString(type)); + return -1; + } + + a_mask =3D virBitmapNew(i_type->bits); + if (!a_mask) + return -1; + + for (i =3D last_pos; i < last_pos + need_bits; i++) { + ignore_value(virBitmapSetBit(a_mask, i)); + ignore_value(virBitmapClearBit(f_mask, i)); + } + + if (virResctrlAllocSetMask(a_type, cache, a_mask) < 0) { + virBitmapFree(a_mask); + return -1; + } + + return 0; +} + + +/* + * This function is called when creating an allocation in the system. Wha= t it + * does is that it gets all the unused bits using virResctrlAllocGetUnused= () and + * then tries to find a proper space for every requested allocation effect= ively + * transforming `sizes` into `masks`. + */ +static int +virResctrlAllocMasksAssign(virResctrlInfoPtr resctrl, + virResctrlAllocPtr alloc) +{ + int ret =3D -1; + unsigned int level =3D 0; + virResctrlAllocPtr alloc_free =3D NULL; + + alloc_free =3D virResctrlAllocGetUnused(resctrl); + if (!alloc_free) + return -1; + + for (level =3D 0; level < alloc->nlevels; level++) { + virResctrlAllocPerLevelPtr a_level =3D alloc->levels[level]; + virResctrlAllocPerLevelPtr f_level =3D NULL; + unsigned int type =3D 0; + + if (!a_level) + continue; + + if (level < alloc_free->nlevels) + f_level =3D alloc_free->levels[level]; + + if (!f_level) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Cache level %d does not support tuning"), + level); + goto cleanup; + } + + for (type =3D 0; type < VIR_CACHE_TYPE_LAST; type++) { + virResctrlAllocPerTypePtr a_type =3D a_level->types[type]; + virResctrlAllocPerTypePtr f_type =3D f_level->types[type]; + unsigned int cache =3D 0; + + if (!a_type) + continue; + + if (!f_type) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Cache level %d does not support tuning f= or " + "scope type '%s'"), + level, virCacheTypeToString(type)); + goto cleanup; + } + + for (cache =3D 0; cache < a_type->nsizes; cache++) { + virResctrlInfoPerLevelPtr i_level =3D resctrl->levels[leve= l]; + virResctrlInfoPerTypePtr i_type =3D i_level->types[type]; + + if (virResctrlAllocFindUnused(a_type, i_type, f_type, leve= l, type, cache) < 0) + goto cleanup; + } + } + } + + ret =3D 0; + cleanup: + virObjectUnref(alloc_free); + return ret; +} + + +/* This checks if the directory for the alloc exists. If not it tries to = create + * it and apply appropriate alloc settings. */ +int +virResctrlAllocCreate(virResctrlInfoPtr resctrl, + virResctrlAllocPtr alloc, + const char *machinename) +{ + char *schemata_path =3D NULL; + char *alloc_str =3D NULL; + int ret =3D -1; + int lockfd =3D -1; + + if (!alloc) + return 0; + + if (!resctrl) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Resource control is not supported on this host")= ); + return -1; + } + + if (!alloc->id) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Resctrl Allocation ID must be set before creatio= n")); + return -1; + } + + if (!alloc->path && + virAsprintf(&alloc->path, "%s/%s-%s", + SYSFS_RESCTRL_PATH, machinename, alloc->id) < 0) + return -1; + + /* Check if this allocation was already created */ + if (virFileIsDir(alloc->path)) + return 0; + + if (virFileExists(alloc->path)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Path '%s' for resctrl allocation exists and is n= ot a " + "directory"), alloc->path); + goto cleanup; + } + + lockfd =3D virResctrlLockWrite(); + if (lockfd < 0) + goto cleanup; + + if (virResctrlAllocMasksAssign(resctrl, alloc) < 0) + goto cleanup; + + alloc_str =3D virResctrlAllocFormat(alloc); + if (!alloc_str) + goto cleanup; + + if (virAsprintf(&schemata_path, "%s/schemata", alloc->path) < 0) + goto cleanup; + + if (virFileMakePath(alloc->path) < 0) { + virReportSystemError(errno, + _("Cannot create resctrl directory '%s'"), + alloc->path); + goto cleanup; + } + + VIR_DEBUG("Writing resctrl schemata '%s' into '%s'", alloc_str, schema= ta_path); + if (virFileWriteStr(schemata_path, alloc_str, 0) < 0) { + rmdir(alloc->path); + virReportSystemError(errno, + _("Cannot write into schemata file '%s'"), + schemata_path); + goto cleanup; + } + + ret =3D 0; + cleanup: + virResctrlUnlock(lockfd); + VIR_FREE(alloc_str); + VIR_FREE(schemata_path); + return ret; +} + + +int +virResctrlAllocAddPID(virResctrlAllocPtr alloc, + pid_t pid) +{ + char *tasks =3D NULL; + char *pidstr =3D NULL; + int ret =3D 0; + + if (!alloc->path) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot add pid to non-existing resctrl allocatio= n")); + return -1; + } + + if (virAsprintf(&tasks, "%s/tasks", alloc->path) < 0) + return -1; + + if (virAsprintf(&pidstr, "%lld", (long long int) pid) < 0) + goto cleanup; + + if (virFileWriteStr(tasks, pidstr, 0) < 0) { + virReportSystemError(errno, + _("Cannot write pid in tasks file '%s'"), + tasks); + goto cleanup; + } + + ret =3D 0; + cleanup: + VIR_FREE(tasks); + VIR_FREE(pidstr); + return ret; +} + + +int +virResctrlAllocRemove(virResctrlAllocPtr alloc) +{ + int ret =3D 0; + + if (!alloc->path) + return 0; + + VIR_DEBUG("Removing resctrl allocation %s", alloc->path); + if (rmdir(alloc->path) !=3D 0 && errno !=3D ENOENT) { + ret =3D -errno; + VIR_ERROR(_("Unable to remove %s (%d)"), alloc->path, errno); + } + + return ret; +} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 471c02f28dcd..27793c86a745 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -68,4 +68,53 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl, size_t *ncontrols, virResctrlInfoPerCachePtr **controls); =20 +/* Alloc-related things */ +typedef struct _virResctrlAlloc virResctrlAlloc; +typedef virResctrlAlloc *virResctrlAllocPtr; + +typedef int virResctrlAllocForeachSizeCallback(unsigned int level, + virCacheType type, + unsigned int cache, + unsigned long long size, + void *opaque); + +virResctrlAllocPtr +virResctrlAllocNew(void); + +bool +virResctrlAllocIsEmpty(virResctrlAllocPtr resctrl); + +int +virResctrlAllocSetSize(virResctrlAllocPtr resctrl, + unsigned int level, + virCacheType type, + unsigned int cache, + unsigned long long size); + +int +virResctrlAllocForeachSize(virResctrlAllocPtr resctrl, + virResctrlAllocForeachSizeCallback cb, + void *opaque); + +int +virResctrlAllocSetID(virResctrlAllocPtr alloc, + const char *id); +const char * +virResctrlAllocGetID(virResctrlAllocPtr alloc); + +char * +virResctrlAllocFormat(virResctrlAllocPtr alloc); + +int +virResctrlAllocCreate(virResctrlInfoPtr r_info, + virResctrlAllocPtr alloc, + const char *machinename); + +int +virResctrlAllocAddPID(virResctrlAllocPtr alloc, + pid_t pid); + +int +virResctrlAllocRemove(virResctrlAllocPtr alloc); + #endif /* __VIR_RESCTRL_H__ */ diff --git a/src/util/virresctrlpriv.h b/src/util/virresctrlpriv.h new file mode 100644 index 000000000000..72b115afd13e --- /dev/null +++ b/src/util/virresctrlpriv.h @@ -0,0 +1,27 @@ +/* + * virresctrlpriv.h: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +#ifndef __VIR_RESCTRL_PRIV_H__ +# define __VIR_RESCTRL_PRIV_H__ + +# include "virresctrl.h" + +virResctrlAllocPtr +virResctrlAllocGetUnused(virResctrlInfoPtr resctrl); + +#endif /* __VIR_RESCTRL_PRIV_H__ */ --=20 2.16.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Mon Apr 29 11:47: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 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 From nobody Mon Apr 29 11:47: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 Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 15167307397431005.1575288588955; Tue, 23 Jan 2018 10:05:39 -0800 (PST) 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 7647D2D269D; Tue, 23 Jan 2018 18:05:33 +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 4DE1EBA66; Tue, 23 Jan 2018 18:05:33 +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 01AA418033DE; Tue, 23 Jan 2018 18:05:33 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w0NI5Tia021566 for ; Tue, 23 Jan 2018 13:05:29 -0500 Received: by smtp.corp.redhat.com (Postfix) id 0667A176DC; Tue, 23 Jan 2018 18:05:29 +0000 (UTC) Received: from caroline.localdomain (unknown [10.43.2.67]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A58525D6A3; 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 9013912043D; Tue, 23 Jan 2018 19:05:23 +0100 (CET) From: Martin Kletzander To: libvir-list@redhat.com Date: Tue, 23 Jan 2018 19:05:16 +0100 Message-Id: <09012196a35aff1efb8009472212e7ec03d08221.1516730683.git.mkletzan@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com Cc: Chris Friesen , Eli Qiao Subject: [libvirt] [PATCH 07/10] tests: Add virresctrltest 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.29]); Tue, 23 Jan 2018 18:05:39 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This test initializes capabilities from vircaps2xmldata (since it exists th= ere already) and then requests list of free bitmaps (all unallocated space) from virresctrl.c Desirable outputs are saved in virresctrldata. Signed-off-by: Martin Kletzander Reviewed-by: Pavel Hrdina --- tests/Makefile.am | 9 +- tests/virresctrldata/resctrl-cdp.schemata | 2 + .../virresctrldata/resctrl-skx-twocaches.schemata | 1 + tests/virresctrldata/resctrl-skx.schemata | 1 + tests/virresctrldata/resctrl.schemata | 1 + tests/virresctrltest.c | 102 +++++++++++++++++= ++++ 6 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 tests/virresctrldata/resctrl-cdp.schemata create mode 100644 tests/virresctrldata/resctrl-skx-twocaches.schemata create mode 100644 tests/virresctrldata/resctrl-skx.schemata create mode 100644 tests/virresctrldata/resctrl.schemata create mode 100644 tests/virresctrltest.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 3441dab6f6bb..497bd21a2587 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -165,6 +165,7 @@ EXTRA_DIST =3D \ xml2vmxdata \ virstorageutildata \ virfilecachedata \ + virresctrldata \ $(NULL) =20 test_helpers =3D commandhelper ssh @@ -232,6 +233,7 @@ if WITH_LINUX test_programs +=3D fchosttest test_programs +=3D scsihosttest test_programs +=3D vircaps2xmltest +test_programs +=3D virresctrltest test_libraries +=3D virusbmock.la \ virnetdevbandwidthmock.la \ virnumamock.la \ @@ -1165,8 +1167,13 @@ virnumamock_la_SOURCES =3D \ virnumamock_la_LDFLAGS =3D $(MOCKLIBS_LDFLAGS) virnumamock_la_LIBADD =3D $(MOCKLIBS_LIBS) =20 +virresctrltest_SOURCES =3D \ + virresctrltest.c testutils.h testutils.c virfilewrapper.h virfilewrapper.c +virresctrltest_LDADD =3D $(LDADDS) + else ! WITH_LINUX -EXTRA_DIST +=3D vircaps2xmltest.c virnumamock.c virfilewrapper.c virfilewr= apper.h +EXTRA_DIST +=3D vircaps2xmltest.c virnumamock.c virfilewrapper.c \ + virfilewrapper.h virresctrltest.c endif ! WITH_LINUX =20 if WITH_NSS diff --git a/tests/virresctrldata/resctrl-cdp.schemata b/tests/virresctrlda= ta/resctrl-cdp.schemata new file mode 100644 index 000000000000..2c31c3b957d5 --- /dev/null +++ b/tests/virresctrldata/resctrl-cdp.schemata @@ -0,0 +1,2 @@ +L3CODE:0=3D00ffc;1=3D0ff00 +L3DATA:0=3D3ffff;1=3D03fff diff --git a/tests/virresctrldata/resctrl-skx-twocaches.schemata b/tests/vi= rresctrldata/resctrl-skx-twocaches.schemata new file mode 100644 index 000000000000..86b3801a04c2 --- /dev/null +++ b/tests/virresctrldata/resctrl-skx-twocaches.schemata @@ -0,0 +1 @@ +L3:0=3D001;1=3D400 diff --git a/tests/virresctrldata/resctrl-skx.schemata b/tests/virresctrlda= ta/resctrl-skx.schemata new file mode 100644 index 000000000000..5e8b0d636277 --- /dev/null +++ b/tests/virresctrldata/resctrl-skx.schemata @@ -0,0 +1 @@ +L3:0=3D70f diff --git a/tests/virresctrldata/resctrl.schemata b/tests/virresctrldata/r= esctrl.schemata new file mode 100644 index 000000000000..fa980e58c9dd --- /dev/null +++ b/tests/virresctrldata/resctrl.schemata @@ -0,0 +1 @@ +L3:0=3D000ff;1=3D000f0 diff --git a/tests/virresctrltest.c b/tests/virresctrltest.c new file mode 100644 index 000000000000..99e20d5dec99 --- /dev/null +++ b/tests/virresctrltest.c @@ -0,0 +1,102 @@ +#include +#include + +#include "testutils.h" +#include "virfilewrapper.h" +#include "virresctrlpriv.h" + + +#define VIR_FROM_THIS VIR_FROM_NONE + +struct virResctrlData { + const char *filename; + bool fail; +}; + + +static int +test_virResctrlGetUnused(const void *opaque) +{ + struct virResctrlData *data =3D (struct virResctrlData *) opaque; + char *system_dir =3D NULL; + char *resctrl_dir =3D NULL; + int ret =3D -1; + virResctrlAllocPtr alloc =3D NULL; + char *schemata_str =3D NULL; + char *schemata_file; + virCapsPtr caps =3D NULL; + + if (virAsprintf(&system_dir, "%s/vircaps2xmldata/linux-%s/system", + abs_srcdir, data->filename) < 0) + goto cleanup; + + if (virAsprintf(&resctrl_dir, "%s/vircaps2xmldata/linux-%s/resctrl", + abs_srcdir, data->filename) < 0) + goto cleanup; + + if (virAsprintf(&schemata_file, "%s/virresctrldata/%s.schemata", + abs_srcdir, data->filename) < 0) + goto cleanup; + + virFileWrapperAddPrefix("/sys/devices/system", system_dir); + virFileWrapperAddPrefix("/sys/fs/resctrl", resctrl_dir); + + caps =3D virCapabilitiesNew(VIR_ARCH_X86_64, false, false); + if (!caps || virCapabilitiesInitCaches(caps) < 0) { + fprintf(stderr, "Could not initialize capabilities"); + goto cleanup; + } + + alloc =3D virResctrlAllocGetUnused(caps->host.resctrl); + + virFileWrapperClearPrefixes(); + + if (!alloc) { + if (data->fail) + ret =3D 0; + goto cleanup; + } else if (data->fail) { + VIR_TEST_DEBUG("Error expected but there wasn't any.\n"); + ret =3D -1; + goto cleanup; + } + + schemata_str =3D virResctrlAllocFormat(alloc); + + if (virTestCompareToFile(schemata_str, schemata_file) < 0) + goto cleanup; + + ret =3D 0; + cleanup: + virObjectUnref(caps); + virObjectUnref(alloc); + VIR_FREE(system_dir); + VIR_FREE(resctrl_dir); + VIR_FREE(schemata_str); + VIR_FREE(schemata_file); + return ret; +} + + +static int +mymain(void) +{ + struct virResctrlData data =3D {0}; + int ret =3D 0; + +#define DO_TEST_UNUSED(_filename) \ + do { \ + data =3D (struct virResctrlData) { .filename =3D _filename }; \ + if (virTestRun("Free: " _filename, test_virResctrlGetUnused, &data= ) < 0) \ + ret =3D -1; \ + } while (0) + + DO_TEST_UNUSED("resctrl"); + DO_TEST_UNUSED("resctrl-cdp"); + DO_TEST_UNUSED("resctrl-skx"); + DO_TEST_UNUSED("resctrl-skx-twocaches"); + + return ret; +} + +VIR_TEST_MAIN(mymain) --=20 2.16.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Mon Apr 29 11:47: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 Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1516730741469402.023765382241; Tue, 23 Jan 2018 10:05:41 -0800 (PST) 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 68D27935AC; Tue, 23 Jan 2018 18:05:40 +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 3F28117DC6; Tue, 23 Jan 2018 18:05:40 +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 0632918033E6; Tue, 23 Jan 2018 18:05:40 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w0NI5T1p021574 for ; Tue, 23 Jan 2018 13:05:29 -0500 Received: by smtp.corp.redhat.com (Postfix) id 448F95D6A3; Tue, 23 Jan 2018 18:05:29 +0000 (UTC) Received: from caroline.localdomain (unknown [10.43.2.67]) by smtp.corp.redhat.com (Postfix) with ESMTPS id AD3455EDEB; 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 9BD65120447; Tue, 23 Jan 2018 19:05:23 +0100 (CET) From: Martin Kletzander To: libvir-list@redhat.com Date: Tue, 23 Jan 2018 19:05:17 +0100 Message-Id: <0f15fdcb2390da1fa300ebea9764690fea083143.1516730683.git.mkletzan@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com Cc: Chris Friesen , Eli Qiao Subject: [libvirt] [PATCH 08/10] qemu: Add support for 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.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 23 Jan 2018 18:05:40 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" We've been building up to this. This adds support for cputune/cachetune settings for domains in the QEMU driver. The addition into qemuProcessSetupVcpu() automatically adds support for hotplug. For hot-unp= lug we need to remove the allocation only if all the vCPUs were unplugged. But since the threads are left running, we can't really do much about it now. Signed-off-by: Martin Kletzander Reviewed-by: Pavel Hrdina --- src/qemu/qemu_process.c | 60 ++++++++++++++++++++++++++++++++++++++++++++-= ---- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 25ec464d3e1c..3a697de037e1 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2507,6 +2507,32 @@ qemuProcessSetupEmulator(virDomainObjPtr vm) } =20 =20 +static int +qemuProcessResctrlCreate(virQEMUDriverPtr driver, + virDomainObjPtr vm) +{ + int ret =3D -1; + size_t i =3D 0; + virCapsPtr caps =3D virQEMUDriverGetCapabilities(driver, false); + qemuDomainObjPrivatePtr priv =3D vm->privateData; + + if (!caps) + return -1; + + for (i =3D 0; i < vm->def->ncachetunes; i++) { + if (virResctrlAllocCreate(caps->host.resctrl, + vm->def->cachetunes[i]->alloc, + priv->machineName) < 0) + goto cleanup; + } + + ret =3D 0; + cleanup: + virObjectUnref(caps); + return ret; +} + + static int qemuProcessInitPasswords(virConnectPtr conn, virQEMUDriverPtr driver, @@ -5018,12 +5044,26 @@ qemuProcessSetupVcpu(virDomainObjPtr vm, { pid_t vcpupid =3D qemuDomainGetVcpuPid(vm, vcpuid); virDomainVcpuDefPtr vcpu =3D virDomainDefGetVcpu(vm->def, vcpuid); + size_t i =3D 0; =20 - return qemuProcessSetupPid(vm, vcpupid, VIR_CGROUP_THREAD_VCPU, - vcpuid, vcpu->cpumask, - vm->def->cputune.period, - vm->def->cputune.quota, - &vcpu->sched); + if (qemuProcessSetupPid(vm, vcpupid, VIR_CGROUP_THREAD_VCPU, + vcpuid, vcpu->cpumask, + vm->def->cputune.period, + vm->def->cputune.quota, + &vcpu->sched) < 0) + return -1; + + for (i =3D 0; i < vm->def->ncachetunes; i++) { + virDomainCachetuneDefPtr ct =3D vm->def->cachetunes[i]; + + if (virBitmapIsBitSet(ct->vcpus, vcpuid)) { + if (virResctrlAllocAddPID(ct->alloc, vcpupid) < 0) + return -1; + break; + } + } + + return 0; } =20 =20 @@ -5896,6 +5936,10 @@ qemuProcessLaunch(virConnectPtr conn, if (qemuProcessSetupEmulator(vm) < 0) goto cleanup; =20 + VIR_DEBUG("Setting up resctrlfs"); + if (qemuProcessResctrlCreate(driver, vm) < 0) + goto cleanup; + VIR_DEBUG("Setting domain security labels"); if (qemuSecuritySetAllLabel(driver, vm, @@ -6544,6 +6588,12 @@ void qemuProcessStop(virQEMUDriverPtr driver, vm->def->name); } =20 + /* 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); + qemuProcessRemoveDomainStatus(driver, vm); =20 /* Remove VNC and Spice ports from port reservation bitmap, but only if --=20 2.16.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Mon Apr 29 11:47: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 Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1516730741745300.5630400726325; Tue, 23 Jan 2018 10:05:41 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C43CBC056789; Tue, 23 Jan 2018 18:05:40 +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 9ED2F1724D; Tue, 23 Jan 2018 18:05:40 +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 6622018033E7; Tue, 23 Jan 2018 18:05:40 +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 w0NI5UJk021584 for ; Tue, 23 Jan 2018 13:05:30 -0500 Received: by smtp.corp.redhat.com (Postfix) id AE5CE18EF5; Tue, 23 Jan 2018 18:05:30 +0000 (UTC) Received: from caroline.localdomain (unknown [10.43.2.67]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7DE0E18F06; Tue, 23 Jan 2018 18:05:29 +0000 (UTC) Received: from caroline.brq.redhat.com (caroline.usersys.redhat.com [127.0.0.1]) by caroline.localdomain (Postfix) with ESMTP id A7CDA12045A; Tue, 23 Jan 2018 19:05:23 +0100 (CET) From: Martin Kletzander To: libvir-list@redhat.com Date: Tue, 23 Jan 2018 19:05:18 +0100 Message-Id: <450cd5caa180f341a971e1f22f6f3cfd96c9ee40.1516730683.git.mkletzan@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com Cc: Chris Friesen , Eli Qiao Subject: [libvirt] [PATCH 09/10] docs: Add CAT (resctrl) support into news.xml 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.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Tue, 23 Jan 2018 18:05:41 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Martin Kletzander Reviewed-by: Pavel Hrdina --- docs/news.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/news.xml b/docs/news.xml index b4d980624956..4ffa736c04c8 100644 --- a/docs/news.xml +++ b/docs/news.xml @@ -35,6 +35,15 @@
+ + + Added support for CAT (Cache allocation Technology) + + + Domain vCPU threads can now have allocated some parts of host ca= che + using the cachetune element in cputune. + +
--=20 2.16.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Mon Apr 29 11:47: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 Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1516730739719782.0669525023117; Tue, 23 Jan 2018 10:05:39 -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 BED56C0567B3; Tue, 23 Jan 2018 18:05:38 +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 941CA5D960; Tue, 23 Jan 2018 18:05:38 +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 33CCB3FC74; Tue, 23 Jan 2018 18:05:38 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w0NI5Xbp021624 for ; Tue, 23 Jan 2018 13:05:33 -0500 Received: by smtp.corp.redhat.com (Postfix) id C800A60E3E; Tue, 23 Jan 2018 18:05:33 +0000 (UTC) Received: from caroline.localdomain (unknown [10.43.2.67]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7E6E0BA7C; Tue, 23 Jan 2018 18:05:29 +0000 (UTC) Received: from caroline.brq.redhat.com (caroline.usersys.redhat.com [127.0.0.1]) by caroline.localdomain (Postfix) with ESMTP id B3A0712045F; Tue, 23 Jan 2018 19:05:23 +0100 (CET) From: Martin Kletzander To: libvir-list@redhat.com Date: Tue, 23 Jan 2018 19:05:19 +0100 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com Cc: Chris Friesen , Eli Qiao Subject: [libvirt] [PATCH 10/10] tests: Clean up and modify some vircaps2xmldata 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.32]); Tue, 23 Jan 2018 18:05:39 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Basically the `cpus` and `tasks` files are not needed, and I've witnessed o= n a real system that the schemata file may have spaces prepended to a line, so = let's adjust at least one test so that it reflects what can happen. Also `000` allocation is invalid and a full mask means it's all free. So adjust for t= hat too. Signed-off-by: Martin Kletzander Reviewed-by: Pavel Hrdina --- tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/cpus | 1 - tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/tasks | 0 tests/vircaps2xmldata/linux-resctrl-skx-twocaches/resctrl/schemata | 2 +- tests/vircaps2xmldata/linux-resctrl/resctrl/cpus | 1 - tests/vircaps2xmldata/linux-resctrl/resctrl/schemata | 2 +- tests/vircaps2xmldata/linux-resctrl/resctrl/tasks | 0 6 files changed, 2 insertions(+), 4 deletions(-) delete mode 100644 tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/cpus delete mode 100644 tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/tasks delete mode 100644 tests/vircaps2xmldata/linux-resctrl/resctrl/cpus delete mode 100644 tests/vircaps2xmldata/linux-resctrl/resctrl/tasks diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/cpus b/tests/v= ircaps2xmldata/linux-resctrl-cdp/resctrl/cpus deleted file mode 100644 index b3a79aa9539f..000000000000 --- a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/cpus +++ /dev/null @@ -1 +0,0 @@ -ffffff,ffffffff,ffffffff diff --git a/tests/vircaps2xmldata/linux-resctrl-cdp/resctrl/tasks b/tests/= vircaps2xmldata/linux-resctrl-cdp/resctrl/tasks deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/tests/vircaps2xmldata/linux-resctrl-skx-twocaches/resctrl/sche= mata b/tests/vircaps2xmldata/linux-resctrl-skx-twocaches/resctrl/schemata index 691fbaf887d1..23af473be4ed 100644 --- a/tests/vircaps2xmldata/linux-resctrl-skx-twocaches/resctrl/schemata +++ b/tests/vircaps2xmldata/linux-resctrl-skx-twocaches/resctrl/schemata @@ -1 +1 @@ -L3:0=3D0f0;1=3D000 +L3:0=3D0f0;1=3D7ff diff --git a/tests/vircaps2xmldata/linux-resctrl/resctrl/cpus b/tests/virca= ps2xmldata/linux-resctrl/resctrl/cpus deleted file mode 100644 index 98d03acc98ed..000000000000 --- a/tests/vircaps2xmldata/linux-resctrl/resctrl/cpus +++ /dev/null @@ -1 +0,0 @@ -fff diff --git a/tests/vircaps2xmldata/linux-resctrl/resctrl/schemata b/tests/v= ircaps2xmldata/linux-resctrl/resctrl/schemata index c1a765f1e0a7..78d2d8a9b826 100644 --- a/tests/vircaps2xmldata/linux-resctrl/resctrl/schemata +++ b/tests/vircaps2xmldata/linux-resctrl/resctrl/schemata @@ -1 +1 @@ -L3:0=3D1ff00;1=3D1ff0f + L3:0=3D1ff00;1=3D1ff0f diff --git a/tests/vircaps2xmldata/linux-resctrl/resctrl/tasks b/tests/virc= aps2xmldata/linux-resctrl/resctrl/tasks deleted file mode 100644 index e69de29bb2d1..000000000000 --=20 2.16.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list