Move all APIs with a virHostCPU name prefix out into new
util/virhostcpu.h & util/virhostcpu.c files
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
cfg.mk | 6 +-
po/POTFILES.in | 1 +
src/Makefile.am | 3 +-
src/libvirt_linux.syms | 2 +-
src/lxc/lxc_controller.c | 2 +-
src/lxc/lxc_driver.c | 1 +
src/nodeinfo.c | 1171 +-----------------
src/nodeinfo.h | 13 -
src/openvz/openvz_driver.c | 1 +
src/qemu/qemu_driver.c | 1 +
src/qemu/qemu_process.c | 2 +-
src/uml/uml_driver.c | 1 +
src/util/vircgroup.c | 3 +-
src/util/virhostcpu.c | 1299 ++++++++++++++++++++
src/util/virhostcpu.h | 54 +
src/{nodeinfopriv.h => util/virhostcpupriv.h} | 12 +-
[...snipped countless more test data renames....]
rename tests/{nodeinfodata => virhostcpudata}/linux-x86_64-test7.expected (100%)
rename tests/{nodeinfodata => virhostcpudata}/linux-x86_64-test8.cpuinfo (100%)
rename tests/{nodeinfodata => virhostcpudata}/linux-x86_64-test8.expected (100%)
rename tests/{nodeinfomock.c => virhostcpumock.c} (95%)
rename tests/{nodeinfotest.c => virhostcputest.c} (89%)
diff --git a/cfg.mk b/cfg.mk
index cd3b515..b1b8bdc 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -1161,7 +1161,7 @@ exclude_file_name_regexp--sc_prohibit_close = \
(\.p[yl]$$|\.spec\.in$$|^docs/|^(src/util/virfile\.c|src/libvirt-stream\.c|tests/vir.+mock\.c)$$)
exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = \
- (^tests/(qemuhelp|nodeinfo|virpcitest)data/|\.diff$$)
+ (^tests/(qemuhelp|virhostcpu|virpcitest)data/|\.diff$$)
_src2=src/(util/vircommand|libvirt|lxc/lxc_controller|locking/lock_daemon|logging/log_daemon)
exclude_file_name_regexp--sc_prohibit_fork_wrappers = \
@@ -1208,7 +1208,7 @@ exclude_file_name_regexp--sc_require_config_h_first = \
^(examples/|tools/virsh-edit\.c$$)
exclude_file_name_regexp--sc_trailing_blank = \
- /qemuhelpdata/|/sysinfodata/.*\.data|/nodeinfodata/.*\.cpuinfo$$
+ /qemuhelpdata/|/sysinfodata/.*\.data|/virhostcpudata/.*\.cpuinfo$$
exclude_file_name_regexp--sc_unmarked_diagnostics = \
^(docs/apibuild.py|tests/virt-aa-helper-test)$$
@@ -1239,7 +1239,7 @@ exclude_file_name_regexp--sc_prohibit_mixed_case_abbreviations = \
^src/(vbox/vbox_CAPI.*.h|esx/esx_vi.(c|h)|esx/esx_storage_backend_iscsi.c)$$
exclude_file_name_regexp--sc_prohibit_empty_first_line = \
-
^(README|daemon/THREADS\.txt|src/esx/README|docs/library.xen|tests/(vmwarever|nodeinfo)data/.*)$$
+
^(README|daemon/THREADS\.txt|src/esx/README|docs/library.xen|tests/(vmwarever|virhostcpu)data/.*)$$
exclude_file_name_regexp--sc_prohibit_useless_translation = \
^tests/virpolkittest.c
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ca23526..b0cd8cf 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -195,6 +195,7 @@ src/util/virfile.c
src/util/virfirewall.c
src/util/virhash.c
src/util/virhook.c
+src/util/virhostcpu.c
src/util/virhostdev.c
src/util/viridentity.c
src/util/virinitctl.c
diff --git a/src/Makefile.am b/src/Makefile.am
index f5e57c0..8d2a8e0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -118,6 +118,7 @@ UTIL_SOURCES = \
util/virhash.c util/virhash.h \
util/virhashcode.c util/virhashcode.h \
util/virhook.c util/virhook.h \
+ util/virhostcpu.c util/virhostcpu.h util/virhostcpupriv.h \
util/virhostdev.c util/virhostdev.h \
util/viridentity.c util/viridentity.h \
util/virinitctl.c util/virinitctl.h \
@@ -190,7 +191,7 @@ util/virkeymaps.h: $(srcdir)/util/keymaps.csv \
<$(srcdir)/util/keymaps.csv >util/virkeymaps.h
# Internal generic driver infrastructure
-NODE_INFO_SOURCES = nodeinfo.h nodeinfo.c nodeinfopriv.h
+NODE_INFO_SOURCES = nodeinfo.h nodeinfo.c
DATATYPES_SOURCES = datatypes.h datatypes.c
DRIVER_SOURCES = \
driver.c driver.h \
diff --git a/src/libvirt_linux.syms b/src/libvirt_linux.syms
index a2fc076..a864b78 100644
--- a/src/libvirt_linux.syms
+++ b/src/libvirt_linux.syms
@@ -2,7 +2,7 @@
# Linux-specific private symbols.
#
-# nodeinfo.h
+# util/virhostcpu.h
virHostCPUGetInfoPopulateLinux;
virHostCPUGetStatsLinux;
virHostCPUSetSysFSSystemPathLinux;
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 45ad25e..d59192d 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -59,7 +59,7 @@
#include "virfile.h"
#include "virpidfile.h"
#include "vircommand.h"
-#include "nodeinfo.h"
+#include "virhostcpu.h"
#include "virrandom.h"
#include "virprocess.h"
#include "virnuma.h"
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index c5e9a5f..2cecabc 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -51,6 +51,7 @@
#include "virnetdevveth.h"
#include "virnetdevopenvswitch.h"
#include "nodeinfo.h"
+#include "virhostcpu.h"
#include "viruuid.h"
#include "virstats.h"
#include "virhook.h"
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index a3d0024..8bf495f 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -46,10 +46,9 @@
# include <sys/resource.h>
#endif
-#include "c-ctype.h"
#include "viralloc.h"
-#include "nodeinfopriv.h"
#include "nodeinfo.h"
+#include "virhostcpu.h"
#include "physmem.h"
#include "virerror.h"
#include "count-one-bits.h"
@@ -66,126 +65,9 @@
VIR_LOG_INIT("nodeinfo");
-#if defined(__FreeBSD__) || defined(__APPLE__)
-static int
-virHostCPUGetCountAppleFreeBSD(void)
-{
- int ncpu_mib[2] = { CTL_HW, HW_NCPU };
- unsigned long ncpu;
- size_t ncpu_len = sizeof(ncpu);
-
- if (sysctl(ncpu_mib, 2, &ncpu, &ncpu_len, NULL, 0) == -1) {
- virReportSystemError(errno, "%s", _("Cannot obtain CPU
count"));
- return -1;
- }
-
- return ncpu;
-}
-#endif /* defined(__FreeBSD__) || defined(__APPLE__) */
-
#ifdef __FreeBSD__
-# define BSD_CPU_STATS_ALL 4
# define BSD_MEMORY_STATS_ALL 4
-# define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / (stathz ? stathz : hz))
-
-static int
-virHostCPUGetStatsFreebsd(int cpuNum,
- virNodeCPUStatsPtr params,
- int *nparams)
-{
- const char *sysctl_name;
- long *cpu_times;
- struct clockinfo clkinfo;
- size_t i, j, cpu_times_size, clkinfo_size;
- int cpu_times_num, offset, hz, stathz, ret = -1;
- struct field_cpu_map {
- const char *field;
- int idx[CPUSTATES];
- } cpu_map[] = {
- {VIR_NODE_CPU_STATS_KERNEL, {CP_SYS}},
- {VIR_NODE_CPU_STATS_USER, {CP_USER, CP_NICE}},
- {VIR_NODE_CPU_STATS_IDLE, {CP_IDLE}},
- {VIR_NODE_CPU_STATS_INTR, {CP_INTR}},
- {NULL, {0}}
- };
-
- if ((*nparams) == 0) {
- *nparams = BSD_CPU_STATS_ALL;
- return 0;
- }
-
- if ((*nparams) != BSD_CPU_STATS_ALL) {
- virReportInvalidArg(*nparams,
- _("nparams in %s must be equal to %d"),
- __FUNCTION__, BSD_CPU_STATS_ALL);
- return -1;
- }
-
- clkinfo_size = sizeof(clkinfo);
- if (sysctlbyname("kern.clockrate", &clkinfo, &clkinfo_size, NULL,
0) < 0) {
- virReportSystemError(errno,
- _("sysctl failed for '%s'"),
- "kern.clockrate");
- return -1;
- }
-
- stathz = clkinfo.stathz;
- hz = clkinfo.hz;
-
- if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) {
- sysctl_name = "kern.cp_time";
- cpu_times_num = 1;
- offset = 0;
- } else {
- sysctl_name = "kern.cp_times";
- cpu_times_num = virHostCPUGetCountAppleFreeBSD();
-
- if (cpuNum >= cpu_times_num) {
- virReportInvalidArg(cpuNum,
- _("Invalid cpuNum in %s"),
- __FUNCTION__);
- return -1;
- }
-
- offset = cpu_times_num * CPUSTATES;
- }
-
- cpu_times_size = sizeof(long) * cpu_times_num * CPUSTATES;
-
- if (VIR_ALLOC_N(cpu_times, cpu_times_num * CPUSTATES) < 0)
- goto cleanup;
-
- if (sysctlbyname(sysctl_name, cpu_times, &cpu_times_size, NULL, 0) < 0) {
- virReportSystemError(errno,
- _("sysctl failed for '%s'"),
- sysctl_name);
- goto cleanup;
- }
-
- for (i = 0; cpu_map[i].field != NULL; i++) {
- virNodeCPUStatsPtr param = ¶ms[i];
-
- if (virStrcpyStatic(param->field, cpu_map[i].field) == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Field '%s' too long for destination"),
- cpu_map[i].field);
- goto cleanup;
- }
-
- param->value = 0;
- for (j = 0; j < ARRAY_CARDINALITY(cpu_map[i].idx); j++)
- param->value += cpu_times[offset + cpu_map[i].idx[j]] * TICK_TO_NSEC;
- }
-
- ret = 0;
-
- cleanup:
- VIR_FREE(cpu_times);
-
- return ret;
-}
-
static int
virHostMemGetStatsFreeBSD(virNodeMemoryStatsPtr params,
int *nparams)
@@ -263,26 +145,13 @@ virHostMemGetStatsFreeBSD(virNodeMemoryStatsPtr params,
#ifdef __linux__
# define SYSFS_SYSTEM_PATH "/sys/devices/system"
-# define CPUINFO_PATH "/proc/cpuinfo"
-# define PROCSTAT_PATH "/proc/stat"
# define MEMINFO_PATH "/proc/meminfo"
# define SYSFS_MEMORY_SHARED_PATH "/sys/kernel/mm/ksm"
# define SYSFS_THREAD_SIBLINGS_LIST_LENGTH_MAX 8192
-# define LINUX_NB_CPU_STATS 4
# define LINUX_NB_MEMORY_STATS_ALL 4
# define LINUX_NB_MEMORY_STATS_CELL 2
-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;
@@ -329,635 +198,6 @@ virNodeGetCpuValue(const char *dir, unsigned int cpu, const char
*file,
return value;
}
-static unsigned long
-virHostCPUCountThreadSiblings(const char *dir, unsigned int cpu)
-{
- unsigned long ret = 0;
- char *path;
- 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 */
- ret = 1;
- goto cleanup;
- }
-
- if (virFileReadAll(path, SYSFS_THREAD_SIBLINGS_LIST_LENGTH_MAX, &str) < 0)
- goto cleanup;
-
- for (i = 0; str[i] != '\0'; i++) {
- if (c_isxdigit(str[i]))
- ret += count_one_bits(virHexToBin(str[i]));
- }
-
- cleanup:
- VIR_FREE(str);
- VIR_FREE(path);
- return ret;
-}
-
-static int
-virHostCPUParseSocket(const char *dir,
- virArch arch,
- unsigned int cpu)
-{
- int ret = virNodeGetCpuValue(dir, cpu, "topology/physical_package_id", 0);
-
- 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;
- }
-
- return ret;
-}
-
-/* parses a node entry, returning number of processors in the node and
- * filling arguments */
-static int
-ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3)
-ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(6)
-ATTRIBUTE_NONNULL(7) ATTRIBUTE_NONNULL(8)
-ATTRIBUTE_NONNULL(9)
-virHostCPUParseNode(const char *node,
- virArch arch,
- virBitmapPtr present_cpus_map,
- virBitmapPtr online_cpus_map,
- int threads_per_subcore,
- int *sockets,
- int *cores,
- int *threads,
- int *offline)
-{
- /* Biggest value we can expect to be used as either socket id
- * or core id. Bitmaps will need to be sized accordingly */
- const int ID_MAX = 4095;
- int ret = -1;
- int processors = 0;
- DIR *cpudir = NULL;
- struct dirent *cpudirent = NULL;
- virBitmapPtr node_cpus_map = NULL;
- virBitmapPtr sockets_map = NULL;
- virBitmapPtr *cores_maps = NULL;
- int npresent_cpus = virBitmapSize(present_cpus_map);
- int sock_max = 0;
- int sock;
- int core;
- size_t i;
- int siblings;
- unsigned int cpu;
- int direrr;
-
- *threads = 0;
- *cores = 0;
- *sockets = 0;
-
- if (!(cpudir = opendir(node))) {
- virReportSystemError(errno, _("cannot opendir %s"), node);
- goto cleanup;
- }
-
- /* Keep track of the CPUs that belong to the current node */
- if (!(node_cpus_map = virBitmapNew(npresent_cpus)))
- goto cleanup;
-
- /* enumerate sockets in the node */
- if (!(sockets_map = virBitmapNew(ID_MAX + 1)))
- goto cleanup;
-
- while ((direrr = virDirRead(cpudir, &cpudirent, node)) > 0) {
- if (sscanf(cpudirent->d_name, "cpu%u", &cpu) != 1)
- continue;
-
- if (!virBitmapIsBitSet(present_cpus_map, cpu))
- continue;
-
- /* Mark this CPU as part of the current node */
- if (virBitmapSetBit(node_cpus_map, cpu) < 0)
- goto cleanup;
-
- if (!virBitmapIsBitSet(online_cpus_map, cpu))
- continue;
-
- /* Parse socket */
- if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
- goto cleanup;
- if (sock > ID_MAX) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Socket %d can't be handled (max socket is
%d)"),
- sock, ID_MAX);
- goto cleanup;
- }
-
- if (virBitmapSetBit(sockets_map, sock) < 0)
- goto cleanup;
-
- if (sock > sock_max)
- sock_max = sock;
- }
-
- if (direrr < 0)
- goto cleanup;
-
- sock_max++;
-
- /* allocate cores maps for each socket */
- if (VIR_ALLOC_N(cores_maps, sock_max) < 0)
- goto cleanup;
-
- for (i = 0; i < sock_max; i++)
- if (!(cores_maps[i] = virBitmapNew(ID_MAX + 1)))
- goto cleanup;
-
- /* Iterate over all CPUs in the node, in ascending order */
- for (cpu = 0; cpu < npresent_cpus; cpu++) {
-
- /* Skip CPUs that are not part of the current node */
- if (!virBitmapIsBitSet(node_cpus_map, cpu))
- continue;
-
- if (!virBitmapIsBitSet(online_cpus_map, cpu)) {
- if (threads_per_subcore > 0 &&
- cpu % threads_per_subcore != 0 &&
- virBitmapIsBitSet(online_cpus_map,
- cpu - (cpu % threads_per_subcore))) {
- /* Secondary offline threads are counted as online when
- * subcores are in use and the corresponding primary
- * thread is online */
- processors++;
- } else {
- /* But they are counted as offline otherwise */
- (*offline)++;
- }
- continue;
- }
-
- processors++;
-
- /* Parse socket */
- if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
- goto cleanup;
- if (!virBitmapIsBitSet(sockets_map, sock)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("CPU socket topology has changed"));
- goto cleanup;
- }
-
- /* Parse core */
- if (ARCH_IS_S390(arch)) {
- /* logical cpu is equivalent to a core on s390 */
- core = cpu;
- } else {
- if ((core = virNodeGetCpuValue(node, cpu,
- "topology/core_id", 0)) < 0)
- goto cleanup;
- }
- if (core > ID_MAX) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Core %d can't be handled (max core is %d)"),
- core, ID_MAX);
- goto cleanup;
- }
-
- if (virBitmapSetBit(cores_maps[sock], core) < 0)
- goto cleanup;
-
- if (!(siblings = virHostCPUCountThreadSiblings(node, cpu)))
- goto cleanup;
-
- if (siblings > *threads)
- *threads = siblings;
- }
-
- /* finalize the returned data */
- *sockets = virBitmapCountBits(sockets_map);
-
- for (i = 0; i < sock_max; i++) {
- if (!virBitmapIsBitSet(sockets_map, i))
- continue;
-
- core = virBitmapCountBits(cores_maps[i]);
- if (core > *cores)
- *cores = core;
- }
-
- if (threads_per_subcore > 0) {
- /* The thread count ignores offline threads, which means that only
- * only primary threads have been considered so far. If subcores
- * are in use, we need to also account for secondary threads */
- *threads *= threads_per_subcore;
- }
- ret = processors;
-
- cleanup:
- /* don't shadow a more serious error */
- if (cpudir && closedir(cpudir) < 0 && ret >= 0) {
- virReportSystemError(errno, _("problem closing %s"), node);
- ret = -1;
- }
- if (cores_maps)
- for (i = 0; i < sock_max; i++)
- virBitmapFree(cores_maps[i]);
- VIR_FREE(cores_maps);
- virBitmapFree(sockets_map);
- virBitmapFree(node_cpus_map);
-
- return ret;
-}
-
-/* Check whether the host subcore configuration is valid.
- *
- * A valid configuration is one where no secondary thread is online;
- * the primary thread in a subcore is always the first one */
-static bool
-virHostCPUHasValidSubcoreConfiguration(int threads_per_subcore)
-{
- virBitmapPtr online_cpus = NULL;
- int cpu = -1;
- bool ret = false;
-
- /* No point in checking if subcores are not in use */
- if (threads_per_subcore <= 0)
- goto cleanup;
-
- if (!(online_cpus = virHostCPUGetOnlineBitmap()))
- goto cleanup;
-
- while ((cpu = virBitmapNextSetBit(online_cpus, cpu)) >= 0) {
-
- /* A single online secondary thread is enough to
- * make the configuration invalid */
- if (cpu % threads_per_subcore != 0)
- goto cleanup;
- }
-
- ret = true;
-
- cleanup:
- virBitmapFree(online_cpus);
-
- return ret;
-}
-
-int
-virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
- virArch arch,
- unsigned int *cpus,
- unsigned int *mhz,
- unsigned int *nodes,
- unsigned int *sockets,
- unsigned int *cores,
- unsigned int *threads)
-{
- virBitmapPtr present_cpus_map = NULL;
- virBitmapPtr online_cpus_map = NULL;
- char line[1024];
- DIR *nodedir = NULL;
- struct dirent *nodedirent = NULL;
- int nodecpus, nodecores, nodesockets, nodethreads, offline = 0;
- int threads_per_subcore = 0;
- unsigned int node;
- int ret = -1;
- char *sysfs_nodedir = NULL;
- char *sysfs_cpudir = NULL;
- int direrr;
-
- *mhz = 0;
- *cpus = *nodes = *sockets = *cores = *threads = 0;
-
- /* Start with parsing CPU clock speed from /proc/cpuinfo */
- while (fgets(line, sizeof(line), cpuinfo) != NULL) {
- if (ARCH_IS_X86(arch)) {
- char *buf = line;
- if (STRPREFIX(buf, "cpu MHz")) {
- char *p;
- unsigned int ui;
-
- buf += 7;
- while (*buf && c_isspace(*buf))
- buf++;
-
- if (*buf != ':' || !buf[1]) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("parsing cpu MHz from cpuinfo"));
- goto cleanup;
- }
-
- if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
- /* Accept trailing fractional part. */
- (*p == '\0' || *p == '.' || c_isspace(*p)))
- *mhz = ui;
- }
- } else if (ARCH_IS_PPC(arch)) {
- char *buf = line;
- if (STRPREFIX(buf, "clock")) {
- char *p;
- unsigned int ui;
-
- buf += 5;
- while (*buf && c_isspace(*buf))
- buf++;
-
- if (*buf != ':' || !buf[1]) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("parsing cpu MHz from cpuinfo"));
- goto cleanup;
- }
-
- if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
- /* Accept trailing fractional part. */
- (*p == '\0' || *p == '.' || c_isspace(*p)))
- *mhz = ui;
- /* No other interesting infos are available in /proc/cpuinfo.
- * However, there is a line identifying processor's version,
- * identification and machine, but we don't want it to be caught
- * and parsed in next iteration, because it is not in expected
- * format and thus lead to error. */
- }
- } else if (ARCH_IS_ARM(arch)) {
- char *buf = line;
- if (STRPREFIX(buf, "BogoMIPS")) {
- char *p;
- unsigned int ui;
-
- buf += 8;
- while (*buf && c_isspace(*buf))
- buf++;
-
- if (*buf != ':' || !buf[1]) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("parsing cpu MHz from
cpuinfo"));
- goto cleanup;
- }
-
- if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
- /* Accept trailing fractional part. */
- && (*p == '\0' || *p == '.' ||
c_isspace(*p)))
- *mhz = ui;
- }
- } else if (ARCH_IS_S390(arch)) {
- /* s390x has no realistic value for CPU speed,
- * assign a value of zero to signify this */
- *mhz = 0;
- } else {
- VIR_WARN("Parser for /proc/cpuinfo needs to be adapted for your
architecture");
- break;
- }
- }
-
- /* Get information about what CPUs are present in the host and what
- * CPUs are online, so that we don't have to so for each node */
- present_cpus_map = virHostCPUGetPresentBitmap();
- if (!present_cpus_map)
- goto cleanup;
- online_cpus_map = virHostCPUGetOnlineBitmap();
- if (!online_cpus_map)
- goto cleanup;
-
- /* 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)
- goto cleanup;
-
- if (!(nodedir = opendir(sysfs_nodedir))) {
- /* the host isn't probably running a NUMA architecture */
- goto fallback;
- }
-
- /* PPC-KVM needs the secondary threads of a core to be offline on the
- * host. The kvm scheduler brings the secondary threads online in the
- * guest context. Moreover, P8 processor has split-core capability
- * where, there can be 1,2 or 4 subcores per core. The primaries of the
- * subcores alone will be online on the host for a subcore in the
- * host. Even though the actual threads per core for P8 processor is 8,
- * depending on the subcores_per_core = 1, 2 or 4, the threads per
- * subcore will vary accordingly to 8, 4 and 2 repectively.
- * So, On host threads_per_core what is arrived at from sysfs in the
- * current logic is actually the subcores_per_core. Threads per subcore
- * can only be obtained from the kvm device. For example, on P8 wih 1
- * core having 8 threads, sub_cores_percore=4, the threads 0,2,4 & 6
- * will be online. The sysfs reflects this and in the current logic
- * variable 'threads' will be 4 which is nothing but subcores_per_core.
- * If the user tampers the cpu online/offline states using chcpu or other
- * means, then it is an unsupported configuration for kvm.
- * The code below tries to keep in mind
- * - when the libvirtd is run inside a KVM guest or Phyp based guest.
- * - Or on the kvm host where user manually tampers the cpu states to
- * offline/online randomly.
- * On hosts other than POWER this will be 0, in which case a simpler
- * thread-counting logic will be used */
- if ((threads_per_subcore = virHostCPUGetThreadsPerSubcore(arch)) < 0)
- goto cleanup;
-
- /* If the subcore configuration is not valid, just pretend subcores
- * are not in use and count threads one by one */
- if (!virHostCPUHasValidSubcoreConfiguration(threads_per_subcore))
- threads_per_subcore = 0;
-
- while ((direrr = virDirRead(nodedir, &nodedirent, sysfs_nodedir)) > 0) {
- if (sscanf(nodedirent->d_name, "node%u", &node) != 1)
- continue;
-
- (*nodes)++;
-
- if (virAsprintf(&sysfs_cpudir, "%s/node/%s",
- sysfs_system_path, nodedirent->d_name) < 0)
- goto cleanup;
-
- if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
- present_cpus_map,
- online_cpus_map,
- threads_per_subcore,
- &nodesockets, &nodecores,
- &nodethreads, &offline)) < 0)
- goto cleanup;
-
- VIR_FREE(sysfs_cpudir);
-
- *cpus += nodecpus;
-
- if (nodesockets > *sockets)
- *sockets = nodesockets;
-
- if (nodecores > *cores)
- *cores = nodecores;
-
- if (nodethreads > *threads)
- *threads = nodethreads;
- }
-
- if (direrr < 0)
- goto cleanup;
-
- if (*cpus && *nodes)
- goto done;
-
- fallback:
- VIR_FREE(sysfs_cpudir);
-
- if (virAsprintf(&sysfs_cpudir, "%s/cpu", sysfs_system_path) < 0)
- goto cleanup;
-
- if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
- present_cpus_map,
- online_cpus_map,
- threads_per_subcore,
- &nodesockets, &nodecores,
- &nodethreads, &offline)) < 0)
- goto cleanup;
-
- *nodes = 1;
- *cpus = nodecpus;
- *sockets = nodesockets;
- *cores = nodecores;
- *threads = nodethreads;
-
- done:
- /* There should always be at least one cpu, socket, node, and thread. */
- if (*cpus == 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no CPUs
found"));
- goto cleanup;
- }
-
- if (*sockets == 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no sockets
found"));
- goto cleanup;
- }
-
- if (*threads == 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no threads
found"));
- 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 ((*nodes *
- *sockets *
- *cores *
- *threads) != (*cpus + offline)) {
- *nodes = 1;
- *sockets = 1;
- *cores = *cpus + offline;
- *threads = 1;
- }
-
- ret = 0;
-
- cleanup:
- /* don't shadow a more serious error */
- if (nodedir && closedir(nodedir) < 0 && ret >= 0) {
- virReportSystemError(errno, _("problem closing %s"), sysfs_nodedir);
- ret = -1;
- }
-
- virBitmapFree(present_cpus_map);
- virBitmapFree(online_cpus_map);
- VIR_FREE(sysfs_nodedir);
- VIR_FREE(sysfs_cpudir);
- return ret;
-}
-
-static int
-virHostCPUStatsAssign(virNodeCPUStatsPtr param,
- const char *name,
- unsigned long long value)
-{
- if (virStrcpyStatic(param->field, name) == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("kernel cpu time field is too long"
- " for the destination"));
- return -1;
- }
- param->value = value;
- return 0;
-}
-
-# define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK))
-
-int
-virHostCPUGetStatsLinux(FILE *procstat,
- int cpuNum,
- virNodeCPUStatsPtr params,
- int *nparams)
-{
- int ret = -1;
- char line[1024];
- unsigned long long usr, ni, sys, idle, iowait;
- unsigned long long irq, softirq, steal, guest, guest_nice;
- char cpu_header[4 + INT_BUFSIZE_BOUND(cpuNum)];
-
- if ((*nparams) == 0) {
- /* Current number of cpu stats supported by linux */
- *nparams = LINUX_NB_CPU_STATS;
- ret = 0;
- goto cleanup;
- }
-
- if ((*nparams) != LINUX_NB_CPU_STATS) {
- virReportInvalidArg(*nparams,
- _("nparams in %s must be equal to %d"),
- __FUNCTION__, LINUX_NB_CPU_STATS);
- goto cleanup;
- }
-
- if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) {
- strcpy(cpu_header, "cpu ");
- } else {
- snprintf(cpu_header, sizeof(cpu_header), "cpu%d ", cpuNum);
- }
-
- while (fgets(line, sizeof(line), procstat) != NULL) {
- char *buf = line;
-
- if (STRPREFIX(buf, cpu_header)) { /* aka logical CPU time */
- if (sscanf(buf,
- "%*s %llu %llu %llu %llu %llu" // user ~ iowait
- "%llu %llu %llu %llu %llu", // irq ~ guest_nice
- &usr, &ni, &sys, &idle, &iowait,
- &irq, &softirq, &steal, &guest, &guest_nice)
< 4) {
- continue;
- }
-
- if (virHostCPUStatsAssign(¶ms[0], VIR_NODE_CPU_STATS_KERNEL,
- (sys + irq + softirq) * TICK_TO_NSEC) < 0)
- goto cleanup;
-
- if (virHostCPUStatsAssign(¶ms[1], VIR_NODE_CPU_STATS_USER,
- (usr + ni) * TICK_TO_NSEC) < 0)
- goto cleanup;
-
- if (virHostCPUStatsAssign(¶ms[2], VIR_NODE_CPU_STATS_IDLE,
- idle * TICK_TO_NSEC) < 0)
- goto cleanup;
-
- if (virHostCPUStatsAssign(¶ms[3], VIR_NODE_CPU_STATS_IOWAIT,
- iowait * TICK_TO_NSEC) < 0)
- goto cleanup;
-
- ret = 0;
- goto cleanup;
- }
- }
-
- virReportInvalidArg(cpuNum,
- _("Invalid cpuNum in %s"),
- __FUNCTION__);
-
- cleanup:
- return ret;
-}
static int
virHostMemGetStatsLinux(FILE *meminfo,
@@ -1065,84 +305,6 @@ virHostMemGetStatsLinux(FILE *meminfo,
return ret;
}
-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)
-{
- char *str = NULL;
- char *tmp;
- int ret = -1;
-
- if (virFileReadAll(path, 5 * VIR_DOMAIN_CPUMASK_LEN, &str) < 0)
- 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 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_DOMAIN_CPUMASK_LEN, &str) < 0)
- goto error;
-
- if (virBitmapParse(str, 0, &map, max_cpuid) < 0)
- goto error;
-
- VIR_FREE(str);
- return map;
-
- error:
- VIR_FREE(str);
- virBitmapFree(map);
- return NULL;
-}
-
static virBitmapPtr
virNodeGetSiblingsListLinux(const char *dir, int cpu_id)
@@ -1169,73 +331,6 @@ virNodeGetSiblingsListLinux(const char *dir, int cpu_id)
#endif
-static int
-virHostCPUGetInfo(virArch hostarch,
- unsigned int *cpus,
- unsigned int *mhz,
- unsigned int *nodes,
- unsigned int *sockets,
- unsigned int *cores,
- unsigned int *threads)
-{
-#ifdef __linux__
- int ret = -1;
- FILE *cpuinfo = fopen(CPUINFO_PATH, "r");
-
- if (!cpuinfo) {
- virReportSystemError(errno,
- _("cannot open %s"), CPUINFO_PATH);
- return -1;
- }
-
- ret = virHostCPUGetInfoPopulateLinux(cpuinfo, hostarch,
- cpus, mhz, nodes,
- sockets, cores, threads);
- if (ret < 0)
- goto cleanup;
-
- cleanup:
- VIR_FORCE_FCLOSE(cpuinfo);
- return ret;
-#elif defined(__FreeBSD__) || defined(__APPLE__)
- unsigned long cpu_freq;
- size_t cpu_freq_len = sizeof(cpu_freq);
-
- *cpus = virHostCPUGetCountAppleFreeBSD();
- if (*cpus == -1)
- return -1;
-
- *nodes = 1;
- *sockets = 1;
- *cores = *cpus;
- *threads = 1;
-
-# ifdef __FreeBSD__
- if (sysctlbyname("dev.cpu.0.freq", &cpu_freq, &cpu_freq_len, NULL,
0) < 0) {
- virReportSystemError(errno, "%s", _("cannot obtain CPU
freq"));
- return -1;
- }
-
- *mhz = cpu_freq;
-# else
- if (sysctlbyname("hw.cpufrequency", &cpu_freq, &cpu_freq_len, NULL,
0) < 0) {
- virReportSystemError(errno, "%s", _("cannot obtain CPU
freq"));
- return -1;
- }
-
- *mhz = cpu_freq / 1000000;
-# endif
-
- return 0;
-#else
- /* XXX Solaris will need an impl later if they port QEMU driver */
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("node info not implemented on this platform"));
- return -1;
-#endif
-}
-
-
int
nodeGetInfo(virNodeInfoPtr nodeinfo)
{
@@ -1260,36 +355,6 @@ nodeGetInfo(virNodeInfoPtr nodeinfo)
return 0;
}
-int
-virHostCPUGetStats(int cpuNum ATTRIBUTE_UNUSED,
- virNodeCPUStatsPtr params ATTRIBUTE_UNUSED,
- int *nparams ATTRIBUTE_UNUSED,
- unsigned int flags)
-{
- virCheckFlags(0, -1);
-
-#ifdef __linux__
- {
- int ret;
- FILE *procstat = fopen(PROCSTAT_PATH, "r");
- if (!procstat) {
- virReportSystemError(errno,
- _("cannot open %s"), PROCSTAT_PATH);
- return -1;
- }
- ret = virHostCPUGetStatsLinux(procstat, cpuNum, params, nparams);
- VIR_FORCE_FCLOSE(procstat);
-
- return ret;
- }
-#elif defined(__FreeBSD__)
- return virHostCPUGetStatsFreeBSD(cpuNum, params, nparams);
-#else
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("node CPU stats not implemented on this platform"));
- return -1;
-#endif
-}
int
virHostMemGetStats(int cellNum ATTRIBUTE_UNUSED,
@@ -1348,146 +413,6 @@ virHostMemGetStats(int cellNum ATTRIBUTE_UNUSED,
#endif
}
-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;
-#elif defined(__FreeBSD__) || defined(__APPLE__)
- return virHostCPUGetCountAppleFreeBSD();
-#else
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("host cpu counting not implemented on this platform"));
- return -1;
-#endif
-}
-
-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;
-
- /* 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);
-
- return present_cpus;
-#endif
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("node present CPU map not implemented on this
platform"));
- return NULL;
-}
-
-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;
-
- if (virAsprintf(&cpudir, "%s/cpu", sysfs_system_path) < 0)
- goto cleanup;
-
- for (i = 0; i < present; i++) {
- int online = virNodeGetCpuValue(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;
-#else
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("node online CPU map not implemented on this platform"));
- return NULL;
-#endif
-}
#ifdef __linux__
static int
@@ -1791,36 +716,6 @@ virHostMemGetParameters(virTypedParameterPtr params
ATTRIBUTE_UNUSED,
#endif
}
-int
-virHostCPUGetMap(unsigned char **cpumap,
- unsigned int *online,
- unsigned int flags)
-{
- virBitmapPtr cpus = NULL;
- int ret = -1;
- int dummy;
-
- virCheckFlags(0, -1);
-
- if (!cpumap && !online)
- return virHostCPUGetCount();
-
- if (!(cpus = virHostCPUGetOnlineBitmap()))
- goto cleanup;
-
- if (cpumap && virBitmapToData(cpus, cpumap, &dummy) < 0)
- goto cleanup;
- if (online)
- *online = virBitmapCountBits(cpus);
-
- ret = virBitmapSize(cpus);
-
- cleanup:
- if (ret < 0 && cpumap)
- VIR_FREE(*cpumap);
- virBitmapFree(cpus);
- return ret;
-}
static int
nodeCapsInitNUMAFake(const char *cpupath ATTRIBUTE_UNUSED,
@@ -2329,67 +1224,3 @@ virHostMemAllocPages(unsigned int npages,
cleanup:
return ret;
}
-
-#if HAVE_LINUX_KVM_H && defined(KVM_CAP_PPC_SMT)
-
-/* Get the number of threads per subcore.
- *
- * This will be 2, 4 or 8 on POWER hosts, depending on the current
- * micro-threading configuration, and 0 everywhere else.
- *
- * Returns the number of threads per subcore if subcores are in use, zero
- * if subcores are not in use, and a negative value on error */
-int
-virHostCPUGetThreadsPerSubcore(virArch arch)
-{
- int threads_per_subcore = 0;
- const char *kvmpath = "/dev/kvm";
- int kvmfd;
-
- if (ARCH_IS_PPC64(arch)) {
-
- /* It's okay if /dev/kvm doesn't exist, because
- * a. we might be running in a guest
- * b. the kvm module might not be installed or enabled
- * In either case, falling back to the subcore-unaware thread
- * counting logic is the right thing to do */
- if (!virFileExists(kvmpath))
- goto out;
-
- if ((kvmfd = open(kvmpath, O_RDONLY)) < 0) {
- /* This can happen when running as a regular user if
- * permissions are tight enough, in which case erroring out
- * is better than silently falling back and reporting
- * different nodeinfo depending on the user */
- virReportSystemError(errno,
- _("Failed to open '%s'"),
- kvmpath);
- threads_per_subcore = -1;
- goto out;
- }
-
- /* For Phyp and KVM based guests the ioctl for KVM_CAP_PPC_SMT
- * returns zero and both primary and secondary threads will be
- * online */
- threads_per_subcore = ioctl(kvmfd,
- KVM_CHECK_EXTENSION,
- KVM_CAP_PPC_SMT);
-
- VIR_FORCE_CLOSE(kvmfd);
- }
-
- out:
- return threads_per_subcore;
-}
-
-#else
-
-/* Fallback for nodeGetThreadsPerSubcore() used when KVM headers
- * are not available on the system */
-int
-virHostCPUGetThreadsPerSubcore(virArch arch ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-#endif /* HAVE_LINUX_KVM_H && defined(KVM_CAP_PPC_SMT) */
diff --git a/src/nodeinfo.h b/src/nodeinfo.h
index 08b9f9d..918fcb5 100644
--- a/src/nodeinfo.h
+++ b/src/nodeinfo.h
@@ -29,10 +29,6 @@
int nodeGetInfo(virNodeInfoPtr nodeinfo);
int nodeCapsInitNUMA(virCapsPtr caps);
-int virHostCPUGetStats(int cpuNum,
- virNodeCPUStatsPtr params,
- int *nparams,
- unsigned int flags);
int virHostMemGetStats(int cellNum,
virNodeMemoryStatsPtr params,
int *nparams,
@@ -43,11 +39,6 @@ int virHostMemGetCellsFree(unsigned long long *freeMems,
int virHostMemGetInfo(unsigned long long *mem,
unsigned long long *freeMem);
-virBitmapPtr virHostCPUGetPresentBitmap(void);
-virBitmapPtr virHostCPUGetOnlineBitmap(void);
-int virHostCPUGetCount(void);
-int virHostCPUGetThreadsPerSubcore(virArch arch);
-
int virHostMemGetParameters(virTypedParameterPtr params,
int *nparams,
unsigned int flags);
@@ -56,10 +47,6 @@ int virHostMemSetParameters(virTypedParameterPtr params,
int nparams,
unsigned int flags);
-int virHostCPUGetMap(unsigned char **cpumap,
- unsigned int *online,
- unsigned int flags);
-
int virHostMemGetFreePages(unsigned int npages,
unsigned int *pages,
int startCell,
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index ef11745..910ccfe 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -49,6 +49,7 @@
#include "virbuffer.h"
#include "openvz_conf.h"
#include "nodeinfo.h"
+#include "virhostcpu.h"
#include "viralloc.h"
#include "virfile.h"
#include "virtypedparam.h"
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 38aab15..ec04fb7 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -63,6 +63,7 @@
#include "datatypes.h"
#include "virbuffer.h"
#include "nodeinfo.h"
+#include "virhostcpu.h"
#include "virstats.h"
#include "capabilities.h"
#include "viralloc.h"
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 7d01e38..5ae38bf 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -54,7 +54,7 @@
#include "virhook.h"
#include "virfile.h"
#include "virpidfile.h"
-#include "nodeinfo.h"
+#include "virhostcpu.h"
#include "domain_audit.h"
#include "domain_nwfilter.h"
#include "locking/domain_lock.h"
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index 19ba901..4048b11 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -46,6 +46,7 @@
#include "uml_conf.h"
#include "virbuffer.h"
#include "nodeinfo.h"
+#include "virhostcpu.h"
#include "virstats.h"
#include "capabilities.h"
#include "viralloc.h"
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index 05097f8..0124dbe 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -52,8 +52,7 @@
#include "virstring.h"
#include "virsystemd.h"
#include "virtypedparam.h"
-
-#include "nodeinfo.h"
+#include "virhostcpu.h"
VIR_LOG_INIT("util.cgroup");
diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
new file mode 100644
index 0000000..72ea943
--- /dev/null
+++ b/src/util/virhostcpu.c
@@ -0,0 +1,1299 @@
+/*
+ * virhostcpu.c: helper APIs for host CPU info
+ *
+ * Copyright (C) 2006-2016 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+#include <dirent.h>
+#include <sys/utsname.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#if HAVE_LINUX_KVM_H
+# include <linux/kvm.h>
+#endif
+
+#if defined(__FreeBSD__) || defined(__APPLE__)
+# include <sys/time.h>
+# include <sys/types.h>
+# include <sys/sysctl.h>
+# include <sys/resource.h>
+#endif
+
+#include "c-ctype.h"
+#include "viralloc.h"
+#include "virhostcpupriv.h"
+#include "physmem.h"
+#include "virerror.h"
+#include "count-one-bits.h"
+#include "intprops.h"
+#include "virarch.h"
+#include "virfile.h"
+#include "virtypedparam.h"
+#include "virstring.h"
+#include "virnuma.h"
+#include "virlog.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_LOG_INIT("util.hostcpu");
+
+
+#if defined(__FreeBSD__) || defined(__APPLE__)
+static int
+virHostCPUGetCountAppleFreeBSD(void)
+{
+ int ncpu_mib[2] = { CTL_HW, HW_NCPU };
+ unsigned long ncpu;
+ size_t ncpu_len = sizeof(ncpu);
+
+ if (sysctl(ncpu_mib, 2, &ncpu, &ncpu_len, NULL, 0) == -1) {
+ virReportSystemError(errno, "%s", _("Cannot obtain CPU
count"));
+ return -1;
+ }
+
+ return ncpu;
+}
+#endif /* defined(__FreeBSD__) || defined(__APPLE__) */
+
+#ifdef __FreeBSD__
+# define BSD_CPU_STATS_ALL 4
+# define BSD_MEMORY_STATS_ALL 4
+
+# define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / (stathz ? stathz : hz))
+
+static int
+virHostCPUGetStatsFreebsd(int cpuNum,
+ virNodeCPUStatsPtr params,
+ int *nparams)
+{
+ const char *sysctl_name;
+ long *cpu_times;
+ struct clockinfo clkinfo;
+ size_t i, j, cpu_times_size, clkinfo_size;
+ int cpu_times_num, offset, hz, stathz, ret = -1;
+ struct field_cpu_map {
+ const char *field;
+ int idx[CPUSTATES];
+ } cpu_map[] = {
+ {VIR_NODE_CPU_STATS_KERNEL, {CP_SYS}},
+ {VIR_NODE_CPU_STATS_USER, {CP_USER, CP_NICE}},
+ {VIR_NODE_CPU_STATS_IDLE, {CP_IDLE}},
+ {VIR_NODE_CPU_STATS_INTR, {CP_INTR}},
+ {NULL, {0}}
+ };
+
+ if ((*nparams) == 0) {
+ *nparams = BSD_CPU_STATS_ALL;
+ return 0;
+ }
+
+ if ((*nparams) != BSD_CPU_STATS_ALL) {
+ virReportInvalidArg(*nparams,
+ _("nparams in %s must be equal to %d"),
+ __FUNCTION__, BSD_CPU_STATS_ALL);
+ return -1;
+ }
+
+ clkinfo_size = sizeof(clkinfo);
+ if (sysctlbyname("kern.clockrate", &clkinfo, &clkinfo_size, NULL,
0) < 0) {
+ virReportSystemError(errno,
+ _("sysctl failed for '%s'"),
+ "kern.clockrate");
+ return -1;
+ }
+
+ stathz = clkinfo.stathz;
+ hz = clkinfo.hz;
+
+ if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) {
+ sysctl_name = "kern.cp_time";
+ cpu_times_num = 1;
+ offset = 0;
+ } else {
+ sysctl_name = "kern.cp_times";
+ cpu_times_num = virHostCPUGetCountAppleFreeBSD();
+
+ if (cpuNum >= cpu_times_num) {
+ virReportInvalidArg(cpuNum,
+ _("Invalid cpuNum in %s"),
+ __FUNCTION__);
+ return -1;
+ }
+
+ offset = cpu_times_num * CPUSTATES;
+ }
+
+ cpu_times_size = sizeof(long) * cpu_times_num * CPUSTATES;
+
+ if (VIR_ALLOC_N(cpu_times, cpu_times_num * CPUSTATES) < 0)
+ goto cleanup;
+
+ if (sysctlbyname(sysctl_name, cpu_times, &cpu_times_size, NULL, 0) < 0) {
+ virReportSystemError(errno,
+ _("sysctl failed for '%s'"),
+ sysctl_name);
+ goto cleanup;
+ }
+
+ for (i = 0; cpu_map[i].field != NULL; i++) {
+ virNodeCPUStatsPtr param = ¶ms[i];
+
+ if (virStrcpyStatic(param->field, cpu_map[i].field) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Field '%s' too long for destination"),
+ cpu_map[i].field);
+ goto cleanup;
+ }
+
+ param->value = 0;
+ for (j = 0; j < ARRAY_CARDINALITY(cpu_map[i].idx); j++)
+ param->value += cpu_times[offset + cpu_map[i].idx[j]] * TICK_TO_NSEC;
+ }
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(cpu_times);
+
+ return ret;
+}
+
+#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 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)
+{
+ unsigned long ret = 0;
+ char *path;
+ 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 */
+ ret = 1;
+ goto cleanup;
+ }
+
+ if (virFileReadAll(path, SYSFS_THREAD_SIBLINGS_LIST_LENGTH_MAX, &str) < 0)
+ goto cleanup;
+
+ for (i = 0; str[i] != '\0'; i++) {
+ if (c_isxdigit(str[i]))
+ ret += count_one_bits(virHexToBin(str[i]));
+ }
+
+ cleanup:
+ VIR_FREE(str);
+ VIR_FREE(path);
+ return ret;
+}
+
+static int
+virHostCPUParseSocket(const char *dir,
+ virArch arch,
+ unsigned int cpu)
+{
+ int ret = virHostCPUGetValue(dir, cpu, "topology/physical_package_id", 0);
+
+ 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;
+ }
+
+ return ret;
+}
+
+/* parses a node entry, returning number of processors in the node and
+ * filling arguments */
+static int
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3)
+ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(6)
+ATTRIBUTE_NONNULL(7) ATTRIBUTE_NONNULL(8)
+ATTRIBUTE_NONNULL(9)
+virHostCPUParseNode(const char *node,
+ virArch arch,
+ virBitmapPtr present_cpus_map,
+ virBitmapPtr online_cpus_map,
+ int threads_per_subcore,
+ int *sockets,
+ int *cores,
+ int *threads,
+ int *offline)
+{
+ /* Biggest value we can expect to be used as either socket id
+ * or core id. Bitmaps will need to be sized accordingly */
+ const int ID_MAX = 4095;
+ int ret = -1;
+ int processors = 0;
+ DIR *cpudir = NULL;
+ struct dirent *cpudirent = NULL;
+ virBitmapPtr node_cpus_map = NULL;
+ virBitmapPtr sockets_map = NULL;
+ virBitmapPtr *cores_maps = NULL;
+ int npresent_cpus = virBitmapSize(present_cpus_map);
+ int sock_max = 0;
+ int sock;
+ int core;
+ size_t i;
+ int siblings;
+ unsigned int cpu;
+ int direrr;
+
+ *threads = 0;
+ *cores = 0;
+ *sockets = 0;
+
+ if (!(cpudir = opendir(node))) {
+ virReportSystemError(errno, _("cannot opendir %s"), node);
+ goto cleanup;
+ }
+
+ /* Keep track of the CPUs that belong to the current node */
+ if (!(node_cpus_map = virBitmapNew(npresent_cpus)))
+ goto cleanup;
+
+ /* enumerate sockets in the node */
+ if (!(sockets_map = virBitmapNew(ID_MAX + 1)))
+ goto cleanup;
+
+ while ((direrr = virDirRead(cpudir, &cpudirent, node)) > 0) {
+ if (sscanf(cpudirent->d_name, "cpu%u", &cpu) != 1)
+ continue;
+
+ if (!virBitmapIsBitSet(present_cpus_map, cpu))
+ continue;
+
+ /* Mark this CPU as part of the current node */
+ if (virBitmapSetBit(node_cpus_map, cpu) < 0)
+ goto cleanup;
+
+ if (!virBitmapIsBitSet(online_cpus_map, cpu))
+ continue;
+
+ /* Parse socket */
+ if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
+ goto cleanup;
+ if (sock > ID_MAX) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Socket %d can't be handled (max socket is
%d)"),
+ sock, ID_MAX);
+ goto cleanup;
+ }
+
+ if (virBitmapSetBit(sockets_map, sock) < 0)
+ goto cleanup;
+
+ if (sock > sock_max)
+ sock_max = sock;
+ }
+
+ if (direrr < 0)
+ goto cleanup;
+
+ sock_max++;
+
+ /* allocate cores maps for each socket */
+ if (VIR_ALLOC_N(cores_maps, sock_max) < 0)
+ goto cleanup;
+
+ for (i = 0; i < sock_max; i++)
+ if (!(cores_maps[i] = virBitmapNew(ID_MAX + 1)))
+ goto cleanup;
+
+ /* Iterate over all CPUs in the node, in ascending order */
+ for (cpu = 0; cpu < npresent_cpus; cpu++) {
+
+ /* Skip CPUs that are not part of the current node */
+ if (!virBitmapIsBitSet(node_cpus_map, cpu))
+ continue;
+
+ if (!virBitmapIsBitSet(online_cpus_map, cpu)) {
+ if (threads_per_subcore > 0 &&
+ cpu % threads_per_subcore != 0 &&
+ virBitmapIsBitSet(online_cpus_map,
+ cpu - (cpu % threads_per_subcore))) {
+ /* Secondary offline threads are counted as online when
+ * subcores are in use and the corresponding primary
+ * thread is online */
+ processors++;
+ } else {
+ /* But they are counted as offline otherwise */
+ (*offline)++;
+ }
+ continue;
+ }
+
+ processors++;
+
+ /* Parse socket */
+ if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
+ goto cleanup;
+ if (!virBitmapIsBitSet(sockets_map, sock)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("CPU socket topology has changed"));
+ goto cleanup;
+ }
+
+ /* Parse core */
+ if (ARCH_IS_S390(arch)) {
+ /* logical cpu is equivalent to a core on s390 */
+ core = cpu;
+ } else {
+ if ((core = virHostCPUGetValue(node, cpu,
+ "topology/core_id", 0)) < 0)
+ goto cleanup;
+ }
+ if (core > ID_MAX) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Core %d can't be handled (max core is %d)"),
+ core, ID_MAX);
+ goto cleanup;
+ }
+
+ if (virBitmapSetBit(cores_maps[sock], core) < 0)
+ goto cleanup;
+
+ if (!(siblings = virHostCPUCountThreadSiblings(node, cpu)))
+ goto cleanup;
+
+ if (siblings > *threads)
+ *threads = siblings;
+ }
+
+ /* finalize the returned data */
+ *sockets = virBitmapCountBits(sockets_map);
+
+ for (i = 0; i < sock_max; i++) {
+ if (!virBitmapIsBitSet(sockets_map, i))
+ continue;
+
+ core = virBitmapCountBits(cores_maps[i]);
+ if (core > *cores)
+ *cores = core;
+ }
+
+ if (threads_per_subcore > 0) {
+ /* The thread count ignores offline threads, which means that only
+ * only primary threads have been considered so far. If subcores
+ * are in use, we need to also account for secondary threads */
+ *threads *= threads_per_subcore;
+ }
+ ret = processors;
+
+ cleanup:
+ /* don't shadow a more serious error */
+ if (cpudir && closedir(cpudir) < 0 && ret >= 0) {
+ virReportSystemError(errno, _("problem closing %s"), node);
+ ret = -1;
+ }
+ if (cores_maps)
+ for (i = 0; i < sock_max; i++)
+ virBitmapFree(cores_maps[i]);
+ VIR_FREE(cores_maps);
+ virBitmapFree(sockets_map);
+ virBitmapFree(node_cpus_map);
+
+ return ret;
+}
+
+/* Check whether the host subcore configuration is valid.
+ *
+ * A valid configuration is one where no secondary thread is online;
+ * the primary thread in a subcore is always the first one */
+static bool
+virHostCPUHasValidSubcoreConfiguration(int threads_per_subcore)
+{
+ virBitmapPtr online_cpus = NULL;
+ int cpu = -1;
+ bool ret = false;
+
+ /* No point in checking if subcores are not in use */
+ if (threads_per_subcore <= 0)
+ goto cleanup;
+
+ if (!(online_cpus = virHostCPUGetOnlineBitmap()))
+ goto cleanup;
+
+ while ((cpu = virBitmapNextSetBit(online_cpus, cpu)) >= 0) {
+
+ /* A single online secondary thread is enough to
+ * make the configuration invalid */
+ if (cpu % threads_per_subcore != 0)
+ goto cleanup;
+ }
+
+ ret = true;
+
+ cleanup:
+ virBitmapFree(online_cpus);
+
+ return ret;
+}
+
+int
+virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
+ virArch arch,
+ unsigned int *cpus,
+ unsigned int *mhz,
+ unsigned int *nodes,
+ unsigned int *sockets,
+ unsigned int *cores,
+ unsigned int *threads)
+{
+ virBitmapPtr present_cpus_map = NULL;
+ virBitmapPtr online_cpus_map = NULL;
+ char line[1024];
+ DIR *nodedir = NULL;
+ struct dirent *nodedirent = NULL;
+ int nodecpus, nodecores, nodesockets, nodethreads, offline = 0;
+ int threads_per_subcore = 0;
+ unsigned int node;
+ int ret = -1;
+ char *sysfs_nodedir = NULL;
+ char *sysfs_cpudir = NULL;
+ int direrr;
+
+ *mhz = 0;
+ *cpus = *nodes = *sockets = *cores = *threads = 0;
+
+ /* Start with parsing CPU clock speed from /proc/cpuinfo */
+ while (fgets(line, sizeof(line), cpuinfo) != NULL) {
+ if (ARCH_IS_X86(arch)) {
+ char *buf = line;
+ if (STRPREFIX(buf, "cpu MHz")) {
+ char *p;
+ unsigned int ui;
+
+ buf += 7;
+ while (*buf && c_isspace(*buf))
+ buf++;
+
+ if (*buf != ':' || !buf[1]) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("parsing cpu MHz from cpuinfo"));
+ goto cleanup;
+ }
+
+ if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
+ /* Accept trailing fractional part. */
+ (*p == '\0' || *p == '.' || c_isspace(*p)))
+ *mhz = ui;
+ }
+ } else if (ARCH_IS_PPC(arch)) {
+ char *buf = line;
+ if (STRPREFIX(buf, "clock")) {
+ char *p;
+ unsigned int ui;
+
+ buf += 5;
+ while (*buf && c_isspace(*buf))
+ buf++;
+
+ if (*buf != ':' || !buf[1]) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("parsing cpu MHz from cpuinfo"));
+ goto cleanup;
+ }
+
+ if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
+ /* Accept trailing fractional part. */
+ (*p == '\0' || *p == '.' || c_isspace(*p)))
+ *mhz = ui;
+ /* No other interesting infos are available in /proc/cpuinfo.
+ * However, there is a line identifying processor's version,
+ * identification and machine, but we don't want it to be caught
+ * and parsed in next iteration, because it is not in expected
+ * format and thus lead to error. */
+ }
+ } else if (ARCH_IS_ARM(arch)) {
+ char *buf = line;
+ if (STRPREFIX(buf, "BogoMIPS")) {
+ char *p;
+ unsigned int ui;
+
+ buf += 8;
+ while (*buf && c_isspace(*buf))
+ buf++;
+
+ if (*buf != ':' || !buf[1]) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("parsing cpu MHz from
cpuinfo"));
+ goto cleanup;
+ }
+
+ if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
+ /* Accept trailing fractional part. */
+ && (*p == '\0' || *p == '.' ||
c_isspace(*p)))
+ *mhz = ui;
+ }
+ } else if (ARCH_IS_S390(arch)) {
+ /* s390x has no realistic value for CPU speed,
+ * assign a value of zero to signify this */
+ *mhz = 0;
+ } else {
+ VIR_WARN("Parser for /proc/cpuinfo needs to be adapted for your
architecture");
+ break;
+ }
+ }
+
+ /* Get information about what CPUs are present in the host and what
+ * CPUs are online, so that we don't have to so for each node */
+ present_cpus_map = virHostCPUGetPresentBitmap();
+ if (!present_cpus_map)
+ goto cleanup;
+ online_cpus_map = virHostCPUGetOnlineBitmap();
+ if (!online_cpus_map)
+ goto cleanup;
+
+ /* 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)
+ goto cleanup;
+
+ if (!(nodedir = opendir(sysfs_nodedir))) {
+ /* the host isn't probably running a NUMA architecture */
+ goto fallback;
+ }
+
+ /* PPC-KVM needs the secondary threads of a core to be offline on the
+ * host. The kvm scheduler brings the secondary threads online in the
+ * guest context. Moreover, P8 processor has split-core capability
+ * where, there can be 1,2 or 4 subcores per core. The primaries of the
+ * subcores alone will be online on the host for a subcore in the
+ * host. Even though the actual threads per core for P8 processor is 8,
+ * depending on the subcores_per_core = 1, 2 or 4, the threads per
+ * subcore will vary accordingly to 8, 4 and 2 repectively.
+ * So, On host threads_per_core what is arrived at from sysfs in the
+ * current logic is actually the subcores_per_core. Threads per subcore
+ * can only be obtained from the kvm device. For example, on P8 wih 1
+ * core having 8 threads, sub_cores_percore=4, the threads 0,2,4 & 6
+ * will be online. The sysfs reflects this and in the current logic
+ * variable 'threads' will be 4 which is nothing but subcores_per_core.
+ * If the user tampers the cpu online/offline states using chcpu or other
+ * means, then it is an unsupported configuration for kvm.
+ * The code below tries to keep in mind
+ * - when the libvirtd is run inside a KVM guest or Phyp based guest.
+ * - Or on the kvm host where user manually tampers the cpu states to
+ * offline/online randomly.
+ * On hosts other than POWER this will be 0, in which case a simpler
+ * thread-counting logic will be used */
+ if ((threads_per_subcore = virHostCPUGetThreadsPerSubcore(arch)) < 0)
+ goto cleanup;
+
+ /* If the subcore configuration is not valid, just pretend subcores
+ * are not in use and count threads one by one */
+ if (!virHostCPUHasValidSubcoreConfiguration(threads_per_subcore))
+ threads_per_subcore = 0;
+
+ while ((direrr = virDirRead(nodedir, &nodedirent, sysfs_nodedir)) > 0) {
+ if (sscanf(nodedirent->d_name, "node%u", &node) != 1)
+ continue;
+
+ (*nodes)++;
+
+ if (virAsprintf(&sysfs_cpudir, "%s/node/%s",
+ sysfs_system_path, nodedirent->d_name) < 0)
+ goto cleanup;
+
+ if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
+ present_cpus_map,
+ online_cpus_map,
+ threads_per_subcore,
+ &nodesockets, &nodecores,
+ &nodethreads, &offline)) < 0)
+ goto cleanup;
+
+ VIR_FREE(sysfs_cpudir);
+
+ *cpus += nodecpus;
+
+ if (nodesockets > *sockets)
+ *sockets = nodesockets;
+
+ if (nodecores > *cores)
+ *cores = nodecores;
+
+ if (nodethreads > *threads)
+ *threads = nodethreads;
+ }
+
+ if (direrr < 0)
+ goto cleanup;
+
+ if (*cpus && *nodes)
+ goto done;
+
+ fallback:
+ VIR_FREE(sysfs_cpudir);
+
+ if (virAsprintf(&sysfs_cpudir, "%s/cpu", sysfs_system_path) < 0)
+ goto cleanup;
+
+ if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
+ present_cpus_map,
+ online_cpus_map,
+ threads_per_subcore,
+ &nodesockets, &nodecores,
+ &nodethreads, &offline)) < 0)
+ goto cleanup;
+
+ *nodes = 1;
+ *cpus = nodecpus;
+ *sockets = nodesockets;
+ *cores = nodecores;
+ *threads = nodethreads;
+
+ done:
+ /* There should always be at least one cpu, socket, node, and thread. */
+ if (*cpus == 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no CPUs
found"));
+ goto cleanup;
+ }
+
+ if (*sockets == 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no sockets
found"));
+ goto cleanup;
+ }
+
+ if (*threads == 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no threads
found"));
+ 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 ((*nodes *
+ *sockets *
+ *cores *
+ *threads) != (*cpus + offline)) {
+ *nodes = 1;
+ *sockets = 1;
+ *cores = *cpus + offline;
+ *threads = 1;
+ }
+
+ ret = 0;
+
+ cleanup:
+ /* don't shadow a more serious error */
+ if (nodedir && closedir(nodedir) < 0 && ret >= 0) {
+ virReportSystemError(errno, _("problem closing %s"), sysfs_nodedir);
+ ret = -1;
+ }
+
+ virBitmapFree(present_cpus_map);
+ virBitmapFree(online_cpus_map);
+ VIR_FREE(sysfs_nodedir);
+ VIR_FREE(sysfs_cpudir);
+ return ret;
+}
+
+static int
+virHostCPUStatsAssign(virNodeCPUStatsPtr param,
+ const char *name,
+ unsigned long long value)
+{
+ if (virStrcpyStatic(param->field, name) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("kernel cpu time field is too long"
+ " for the destination"));
+ return -1;
+ }
+ param->value = value;
+ return 0;
+}
+
+# define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK))
+
+int
+virHostCPUGetStatsLinux(FILE *procstat,
+ int cpuNum,
+ virNodeCPUStatsPtr params,
+ int *nparams)
+{
+ int ret = -1;
+ char line[1024];
+ unsigned long long usr, ni, sys, idle, iowait;
+ unsigned long long irq, softirq, steal, guest, guest_nice;
+ char cpu_header[4 + INT_BUFSIZE_BOUND(cpuNum)];
+
+ if ((*nparams) == 0) {
+ /* Current number of cpu stats supported by linux */
+ *nparams = LINUX_NB_CPU_STATS;
+ ret = 0;
+ goto cleanup;
+ }
+
+ if ((*nparams) != LINUX_NB_CPU_STATS) {
+ virReportInvalidArg(*nparams,
+ _("nparams in %s must be equal to %d"),
+ __FUNCTION__, LINUX_NB_CPU_STATS);
+ goto cleanup;
+ }
+
+ if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) {
+ strcpy(cpu_header, "cpu ");
+ } else {
+ snprintf(cpu_header, sizeof(cpu_header), "cpu%d ", cpuNum);
+ }
+
+ while (fgets(line, sizeof(line), procstat) != NULL) {
+ char *buf = line;
+
+ if (STRPREFIX(buf, cpu_header)) { /* aka logical CPU time */
+ if (sscanf(buf,
+ "%*s %llu %llu %llu %llu %llu" // user ~ iowait
+ "%llu %llu %llu %llu %llu", // irq ~ guest_nice
+ &usr, &ni, &sys, &idle, &iowait,
+ &irq, &softirq, &steal, &guest, &guest_nice)
< 4) {
+ continue;
+ }
+
+ if (virHostCPUStatsAssign(¶ms[0], VIR_NODE_CPU_STATS_KERNEL,
+ (sys + irq + softirq) * TICK_TO_NSEC) < 0)
+ goto cleanup;
+
+ if (virHostCPUStatsAssign(¶ms[1], VIR_NODE_CPU_STATS_USER,
+ (usr + ni) * TICK_TO_NSEC) < 0)
+ goto cleanup;
+
+ if (virHostCPUStatsAssign(¶ms[2], VIR_NODE_CPU_STATS_IDLE,
+ idle * TICK_TO_NSEC) < 0)
+ goto cleanup;
+
+ if (virHostCPUStatsAssign(¶ms[3], VIR_NODE_CPU_STATS_IOWAIT,
+ iowait * TICK_TO_NSEC) < 0)
+ goto cleanup;
+
+ ret = 0;
+ goto cleanup;
+ }
+ }
+
+ virReportInvalidArg(cpuNum,
+ _("Invalid cpuNum in %s"),
+ __FUNCTION__);
+
+ cleanup:
+ return ret;
+}
+
+
+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)
+{
+ char *str = NULL;
+ char *tmp;
+ int ret = -1;
+
+ if (virFileReadAll(path, 5 * VIR_HOST_CPU_MASK_LEN, &str) < 0)
+ 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 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, 0, &map, max_cpuid) < 0)
+ goto error;
+
+ VIR_FREE(str);
+ return map;
+
+ error:
+ VIR_FREE(str);
+ virBitmapFree(map);
+ return NULL;
+}
+#endif
+
+
+int
+virHostCPUGetInfo(virArch hostarch,
+ unsigned int *cpus,
+ unsigned int *mhz,
+ unsigned int *nodes,
+ unsigned int *sockets,
+ unsigned int *cores,
+ unsigned int *threads)
+{
+#ifdef __linux__
+ int ret = -1;
+ FILE *cpuinfo = fopen(CPUINFO_PATH, "r");
+
+ if (!cpuinfo) {
+ virReportSystemError(errno,
+ _("cannot open %s"), CPUINFO_PATH);
+ return -1;
+ }
+
+ ret = virHostCPUGetInfoPopulateLinux(cpuinfo, hostarch,
+ cpus, mhz, nodes,
+ sockets, cores, threads);
+ if (ret < 0)
+ goto cleanup;
+
+ cleanup:
+ VIR_FORCE_FCLOSE(cpuinfo);
+ return ret;
+#elif defined(__FreeBSD__) || defined(__APPLE__)
+ unsigned long cpu_freq;
+ size_t cpu_freq_len = sizeof(cpu_freq);
+
+ *cpus = virHostCPUGetCountAppleFreeBSD();
+ if (*cpus == -1)
+ return -1;
+
+ *nodes = 1;
+ *sockets = 1;
+ *cores = *cpus;
+ *threads = 1;
+
+# ifdef __FreeBSD__
+ if (sysctlbyname("dev.cpu.0.freq", &cpu_freq, &cpu_freq_len, NULL,
0) < 0) {
+ virReportSystemError(errno, "%s", _("cannot obtain CPU
freq"));
+ return -1;
+ }
+
+ *mhz = cpu_freq;
+# else
+ if (sysctlbyname("hw.cpufrequency", &cpu_freq, &cpu_freq_len, NULL,
0) < 0) {
+ virReportSystemError(errno, "%s", _("cannot obtain CPU
freq"));
+ return -1;
+ }
+
+ *mhz = cpu_freq / 1000000;
+# endif
+
+ return 0;
+#else
+ /* XXX Solaris will need an impl later if they port QEMU driver */
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("node info not implemented on this platform"));
+ return -1;
+#endif
+}
+
+
+int
+virHostCPUGetStats(int cpuNum ATTRIBUTE_UNUSED,
+ virNodeCPUStatsPtr params ATTRIBUTE_UNUSED,
+ int *nparams ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
+
+#ifdef __linux__
+ {
+ int ret;
+ FILE *procstat = fopen(PROCSTAT_PATH, "r");
+ if (!procstat) {
+ virReportSystemError(errno,
+ _("cannot open %s"), PROCSTAT_PATH);
+ return -1;
+ }
+ ret = virHostCPUGetStatsLinux(procstat, cpuNum, params, nparams);
+ VIR_FORCE_FCLOSE(procstat);
+
+ return ret;
+ }
+#elif defined(__FreeBSD__)
+ return virHostCPUGetStatsFreeBSD(cpuNum, params, nparams);
+#else
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("node CPU stats not implemented on this platform"));
+ return -1;
+#endif
+}
+
+
+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;
+#elif defined(__FreeBSD__) || defined(__APPLE__)
+ return virHostCPUGetCountAppleFreeBSD();
+#else
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("host cpu counting not implemented on this platform"));
+ return -1;
+#endif
+}
+
+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;
+
+ /* 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);
+
+ return present_cpus;
+#endif
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("node present CPU map not implemented on this
platform"));
+ return NULL;
+}
+
+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;
+
+ if (virAsprintf(&cpudir, "%s/cpu", sysfs_system_path) < 0)
+ goto cleanup;
+
+ 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;
+#else
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("node online CPU map not implemented on this platform"));
+ return NULL;
+#endif
+}
+
+
+int
+virHostCPUGetMap(unsigned char **cpumap,
+ unsigned int *online,
+ unsigned int flags)
+{
+ virBitmapPtr cpus = NULL;
+ int ret = -1;
+ int dummy;
+
+ virCheckFlags(0, -1);
+
+ if (!cpumap && !online)
+ return virHostCPUGetCount();
+
+ if (!(cpus = virHostCPUGetOnlineBitmap()))
+ goto cleanup;
+
+ if (cpumap && virBitmapToData(cpus, cpumap, &dummy) < 0)
+ goto cleanup;
+ if (online)
+ *online = virBitmapCountBits(cpus);
+
+ ret = virBitmapSize(cpus);
+
+ cleanup:
+ if (ret < 0 && cpumap)
+ VIR_FREE(*cpumap);
+ virBitmapFree(cpus);
+ return ret;
+}
+
+
+#if HAVE_LINUX_KVM_H && defined(KVM_CAP_PPC_SMT)
+
+/* Get the number of threads per subcore.
+ *
+ * This will be 2, 4 or 8 on POWER hosts, depending on the current
+ * micro-threading configuration, and 0 everywhere else.
+ *
+ * Returns the number of threads per subcore if subcores are in use, zero
+ * if subcores are not in use, and a negative value on error */
+int
+virHostCPUGetThreadsPerSubcore(virArch arch)
+{
+ int threads_per_subcore = 0;
+ const char *kvmpath = "/dev/kvm";
+ int kvmfd;
+
+ if (ARCH_IS_PPC64(arch)) {
+
+ /* It's okay if /dev/kvm doesn't exist, because
+ * a. we might be running in a guest
+ * b. the kvm module might not be installed or enabled
+ * In either case, falling back to the subcore-unaware thread
+ * counting logic is the right thing to do */
+ if (!virFileExists(kvmpath))
+ goto out;
+
+ if ((kvmfd = open(kvmpath, O_RDONLY)) < 0) {
+ /* This can happen when running as a regular user if
+ * permissions are tight enough, in which case erroring out
+ * is better than silently falling back and reporting
+ * different nodeinfo depending on the user */
+ virReportSystemError(errno,
+ _("Failed to open '%s'"),
+ kvmpath);
+ threads_per_subcore = -1;
+ goto out;
+ }
+
+ /* For Phyp and KVM based guests the ioctl for KVM_CAP_PPC_SMT
+ * returns zero and both primary and secondary threads will be
+ * online */
+ threads_per_subcore = ioctl(kvmfd,
+ KVM_CHECK_EXTENSION,
+ KVM_CAP_PPC_SMT);
+
+ VIR_FORCE_CLOSE(kvmfd);
+ }
+
+ out:
+ return threads_per_subcore;
+}
+
+#else
+
+/* Fallback for nodeGetThreadsPerSubcore() used when KVM headers
+ * are not available on the system */
+int
+virHostCPUGetThreadsPerSubcore(virArch arch ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+#endif /* HAVE_LINUX_KVM_H && defined(KVM_CAP_PPC_SMT) */
diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h
new file mode 100644
index 0000000..e5ffc70
--- /dev/null
+++ b/src/util/virhostcpu.h
@@ -0,0 +1,54 @@
+/*
+ * virhostcpu.h: helper APIs for host CPU info
+ *
+ * Copyright (C) 2006-2016 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#ifndef __VIR_HOSTCPU_H__
+# define __VIR_HOSTCPU_H__
+
+# include "internal.h"
+# include "virarch.h"
+# include "virbitmap.h"
+
+# define VIR_HOST_CPU_MASK_LEN 1024
+
+int virHostCPUGetStats(int cpuNum,
+ virNodeCPUStatsPtr params,
+ int *nparams,
+ unsigned int flags);
+
+virBitmapPtr virHostCPUGetPresentBitmap(void);
+virBitmapPtr virHostCPUGetOnlineBitmap(void);
+int virHostCPUGetCount(void);
+int virHostCPUGetThreadsPerSubcore(virArch arch);
+
+int virHostCPUGetMap(unsigned char **cpumap,
+ unsigned int *online,
+ unsigned int flags);
+int virHostCPUGetInfo(virArch hostarch,
+ unsigned int *cpus,
+ unsigned int *mhz,
+ unsigned int *nodes,
+ unsigned int *sockets,
+ unsigned int *cores,
+ unsigned int *threads);
+
+#endif /* __VIR_HOSTCPU_H__*/
diff --git a/src/nodeinfopriv.h b/src/util/virhostcpupriv.h
similarity index 86%
rename from src/nodeinfopriv.h
rename to src/util/virhostcpupriv.h
index 0fd4391..de30983 100644
--- a/src/nodeinfopriv.h
+++ b/src/util/virhostcpupriv.h
@@ -1,7 +1,7 @@
/*
- * nodeinfopriv.h: internal APIs for testing nodeinfo code
+ * virhostcpupriv.h: helper APIs for host CPU info
*
- * Copyright (C) 2014 Red Hat, Inc.
+ * Copyright (C) 2014-2016 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,10 +19,10 @@
*
*/
-#ifndef __NODEINFO_PRIV_H__
-# define __NODEINFO_PRIV_H__
+#ifndef __VIR_HOSTCPU_PRIV_H__
+# define __VIR_HOSTCPU_PRIV_H__
-# include "nodeinfo.h"
+# include "virhostcpu.h"
# ifdef __linux__
void virHostCPUSetSysFSSystemPathLinux(const char *path);
@@ -42,4 +42,4 @@ int virHostCPUGetStatsLinux(FILE *procstat,
int *nparams);
# endif
-#endif /* __NODEINFO_PRIV_H__ */
+#endif /* __VIR_HOSTCPU_PRIV_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index db4f88b..16677cb 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -107,7 +107,7 @@ EXTRA_DIST = \
networkxml2xmlupdateout \
nodedevschemadata \
nodedevschematest \
- nodeinfodata \
+ virhostcpudata \
nssdata \
nwfilterschematest \
nwfilterxml2firewalldata \
@@ -160,7 +160,7 @@ EXTRA_DIST = \
test_helpers = commandhelper ssh test_conf
test_programs = virshtest sockettest \
- nodeinfotest virbuftest \
+ virhostcputest virbuftest \
commandtest seclabeltest \
virhashtest \
viratomictest \
@@ -426,7 +426,7 @@ test_libraries = libshunload.la \
vircgroupmock.la \
virpcimock.la \
virnetdevmock.la \
- nodeinfomock.la \
+ virhostcpumock.la \
nssmock.la \
$(NULL)
if WITH_QEMU
@@ -875,9 +875,9 @@ test_conf_SOURCES = \
test_conf.c
test_conf_LDADD = $(LDADDS)
-nodeinfotest_SOURCES = \
- nodeinfotest.c testutils.h testutils.c
-nodeinfotest_LDADD = $(LDADDS)
+virhostcputest_SOURCES = \
+ virhostcputest.c testutils.h testutils.c
+virhostcputest_LDADD = $(LDADDS)
commandtest_SOURCES = \
commandtest.c testutils.h testutils.c
@@ -1068,11 +1068,11 @@ virpcimock_la_CFLAGS = $(AM_CFLAGS)
virpcimock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
virpcimock_la_LIBADD = $(MOCKLIBS_LIBS)
-nodeinfomock_la_SOURCES = \
- nodeinfomock.c
-nodeinfomock_la_CFLAGS = $(AM_CFLAGS)
-nodeinfomock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
-nodeinfomock_la_LIBADD = $(MOCKLIBS_LIBS)
+virhostcpumock_la_SOURCES = \
+ virhostcpumock.c
+virhostcpumock_la_CFLAGS = $(AM_CFLAGS)
+virhostcpumock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
+virhostcpumock_la_LIBADD = $(MOCKLIBS_LIBS)
nsstest_SOURCES = \
nsstest.c testutils.h testutils.c
diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
index 148721d..566ffa8 100644
--- a/tests/vircgrouptest.c
+++ b/tests/vircgrouptest.c
@@ -34,7 +34,7 @@
# include "virfile.h"
# include "virbuffer.h"
# include "testutilslxc.h"
-# include "nodeinfo.h"
+# include "virhostcpu.h"
# define VIR_FROM_THIS VIR_FROM_NONE
diff --git a/tests/nodeinfodata/linux-aarch64-f21-mustang.cpuinfo
b/tests/virhostcpudata/linux-aarch64-f21-mustang.cpuinfo
similarity index 100%
rename from tests/nodeinfodata/linux-aarch64-f21-mustang.cpuinfo
rename to tests/virhostcpudata/linux-aarch64-f21-mustang.cpuinfo
diff --git a/tests/nodeinfodata/linux-aarch64-f21-mustang.expected
b/tests/virhostcpudata/linux-aarch64-f21-mustang.expected
similarity index 100%
rename from tests/nodeinfodata/linux-aarch64-f21-mustang.expected
rename to tests/virhostcpudata/linux-aarch64-f21-mustang.expected
diff --git a/tests/nodeinfodata/linux-aarch64-rhelsa-3.19.0-mustang.cpuinfo
b/tests/virhostcpudata/linux-aarch64-rhelsa-3.19.0-mustang.cpuinfo
similarity index 100%
rename from tests/nodeinfodata/linux-aarch64-rhelsa-3.19.0-mustang.cpuinfo
rename to tests/virhostcpudata/linux-aarch64-rhelsa-3.19.0-mustang.cpuinfo
[...snipped countless more renames...]
diff --git a/tests/nodeinfomock.c b/tests/virhostcpumock.c
similarity index 95%
rename from tests/nodeinfomock.c
rename to tests/virhostcpumock.c
index ac12b5e..00d10f1 100644
--- a/tests/nodeinfomock.c
+++ b/tests/virhostcpumock.c
@@ -19,8 +19,7 @@
#include <config.h>
-#include "internal.h"
-#include "nodeinfo.h"
+#include "virhostcpu.h"
int
virHostCPUGetThreadsPerSubcore(virArch arch)
diff --git a/tests/nodeinfotest.c b/tests/virhostcputest.c
similarity index 89%
rename from tests/nodeinfotest.c
rename to tests/virhostcputest.c
index 50b1c82..0643876 100644
--- a/tests/nodeinfotest.c
+++ b/tests/virhostcputest.c
@@ -7,7 +7,7 @@
#include "testutils.h"
#include "internal.h"
-#include "nodeinfopriv.h"
+#include "virhostcpupriv.h"
#include "virfile.h"
#include "virstring.h"
@@ -155,26 +155,26 @@ linuxCPUStatsCompareFiles(const char *cpustatfile,
}
-struct linuxTestNodeInfoData {
+struct linuxTestHostCPUData {
const char *testName;
virArch arch;
};
static int
-linuxTestNodeInfo(const void *opaque)
+linuxTestHostCPU(const void *opaque)
{
int result = -1;
char *cpuinfo = NULL;
char *sysfs_prefix = NULL;
char *output = NULL;
- struct linuxTestNodeInfoData *data = (struct linuxTestNodeInfoData *) opaque;
+ struct linuxTestHostCPUData *data = (struct linuxTestHostCPUData *) opaque;
const char *archStr = virArchToString(data->arch);
- if (virAsprintf(&sysfs_prefix, "%s/nodeinfodata/linux-%s",
+ if (virAsprintf(&sysfs_prefix, "%s/virhostcpudata/linux-%s",
abs_srcdir, data->testName) < 0 ||
- virAsprintf(&cpuinfo, "%s/nodeinfodata/linux-%s-%s.cpuinfo",
+ virAsprintf(&cpuinfo, "%s/virhostcpudata/linux-%s-%s.cpuinfo",
abs_srcdir, archStr, data->testName) < 0 ||
- virAsprintf(&output, "%s/nodeinfodata/linux-%s-%s.expected",
+ virAsprintf(&output, "%s/virhostcpudata/linux-%s-%s.expected",
abs_srcdir, archStr, data->testName) < 0) {
goto cleanup;
}
@@ -204,9 +204,9 @@ linuxTestNodeCPUStats(const void *data)
char *cpustatfile = NULL;
char *outfile = NULL;
- if (virAsprintf(&cpustatfile, "%s/nodeinfodata/linux-cpustat-%s.stat",
+ if (virAsprintf(&cpustatfile,
"%s/virhostcpudata/linux-cpustat-%s.stat",
abs_srcdir, testData->name) < 0 ||
- virAsprintf(&outfile, "%s/nodeinfodata/linux-cpustat-%s.out",
+ virAsprintf(&outfile, "%s/virhostcpudata/linux-cpustat-%s.out",
abs_srcdir, testData->name) < 0)
goto fail;
@@ -225,7 +225,7 @@ mymain(void)
{
int ret = 0;
size_t i;
- const struct linuxTestNodeInfoData nodeData[] = {
+ const struct linuxTestHostCPUData nodeData[] = {
{"test1", VIR_ARCH_X86_64},
{"test1", VIR_ARCH_PPC},
{"test2", VIR_ARCH_X86_64},
@@ -251,7 +251,7 @@ mymain(void)
return EXIT_FAILURE;
for (i = 0; i < ARRAY_CARDINALITY(nodeData); i++)
- if (virtTestRun(nodeData[i].testName, linuxTestNodeInfo, &nodeData[i]) != 0)
+ if (virtTestRun(nodeData[i].testName, linuxTestHostCPU, &nodeData[i]) != 0)
ret = -1;
# define DO_TEST_CPU_STATS(name, ncpus) \
@@ -266,6 +266,6 @@ mymain(void)
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
-VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/nodeinfomock.so")
+VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virhostcpumock.so")
#endif /* __linux__ */
--
2.5.5