<cpu>
...
<numa>
- <cell cpus='0-3' memory='512000'/>
- <cell cpus='4-7' memory='512000'/>
+ <cell id='0' cpus='0-3' memory='512000'/>
+ <cell id='1' cpus='4-7' memory='512000'/>
</numa>
...
</cpu>
<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 kibibytes
- (i.e. blocks of 1024 bytes). Each cell or node is assigned cellid
- or nodeid in the increasing order starting from 0.
+ <code>cpus</code> specifies the CPU or range of CPUs that are
+ part of the node. <code>memory</code> specifies the node memory
+ in kibibytes (i.e. blocks of 1024 bytes).
+ <span class="since">Since 1.2.7</span> all cells should
+ have <code>id</code> attribute in case referring to some cell is
+ necessary in the code, otherwise the cells are
+ assigned <code>id</code>s in the increasing order starting from
+ 0. Mixing cells with and without the <code>id</code> attribute
+ is not recommended as it may result in unwanted behaviour.
</p>
<p>
<define name="numaCell">
<element name="cell">
+ <optional>
+ <attribute name="id">
+ <ref name="unsignedInt"/>
+ </attribute>
+ </optional>
<attribute name="cpus">
<ref name="cpuset"/>
</attribute>
copy->ncells_max = copy->ncells = cpu->ncells;
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].cpumask = virBitmapNewCopy(cpu->cells[i].cpumask);
for (i = 0; i < n; i++) {
char *cpus, *memory;
int ret, ncpus = 0;
+ unsigned int cur_cell;
+ char *tmp = NULL;
+
+ tmp = virXMLPropString(nodes[i], "id");
+ if (!tmp) {
+ cur_cell = i;
+ } else {
+ ret = virStrToLong_ui(tmp, NULL, 10, &cur_cell);
+ if (ret == -1) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid 'id' attribute in NUMA cell: %s"),
+ tmp);
+ VIR_FREE(tmp);
+ goto error;
+ }
+ VIR_FREE(tmp);
+ }
+
+ if (cur_cell >= n) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Exactly one 'cell' element per guest "
+ "NUMA cell allowed, non-contiguous ranges or "
+ "ranges not starting from 0 are not allowed"));
+ goto error;
+ }
+
+ if (def->cells[cur_cell].cpustr) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Duplicate NUMA cell info for cell id '%u'"),
+ cur_cell);
+ goto error;
+ }
- def->cells[i].cellid = i;
cpus = virXMLPropString(nodes[i], "cpus");
if (!cpus) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Missing 'cpus' attribute in NUMA cell"));
goto error;
}
- def->cells[i].cpustr = cpus;
+ def->cells[cur_cell].cpustr = cpus;
- ncpus = virBitmapParse(cpus, 0, &def->cells[i].cpumask,
+ ncpus = virBitmapParse(cpus, 0, &def->cells[cur_cell].cpumask,
VIR_DOMAIN_CPUMASK_LEN);
if (ncpus <= 0)
goto error;
goto error;
}
- ret = virStrToLong_ui(memory, NULL, 10, &def->cells[i].mem);
+ ret = virStrToLong_ui(memory, NULL, 10, &def->cells[cur_cell].mem);
if (ret == -1) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Invalid 'memory' attribute in NUMA cell"));
virBufferAdjustIndent(buf, 2);
for (i = 0; i < def->ncells; i++) {
virBufferAddLit(buf, "<cell");
+ virBufferAsprintf(buf, " id='%zu'", i);
virBufferAsprintf(buf, " cpus='%s'", def->cells[i].cpustr);
virBufferAsprintf(buf, " memory='%d'", def->cells[i].mem);
virBufferAddLit(buf, "/>\n");
/*
* cpu_conf.h: CPU XML handling
*
- * Copyright (C) 2009-2011, 2013 Red Hat, Inc.
+ * Copyright (C) 2009-2011, 2013, 2014 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
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 */
}
virCommandAddArg(cmd, "-numa");
- virBufferAsprintf(&buf, "node,nodeid=%d", def->cpu->cells[i].cellid);
+ virBufferAsprintf(&buf, "node,nodeid=%zu", i);
virBufferAddLit(&buf, ",cpus=");
/* Up through qemu 1.4, -numa does not accept a cpus
<boot dev='network'/>
</os>
<cpu>
- <topology sockets="2" cores="4" threads="2"/>
+ <topology sockets='2' cores='4' threads='2'/>
<numa>
- <cell cpus="0-7" memory="109550"/>
- <cell cpus="8-15" memory="109550"/>
+ <cell cpus='0-7' memory='109550'/>
+ <cell cpus='8-15' memory='109550'/>
</numa>
</cpu>
<clock offset='utc'/>
<boot dev='network'/>
</os>
<cpu>
- <topology sockets="2" cores="4" threads="2"/>
+ <topology sockets='2' cores='4' threads='2'/>
<numa>
- <cell cpus="0-7" memory="109550"/>
- <cell cpus="8-15" memory="109550"/>
+ <cell id='1' cpus='8-15' memory='109550'/>
+ <cell id='0' cpus='0-7' memory='109550'/>
</numa>
</cpu>
<clock offset='utc'/>
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>16</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='network'/>
+ </os>
+ <cpu>
+ <topology sockets='2' cores='4' threads='2'/>
+ <numa>
+ <cell id='1' cpus='0-7' memory='109550'/>
+ <cell id='2' cpus='8-15' memory='109550'/>
+ </numa>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ </devices>
+</domain>
DO_TEST("cpu-strict1", NONE);
DO_TEST("cpu-numa1", NONE);
DO_TEST("cpu-numa2", QEMU_CAPS_SMP_TOPOLOGY);
+ DO_TEST_PARSE_ERROR("cpu-numa3", NONE);
DO_TEST("cpu-host-model", NONE);
skipLegacyCPUs = true;
DO_TEST("cpu-host-model-fallback", NONE);
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>16</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='network'/>
+ </os>
+ <cpu>
+ <topology sockets='2' cores='4' threads='2'/>
+ <numa>
+ <cell id='0' cpus='0-7' memory='109550'/>
+ <cell id='1' cpus='8-15' memory='109550'/>
+ </numa>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <controller type='usb' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>16</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='network'/>
+ </os>
+ <cpu>
+ <topology sockets='2' cores='4' threads='2'/>
+ <numa>
+ <cell id='0' cpus='0-7' memory='109550'/>
+ <cell id='1' cpus='8-15' memory='109550'/>
+ </numa>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <controller type='usb' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
DO_TEST("chardev-label");
+ DO_TEST_DIFFERENT("cpu-numa1");
+ DO_TEST_DIFFERENT("cpu-numa2");
+
virObjectUnref(driver.caps);
virObjectUnref(driver.xmlopt);