Since qemu has supported '-numa memdev=ram0' command option, so libvirt
should add numa element to support specified memdev attrubute in XML.
Signed-off-by: Chen Fan <chen.fan.fnst(a)cn.fujitsu.com>
---
src/conf/cpu_conf.c | 73 +++++++++++++++++++++++++++++++++++++++----------
src/conf/cpu_conf.h | 13 ++++++++-
src/qemu/qemu_command.c | 10 +++++--
3 files changed, 78 insertions(+), 18 deletions(-)
diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
index ebdaa19..2d0980e 100644
--- a/src/conf/cpu_conf.c
+++ b/src/conf/cpu_conf.c
@@ -29,6 +29,7 @@
#include "cpu_conf.h"
#include "domain_conf.h"
#include "virstring.h"
+#include "c-ctype.h"
#define VIR_FROM_THIS VIR_FROM_CPU
@@ -84,6 +85,8 @@ virCPUDefFree(virCPUDefPtr def)
for (i = 0; i < def->ncells; i++) {
virBitmapFree(def->cells[i].cpumask);
VIR_FREE(def->cells[i].cpustr);
+ if (def->cells[i].memtype == VIR_CPU_CELL_MEMORY_DEV)
+ VIR_FREE(def->cells[i].data.memstr);
}
VIR_FREE(def->cells);
VIR_FREE(def->vendor_id);
@@ -153,7 +156,13 @@ virCPUDefCopy(const virCPUDef *cpu)
for (i = 0; i < cpu->ncells; i++) {
copy->cells[i].cellid = cpu->cells[i].cellid;
- copy->cells[i].mem = cpu->cells[i].mem;
+ copy->cells[i].memtype = cpu->cells[i].memtype;
+ if (cpu->cells[i].memtype == VIR_CPU_CELL_MEMORY_DEV) {
+ if (VIR_STRDUP(copy->cells[i].data.memstr,
cpu->cells[i].data.memstr) < 0)
+ goto error;
+ } else {
+ copy->cells[i].data.mem = cpu->cells[i].data.mem;
+ }
copy->cells[i].cpumask = virBitmapNewCopy(cpu->cells[i].cpumask);
@@ -436,7 +445,7 @@ virCPUDefParseXML(xmlNodePtr node,
def->ncells = n;
for (i = 0; i < n; i++) {
- char *cpus, *memory;
+ char *cpus, *memory, *memdev;
int ret, ncpus = 0;
def->cells[i].cellid = i;
@@ -455,20 +464,52 @@ virCPUDefParseXML(xmlNodePtr node,
def->cells_cpus += ncpus;
memory = virXMLPropString(nodes[i], "memory");
- if (!memory) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("Missing 'memory' attribute in NUMA
cell"));
- goto error;
- }
-
- ret = virStrToLong_ui(memory, NULL, 10, &def->cells[i].mem);
- if (ret == -1) {
+ memdev = virXMLPropString(nodes[i], "memdev");
+ if (memory || memdev) {
+ if (memory && memdev) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Both 'memory' and 'memdev'
attribute in NUMA cell is not allowed"));
+ goto error;
+ }
+
+ if (memory) {
+ ret = virStrToLong_ui(memory, NULL, 10,
&def->cells[i].data.mem);
+ if (ret == -1) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Invalid 'memory' attribute in NUMA
cell"));
+ VIR_FREE(memory);
+ goto error;
+ }
+ def->cells[i].memtype = VIR_CPU_CELL_MEMORY_SIZE;
+ VIR_FREE(memory);
+ } else {
+ if (strlen(memdev) < 1) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Empty 'memdev' attribute in NUMA
cell"));
+ VIR_FREE(memdev);
+ goto error;
+ }
+
+ if (!c_isalpha(memdev[0])) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Invalid 'memdev' attribute name in
NUMA cell, "
+ "it must begin with a letter"));
+ VIR_FREE(memdev);
+ goto error;
+ }
+
+ if (VIR_STRDUP(def->cells[i].data.memstr, memdev) < 0) {
+ VIR_FREE(memdev);
+ goto error;
+ }
+ def->cells[i].memtype = VIR_CPU_CELL_MEMORY_DEV;
+ VIR_FREE(memdev);
+ }
+ } else {
virReportError(VIR_ERR_XML_ERROR, "%s",
- _("Invalid 'memory' attribute in NUMA
cell"));
- VIR_FREE(memory);
+ _("Missing 'memory' or 'memdev'
attribute in NUMA cell"));
goto error;
}
- VIR_FREE(memory);
}
}
@@ -648,7 +689,11 @@ virCPUDefFormatBuf(virBufferPtr buf,
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);
+ if (def->cells[i].memtype == VIR_CPU_CELL_MEMORY_DEV) {
+ virBufferAsprintf(buf, " memdev='%s'",
def->cells[i].data.memstr);
+ } else {
+ virBufferAsprintf(buf, " memory='%d'",
def->cells[i].data.mem);
+ }
virBufferAddLit(buf, "/>\n");
}
virBufferAdjustIndent(buf, -2);
diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h
index 8c932ce..b1ebd9c 100644
--- a/src/conf/cpu_conf.h
+++ b/src/conf/cpu_conf.h
@@ -90,13 +90,24 @@ struct _virCPUFeatureDef {
int policy; /* enum virCPUFeaturePolicy */
};
+typedef enum {
+ VIR_CPU_CELL_MEMORY_SIZE,
+ VIR_CPU_CELL_MEMORY_DEV,
+
+ VIR_CPU_CELL_MEMORY_LAST
+} virCPUCellMemoryType;
+
typedef struct _virCellDef virCellDef;
typedef virCellDef *virCellDefPtr;
struct _virCellDef {
int cellid;
virBitmapPtr cpumask; /* CPUs that are part of this node */
char *cpustr; /* CPUs stored in string form for dumpxml */
- unsigned int mem; /* Node memory in kB */
+ int memtype;
+ union {
+ char *memstr; /* Node memory device name */
+ unsigned int mem; /* Node memory in kB */
+ } data;
};
typedef struct _virCPUDef virCPUDef;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2caee66..b351f60 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6560,9 +6560,13 @@ qemuBuildNumaArgStr(const virDomainDef *def, virCommandPtr cmd)
goto cleanup;
}
virBufferAdd(&buf, cpumask, -1);
- def->cpu->cells[i].mem = VIR_DIV_UP(def->cpu->cells[i].mem,
- 1024) * 1024;
- virBufferAsprintf(&buf, ",mem=%d", def->cpu->cells[i].mem /
1024);
+ if (def->cpu->cells[i].memtype == VIR_CPU_CELL_MEMORY_DEV) {
+ virBufferAsprintf(&buf, ",memdev=%s",
def->cpu->cells[i].data.memstr);
+ } else {
+ def->cpu->cells[i].data.mem =
VIR_DIV_UP(def->cpu->cells[i].data.mem,
+ 1024) * 1024;
+ virBufferAsprintf(&buf, ",mem=%d",
def->cpu->cells[i].data.mem / 1024);
+ }
if (virBufferError(&buf)) {
virReportOOMError();
--
1.9.3