From 19f434a391d8675609adc02ada6398ef1db32830 Mon Sep 17 00:00:00 2001 Message-Id: <19f434a391d8675609adc02ada6398ef1db32830@dist-git> From: Bing Niu Date: Mon, 15 Apr 2019 17:32:50 +0200 Subject: [PATCH] util: Add MBA schemata parse and format methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce virResctrlAllocMemoryBandwidthFormat and virResctrlAllocParseMemoryBandwidthLine which will format and parse an entry in the schemata file for MBA. Signed-off-by: Bing Niu Reviewed-by: John Ferlan (cherry picked from commit 34a2ba2c466fe62611c9284d7de923879821b11a) Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1468650 Signed-off-by: Pavel Hrdina Message-Id: <48c9580bb6f7ce738b567c72a54d3ecfe930a2a9.1555342313.git.phrdina@redhat.com> Reviewed-by: Ján Tomko --- src/util/virresctrl.c | 140 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 8a25798f7d..3148184d28 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -986,6 +986,138 @@ virResctrlAllocGetID(virResctrlAllocPtr alloc) } +/* Format the Memory Bandwidth Allocation line that will be found in + * the schemata files. The line should be start with "MB:" and be + * followed by "id=value" pairs separated by a semi-colon such as: + * + * MB:0=100;1=100 + * + * which indicates node id 0 has 100 percent bandwith and node id 1 + * has 100 percent bandwidth. A trailing semi-colon is not formatted. + */ +static int +virResctrlAllocMemoryBandwidthFormat(virResctrlAllocPtr alloc, + virBufferPtr buf) +{ + size_t i; + + if (!alloc->mem_bw) + return 0; + + virBufferAddLit(buf, "MB:"); + + for (i = 0; i < alloc->mem_bw->nbandwidths; i++) { + if (alloc->mem_bw->bandwidths[i]) { + virBufferAsprintf(buf, "%zd=%u;", i, + *(alloc->mem_bw->bandwidths[i])); + } + } + + virBufferTrim(buf, ";", 1); + virBufferAddChar(buf, '\n'); + return virBufferCheckError(buf); +} + + +static int +virResctrlAllocParseProcessMemoryBandwidth(virResctrlInfoPtr resctrl, + virResctrlAllocPtr alloc, + char *mem_bw) +{ + unsigned int bandwidth; + unsigned int id; + char *tmp = NULL; + + tmp = strchr(mem_bw, '='); + if (!tmp) + return 0; + *tmp = '\0'; + tmp++; + + if (virStrToLong_uip(mem_bw, NULL, 10, &id) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid node id %u "), id); + return -1; + } + if (virStrToLong_uip(tmp, NULL, 10, &bandwidth) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid bandwidth %u"), bandwidth); + return -1; + } + if (bandwidth < resctrl->membw_info->min_bandwidth || + id > resctrl->membw_info->max_id) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Missing or inconsistent resctrl info for " + "memory bandwidth node '%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) < 0) { + return -1; + } + if (!alloc->mem_bw->bandwidths[id]) { + if (VIR_ALLOC(alloc->mem_bw->bandwidths[id]) < 0) + return -1; + } + + *(alloc->mem_bw->bandwidths[id]) = bandwidth; + return 0; +} + + +/* Parse a schemata formatted MB: entry. Format details are described in + * virResctrlAllocMemoryBandwidthFormat. + */ +static int +virResctrlAllocParseMemoryBandwidthLine(virResctrlInfoPtr resctrl, + virResctrlAllocPtr alloc, + char *line) +{ + char **mbs = NULL; + char *tmp = NULL; + size_t nmbs = 0; + size_t i; + int ret = -1; + + /* For no reason there can be spaces */ + virSkipSpaces((const char **) &line); + + if (STRNEQLEN(line, "MB", 2)) + return 0; + + if (!resctrl || !resctrl->membw_info || + !resctrl->membw_info->min_bandwidth || + !resctrl->membw_info->bandwidth_granularity) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing or inconsistent resctrl info for " + "memory bandwidth allocation")); + return -1; + } + + if (!alloc->mem_bw) { + if (VIR_ALLOC(alloc->mem_bw) < 0) + return -1; + } + + tmp = strchr(line, ':'); + if (!tmp) + return 0; + tmp++; + + mbs = virStringSplitCount(tmp, ";", 0, &nmbs); + for (i = 0; i < nmbs; i++) { + if (virResctrlAllocParseProcessMemoryBandwidth(resctrl, alloc, mbs[i]) < 0) + goto cleanup; + } + + ret = 0; + cleanup: + virStringListFree(mbs); + return ret; +} + + static int virResctrlAllocFormatCache(virResctrlAllocPtr alloc, virBufferPtr buf) @@ -1045,6 +1177,11 @@ virResctrlAllocFormat(virResctrlAllocPtr alloc) return NULL; } + if (virResctrlAllocMemoryBandwidthFormat(alloc, &buf) < 0) { + virBufferFreeAndReset(&buf); + return NULL; + } + return virBufferContentAndReset(&buf); } @@ -1173,6 +1310,9 @@ virResctrlAllocParse(virResctrlInfoPtr resctrl, for (i = 0; i < nlines; i++) { if (virResctrlAllocParseCacheLine(resctrl, alloc, lines[i]) < 0) goto cleanup; + if (virResctrlAllocParseMemoryBandwidthLine(resctrl, alloc, lines[i]) < 0) + goto cleanup; + } ret = 0; -- 2.21.0