On some platforms like IBM PowerNV the NUMA node numbers can be
non-sequential. For eg. numactl --hardware o/p from such a machine looks
as given below
node distances:
node 0 1 16 17
0: 10 40 40 40
1: 40 10 40 40
16: 40 40 10 40
17: 40 40 40 10
The NUMA nodes are 0,1,16,17
Libvirt uses sequential index as NUMA node numbers and this can
result in crash or incorrect results.
Signed-off-by: Shivaprasad G Bhat <sbhat(a)linux.vnet.ibm.com>
Signed-off-by: Pradipta Kr. Banerjee <bpradip(a)in.ibm.com>
---
src/conf/capabilities.c | 12 ++++++++++--
src/qemu/qemu_driver.c | 5 +++--
src/qemu/qemu_process.c | 2 +-
3 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index 726ec3f..78f65cb 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -1000,10 +1000,18 @@ virCapabilitiesGetCpusForNode(virCapsPtr caps,
size_t node,
virBitmapPtr cpumask)
{
- virCapsHostNUMACellPtr cell = caps->host.numaCell[node];
+ virCapsHostNUMACellPtr cell = NULL;
size_t cpu;
+ size_t index;
+ /* The numa node numbers can be non-contiguous. Ex: 0,1,16,17. */
+ for (index = 0; index < caps->host.nnumaCell; index++) {
+ if (caps->host.numaCell[index]->num == node) {
+ cell = caps->host.numaCell[index];
+ break;
+ }
+ }
- for (cpu = 0; cpu < cell->ncpus; cpu++) {
+ for (cpu = 0; cell && cpu < cell->ncpus; cpu++) {
if (virBitmapSetBit(cpumask, cell->cpus[cpu].id) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Cpu '%u' in node '%zu' is out of range
"
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 944facb..cb63b60 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -8566,12 +8566,13 @@ qemuDomainSetNumaParamsLive(virDomainObjPtr vm,
for (i = 0; i < caps->host.nnumaCell; i++) {
bool result;
- if (virBitmapGetBit(nodeset, i, &result) < 0) {
+ virCapsHostNUMACellPtr cell = caps->host.numaCell[i];
+ if (virBitmapGetBit(nodeset, cell->num, &result) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Failed to get cpuset bit values"));
goto cleanup;
}
- if (result && (virBitmapSetBit(temp_nodeset, i) < 0)) {
+ if (result && (virBitmapSetBit(temp_nodeset, cell->num) < 0)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Failed to set temporary cpuset bit values"));
goto cleanup;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 8bcd98e..c28f84d 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2002,7 +2002,7 @@ qemuPrepareCpumap(virQEMUDriverPtr driver,
size_t j;
int cur_ncpus = caps->host.numaCell[i]->ncpus;
bool result;
- if (virBitmapGetBit(nodemask, i, &result) < 0) {
+ if (virBitmapGetBit(nodemask, caps->host.numaCell[i]->num, &result)
< 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Failed to convert nodeset to cpuset"));
virBitmapFree(cpumap);
--
1.8.5.3