Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf tools: Don't read build-ids from non-regular files

Simplify the build ID reading code by removing the non-blocking option.
Having to pass the correct option to this function was fragile and a
mistake would result in a hang, see the linked fix. Furthermore,
compressed files are always opened blocking anyway, ignoring the
non-blocking option.

We also don't expect to read build IDs from non-regular files. The only
hits to this function that are non-regular are devices that won't be elf
files with build IDs, for example "/dev/dri/renderD129".

Now instead of opening these as non-blocking and failing to read, we
skip them. Even if something like a pipe or character device did have a
build ID, I don't think it would have worked because you need to call
read() in a loop, check for -EAGAIN and handle timeouts to make
non-blocking reads work.

Link: https://lore.kernel.org/linux-perf-users/20251022-james-perf-fix-dso-block-v1-1-c4faab150546@linaro.org/
Signed-off-by: James Clark <james.clark@linaro.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

authored by

James Clark and committed by
Namhyung Kim
834ebb56 c9573287

+43 -34
+1 -1
tools/perf/bench/inject-buildid.c
··· 85 85 if (typeflag == FTW_D || typeflag == FTW_SL) 86 86 return 0; 87 87 88 - if (filename__read_build_id(fpath, &bid, /*block=*/true) < 0) 88 + if (filename__read_build_id(fpath, &bid) < 0) 89 89 return 0; 90 90 91 91 dso->name = realpath(fpath, NULL);
+4 -4
tools/perf/builtin-buildid-cache.c
··· 180 180 struct nscookie nsc; 181 181 182 182 nsinfo__mountns_enter(nsi, &nsc); 183 - err = filename__read_build_id(filename, &bid, /*block=*/true); 183 + err = filename__read_build_id(filename, &bid); 184 184 nsinfo__mountns_exit(&nsc); 185 185 if (err < 0) { 186 186 pr_debug("Couldn't read a build-id in %s\n", filename); ··· 204 204 int err; 205 205 206 206 nsinfo__mountns_enter(nsi, &nsc); 207 - err = filename__read_build_id(filename, &bid, /*block=*/true); 207 + err = filename__read_build_id(filename, &bid); 208 208 nsinfo__mountns_exit(&nsc); 209 209 if (err < 0) { 210 210 pr_debug("Couldn't read a build-id in %s\n", filename); ··· 280 280 if (!dso__build_id_filename(dso, filename, sizeof(filename), false)) 281 281 return true; 282 282 283 - if (filename__read_build_id(filename, &bid, /*block=*/true) == -1) { 283 + if (filename__read_build_id(filename, &bid) == -1) { 284 284 if (errno == ENOENT) 285 285 return false; 286 286 ··· 309 309 int err; 310 310 311 311 nsinfo__mountns_enter(nsi, &nsc); 312 - err = filename__read_build_id(filename, &bid, /*block=*/true); 312 + err = filename__read_build_id(filename, &bid); 313 313 nsinfo__mountns_exit(&nsc); 314 314 if (err < 0) { 315 315 pr_debug("Couldn't read a build-id in %s\n", filename);
+2 -2
tools/perf/builtin-inject.c
··· 668 668 669 669 mutex_lock(dso__lock(dso)); 670 670 nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); 671 - if (filename__read_build_id(dso__long_name(dso), &bid, /*block=*/true) > 0) 671 + if (filename__read_build_id(dso__long_name(dso), &bid) > 0) 672 672 dso__set_build_id(dso, &bid); 673 673 else if (dso__nsinfo(dso)) { 674 674 char *new_name = dso__filename_with_chroot(dso, dso__long_name(dso)); 675 675 676 - if (new_name && filename__read_build_id(new_name, &bid, /*block=*/true) > 0) 676 + if (new_name && filename__read_build_id(new_name, &bid) > 0) 677 677 dso__set_build_id(dso, &bid); 678 678 free(new_name); 679 679 }
+2 -2
tools/perf/tests/pe-file-parsing.c
··· 37 37 size_t idx; 38 38 39 39 scnprintf(filename, PATH_MAX, "%s/pe-file.exe", d); 40 - ret = filename__read_build_id(filename, &bid, /*block=*/true); 40 + ret = filename__read_build_id(filename, &bid); 41 41 TEST_ASSERT_VAL("Failed to read build_id", 42 42 ret == sizeof(expect_build_id)); 43 43 TEST_ASSERT_VAL("Wrong build_id", !memcmp(bid.data, expect_build_id, ··· 49 49 !strcmp(debuglink, expect_debuglink)); 50 50 51 51 scnprintf(debugfile, PATH_MAX, "%s/%s", d, debuglink); 52 - ret = filename__read_build_id(debugfile, &bid, /*block=*/true); 52 + ret = filename__read_build_id(debugfile, &bid); 53 53 TEST_ASSERT_VAL("Failed to read debug file build_id", 54 54 ret == sizeof(expect_build_id)); 55 55 TEST_ASSERT_VAL("Wrong build_id", !memcmp(bid.data, expect_build_id,
+1 -1
tools/perf/tests/sdt.c
··· 31 31 struct build_id bid = { .size = 0, }; 32 32 int err; 33 33 34 - err = filename__read_build_id(filename, &bid, /*block=*/true); 34 + err = filename__read_build_id(filename, &bid); 35 35 if (err < 0) { 36 36 pr_debug("Failed to read build id of %s\n", filename); 37 37 return err;
+2 -2
tools/perf/util/build-id.c
··· 122 122 struct build_id bid = { .size = 0, }; 123 123 int ret; 124 124 125 - ret = filename__read_build_id(pathname, &bid, /*block=*/true); 125 + ret = filename__read_build_id(pathname, &bid); 126 126 if (ret < 0) 127 127 return ret; 128 128 ··· 848 848 int ret; 849 849 850 850 nsinfo__mountns_enter(nsi, &nsc); 851 - ret = filename__read_build_id(filename, bid, /*block=*/true); 851 + ret = filename__read_build_id(filename, bid); 852 852 nsinfo__mountns_exit(&nsc); 853 853 854 854 return ret;
+1 -1
tools/perf/util/debuginfo.c
··· 115 115 * incase the path isn't for a regular file. 116 116 */ 117 117 assert(!dso__has_build_id(dso)); 118 - if (filename__read_build_id(path, &bid, /*block=*/false) > 0) 118 + if (filename__read_build_id(path, &bid) > 0) 119 119 dso__set_build_id(dso, &bid); 120 120 121 121 for (type = distro_dwarf_types;
+2 -2
tools/perf/util/dsos.c
··· 81 81 return 0; 82 82 } 83 83 nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); 84 - if (filename__read_build_id(dso__long_name(dso), &bid, /*block=*/true) > 0) { 84 + if (filename__read_build_id(dso__long_name(dso), &bid) > 0) { 85 85 dso__set_build_id(dso, &bid); 86 86 args->have_build_id = true; 87 87 } else if (errno == ENOENT && dso__nsinfo(dso)) { 88 88 char *new_name = dso__filename_with_chroot(dso, dso__long_name(dso)); 89 89 90 - if (new_name && filename__read_build_id(new_name, &bid, /*block=*/true) > 0) { 90 + if (new_name && filename__read_build_id(new_name, &bid) > 0) { 91 91 dso__set_build_id(dso, &bid); 92 92 args->have_build_id = true; 93 93 }
+7 -2
tools/perf/util/libbfd.c
··· 383 383 return err; 384 384 } 385 385 386 - int libbfd__read_build_id(const char *filename, struct build_id *bid, bool block) 386 + int libbfd__read_build_id(const char *filename, struct build_id *bid) 387 387 { 388 388 size_t size = sizeof(bid->data); 389 389 int err = -1, fd; 390 390 bfd *abfd; 391 391 392 - fd = open(filename, block ? O_RDONLY : (O_RDONLY | O_NONBLOCK)); 392 + if (!filename) 393 + return -EFAULT; 394 + if (!is_regular_file(filename)) 395 + return -EWOULDBLOCK; 396 + 397 + fd = open(filename, O_RDONLY); 393 398 if (fd < 0) 394 399 return -1; 395 400
+2 -3
tools/perf/util/libbfd.h
··· 25 25 int symbol__disassemble_libbfd(const char *filename, struct symbol *sym, 26 26 struct annotate_args *args); 27 27 28 - int libbfd__read_build_id(const char *filename, struct build_id *bid, bool block); 28 + int libbfd__read_build_id(const char *filename, struct build_id *bid); 29 29 30 30 int libbfd_filename__read_debuglink(const char *filename, char *debuglink, size_t size); 31 31 ··· 59 59 } 60 60 61 61 static inline int libbfd__read_build_id(const char *filename __always_unused, 62 - struct build_id *bid __always_unused, 63 - bool block __always_unused) 62 + struct build_id *bid __always_unused) 64 63 { 65 64 return -1; 66 65 }
+7 -6
tools/perf/util/symbol-elf.c
··· 860 860 return err; 861 861 } 862 862 863 - static int read_build_id(const char *filename, struct build_id *bid, bool block) 863 + static int read_build_id(const char *filename, struct build_id *bid) 864 864 { 865 865 size_t size = sizeof(bid->data); 866 866 int fd, err; 867 867 Elf *elf; 868 868 869 - err = libbfd__read_build_id(filename, bid, block); 869 + err = libbfd__read_build_id(filename, bid); 870 870 if (err >= 0) 871 871 goto out; 872 872 873 873 if (size < BUILD_ID_SIZE) 874 874 goto out; 875 875 876 - fd = open(filename, block ? O_RDONLY : (O_RDONLY | O_NONBLOCK)); 876 + fd = open(filename, O_RDONLY); 877 877 if (fd < 0) 878 878 goto out; 879 879 ··· 894 894 return err; 895 895 } 896 896 897 - int filename__read_build_id(const char *filename, struct build_id *bid, bool block) 897 + int filename__read_build_id(const char *filename, struct build_id *bid) 898 898 { 899 899 struct kmod_path m = { .name = NULL, }; 900 900 char path[PATH_MAX]; ··· 902 902 903 903 if (!filename) 904 904 return -EFAULT; 905 + if (!is_regular_file(filename)) 906 + return -EWOULDBLOCK; 905 907 906 908 err = kmod_path__parse(&m, filename); 907 909 if (err) ··· 920 918 } 921 919 close(fd); 922 920 filename = path; 923 - block = true; 924 921 } 925 922 926 - err = read_build_id(filename, bid, block); 923 + err = read_build_id(filename, bid); 927 924 928 925 if (m.comp) 929 926 unlink(filename);
+8 -3
tools/perf/util/symbol-minimal.c
··· 85 85 /* 86 86 * Just try PT_NOTE header otherwise fails 87 87 */ 88 - int filename__read_build_id(const char *filename, struct build_id *bid, bool block) 88 + int filename__read_build_id(const char *filename, struct build_id *bid) 89 89 { 90 90 int fd, ret = -1; 91 91 bool need_swap = false, elf32; ··· 102 102 void *phdr, *buf = NULL; 103 103 ssize_t phdr_size, ehdr_size, buf_size = 0; 104 104 105 - fd = open(filename, block ? O_RDONLY : (O_RDONLY | O_NONBLOCK)); 105 + if (!filename) 106 + return -EFAULT; 107 + if (!is_regular_file(filename)) 108 + return -EWOULDBLOCK; 109 + 110 + fd = open(filename, O_RDONLY); 106 111 if (fd < 0) 107 112 return -1; 108 113 ··· 328 323 if (ret >= 0) 329 324 RC_CHK_ACCESS(dso)->is_64_bit = ret; 330 325 331 - if (filename__read_build_id(ss->name, &bid, /*block=*/true) > 0) 326 + if (filename__read_build_id(ss->name, &bid) > 0) 332 327 dso__set_build_id(dso, &bid); 333 328 return 0; 334 329 }
+2 -3
tools/perf/util/symbol.c
··· 1743 1743 1744 1744 /* 1745 1745 * Read the build id if possible. This is required for 1746 - * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work. Don't block in case path 1747 - * isn't for a regular file. 1746 + * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work. 1748 1747 */ 1749 1748 if (!dso__has_build_id(dso)) { 1750 1749 struct build_id bid = { .size = 0, }; 1751 1750 1752 1751 __symbol__join_symfs(name, PATH_MAX, dso__long_name(dso)); 1753 - if (filename__read_build_id(name, &bid, /*block=*/false) > 0) 1752 + if (filename__read_build_id(name, &bid) > 0) 1754 1753 dso__set_build_id(dso, &bid); 1755 1754 } 1756 1755
+1 -1
tools/perf/util/symbol.h
··· 140 140 141 141 enum dso_type dso__type_fd(int fd); 142 142 143 - int filename__read_build_id(const char *filename, struct build_id *id, bool block); 143 + int filename__read_build_id(const char *filename, struct build_id *id); 144 144 int sysfs__read_build_id(const char *filename, struct build_id *bid); 145 145 int modules__parse(const char *filename, void *arg, 146 146 int (*process_module)(void *arg, const char *name,
+1 -1
tools/perf/util/synthetic-events.c
··· 401 401 nsi = nsinfo__new(event->pid); 402 402 nsinfo__mountns_enter(nsi, &nc); 403 403 404 - rc = filename__read_build_id(event->filename, &bid, /*block=*/false) > 0 ? 0 : -1; 404 + rc = filename__read_build_id(event->filename, &bid) > 0 ? 0 : -1; 405 405 406 406 nsinfo__mountns_exit(&nc); 407 407 nsinfo__put(nsi);