mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
numa: Add wrapper of numa_node_to_cpus and use it
This commit is contained in:
parent
f162a229e7
commit
223521bd33
@ -1535,11 +1535,6 @@ nodeGetFreeMemoryFake(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if WITH_NUMACTL
|
#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
|
static virBitmapPtr
|
||||||
virNodeGetSiblingsList(const char *dir, int cpu_id)
|
virNodeGetSiblingsList(const char *dir, int cpu_id)
|
||||||
{
|
{
|
||||||
@ -1592,14 +1587,12 @@ int
|
|||||||
nodeCapsInitNUMA(virCapsPtr caps)
|
nodeCapsInitNUMA(virCapsPtr caps)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
unsigned long *mask = NULL;
|
|
||||||
unsigned long *allonesmask = NULL;
|
|
||||||
unsigned long long memory;
|
unsigned long long memory;
|
||||||
virCapsHostNUMACellCPUPtr cpus = NULL;
|
virCapsHostNUMACellCPUPtr cpus = NULL;
|
||||||
|
virBitmapPtr cpumap = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int max_n_cpus = virNumaGetMaxCPUs();
|
|
||||||
int mask_n_bytes = max_n_cpus / 8;
|
|
||||||
int ncpus = 0;
|
int ncpus = 0;
|
||||||
|
int cpu;
|
||||||
bool topology_failed = false;
|
bool topology_failed = false;
|
||||||
int max_node;
|
int max_node;
|
||||||
|
|
||||||
@ -1609,49 +1602,41 @@ nodeCapsInitNUMA(virCapsPtr caps)
|
|||||||
if ((max_node = virNumaGetMaxNode()) < 0)
|
if ((max_node = virNumaGetMaxNode()) < 0)
|
||||||
goto cleanup;
|
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++) {
|
for (n = 0; n <= max_node; n++) {
|
||||||
size_t i;
|
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 */
|
if ((ncpus = virNumaGetNodeCPUs(n, &cpumap)) < 0) {
|
||||||
virNumaGetNodeMemory(n, &memory, NULL);
|
if (ncpus == -2)
|
||||||
memory >>= 10;
|
continue;
|
||||||
|
|
||||||
for (ncpus = 0, i = 0; i < max_n_cpus; i++)
|
goto cleanup;
|
||||||
if (MASK_CPU_ISSET(mask, i))
|
}
|
||||||
ncpus++;
|
|
||||||
|
|
||||||
if (VIR_ALLOC_N(cpus, ncpus) < 0)
|
if (VIR_ALLOC_N(cpus, ncpus) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
cpu = 0;
|
||||||
|
|
||||||
for (ncpus = 0, i = 0; i < max_n_cpus; i++) {
|
for (i = 0; i < virBitmapSize(cpumap); i++) {
|
||||||
if (MASK_CPU_ISSET(mask, i)) {
|
bool cpustate;
|
||||||
if (virNodeCapsFillCPUInfo(i, cpus + ncpus++) < 0) {
|
if (virBitmapGetBit(cpumap, i, &cpustate) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cpustate) {
|
||||||
|
if (virNodeCapsFillCPUInfo(i, cpus + cpu++) < 0) {
|
||||||
topology_failed = true;
|
topology_failed = true;
|
||||||
virResetLastError();
|
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)
|
if (virCapabilitiesAddHostNUMACell(caps, n, ncpus, memory, cpus) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
cpus = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -1660,11 +1645,12 @@ cleanup:
|
|||||||
if (topology_failed || ret < 0)
|
if (topology_failed || ret < 0)
|
||||||
virCapabilitiesClearHostNUMACellCPUTopology(cpus, ncpus);
|
virCapabilitiesClearHostNUMACellCPUTopology(cpus, ncpus);
|
||||||
|
|
||||||
|
virBitmapFree(cpumap);
|
||||||
|
VIR_FREE(cpus);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
VIR_FREE(cpus);
|
VIR_FREE(cpus);
|
||||||
|
|
||||||
VIR_FREE(mask);
|
|
||||||
VIR_FREE(allonesmask);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
#include "vircommand.h"
|
#include "vircommand.h"
|
||||||
#include "virerror.h"
|
#include "virerror.h"
|
||||||
#include "virlog.h"
|
#include "virlog.h"
|
||||||
|
#include "viralloc.h"
|
||||||
|
#include "virbitmap.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_NONE
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
||||||
|
|
||||||
@ -249,6 +251,83 @@ virNumaGetNodeMemory(int node,
|
|||||||
|
|
||||||
return 0;
|
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
|
#else
|
||||||
int
|
int
|
||||||
virNumaSetupMemoryPolicy(virNumaTuneDef numatune,
|
virNumaSetupMemoryPolicy(virNumaTuneDef numatune,
|
||||||
@ -295,6 +374,18 @@ virNumaGetNodeMemory(int node ATTRIBUTE_UNUSED,
|
|||||||
VIR_DEBUG("NUMA isn't available on this host");
|
VIR_DEBUG("NUMA isn't available on this host");
|
||||||
return -1;
|
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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,4 +64,6 @@ int virNumaGetNodeMemory(int node,
|
|||||||
|
|
||||||
unsigned int virNumaGetMaxCPUs(void);
|
unsigned int virNumaGetMaxCPUs(void);
|
||||||
|
|
||||||
|
int virNumaGetNodeCPUs(int node, virBitmapPtr *cpus);
|
||||||
|
|
||||||
#endif /* __VIR_NUMA_H__ */
|
#endif /* __VIR_NUMA_H__ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user