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@xxxxxxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list