[libvirt] [PATCHv2 09/10] numa: Add wrapper of numa_node_to_cpus and use it

Peter Krempa pkrempa at redhat.com
Fri Oct 18 15:05:49 UTC 2013


---
 src/nodeinfo.c     | 62 ++++++++++++++-----------------------
 src/util/virnuma.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/util/virnuma.h |  2 ++
 3 files changed, 117 insertions(+), 38 deletions(-)

diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index 4f0d412..7e75611 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -1513,11 +1513,6 @@ nodeGetFreeMemoryFake(void)
 }

 #if WITH_NUMACTL
-
-# define n_bits(var) (8 * sizeof(var))
-# define MASK_CPU_ISSET(mask, cpu) \
-  (((mask)[((cpu) / n_bits(*(mask)))] >> ((cpu) % n_bits(*(mask)))) & 1)
-
 static virBitmapPtr
 virNodeGetSiblingsList(const char *dir, int cpu_id)
 {
@@ -1570,14 +1565,12 @@ int
 nodeCapsInitNUMA(virCapsPtr caps)
 {
     int n;
-    unsigned long *mask = NULL;
-    unsigned long *allonesmask = NULL;
     unsigned long long memory;
     virCapsHostNUMACellCPUPtr cpus = NULL;
+    virBitmapPtr cpumap = NULL;
     int ret = -1;
-    int max_n_cpus = virNumaGetMaxCPUs();
-    int mask_n_bytes = max_n_cpus / 8;
     int ncpus = 0;
+    int cpu;
     bool topology_failed = false;
     int max_node;

@@ -1587,49 +1580,41 @@ nodeCapsInitNUMA(virCapsPtr caps)
     if ((max_node = virNumaGetMaxNode()) < 0)
         goto cleanup;

-    if (VIR_ALLOC_N(mask, mask_n_bytes / sizeof(*mask)) < 0)
-        goto cleanup;
-    if (VIR_ALLOC_N(allonesmask, mask_n_bytes / sizeof(*mask)) < 0)
-        goto cleanup;
-    memset(allonesmask, 0xff, mask_n_bytes);
-
     for (n = 0; n <= max_node; n++) {
         size_t i;
-        /* The first time this returns -1, ENOENT if node doesn't exist... */
-        if (numa_node_to_cpus(n, mask, mask_n_bytes) < 0) {
-            VIR_WARN("NUMA topology for cell %d of %d not available, ignoring",
-                     n, max_node + 1);
-            continue;
-        }
-        /* second, third... times it returns an all-1's mask */
-        if (memcmp(mask, allonesmask, mask_n_bytes) == 0) {
-            VIR_DEBUG("NUMA topology for cell %d of %d is all ones, ignoring",
-                      n, max_node + 1);
-            continue;
-        }

-        /* Detect the amount of memory in the numa cell in KiB */
-        virNumaGetNodeMemory(n, &memory, NULL);
-        memory >>= 10;
+        if ((ncpus = virNumaGetNodeCPUs(n, &cpumap)) < 0) {
+            if (ncpus == -2)
+                continue;

-        for (ncpus = 0, i = 0; i < max_n_cpus; i++)
-            if (MASK_CPU_ISSET(mask, i))
-                ncpus++;
+            goto cleanup;
+        }

         if (VIR_ALLOC_N(cpus, ncpus) < 0)
             goto cleanup;
+        cpu = 0;

-        for (ncpus = 0, i = 0; i < max_n_cpus; i++) {
-            if (MASK_CPU_ISSET(mask, i)) {
-                if (virNodeCapsFillCPUInfo(i, cpus + ncpus++) < 0) {
+        for (i = 0; i < virBitmapSize(cpumap); i++) {
+            bool cpustate;
+            if (virBitmapGetBit(cpumap, i, &cpustate) < 0)
+                continue;
+
+            if (cpustate) {
+                if (virNodeCapsFillCPUInfo(i, cpus + cpu++) < 0) {
                     topology_failed = true;
                     virResetLastError();
                 }
             }
         }

+        /* Detect the amount of memory in the numa cell in KiB */
+        virNumaGetNodeMemory(n, &memory, NULL);
+        memory >>= 10;
+
         if (virCapabilitiesAddHostNUMACell(caps, n, ncpus, memory, cpus) < 0)
             goto cleanup;
+
+        cpus = NULL;
     }

     ret = 0;
@@ -1638,11 +1623,12 @@ cleanup:
     if (topology_failed || ret < 0)
         virCapabilitiesClearHostNUMACellCPUTopology(cpus, ncpus);

+    virBitmapFree(cpumap);
+    VIR_FREE(cpus);
+
     if (ret < 0)
         VIR_FREE(cpus);

-    VIR_FREE(mask);
-    VIR_FREE(allonesmask);
     return ret;
 }

diff --git a/src/util/virnuma.c b/src/util/virnuma.c
index 0530d64..ab46591 100644
--- a/src/util/virnuma.c
+++ b/src/util/virnuma.c
@@ -38,6 +38,8 @@
 #include "vircommand.h"
 #include "virerror.h"
 #include "virlog.h"
+#include "viralloc.h"
+#include "virbitmap.h"

 #define VIR_FROM_THIS VIR_FROM_NONE

@@ -249,6 +251,83 @@ virNumaGetNodeMemory(int node,

     return 0;
 }
+
+
+/**
+ * virNumaGetNodeCPUs:
+ * @node: identifier of the requested NUMA node
+ * @cpus: returns a bitmap of CPUs in @node
+ *
+ * Returns count of CPUs in the selected node and sets the map of the cpus to
+ * @cpus. On error if the @node doesn't exist in the system this function
+ * returns -2 and sets @cpus to NULL. On other errors -1 is returned, @cpus
+ * is set to NULL and an error is reported.
+ */
+
+# define n_bits(var) (8 * sizeof(var))
+# define MASK_CPU_ISSET(mask, cpu) \
+  (((mask)[((cpu) / n_bits(*(mask)))] >> ((cpu) % n_bits(*(mask)))) & 1)
+int
+virNumaGetNodeCPUs(int node,
+                   virBitmapPtr *cpus)
+{
+    unsigned long *mask = NULL;
+    unsigned long *allonesmask = NULL;
+    virBitmapPtr cpumap = NULL;
+    int ncpus = 0;
+    int max_n_cpus = virNumaGetMaxCPUs();
+    int mask_n_bytes = max_n_cpus / 8;
+    size_t i;
+    int ret = -1;
+
+    *cpus = NULL;
+
+    if (VIR_ALLOC_N(mask, mask_n_bytes / sizeof(*mask)) < 0)
+        goto cleanup;
+
+    if (VIR_ALLOC_N(allonesmask, mask_n_bytes / sizeof(*mask)) < 0)
+        goto cleanup;
+
+    memset(allonesmask, 0xff, mask_n_bytes);
+
+    /* The first time this returns -1, ENOENT if node doesn't exist... */
+    if (numa_node_to_cpus(node, mask, mask_n_bytes) < 0) {
+        VIR_WARN("NUMA topology for cell %d is not available, ignoring", node);
+        ret = -2;
+        goto cleanup;
+    }
+
+    /* second, third... times it returns an all-1's mask */
+    if (memcmp(mask, allonesmask, mask_n_bytes) == 0) {
+        VIR_DEBUG("NUMA topology for cell %d is invalid, ignoring", node);
+        ret = -2;
+        goto cleanup;
+    }
+
+    if (!(cpumap = virBitmapNew(max_n_cpus)))
+        goto cleanup;
+
+    for (i = 0; i < max_n_cpus; i++) {
+        if (MASK_CPU_ISSET(mask, i)) {
+            ignore_value(virBitmapSetBit(cpumap, i));
+            ncpus++;
+        }
+    }
+
+    *cpus = cpumap;
+    cpumap = NULL;
+    ret = ncpus;
+
+cleanup:
+    VIR_FREE(mask);
+    VIR_FREE(allonesmask);
+    VIR_FREE(cpumap);
+
+    return ret;
+}
+# undef MASK_CPU_ISSET
+# undef n_bits
+
 #else
 int
 virNumaSetupMemoryPolicy(virNumaTuneDef numatune,
@@ -295,6 +374,18 @@ virNumaGetNodeMemory(int node ATTRIBUTE_UNUSED,
     VIR_DEBUG("NUMA isn't available on this host");
     return -1;
 }
+
+
+int
+virNumaGetNodeCPUs(int node ATTRIBUTE_UNUSED,
+                   virBitmapPtr *cpus)
+{
+    *cpus = NULL;
+
+    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                   _("NUMA isn't available on this host"));
+    return -1;
+}
 #endif


diff --git a/src/util/virnuma.h b/src/util/virnuma.h
index 62b2c0a..eee0225 100644
--- a/src/util/virnuma.h
+++ b/src/util/virnuma.h
@@ -64,4 +64,6 @@ int virNumaGetNodeMemory(int node,

 unsigned int virNumaGetMaxCPUs(void);

+int virNumaGetNodeCPUs(int node, virBitmapPtr *cpus);
+
 #endif /* __VIR_NUMA_H__ */
-- 
1.8.3.2




More information about the libvir-list mailing list