mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 03:12:22 +00:00
nodeinfo: improve probing node cpu bitmap
Callers should not need to know what the name of the file to be read in the Linux-specific version of nodeGetCPUmap; furthermore, qemu cares about online cpus, not present cpus, when determining which cpus to skip. While at it, I fixed the fact that we were computing the maximum online cpu id by doing a slow iteration, when what we really want to know is the max available cpu. * src/nodeinfo.h (nodeGetCPUmap): Rename... (nodeGetCPUBitmap): ...and simplify signature. * src/nodeinfo.c (linuxParseCPUmax): New function. (linuxParseCPUmap): Simplify and alter signature. (nodeGetCPUBitmap): Change implementation. * src/libvirt_private.syms (nodeinfo.h): Reflect rename. * src/qemu/qemu_driver.c (qemuDomainGetPercpuStats): Update caller.
This commit is contained in:
parent
0711c4b74d
commit
2f4c5338a6
@ -907,7 +907,7 @@ virNodeDeviceObjUnlock;
|
|||||||
|
|
||||||
# nodeinfo.h
|
# nodeinfo.h
|
||||||
nodeCapsInitNUMA;
|
nodeCapsInitNUMA;
|
||||||
nodeGetCPUmap;
|
nodeGetCPUBitmap;
|
||||||
nodeGetCPUStats;
|
nodeGetCPUStats;
|
||||||
nodeGetCellsFreeMemory;
|
nodeGetCellsFreeMemory;
|
||||||
nodeGetFreeMemory;
|
nodeGetFreeMemory;
|
||||||
|
@ -755,34 +755,55 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Determine the maximum cpu id from a Linux sysfs cpu/present file. */
|
||||||
|
static int
|
||||||
|
linuxParseCPUmax(const char *path)
|
||||||
|
{
|
||||||
|
char *str = NULL;
|
||||||
|
char *tmp;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (virFileReadAll(path, 5 * VIR_DOMAIN_CPUMASK_LEN, &str) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = str;
|
||||||
|
do {
|
||||||
|
if (virStrToLong_i(tmp, &tmp, 10, &ret) < 0 ||
|
||||||
|
!strchr(",-\n", *tmp)) {
|
||||||
|
virReportError(VIR_ERR_NO_SUPPORT,
|
||||||
|
_("failed to parse %s"), path);
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} while (*tmp++ != '\n');
|
||||||
|
ret++;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(str);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Linux maintains cpu bit map. For example, if cpuid=5's flag is not set
|
* Linux maintains cpu bit map under cpu/online. For example, if
|
||||||
* and max cpu is 7. The map file shows 0-4,6-7. This function parses
|
* cpuid=5's flag is not set and max cpu is 7, the map file shows
|
||||||
* it and returns cpumap.
|
* 0-4,6-7. This function parses it and returns cpumap.
|
||||||
*/
|
*/
|
||||||
static virBitmapPtr
|
static virBitmapPtr
|
||||||
linuxParseCPUmap(int *max_cpuid, const char *path)
|
linuxParseCPUmap(int max_cpuid, const char *path)
|
||||||
{
|
{
|
||||||
virBitmapPtr map = NULL;
|
virBitmapPtr map = NULL;
|
||||||
char *str = NULL;
|
char *str = NULL;
|
||||||
int max_id = 0, i;
|
|
||||||
|
|
||||||
if (virFileReadAll(path, 5 * VIR_DOMAIN_CPUMASK_LEN, &str) < 0) {
|
if (virFileReadAll(path, 5 * VIR_DOMAIN_CPUMASK_LEN, &str) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virBitmapParse(str, 0, &map,
|
if (virBitmapParse(str, 0, &map, max_cpuid) < 0)
|
||||||
VIR_DOMAIN_CPUMASK_LEN) < 0) {
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
|
|
||||||
i = -1;
|
|
||||||
while ((i = virBitmapNextSetBit(map, i)) >= 0) {
|
|
||||||
max_id = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
*max_cpuid = max_id;
|
|
||||||
|
|
||||||
VIR_FREE(str);
|
VIR_FREE(str);
|
||||||
return map;
|
return map;
|
||||||
@ -929,21 +950,24 @@ int nodeGetMemoryStats(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
virBitmapPtr
|
virBitmapPtr
|
||||||
nodeGetCPUmap(virConnectPtr conn ATTRIBUTE_UNUSED,
|
nodeGetCPUBitmap(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||||
int *max_id ATTRIBUTE_UNUSED,
|
int *max_id ATTRIBUTE_UNUSED)
|
||||||
const char *mapname ATTRIBUTE_UNUSED)
|
|
||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
char *path;
|
|
||||||
virBitmapPtr cpumap;
|
virBitmapPtr cpumap;
|
||||||
|
int present;
|
||||||
|
|
||||||
if (virAsprintf(&path, SYSFS_SYSTEM_PATH "/cpu/%s", mapname) < 0) {
|
present = linuxParseCPUmax(SYSFS_SYSTEM_PATH "/cpu/present");
|
||||||
virReportOOMError();
|
/* XXX should we also work on older kernels, like RHEL5, that lack
|
||||||
|
* cpu/present and cpu/online files? Those kernels also lack cpu
|
||||||
|
* hotplugging, so it would be a matter of finding the largest
|
||||||
|
* cpu/cpuNN directory, and creating a map that size with all bits
|
||||||
|
* set. */
|
||||||
|
if (present < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
cpumap = linuxParseCPUmap(present, SYSFS_SYSTEM_PATH "/cpu/online");
|
||||||
|
if (max_id && cpumap)
|
||||||
cpumap = linuxParseCPUmap(max_id, path);
|
*max_id = present;
|
||||||
VIR_FREE(path);
|
|
||||||
return cpumap;
|
return cpumap;
|
||||||
#else
|
#else
|
||||||
virReportError(VIR_ERR_NO_SUPPORT, "%s",
|
virReportError(VIR_ERR_NO_SUPPORT, "%s",
|
||||||
|
@ -46,9 +46,8 @@ int nodeGetCellsFreeMemory(virConnectPtr conn,
|
|||||||
int maxCells);
|
int maxCells);
|
||||||
unsigned long long nodeGetFreeMemory(virConnectPtr conn);
|
unsigned long long nodeGetFreeMemory(virConnectPtr conn);
|
||||||
|
|
||||||
virBitmapPtr nodeGetCPUmap(virConnectPtr conn,
|
virBitmapPtr nodeGetCPUBitmap(virConnectPtr conn,
|
||||||
int *max_id,
|
int *max_id);
|
||||||
const char *mapname);
|
|
||||||
|
|
||||||
int nodeGetMemoryParameters(virConnectPtr conn,
|
int nodeGetMemoryParameters(virConnectPtr conn,
|
||||||
virTypedParameterPtr params,
|
virTypedParameterPtr params,
|
||||||
|
@ -13615,8 +13615,8 @@ qemuDomainGetPercpuStats(virDomainPtr domain,
|
|||||||
if (nparams == 0 && ncpus != 0)
|
if (nparams == 0 && ncpus != 0)
|
||||||
return QEMU_NB_PER_CPU_STAT_PARAM;
|
return QEMU_NB_PER_CPU_STAT_PARAM;
|
||||||
|
|
||||||
/* To parse account file, we need "present" cpu map. */
|
/* To parse account file, we need bitmap of online cpus. */
|
||||||
map = nodeGetCPUmap(domain->conn, &max_id, "present");
|
map = nodeGetCPUBitmap(domain->conn, &max_id);
|
||||||
if (!map)
|
if (!map)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
@ -13681,7 +13681,7 @@ qemuDomainGetPercpuStats(virDomainPtr domain,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* Check that the mapping of online cpus didn't change mid-parse. */
|
/* Check that the mapping of online cpus didn't change mid-parse. */
|
||||||
map2 = nodeGetCPUmap(domain->conn, &max_id, "present");
|
map2 = nodeGetCPUBitmap(domain->conn, &max_id);
|
||||||
if (!map2 || !virBitmapEqual(map, map2)) {
|
if (!map2 || !virBitmapEqual(map, map2)) {
|
||||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||||
_("the set of online cpus changed while reading"));
|
_("the set of online cpus changed while reading"));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user