提交 5f7b71b4 编写于 作者: B Bharata B Rao 提交者: Eric Blake

XML definitions for guest NUMA and parsing routines

This patch adds XML definitions for guest NUMA specification and contains
routines to parse the same. The guest NUMA specification looks like this:

<cpu>
        ...
        <topology sockets='2' cores='4' threads='2'/>
        <numa>
                <cell cpus='0-7' memory='512000'/>
                <cell cpus='8-15' memory='512000'/>
        </numa>
        ...
</cpu>
Signed-off-by: NBharata B Rao <bharata@linux.vnet.ibm.com>
上级 c74b9715
......@@ -205,6 +205,7 @@ Patches have also been contributed by:
Patrice LACHANCE <patlachance@gmail.com>
Eli Qiao <taget@linux.vnet.ibm.com>
Michael Wood <esiotrot@gmail.com>
Bharata B Rao <bharata@linux.vnet.ibm.com>
[....send patches to get your name here....]
......
......@@ -628,6 +628,35 @@
</dd>
</dl>
<p>
Guest NUMA topology can be specifed using the <code>numa</code> element.
<span class="since">Since 0.9.8</span>
</p>
<pre>
...
&lt;cpu&gt;
...
&lt;numa&gt;
&lt;cell cpus='0-3' memory='512000'/&gt;
&lt;cell cpus='4-7' memory='512000'/&gt;
&lt;/numa&gt;
...
&lt;/cpu&gt;
...</pre>
<p>
Each <code>cell</code> element specifies a NUMA cell or a NUMA node.
<code>cpus</code> specifies the CPU or range of CPUs that are part of
the node. <code>memory</code> specifies the node memory in kilobytes
(i.e. blocks of 1024 bytes). Each cell or node is assigned cellid
or nodeid in the increasing order starting from 0.
</p>
<p>
This guest NUMA specification is currently available only for QEMU/KVM.
</p>
<h3><a name="elementsLifecycle">Lifecycle control</a></h3>
<p>
......
......@@ -2297,7 +2297,16 @@
<define name="cpu">
<element name="cpu">
<choice>
<ref name="cpuTopology"/>
<group>
<interleave>
<optional>
<ref name="cpuTopology"/>
</optional>
<optional>
<ref name="cpuNuma"/>
</optional>
</interleave>
</group>
<group>
<ref name="cpuMatch"/>
<interleave>
......@@ -2311,6 +2320,9 @@
<zeroOrMore>
<ref name="cpuFeature"/>
</zeroOrMore>
<optional>
<ref name="cpuNuma"/>
</optional>
</interleave>
</group>
</choice>
......@@ -2371,6 +2383,25 @@
</element>
</define>
<define name="cpuNuma">
<element name="numa">
<oneOrMore>
<ref name="numaCell"/>
</oneOrMore>
</element>
</define>
<define name="numaCell">
<element name="cell">
<attribute name="cpus">
<ref name="cpuset"/>
</attribute>
<attribute name="memory">
<ref name="memoryKB"/>
</attribute>
</element>
</define>
<!--
System information specification:
Placeholder for system specific informations likes the ones
......
......@@ -28,6 +28,7 @@
#include "util.h"
#include "buf.h"
#include "cpu_conf.h"
#include "domain_conf.h"
#define VIR_FROM_THIS VIR_FROM_CPU
......@@ -67,6 +68,12 @@ virCPUDefFree(virCPUDefPtr def)
VIR_FREE(def->features[i].name);
VIR_FREE(def->features);
for (i = 0 ; i < def->ncells ; i++) {
VIR_FREE(def->cells[i].cpumask);
VIR_FREE(def->cells[i].cpustr);
}
VIR_FREE(def->cells);
VIR_FREE(def);
}
......@@ -109,7 +116,6 @@ no_memory:
return NULL;
}
virCPUDefPtr
virCPUDefParseXML(const xmlNodePtr node,
xmlXPathContextPtr ctxt,
......@@ -289,9 +295,75 @@ virCPUDefParseXML(const xmlNodePtr node,
def->features[i].policy = policy;
}
if (virXPathNode("./numa[1]", ctxt)) {
VIR_FREE(nodes);
n = virXPathNodeSet("./numa[1]/cell", ctxt, &nodes);
if (n <= 0) {
virCPUReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("NUMA topology defined without NUMA cells"));
goto error;
}
if (VIR_RESIZE_N(def->cells, def->ncells_max,
def->ncells, n) < 0)
goto no_memory;
def->ncells = n;
for (i = 0 ; i < n ; i++) {
char *cpus, *cpus_parse, *memory;
int cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
int ret, ncpus = 0;
def->cells[i].cellid = i;
cpus = cpus_parse = virXMLPropString(nodes[i], "cpus");
if (!cpus) {
virCPUReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("Missing 'cpus' attribute in NUMA cell"));
goto error;
}
def->cells[i].cpustr = strdup(cpus);
if (!def->cells[i].cpustr) {
VIR_FREE(cpus);
goto no_memory;
}
if (VIR_ALLOC_N(def->cells[i].cpumask, cpumasklen) < 0) {
VIR_FREE(cpus);
goto no_memory;
}
ncpus = virDomainCpuSetParse((const char **)&cpus_parse,
0, def->cells[i].cpumask, cpumasklen);
if (ncpus <= 0) {
VIR_FREE(cpus);
goto error;
}
def->cells_cpus += ncpus;
memory = virXMLPropString(nodes[i], "memory");
if (!memory) {
virCPUReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("Missing 'memory' attribute in NUMA cell"));
VIR_FREE(cpus);
goto error;
}
ret = virStrToLong_ui(memory, NULL, 10, &def->cells[i].mem);
if (ret == -1) {
VIR_FREE(cpus);
VIR_FREE(memory);
goto error;
}
VIR_FREE(cpus);
VIR_FREE(memory);
}
}
cleanup:
VIR_FREE(nodes);
return def;
no_memory:
......@@ -414,6 +486,16 @@ virCPUDefFormatBuf(virBufferPtr buf,
}
}
if (def->ncells) {
virBufferAddLit(buf, "<numa>\n");
for (i = 0; i < def->ncells; i++) {
virBufferAddLit(buf, " <cell");
virBufferAsprintf(buf, " cpus='%s'", def->cells[i].cpustr);
virBufferAsprintf(buf, " memory='%d'", def->cells[i].mem);
virBufferAddLit(buf, "/>\n");
}
virBufferAddLit(buf, "</numa>\n");
}
return 0;
}
......
......@@ -67,6 +67,15 @@ struct _virCPUFeatureDef {
int policy; /* enum virCPUFeaturePolicy */
};
typedef struct _virCellDef virCellDef;
typedef virCellDef *virCellDefPtr;
struct _virCellDef {
int cellid;
char *cpumask; /* CPUs that are part of this node */
char *cpustr; /* CPUs stored in string form for dumpxml */
unsigned int mem; /* Node memory in kB */
};
typedef struct _virCPUDef virCPUDef;
typedef virCPUDef *virCPUDefPtr;
struct _virCPUDef {
......@@ -81,6 +90,10 @@ struct _virCPUDef {
size_t nfeatures;
size_t nfeatures_max;
virCPUFeatureDefPtr features;
size_t ncells;
size_t ncells_max;
virCellDefPtr cells;
unsigned int cells_cpus;
};
......
......@@ -7572,6 +7572,13 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
if (def->cpu == NULL)
goto error;
if (def->cpu->cells_cpus > def->maxvcpus) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Number of CPUs in <numa> exceeds the"
" <vcpu> count"));
goto error;
}
}
if ((node = virXPathNode("./sysinfo[1]", ctxt)) != NULL) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册