|
|
c1c534 |
From bc7971b29f6c152a9c20aa3cda9bd361dcb61f14 Mon Sep 17 00:00:00 2001
|
|
|
c1c534 |
Message-Id: <bc7971b29f6c152a9c20aa3cda9bd361dcb61f14@dist-git>
|
|
|
c1c534 |
From: Wim ten Have <wim.ten.have@oracle.com>
|
|
|
c1c534 |
Date: Mon, 4 Dec 2017 13:38:48 +0100
|
|
|
c1c534 |
Subject: [PATCH] xenconfig: add domxml conversions for xen-xl
|
|
|
c1c534 |
|
|
|
c1c534 |
https://bugzilla.redhat.com/show_bug.cgi?id=1454889
|
|
|
c1c534 |
|
|
|
c1c534 |
This patch converts NUMA configurations between the Xen libxl
|
|
|
c1c534 |
configuration file format and libvirt's XML format.
|
|
|
c1c534 |
|
|
|
c1c534 |
XML HVM domain on a 4 node (2 cores/socket) configuration:
|
|
|
c1c534 |
|
|
|
c1c534 |
<cpu>
|
|
|
c1c534 |
<numa>
|
|
|
c1c534 |
<cell id='0' cpus='0-1' memory='2097152' unit='KiB'>
|
|
|
c1c534 |
<distances>
|
|
|
c1c534 |
<sibling id='0' value='10'/>
|
|
|
c1c534 |
<sibling id='1' value='21'/>
|
|
|
c1c534 |
<sibling id='2' value='31'/>
|
|
|
c1c534 |
<sibling id='3' value='21'/>
|
|
|
c1c534 |
</distances>
|
|
|
c1c534 |
</cell>
|
|
|
c1c534 |
<cell id='1' cpus='2-3' memory='2097152' unit='KiB'>
|
|
|
c1c534 |
<distances>
|
|
|
c1c534 |
<sibling id='0' value='21'/>
|
|
|
c1c534 |
<sibling id='1' value='10'/>
|
|
|
c1c534 |
<sibling id='2' value='21'/>
|
|
|
c1c534 |
<sibling id='3' value='31'/>
|
|
|
c1c534 |
</distances>
|
|
|
c1c534 |
</cell>
|
|
|
c1c534 |
<cell id='2' cpus='3-4' memory='2097152' unit='KiB'>
|
|
|
c1c534 |
<distances>
|
|
|
c1c534 |
<sibling id='0' value='31'/>
|
|
|
c1c534 |
<sibling id='1' value='21'/>
|
|
|
c1c534 |
<sibling id='2' value='10'/>
|
|
|
c1c534 |
<sibling id='3' value='21'/>
|
|
|
c1c534 |
</distances>
|
|
|
c1c534 |
</cell>
|
|
|
c1c534 |
<cell id='3' cpus='5-6' memory='2097152' unit='KiB'>
|
|
|
c1c534 |
<distances>
|
|
|
c1c534 |
<sibling id='0' value='21'/>
|
|
|
c1c534 |
<sibling id='1' value='31'/>
|
|
|
c1c534 |
<sibling id='2' value='21'/>
|
|
|
c1c534 |
<sibling id='3' value='10'/>
|
|
|
c1c534 |
</distances>
|
|
|
c1c534 |
</cell>
|
|
|
c1c534 |
</numa>
|
|
|
c1c534 |
</cpu>
|
|
|
c1c534 |
|
|
|
c1c534 |
Xen xl.cfg domain configuration:
|
|
|
c1c534 |
|
|
|
c1c534 |
vnuma = [["pnode=0","size=2048","vcpus=0-1","vdistances=10,21,31,21"],
|
|
|
c1c534 |
["pnode=1","size=2048","vcpus=2-3","vdistances=21,10,21,31"],
|
|
|
c1c534 |
["pnode=2","size=2048","vcpus=4-5","vdistances=31,21,10,21"],
|
|
|
c1c534 |
["pnode=3","size=2048","vcpus=6-7","vdistances=21,31,21,10"]]
|
|
|
c1c534 |
|
|
|
c1c534 |
If there is no XML <distances> description amongst the <cell> data the
|
|
|
c1c534 |
conversion schema from xml to native will generate 10 for local and 20
|
|
|
c1c534 |
for all remote instances.
|
|
|
c1c534 |
|
|
|
c1c534 |
Signed-off-by: Wim ten Have <wim.ten.have@oracle.com>
|
|
|
c1c534 |
Reviewed-by: Jim Fehlig <jfehlig@suse.com>
|
|
|
c1c534 |
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
|
|
|
c1c534 |
(cherry picked from commit 03d0959af3a72eb2aed47a1d2dcf8ccbb39d4b0e)
|
|
|
c1c534 |
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
c1c534 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
c1c534 |
---
|
|
|
c1c534 |
src/conf/numa_conf.c | 137 +++++++++++++++++++
|
|
|
c1c534 |
src/conf/numa_conf.h | 25 ++++
|
|
|
c1c534 |
src/libvirt_private.syms | 5 +
|
|
|
c1c534 |
src/xenconfig/xen_xl.c | 335 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
c1c534 |
4 files changed, 502 insertions(+)
|
|
|
c1c534 |
|
|
|
c1c534 |
diff --git a/src/conf/numa_conf.c b/src/conf/numa_conf.c
|
|
|
c1c534 |
index 5fbcc72041..7bba4120bd 100644
|
|
|
c1c534 |
--- a/src/conf/numa_conf.c
|
|
|
c1c534 |
+++ b/src/conf/numa_conf.c
|
|
|
c1c534 |
@@ -1114,6 +1114,132 @@ virDomainNumaGetNodeCount(virDomainNumaPtr numa)
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
|
|
|
c1c534 |
+size_t
|
|
|
c1c534 |
+virDomainNumaSetNodeCount(virDomainNumaPtr numa, size_t nmem_nodes)
|
|
|
c1c534 |
+{
|
|
|
c1c534 |
+ if (!nmem_nodes) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
c1c534 |
+ _("Cannot set an empty mem_nodes set"));
|
|
|
c1c534 |
+ return 0;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (numa->mem_nodes) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
c1c534 |
+ _("Cannot alter an existing mem_nodes set"));
|
|
|
c1c534 |
+ return 0;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (VIR_ALLOC_N(numa->mem_nodes, nmem_nodes) < 0)
|
|
|
c1c534 |
+ return 0;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ numa->nmem_nodes = nmem_nodes;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ return numa->nmem_nodes;
|
|
|
c1c534 |
+}
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+size_t
|
|
|
c1c534 |
+virDomainNumaGetNodeDistance(virDomainNumaPtr numa,
|
|
|
c1c534 |
+ size_t node,
|
|
|
c1c534 |
+ size_t cellid)
|
|
|
c1c534 |
+{
|
|
|
c1c534 |
+ virDomainNumaDistancePtr distances = NULL;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (node < numa->nmem_nodes)
|
|
|
c1c534 |
+ distances = numa->mem_nodes[node].distances;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ /*
|
|
|
c1c534 |
+ * Present the configured distance value. If
|
|
|
c1c534 |
+ * out of range or not available set the platform
|
|
|
c1c534 |
+ * defined default for local and remote nodes.
|
|
|
c1c534 |
+ */
|
|
|
c1c534 |
+ if (!distances ||
|
|
|
c1c534 |
+ !distances[cellid].value ||
|
|
|
c1c534 |
+ !numa->mem_nodes[node].ndistances)
|
|
|
c1c534 |
+ return (node == cellid) ? LOCAL_DISTANCE : REMOTE_DISTANCE;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ return distances[cellid].value;
|
|
|
c1c534 |
+}
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+int
|
|
|
c1c534 |
+virDomainNumaSetNodeDistance(virDomainNumaPtr numa,
|
|
|
c1c534 |
+ size_t node,
|
|
|
c1c534 |
+ size_t cellid,
|
|
|
c1c534 |
+ unsigned int value)
|
|
|
c1c534 |
+{
|
|
|
c1c534 |
+ virDomainNumaDistancePtr distances;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (node >= numa->nmem_nodes) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c1c534 |
+ _("Argument 'node' %zu outranges "
|
|
|
c1c534 |
+ "defined number of NUMA nodes"),
|
|
|
c1c534 |
+ node);
|
|
|
c1c534 |
+ return -1;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ distances = numa->mem_nodes[node].distances;
|
|
|
c1c534 |
+ if (!distances ||
|
|
|
c1c534 |
+ cellid >= numa->mem_nodes[node].ndistances) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
c1c534 |
+ _("Arguments under memnode element do not "
|
|
|
c1c534 |
+ "correspond with existing guest's NUMA cell"));
|
|
|
c1c534 |
+ return -1;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ /*
|
|
|
c1c534 |
+ * Advanced Configuration and Power Interface
|
|
|
c1c534 |
+ * Specification version 6.1. Chapter 5.2.17
|
|
|
c1c534 |
+ * System Locality Distance Information Table
|
|
|
c1c534 |
+ * ... Distance values of 0-9 are reserved.
|
|
|
c1c534 |
+ */
|
|
|
c1c534 |
+ if (value < LOCAL_DISTANCE ||
|
|
|
c1c534 |
+ value > UNREACHABLE) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
c1c534 |
+ _("Distance value of %d is not in valid range"),
|
|
|
c1c534 |
+ value);
|
|
|
c1c534 |
+ return -1;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (value == LOCAL_DISTANCE && node != cellid) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
c1c534 |
+ _("Distance value %d under node %zu is "
|
|
|
c1c534 |
+ "LOCAL_DISTANCE and should be set to 10"),
|
|
|
c1c534 |
+ value, node);
|
|
|
c1c534 |
+ return -1;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ distances[cellid].cellid = cellid;
|
|
|
c1c534 |
+ distances[cellid].value = value;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ return distances[cellid].value;
|
|
|
c1c534 |
+}
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+size_t
|
|
|
c1c534 |
+virDomainNumaSetNodeDistanceCount(virDomainNumaPtr numa,
|
|
|
c1c534 |
+ size_t node,
|
|
|
c1c534 |
+ size_t ndistances)
|
|
|
c1c534 |
+{
|
|
|
c1c534 |
+ virDomainNumaDistancePtr distances;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ distances = numa->mem_nodes[node].distances;
|
|
|
c1c534 |
+ if (distances) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c1c534 |
+ _("Cannot alter an existing nmem_nodes distances set for node: %zu"),
|
|
|
c1c534 |
+ node);
|
|
|
c1c534 |
+ return 0;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (VIR_ALLOC_N(distances, ndistances) < 0)
|
|
|
c1c534 |
+ return 0;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ numa->mem_nodes[node].distances = distances;
|
|
|
c1c534 |
+ numa->mem_nodes[node].ndistances = ndistances;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ return numa->mem_nodes[node].ndistances;
|
|
|
c1c534 |
+}
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+
|
|
|
c1c534 |
virBitmapPtr
|
|
|
c1c534 |
virDomainNumaGetNodeCpumask(virDomainNumaPtr numa,
|
|
|
c1c534 |
size_t node)
|
|
|
c1c534 |
@@ -1122,6 +1248,17 @@ virDomainNumaGetNodeCpumask(virDomainNumaPtr numa,
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
|
|
|
c1c534 |
+virBitmapPtr
|
|
|
c1c534 |
+virDomainNumaSetNodeCpumask(virDomainNumaPtr numa,
|
|
|
c1c534 |
+ size_t node,
|
|
|
c1c534 |
+ virBitmapPtr cpumask)
|
|
|
c1c534 |
+{
|
|
|
c1c534 |
+ numa->mem_nodes[node].cpumask = cpumask;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ return numa->mem_nodes[node].cpumask;
|
|
|
c1c534 |
+}
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+
|
|
|
c1c534 |
virDomainMemoryAccess
|
|
|
c1c534 |
virDomainNumaGetNodeMemoryAccessMode(virDomainNumaPtr numa,
|
|
|
c1c534 |
size_t node)
|
|
|
c1c534 |
diff --git a/src/conf/numa_conf.h b/src/conf/numa_conf.h
|
|
|
c1c534 |
index 378b772e4b..4655de3aa7 100644
|
|
|
c1c534 |
--- a/src/conf/numa_conf.h
|
|
|
c1c534 |
+++ b/src/conf/numa_conf.h
|
|
|
c1c534 |
@@ -87,6 +87,11 @@ int virDomainNumatuneMaybeGetNodeset(virDomainNumaPtr numatune,
|
|
|
c1c534 |
|
|
|
c1c534 |
size_t virDomainNumaGetNodeCount(virDomainNumaPtr numa);
|
|
|
c1c534 |
|
|
|
c1c534 |
+size_t virDomainNumaGetNodeDistance(virDomainNumaPtr numa,
|
|
|
c1c534 |
+ size_t node,
|
|
|
c1c534 |
+ size_t sibling)
|
|
|
c1c534 |
+ ATTRIBUTE_NONNULL(1);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
virBitmapPtr virDomainNumaGetNodeCpumask(virDomainNumaPtr numa,
|
|
|
c1c534 |
size_t node)
|
|
|
c1c534 |
ATTRIBUTE_NONNULL(1);
|
|
|
c1c534 |
@@ -124,11 +129,31 @@ int virDomainNumatuneSet(virDomainNumaPtr numa,
|
|
|
c1c534 |
virBitmapPtr nodeset)
|
|
|
c1c534 |
ATTRIBUTE_NONNULL(1);
|
|
|
c1c534 |
|
|
|
c1c534 |
+size_t virDomainNumaSetNodeCount(virDomainNumaPtr numa,
|
|
|
c1c534 |
+ size_t nmem_nodes)
|
|
|
c1c534 |
+ ATTRIBUTE_NONNULL(1);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
void virDomainNumaSetNodeMemorySize(virDomainNumaPtr numa,
|
|
|
c1c534 |
size_t node,
|
|
|
c1c534 |
unsigned long long size)
|
|
|
c1c534 |
ATTRIBUTE_NONNULL(1);
|
|
|
c1c534 |
|
|
|
c1c534 |
+int virDomainNumaSetNodeDistance(virDomainNumaPtr numa,
|
|
|
c1c534 |
+ size_t node,
|
|
|
c1c534 |
+ size_t sibling,
|
|
|
c1c534 |
+ unsigned int value)
|
|
|
c1c534 |
+ ATTRIBUTE_NONNULL(1);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+size_t virDomainNumaSetNodeDistanceCount(virDomainNumaPtr numa,
|
|
|
c1c534 |
+ size_t node,
|
|
|
c1c534 |
+ size_t ndistances)
|
|
|
c1c534 |
+ ATTRIBUTE_NONNULL(1);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+virBitmapPtr virDomainNumaSetNodeCpumask(virDomainNumaPtr numa,
|
|
|
c1c534 |
+ size_t node,
|
|
|
c1c534 |
+ virBitmapPtr cpumask)
|
|
|
c1c534 |
+ ATTRIBUTE_NONNULL(1);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
/*
|
|
|
c1c534 |
* Other accessors
|
|
|
c1c534 |
*/
|
|
|
c1c534 |
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
|
c1c534 |
index ecf7036dff..19543e06ae 100644
|
|
|
c1c534 |
--- a/src/libvirt_private.syms
|
|
|
c1c534 |
+++ b/src/libvirt_private.syms
|
|
|
c1c534 |
@@ -723,9 +723,14 @@ virDomainNumaGetMaxCPUID;
|
|
|
c1c534 |
virDomainNumaGetMemorySize;
|
|
|
c1c534 |
virDomainNumaGetNodeCount;
|
|
|
c1c534 |
virDomainNumaGetNodeCpumask;
|
|
|
c1c534 |
+virDomainNumaGetNodeDistance;
|
|
|
c1c534 |
virDomainNumaGetNodeMemoryAccessMode;
|
|
|
c1c534 |
virDomainNumaGetNodeMemorySize;
|
|
|
c1c534 |
virDomainNumaNew;
|
|
|
c1c534 |
+virDomainNumaSetNodeCount;
|
|
|
c1c534 |
+virDomainNumaSetNodeCpumask;
|
|
|
c1c534 |
+virDomainNumaSetNodeDistance;
|
|
|
c1c534 |
+virDomainNumaSetNodeDistanceCount;
|
|
|
c1c534 |
virDomainNumaSetNodeMemorySize;
|
|
|
c1c534 |
virDomainNumatuneFormatNodeset;
|
|
|
c1c534 |
virDomainNumatuneFormatXML;
|
|
|
c1c534 |
diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c
|
|
|
c1c534 |
index 8acbfe3f69..81e780586f 100644
|
|
|
c1c534 |
--- a/src/xenconfig/xen_xl.c
|
|
|
c1c534 |
+++ b/src/xenconfig/xen_xl.c
|
|
|
c1c534 |
@@ -309,6 +309,203 @@ xenParseXLSpice(virConfPtr conf, virDomainDefPtr def)
|
|
|
c1c534 |
return -1;
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
+#ifdef LIBXL_HAVE_VNUMA
|
|
|
c1c534 |
+static int
|
|
|
c1c534 |
+xenParseXLVnuma(virConfPtr conf,
|
|
|
c1c534 |
+ virDomainDefPtr def)
|
|
|
c1c534 |
+{
|
|
|
c1c534 |
+ int ret = -1;
|
|
|
c1c534 |
+ char *tmp = NULL;
|
|
|
c1c534 |
+ char **token = NULL;
|
|
|
c1c534 |
+ size_t vcpus = 0;
|
|
|
c1c534 |
+ size_t nr_nodes = 0;
|
|
|
c1c534 |
+ size_t vnodeCnt = 0;
|
|
|
c1c534 |
+ virCPUDefPtr cpu = NULL;
|
|
|
c1c534 |
+ virConfValuePtr list;
|
|
|
c1c534 |
+ virConfValuePtr vnode;
|
|
|
c1c534 |
+ virDomainNumaPtr numa;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ numa = def->numa;
|
|
|
c1c534 |
+ if (numa == NULL)
|
|
|
c1c534 |
+ return -1;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ list = virConfGetValue(conf, "vnuma");
|
|
|
c1c534 |
+ if (!list || list->type != VIR_CONF_LIST)
|
|
|
c1c534 |
+ return 0;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ vnode = list->list;
|
|
|
c1c534 |
+ while (vnode && vnode->type == VIR_CONF_LIST) {
|
|
|
c1c534 |
+ vnode = vnode->next;
|
|
|
c1c534 |
+ nr_nodes++;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (!virDomainNumaSetNodeCount(numa, nr_nodes))
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (VIR_ALLOC(cpu) < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ list = list->list;
|
|
|
c1c534 |
+ while (list) {
|
|
|
c1c534 |
+ int pnode = -1;
|
|
|
c1c534 |
+ virBitmapPtr cpumask = NULL;
|
|
|
c1c534 |
+ unsigned long long kbsize = 0;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ /* Is there a sublist (vnode)? */
|
|
|
c1c534 |
+ if (list && list->type == VIR_CONF_LIST) {
|
|
|
c1c534 |
+ vnode = list->list;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ while (vnode && vnode->type == VIR_CONF_STRING) {
|
|
|
c1c534 |
+ const char *data;
|
|
|
c1c534 |
+ const char *str = vnode->str;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (!str ||
|
|
|
c1c534 |
+ !(data = strrchr(str, '='))) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c1c534 |
+ _("vnuma vnode invalid format '%s'"),
|
|
|
c1c534 |
+ str);
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+ data++;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (*data) {
|
|
|
c1c534 |
+ size_t len;
|
|
|
c1c534 |
+ char vtoken[64];
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (STRPREFIX(str, "pnode")) {
|
|
|
c1c534 |
+ unsigned int cellid;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ len = strlen(data);
|
|
|
c1c534 |
+ if (!virStrncpy(vtoken, data,
|
|
|
c1c534 |
+ len, sizeof(vtoken))) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c1c534 |
+ _("vnuma vnode %zu pnode '%s' too long for destination"),
|
|
|
c1c534 |
+ vnodeCnt, data);
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if ((virStrToLong_ui(vtoken, NULL, 10, &cellid) < 0) ||
|
|
|
c1c534 |
+ (cellid >= nr_nodes)) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
c1c534 |
+ _("vnuma vnode %zu contains invalid pnode value '%s'"),
|
|
|
c1c534 |
+ vnodeCnt, data);
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+ pnode = cellid;
|
|
|
c1c534 |
+ } else if (STRPREFIX(str, "size")) {
|
|
|
c1c534 |
+ len = strlen(data);
|
|
|
c1c534 |
+ if (!virStrncpy(vtoken, data,
|
|
|
c1c534 |
+ len, sizeof(vtoken))) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c1c534 |
+ _("vnuma vnode %zu size '%s' too long for destination"),
|
|
|
c1c534 |
+ vnodeCnt, data);
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (virStrToLong_ull(vtoken, NULL, 10, &kbsize) < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ virDomainNumaSetNodeMemorySize(numa, vnodeCnt, (kbsize * 1024));
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ } else if (STRPREFIX(str, "vcpus")) {
|
|
|
c1c534 |
+ len = strlen(data);
|
|
|
c1c534 |
+ if (!virStrncpy(vtoken, data,
|
|
|
c1c534 |
+ len, sizeof(vtoken))) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c1c534 |
+ _("vnuma vnode %zu vcpus '%s' too long for destination"),
|
|
|
c1c534 |
+ vnodeCnt, data);
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if ((virBitmapParse(vtoken, &cpumask, VIR_DOMAIN_CPUMASK_LEN) < 0) ||
|
|
|
c1c534 |
+ (virDomainNumaSetNodeCpumask(numa, vnodeCnt, cpumask) == NULL))
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ vcpus += virBitmapCountBits(cpumask);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ } else if (STRPREFIX(str, "vdistances")) {
|
|
|
c1c534 |
+ size_t i, ndistances;
|
|
|
c1c534 |
+ unsigned int value;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ len = strlen(data);
|
|
|
c1c534 |
+ if (!virStrncpy(vtoken, data,
|
|
|
c1c534 |
+ len, sizeof(vtoken))) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c1c534 |
+ _("vnuma vnode %zu vdistances '%s' too long for destination"),
|
|
|
c1c534 |
+ vnodeCnt, data);
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (VIR_STRDUP(tmp, vtoken) < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (!(token = virStringSplitCount(tmp, ",", 0, &ndistances)))
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (ndistances != nr_nodes) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
c1c534 |
+ _("vnuma pnode %d configured '%s' (count %zu) doesn't fit the number of specified vnodes %zu"),
|
|
|
c1c534 |
+ pnode, str, ndistances, nr_nodes);
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (virDomainNumaSetNodeDistanceCount(numa, vnodeCnt, ndistances) != ndistances)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ for (i = 0; i < ndistances; i++) {
|
|
|
c1c534 |
+ if ((virStrToLong_ui(token[i], NULL, 10, &value) < 0) ||
|
|
|
c1c534 |
+ (virDomainNumaSetNodeDistance(numa, vnodeCnt, i, value) != value))
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ } else {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_CONF_SYNTAX,
|
|
|
c1c534 |
+ _("Invalid vnuma configuration for vnode %zu"),
|
|
|
c1c534 |
+ vnodeCnt);
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+ vnode = vnode->next;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if ((pnode < 0) ||
|
|
|
c1c534 |
+ (cpumask == NULL) ||
|
|
|
c1c534 |
+ (kbsize == 0)) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_CONF_SYNTAX,
|
|
|
c1c534 |
+ _("Incomplete vnuma configuration for vnode %zu"),
|
|
|
c1c534 |
+ vnodeCnt);
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ list = list->next;
|
|
|
c1c534 |
+ vnodeCnt++;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (def->maxvcpus == 0)
|
|
|
c1c534 |
+ def->maxvcpus = vcpus;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (def->maxvcpus < vcpus) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
c1c534 |
+ _("vnuma configuration contains %zu vcpus, which is greater than %zu maxvcpus"),
|
|
|
c1c534 |
+ vcpus, def->maxvcpus);
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ cpu->type = VIR_CPU_TYPE_GUEST;
|
|
|
c1c534 |
+ def->cpu = cpu;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ ret = 0;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ cleanup:
|
|
|
c1c534 |
+ if (ret)
|
|
|
c1c534 |
+ VIR_FREE(cpu);
|
|
|
c1c534 |
+ virStringListFree(token);
|
|
|
c1c534 |
+ VIR_FREE(tmp);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ return ret;
|
|
|
c1c534 |
+}
|
|
|
c1c534 |
+#endif
|
|
|
c1c534 |
|
|
|
c1c534 |
static int
|
|
|
c1c534 |
xenParseXLDiskSrc(virDomainDiskDefPtr disk, char *srcstr)
|
|
|
c1c534 |
@@ -863,6 +1060,11 @@ xenParseXL(virConfPtr conf,
|
|
|
c1c534 |
if (xenParseXLOS(conf, def, caps) < 0)
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
|
|
|
c1c534 |
+#ifdef LIBXL_HAVE_VNUMA
|
|
|
c1c534 |
+ if (xenParseXLVnuma(conf, def) < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+#endif
|
|
|
c1c534 |
+
|
|
|
c1c534 |
if (xenParseXLDisk(conf, def) < 0)
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -1005,6 +1207,134 @@ xenFormatXLOS(virConfPtr conf, virDomainDefPtr def)
|
|
|
c1c534 |
return 0;
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
+#ifdef LIBXL_HAVE_VNUMA
|
|
|
c1c534 |
+static int
|
|
|
c1c534 |
+xenFormatXLVnode(virConfValuePtr list,
|
|
|
c1c534 |
+ virBufferPtr buf)
|
|
|
c1c534 |
+{
|
|
|
c1c534 |
+ int ret = -1;
|
|
|
c1c534 |
+ virConfValuePtr numaPnode, tmp;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (virBufferCheckError(buf) < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (VIR_ALLOC(numaPnode) < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ /* Place VNODE directive */
|
|
|
c1c534 |
+ numaPnode->type = VIR_CONF_STRING;
|
|
|
c1c534 |
+ numaPnode->str = virBufferContentAndReset(buf);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ tmp = list->list;
|
|
|
c1c534 |
+ while (tmp && tmp->next)
|
|
|
c1c534 |
+ tmp = tmp->next;
|
|
|
c1c534 |
+ if (tmp)
|
|
|
c1c534 |
+ tmp->next = numaPnode;
|
|
|
c1c534 |
+ else
|
|
|
c1c534 |
+ list->list = numaPnode;
|
|
|
c1c534 |
+ ret = 0;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ cleanup:
|
|
|
c1c534 |
+ virBufferFreeAndReset(buf);
|
|
|
c1c534 |
+ return ret;
|
|
|
c1c534 |
+}
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+static int
|
|
|
c1c534 |
+xenFormatXLVnuma(virConfValuePtr list,
|
|
|
c1c534 |
+ virDomainNumaPtr numa,
|
|
|
c1c534 |
+ size_t node,
|
|
|
c1c534 |
+ size_t nr_nodes)
|
|
|
c1c534 |
+{
|
|
|
c1c534 |
+ int ret = -1;
|
|
|
c1c534 |
+ size_t i;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
c1c534 |
+ virConfValuePtr numaVnode, tmp;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ size_t nodeSize = virDomainNumaGetNodeMemorySize(numa, node) / 1024;
|
|
|
c1c534 |
+ char *nodeVcpus = virBitmapFormat(virDomainNumaGetNodeCpumask(numa, node));
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (VIR_ALLOC(numaVnode) < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ numaVnode->type = VIR_CONF_LIST;
|
|
|
c1c534 |
+ numaVnode->list = NULL;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ /* pnode */
|
|
|
c1c534 |
+ virBufferAsprintf(&buf, "pnode=%ld", node);
|
|
|
c1c534 |
+ xenFormatXLVnode(numaVnode, &buf;;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ /* size */
|
|
|
c1c534 |
+ virBufferAsprintf(&buf, "size=%ld", nodeSize);
|
|
|
c1c534 |
+ xenFormatXLVnode(numaVnode, &buf;;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ /* vcpus */
|
|
|
c1c534 |
+ virBufferAsprintf(&buf, "vcpus=%s", nodeVcpus);
|
|
|
c1c534 |
+ xenFormatXLVnode(numaVnode, &buf;;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ /* distances */
|
|
|
c1c534 |
+ virBufferAddLit(&buf, "vdistances=");
|
|
|
c1c534 |
+ for (i = 0; i < nr_nodes; i++) {
|
|
|
c1c534 |
+ virBufferAsprintf(&buf, "%zu",
|
|
|
c1c534 |
+ virDomainNumaGetNodeDistance(numa, node, i));
|
|
|
c1c534 |
+ if ((nr_nodes - i) > 1)
|
|
|
c1c534 |
+ virBufferAddLit(&buf, ",");
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+ xenFormatXLVnode(numaVnode, &buf;;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ tmp = list->list;
|
|
|
c1c534 |
+ while (tmp && tmp->next)
|
|
|
c1c534 |
+ tmp = tmp->next;
|
|
|
c1c534 |
+ if (tmp)
|
|
|
c1c534 |
+ tmp->next = numaVnode;
|
|
|
c1c534 |
+ else
|
|
|
c1c534 |
+ list->list = numaVnode;
|
|
|
c1c534 |
+ ret = 0;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ cleanup:
|
|
|
c1c534 |
+ VIR_FREE(nodeVcpus);
|
|
|
c1c534 |
+ return ret;
|
|
|
c1c534 |
+}
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+static int
|
|
|
c1c534 |
+xenFormatXLDomainVnuma(virConfPtr conf,
|
|
|
c1c534 |
+ virDomainDefPtr def)
|
|
|
c1c534 |
+{
|
|
|
c1c534 |
+ virDomainNumaPtr numa = def->numa;
|
|
|
c1c534 |
+ virConfValuePtr vnumaVal;
|
|
|
c1c534 |
+ size_t i;
|
|
|
c1c534 |
+ size_t nr_nodes;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (numa == NULL)
|
|
|
c1c534 |
+ return -1;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (VIR_ALLOC(vnumaVal) < 0)
|
|
|
c1c534 |
+ return -1;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ vnumaVal->type = VIR_CONF_LIST;
|
|
|
c1c534 |
+ vnumaVal->list = NULL;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ nr_nodes = virDomainNumaGetNodeCount(numa);
|
|
|
c1c534 |
+ for (i = 0; i < nr_nodes; i++) {
|
|
|
c1c534 |
+ if (xenFormatXLVnuma(vnumaVal, numa, i, nr_nodes) < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (vnumaVal->list != NULL) {
|
|
|
c1c534 |
+ int ret = virConfSetValue(conf, "vnuma", vnumaVal);
|
|
|
c1c534 |
+ vnumaVal = NULL;
|
|
|
c1c534 |
+ if (ret < 0)
|
|
|
c1c534 |
+ return -1;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
+ VIR_FREE(vnumaVal);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ return 0;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ cleanup:
|
|
|
c1c534 |
+ virConfFreeValue(vnumaVal);
|
|
|
c1c534 |
+ return -1;
|
|
|
c1c534 |
+}
|
|
|
c1c534 |
+#endif
|
|
|
c1c534 |
|
|
|
c1c534 |
static char *
|
|
|
c1c534 |
xenFormatXLDiskSrcNet(virStorageSourcePtr src)
|
|
|
c1c534 |
@@ -1642,6 +1972,11 @@ xenFormatXL(virDomainDefPtr def, virConnectPtr conn)
|
|
|
c1c534 |
if (xenFormatXLOS(conf, def) < 0)
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
|
|
|
c1c534 |
+#ifdef LIBXL_HAVE_VNUMA
|
|
|
c1c534 |
+ if (xenFormatXLDomainVnuma(conf, def) < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+#endif
|
|
|
c1c534 |
+
|
|
|
c1c534 |
if (xenFormatXLDomainDisks(conf, def) < 0)
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
|
|
|
c1c534 |
--
|
|
|
c1c534 |
2.15.1
|
|
|
c1c534 |
|