提交 223521bd 编写于 作者: P Peter Krempa

numa: Add wrapper of numa_node_to_cpus and use it

上级 f162a229
......@@ -1535,11 +1535,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)
{
......@@ -1592,14 +1587,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;
......@@ -1609,49 +1602,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 (i = 0; i < virBitmapSize(cpumap); i++) {
bool cpustate;
if (virBitmapGetBit(cpumap, i, &cpustate) < 0)
continue;
for (ncpus = 0, i = 0; i < max_n_cpus; i++) {
if (MASK_CPU_ISSET(mask, i)) {
if (virNodeCapsFillCPUInfo(i, cpus + ncpus++) < 0) {
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;
......@@ -1660,11 +1645,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;
}
......
......@@ -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
......
......@@ -64,4 +64,6 @@ int virNumaGetNodeMemory(int node,
unsigned int virNumaGetMaxCPUs(void);
int virNumaGetNodeCPUs(int node, virBitmapPtr *cpus);
#endif /* __VIR_NUMA_H__ */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册