While on that, drop support for kernels from RHEL-5 era (missing
cpu/present file). Also add some useful functions and export them.
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
src/libvirt_linux.syms | 1 -
src/libvirt_private.syms | 3 +
src/util/virhostcpu.c | 345 +++++++++++++---------------------------------
src/util/virhostcpu.h | 7 +-
src/util/virhostcpupriv.h | 2 -
tests/virhostcputest.c | 5 +-
6 files changed, 109 insertions(+), 254 deletions(-)
diff --git a/src/libvirt_linux.syms b/src/libvirt_linux.syms
index a864b78ce7b7..3d66f013062b 100644
--- a/src/libvirt_linux.syms
+++ b/src/libvirt_linux.syms
@@ -5,7 +5,6 @@
# util/virhostcpu.h
virHostCPUGetInfoPopulateLinux;
virHostCPUGetStatsLinux;
-virHostCPUSetSysFSSystemPathLinux;
# Let emacs know we want case-insensitive sorting
# Local Variables:
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0a4659fe5e92..c5181e5ff6de 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1712,12 +1712,15 @@ virHookPresent;
# util/virhostcpu.h
+virHostCPUGetCore;
virHostCPUGetCount;
virHostCPUGetInfo;
virHostCPUGetKVMMaxVCPUs;
virHostCPUGetMap;
+virHostCPUGetOnline;
virHostCPUGetOnlineBitmap;
virHostCPUGetPresentBitmap;
+virHostCPUGetSocket;
virHostCPUGetStats;
virHostCPUGetThreadsPerSubcore;
virHostCPUHasBitmap;
diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
index f29f3122acee..47f930cdbf3c 100644
--- a/src/util/virhostcpu.c
+++ b/src/util/virhostcpu.c
@@ -56,6 +56,7 @@
#include "virfile.h"
#include "virtypedparam.h"
#include "virstring.h"
+#include "virsysfs.h"
#include "virnuma.h"
#include "virlog.h"
@@ -189,89 +190,27 @@ virHostCPUGetStatsFreeBSD(int cpuNum,
#endif /* __FreeBSD__ */
#ifdef __linux__
-# define SYSFS_SYSTEM_PATH "/sys/devices/system"
# define CPUINFO_PATH "/proc/cpuinfo"
# define PROCSTAT_PATH "/proc/stat"
-# define SYSFS_THREAD_SIBLINGS_LIST_LENGTH_MAX 8192
+# define VIR_HOST_CPU_MASK_LEN 1024
# define LINUX_NB_CPU_STATS 4
-static const char *sysfs_system_path = SYSFS_SYSTEM_PATH;
-
-void virHostCPUSetSysFSSystemPathLinux(const char *path)
-{
- if (path)
- sysfs_system_path = path;
- else
- sysfs_system_path = SYSFS_SYSTEM_PATH;
-}
-
-/* Return the positive decimal contents of the given
- * DIR/cpu%u/FILE, or -1 on error. If DEFAULT_VALUE is non-negative
- * and the file could not be found, return that instead of an error;
- * this is useful for machines that cannot hot-unplug cpu0, or where
- * hot-unplugging is disabled, or where the kernel is too old
- * to support NUMA cells, etc. */
-static int
-virHostCPUGetValue(const char *dir, unsigned int cpu, const char *file,
- int default_value)
-{
- char *path;
- FILE *pathfp;
- int value = -1;
- char value_str[INT_BUFSIZE_BOUND(value)];
- char *tmp;
-
- if (virAsprintf(&path, "%s/cpu%u/%s", dir, cpu, file) < 0)
- return -1;
-
- pathfp = fopen(path, "r");
- if (pathfp == NULL) {
- if (default_value >= 0 && errno == ENOENT)
- value = default_value;
- else
- virReportSystemError(errno, _("cannot open %s"), path);
- goto cleanup;
- }
-
- if (fgets(value_str, sizeof(value_str), pathfp) == NULL) {
- virReportSystemError(errno, _("cannot read from %s"), path);
- goto cleanup;
- }
- if (virStrToLong_i(value_str, &tmp, 10, &value) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("could not convert '%s' to an integer"),
- value_str);
- goto cleanup;
- }
-
- cleanup:
- VIR_FORCE_FCLOSE(pathfp);
- VIR_FREE(path);
-
- return value;
-}
static unsigned long
-virHostCPUCountThreadSiblings(const char *dir, unsigned int cpu)
+virHostCPUCountThreadSiblings(unsigned int cpu)
{
unsigned long ret = 0;
- char *path;
+ int rv = -1;
char *str = NULL;
size_t i;
- if (virAsprintf(&path, "%s/cpu%u/topology/thread_siblings",
- dir, cpu) < 0)
- return 0;
-
- if (!virFileExists(path)) {
- /* If file doesn't exist, then pretend our only
- * sibling is ourself */
+ rv = virSysfsGetCpuValueString(cpu, "topology/thread_siblings", &str);
+ if (rv == -2) {
ret = 1;
goto cleanup;
}
-
- if (virFileReadAll(path, SYSFS_THREAD_SIBLINGS_LIST_LENGTH_MAX, &str) < 0)
+ if (rv < 0)
goto cleanup;
for (i = 0; str[i] != '\0'; i++) {
@@ -281,21 +220,78 @@ virHostCPUCountThreadSiblings(const char *dir, unsigned int cpu)
cleanup:
VIR_FREE(str);
- VIR_FREE(path);
return ret;
}
-static int
-virHostCPUParseSocket(const char *dir,
- virArch arch,
- unsigned int cpu)
+int
+virHostCPUGetSocket(unsigned int cpu, unsigned int *socket)
{
- int ret = virHostCPUGetValue(dir, cpu, "topology/physical_package_id", 0);
+ int tmp;
+ int ret = virSysfsGetCpuValueInt(cpu,
+ "topology/physical_package_id",
+ &tmp);
+
+ /* If the file is not there, it's 0 */
+ if (ret == -2)
+ tmp = 0;
+ else if (ret < 0)
+ return -1;
- if (ARCH_IS_ARM(arch) || ARCH_IS_PPC(arch) || ARCH_IS_S390(arch)) {
- /* arm, ppc and s390(x) has -1 */
- if (ret < 0)
- ret = 0;
+ /* Some architectures might have '-1' validly in the file, but that actually
+ * means there are no sockets, so from our point of view it's all one socket,
+ * i.e. socket 0. Similarly when the file does not exist. */
+ if (tmp < 0)
+ tmp = 0;
+
+ *socket = tmp;
+
+ return 0;
+}
+
+int
+virHostCPUGetCore(unsigned int cpu, unsigned int *core)
+{
+ int ret = virSysfsGetCpuValueUint(cpu, "topology/core_id", core);
+
+ /* If the file is not there, it's 0 */
+ if (ret == -2)
+ *core = 0;
+ else if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+int
+virHostCPUGetOnline(unsigned int cpu, bool *online)
+{
+ unsigned int tmp = 0;
+ int ret = virSysfsGetCpuValueUint(cpu, "online", &tmp);
+
+
+ /* If the file is not there, it's online (doesn't support offlining) */
+ if (ret == -2)
+ tmp = 1;
+ else if (ret < 0)
+ return -1;
+
+ *online = tmp;
+
+ return 0;
+}
+
+virBitmapPtr
+virHostCPUGetSiblingsList(unsigned int cpu)
+{
+ virBitmapPtr ret = NULL;
+ int rv = -1;
+
+ rv = virSysfsGetCpuValueBitmap(cpu, "topology/thread_siblings_list",
&ret);
+ if (rv == -2) {
+ /* If the file doesn't exist, the threadis its only sibling */
+ ret = virBitmapNew(cpu + 1);
+ if (ret)
+ ignore_value(virBitmapSetBit(ret, cpu));
}
return ret;
@@ -329,9 +325,9 @@ virHostCPUParseNode(const char *node,
virBitmapPtr sockets_map = NULL;
virBitmapPtr *cores_maps = NULL;
int npresent_cpus = virBitmapSize(present_cpus_map);
- int sock_max = 0;
- int sock;
- int core;
+ unsigned int sock_max = 0;
+ unsigned int sock;
+ unsigned int core;
size_t i;
int siblings;
unsigned int cpu;
@@ -366,8 +362,7 @@ virHostCPUParseNode(const char *node,
if (!virBitmapIsBitSet(online_cpus_map, cpu))
continue;
- /* Parse socket */
- if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
+ if (virHostCPUGetSocket(cpu, &sock) < 0)
goto cleanup;
if (sock > ID_MAX) {
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -421,8 +416,7 @@ virHostCPUParseNode(const char *node,
processors++;
- /* Parse socket */
- if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
+ if (virHostCPUGetSocket(cpu, &sock) < 0)
goto cleanup;
if (!virBitmapIsBitSet(sockets_map, sock)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -435,8 +429,7 @@ virHostCPUParseNode(const char *node,
/* logical cpu is equivalent to a core on s390 */
core = cpu;
} else {
- if ((core = virHostCPUGetValue(node, cpu,
- "topology/core_id", 0)) < 0)
+ if (virHostCPUGetCore(cpu, &core) < 0)
goto cleanup;
}
if (core > ID_MAX) {
@@ -449,7 +442,7 @@ virHostCPUParseNode(const char *node,
if (virBitmapSetBit(cores_maps[sock], core) < 0)
goto cleanup;
- if (!(siblings = virHostCPUCountThreadSiblings(node, cpu)))
+ if (!(siblings = virHostCPUCountThreadSiblings(cpu)))
goto cleanup;
if (siblings > *threads)
@@ -640,7 +633,7 @@ virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
/* OK, we've parsed clock speed out of /proc/cpuinfo. Get the
* core, node, socket, thread and topology information from /sys
*/
- if (virAsprintf(&sysfs_nodedir, "%s/node", sysfs_system_path) < 0)
+ if (virAsprintf(&sysfs_nodedir, "%s/node", virSysfsGetSystemPath())
< 0)
goto cleanup;
if (virDirOpenQuiet(&nodedir, sysfs_nodedir) < 0) {
@@ -685,7 +678,7 @@ virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
(*nodes)++;
if (virAsprintf(&sysfs_cpudir, "%s/node/%s",
- sysfs_system_path, nodedirent->d_name) < 0)
+ virSysfsGetSystemPath(), nodedirent->d_name) < 0)
goto cleanup;
if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
@@ -719,7 +712,7 @@ virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
fallback:
VIR_FREE(sysfs_cpudir);
- if (virAsprintf(&sysfs_cpudir, "%s/cpu", sysfs_system_path) < 0)
+ if (virAsprintf(&sysfs_cpudir, "%s/cpu", virSysfsGetSystemPath()) <
0)
goto cleanup;
if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
@@ -857,47 +850,24 @@ virHostCPUGetStatsLinux(FILE *procstat,
}
-static char *
-virHostCPUGetGlobalPathLinux(const char *file)
-{
- char *path = NULL;
-
- if (virAsprintf(&path, "%s/cpu/%s", sysfs_system_path, file) < 0)
- return NULL;
-
- return path;
-}
-
-static char *
-virHostCPUGetPresentPathLinux(void)
-{
- return virHostCPUGetGlobalPathLinux("present");
-}
-
-static char *
-virHostCPUGetOnlinePathLinux(void)
-{
- return virHostCPUGetGlobalPathLinux("online");
-}
-
/* Determine the number of CPUs (maximum CPU id + 1) from a file containing
* a list of CPU ids, like the Linux sysfs cpu/present file */
static int
-virHostCPUParseCountLinux(const char *path)
+virHostCPUParseCountLinux(void)
{
char *str = NULL;
char *tmp;
int ret = -1;
- if (virFileReadAll(path, 5 * VIR_HOST_CPU_MASK_LEN, &str) < 0)
- goto cleanup;
+ if (virSysfsGetValueString("cpu/present", &str) < 0)
+ return -1;
tmp = str;
do {
if (virStrToLong_i(tmp, &tmp, 10, &ret) < 0 ||
!strchr(",-\n", *tmp)) {
virReportError(VIR_ERR_NO_SUPPORT,
- _("failed to parse %s"), path);
+ _("failed to parse %s"), str);
ret = -1;
goto cleanup;
}
@@ -908,32 +878,6 @@ virHostCPUParseCountLinux(const char *path)
VIR_FREE(str);
return ret;
}
-
-/*
- * Linux maintains cpu bit map under cpu/online. For example, if
- * cpuid=5's flag is not set and max cpu is 7, the map file shows
- * 0-4,6-7. This function parses it and returns cpumap.
- */
-static virBitmapPtr
-virHostCPUParseMapLinux(int max_cpuid, const char *path)
-{
- virBitmapPtr map = NULL;
- char *str = NULL;
-
- if (virFileReadAll(path, 5 * VIR_HOST_CPU_MASK_LEN, &str) < 0)
- goto error;
-
- if (virBitmapParse(str, &map, max_cpuid) < 0)
- goto error;
-
- VIR_FREE(str);
- return map;
-
- error:
- VIR_FREE(str);
- virBitmapFree(map);
- return NULL;
-}
#endif
@@ -1063,46 +1007,7 @@ int
virHostCPUGetCount(void)
{
#if defined(__linux__)
- /* To support older kernels that lack cpu/present, such as 2.6.18
- * in RHEL5, we fall back to count cpu/cpuNN entries; this assumes
- * that such kernels also lack hotplug, and therefore cpu/cpuNN
- * will be consecutive.
- */
- char *present_path = NULL;
- char *cpupath = NULL;
- int ncpu = -1;
-
- if (!(present_path = virHostCPUGetPresentPathLinux()))
- return -1;
-
- if (virFileExists(present_path)) {
- ncpu = virHostCPUParseCountLinux(present_path);
- goto cleanup;
- }
-
- if (virAsprintf(&cpupath, "%s/cpu/cpu0", sysfs_system_path) < 0)
- goto cleanup;
- if (virFileExists(cpupath)) {
- ncpu = 0;
- do {
- ncpu++;
- VIR_FREE(cpupath);
- if (virAsprintf(&cpupath, "%s/cpu/cpu%d",
- sysfs_system_path, ncpu) < 0) {
- ncpu = -1;
- goto cleanup;
- }
- } while (virFileExists(cpupath));
- } else {
- /* no cpu/cpu0: we give up */
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("host cpu counting not supported on this node"));
- }
-
- cleanup:
- VIR_FREE(present_path);
- VIR_FREE(cpupath);
- return ncpu;
+ return virHostCPUParseCountLinux();
#elif defined(__FreeBSD__) || defined(__APPLE__)
return virHostCPUGetCountAppleFreeBSD();
#else
@@ -1126,83 +1031,27 @@ virBitmapPtr
virHostCPUGetPresentBitmap(void)
{
#ifdef __linux__
- virBitmapPtr present_cpus = NULL;
- char *present_path = NULL;
- int npresent_cpus;
-
- if ((npresent_cpus = virHostCPUGetCount()) < 0)
- goto cleanup;
-
- if (!(present_path = virHostCPUGetPresentPathLinux()))
- goto cleanup;
+ virBitmapPtr ret = NULL;
- /* If the cpu/present file is available, parse it and exit */
- if (virFileExists(present_path)) {
- present_cpus = virHostCPUParseMapLinux(npresent_cpus, present_path);
- goto cleanup;
- }
-
- /* If the file is not available, we can assume that the kernel is
- * too old to support non-consecutive CPU ids and just mark all
- * possible CPUs as present */
- if (!(present_cpus = virBitmapNew(npresent_cpus)))
- goto cleanup;
-
- virBitmapSetAll(present_cpus);
-
- cleanup:
- VIR_FREE(present_path);
+ virSysfsGetValueBitmap("cpu/present", &ret);
- return present_cpus;
-#endif
+ return ret;
+#else
virReportError(VIR_ERR_NO_SUPPORT, "%s",
_("node present CPU map not implemented on this
platform"));
return NULL;
+#endif
}
virBitmapPtr
virHostCPUGetOnlineBitmap(void)
{
#ifdef __linux__
- char *online_path = NULL;
- char *cpudir = NULL;
- virBitmapPtr cpumap;
- int present;
-
- present = virHostCPUGetCount();
- if (present < 0)
- return NULL;
-
- if (!(online_path = virHostCPUGetOnlinePathLinux()))
- return NULL;
- if (virFileExists(online_path)) {
- cpumap = virHostCPUParseMapLinux(present, online_path);
- } else {
- size_t i;
-
- cpumap = virBitmapNew(present);
- if (!cpumap)
- goto cleanup;
+ virBitmapPtr ret = NULL;
- if (virAsprintf(&cpudir, "%s/cpu", sysfs_system_path) < 0)
- goto cleanup;
+ virSysfsGetValueBitmap("cpu/online", &ret);
- for (i = 0; i < present; i++) {
- int online = virHostCPUGetValue(cpudir, i, "online", 1);
- if (online < 0) {
- virBitmapFree(cpumap);
- cpumap = NULL;
- goto cleanup;
- }
- if (online)
- ignore_value(virBitmapSetBit(cpumap, i));
- }
- }
-
- cleanup:
- VIR_FREE(online_path);
- VIR_FREE(cpudir);
- return cpumap;
+ return ret;
#else
virReportError(VIR_ERR_NO_SUPPORT, "%s",
_("node online CPU map not implemented on this platform"));
diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h
index 39f7cf8c8814..a4ce655d6a2e 100644
--- a/src/util/virhostcpu.h
+++ b/src/util/virhostcpu.h
@@ -28,7 +28,6 @@
# include "virarch.h"
# include "virbitmap.h"
-# define VIR_HOST_CPU_MASK_LEN 1024
int virHostCPUGetStats(int cpuNum,
virNodeCPUStatsPtr params,
@@ -58,4 +57,10 @@ int virHostCPUStatsAssign(virNodeCPUStatsPtr param,
const char *name,
unsigned long long value);
+int virHostCPUGetSocket(unsigned int cpu, unsigned int *socket);
+int virHostCPUGetCore(unsigned int cpu, unsigned int *core);
+int virHostCPUGetOnline(unsigned int cpu, bool *online);
+
+virBitmapPtr virHostCPUGetSiblingsList(unsigned int cpu);
+
#endif /* __VIR_HOSTCPU_H__*/
diff --git a/src/util/virhostcpupriv.h b/src/util/virhostcpupriv.h
index de30983881c2..5e7ae3b88ad3 100644
--- a/src/util/virhostcpupriv.h
+++ b/src/util/virhostcpupriv.h
@@ -25,8 +25,6 @@
# include "virhostcpu.h"
# ifdef __linux__
-void virHostCPUSetSysFSSystemPathLinux(const char *path);
-
int virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
virArch arch,
unsigned int *cpus,
diff --git a/tests/virhostcputest.c b/tests/virhostcputest.c
index 09be1208de40..10e49ea4f0a4 100644
--- a/tests/virhostcputest.c
+++ b/tests/virhostcputest.c
@@ -8,6 +8,7 @@
#include "testutils.h"
#include "internal.h"
#include "virhostcpupriv.h"
+#include "virsysfspriv.h"
#include "virfile.h"
#include "virstring.h"
@@ -177,9 +178,9 @@ linuxTestHostCPU(const void *opaque)
goto cleanup;
}
- virHostCPUSetSysFSSystemPathLinux(sysfs_prefix);
+ virSysfsSetSystemPath(sysfs_prefix);
result = linuxTestCompareFiles(cpuinfo, data->arch, output);
- virHostCPUSetSysFSSystemPathLinux(NULL);
+ virSysfsSetSystemPath(NULL);
cleanup:
VIR_FREE(cpuinfo);
--
2.12.0