[libvirt] [PATCH] Create fake NUMA info if libnuma isn't available

Daniel P. Berrange berrange at redhat.com
Wed Apr 3 20:12:26 UTC 2013


From: "Daniel P. Berrange" <berrange at redhat.com>

If libnuma is not compiled in, or numa_available() returns an
error, stub out fake NUMA info consisting of one NUMA cell
containing all CPUs and memory.

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 src/nodeinfo.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 111 insertions(+), 26 deletions(-)

diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index 72ab394..34d9410 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -1467,6 +1467,97 @@ cleanup:
     return ret;
 }
 
+static int
+nodeCapsInitNUMAFake(virCapsPtr caps ATTRIBUTE_UNUSED)
+{
+    virNodeInfo nodeinfo;
+    virCapsHostNUMACellCPUPtr cpus;
+    int ncpus;
+    int s, c, t;
+    int id;
+
+    if (nodeGetInfo(NULL, &nodeinfo) < 0)
+        return -1;
+
+    ncpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
+
+    if (VIR_ALLOC_N(cpus, ncpus) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+
+    id = 0;
+    for (s = 0 ; s < nodeinfo.sockets ; s++) {
+        for (c = 0 ; c < nodeinfo.cores ; c++) {
+            for (t = 0 ; t < nodeinfo.threads ; t++) {
+                cpus[id].id = id;
+                cpus[id].socket_id = s;
+                cpus[id].core_id = c;
+                if (!(cpus[id].siblings = virBitmapNew(ncpus)))
+                    goto error;
+                if (virBitmapSetBit(cpus[id].siblings, id) < 0)
+                    goto error;
+                id++;
+            }
+        }
+    }
+
+    if (virCapabilitiesAddHostNUMACell(caps, 0,
+                                       ncpus,
+                                       nodeinfo.memory,
+                                       cpus) < 0)
+        goto error;
+
+    return 0;
+
+ error:
+    for ( ; id >= 0 ; id--)
+        virBitmapFree(cpus[id].siblings);
+    VIR_FREE(cpus);
+    return -1;
+}
+
+static int
+nodeGetCellsFreeMemoryFake(virConnectPtr conn ATTRIBUTE_UNUSED,
+                           unsigned long long *freeMems,
+                           int startCell,
+                           int maxCells ATTRIBUTE_UNUSED)
+{
+    double avail = physmem_available();
+
+    if (startCell != 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("start cell %d out of range (0-%d)"),
+                       startCell, 0);
+        return -1;
+    }
+
+    freeMems[0] = (unsigned long long)avail;
+
+    if (!freeMems[0]) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Cannot determine free memory"));
+        return -1;
+    }
+
+    return 1;
+}
+
+static unsigned long long
+nodeGetFreeMemoryFake(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    double avail = physmem_available();
+    unsigned long long ret;
+
+    if (!(ret = (unsigned long long)avail)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Cannot determine free memory"));
+        return 0;
+    }
+
+    return ret;
+}
+
 #if WITH_NUMACTL
 # if LIBNUMA_API_VERSION <= 1
 #  define NUMA_MAX_N_CPUS 4096
@@ -1547,7 +1638,7 @@ nodeCapsInitNUMA(virCapsPtr caps)
     bool topology_failed = false;
 
     if (numa_available() < 0)
-        return 0;
+        return nodeCapsInitNUMAFake(caps);
 
     int mask_n_bytes = max_n_cpus / 8;
     if (VIR_ALLOC_N(mask, mask_n_bytes / sizeof(*mask)) < 0)
@@ -1610,7 +1701,7 @@ cleanup:
 
 
 int
-nodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED,
+nodeGetCellsFreeMemory(virConnectPtr conn,
                        unsigned long long *freeMems,
                        int startCell,
                        int maxCells)
@@ -1619,11 +1710,10 @@ nodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED,
     int ret = -1;
     int maxCell;
 
-    if (numa_available() < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("NUMA not supported on this host"));
-        goto cleanup;
-    }
+    if (numa_available() < 0)
+        return nodeGetCellsFreeMemoryFake(conn, freeMems,
+                                          startCell, maxCells);
+
     maxCell = numa_max_node();
     if (startCell > maxCell) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -1652,16 +1742,14 @@ cleanup:
 }
 
 unsigned long long
-nodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED)
+nodeGetFreeMemory(virConnectPtr conn)
 {
     unsigned long long freeMem = 0;
     int n;
 
-    if (numa_available() < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       "%s", _("NUMA not supported on this host"));
-        goto cleanup;
-    }
+    if (numa_available() < 0)
+        return nodeGetFreeMemoryFake(conn);
+
 
     for (n = 0 ; n <= numa_max_node() ; n++) {
         long long mem;
@@ -1720,24 +1808,21 @@ cleanup:
 
 
 #else
-int nodeCapsInitNUMA(virCapsPtr caps ATTRIBUTE_UNUSED) {
-    return 0;
+int nodeCapsInitNUMA(virCapsPtr caps) {
+    return nodeCapsInitNUMAFake(caps);
 }
 
-int nodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED,
-                              unsigned long long *freeMems ATTRIBUTE_UNUSED,
-                              int startCell ATTRIBUTE_UNUSED,
-                              int maxCells ATTRIBUTE_UNUSED)
+int nodeGetCellsFreeMemory(virConnectPtr conn,
+                           unsigned long long *freeMems,
+                           int startCell,
+                           int maxCells)
 {
-    virReportError(VIR_ERR_NO_SUPPORT, "%s",
-                   _("NUMA memory information not available on this platform"));
-    return -1;
+    return nodeGetCellsFreeMemoryFake(conn, freeMems,
+                                      startCell, maxCells);
 }
 
-unsigned long long nodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED)
+unsigned long long nodeGetFreeMemory(virConnectPtr conn)
 {
-    virReportError(VIR_ERR_NO_SUPPORT, "%s",
-                   _("NUMA memory information not available on this platform"));
-    return 0;
+    return nodeGetFreeMemoryFake(conn);
 }
 #endif
-- 
1.8.1.4




More information about the libvir-list mailing list