Create fake NUMA info if libnuma isn't available

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@redhat.com>
This commit is contained in:
Daniel P. Berrange 2013-04-03 21:11:15 +01:00
parent 4a2891510b
commit 8d3d05d3c1

View File

@ -1467,6 +1467,97 @@ cleanup:
return ret; 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 WITH_NUMACTL
# if LIBNUMA_API_VERSION <= 1 # if LIBNUMA_API_VERSION <= 1
# define NUMA_MAX_N_CPUS 4096 # define NUMA_MAX_N_CPUS 4096
@ -1547,7 +1638,7 @@ nodeCapsInitNUMA(virCapsPtr caps)
bool topology_failed = false; bool topology_failed = false;
if (numa_available() < 0) if (numa_available() < 0)
return 0; return nodeCapsInitNUMAFake(caps);
int mask_n_bytes = max_n_cpus / 8; int mask_n_bytes = max_n_cpus / 8;
if (VIR_ALLOC_N(mask, mask_n_bytes / sizeof(*mask)) < 0) if (VIR_ALLOC_N(mask, mask_n_bytes / sizeof(*mask)) < 0)
@ -1610,7 +1701,7 @@ cleanup:
int int
nodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, nodeGetCellsFreeMemory(virConnectPtr conn,
unsigned long long *freeMems, unsigned long long *freeMems,
int startCell, int startCell,
int maxCells) int maxCells)
@ -1619,11 +1710,10 @@ nodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED,
int ret = -1; int ret = -1;
int maxCell; int maxCell;
if (numa_available() < 0) { if (numa_available() < 0)
virReportError(VIR_ERR_INTERNAL_ERROR, return nodeGetCellsFreeMemoryFake(conn, freeMems,
"%s", _("NUMA not supported on this host")); startCell, maxCells);
goto cleanup;
}
maxCell = numa_max_node(); maxCell = numa_max_node();
if (startCell > maxCell) { if (startCell > maxCell) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
@ -1652,16 +1742,14 @@ cleanup:
} }
unsigned long long unsigned long long
nodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) nodeGetFreeMemory(virConnectPtr conn)
{ {
unsigned long long freeMem = 0; unsigned long long freeMem = 0;
int n; int n;
if (numa_available() < 0) { if (numa_available() < 0)
virReportError(VIR_ERR_INTERNAL_ERROR, return nodeGetFreeMemoryFake(conn);
"%s", _("NUMA not supported on this host"));
goto cleanup;
}
for (n = 0 ; n <= numa_max_node() ; n++) { for (n = 0 ; n <= numa_max_node() ; n++) {
long long mem; long long mem;
@ -1720,24 +1808,21 @@ cleanup:
#else #else
int nodeCapsInitNUMA(virCapsPtr caps ATTRIBUTE_UNUSED) { int nodeCapsInitNUMA(virCapsPtr caps) {
return 0; return nodeCapsInitNUMAFake(caps);
} }
int nodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, int nodeGetCellsFreeMemory(virConnectPtr conn,
unsigned long long *freeMems ATTRIBUTE_UNUSED, unsigned long long *freeMems,
int startCell ATTRIBUTE_UNUSED, int startCell,
int maxCells ATTRIBUTE_UNUSED) int maxCells)
{ {
virReportError(VIR_ERR_NO_SUPPORT, "%s", return nodeGetCellsFreeMemoryFake(conn, freeMems,
_("NUMA memory information not available on this platform")); startCell, maxCells);
return -1;
} }
unsigned long long nodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) unsigned long long nodeGetFreeMemory(virConnectPtr conn)
{ {
virReportError(VIR_ERR_NO_SUPPORT, "%s", return nodeGetFreeMemoryFake(conn);
_("NUMA memory information not available on this platform"));
return 0;
} }
#endif #endif