From nobody Wed Feb 11 10:12:42 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1490382202430970.3235224319036; Fri, 24 Mar 2017 12:03:22 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 141E6C05B1D3; Fri, 24 Mar 2017 19:03:22 +0000 (UTC) Received: from colo-mx.corp.redhat.com (unknown [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id DCA5B7958B; Fri, 24 Mar 2017 19:03:21 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 9B1324EBDC; Fri, 24 Mar 2017 19:03:21 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v2OJ0bv9019172 for ; Fri, 24 Mar 2017 15:00:37 -0400 Received: by smtp.corp.redhat.com (Postfix) id ECA757D569; Fri, 24 Mar 2017 19:00:37 +0000 (UTC) Received: from caroline.brq.redhat.com (dhcp129-198.brq.redhat.com [10.34.129.198]) by smtp.corp.redhat.com (Postfix) with ESMTP id 73CD919630 for ; Fri, 24 Mar 2017 19:00:37 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 141E6C05B1D3 Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=libvir-list-bounces@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 141E6C05B1D3 From: Martin Kletzander To: libvir-list@redhat.com Date: Fri, 24 Mar 2017 20:00:03 +0100 Message-Id: <7e6690e15e3165d850042435f805491dfbfd3162.1490381160.git.mkletzan@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 15/23] util: Adapt virhostcpu to the new virsysfs X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Fri, 24 Mar 2017 19:03:22 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" 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 --- 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 =3D SYSFS_SYSTEM_PATH; - -void virHostCPUSetSysFSSystemPathLinux(const char *path) -{ - if (path) - sysfs_system_path =3D path; - else - sysfs_system_path =3D 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 =3D -1; - char value_str[INT_BUFSIZE_BOUND(value)]; - char *tmp; - - if (virAsprintf(&path, "%s/cpu%u/%s", dir, cpu, file) < 0) - return -1; - - pathfp =3D fopen(path, "r"); - if (pathfp =3D=3D NULL) { - if (default_value >=3D 0 && errno =3D=3D ENOENT) - value =3D default_value; - else - virReportSystemError(errno, _("cannot open %s"), path); - goto cleanup; - } - - if (fgets(value_str, sizeof(value_str), pathfp) =3D=3D 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 =3D 0; - char *path; + int rv =3D -1; char *str =3D 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 =3D virSysfsGetCpuValueString(cpu, "topology/thread_siblings", &str= ); + if (rv =3D=3D -2) { ret =3D 1; goto cleanup; } - - if (virFileReadAll(path, SYSFS_THREAD_SIBLINGS_LIST_LENGTH_MAX, &str) = < 0) + if (rv < 0) goto cleanup; for (i =3D 0; str[i] !=3D '\0'; i++) { @@ -281,21 +220,78 @@ virHostCPUCountThreadSiblings(const char *dir, unsign= ed 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 =3D virHostCPUGetValue(dir, cpu, "topology/physical_package_id= ", 0); + int tmp; + int ret =3D virSysfsGetCpuValueInt(cpu, + "topology/physical_package_id", + &tmp); + + /* If the file is not there, it's 0 */ + if (ret =3D=3D -2) + tmp =3D 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 =3D 0; + /* Some architectures might have '-1' validly in the file, but that ac= tually + * 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 =3D 0; + + *socket =3D tmp; + + return 0; +} + +int +virHostCPUGetCore(unsigned int cpu, unsigned int *core) +{ + int ret =3D virSysfsGetCpuValueUint(cpu, "topology/core_id", core); + + /* If the file is not there, it's 0 */ + if (ret =3D=3D -2) + *core =3D 0; + else if (ret < 0) + return -1; + + return 0; +} + +int +virHostCPUGetOnline(unsigned int cpu, bool *online) +{ + unsigned int tmp =3D 0; + int ret =3D virSysfsGetCpuValueUint(cpu, "online", &tmp); + + + /* If the file is not there, it's online (doesn't support offlining) */ + if (ret =3D=3D -2) + tmp =3D 1; + else if (ret < 0) + return -1; + + *online =3D tmp; + + return 0; +} + +virBitmapPtr +virHostCPUGetSiblingsList(unsigned int cpu) +{ + virBitmapPtr ret =3D NULL; + int rv =3D -1; + + rv =3D virSysfsGetCpuValueBitmap(cpu, "topology/thread_siblings_list",= &ret); + if (rv =3D=3D -2) { + /* If the file doesn't exist, the threadis its only sibling */ + ret =3D virBitmapNew(cpu + 1); + if (ret) + ignore_value(virBitmapSetBit(ret, cpu)); } return ret; @@ -329,9 +325,9 @@ virHostCPUParseNode(const char *node, virBitmapPtr sockets_map =3D NULL; virBitmapPtr *cores_maps =3D NULL; int npresent_cpus =3D virBitmapSize(present_cpus_map); - int sock_max =3D 0; - int sock; - int core; + unsigned int sock_max =3D 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 =3D 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 =3D 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 =3D cpu; } else { - if ((core =3D 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 =3D virHostCPUCountThreadSiblings(node, cpu))) + if (!(siblings =3D 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 =3D 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 =3D virHostCPUParseNode(sysfs_cpudir, arch, @@ -857,47 +850,24 @@ virHostCPUGetStatsLinux(FILE *procstat, } -static char * -virHostCPUGetGlobalPathLinux(const char *file) -{ - char *path =3D 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 =3D NULL; char *tmp; int ret =3D -1; - if (virFileReadAll(path, 5 * VIR_HOST_CPU_MASK_LEN, &str) < 0) - goto cleanup; + if (virSysfsGetValueString("cpu/present", &str) < 0) + return -1; tmp =3D 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 =3D -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=3D5'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 =3D NULL; - char *str =3D 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 =3D NULL; - char *cpupath =3D NULL; - int ncpu =3D -1; - - if (!(present_path =3D virHostCPUGetPresentPathLinux())) - return -1; - - if (virFileExists(present_path)) { - ncpu =3D virHostCPUParseCountLinux(present_path); - goto cleanup; - } - - if (virAsprintf(&cpupath, "%s/cpu/cpu0", sysfs_system_path) < 0) - goto cleanup; - if (virFileExists(cpupath)) { - ncpu =3D 0; - do { - ncpu++; - VIR_FREE(cpupath); - if (virAsprintf(&cpupath, "%s/cpu/cpu%d", - sysfs_system_path, ncpu) < 0) { - ncpu =3D -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 =3D NULL; - char *present_path =3D NULL; - int npresent_cpus; - - if ((npresent_cpus =3D virHostCPUGetCount()) < 0) - goto cleanup; - - if (!(present_path =3D virHostCPUGetPresentPathLinux())) - goto cleanup; + virBitmapPtr ret =3D NULL; - /* If the cpu/present file is available, parse it and exit */ - if (virFileExists(present_path)) { - present_cpus =3D virHostCPUParseMapLinux(npresent_cpus, present_pa= th); - 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 =3D 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 platfor= m")); return NULL; +#endif } virBitmapPtr virHostCPUGetOnlineBitmap(void) { #ifdef __linux__ - char *online_path =3D NULL; - char *cpudir =3D NULL; - virBitmapPtr cpumap; - int present; - - present =3D virHostCPUGetCount(); - if (present < 0) - return NULL; - - if (!(online_path =3D virHostCPUGetOnlinePathLinux())) - return NULL; - if (virFileExists(online_path)) { - cpumap =3D virHostCPUParseMapLinux(present, online_path); - } else { - size_t i; - - cpumap =3D virBitmapNew(present); - if (!cpumap) - goto cleanup; + virBitmapPtr ret =3D NULL; - if (virAsprintf(&cpudir, "%s/cpu", sysfs_system_path) < 0) - goto cleanup; + virSysfsGetValueBitmap("cpu/online", &ret); - for (i =3D 0; i < present; i++) { - int online =3D virHostCPUGetValue(cpudir, i, "online", 1); - if (online < 0) { - virBitmapFree(cpumap); - cpumap =3D 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 =3D linuxTestCompareFiles(cpuinfo, data->arch, output); - virHostCPUSetSysFSSystemPathLinux(NULL); + virSysfsSetSystemPath(NULL); cleanup: VIR_FREE(cpuinfo); --=20 2.12.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list