aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2016-11-14 23:05:44 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-11-25 09:00:30 -0500
commitd18acd15c6dfb669f0463afa31ac5343594d2fe2 (patch)
tree518a4ddf76295a74020dd5ec8a9a1282bd2d8beb
parent8388deb3ba4d36ffcae91a2a01cb2ea6f27553e6 (diff)
perf tools: Fix kernel version error in ubuntu
On ubuntu the internal kernel version code is different from what can be retrived from uname: $ uname -r 4.4.0-47-generic $ cat /lib/modules/`uname -r`/build/include/generated/uapi/linux/version.h #define LINUX_VERSION_CODE 263192 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) $ cat /lib/modules/`uname -r`/build/include/generated/utsrelease.h #define UTS_RELEASE "4.4.0-47-generic" #define UTS_UBUNTU_RELEASE_ABI 47 $ cat /proc/version_signature Ubuntu 4.4.0-47.68-generic 4.4.24 The macro LINUX_VERSION_CODE is set to 4.4.24 (263192 == 0x40418), but `uname -r` reports 4.4.0. This mismatch causes LINUX_VERSION_CODE macro passed to BPF script become an incorrect value, results in magic failure in BPF loading: $ sudo ./buildperf/perf record -e ./tools/perf/tests/bpf-script-example.c ls event syntax error: './tools/perf/tests/bpf-script-example.c' \___ Failed to load program for unknown reason According to Ubuntu document (https://wiki.ubuntu.com/Kernel/FAQ), the correct kernel version can be retrived through /proc/version_signature, which is ubuntu specific. This patch checks the existance of /proc/version_signature, and returns version number through parsing this file instead of uname. Version string is untouched (value returns from uname) because `uname -r` is required to be consistence with path of kbuild directory in /lib/module. Signed-off-by: Wang Nan <wangnan0@huawei.com> Cc: Alexei Starovoitov <ast@fb.com> Cc: He Kuang <hekuang@huawei.com> Cc: Zefan Li <lizefan@huawei.com> Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/20161115040617.69788-2-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/util.c55
1 files changed, 53 insertions, 2 deletions
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 5bbd1f609f1f..67ac765da27a 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -637,12 +637,63 @@ bool find_process(const char *name)
637 return ret ? false : true; 637 return ret ? false : true;
638} 638}
639 639
640static int
641fetch_ubuntu_kernel_version(unsigned int *puint)
642{
643 ssize_t len;
644 size_t line_len = 0;
645 char *ptr, *line = NULL;
646 int version, patchlevel, sublevel, err;
647 FILE *vsig = fopen("/proc/version_signature", "r");
648
649 if (!vsig) {
650 pr_debug("Open /proc/version_signature failed: %s\n",
651 strerror(errno));
652 return -1;
653 }
654
655 len = getline(&line, &line_len, vsig);
656 fclose(vsig);
657 err = -1;
658 if (len <= 0) {
659 pr_debug("Reading from /proc/version_signature failed: %s\n",
660 strerror(errno));
661 goto errout;
662 }
663
664 ptr = strrchr(line, ' ');
665 if (!ptr) {
666 pr_debug("Parsing /proc/version_signature failed: %s\n", line);
667 goto errout;
668 }
669
670 err = sscanf(ptr + 1, "%d.%d.%d",
671 &version, &patchlevel, &sublevel);
672 if (err != 3) {
673 pr_debug("Unable to get kernel version from /proc/version_signature '%s'\n",
674 line);
675 goto errout;
676 }
677
678 if (puint)
679 *puint = (version << 16) + (patchlevel << 8) + sublevel;
680 err = 0;
681errout:
682 free(line);
683 return err;
684}
685
640int 686int
641fetch_kernel_version(unsigned int *puint, char *str, 687fetch_kernel_version(unsigned int *puint, char *str,
642 size_t str_size) 688 size_t str_size)
643{ 689{
644 struct utsname utsname; 690 struct utsname utsname;
645 int version, patchlevel, sublevel, err; 691 int version, patchlevel, sublevel, err;
692 bool int_ver_ready = false;
693
694 if (access("/proc/version_signature", R_OK) == 0)
695 if (!fetch_ubuntu_kernel_version(puint))
696 int_ver_ready = true;
646 697
647 if (uname(&utsname)) 698 if (uname(&utsname))
648 return -1; 699 return -1;
@@ -656,12 +707,12 @@ fetch_kernel_version(unsigned int *puint, char *str,
656 &version, &patchlevel, &sublevel); 707 &version, &patchlevel, &sublevel);
657 708
658 if (err != 3) { 709 if (err != 3) {
659 pr_debug("Unablt to get kernel version from uname '%s'\n", 710 pr_debug("Unable to get kernel version from uname '%s'\n",
660 utsname.release); 711 utsname.release);
661 return -1; 712 return -1;
662 } 713 }
663 714
664 if (puint) 715 if (puint && !int_ver_ready)
665 *puint = (version << 16) + (patchlevel << 8) + sublevel; 716 *puint = (version << 16) + (patchlevel << 8) + sublevel;
666 return 0; 717 return 0;
667} 718}