From nobody Thu May 15 03:45:35 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 151739175496761.11950464806716; Wed, 31 Jan 2018 01:42:34 -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 8A46EC05B00E; Wed, 31 Jan 2018 09:42: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 525245D6B7; Wed, 31 Jan 2018 09:42: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 150A418033E2; Wed, 31 Jan 2018 09:42: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 w0V9g71S025615 for ; Wed, 31 Jan 2018 04:42:07 -0500 Received: by smtp.corp.redhat.com (Postfix) id 49FE15EDEE; Wed, 31 Jan 2018 09:42:07 +0000 (UTC) Received: from caroline.localdomain (unknown [10.43.2.67]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7138F61F41 for ; Wed, 31 Jan 2018 09:41:59 +0000 (UTC) Received: from caroline.brq.redhat.com (caroline.usersys.redhat.com [127.0.0.1]) by caroline.localdomain (Postfix) with ESMTP id B8233120497 for ; Wed, 31 Jan 2018 10:41:50 +0100 (CET) From: Martin Kletzander To: libvir-list@redhat.com Date: Wed, 31 Jan 2018 10:41:45 +0100 Message-Id: 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 Subject: [libvirt] [PATCH 7/8] util: Reorder functions in virresctrl to minimize stubs 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.31]); Wed, 31 Jan 2018 09:42:34 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" If we reorder the functions properly, we only need to have few stub functio= ns for non-Linux platforms and it is also nicer to look at and read if they ar= e in one place with only one preprocessor condition. The order after this patch= is: - Class allocation and Static functions (used by everything, static depende= ncies) - Linux-only functions - Non-Linux stubs - Exported functions (as they rely on all previous functions) Signed-off-by: Martin Kletzander --- src/libvirt_linux.syms | 3 + src/libvirt_private.syms | 1 - src/util/virresctrl.c | 939 +++++++++++++++++++++++--------------------= ---- 3 files changed, 459 insertions(+), 484 deletions(-) diff --git a/src/libvirt_linux.syms b/src/libvirt_linux.syms index 5fa2c790efc1..27425e4bbebb 100644 --- a/src/libvirt_linux.syms +++ b/src/libvirt_linux.syms @@ -9,6 +9,9 @@ virHostCPUGetSiblingsList; virHostCPUGetSocket; virHostCPUGetStatsLinux; =20 +# util/virresctrl.h +virResctrlAllocGetUnused; + # Let emacs know we want case-insensitive sorting # Local Variables: # sort-fold-case: t diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 9339c2c3259d..21ec8d8c8c34 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2564,7 +2564,6 @@ virResctrlAllocDeterminePath; virResctrlAllocForeachSize; virResctrlAllocFormat; virResctrlAllocGetID; -virResctrlAllocGetUnused; virResctrlAllocNew; virResctrlAllocRemove; virResctrlAllocSetID; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index fefca32a6710..cab7570f7b8e 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -294,346 +294,6 @@ virResctrlAllocNew(void) } =20 =20 -/* Common functions */ -#ifdef __linux__ -static int -virResctrlLockInternal(int op) -{ - int fd =3D open(SYSFS_RESCTRL_PATH, O_DIRECTORY | O_CLOEXEC); - - if (fd < 0) { - virReportSystemError(errno, "%s", _("Cannot open resctrl")); - return -1; - } - - if (flock(fd, op) < 0) { - virReportSystemError(errno, "%s", _("Cannot lock resctrl")); - VIR_FORCE_CLOSE(fd); - return -1; - } - - return fd; -} - - -static inline int -virResctrlLockWrite(void) -{ - return virResctrlLockInternal(LOCK_EX); -} - -#else - -static inline int -virResctrlLockWrite(void) -{ - virReportSystemError(ENOSYS, "%s", - _("resctrl not supported on this platform")); - return -1; -} - -#endif - - - - -static int -virResctrlUnlock(int fd) -{ - if (fd =3D=3D -1) - return 0; - -#ifdef __linux__ - /* 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 resctrl")); - - /* Trying to save the already broken */ - if (flock(fd, LOCK_UN) < 0) - virReportSystemError(errno, "%s", _("Cannot unlock resctrl")); - return -1; - } -#endif /* ! __linux__ */ - - return 0; -} - - -/* Info-related functions */ -static 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; -} - - -#ifdef __linux__ - -int -virResctrlGetInfo(virResctrlInfoPtr resctrl) -{ - DIR *dirp =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= ) { - VIR_DEBUG("Parsing info type '%s'", ent->d_name); - if (ent->d_name[0] !=3D 'L') - continue; - - if (virStrToLong_uip(ent->d_name + 1, &endptr, 10, &level) < 0) { - VIR_DEBUG("Cannot parse resctrl cache info level '%s'", ent->d= _name + 1); - continue; - } - - type =3D virResctrlTypeFromString(endptr); - if (type < 0) { - VIR_DEBUG("Cannot parse resctrl cache info type '%s'", endptr); - continue; - } - - 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) { - /* The file doesn't exist, so it's unusable for us, - * but we can scan further */ - VIR_WARN("The path '" SYSFS_RESCTRL_PATH "/info/%s/num_closids= ' " - "does not exist", - ent->d_name); - } else if (rv < 0) { - /* Other failures are fatal, so just quit */ - goto cleanup; - } - - rv =3D virFileReadValueString(&i_type->cbm_mask, - SYSFS_RESCTRL_PATH - "/info/%s/cbm_mask", - ent->d_name); - if (rv =3D=3D -2) { - /* If the previous file exists, so should this one. Hence -2 = is - * fatal in this case as well (errors out in next condition) -= the - * kernel interface might've changed too much or something els= e is - * wrong. */ - 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]) { - 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]; - - if (i_level->types[type]) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Duplicate cache type in resctrl 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); - if (i_type) - VIR_FREE(i_type->cbm_mask); - VIR_FREE(i_type); - return ret; -} - -#else /* ! __linux__ */ - -int -virResctrlGetInfo(virResctrlInfoPtr resctrl ATTRIBUTE_UNUSED) -{ - virReportSystemError(ENOSYS, "%s", - _("Cache tune not supported on this platform")); - return -1; -} - -#endif /* ! __linux__ */ - - -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 does 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; -} - - -/* 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, @@ -667,38 +327,6 @@ virResctrlAllocGetType(virResctrlAllocPtr resctrl, } =20 =20 -#ifdef __linux__ - -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); -} - -#endif - - static int virResctrlAllocUpdateSize(virResctrlAllocPtr resctrl, unsigned int level, @@ -725,6 +353,31 @@ virResctrlAllocUpdateSize(virResctrlAllocPtr resctrl, } =20 =20 +static 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; +} + + /* * 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, @@ -775,150 +428,223 @@ virResctrlAllocCheckCollision(virResctrlAllocPtr al= loc, } else { a_type =3D a_level->types[type]; =20 - if (a_type && a_type->nsizes > cache && a_type->sizes[cache]) - return true; + if (a_type && a_type->nsizes > cache && a_type->sizes[cache]) + return true; + } + + return false; +} + + +#ifdef __linux__ + +static int +virResctrlLockInternal(int op) +{ + int fd =3D open(SYSFS_RESCTRL_PATH, O_DIRECTORY | O_CLOEXEC); + + if (fd < 0) { + virReportSystemError(errno, "%s", _("Cannot open resctrl")); + return -1; + } + + if (flock(fd, op) < 0) { + virReportSystemError(errno, "%s", _("Cannot lock resctrl")); + VIR_FORCE_CLOSE(fd); + return -1; } =20 - return false; + return fd; } =20 =20 -int -virResctrlAllocSetSize(virResctrlAllocPtr resctrl, - unsigned int level, - virCacheType type, - unsigned int cache, - unsigned long long size) +static inline int +virResctrlLockWrite(void) { - 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 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 resctrl")); + + /* Trying to save the already broken */ + if (flock(fd, LOCK_UN) < 0) + virReportSystemError(errno, "%s", _("Cannot unlock resctrl")); return -1; } =20 - return virResctrlAllocUpdateSize(resctrl, level, type, cache, size); + return 0; } =20 =20 int -virResctrlAllocForeachSize(virResctrlAllocPtr resctrl, - virResctrlAllocForeachSizeCallback cb, - void *opaque) +virResctrlGetInfo(virResctrlInfoPtr resctrl) { - int ret =3D 0; + DIR *dirp =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; - unsigned int type =3D 0; - unsigned int cache =3D 0; - - if (!resctrl) - return 0; + virResctrlInfoPerLevelPtr i_level =3D NULL; + virResctrlInfoPerTypePtr i_type =3D NULL; =20 - for (level =3D 0; level < resctrl->nlevels; level++) { - virResctrlAllocPerLevelPtr a_level =3D resctrl->levels[level]; + rv =3D virDirOpenIfExists(&dirp, SYSFS_RESCTRL_PATH "/info"); + if (rv <=3D 0) { + ret =3D rv; + goto cleanup; + } =20 - if (!a_level) + while ((rv =3D virDirRead(dirp, &ent, SYSFS_RESCTRL_PATH "/info")) > 0= ) { + VIR_DEBUG("Parsing info type '%s'", ent->d_name); + if (ent->d_name[0] !=3D 'L') continue; =20 - for (type =3D 0; type < VIR_CACHE_TYPE_LAST; type++) { - virResctrlAllocPerTypePtr a_type =3D a_level->types[type]; + if (virStrToLong_uip(ent->d_name + 1, &endptr, 10, &level) < 0) { + VIR_DEBUG("Cannot parse resctrl cache info level '%s'", ent->d= _name + 1); + continue; + } =20 - if (!a_type) - continue; + type =3D virResctrlTypeFromString(endptr); + if (type < 0) { + VIR_DEBUG("Cannot parse resctrl cache info type '%s'", endptr); + continue; + } =20 - for (cache =3D 0; cache < a_type->nsizes; cache++) { - unsigned long long *size =3D a_type->sizes[cache]; + if (VIR_ALLOC(i_type) < 0) + goto cleanup; =20 - if (!size) - continue; + i_type->control.scope =3D type; =20 - ret =3D cb(level, type, cache, *size, opaque); - if (ret < 0) - return ret; - } + rv =3D virFileReadValueUint(&i_type->control.max_allocation, + SYSFS_RESCTRL_PATH "/info/%s/num_closids= ", + ent->d_name); + if (rv =3D=3D -2) { + /* The file doesn't exist, so it's unusable for us, + * but we can scan further */ + VIR_WARN("The path '" SYSFS_RESCTRL_PATH "/info/%s/num_closids= ' " + "does not exist", + ent->d_name); + } else if (rv < 0) { + /* Other failures are fatal, so just quit */ + goto cleanup; } - } =20 - return 0; -} + rv =3D virFileReadValueString(&i_type->cbm_mask, + SYSFS_RESCTRL_PATH + "/info/%s/cbm_mask", + ent->d_name); + if (rv =3D=3D -2) { + /* If the previous file exists, so should this one. Hence -2 = is + * fatal in this case as well (errors out in next condition) -= the + * kernel interface might've changed too much or something els= e is + * wrong. */ + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot get cbm_mask from resctrl cache info"= )); + } + if (rv < 0) + goto cleanup; =20 + virStringTrimOptionalNewline(i_type->cbm_mask); =20 -int -virResctrlAllocSetID(virResctrlAllocPtr alloc, - const char *id) -{ - if (!id) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Resctrl allocation 'id' cannot be NULL")); - return -1; - } + 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; =20 - return VIR_STRDUP(alloc->id, id); -} + if (resctrl->nlevels <=3D level && + VIR_EXPAND_N(resctrl->levels, resctrl->nlevels, + level - resctrl->nlevels + 1) < 0) + goto cleanup; =20 + if (!resctrl->levels[level]) { + virResctrlInfoPerTypePtr *types =3D NULL; =20 -const char * -virResctrlAllocGetID(virResctrlAllocPtr alloc) -{ - return alloc->id; -} + if (VIR_ALLOC_N(types, VIR_CACHE_TYPE_LAST) < 0) + goto cleanup; =20 + if (VIR_ALLOC(resctrl->levels[level]) < 0) { + VIR_FREE(types); + goto cleanup; + } + resctrl->levels[level]->types =3D types; + } =20 -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; + i_level =3D resctrl->levels[level]; =20 - if (!resctrl) - return NULL; + if (i_level->types[type]) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Duplicate cache type in resctrl for level %u= "), + level); + goto cleanup; + } =20 - for (level =3D 0; level < resctrl->nlevels; level++) { - virResctrlAllocPerLevelPtr a_level =3D resctrl->levels[level]; + 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; + } =20 - if (!a_level) - continue; + i_type->bits +=3D count_one_bits(virHexToBin(*tmp_str)); + } =20 - for (type =3D 0; type < VIR_CACHE_TYPE_LAST; type++) { - virResctrlAllocPerTypePtr a_type =3D a_level->types[type]; + VIR_STEAL_PTR(i_level->types[type], i_type); + } =20 - if (!a_type) - continue; + ret =3D 0; + cleanup: + VIR_DIR_CLOSE(dirp); + if (i_type) + VIR_FREE(i_type->cbm_mask); + VIR_FREE(i_type); + return ret; +} =20 - virBufferAsprintf(&buf, "L%u%s:", level, virResctrlTypeToStrin= g(type)); =20 - for (cache =3D 0; cache < a_type->nmasks; cache++) { - virBitmapPtr mask =3D a_type->masks[cache]; - char *mask_str =3D NULL; +static int +virResctrlAllocUpdateMask(virResctrlAllocPtr resctrl, + unsigned int level, + virCacheType type, + unsigned int cache, + virBitmapPtr mask) +{ + virResctrlAllocPerTypePtr a_type =3D virResctrlAllocGetType(resctrl, l= evel, type); =20 - if (!mask) - continue; + if (!a_type) + return -1; =20 - mask_str =3D virBitmapToString(mask, false, true); - if (!mask_str) { - virBufferFreeAndReset(&buf); - return NULL; - } + if (a_type->nmasks <=3D cache && + VIR_EXPAND_N(a_type->masks, a_type->nmasks, + cache - a_type->nmasks + 1) < 0) + return -1; =20 - virBufferAsprintf(&buf, "%u=3D%s;", cache, mask_str); - VIR_FREE(mask_str); - } + if (!a_type->masks[cache]) { + a_type->masks[cache] =3D virBitmapNew(virBitmapSize(mask)); =20 - virBufferTrim(&buf, ";", 1); - virBufferAddChar(&buf, '\n'); - } + if (!a_type->masks[cache]) + return -1; } =20 - virBufferCheckError(&buf); - return virBufferContentAndReset(&buf); + return virBitmapCopy(a_type->masks[cache], mask); } =20 =20 -#ifdef __linux__ - static int virResctrlAllocParseProcessCache(virResctrlInfoPtr resctrl, virResctrlAllocPtr alloc, @@ -1171,6 +897,7 @@ virResctrlAllocNewFromInfo(virResctrlInfoPtr info) goto cleanup; } =20 + /* * This function creates an allocation that represents all unused parts of= all * caches in the system. It uses virResctrlInfo for creating a new full @@ -1238,23 +965,11 @@ virResctrlAllocGetUnused(virResctrlInfoPtr resctrl) return ret; =20 error: - virObjectUnref(ret); - ret =3D NULL; - goto cleanup; -} - -#else /* ! __linux__ */ - -virResctrlAllocPtr -virResctrlAllocGetUnused(virResctrlInfoPtr resctrl ATTRIBUTE_UNUSED) -{ - virReportSystemError(ENOSYS, "%s", - _("Cache tune not supported on this platform")); - return NULL; + virObjectUnref(ret); + ret =3D NULL; + goto cleanup; } =20 -#endif /* ! __linux__ */ - =20 /* * Given the information about requested allocation type `a_type`, the host @@ -1591,6 +1306,264 @@ virResctrlAllocCreate(virResctrlInfoPtr resctrl, return ret; } =20 +#else /* ! __linux__ */ + +int +virResctrlGetInfo(virResctrlInfoPtr resctrl ATTRIBUTE_UNUSED) +{ + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Resource control is not supported on this host")); + return -1; +} + +int +virResctrlAllocCreate(virResctrlInfoPtr resctrl ATTRIBUTE_UNUSED, + virResctrlAllocPtr alloc ATTRIBUTE_UNUSED, + const char *machinename ATTRIBUTE_UNUSED) +{ + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Resource control is not supported on this host")); + return -1; +} + +#endif /* ! __linux__ */ + + +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 does 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; +} + + +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; +} + + +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); +} + =20 int virResctrlAllocAddPID(virResctrlAllocPtr alloc, --=20 2.16.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list