Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
src/conf/capabilities.c | 5 ++-
src/util/virresctrl.c | 77 ++++++++++++++++++++++++-----------------
src/util/virresctrl.h | 3 ++
3 files changed, 53 insertions(+), 32 deletions(-)
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index 1d3b7050b2e3..3d0602e1b6fe 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -2128,7 +2128,9 @@ virCapabilitiesInitResctrlMemory(virCaps *caps)
node = g_new0(virCapsHostMemBWNode, 1);
if (virResctrlInfoGetMemoryBandwidth(caps->host.resctrl,
- bank->level, &node->control) >
0) {
+ bank->level,
+ bank->id,
+ &node->control) > 0) {
node->id = bank->id;
node->cpus = virBitmapNewCopy(bank->cpus);
@@ -2269,6 +2271,7 @@ virCapabilitiesInitCaches(virCaps *caps)
if (i == caps->host.cache.nbanks) {
/* If it is a new cache, then update its resctrl information. */
if (virResctrlInfoGetCache(caps->host.resctrl,
+ bank->id,
bank->level,
bank->size,
&bank->ncontrols,
diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
index f3ec4d67059f..3acc1447ad56 100644
--- a/src/util/virresctrl.c
+++ b/src/util/virresctrl.c
@@ -121,6 +121,7 @@ struct _virResctrlInfoPerType {
unsigned int bits;
unsigned int max_cache_id;
+ virBitmap *cache_ids;
/* In order to be self-sufficient we need size information per cache.
* Funnily enough, one of the outcomes of the resctrl design is that it
* does not account for different sizes per cache on the same level. So
@@ -146,11 +147,8 @@ struct _virResctrlInfoMemBW {
unsigned int max_allocation;
/* level number of last level cache */
unsigned int last_level_cache;
- /* max id of last level cache, this is used to track
- * how many last level cache available in host system,
- * the number of memory bandwidth allocation controller
- * is identical with last level cache. */
- unsigned int max_id;
+
+ virBitmap *cache_ids;
};
struct _virResctrlInfoMongrp {
@@ -192,6 +190,7 @@ virResctrlInfoMemBWFree(virResctrlInfoMemBW *ptr)
if (!ptr)
return;
+ virBitmapFree(ptr->cache_ids);
g_free(ptr);
}
@@ -203,6 +202,7 @@ virResctrlInfoPerTypeFree(virResctrlInfoPerType *ptr)
if (!ptr)
return;
+ virBitmapFree(ptr->cache_ids);
g_free(ptr);
}
@@ -848,6 +848,7 @@ virResctrlInfoIsEmpty(virResctrlInfo *resctrl)
int
virResctrlInfoGetMemoryBandwidth(virResctrlInfo *resctrl,
unsigned int level,
+ unsigned int id,
virResctrlInfoMemBWPerNode *control)
{
virResctrlInfoMemBW *membw_info = resctrl->membw_info;
@@ -858,6 +859,13 @@ virResctrlInfoGetMemoryBandwidth(virResctrlInfo *resctrl,
if (membw_info->last_level_cache != level)
return 0;
+ /* This "should not happen", but resctrl code is constantly full of
+ * surprises. Warning might make us aware in the future. */
+ if (!virBitmapIsBitSet(membw_info->cache_ids, id)) {
+ VIR_WARN("Memory bandwidth for cache id %u is not recorded in list of cache
IDs",
+ id);
+ }
+
control->granularity = membw_info->bandwidth_granularity;
control->min = membw_info->min_bandwidth;
control->max_allocation = membw_info->max_allocation;
@@ -867,6 +875,7 @@ virResctrlInfoGetMemoryBandwidth(virResctrlInfo *resctrl,
int
virResctrlInfoGetCache(virResctrlInfo *resctrl,
+ unsigned int id,
unsigned int level,
unsigned long long size,
size_t *ncontrols,
@@ -885,12 +894,15 @@ virResctrlInfoGetCache(virResctrlInfo *resctrl,
if (resctrl->membw_info) {
virResctrlInfoMemBW *membw_info = resctrl->membw_info;
+ if (!membw_info->cache_ids)
+ membw_info->cache_ids = virBitmapNew(0);
+
if (level > membw_info->last_level_cache) {
membw_info->last_level_cache = level;
- membw_info->max_id = 0;
- } else if (membw_info->last_level_cache == level) {
- membw_info->max_id++;
+ virBitmapShrink(membw_info->cache_ids, 0);
}
+
+ virBitmapSetBitExpand(membw_info->cache_ids, id);
}
if (level >= resctrl->nlevels)
@@ -905,6 +917,11 @@ virResctrlInfoGetCache(virResctrlInfo *resctrl,
if (!i_type)
continue;
+ if (!i_type->cache_ids)
+ i_type->cache_ids = virBitmapNew(id);
+
+ virBitmapSetBitExpand(i_type->cache_ids, id);
+
/* Let's take the opportunity to update our internal information about
* the cache size */
if (!i_type->size) {
@@ -919,7 +936,6 @@ virResctrlInfoGetCache(virResctrlInfo *resctrl,
level, i_type->size, size);
goto error;
}
- i_type->max_cache_id++;
}
VIR_EXPAND_N(*controls, *ncontrols, 1);
@@ -1418,8 +1434,7 @@ virResctrlAllocMemoryBandwidthFormat(virResctrlAlloc *alloc,
static int
-virResctrlAllocParseProcessMemoryBandwidth(virResctrlInfo *resctrl,
- virResctrlAlloc *alloc,
+virResctrlAllocParseProcessMemoryBandwidth(virResctrlAlloc *alloc,
char *mem_bw)
{
unsigned int bandwidth;
@@ -1442,12 +1457,6 @@ virResctrlAllocParseProcessMemoryBandwidth(virResctrlInfo
*resctrl,
_("Invalid bandwidth %1$u"), bandwidth);
return -1;
}
- if (id > resctrl->membw_info->max_id) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Missing or inconsistent resctrl info for memory bandwidth
node '%1$u'"),
- id);
- return -1;
- }
if (alloc->mem_bw->nbandwidths <= id) {
VIR_EXPAND_N(alloc->mem_bw->bandwidths, alloc->mem_bw->nbandwidths,
id - alloc->mem_bw->nbandwidths + 1);
@@ -1495,7 +1504,7 @@ virResctrlAllocParseMemoryBandwidthLine(virResctrlInfo *resctrl,
mbs = g_strsplit(tmp, ";", 0);
for (next = mbs; *next; next++) {
- if (virResctrlAllocParseProcessMemoryBandwidth(resctrl, alloc, *next) < 0)
+ if (virResctrlAllocParseProcessMemoryBandwidth(alloc, *next) < 0)
return -1;
}
@@ -1597,7 +1606,8 @@ virResctrlAllocParseProcessCache(virResctrlInfo *resctrl,
if (!resctrl ||
level >= resctrl->nlevels ||
!resctrl->levels[level] ||
- !resctrl->levels[level]->types[type]) {
+ !resctrl->levels[level]->types[type] ||
+ !virBitmapIsBitSet(resctrl->levels[level]->types[type]->cache_ids,
cache_id)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Missing or inconsistent resctrl info for level
'%1$u' type '%2$s'"),
level, virCacheTypeToString(type));
@@ -1790,7 +1800,7 @@ virResctrlAllocNewFromInfo(virResctrlInfo *info)
for (j = 0; j < VIR_CACHE_TYPE_LAST; j++) {
virResctrlInfoPerType *i_type = i_level->types[j];
g_autoptr(virBitmap) mask = NULL;
- size_t k = 0;
+ ssize_t bit = -1;
if (!i_type)
continue;
@@ -1798,8 +1808,8 @@ virResctrlAllocNewFromInfo(virResctrlInfo *info)
mask = virBitmapNew(i_type->bits);
virBitmapSetAll(mask);
- for (k = 0; k <= i_type->max_cache_id; k++) {
- if (virResctrlAllocUpdateMask(ret, i, j, k, mask) < 0)
+ while ((bit = virBitmapNextSetBit(i_type->cache_ids, bit)) >= 0) {
+ if (virResctrlAllocUpdateMask(ret, i, j, bit, mask) < 0)
return NULL;
}
}
@@ -1830,10 +1840,21 @@ virResctrlAllocCopyMemBW(virResctrlAlloc *dst,
src_bw->nbandwidths - dst_bw->nbandwidths);
for (i = 0; i < src_bw->nbandwidths; i++) {
- if (dst_bw->bandwidths[i])
+ if (!src_bw->bandwidths[i]) {
+ if (!dst_bw->bandwidths[i])
+ continue;
+
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("bandwidth controller id %1$zd does not exist"),
+ i);
+ return -1;
+ }
+
+ if (!dst_bw->bandwidths[i]) {
+ dst_bw->bandwidths[i] = g_new0(unsigned int, 1);
+ *dst_bw->bandwidths[i] = *src_bw->bandwidths[i];
continue;
- dst_bw->bandwidths[i] = g_new0(unsigned int, 1);
- *dst_bw->bandwidths[i] = *src_bw->bandwidths[i];
+ }
}
return 0;
@@ -2065,12 +2086,6 @@ virResctrlAllocMemoryBandwidth(virResctrlInfo *resctrl,
mem_bw_info->min_bandwidth);
return -1;
}
- if (i > mem_bw_info->max_id) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("bandwidth controller id %1$zd does not exist, max
controller id %2$u"),
- i, mem_bw_info->max_id);
- return -1;
- }
}
return 0;
}
diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h
index 0e4b535f9e52..c70b112864eb 100644
--- a/src/util/virresctrl.h
+++ b/src/util/virresctrl.h
@@ -47,6 +47,7 @@ VIR_ENUM_DECL(virResctrlMonitorPrefix);
typedef struct _virResctrlInfoPerCache virResctrlInfoPerCache;
struct _virResctrlInfoPerCache {
+ unsigned int id;
/* Smallest possible increase of the allocation size in bytes */
unsigned long long granularity;
/* Minimal allocatable size in bytes (if different from granularity) */
@@ -96,6 +97,7 @@ virResctrlInfoNew(void);
int
virResctrlInfoGetCache(virResctrlInfo *resctrl,
+ unsigned int id,
unsigned int level,
unsigned long long size,
size_t *ncontrols,
@@ -104,6 +106,7 @@ virResctrlInfoGetCache(virResctrlInfo *resctrl,
int
virResctrlInfoGetMemoryBandwidth(virResctrlInfo *resctrl,
unsigned int level,
+ unsigned int id,
virResctrlInfoMemBWPerNode *control);
/* Alloc-related things */
typedef struct _virResctrlAlloc virResctrlAlloc;
--
2.46.0