diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c88b032c2b..e5e0167262 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -6300,8 +6300,9 @@ qemu-kvm -net nic,model=? /dev/null added memory as a scaled integer.

- The mandatory node subelement configures the guest NUMA - node to attach the memory to. + The node subelement configures the guest NUMA node to + attach the memory to. The element shall be used only if the guest has + NUMA nodes configured.

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index f1961773c8..994faceec7 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4532,9 +4532,11 @@ - - - + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index eb0044449a..0ac7dbf249 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -12544,10 +12544,15 @@ virDomainMemoryTargetDefParseXML(xmlNodePtr node, int ret = -1; xmlNodePtr save = ctxt->node; ctxt->node = node; + int rv; - if (virXPathUInt("string(./node)", ctxt, &def->targetNode) < 0) { + /* initialize to value which marks that the user didn't specify it */ + def->targetNode = -1; + + if ((rv = virXPathInt("string(./node)", ctxt, &def->targetNode)) == -2 || + (rv == 0 && def->targetNode < 0)) { virReportError(VIR_ERR_XML_ERROR, "%s", - _("invalid or missing value of memory device node")); + _("invalid value of memory device node")); goto cleanup; } @@ -17711,8 +17716,8 @@ virDomainMemoryDefCheckABIStability(virDomainMemoryDefPtr src, if (src->targetNode != dst->targetNode) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Target memory device targetNode '%u' " - "doesn't match source targetNode '%u'"), + _("Target memory device targetNode '%d' " + "doesn't match source targetNode '%d'"), dst->targetNode, src->targetNode); return false; } @@ -20802,7 +20807,8 @@ virDomainMemoryTargetDefFormat(virBufferPtr buf, virBufferAdjustIndent(buf, 2); virBufferAsprintf(buf, "%llu\n", def->size); - virBufferAsprintf(buf, "%u\n", def->targetNode); + if (def->targetNode >= 0) + virBufferAsprintf(buf, "%d\n", def->targetNode); virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "\n"); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f10b5348b7..8d43ee65d8 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2022,7 +2022,7 @@ struct _virDomainMemoryDef { /* target */ int model; /* virDomainMemoryModel */ - unsigned int targetNode; + int targetNode; unsigned long long size; /* kibibytes */ virDomainDeviceInfo info; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 507d44695f..52488ab08d 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3597,6 +3597,13 @@ qemuDomainDefValidateMemoryHotplugDevice(const virDomainMemoryDef *mem, return -1; } + if (mem->targetNode == -1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("target NUMA node needs to be specified for " + "memory device")); + return -1; + } + if (mem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM) { if (mem->info.addr.dimm.slot >= def->mem.memory_slots) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED,