From 94472525d9e6a778b496dc1dc11af6986764cd28 Mon Sep 17 00:00:00 2001 From: lutong Date: Mon, 25 Aug 2025 10:08:37 +0800 Subject: [PATCH] libvirt update to version 9.10.0-18 --- conf-add-support-for-MB-min_bandwidth.patch | 99 ++++ ...dd-support-for-cachetune-L3-priority.patch | 125 +++++ ...r-memorytune-XML-processing-for-MB-h.patch | 195 +++++++ ...r-memorytune-XML-processing-for-MB-p.patch | 109 ++++ libvirt.spec | 19 +- ...-L3-priority-parse-and-format-method.patch | 365 ++++++++++++ ...-parsing-process-for-the-new-paramet.patch | 184 ++++++ ...ine-memory-bandwidth-types-add-parse.patch | 526 ++++++++++++++++++ 8 files changed, 1621 insertions(+), 1 deletion(-) create mode 100644 conf-add-support-for-MB-min_bandwidth.patch create mode 100644 conf-add-support-for-cachetune-L3-priority.patch create mode 100644 conf-add-support-for-memorytune-XML-processing-for-MB-h.patch create mode 100644 conf-add-support-for-memorytune-XML-processing-for-MB-p.patch create mode 100644 util-resctrl-add-L3-priority-parse-and-format-method.patch create mode 100644 util-resctrl-add-parsing-process-for-the-new-paramet.patch create mode 100644 util-resctrl-define-memory-bandwidth-types-add-parse.patch diff --git a/conf-add-support-for-MB-min_bandwidth.patch b/conf-add-support-for-MB-min_bandwidth.patch new file mode 100644 index 0000000..86c1340 --- /dev/null +++ b/conf-add-support-for-MB-min_bandwidth.patch @@ -0,0 +1,99 @@ +From 2b6d170cc9b511657cd0aefc8515bdc4b7467a94 Mon Sep 17 00:00:00 2001 +From: hy <941973499@qq.com> +Date: Mon, 18 Aug 2025 11:02:40 +0800 +Subject: [PATCH 1/6] conf: add support for memorytune XML processing for MB + min_bandwidth + +--- + src/conf/domain_conf.c | 12 ++++++++++-- + src/conf/schemas/domaincommon.rng | 5 +++++ + src/util/virresctrl.c | 8 +++++++- + 3 files changed, 22 insertions(+), 3 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 28b2157424..04f2642109 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -18239,6 +18239,7 @@ virDomainMemorytuneDefParseMemory(xmlXPathContextPtr ctxt, + unsigned int bandwidth; + unsigned int hard_limit = UINT_MAX; + unsigned int priority = UINT_MAX; ++ unsigned int min_bandwidth = UINT_MAX; + + ctxt->node = node; + +@@ -18252,20 +18253,27 @@ virDomainMemorytuneDefParseMemory(xmlXPathContextPtr ctxt, + if (virResctrlAllocSetMemoryBandwidth(alloc, VIR_MEMORY_TYPE_BANDWIDTH, id, bandwidth) < 0) + return -1; + +- if (virXMLPropUIntDefault(node, "hardlimit", 10, 0, &hard_limit, UINT_MAX) < 0) ++ if (virXMLPropUIntDefault(node, "hardlimit", 10, VIR_XML_PROP_NONE, &hard_limit, UINT_MAX) < 0) + return -1; + + if (hard_limit != UINT_MAX && + virResctrlAllocSetMemoryBandwidth(alloc, VIR_MEMORY_TYPE_HARDLIMIT, id, hard_limit) < 0) + return -1; + +- if (virXMLPropUIntDefault(node, "priority", 10, 0, &priority, UINT_MAX) < 0) ++ if (virXMLPropUIntDefault(node, "priority", 10, VIR_XML_PROP_NONE, &priority, UINT_MAX) < 0) + return -1; + + if (priority != UINT_MAX && + virResctrlAllocSetMemoryBandwidth(alloc, VIR_MEMORY_TYPE_PRIORITY, id, priority) < 0) + return -1; + ++ if (virXMLPropUIntDefault(node, "min_bandwidth", 10, VIR_XML_PROP_NONE, &min_bandwidth, UINT_MAX) < 0) ++ return -1; ++ ++ if (min_bandwidth != UINT_MAX && ++ virResctrlAllocSetMemoryBandwidth(alloc, VIR_MEMORY_TYPE_MIN_BANDWIDTH, id, min_bandwidth) < 0) ++ return -1; ++ + return 0; + } + +diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng +index 1b2256fddf..a2e0119888 100644 +--- a/src/conf/schemas/domaincommon.rng ++++ b/src/conf/schemas/domaincommon.rng +@@ -1195,6 +1195,11 @@ + + + ++ ++ ++ ++ ++ + + + +diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c +index 06935cc11f..afd70c821a 100644 +--- a/src/util/virresctrl.c ++++ b/src/util/virresctrl.c +@@ -87,7 +87,7 @@ VIR_ENUM_IMPL(virMemory, + "bandwidth", + "hardlimit", + "priority", +- "minbandwidth", ++ "min_bandwidth", + ); + + VIR_ENUM_DECL(virResctrlMemory); +@@ -1423,6 +1423,12 @@ virResctrlAllocSetMemoryBandwidth(virResctrlAlloc *alloc, + } + break; + case VIR_MEMORY_TYPE_MIN_BANDWIDTH: ++ if (value > 100) { ++ virReportError(VIR_ERR_XML_ERROR, "%s", ++ _("Memory Bandwidth min_bandwidth value exceeding 100 is invalid.")); ++ return -1; ++ } ++ break; + case VIR_MEMORY_TYPE_LAST: + default: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +-- +2.43.0 + diff --git a/conf-add-support-for-cachetune-L3-priority.patch b/conf-add-support-for-cachetune-L3-priority.patch new file mode 100644 index 0000000..b6ad613 --- /dev/null +++ b/conf-add-support-for-cachetune-L3-priority.patch @@ -0,0 +1,125 @@ +From f6081b2631ac124b73be5953a9b9ce4922bf505e Mon Sep 17 00:00:00 2001 +From: lutong +Date: Mon, 28 Jul 2025 14:59:13 +0800 +Subject: [PATCH 3/6] conf: add support for cachetune/L3 priority + +--- + src/conf/domain_conf.c | 29 +++++++++++++++++++++-------- + src/conf/schemas/domaincommon.rng | 1 + + src/util/virresctrl.c | 27 +++++++++++++++++++++++++-- + 3 files changed, 47 insertions(+), 10 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 9643b9ce01..5dbbe5cd3c 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -17680,10 +17680,15 @@ virDomainCachetuneDefParseCache(xmlXPathContextPtr ctxt, + VIR_XML_PROP_REQUIRED, &type) < 0) + return -1; + +- if (virParseScaledValue("./@size", "./@unit", +- ctxt, &size, 1024, +- ULLONG_MAX, true) < 0) ++ if (type == VIR_CACHE_TYPE_PRIORITY) { ++ if (virXMLPropULongLong(node, "size", 10, VIR_XML_PROP_REQUIRED, &size) < 0) ++ return -1; ++ } else { ++ if (virParseScaledValue("./@size", "./@unit", ++ ctxt, &size, 1024, ++ ULLONG_MAX, true) < 0) + return -1; ++ } + + if (virResctrlAllocSetCacheSize(alloc, level, type, cache, size) < 0) + return -1; +@@ -26749,11 +26754,19 @@ virDomainCachetuneDefFormatHelper(unsigned int level, + virBuffer *buf = opaque; + unsigned long long short_size = virFormatIntPretty(size, &unit); + +- virBufferAsprintf(buf, +- "\n", +- cache, level, virCacheTypeToString(type), +- short_size, unit); ++ if (type == VIR_CACHE_TYPE_PRIORITY) { ++ virBufferAsprintf(buf, ++ "\n", ++ cache, level, virCacheTypeToString(type), ++ size); ++ } else { ++ virBufferAsprintf(buf, ++ "\n", ++ cache, level, virCacheTypeToString(type), ++ short_size, unit); ++ } + + return 0; + } +diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng +index f31603b2fd..7278b699e0 100644 +--- a/src/conf/schemas/domaincommon.rng ++++ b/src/conf/schemas/domaincommon.rng +@@ -1147,6 +1147,7 @@ + both + code + data ++ priority + + + +diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c +index 3d2be7560c..7bdbc85bc9 100644 +--- a/src/util/virresctrl.c ++++ b/src/util/virresctrl.c +@@ -1184,6 +1184,15 @@ virResctrlAllocCheckCollision(virResctrlAlloc *alloc, + if (!a_level) + return false; + ++ if (type == VIR_CACHE_TYPE_PRIORITY) { ++ a_type = a_level->types[VIR_CACHE_TYPE_PRIORITY]; ++ ++ if (a_type && a_type->nsizes > cache && a_type->sizes[cache]) ++ return true; ++ ++ return false; ++ } ++ + a_type = a_level->types[VIR_CACHE_TYPE_BOTH]; + + /* If there is an allocation for type 'both', there can be no other +@@ -2330,14 +2339,28 @@ virResctrlAllocAssign(virResctrlInfo *resctrl, + if (!a_type->sizes[cache]) + continue; + +- if (!a_type->priorities[cache]) { ++ if (a_type->npriorities == 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Cache level %1$d does not support tuning for scope type '%2$s'"), + level, virCacheTypeToString(type)); + return -1; + } + +- *a_type->priorities[cache] = *a_type->sizes[cache]; ++ if (a_type->npriorities <= cache || !a_type->priorities[cache]) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, ++ _("Cache id %1$d does not exist for level %2$d"), ++ cache, level); ++ return -1; ++ } ++ ++ if (*(a_type->sizes[cache]) > 3) { ++ virReportError(VIR_ERR_XML_ERROR, ++ _("Cache level %1$d id %2$d priority value just support 0-3"), ++ level, cache); ++ return -1; ++ } ++ ++ *(a_type->priorities[cache]) = *(a_type->sizes[cache]); + } + continue; + } +-- +2.43.0 + diff --git a/conf-add-support-for-memorytune-XML-processing-for-MB-h.patch b/conf-add-support-for-memorytune-XML-processing-for-MB-h.patch new file mode 100644 index 0000000..f82233c --- /dev/null +++ b/conf-add-support-for-memorytune-XML-processing-for-MB-h.patch @@ -0,0 +1,195 @@ +From f2d73e1d3b02894f40dbb9513f6ed923d2132e88 Mon Sep 17 00:00:00 2001 +From: lutong +Date: Mon, 4 Aug 2025 10:19:41 +0800 +Subject: [PATCH 5/6] conf: add support for memorytune XML processing for MB + hardlimit + +--- + src/conf/domain_conf.c | 23 ++++++++++++++--- + src/conf/schemas/domaincommon.rng | 5 ++++ + src/util/virresctrl.c | 43 ++++++++++++++++++++++++------- + src/util/virresctrl.h | 3 ++- + 4 files changed, 59 insertions(+), 15 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 12e02e4893..6c25d62998 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -18237,6 +18237,7 @@ virDomainMemorytuneDefParseMemory(xmlXPathContextPtr ctxt, + VIR_XPATH_NODE_AUTORESTORE(ctxt) + unsigned int id; + unsigned int bandwidth; ++ unsigned int hard_limit = UINT_MAX; + + ctxt->node = node; + +@@ -18250,6 +18251,13 @@ virDomainMemorytuneDefParseMemory(xmlXPathContextPtr ctxt, + if (virResctrlAllocSetMemoryBandwidth(alloc, VIR_MEMORY_TYPE_BANDWIDTH, id, bandwidth) < 0) + return -1; + ++ if (virXMLPropUIntDefault(node, "hardlimit", 10, 0, &hard_limit, UINT_MAX) < 0) ++ return -1; ++ ++ if (hard_limit != UINT_MAX && ++ virResctrlAllocSetMemoryBandwidth(alloc, VIR_MEMORY_TYPE_HARDLIMIT, id, hard_limit) < 0) ++ return -1; ++ + return 0; + } + +@@ -26846,14 +26854,21 @@ virDomainCachetuneDefFormat(virBuffer *buf, + + static int + virDomainMemorytuneDefFormatHelper(unsigned int id, +- unsigned int bandwidth, ++ unsigned int *types, ++ unsigned int *values, + void *opaque) + { + virBuffer *buf = opaque; ++ size_t i; + +- virBufferAsprintf(buf, +- "\n", +- id, bandwidth); ++ virBufferAsprintf(buf, "\n"); + return 0; + } + +diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng +index 7278b699e0..504147a0b5 100644 +--- a/src/conf/schemas/domaincommon.rng ++++ b/src/conf/schemas/domaincommon.rng +@@ -1185,6 +1185,11 @@ + + + ++ ++ ++ ++ ++ + + + +diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c +index 77abf03a3c..e262deae73 100644 +--- a/src/util/virresctrl.c ++++ b/src/util/virresctrl.c +@@ -1383,10 +1383,11 @@ virResctrlAllocForeachCache(virResctrlAlloc *alloc, + + /* virResctrlAllocSetMemoryBandwidth + * @alloc: Pointer to an active allocation ++ * @type: type of memory bandwidth to be set + * @id: node id of MBA to be set +- * @memory_bandwidth: new memory bandwidth value ++ * @value: new memory bandwidth type value + * +- * Set the @memory_bandwidth for the node @id entry in the @alloc. ++ * Set the @value for the node @id entry in the @alloc. + * + * Returns 0 on success, -1 on failure with error message set. + */ +@@ -1394,13 +1395,13 @@ int + virResctrlAllocSetMemoryBandwidth(virResctrlAlloc *alloc, + virMemoryType type, + unsigned int id, +- unsigned int memory_bandwidth) ++ unsigned int value) + { + virResctrlAllocMemBW *mem_bw = alloc->mem_bw; + virResctrlAllocMemPerType *a_type = NULL; + + if (type == VIR_MEMORY_TYPE_HARDLIMIT) { +- if (memory_bandwidth > 1) { ++ if (value > 1) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Memory Bandwidth hard limit value just support 0 or 1.")); + return -1; +@@ -1408,7 +1409,7 @@ virResctrlAllocSetMemoryBandwidth(virResctrlAlloc *alloc, + } + + if (type == VIR_MEMORY_TYPE_BANDWIDTH) { +- if (memory_bandwidth > 100) { ++ if (value > 100) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Memory Bandwidth value exceeding 100 is invalid.")); + return -1; +@@ -1437,7 +1438,7 @@ virResctrlAllocSetMemoryBandwidth(virResctrlAlloc *alloc, + } + + a_type->user_values[id] = g_new0(unsigned int, 1); +- *(a_type->user_values[id]) = memory_bandwidth; ++ *(a_type->user_values[id]) = value; + + return 0; + } +@@ -1458,18 +1459,40 @@ virResctrlAllocForeachMemory(virResctrlAlloc *alloc, + virResctrlAllocForeachMemoryCallback cb, + void *opaque) + { +- size_t i = 0; ++ unsigned int i, type; + virResctrlAllocMemBW *mem_bw; ++ g_autofree unsigned int *types = NULL; ++ g_autofree unsigned int *values = NULL; + + if (!alloc || !alloc->mem_bw) + return 0; + + mem_bw = alloc->mem_bw; ++ ++ if (!mem_bw->types) ++ return 0; ++ ++ if (!mem_bw->types[VIR_MEMORY_TYPE_BANDWIDTH]) ++ return 0; ++ ++ types = g_new0(unsigned int, VIR_MEMORY_TYPE_LAST); ++ values = g_new0(unsigned int, VIR_MEMORY_TYPE_LAST); ++ + for (i = 0; i < mem_bw->types[VIR_MEMORY_TYPE_BANDWIDTH]->nuser_values; i++) { +- if (mem_bw->types[VIR_MEMORY_TYPE_BANDWIDTH]->user_values[i]) { +- if (cb(i, *mem_bw->types[VIR_MEMORY_TYPE_BANDWIDTH]->user_values[i], opaque) < 0) +- return -1; ++ if (!mem_bw->types[VIR_MEMORY_TYPE_BANDWIDTH]->user_values[i]) ++ continue; ++ ++ for (type = 0; type < VIR_MEMORY_TYPE_LAST; type++) { ++ virResctrlAllocMemPerType *a_type = mem_bw->types[type]; ++ if (!a_type || a_type->nuser_values <= i || !a_type->user_values[i]) { ++ types[type] = VIR_MEMORY_TYPE_LAST; ++ continue; ++ } ++ ++ types[type] = type; ++ values[type] = *(a_type->user_values[i]); + } ++ cb(i, types, values, opaque); + } + + return 0; +diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h +index 9ee76eb225..9b317187f5 100644 +--- a/src/util/virresctrl.h ++++ b/src/util/virresctrl.h +@@ -129,7 +129,8 @@ typedef int virResctrlAllocForeachCacheCallback(unsigned int level, + void *opaque); + + typedef int virResctrlAllocForeachMemoryCallback(unsigned int id, +- unsigned int size, ++ unsigned int *types, ++ unsigned int *values, + void *opaque); + + virResctrlAlloc * +-- +2.43.0 + diff --git a/conf-add-support-for-memorytune-XML-processing-for-MB-p.patch b/conf-add-support-for-memorytune-XML-processing-for-MB-p.patch new file mode 100644 index 0000000..ebc7d10 --- /dev/null +++ b/conf-add-support-for-memorytune-XML-processing-for-MB-p.patch @@ -0,0 +1,109 @@ +From 3d24834d3cccccfe8e482ae3c86c10fa990d560f Mon Sep 17 00:00:00 2001 +From: lutong +Date: Tue, 12 Aug 2025 15:26:52 +0800 +Subject: [PATCH 6/6] conf: add support for memorytune XML processing for MB + priority + +--- + src/conf/domain_conf.c | 8 +++++++ + src/conf/schemas/domaincommon.rng | 5 ++++ + src/util/virresctrl.c | 40 +++++++++++++++++++++---------- + 3 files changed, 40 insertions(+), 13 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 6c25d62998..28b2157424 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -18238,6 +18238,7 @@ virDomainMemorytuneDefParseMemory(xmlXPathContextPtr ctxt, + unsigned int id; + unsigned int bandwidth; + unsigned int hard_limit = UINT_MAX; ++ unsigned int priority = UINT_MAX; + + ctxt->node = node; + +@@ -18258,6 +18259,13 @@ virDomainMemorytuneDefParseMemory(xmlXPathContextPtr ctxt, + virResctrlAllocSetMemoryBandwidth(alloc, VIR_MEMORY_TYPE_HARDLIMIT, id, hard_limit) < 0) + return -1; + ++ if (virXMLPropUIntDefault(node, "priority", 10, 0, &priority, UINT_MAX) < 0) ++ return -1; ++ ++ if (priority != UINT_MAX && ++ virResctrlAllocSetMemoryBandwidth(alloc, VIR_MEMORY_TYPE_PRIORITY, id, priority) < 0) ++ return -1; ++ + return 0; + } + +diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng +index 504147a0b5..1b2256fddf 100644 +--- a/src/conf/schemas/domaincommon.rng ++++ b/src/conf/schemas/domaincommon.rng +@@ -1190,6 +1190,11 @@ + + + ++ ++ ++ ++ ++ + + + +diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c +index e262deae73..06935cc11f 100644 +--- a/src/util/virresctrl.c ++++ b/src/util/virresctrl.c +@@ -1400,20 +1400,34 @@ virResctrlAllocSetMemoryBandwidth(virResctrlAlloc *alloc, + virResctrlAllocMemBW *mem_bw = alloc->mem_bw; + virResctrlAllocMemPerType *a_type = NULL; + +- if (type == VIR_MEMORY_TYPE_HARDLIMIT) { +- if (value > 1) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _("Memory Bandwidth hard limit value just support 0 or 1.")); +- return -1; +- } +- } +- +- if (type == VIR_MEMORY_TYPE_BANDWIDTH) { +- if (value > 100) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _("Memory Bandwidth value exceeding 100 is invalid.")); ++ switch (type) { ++ case VIR_MEMORY_TYPE_BANDWIDTH: ++ if (value > 100) { ++ virReportError(VIR_ERR_XML_ERROR, "%s", ++ _("Memory Bandwidth value exceeding 100 is invalid.")); ++ return -1; ++ } ++ break; ++ case VIR_MEMORY_TYPE_HARDLIMIT: ++ if (value > 1) { ++ virReportError(VIR_ERR_XML_ERROR, "%s", ++ _("Memory Bandwidth hard limit value just support 0 or 1.")); ++ return -1; ++ } ++ break; ++ case VIR_MEMORY_TYPE_PRIORITY: ++ if (value > 7) { ++ virReportError(VIR_ERR_XML_ERROR, "%s", ++ _("Memory Bandwidth priority value just support 0-7.")); ++ return -1; ++ } ++ break; ++ case VIR_MEMORY_TYPE_MIN_BANDWIDTH: ++ case VIR_MEMORY_TYPE_LAST: ++ default: ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("Invalid memory bandwidth type.")); + return -1; +- } + } + + if (!mem_bw) { +-- +2.43.0 + diff --git a/libvirt.spec b/libvirt.spec index 6c5e52f..c4b84da 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -262,7 +262,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 9.10.0 -Release: 17 +Release: 18 License: LGPLv2+ URL: https://libvirt.org/ @@ -341,6 +341,13 @@ Patch0067: Revert-qemu-Remove-pre-blockdev-PFLASH-setup.patch Patch0068: qemu_command-get-disk-alias-from-disk-instead-of-nod.patch Patch0069: migration-Add-the-VIR_MIGRATE_RETURNPATH-flag.patch Patch0070: Revert-Automatically-unbind-all-devices-driver-under.patch +Patch0071: util-resctrl-add-parsing-process-for-the-new-paramet.patch +Patch0072: util-resctrl-add-L3-priority-parse-and-format-method.patch +Patch0073: conf-add-support-for-cachetune-L3-priority.patch +Patch0074: util-resctrl-define-memory-bandwidth-types-add-parse.patch +Patch0075: conf-add-support-for-memorytune-XML-processing-for-MB-h.patch +Patch0076: conf-add-support-for-memorytune-XML-processing-for-MB-p.patch +Patch0077: conf-add-support-for-MB-min_bandwidth.patch Requires: libvirt-daemon = %{version}-%{release} @@ -2633,6 +2640,16 @@ exit 0 %endif %changelog +* Mon Aug 25 2025 lutong - 9.10.0-18 +- util: resctrl: Adapt MPAM QoS interface +- util-resctrl-add-parsing-process-for-the-new-paramet.patch +- util-resctrl-add-L3-priority-parse-and-format-method.patch +- conf-add-support-for-cachetune-L3-priority.patch +- util-resctrl-define-memory-bandwidth-types-add-parse.patch +- conf-add-support-for-memorytune-XML-processing-for-MB-h.patch +- conf-add-support-for-memorytune-XML-processing-for-MB-p.patch +- conf-add-support-for-MB-min_bandwidth.patch + * Wed Jul 30 2025 JiaboFeng - 9.10.0-17 - Revert "Automatically unbind all devices' driver under same root port and bind to vfio-pci in the context of CVM." diff --git a/util-resctrl-add-L3-priority-parse-and-format-method.patch b/util-resctrl-add-L3-priority-parse-and-format-method.patch new file mode 100644 index 0000000..41d1d94 --- /dev/null +++ b/util-resctrl-add-L3-priority-parse-and-format-method.patch @@ -0,0 +1,365 @@ +From fbc6ac1471bdc6ffdb5fe5e47bf6df2753acf949 Mon Sep 17 00:00:00 2001 +From: lutong +Date: Sat, 26 Jul 2025 17:40:03 +0800 +Subject: [PATCH 2/6] util:resctrl:add L3 priority parse and format method + +--- + src/libvirt_private.syms | 2 + + src/util/virresctrl.c | 168 +++++++++++++++++++++++++++++++------- + src/util/virresctrl.h | 1 + + src/util/virresctrlpriv.h | 7 ++ + tests/virresctrltest.c | 5 ++ + 5 files changed, 153 insertions(+), 30 deletions(-) + +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index cd99cc302a..a3799a0108 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -3252,11 +3252,13 @@ virCacheKernelTypeToString; + virCacheTypeFromString; + virCacheTypeToString; + virResctrlAllocAddPID; ++virResctrlAllocCopyCacheProperties; + virResctrlAllocCreate; + virResctrlAllocDeterminePath; + virResctrlAllocForeachCache; + virResctrlAllocForeachMemory; + virResctrlAllocFormat; ++virResctrlAllocGetDefault; + virResctrlAllocGetID; + virResctrlAllocGetUnused; + virResctrlAllocIsEmpty; +diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c +index 7d661e944f..3d2be7560c 100644 +--- a/src/util/virresctrl.c ++++ b/src/util/virresctrl.c +@@ -60,6 +60,7 @@ VIR_ENUM_IMPL(virCacheKernel, + "Unified", + "Instruction", + "Data", ++ "Priority", + ); + + /* Cache name mapping for our XML naming. */ +@@ -68,6 +69,7 @@ VIR_ENUM_IMPL(virCache, + "both", + "code", + "data", ++ "priority", + ); + + /* Cache name mapping for resctrl interface naming. */ +@@ -77,6 +79,7 @@ VIR_ENUM_IMPL(virResctrl, + "", + "CODE", + "DATA", ++ "PRI", + ); + + /* Monitor feature name prefix mapping for monitor naming */ +@@ -313,6 +316,10 @@ struct _virResctrlAllocPerType { + /* cache id map for each cache */ + unsigned int **cache_ids; + size_t ncache_ids; ++ ++ /* priority for each cahe */ ++ unsigned long long **priorities; ++ size_t npriorities; + }; + + struct _virResctrlAllocPerLevel { +@@ -401,9 +408,13 @@ virResctrlAllocDispose(void *obj) + for (k = 0; k < type->ncache_ids; k++) + g_free(type->cache_ids[k]); + ++ for (k = 0; k < type->npriorities; k++) ++ g_free(type->priorities[k]); ++ + g_free(type->sizes); + g_free(type->masks); + g_free(type->cache_ids); ++ g_free(type->priorities); + g_free(type); + } + g_free(level->types); +@@ -1518,19 +1529,25 @@ virResctrlAllocFormatCache(virResctrlAlloc *alloc, + + virBufferAsprintf(buf, "L%u%s:", level, virResctrlTypeToString(type)); + +- for (cache = 0; cache < a_type->nmasks; cache++) { +- virBitmap *mask = a_type->masks[cache]; +- char *mask_str = NULL; +- +- if (!mask) +- continue; +- +- mask_str = virBitmapToString(mask); +- if (!mask_str) +- return -1; +- +- virBufferAsprintf(buf, "%u=%s;", *a_type->cache_ids[cache], mask_str); +- VIR_FREE(mask_str); ++ if (type == VIR_CACHE_TYPE_PRIORITY) { ++ for (cache = 0; cache < a_type->npriorities; cache++) { ++ virBufferAsprintf(buf, "%u=%llu;", *(a_type->cache_ids[cache]), *(a_type->priorities[cache])); ++ } ++ } else { ++ for (cache = 0; cache < a_type->nmasks; cache++) { ++ virBitmap *mask = a_type->masks[cache]; ++ char *mask_str = NULL; ++ ++ if (!mask) ++ continue; ++ ++ mask_str = virBitmapToString(mask); ++ if (!mask_str) ++ return -1; ++ ++ virBufferAsprintf(buf, "%u=%s;", *(a_type->cache_ids[cache]), mask_str); ++ VIR_FREE(mask_str); ++ } + } + + virBufferTrim(buf, ";"); +@@ -1604,6 +1621,41 @@ virResctrlAllocParseProcessCacheId(virResctrlInfo *resctrl, + } + + ++static int ++virResctrlAllocParseProcessCachePriority(virResctrlAlloc *alloc, ++ unsigned int level, ++ virCacheType type, ++ char *value, ++ unsigned int node_id) ++{ ++ unsigned int priority = 0; ++ virResctrlAllocPerType *a_type = NULL; ++ ++ if (virStrToLong_uip(value, NULL, 10, &priority) < 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Invalid priority '%1$s'"), value); ++ return -1; ++ } ++ ++ a_type = virResctrlAllocGetType(alloc, level, type); ++ ++ if (!a_type) ++ return -1; ++ ++ if (a_type->npriorities <= node_id) { ++ VIR_EXPAND_N(a_type->priorities, a_type->npriorities, ++ node_id - a_type->npriorities + 1); ++ } ++ ++ if (!a_type->priorities[node_id]) ++ a_type->priorities[node_id] = g_new0(unsigned long long, 1); ++ ++ *(a_type->priorities[node_id]) = priority; ++ ++ return 0; ++} ++ ++ + static int + virResctrlAllocParseProcessCache(virResctrlInfo *resctrl, + virResctrlAlloc *alloc, +@@ -1613,7 +1665,6 @@ virResctrlAllocParseProcessCache(virResctrlInfo *resctrl, + unsigned int node_id) + { + char *tmp = strchr(cache, '='); +- unsigned int cache_id = 0; + g_autoptr(virBitmap) mask = NULL; + + if (!tmp) +@@ -1626,10 +1677,8 @@ virResctrlAllocParseProcessCache(virResctrlInfo *resctrl, + return -1; + } + +- if (virStrToLong_uip(cache, NULL, 10, &cache_id) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, +- _("Invalid cache id '%1$s'"), cache); +- return -1; ++ if (type == VIR_CACHE_TYPE_PRIORITY) { ++ return virResctrlAllocParseProcessCachePriority(alloc, level, type, tmp, node_id); + } + + mask = virBitmapNewString(tmp); +@@ -1762,7 +1811,7 @@ virResctrlAllocGetGroup(virResctrlInfo *resctrl, + } + + +-static virResctrlAlloc * ++virResctrlAlloc * + virResctrlAllocGetDefault(virResctrlInfo *resctrl) + { + virResctrlAlloc *ret = NULL; +@@ -2128,9 +2177,9 @@ virResctrlAllocCopyMemBW(virResctrlAlloc *dst, + } + + +-static int +-virResctrlAllocCopyCache(virResctrlAlloc *dst, +- virResctrlAlloc *src) ++int ++virResctrlAllocCopyCacheProperties(virResctrlAlloc *dst, ++ virResctrlAlloc *src) + { + unsigned int level = 0; + +@@ -2153,13 +2202,6 @@ virResctrlAllocCopyCache(virResctrlAlloc *dst, + if (!d_type) + return -1; + +- for (cache = 0; cache < s_type->nmasks; cache++) { +- virBitmap *mask = s_type->masks[cache]; +- +- if (mask && virResctrlAllocUpdateMask(dst, level, type, cache, mask) < 0) +- return -1; +- } +- + if (s_type->ncache_ids > d_type->ncache_ids) + VIR_EXPAND_N(d_type->cache_ids, d_type->ncache_ids, + s_type->ncache_ids - d_type->ncache_ids); +@@ -2168,7 +2210,18 @@ virResctrlAllocCopyCache(virResctrlAlloc *dst, + if (d_type->cache_ids[cache]) + continue; + d_type->cache_ids[cache] = g_new0(unsigned int, 1); +- *d_type->cache_ids[cache] = *s_type->cache_ids[cache]; ++ *(d_type->cache_ids[cache]) = *(s_type->cache_ids[cache]); ++ } ++ ++ if (s_type->npriorities > d_type->npriorities) ++ VIR_EXPAND_N(d_type->priorities, d_type->npriorities, ++ s_type->npriorities - d_type->npriorities); ++ ++ for (cache = 0; cache < s_type->npriorities; cache++) { ++ if (d_type->priorities[cache]) ++ continue; ++ d_type->priorities[cache] = g_new0(long long unsigned int, 1); ++ *(d_type->priorities[cache]) = *(s_type->priorities[cache]); + } + } + } +@@ -2177,6 +2230,44 @@ virResctrlAllocCopyCache(virResctrlAlloc *dst, + } + + ++static int ++virResctrlAllocCopyCache(virResctrlAlloc *dst, ++ virResctrlAlloc *src) ++{ ++ unsigned int level = 0; ++ ++ for (level = 0; level < src->nlevels; level++) { ++ virResctrlAllocPerLevel *s_level = src->levels[level]; ++ unsigned int type = 0; ++ ++ if (!s_level) ++ continue; ++ ++ for (type = 0; type < VIR_CACHE_TYPE_LAST; type++) { ++ virResctrlAllocPerType *s_type = s_level->types[type]; ++ virResctrlAllocPerType *d_type = NULL; ++ unsigned int cache = 0; ++ ++ if (!s_type) ++ continue; ++ ++ d_type = virResctrlAllocGetType(dst, level, type); ++ if (!d_type) ++ return -1; ++ ++ for (cache = 0; cache < s_type->nmasks; cache++) { ++ virBitmap *mask = s_type->masks[cache]; ++ ++ if (mask && virResctrlAllocUpdateMask(dst, level, type, cache, mask) < 0) ++ return -1; ++ } ++ } ++ } ++ ++ return virResctrlAllocCopyCacheProperties(dst, src); ++} ++ ++ + /* + * This function is called when creating an allocation in the system. + * What it does is that it gets all the unused resources using +@@ -2234,6 +2325,23 @@ virResctrlAllocAssign(virResctrlInfo *resctrl, + if (!a_type) + continue; + ++ if (type == VIR_CACHE_TYPE_PRIORITY) { ++ for (cache = 0; cache < a_type->nsizes; cache++) { ++ if (!a_type->sizes[cache]) ++ continue; ++ ++ if (!a_type->priorities[cache]) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, ++ _("Cache level %1$d does not support tuning for scope type '%2$s'"), ++ level, virCacheTypeToString(type)); ++ return -1; ++ } ++ ++ *a_type->priorities[cache] = *a_type->sizes[cache]; ++ } ++ continue; ++ } ++ + if (!f_type) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Cache level %1$d does not support tuning for scope type '%2$s'"), +diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h +index 0e4b535f9e..af135520d7 100644 +--- a/src/util/virresctrl.h ++++ b/src/util/virresctrl.h +@@ -27,6 +27,7 @@ typedef enum { + VIR_CACHE_TYPE_BOTH, + VIR_CACHE_TYPE_CODE, + VIR_CACHE_TYPE_DATA, ++ VIR_CACHE_TYPE_PRIORITY, + + VIR_CACHE_TYPE_LAST + } virCacheType; +diff --git a/src/util/virresctrlpriv.h b/src/util/virresctrlpriv.h +index 803f9b62ab..646b040761 100644 +--- a/src/util/virresctrlpriv.h ++++ b/src/util/virresctrlpriv.h +@@ -26,3 +26,10 @@ + + virResctrlAlloc * + virResctrlAllocGetUnused(virResctrlInfo *resctrl); ++ ++virResctrlAlloc * ++virResctrlAllocGetDefault(virResctrlInfo *resctrl); ++ ++int ++virResctrlAllocCopyCacheProperties(virResctrlAlloc *dst, ++ virResctrlAlloc *src); +\ No newline at end of file +diff --git a/tests/virresctrltest.c b/tests/virresctrltest.c +index c5733a7972..d5bc37259c 100644 +--- a/tests/virresctrltest.c ++++ b/tests/virresctrltest.c +@@ -21,6 +21,7 @@ test_virResctrlGetUnused(const void *opaque) + g_autofree char *system_dir = NULL; + g_autofree char *resctrl_dir = NULL; + g_autoptr(virResctrlAlloc) alloc = NULL; ++ g_autoptr(virResctrlAlloc) default_alloc = NULL; + g_autofree char *schemata_str = NULL; + g_autofree char *schemata_file = NULL; + g_autoptr(virCaps) caps = NULL; +@@ -44,6 +45,10 @@ test_virResctrlGetUnused(const void *opaque) + } + + alloc = virResctrlAllocGetUnused(caps->host.resctrl); ++ default_alloc = virResctrlAllocGetDefault(caps->host.resctrl); ++ ++ if (virResctrlAllocCopyCacheProperties(alloc, default_alloc) < 0) ++ return -1; + + virFileWrapperClearPrefixes(); + +-- +2.43.0 + diff --git a/util-resctrl-add-parsing-process-for-the-new-paramet.patch b/util-resctrl-add-parsing-process-for-the-new-paramet.patch new file mode 100644 index 0000000..fe5db7b --- /dev/null +++ b/util-resctrl-add-parsing-process-for-the-new-paramet.patch @@ -0,0 +1,184 @@ +From a63abd6836364df141e2428df2f76b233ebc56aa Mon Sep 17 00:00:00 2001 +From: lutong +Date: Sat, 26 Jul 2025 15:49:33 +0800 +Subject: [PATCH 1/6] util: resctrl: add parsing process for the new parameters + cache id + +--- + src/util/virresctrl.c | 83 +++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 76 insertions(+), 7 deletions(-) + +diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c +index 30ae25c487..7d661e944f 100644 +--- a/src/util/virresctrl.c ++++ b/src/util/virresctrl.c +@@ -309,6 +309,10 @@ struct _virResctrlAllocPerType { + /* Mask for each cache */ + virBitmap **masks; + size_t nmasks; ++ ++ /* cache id map for each cache */ ++ unsigned int **cache_ids; ++ size_t ncache_ids; + }; + + struct _virResctrlAllocPerLevel { +@@ -394,8 +398,12 @@ virResctrlAllocDispose(void *obj) + for (k = 0; k < type->nmasks; k++) + virBitmapFree(type->masks[k]); + ++ for (k = 0; k < type->ncache_ids; k++) ++ g_free(type->cache_ids[k]); ++ + g_free(type->sizes); + g_free(type->masks); ++ g_free(type->cache_ids); + g_free(type); + } + g_free(level->types); +@@ -1521,7 +1529,7 @@ virResctrlAllocFormatCache(virResctrlAlloc *alloc, + if (!mask_str) + return -1; + +- virBufferAsprintf(buf, "%u=%s;", cache, mask_str); ++ virBufferAsprintf(buf, "%u=%s;", *a_type->cache_ids[cache], mask_str); + VIR_FREE(mask_str); + } + +@@ -1552,12 +1560,57 @@ virResctrlAllocFormat(virResctrlAlloc *alloc) + } + + ++static int ++virResctrlAllocParseProcessCacheId(virResctrlInfo *resctrl, ++ virResctrlAlloc *alloc, ++ unsigned int level, ++ virCacheType type, ++ char *cache, ++ unsigned int node_id) ++{ ++ unsigned int cache_id = 0; ++ virResctrlAllocPerType *a_type = NULL; ++ ++ if (virStrToLong_uip(cache, NULL, 10, &cache_id) < 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Invalid cache id '%1$s'"), cache); ++ return -1; ++ } ++ ++ if (!resctrl || ++ level >= resctrl->nlevels || ++ !resctrl->levels[level]) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Missing or inconsistent resctrl info for level '%1$u'"), ++ level); ++ return -1; ++ } ++ ++ a_type = virResctrlAllocGetType(alloc, level, type); ++ if (!a_type) ++ return -1; ++ ++ if (a_type->ncache_ids <= node_id) { ++ VIR_EXPAND_N(a_type->cache_ids, a_type->ncache_ids, ++ node_id - a_type->ncache_ids + 1); ++ } ++ ++ if (!a_type->cache_ids[node_id]) ++ a_type->cache_ids[node_id] = g_new0(unsigned int, 1); ++ ++ *(a_type->cache_ids[node_id]) = cache_id; ++ ++ return 0; ++} ++ ++ + static int + virResctrlAllocParseProcessCache(virResctrlInfo *resctrl, + virResctrlAlloc *alloc, + unsigned int level, + virCacheType type, +- char *cache) ++ char *cache, ++ unsigned int node_id) + { + char *tmp = strchr(cache, '='); + unsigned int cache_id = 0; +@@ -1569,6 +1622,10 @@ virResctrlAllocParseProcessCache(virResctrlInfo *resctrl, + *tmp = '\0'; + tmp++; + ++ if (virResctrlAllocParseProcessCacheId(resctrl, alloc, level, type, cache, node_id) < 0) { ++ return -1; ++ } ++ + if (virStrToLong_uip(cache, NULL, 10, &cache_id) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid cache id '%1$s'"), cache); +@@ -1591,7 +1648,7 @@ virResctrlAllocParseProcessCache(virResctrlInfo *resctrl, + + virBitmapShrink(mask, resctrl->levels[level]->types[type]->bits); + +- if (virResctrlAllocUpdateMask(alloc, level, type, cache_id, mask) < 0) ++ if (virResctrlAllocUpdateMask(alloc, level, type, node_id, mask) < 0) + return -1; + + return 0; +@@ -1607,6 +1664,7 @@ virResctrlAllocParseCacheLine(virResctrlInfo *resctrl, + GStrv next; + char *tmp = NULL; + unsigned int level = 0; ++ unsigned int node_id = 0; + int type = -1; + + /* For no reason there can be spaces */ +@@ -1643,8 +1701,8 @@ virResctrlAllocParseCacheLine(virResctrlInfo *resctrl, + if (!caches) + return 0; + +- for (next = caches; *next; next++) { +- if (virResctrlAllocParseProcessCache(resctrl, alloc, level, type, *next) < 0) ++ for (next = caches; *next; next++, node_id++) { ++ if (virResctrlAllocParseProcessCache(resctrl, alloc, level, type, *next, node_id) < 0) + return -1; + } + +@@ -2071,7 +2129,7 @@ virResctrlAllocCopyMemBW(virResctrlAlloc *dst, + + + static int +-virResctrlAllocCopyMasks(virResctrlAlloc *dst, ++virResctrlAllocCopyCache(virResctrlAlloc *dst, + virResctrlAlloc *src) + { + unsigned int level = 0; +@@ -2101,6 +2159,17 @@ virResctrlAllocCopyMasks(virResctrlAlloc *dst, + if (mask && virResctrlAllocUpdateMask(dst, level, type, cache, mask) < 0) + return -1; + } ++ ++ if (s_type->ncache_ids > d_type->ncache_ids) ++ VIR_EXPAND_N(d_type->cache_ids, d_type->ncache_ids, ++ s_type->ncache_ids - d_type->ncache_ids); ++ ++ for (cache = 0; cache < s_type->ncache_ids; cache++) { ++ if (d_type->cache_ids[cache]) ++ continue; ++ d_type->cache_ids[cache] = g_new0(unsigned int, 1); ++ *d_type->cache_ids[cache] = *s_type->cache_ids[cache]; ++ } + } + } + +@@ -2133,7 +2202,7 @@ virResctrlAllocAssign(virResctrlInfo *resctrl, + if (virResctrlAllocMemoryBandwidth(resctrl, alloc) < 0) + return -1; + +- if (virResctrlAllocCopyMasks(alloc, alloc_default) < 0) ++ if (virResctrlAllocCopyCache(alloc, alloc_default) < 0) + return -1; + + if (virResctrlAllocCopyMemBW(alloc, alloc_default) < 0) +-- +2.43.0 + diff --git a/util-resctrl-define-memory-bandwidth-types-add-parse.patch b/util-resctrl-define-memory-bandwidth-types-add-parse.patch new file mode 100644 index 0000000..1982437 --- /dev/null +++ b/util-resctrl-define-memory-bandwidth-types-add-parse.patch @@ -0,0 +1,526 @@ +From b8ff1a5efe7ae9a173fb1a6fdf47f3c76de9b73a Mon Sep 17 00:00:00 2001 +From: lutong +Date: Wed, 30 Jul 2025 15:22:05 +0800 +Subject: [PATCH 4/6] util: resctrl: define memory bandwidth types & add parse + and format method + +--- + src/conf/domain_conf.c | 2 +- + src/util/virresctrl.c | 274 ++++++++++++++++++++++++++++++++--------- + src/util/virresctrl.h | 13 +- + 3 files changed, 227 insertions(+), 62 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 5dbbe5cd3c..12e02e4893 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -18247,7 +18247,7 @@ virDomainMemorytuneDefParseMemory(xmlXPathContextPtr ctxt, + &bandwidth) < 0) + return -1; + +- if (virResctrlAllocSetMemoryBandwidth(alloc, id, bandwidth) < 0) ++ if (virResctrlAllocSetMemoryBandwidth(alloc, VIR_MEMORY_TYPE_BANDWIDTH, id, bandwidth) < 0) + return -1; + + return 0; +diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c +index 7bdbc85bc9..77abf03a3c 100644 +--- a/src/util/virresctrl.c ++++ b/src/util/virresctrl.c +@@ -82,6 +82,23 @@ VIR_ENUM_IMPL(virResctrl, + "PRI", + ); + ++VIR_ENUM_IMPL(virMemory, ++ VIR_MEMORY_TYPE_LAST, ++ "bandwidth", ++ "hardlimit", ++ "priority", ++ "minbandwidth", ++); ++ ++VIR_ENUM_DECL(virResctrlMemory); ++VIR_ENUM_IMPL(virResctrlMemory, ++ VIR_MEMORY_TYPE_LAST, ++ "", ++ "HDL", ++ "PRI", ++ "MIN", ++); ++ + /* Monitor feature name prefix mapping for monitor naming */ + VIR_ENUM_IMPL(virResctrlMonitorPrefix, + VIR_RESCTRL_MONITOR_TYPE_LAST, +@@ -106,6 +123,8 @@ typedef struct _virResctrlAllocPerType virResctrlAllocPerType; + + typedef struct _virResctrlAllocPerLevel virResctrlAllocPerLevel; + ++typedef struct _virResctrlAllocMemPerType virResctrlAllocMemPerType; ++ + typedef struct _virResctrlAllocMemBW virResctrlAllocMemBW; + + +@@ -333,9 +352,18 @@ struct _virResctrlAllocPerLevel { + * Since it can have several last level caches in a NUMA system, it is + * also represented as a nested sparse arrays as virRestrlAllocPerLevel. + */ ++struct _virResctrlAllocMemPerType { ++ unsigned int **values; ++ size_t nvalues; ++ ++ unsigned int **user_values; ++ size_t nuser_values; ++}; ++ + struct _virResctrlAllocMemBW { +- unsigned int **bandwidths; +- size_t nbandwidths; ++ virResctrlAllocMemPerType **types; /* Indexed with enum virMemoryType */ ++ /* There is no `ntypes` member variable as it is always allocated for ++ * VIR_MEMORY_TYPE_LAST number of items */ + }; + + struct _virResctrlAlloc { +@@ -423,9 +451,24 @@ virResctrlAllocDispose(void *obj) + + if (alloc->mem_bw) { + virResctrlAllocMemBW *mem_bw = alloc->mem_bw; +- for (i = 0; i < mem_bw->nbandwidths; i++) +- g_free(mem_bw->bandwidths[i]); +- g_free(alloc->mem_bw->bandwidths); ++ ++ for (i = 0; i < VIR_MEMORY_TYPE_LAST; i++) { ++ virResctrlAllocMemPerType *type = mem_bw->types[i]; ++ ++ if (!type) ++ continue; ++ ++ for (j = 0; j < type->nvalues; j++) ++ g_free(type->values[j]); ++ ++ for (j = 0; j < type->nuser_values; j++) ++ g_free(type->user_values[j]); ++ ++ g_free(type->values); ++ g_free(type->user_values); ++ g_free(type); ++ } ++ g_free(mem_bw->types); + g_free(alloc->mem_bw); + } + +@@ -1104,6 +1147,28 @@ virResctrlAllocGetType(virResctrlAlloc *alloc, + } + + ++static virResctrlAllocMemPerType * ++virResctrlAllocGetMemType(virResctrlAlloc *alloc, ++ virMemoryType type) ++{ ++ virResctrlAllocMemBW *mem_bw = NULL; ++ ++ if (!alloc->mem_bw) ++ alloc->mem_bw = g_new0(virResctrlAllocMemBW, 1); ++ ++ mem_bw = alloc->mem_bw; ++ ++ if (!mem_bw->types) { ++ mem_bw->types = g_new0(virResctrlAllocMemPerType *, VIR_MEMORY_TYPE_LAST); ++ } ++ ++ if (!mem_bw->types[type]) ++ mem_bw->types[type] = g_new0(virResctrlAllocMemPerType, 1); ++ ++ return mem_bw->types[type]; ++} ++ ++ + static int + virResctrlAllocUpdateMask(virResctrlAlloc *alloc, + unsigned int level, +@@ -1154,6 +1219,41 @@ virResctrlAllocUpdateSize(virResctrlAlloc *alloc, + } + + ++static int ++virResctrlAllocUpdateMBValue(virResctrlAlloc *alloc) ++{ ++ virResctrlAllocMemBW *mem_bw = alloc->mem_bw; ++ virResctrlAllocMemPerType *a_type = NULL; ++ unsigned int type = 0; ++ unsigned int id = 0; ++ ++ if (!mem_bw || !mem_bw->types) ++ return 0; ++ ++ for (type = 0; type < VIR_MEMORY_TYPE_LAST; type++) { ++ a_type = mem_bw->types[type]; ++ if (!a_type) ++ continue; ++ ++ for (id = 0; id < a_type->nuser_values; id++) { ++ if (!a_type->user_values[id]) ++ continue; ++ ++ if (a_type->nvalues <= id || !a_type->values[id]) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, ++ _("Node %1$u memory bandwidth does not support tuning for scope type '%2$s'"), ++ id, virMemoryTypeToString(type)); ++ return -1; ++ } ++ ++ *(a_type->values[id]) = *(a_type->user_values[id]); ++ } ++ } ++ ++ return 0; ++} ++ ++ + /* + * Check if there is an allocation for this level/type/cache already. Called + * before updating the structure. VIR_CACHE_TYPE_BOTH collides with any type, +@@ -1292,15 +1392,27 @@ virResctrlAllocForeachCache(virResctrlAlloc *alloc, + */ + int + virResctrlAllocSetMemoryBandwidth(virResctrlAlloc *alloc, ++ virMemoryType type, + unsigned int id, + unsigned int memory_bandwidth) + { + virResctrlAllocMemBW *mem_bw = alloc->mem_bw; ++ virResctrlAllocMemPerType *a_type = NULL; + +- if (memory_bandwidth > 100) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _("Memory Bandwidth value exceeding 100 is invalid.")); +- return -1; ++ if (type == VIR_MEMORY_TYPE_HARDLIMIT) { ++ if (memory_bandwidth > 1) { ++ virReportError(VIR_ERR_XML_ERROR, "%s", ++ _("Memory Bandwidth hard limit value just support 0 or 1.")); ++ return -1; ++ } ++ } ++ ++ if (type == VIR_MEMORY_TYPE_BANDWIDTH) { ++ if (memory_bandwidth > 100) { ++ virReportError(VIR_ERR_XML_ERROR, "%s", ++ _("Memory Bandwidth value exceeding 100 is invalid.")); ++ return -1; ++ } + } + + if (!mem_bw) { +@@ -1308,19 +1420,25 @@ virResctrlAllocSetMemoryBandwidth(virResctrlAlloc *alloc, + alloc->mem_bw = mem_bw; + } + +- if (mem_bw->nbandwidths <= id) +- VIR_EXPAND_N(mem_bw->bandwidths, mem_bw->nbandwidths, +- id - mem_bw->nbandwidths + 1); ++ a_type = virResctrlAllocGetMemType(alloc, type); ++ if (!a_type) ++ return -1; + +- if (mem_bw->bandwidths[id]) { ++ if (a_type->nuser_values <= id) ++ VIR_EXPAND_N(a_type->user_values, a_type->nuser_values, ++ id - a_type->nuser_values + 1); ++ ++ if (a_type->user_values[id]) { + virReportError(VIR_ERR_XML_ERROR, +- _("Memory Bandwidth already defined for node %1$u"), ++ _("Memory Bandwidth type '%1$s' already defined for node %2$u"), ++ virMemoryTypeToString(type), + id); + return -1; + } + +- mem_bw->bandwidths[id] = g_new0(unsigned int, 1); +- *(mem_bw->bandwidths[id]) = memory_bandwidth; ++ a_type->user_values[id] = g_new0(unsigned int, 1); ++ *(a_type->user_values[id]) = memory_bandwidth; ++ + return 0; + } + +@@ -1347,9 +1465,9 @@ virResctrlAllocForeachMemory(virResctrlAlloc *alloc, + return 0; + + mem_bw = alloc->mem_bw; +- for (i = 0; i < mem_bw->nbandwidths; i++) { +- if (mem_bw->bandwidths[i]) { +- if (cb(i, *mem_bw->bandwidths[i], opaque) < 0) ++ for (i = 0; i < mem_bw->types[VIR_MEMORY_TYPE_BANDWIDTH]->nuser_values; i++) { ++ if (mem_bw->types[VIR_MEMORY_TYPE_BANDWIDTH]->user_values[i]) { ++ if (cb(i, *mem_bw->types[VIR_MEMORY_TYPE_BANDWIDTH]->user_values[i], opaque) < 0) + return -1; + } + } +@@ -1408,22 +1526,26 @@ static int + virResctrlAllocMemoryBandwidthFormat(virResctrlAlloc *alloc, + virBuffer *buf) + { +- size_t i; ++ unsigned int i, type; + + if (!alloc->mem_bw) + return 0; + +- virBufferAddLit(buf, "MB:"); ++ for (type = 0; type < VIR_MEMORY_TYPE_LAST; type++) { ++ virResctrlAllocMemPerType *a_type = alloc->mem_bw->types[type]; ++ if (!a_type) ++ continue; ++ ++ virBufferAsprintf(buf, "MB%s:", virResctrlMemoryTypeToString(type)); + +- 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])); ++ for (i = 0; i < a_type->nvalues; i++) { ++ virBufferAsprintf(buf, "%u=%u;", i, *(a_type->values[i])); + } ++ ++ virBufferTrim(buf, ";"); ++ virBufferAddChar(buf, '\n'); + } + +- virBufferTrim(buf, ";"); +- virBufferAddChar(buf, '\n'); + return 0; + } + +@@ -1431,11 +1553,13 @@ virResctrlAllocMemoryBandwidthFormat(virResctrlAlloc *alloc, + static int + virResctrlAllocParseProcessMemoryBandwidth(virResctrlInfo *resctrl, + virResctrlAlloc *alloc, ++ virMemoryType type, + char *mem_bw) + { +- unsigned int bandwidth; ++ unsigned int value; + unsigned int id; + char *tmp = NULL; ++ virResctrlAllocMemPerType *a_type = NULL; + + tmp = strchr(mem_bw, '='); + if (!tmp) +@@ -1448,26 +1572,32 @@ virResctrlAllocParseProcessMemoryBandwidth(virResctrlInfo *resctrl, + _("Invalid node id %1$u "), id); + return -1; + } +- if (virStrToLong_uip(tmp, NULL, 10, &bandwidth) < 0) { ++ if (virStrToLong_uip(tmp, NULL, 10, &value) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, +- _("Invalid bandwidth %1$u"), bandwidth); ++ _("Invalid MB%1$s value %2$u"), ++ virResctrlMemoryTypeToString(type), value); + return -1; + } +- if (bandwidth < resctrl->membw_info->min_bandwidth || ++ if ((type == VIR_MEMORY_TYPE_BANDWIDTH && value < 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 '%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); ++ ++ a_type = virResctrlAllocGetMemType(alloc, type); ++ if (!a_type) ++ return -1; ++ ++ if (a_type->nvalues <= id) { ++ VIR_EXPAND_N(a_type->values, a_type->nvalues, ++ id - a_type->nvalues + 1); + } +- if (!alloc->mem_bw->bandwidths[id]) +- alloc->mem_bw->bandwidths[id] = g_new0(unsigned int, 1); ++ if (!a_type->values[id]) ++ a_type->values[id] = g_new0(unsigned int, 1); + +- *(alloc->mem_bw->bandwidths[id]) = bandwidth; ++ *(a_type->values[id]) = value; + return 0; + } + +@@ -1483,6 +1613,7 @@ virResctrlAllocParseMemoryBandwidthLine(virResctrlInfo *resctrl, + g_auto(GStrv) mbs = NULL; + GStrv next; + char *tmp = NULL; ++ int type = -1; + + /* For no reason there can be spaces */ + virSkipSpaces((const char **) &line); +@@ -1504,11 +1635,19 @@ virResctrlAllocParseMemoryBandwidthLine(virResctrlInfo *resctrl, + tmp = strchr(line, ':'); + if (!tmp) + return 0; ++ *tmp = '\0'; + tmp++; + ++ type = virResctrlMemoryTypeFromString(line + 2); ++ if (type < 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Cannot parse resctrl schemata line '%1$s'"), line); ++ return -1; ++ } ++ + mbs = g_strsplit(tmp, ";", 0); + for (next = mbs; *next; next++) { +- if (virResctrlAllocParseProcessMemoryBandwidth(resctrl, alloc, *next) < 0) ++ if (virResctrlAllocParseProcessMemoryBandwidth(resctrl, alloc, type, *next) < 0) + return -1; + } + +@@ -1908,14 +2047,19 @@ virResctrlAllocNewFromInfo(virResctrlInfo *info) + + /* set default free memory bandwidth to 100% */ + if (info->membw_info) { ++ virResctrlAllocMemPerType *type = NULL; + ret->mem_bw = g_new0(virResctrlAllocMemBW, 1); + +- VIR_EXPAND_N(ret->mem_bw->bandwidths, ret->mem_bw->nbandwidths, ++ type = virResctrlAllocGetMemType(ret, VIR_MEMORY_TYPE_BANDWIDTH); ++ if (!type) ++ return NULL; ++ ++ VIR_EXPAND_N(type->values, type->nvalues, + info->membw_info->max_id + 1); + +- for (i = 0; i < ret->mem_bw->nbandwidths; i++) { +- ret->mem_bw->bandwidths[i] = g_new0(unsigned int, 1); +- *(ret->mem_bw->bandwidths[i]) = 100; ++ for (i = 0; i < type->nvalues; i++) { ++ type->values[i] = g_new0(unsigned int, 1); ++ *(type->values[i]) = 100; + } + } + +@@ -2126,21 +2270,21 @@ virResctrlAllocMemoryBandwidth(virResctrlInfo *resctrl, + return -1; + } + +- for (i = 0; i < mem_bw_alloc->nbandwidths; i++) { +- if (!mem_bw_alloc->bandwidths[i]) ++ for (i = 0; i < mem_bw_alloc->types[VIR_MEMORY_TYPE_BANDWIDTH]->nuser_values; i++) { ++ if (!mem_bw_alloc->types[VIR_MEMORY_TYPE_BANDWIDTH]->user_values[i]) + continue; + +- if (*(mem_bw_alloc->bandwidths[i]) % mem_bw_info->bandwidth_granularity) { ++ if (*(mem_bw_alloc->types[VIR_MEMORY_TYPE_BANDWIDTH]->user_values[i]) % mem_bw_info->bandwidth_granularity) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Memory Bandwidth allocation of size %1$u is not divisible by granularity %2$u"), +- *(mem_bw_alloc->bandwidths[i]), ++ *(mem_bw_alloc->types[VIR_MEMORY_TYPE_BANDWIDTH]->user_values[i]), + mem_bw_info->bandwidth_granularity); + return -1; + } +- if (*(mem_bw_alloc->bandwidths[i]) < mem_bw_info->min_bandwidth) { ++ if (*(mem_bw_alloc->types[VIR_MEMORY_TYPE_BANDWIDTH]->user_values[i]) < mem_bw_info->min_bandwidth) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Memory Bandwidth allocation of size %1$u is smaller than the minimum allowed allocation %2$u"), +- *(mem_bw_alloc->bandwidths[i]), ++ *(mem_bw_alloc->types[VIR_MEMORY_TYPE_BANDWIDTH]->user_values[i]), + mem_bw_info->min_bandwidth); + return -1; + } +@@ -2160,26 +2304,33 @@ virResctrlAllocCopyMemBW(virResctrlAlloc *dst, + virResctrlAlloc *src) + { + size_t i = 0; +- virResctrlAllocMemBW *dst_bw = NULL; ++ unsigned int type = 0; + virResctrlAllocMemBW *src_bw = src->mem_bw; + + if (!src->mem_bw) + return 0; + +- if (!dst->mem_bw) +- dst->mem_bw = g_new0(virResctrlAllocMemBW, 1); ++ for (type = 0; type < VIR_MEMORY_TYPE_LAST; type++) { ++ virResctrlAllocMemPerType *s_type = src_bw->types[type]; ++ virResctrlAllocMemPerType *d_type = NULL; + +- dst_bw = dst->mem_bw; ++ if (!s_type) ++ continue; + +- if (src_bw->nbandwidths > dst_bw->nbandwidths) +- VIR_EXPAND_N(dst_bw->bandwidths, dst_bw->nbandwidths, +- src_bw->nbandwidths - dst_bw->nbandwidths); ++ d_type = virResctrlAllocGetMemType(dst, type); ++ if (!d_type) ++ return -1; + +- for (i = 0; i < src_bw->nbandwidths; i++) { +- if (dst_bw->bandwidths[i]) +- continue; +- dst_bw->bandwidths[i] = g_new0(unsigned int, 1); +- *dst_bw->bandwidths[i] = *src_bw->bandwidths[i]; ++ if (s_type->nvalues > d_type->nvalues) ++ VIR_EXPAND_N(d_type->values, d_type->nvalues, ++ s_type->nvalues - d_type->nvalues); ++ ++ for (i = 0; i < s_type->nvalues; i++) { ++ if (d_type->values[i]) ++ continue; ++ d_type->values[i] = g_new0(unsigned int, 1); ++ *(d_type->values[i]) = *(s_type->values[i]); ++ } + } + + return 0; +@@ -2308,6 +2459,9 @@ virResctrlAllocAssign(virResctrlInfo *resctrl, + if (virResctrlAllocCopyMemBW(alloc, alloc_default) < 0) + return -1; + ++ if (virResctrlAllocUpdateMBValue(alloc) < 0) ++ return -1; ++ + for (level = 0; level < alloc->nlevels; level++) { + virResctrlAllocPerLevel *a_level = alloc->levels[level]; + virResctrlAllocPerLevel *f_level = NULL; +diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h +index af135520d7..9ee76eb225 100644 +--- a/src/util/virresctrl.h ++++ b/src/util/virresctrl.h +@@ -32,8 +32,18 @@ typedef enum { + VIR_CACHE_TYPE_LAST + } virCacheType; + ++typedef enum { ++ VIR_MEMORY_TYPE_BANDWIDTH, ++ VIR_MEMORY_TYPE_HARDLIMIT, ++ VIR_MEMORY_TYPE_PRIORITY, ++ VIR_MEMORY_TYPE_MIN_BANDWIDTH, ++ ++ VIR_MEMORY_TYPE_LAST ++} virMemoryType; ++ + VIR_ENUM_DECL(virCache); + VIR_ENUM_DECL(virCacheKernel); ++VIR_ENUM_DECL(virMemory); + + typedef enum { + VIR_RESCTRL_MONITOR_TYPE_UNSUPPORT, +@@ -142,8 +152,9 @@ virResctrlAllocForeachCache(virResctrlAlloc *alloc, + + int + virResctrlAllocSetMemoryBandwidth(virResctrlAlloc *alloc, ++ virMemoryType type, + unsigned int id, +- unsigned int memory_bandwidth); ++ unsigned int value); + + int + virResctrlAllocForeachMemory(virResctrlAlloc *alloc, +-- +2.43.0 + -- Gitee