[libvirt] [PATCH 1/3] caps: Add helpers to convert NUMA nodes to corresponding CPUs

Peter Krempa pkrempa at redhat.com
Thu Jul 18 10:49:33 UTC 2013


These helpers use the remembered host capabilities to retrieve the cpu
map rather than query the host again. The intended usage for this
helpers is to fix automatic NUMA placement with strict memory alloc. The
code doing the prepare needs to pin the emulator process only to cpus
belonging to a subset of NUMA nodes of the host.
---
 po/POTFILES.in           |  1 +
 src/conf/capabilities.c  | 64 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/conf/capabilities.h  |  2 ++
 src/libvirt_private.syms |  1 +
 4 files changed, 68 insertions(+)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0b65765..0770b8f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -8,6 +8,7 @@ gnulib/lib/gai_strerror.c
 gnulib/lib/regcomp.c
 src/access/viraccessdriverpolkit.c
 src/access/viraccessmanager.c
+src/conf/capabilities.c
 src/conf/cpu_conf.c
 src/conf/device_conf.c
 src/conf/domain_conf.c
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index bb5fe4e..1acc936 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -916,3 +916,67 @@ virCapabilitiesFormatXML(virCapsPtr caps)

     return virBufferContentAndReset(&xml);
 }
+
+/* get the maximum ID of cpus in the host */
+static unsigned int
+virCapabilitiesGetHostMaxcpu(virCapsPtr caps)
+{
+    unsigned int maxcpu = 0;
+    size_t node;
+    size_t cpu;
+
+    for (node = 0; node < caps->host.nnumaCell; node++) {
+        virCapsHostNUMACellPtr cell = caps->host.numaCell[node];
+
+        for (cpu = 0; cpu < cell->ncpus; cpu++) {
+            if (cell->cpus[cpu].id > maxcpu)
+                maxcpu = cell->cpus[cpu].id;
+        }
+    }
+
+    return maxcpu;
+}
+
+/* set cpus of a numa node in the bitmask */
+static int
+virCapabilitiesGetCpusForNode(virCapsPtr caps,
+                              size_t node,
+                              virBitmapPtr cpumask)
+{
+    virCapsHostNUMACellPtr cell = caps->host.numaCell[node];
+    size_t cpu;
+
+    for (cpu = 0; 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 "
+                             "of the provided bitmap"),
+                           cell->cpus[cpu].id, node);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+virBitmapPtr
+virCapabilitiesGetCpusForNodemask(virCapsPtr caps,
+                                  virBitmapPtr nodemask)
+{
+    virBitmapPtr ret = NULL;
+    unsigned int maxcpu = virCapabilitiesGetHostMaxcpu(caps);
+    ssize_t node = -1;
+
+    if (!(ret = virBitmapNew(maxcpu + 1)))
+        return NULL;
+
+
+    while ((node = virBitmapNextSetBit(nodemask, node)) >= 0) {
+        if (virCapabilitiesGetCpusForNode(caps, node, ret) < 0) {
+            virBitmapFree(ret);
+            return NULL;
+        }
+    }
+
+    return ret;
+}
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index 6c7efde..88ec454 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -257,5 +257,7 @@ virCapabilitiesDefaultGuestEmulator(virCapsPtr caps,
 extern char *
 virCapabilitiesFormatXML(virCapsPtr caps);

+virBitmapPtr virCapabilitiesGetCpusForNodemask(virCapsPtr caps,
+                                               virBitmapPtr nodemask);

 #endif /* __VIR_CAPABILITIES_H */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index fc4e750..d07ceaa 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -57,6 +57,7 @@ virCapabilitiesDefaultGuestMachine;
 virCapabilitiesFormatXML;
 virCapabilitiesFreeMachines;
 virCapabilitiesFreeNUMAInfo;
+virCapabilitiesGetCpusForNodemask;
 virCapabilitiesNew;
 virCapabilitiesSetHostCPU;

-- 
1.8.3.2




More information about the libvir-list mailing list