提交 2f4c5338 编写于 作者: E Eric Blake

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.
上级 0711c4b7
...@@ -907,7 +907,7 @@ virNodeDeviceObjUnlock; ...@@ -907,7 +907,7 @@ virNodeDeviceObjUnlock;
# nodeinfo.h # nodeinfo.h
nodeCapsInitNUMA; nodeCapsInitNUMA;
nodeGetCPUmap; nodeGetCPUBitmap;
nodeGetCPUStats; nodeGetCPUStats;
nodeGetCellsFreeMemory; nodeGetCellsFreeMemory;
nodeGetFreeMemory; nodeGetFreeMemory;
......
...@@ -755,34 +755,55 @@ cleanup: ...@@ -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, ...@@ -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) {
virReportOOMError(); present = linuxParseCPUmax(SYSFS_SYSTEM_PATH "/cpu/present");
/* 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, ...@@ -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, ...@@ -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, ...@@ -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"));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册