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 symbol: Add blocking argument to filename__read_build_id

When synthesizing build-ids, for build ID mmap2 events, they will be
added for data mmaps if -d/--data is specified. The files opened for
their build IDs may block on the open causing perf to hang during
synthesis. There is some robustness in existing calls to
filename__read_build_id by checking the file path is to a regular
file, which unfortunately fails for symlinks. Rather than adding more
is_regular_file calls, switch filename__read_build_id to take a
"block" argument and specify O_NONBLOCK when this is false. The
existing is_regular_file checking callers and the event synthesis
callers are made to pass false and thereby avoiding the hang.

Fixes: 53b00ff358dc ("perf record: Make --buildid-mmap the default")
Signed-off-by: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250823000024.724394-3-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

authored by

Ian Rogers and committed by
Namhyung Kim
2c369d91 ba0b7081

+32 -27
+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) < 0) 88 + if (filename__read_build_id(fpath, &bid, /*block=*/true) < 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); 183 + err = filename__read_build_id(filename, &bid, /*block=*/true); 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); 207 + err = filename__read_build_id(filename, &bid, /*block=*/true); 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) == -1) { 283 + if (filename__read_build_id(filename, &bid, /*block=*/true) == -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); 312 + err = filename__read_build_id(filename, &bid, /*block=*/true); 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
··· 680 680 681 681 mutex_lock(dso__lock(dso)); 682 682 nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); 683 - if (filename__read_build_id(dso__long_name(dso), &bid) > 0) 683 + if (filename__read_build_id(dso__long_name(dso), &bid, /*block=*/true) > 0) 684 684 dso__set_build_id(dso, &bid); 685 685 else if (dso__nsinfo(dso)) { 686 686 char *new_name = dso__filename_with_chroot(dso, dso__long_name(dso)); 687 687 688 - if (new_name && filename__read_build_id(new_name, &bid) > 0) 688 + if (new_name && filename__read_build_id(new_name, &bid, /*block=*/true) > 0) 689 689 dso__set_build_id(dso, &bid); 690 690 free(new_name); 691 691 }
+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); 34 + err = filename__read_build_id(filename, &bid, /*block=*/true); 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
··· 115 115 struct build_id bid = { .size = 0, }; 116 116 int ret; 117 117 118 - ret = filename__read_build_id(pathname, &bid); 118 + ret = filename__read_build_id(pathname, &bid, /*block=*/true); 119 119 if (ret < 0) 120 120 return ret; 121 121 ··· 841 841 int ret; 842 842 843 843 nsinfo__mountns_enter(nsi, &nsc); 844 - ret = filename__read_build_id(filename, bid); 844 + ret = filename__read_build_id(filename, bid, /*block=*/true); 845 845 nsinfo__mountns_exit(&nsc); 846 846 847 847 return ret;
+6 -2
tools/perf/util/debuginfo.c
··· 110 110 if (!dso) 111 111 goto out; 112 112 113 - /* Set the build id for DSO_BINARY_TYPE__BUILDID_DEBUGINFO */ 114 - if (is_regular_file(path) && filename__read_build_id(path, &bid) > 0) 113 + /* 114 + * Set the build id for DSO_BINARY_TYPE__BUILDID_DEBUGINFO. Don't block 115 + * incase the path isn't for a regular file. 116 + */ 117 + assert(!dso__has_build_id(dso)); 118 + if (filename__read_build_id(path, &bid, /*block=*/false) > 0) 115 119 dso__set_build_id(dso, &bid); 116 120 117 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) > 0) { 84 + if (filename__read_build_id(dso__long_name(dso), &bid, /*block=*/true) > 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) > 0) { 90 + if (new_name && filename__read_build_id(new_name, &bid, /*block=*/true) > 0) { 91 91 dso__set_build_id(dso, &bid); 92 92 args->have_build_id = true; 93 93 }
+5 -4
tools/perf/util/symbol-elf.c
··· 902 902 903 903 #else // HAVE_LIBBFD_BUILDID_SUPPORT 904 904 905 - static int read_build_id(const char *filename, struct build_id *bid) 905 + static int read_build_id(const char *filename, struct build_id *bid, bool block) 906 906 { 907 907 size_t size = sizeof(bid->data); 908 908 int fd, err = -1; ··· 911 911 if (size < BUILD_ID_SIZE) 912 912 goto out; 913 913 914 - fd = open(filename, O_RDONLY); 914 + fd = open(filename, block ? O_RDONLY : (O_RDONLY | O_NONBLOCK)); 915 915 if (fd < 0) 916 916 goto out; 917 917 ··· 934 934 935 935 #endif // HAVE_LIBBFD_BUILDID_SUPPORT 936 936 937 - int filename__read_build_id(const char *filename, struct build_id *bid) 937 + int filename__read_build_id(const char *filename, struct build_id *bid, bool block) 938 938 { 939 939 struct kmod_path m = { .name = NULL, }; 940 940 char path[PATH_MAX]; ··· 958 958 } 959 959 close(fd); 960 960 filename = path; 961 + block = true; 961 962 } 962 963 963 - err = read_build_id(filename, bid); 964 + err = read_build_id(filename, bid, block); 964 965 965 966 if (m.comp) 966 967 unlink(filename);
+3 -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) 88 + int filename__read_build_id(const char *filename, struct build_id *bid, bool block) 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, O_RDONLY); 105 + fd = open(filename, block ? O_RDONLY : (O_RDONLY | O_NONBLOCK)); 106 106 if (fd < 0) 107 107 return -1; 108 108 ··· 323 323 if (ret >= 0) 324 324 RC_CHK_ACCESS(dso)->is_64_bit = ret; 325 325 326 - if (filename__read_build_id(ss->name, &bid) > 0) 326 + if (filename__read_build_id(ss->name, &bid, /*block=*/true) > 0) 327 327 dso__set_build_id(dso, &bid); 328 328 return 0; 329 329 }
+4 -4
tools/perf/util/symbol.c
··· 1869 1869 1870 1870 /* 1871 1871 * Read the build id if possible. This is required for 1872 - * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work 1872 + * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work. Don't block in case path 1873 + * isn't for a regular file. 1873 1874 */ 1874 - if (!dso__has_build_id(dso) && 1875 - is_regular_file(dso__long_name(dso))) { 1875 + if (!dso__has_build_id(dso)) { 1876 1876 struct build_id bid = { .size = 0, }; 1877 1877 1878 1878 __symbol__join_symfs(name, PATH_MAX, dso__long_name(dso)); 1879 - if (filename__read_build_id(name, &bid) > 0) 1879 + if (filename__read_build_id(name, &bid, /*block=*/false) > 0) 1880 1880 dso__set_build_id(dso, &bid); 1881 1881 } 1882 1882
+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); 143 + int filename__read_build_id(const char *filename, struct build_id *id, bool block); 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) > 0 ? 0 : -1; 404 + rc = filename__read_build_id(event->filename, &bid, /*block=*/false) > 0 ? 0 : -1; 405 405 406 406 nsinfo__mountns_exit(&nc); 407 407 nsinfo__put(nsi);