mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-06 08:53:48 +00:00
nodeinfo: Add check and workaround to guarantee valid cpu topologies
Lately there were a few reports of the output of the virsh nodeinfo command being inaccurate. This patch tries to avoid that by checking if the topology actually makes sense. If it doesn't we then report a synthetic topology that indicates to the user that the host capabilities should be checked for the actual topology.
This commit is contained in:
parent
fd723164c7
commit
9576afd110
@ -531,17 +531,19 @@ typedef virTypedParameter *virTypedParameterPtr;
|
|||||||
typedef struct _virNodeInfo virNodeInfo;
|
typedef struct _virNodeInfo virNodeInfo;
|
||||||
|
|
||||||
struct _virNodeInfo {
|
struct _virNodeInfo {
|
||||||
char model[32]; /* string indicating the CPU model */
|
char model[32]; /* string indicating the CPU model */
|
||||||
unsigned long memory;/* memory size in kilobytes */
|
unsigned long memory; /* memory size in kilobytes */
|
||||||
unsigned int cpus; /* the number of active CPUs */
|
unsigned int cpus; /* the number of active CPUs */
|
||||||
unsigned int mhz; /* expected CPU frequency */
|
unsigned int mhz; /* expected CPU frequency */
|
||||||
unsigned int nodes; /* the number of NUMA cell, 1 for unusual NUMA
|
unsigned int nodes; /* the number of NUMA cell, 1 for unusual NUMA
|
||||||
topologies or uniform memory access; check
|
topologies or uniform memory access; check
|
||||||
capabilities XML for the actual NUMA topology */
|
capabilities XML for the actual NUMA topology */
|
||||||
unsigned int sockets;/* number of CPU sockets per node if nodes > 1,
|
unsigned int sockets; /* number of CPU sockets per node if nodes > 1,
|
||||||
total number of CPU sockets otherwise */
|
1 in case of unusual NUMA topology */
|
||||||
unsigned int cores; /* number of cores per socket */
|
unsigned int cores; /* number of cores per socket, total number of
|
||||||
unsigned int threads;/* number of threads per core */
|
processors in case of unusual NUMA topology*/
|
||||||
|
unsigned int threads; /* number of threads per core, 1 in case of
|
||||||
|
unusual numa topology */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -204,7 +204,12 @@ CPU_COUNT(cpu_set_t *set)
|
|||||||
static int
|
static int
|
||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
|
||||||
ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
|
ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
|
||||||
virNodeParseNode(const char *node, int *sockets, int *cores, int *threads)
|
ATTRIBUTE_NONNULL(5)
|
||||||
|
virNodeParseNode(const char *node,
|
||||||
|
int *sockets,
|
||||||
|
int *cores,
|
||||||
|
int *threads,
|
||||||
|
int *offline)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int processors = 0;
|
int processors = 0;
|
||||||
@ -278,8 +283,10 @@ virNodeParseNode(const char *node, int *sockets, int *cores, int *threads)
|
|||||||
if ((online = virNodeGetCpuValue(node, cpu, "online", true)) < 0)
|
if ((online = virNodeGetCpuValue(node, cpu, "online", true)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (!online)
|
if (!online) {
|
||||||
|
(*offline)++;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
processors++;
|
processors++;
|
||||||
|
|
||||||
@ -348,7 +355,7 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
|
|||||||
char line[1024];
|
char line[1024];
|
||||||
DIR *nodedir = NULL;
|
DIR *nodedir = NULL;
|
||||||
struct dirent *nodedirent = NULL;
|
struct dirent *nodedirent = NULL;
|
||||||
int cpus, cores, socks, threads;
|
int cpus, cores, socks, threads, offline = 0;
|
||||||
unsigned int node;
|
unsigned int node;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
char *sysfs_nodedir = NULL;
|
char *sysfs_nodedir = NULL;
|
||||||
@ -469,8 +476,8 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cpus = virNodeParseNode(sysfs_cpudir, &socks,
|
if ((cpus = virNodeParseNode(sysfs_cpudir, &socks, &cores,
|
||||||
&cores, &threads)) < 0)
|
&threads, &offline)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_FREE(sysfs_cpudir);
|
VIR_FREE(sysfs_cpudir);
|
||||||
@ -505,7 +512,8 @@ fallback:
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cpus = virNodeParseNode(sysfs_cpudir, &socks, &cores, &threads)) < 0)
|
if ((cpus = virNodeParseNode(sysfs_cpudir, &socks, &cores,
|
||||||
|
&threads, &offline)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
nodeinfo->nodes = 1;
|
nodeinfo->nodes = 1;
|
||||||
@ -531,6 +539,23 @@ done:
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now check if the topology makes sense. There are machines that don't
|
||||||
|
* expose their real number of nodes or for example the AMD Bulldozer
|
||||||
|
* architecture that exposes their Clustered integer core modules as both
|
||||||
|
* threads and cores. This approach throws off our detection. Unfortunately
|
||||||
|
* the nodeinfo structure isn't designed to carry the full topology so
|
||||||
|
* we're going to lie about the detected topology to notify the user
|
||||||
|
* to check the host capabilities for the actual topology. */
|
||||||
|
if ((nodeinfo->nodes *
|
||||||
|
nodeinfo->sockets *
|
||||||
|
nodeinfo->cores *
|
||||||
|
nodeinfo->threads) != (nodeinfo->cpus + offline)) {
|
||||||
|
nodeinfo->nodes = 1;
|
||||||
|
nodeinfo->sockets = 1;
|
||||||
|
nodeinfo->cores = nodeinfo->cpus + offline;
|
||||||
|
nodeinfo->threads = 1;
|
||||||
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
Loading…
Reference in New Issue
Block a user