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

perf buildid-cache: Support binary objects from other namespaces

Teach buildid-cache how to add, remove, and update binary objects from
other mount namespaces. Allow probe events tracing binaries in
different namespaces to add their objects to the probe and build-id
caches too. As a handy side effect, this also lets us access SDT probes
in binaries from alternate mount namespaces.

Signed-off-by: Krister Johansen <kjlx@templeofstupid.com>
Tested-by: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas-Mich Richter <tmricht@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1499305693-1599-5-git-send-email-kjlx@templeofstupid.com
[ Add util/namespaces.c to tools/perf/util/python-ext-sources, to fix the python binding 'perf test' ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Krister Johansen and committed by
Arnaldo Carvalho de Melo
f045b8c4 544abd44

+160 -63
+5
tools/perf/Documentation/perf-buildid-cache.txt
··· 61 61 --verbose:: 62 62 Be more verbose. 63 63 64 + --target-ns=PID: 65 + Obtain mount namespace information from the target pid. This is 66 + used when creating a uprobe for a process that resides in a 67 + different mount namespace from the perf(1) utility. 68 + 64 69 SEE ALSO 65 70 -------- 66 71 linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-buildid-list[1]
+5
tools/perf/Documentation/perf-probe.txt
··· 273 273 274 274 ./perf probe --target-ns <target pid> -x /lib64/libc.so.6 malloc 275 275 276 + Add a USDT probe to a target process running in a different mount namespace 277 + 278 + ./perf probe --target-ns <target pid> -x /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.121-0.b13.el7_3.x86_64/jre/lib/amd64/server/libjvm.so %sdt_hotspot:thread__sleep__end 279 + 280 + 276 281 SEE ALSO 277 282 -------- 278 283 linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1]
+37 -15
tools/perf/builtin-buildid-cache.c
··· 14 14 #include <unistd.h> 15 15 #include "builtin.h" 16 16 #include "perf.h" 17 + #include "namespaces.h" 17 18 #include "util/cache.h" 18 19 #include "util/debug.h" 19 20 #include "util/header.h" ··· 166 165 return 0; 167 166 } 168 167 169 - static int build_id_cache__add_file(const char *filename) 168 + static int build_id_cache__add_file(const char *filename, struct nsinfo *nsi) 170 169 { 171 170 char sbuild_id[SBUILD_ID_SIZE]; 172 171 u8 build_id[BUILD_ID_SIZE]; 173 172 int err; 173 + struct nscookie nsc; 174 174 175 - if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) { 175 + nsinfo__mountns_enter(nsi, &nsc); 176 + err = filename__read_build_id(filename, &build_id, sizeof(build_id)); 177 + nsinfo__mountns_exit(&nsc); 178 + if (err < 0) { 176 179 pr_debug("Couldn't read a build-id in %s\n", filename); 177 180 return -1; 178 181 } 179 182 180 183 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 181 - err = build_id_cache__add_s(sbuild_id, filename, 184 + err = build_id_cache__add_s(sbuild_id, filename, nsi, 182 185 false, false); 183 186 pr_debug("Adding %s %s: %s\n", sbuild_id, filename, 184 187 err ? "FAIL" : "Ok"); 185 188 return err; 186 189 } 187 190 188 - static int build_id_cache__remove_file(const char *filename) 191 + static int build_id_cache__remove_file(const char *filename, struct nsinfo *nsi) 189 192 { 190 193 u8 build_id[BUILD_ID_SIZE]; 191 194 char sbuild_id[SBUILD_ID_SIZE]; 195 + struct nscookie nsc; 192 196 193 197 int err; 194 198 195 - if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) { 199 + nsinfo__mountns_enter(nsi, &nsc); 200 + err = filename__read_build_id(filename, &build_id, sizeof(build_id)); 201 + nsinfo__mountns_exit(&nsc); 202 + if (err < 0) { 196 203 pr_debug("Couldn't read a build-id in %s\n", filename); 197 204 return -1; 198 205 } ··· 213 204 return err; 214 205 } 215 206 216 - static int build_id_cache__purge_path(const char *pathname) 207 + static int build_id_cache__purge_path(const char *pathname, struct nsinfo *nsi) 217 208 { 218 209 struct strlist *list; 219 210 struct str_node *pos; 220 211 int err; 221 212 222 - err = build_id_cache__list_build_ids(pathname, &list); 213 + err = build_id_cache__list_build_ids(pathname, nsi, &list); 223 214 if (err) 224 215 goto out; 225 216 ··· 265 256 return 0; 266 257 } 267 258 268 - static int build_id_cache__update_file(const char *filename) 259 + static int build_id_cache__update_file(const char *filename, struct nsinfo *nsi) 269 260 { 270 261 u8 build_id[BUILD_ID_SIZE]; 271 262 char sbuild_id[SBUILD_ID_SIZE]; 263 + struct nscookie nsc; 272 264 273 - int err = 0; 265 + int err; 274 266 275 - if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) { 267 + nsinfo__mountns_enter(nsi, &nsc); 268 + err = filename__read_build_id(filename, &build_id, sizeof(build_id)); 269 + nsinfo__mountns_exit(&nsc); 270 + if (err < 0) { 276 271 pr_debug("Couldn't read a build-id in %s\n", filename); 277 272 return -1; 278 273 } 274 + err = 0; 279 275 280 276 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 281 277 if (build_id_cache__cached(sbuild_id)) 282 278 err = build_id_cache__remove_s(sbuild_id); 283 279 284 280 if (!err) 285 - err = build_id_cache__add_s(sbuild_id, filename, false, false); 281 + err = build_id_cache__add_s(sbuild_id, filename, nsi, false, 282 + false); 286 283 287 284 pr_debug("Updating %s %s: %s\n", sbuild_id, filename, 288 285 err ? "FAIL" : "Ok"); ··· 301 286 struct strlist *list; 302 287 struct str_node *pos; 303 288 int ret = 0; 289 + int ns_id = -1; 304 290 bool force = false; 305 291 char const *add_name_list_str = NULL, 306 292 *remove_name_list_str = NULL, ··· 315 299 .mode = PERF_DATA_MODE_READ, 316 300 }; 317 301 struct perf_session *session = NULL; 302 + struct nsinfo *nsi = NULL; 318 303 319 304 const struct option buildid_cache_options[] = { 320 305 OPT_STRING('a', "add", &add_name_list_str, ··· 332 315 OPT_STRING('u', "update", &update_name_list_str, "file list", 333 316 "file(s) to update"), 334 317 OPT_INCR('v', "verbose", &verbose, "be more verbose"), 318 + OPT_INTEGER(0, "target-ns", &ns_id, "target pid for namespace context"), 335 319 OPT_END() 336 320 }; 337 321 const char * const buildid_cache_usage[] = { ··· 347 329 !remove_name_list_str && !purge_name_list_str && 348 330 !missing_filename && !update_name_list_str)) 349 331 usage_with_options(buildid_cache_usage, buildid_cache_options); 332 + 333 + if (ns_id > 0) 334 + nsi = nsinfo__new(ns_id); 350 335 351 336 if (missing_filename) { 352 337 file.path = missing_filename; ··· 369 348 list = strlist__new(add_name_list_str, NULL); 370 349 if (list) { 371 350 strlist__for_each_entry(pos, list) 372 - if (build_id_cache__add_file(pos->s)) { 351 + if (build_id_cache__add_file(pos->s, nsi)) { 373 352 if (errno == EEXIST) { 374 353 pr_debug("%s already in the cache\n", 375 354 pos->s); ··· 387 366 list = strlist__new(remove_name_list_str, NULL); 388 367 if (list) { 389 368 strlist__for_each_entry(pos, list) 390 - if (build_id_cache__remove_file(pos->s)) { 369 + if (build_id_cache__remove_file(pos->s, nsi)) { 391 370 if (errno == ENOENT) { 392 371 pr_debug("%s wasn't in the cache\n", 393 372 pos->s); ··· 405 384 list = strlist__new(purge_name_list_str, NULL); 406 385 if (list) { 407 386 strlist__for_each_entry(pos, list) 408 - if (build_id_cache__purge_path(pos->s)) { 387 + if (build_id_cache__purge_path(pos->s, nsi)) { 409 388 if (errno == ENOENT) { 410 389 pr_debug("%s wasn't in the cache\n", 411 390 pos->s); ··· 426 405 list = strlist__new(update_name_list_str, NULL); 427 406 if (list) { 428 407 strlist__for_each_entry(pos, list) 429 - if (build_id_cache__update_file(pos->s)) { 408 + if (build_id_cache__update_file(pos->s, nsi)) { 430 409 if (errno == ENOENT) { 431 410 pr_debug("%s wasn't in the cache\n", 432 411 pos->s); ··· 445 424 446 425 out: 447 426 perf_session__delete(session); 427 + nsinfo__zput(nsi); 448 428 449 429 return ret; 450 430 }
+1 -1
tools/perf/builtin-probe.c
··· 416 416 } 417 417 418 418 strlist__for_each_entry(nd, bidlist) { 419 - cache = probe_cache__new(nd->s); 419 + cache = probe_cache__new(nd->s, NULL); 420 420 if (!cache) 421 421 continue; 422 422 if (probe_cache__filter_purge(cache, filter) < 0 ||
+2 -2
tools/perf/tests/sdt.c
··· 33 33 } 34 34 35 35 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 36 - err = build_id_cache__add_s(sbuild_id, filename, false, false); 36 + err = build_id_cache__add_s(sbuild_id, filename, NULL, false, false); 37 37 if (err < 0) 38 38 pr_debug("Failed to add build id cache of %s\n", filename); 39 39 return err; ··· 54 54 static int search_cached_probe(const char *target, 55 55 const char *group, const char *event) 56 56 { 57 - struct probe_cache *cache = probe_cache__new(target); 57 + struct probe_cache *cache = probe_cache__new(target, NULL); 58 58 int ret = 0; 59 59 60 60 if (!cache) {
+30 -17
tools/perf/util/build-id.c
··· 534 534 } 535 535 536 536 char *build_id_cache__cachedir(const char *sbuild_id, const char *name, 537 - bool is_kallsyms, bool is_vdso) 537 + struct nsinfo *nsi, bool is_kallsyms, 538 + bool is_vdso) 538 539 { 539 540 char *realname = (char *)name, *filename; 540 541 bool slash = is_kallsyms || is_vdso; 541 542 542 543 if (!slash) { 543 - realname = realpath(name, NULL); 544 + realname = nsinfo__realpath(name, nsi); 544 545 if (!realname) 545 546 return NULL; 546 547 } ··· 557 556 return filename; 558 557 } 559 558 560 - int build_id_cache__list_build_ids(const char *pathname, 559 + int build_id_cache__list_build_ids(const char *pathname, struct nsinfo *nsi, 561 560 struct strlist **result) 562 561 { 563 562 char *dir_name; 564 563 int ret = 0; 565 564 566 - dir_name = build_id_cache__cachedir(NULL, pathname, false, false); 565 + dir_name = build_id_cache__cachedir(NULL, pathname, nsi, false, false); 567 566 if (!dir_name) 568 567 return -ENOMEM; 569 568 ··· 577 576 578 577 #if defined(HAVE_LIBELF_SUPPORT) && defined(HAVE_GELF_GETNOTE_SUPPORT) 579 578 static int build_id_cache__add_sdt_cache(const char *sbuild_id, 580 - const char *realname) 579 + const char *realname, 580 + struct nsinfo *nsi) 581 581 { 582 582 struct probe_cache *cache; 583 583 int ret; 584 + struct nscookie nsc; 584 585 585 - cache = probe_cache__new(sbuild_id); 586 + cache = probe_cache__new(sbuild_id, nsi); 586 587 if (!cache) 587 588 return -1; 588 589 590 + nsinfo__mountns_enter(nsi, &nsc); 589 591 ret = probe_cache__scan_sdt(cache, realname); 592 + nsinfo__mountns_exit(&nsc); 590 593 if (ret >= 0) { 591 594 pr_debug4("Found %d SDTs in %s\n", ret, realname); 592 595 if (probe_cache__commit(cache) < 0) ··· 600 595 return ret; 601 596 } 602 597 #else 603 - #define build_id_cache__add_sdt_cache(sbuild_id, realname) (0) 598 + #define build_id_cache__add_sdt_cache(sbuild_id, realname, nsi) (0) 604 599 #endif 605 600 606 601 int build_id_cache__add_s(const char *sbuild_id, const char *name, 607 - bool is_kallsyms, bool is_vdso) 602 + struct nsinfo *nsi, bool is_kallsyms, bool is_vdso) 608 603 { 609 604 const size_t size = PATH_MAX; 610 605 char *realname = NULL, *filename = NULL, *dir_name = NULL, ··· 612 607 int err = -1; 613 608 614 609 if (!is_kallsyms) { 615 - realname = realpath(name, NULL); 610 + if (!is_vdso) 611 + realname = nsinfo__realpath(name, nsi); 612 + else 613 + realname = realpath(name, NULL); 616 614 if (!realname) 617 615 goto out_free; 618 616 } 619 617 620 - dir_name = build_id_cache__cachedir(sbuild_id, name, 621 - is_kallsyms, is_vdso); 618 + dir_name = build_id_cache__cachedir(sbuild_id, name, nsi, is_kallsyms, 619 + is_vdso); 622 620 if (!dir_name) 623 621 goto out_free; 624 622 ··· 642 634 643 635 if (access(filename, F_OK)) { 644 636 if (is_kallsyms) { 645 - if (copyfile("/proc/kallsyms", filename)) 637 + if (copyfile("/proc/kallsyms", filename)) 638 + goto out_free; 639 + } else if (nsi && nsi->need_setns) { 640 + if (copyfile_ns(name, filename, nsi)) 646 641 goto out_free; 647 642 } else if (link(realname, filename) && errno != EEXIST && 648 643 copyfile(name, filename)) ··· 668 657 err = 0; 669 658 670 659 /* Update SDT cache : error is just warned */ 671 - if (realname && build_id_cache__add_sdt_cache(sbuild_id, realname) < 0) 660 + if (realname && 661 + build_id_cache__add_sdt_cache(sbuild_id, realname, nsi) < 0) 672 662 pr_debug4("Failed to update/scan SDT cache for %s\n", realname); 673 663 674 664 out_free: ··· 682 670 } 683 671 684 672 static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, 685 - const char *name, bool is_kallsyms, 686 - bool is_vdso) 673 + const char *name, struct nsinfo *nsi, 674 + bool is_kallsyms, bool is_vdso) 687 675 { 688 676 char sbuild_id[SBUILD_ID_SIZE]; 689 677 690 678 build_id__sprintf(build_id, build_id_size, sbuild_id); 691 679 692 - return build_id_cache__add_s(sbuild_id, name, is_kallsyms, is_vdso); 680 + return build_id_cache__add_s(sbuild_id, name, nsi, is_kallsyms, 681 + is_vdso); 693 682 } 694 683 695 684 bool build_id_cache__cached(const char *sbuild_id) ··· 756 743 name = nm; 757 744 } 758 745 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, 759 - is_kallsyms, is_vdso); 746 + dso->nsinfo, is_kallsyms, is_vdso); 760 747 } 761 748 762 749 static int __dsos__cache_build_ids(struct list_head *head,
+6 -3
tools/perf/util/build-id.h
··· 5 5 #define SBUILD_ID_SIZE (BUILD_ID_SIZE * 2 + 1) 6 6 7 7 #include "tool.h" 8 + #include "namespaces.h" 8 9 #include <linux/types.h> 9 10 10 11 extern struct perf_tool build_id__mark_dso_hit_ops; ··· 32 31 char *build_id_cache__origname(const char *sbuild_id); 33 32 char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size); 34 33 char *build_id_cache__cachedir(const char *sbuild_id, const char *name, 35 - bool is_kallsyms, bool is_vdso); 34 + struct nsinfo *nsi, bool is_kallsyms, 35 + bool is_vdso); 36 36 37 37 struct strlist; 38 38 39 39 struct strlist *build_id_cache__list_all(bool validonly); 40 40 char *build_id_cache__complement(const char *incomplete_sbuild_id); 41 - int build_id_cache__list_build_ids(const char *pathname, 41 + int build_id_cache__list_build_ids(const char *pathname, struct nsinfo *nsi, 42 42 struct strlist **result); 43 43 bool build_id_cache__cached(const char *sbuild_id); 44 44 int build_id_cache__add_s(const char *sbuild_id, 45 - const char *name, bool is_kallsyms, bool is_vdso); 45 + const char *name, struct nsinfo *nsi, 46 + bool is_kallsyms, bool is_vdso); 46 47 int build_id_cache__remove_s(const char *sbuild_id); 47 48 48 49 extern char buildid_dir[];
+11 -1
tools/perf/util/dso.c
··· 504 504 */ 505 505 static int open_dso(struct dso *dso, struct machine *machine) 506 506 { 507 - int fd = __open_dso(dso, machine); 507 + int fd; 508 + struct nscookie nsc; 509 + 510 + if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE) 511 + nsinfo__mountns_enter(dso->nsinfo, &nsc); 512 + fd = __open_dso(dso, machine); 513 + if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE) 514 + nsinfo__mountns_exit(&nsc); 508 515 509 516 if (fd >= 0) { 510 517 dso__list_add(dso); ··· 1309 1302 { 1310 1303 bool have_build_id = false; 1311 1304 struct dso *pos; 1305 + struct nscookie nsc; 1312 1306 1313 1307 list_for_each_entry(pos, head, node) { 1314 1308 if (with_hits && !pos->hit && !dso__is_vdso(pos)) ··· 1318 1310 have_build_id = true; 1319 1311 continue; 1320 1312 } 1313 + nsinfo__mountns_enter(pos->nsinfo, &nsc); 1321 1314 if (filename__read_build_id(pos->long_name, pos->build_id, 1322 1315 sizeof(pos->build_id)) > 0) { 1323 1316 have_build_id = true; 1324 1317 pos->has_build_id = true; 1325 1318 } 1319 + nsinfo__mountns_exit(&nsc); 1326 1320 } 1327 1321 1328 1322 return have_build_id;
+1 -1
tools/perf/util/parse-events.c
··· 2124 2124 return; 2125 2125 } 2126 2126 strlist__for_each_entry(nd, bidlist) { 2127 - pcache = probe_cache__new(nd->s); 2127 + pcache = probe_cache__new(nd->s, NULL); 2128 2128 if (!pcache) 2129 2129 continue; 2130 2130 list_for_each_entry(ent, &pcache->entries, node) {
+3 -3
tools/perf/util/probe-event.c
··· 2769 2769 if (ret == -EINVAL && pev->uprobes) 2770 2770 warn_uprobe_event_compat(tev); 2771 2771 if (ret == 0 && probe_conf.cache) { 2772 - cache = probe_cache__new(pev->target); 2772 + cache = probe_cache__new(pev->target, pev->nsi); 2773 2773 if (!cache || 2774 2774 probe_cache__add_entry(cache, pev, tevs, ntevs) < 0 || 2775 2775 probe_cache__commit(cache) < 0) ··· 3119 3119 int ntevs = 0; 3120 3120 int ret = 0; 3121 3121 3122 - cache = probe_cache__new(target); 3122 + cache = probe_cache__new(target, pev->nsi); 3123 3123 /* Return 0 ("not found") if the target has no probe cache. */ 3124 3124 if (!cache) 3125 3125 return 0; ··· 3209 3209 else 3210 3210 return find_cached_events(pev, tevs, pev->target); 3211 3211 } 3212 - cache = probe_cache__new(pev->target); 3212 + cache = probe_cache__new(pev->target, pev->nsi); 3213 3213 if (!cache) 3214 3214 return 0; 3215 3215
+12 -7
tools/perf/util/probe-file.c
··· 412 412 } 413 413 414 414 /* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */ 415 - static int probe_cache__open(struct probe_cache *pcache, const char *target) 415 + static int probe_cache__open(struct probe_cache *pcache, const char *target, 416 + struct nsinfo *nsi) 416 417 { 417 418 char cpath[PATH_MAX]; 418 419 char sbuildid[SBUILD_ID_SIZE]; 419 420 char *dir_name = NULL; 420 421 bool is_kallsyms = false; 421 422 int ret, fd; 423 + struct nscookie nsc; 422 424 423 425 if (target && build_id_cache__cached(target)) { 424 426 /* This is a cached buildid */ ··· 433 431 target = DSO__NAME_KALLSYMS; 434 432 is_kallsyms = true; 435 433 ret = sysfs__sprintf_build_id("/", sbuildid); 436 - } else 434 + } else { 435 + nsinfo__mountns_enter(nsi, &nsc); 437 436 ret = filename__sprintf_build_id(target, sbuildid); 437 + nsinfo__mountns_exit(&nsc); 438 + } 438 439 439 440 if (ret < 0) { 440 441 pr_debug("Failed to get build-id from %s.\n", target); ··· 446 441 447 442 /* If we have no buildid cache, make it */ 448 443 if (!build_id_cache__cached(sbuildid)) { 449 - ret = build_id_cache__add_s(sbuildid, target, 444 + ret = build_id_cache__add_s(sbuildid, target, nsi, 450 445 is_kallsyms, NULL); 451 446 if (ret < 0) { 452 447 pr_debug("Failed to add build-id cache: %s\n", target); ··· 454 449 } 455 450 } 456 451 457 - dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms, 452 + dir_name = build_id_cache__cachedir(sbuildid, target, nsi, is_kallsyms, 458 453 false); 459 454 found: 460 455 if (!dir_name) { ··· 559 554 free(pcache); 560 555 } 561 556 562 - struct probe_cache *probe_cache__new(const char *target) 557 + struct probe_cache *probe_cache__new(const char *target, struct nsinfo *nsi) 563 558 { 564 559 struct probe_cache *pcache = probe_cache__alloc(); 565 560 int ret; ··· 567 562 if (!pcache) 568 563 return NULL; 569 564 570 - ret = probe_cache__open(pcache, target); 565 + ret = probe_cache__open(pcache, target, nsi); 571 566 if (ret < 0) { 572 567 pr_debug("Cache open error: %d\n", ret); 573 568 goto out_err; ··· 979 974 return -EINVAL; 980 975 } 981 976 strlist__for_each_entry(nd, bidlist) { 982 - pcache = probe_cache__new(nd->s); 977 + pcache = probe_cache__new(nd->s, NULL); 983 978 if (!pcache) 984 979 continue; 985 980 if (!list_empty(&pcache->entries)) {
+2 -2
tools/perf/util/probe-file.h
··· 51 51 int probe_cache_entry__get_event(struct probe_cache_entry *entry, 52 52 struct probe_trace_event **tevs); 53 53 54 - struct probe_cache *probe_cache__new(const char *target); 54 + struct probe_cache *probe_cache__new(const char *target, struct nsinfo *nsi); 55 55 int probe_cache__add_entry(struct probe_cache *pcache, 56 56 struct perf_probe_event *pev, 57 57 struct probe_trace_event *tevs, int ntevs); ··· 69 69 bool probe_type_is_available(enum probe_type type); 70 70 bool kretprobe_offset_is_supported(void); 71 71 #else /* ! HAVE_LIBELF_SUPPORT */ 72 - static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused) 72 + static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused, struct nsinfo *nsi __maybe_unused) 73 73 { 74 74 return NULL; 75 75 }
+1
tools/perf/util/python-ext-sources
··· 10 10 util/evlist.c 11 11 util/evsel.c 12 12 util/cpumap.c 13 + util/namespaces.c 13 14 ../lib/bitmap.c 14 15 ../lib/find_bit.c 15 16 ../lib/hweight.c
+14 -5
tools/perf/util/symbol.c
··· 1464 1464 return rc; 1465 1465 } 1466 1466 1467 - 1468 1467 int dso__load(struct dso *dso, struct map *map) 1469 1468 { 1470 1469 char *name; ··· 1564 1565 for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) { 1565 1566 struct symsrc *ss = &ss_[ss_pos]; 1566 1567 bool next_slot = false; 1568 + bool is_reg; 1569 + int sirc; 1567 1570 1568 1571 enum dso_binary_type symtab_type = binary_type_symtab[i]; 1569 1572 ··· 1576 1575 root_dir, name, PATH_MAX)) 1577 1576 continue; 1578 1577 1579 - if (!is_regular_file(name)) 1580 - continue; 1578 + if (symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE) 1579 + nsinfo__mountns_exit(&nsc); 1581 1580 1582 - /* Name is now the name of the next image to try */ 1583 - if (symsrc__init(ss, dso, name, symtab_type) < 0) 1581 + is_reg = is_regular_file(name); 1582 + sirc = symsrc__init(ss, dso, name, symtab_type); 1583 + 1584 + if (symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE) 1585 + nsinfo__mountns_enter(dso->nsinfo, &nsc); 1586 + 1587 + if (!is_reg || sirc < 0) { 1588 + if (sirc >= 0) 1589 + symsrc__destroy(ss); 1584 1590 continue; 1591 + } 1585 1592 1586 1593 if (!syms_ss && symsrc__has_symtab(ss)) { 1587 1594 syms_ss = ss;
+28 -6
tools/perf/util/util.c
··· 143 143 return list; 144 144 } 145 145 146 - static int slow_copyfile(const char *from, const char *to) 146 + static int slow_copyfile(const char *from, const char *to, struct nsinfo *nsi) 147 147 { 148 148 int err = -1; 149 149 char *line = NULL; 150 150 size_t n; 151 - FILE *from_fp = fopen(from, "r"), *to_fp; 151 + FILE *from_fp, *to_fp; 152 + struct nscookie nsc; 152 153 154 + nsinfo__mountns_enter(nsi, &nsc); 155 + from_fp = fopen(from, "r"); 156 + nsinfo__mountns_exit(&nsc); 153 157 if (from_fp == NULL) 154 158 goto out; 155 159 ··· 202 198 return size ? -1 : 0; 203 199 } 204 200 205 - int copyfile_mode(const char *from, const char *to, mode_t mode) 201 + static int copyfile_mode_ns(const char *from, const char *to, mode_t mode, 202 + struct nsinfo *nsi) 206 203 { 207 204 int fromfd, tofd; 208 205 struct stat st; 209 - int err = -1; 206 + int err; 210 207 char *tmp = NULL, *ptr = NULL; 208 + struct nscookie nsc; 211 209 212 - if (stat(from, &st)) 210 + nsinfo__mountns_enter(nsi, &nsc); 211 + err = stat(from, &st); 212 + nsinfo__mountns_exit(&nsc); 213 + if (err) 213 214 goto out; 215 + err = -1; 214 216 215 217 /* extra 'x' at the end is to reserve space for '.' */ 216 218 if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) { ··· 237 227 goto out_close_to; 238 228 239 229 if (st.st_size == 0) { /* /proc? do it slowly... */ 240 - err = slow_copyfile(from, tmp); 230 + err = slow_copyfile(from, tmp, nsi); 241 231 goto out_close_to; 242 232 } 243 233 234 + nsinfo__mountns_enter(nsi, &nsc); 244 235 fromfd = open(from, O_RDONLY); 236 + nsinfo__mountns_exit(&nsc); 245 237 if (fromfd < 0) 246 238 goto out_close_to; 247 239 ··· 258 246 out: 259 247 free(tmp); 260 248 return err; 249 + } 250 + 251 + int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi) 252 + { 253 + return copyfile_mode_ns(from, to, 0755, nsi); 254 + } 255 + 256 + int copyfile_mode(const char *from, const char *to, mode_t mode) 257 + { 258 + return copyfile_mode_ns(from, to, mode, NULL); 261 259 } 262 260 263 261 int copyfile(const char *from, const char *to)
+2
tools/perf/util/util.h
··· 12 12 #include <stdarg.h> 13 13 #include <linux/compiler.h> 14 14 #include <linux/types.h> 15 + #include "namespaces.h" 15 16 16 17 /* General helper functions */ 17 18 void usage(const char *err) __noreturn; ··· 34 33 bool lsdir_no_dot_filter(const char *name, struct dirent *d); 35 34 int copyfile(const char *from, const char *to); 36 35 int copyfile_mode(const char *from, const char *to, mode_t mode); 36 + int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi); 37 37 int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size); 38 38 39 39 ssize_t readn(int fd, void *buf, size_t n);