summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrister Johansen <kjlx@templeofstupid.com>2017-07-05 21:48:10 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-07-18 22:14:10 -0400
commit544abd44c7064c8a58a6bd2073d757f6b91d98c5 (patch)
treefaa9e5d4c4b86067f4b5cd9f8200010a726a314d
parentbf2e710b3cb8445c052f2ff50b4875a2523bb279 (diff)
perf probe: Allow placing uprobes in alternate namespaces.
Teaches perf how to place a uprobe on a file that's in a different mount namespace. The user must add the probe using the --target-ns argument to perf probe. Once it has been placed, it may be recorded against without further namespace-specific commands. Signed-off-by: Krister Johansen <kjlx@templeofstupid.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Brendan Gregg <brendan.d.gregg@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> [ PPC build fixed by Ravi: ] Link: http://lkml.kernel.org/r/1500287542-6219-1-git-send-email-ravi.bangoria@linux.vnet.ibm.com Cc: Thomas-Mich Richter <tmricht@linux.vnet.ibm.com> [ Fix !HAVE_DWARF_SUPPORT build ] Link: http://lkml.kernel.org/r/1499305693-1599-4-git-send-email-kjlx@templeofstupid.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/Documentation/perf-probe.txt9
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c2
-rw-r--r--tools/perf/builtin-probe.c43
-rw-r--r--tools/perf/util/namespaces.c13
-rw-r--r--tools/perf/util/namespaces.h2
-rw-r--r--tools/perf/util/probe-event.c80
-rw-r--r--tools/perf/util/probe-event.h10
7 files changed, 125 insertions, 34 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 165c2b1d4317..a42aabc2b082 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -130,6 +130,11 @@ OPTIONS
130--max-probes=NUM:: 130--max-probes=NUM::
131 Set the maximum number of probe points for an event. Default is 128. 131 Set the maximum number of probe points for an event. Default is 128.
132 132
133--target-ns=PID:
134 Obtain mount namespace information from the target pid. This is
135 used when creating a uprobe for a process that resides in a
136 different mount namespace from the perf(1) utility.
137
133-x:: 138-x::
134--exec=PATH:: 139--exec=PATH::
135 Specify path to the executable or shared library file for user 140 Specify path to the executable or shared library file for user
@@ -264,6 +269,10 @@ Add probes at malloc() function on libc
264 269
265 ./perf probe -x /lib/libc.so.6 malloc or ./perf probe /lib/libc.so.6 malloc 270 ./perf probe -x /lib/libc.so.6 malloc or ./perf probe /lib/libc.so.6 malloc
266 271
272Add a uprobe to a target process running in a different mount namespace
273
274 ./perf probe --target-ns <target pid> -x /lib64/libc.so.6 malloc
275
267SEE ALSO 276SEE ALSO
268-------- 277--------
269linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1] 278linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1]
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index bf9a2594572c..9c4e23d8c8ce 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -126,7 +126,7 @@ void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
126 struct rb_node *tmp; 126 struct rb_node *tmp;
127 int i = 0; 127 int i = 0;
128 128
129 map = get_target_map(pev->target, pev->uprobes); 129 map = get_target_map(pev->target, pev->nsi, pev->uprobes);
130 if (!map || map__load(map) < 0) 130 if (!map || map__load(map) < 0)
131 return; 131 return;
132 132
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index cf9f9e9c2fc0..3fb98d59cd27 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -58,6 +58,7 @@ static struct {
58 struct line_range line_range; 58 struct line_range line_range;
59 char *target; 59 char *target;
60 struct strfilter *filter; 60 struct strfilter *filter;
61 struct nsinfo *nsi;
61} params; 62} params;
62 63
63/* Parse an event definition. Note that any error must die. */ 64/* Parse an event definition. Note that any error must die. */
@@ -80,6 +81,9 @@ static int parse_probe_event(const char *str)
80 params.target_used = true; 81 params.target_used = true;
81 } 82 }
82 83
84 if (params.nsi)
85 pev->nsi = nsinfo__get(params.nsi);
86
83 /* Parse a perf-probe command into event */ 87 /* Parse a perf-probe command into event */
84 ret = parse_perf_probe_command(str, pev); 88 ret = parse_perf_probe_command(str, pev);
85 pr_debug("%d arguments\n", pev->nargs); 89 pr_debug("%d arguments\n", pev->nargs);
@@ -189,7 +193,7 @@ static int opt_set_target(const struct option *opt, const char *str,
189 193
190 /* Expand given path to absolute path, except for modulename */ 194 /* Expand given path to absolute path, except for modulename */
191 if (params.uprobes || strchr(str, '/')) { 195 if (params.uprobes || strchr(str, '/')) {
192 tmp = realpath(str, NULL); 196 tmp = nsinfo__realpath(str, params.nsi);
193 if (!tmp) { 197 if (!tmp) {
194 pr_warning("Failed to get the absolute path of %s: %m\n", str); 198 pr_warning("Failed to get the absolute path of %s: %m\n", str);
195 return ret; 199 return ret;
@@ -208,6 +212,34 @@ static int opt_set_target(const struct option *opt, const char *str,
208 return ret; 212 return ret;
209} 213}
210 214
215static int opt_set_target_ns(const struct option *opt __maybe_unused,
216 const char *str, int unset __maybe_unused)
217{
218 int ret = -ENOENT;
219 pid_t ns_pid;
220 struct nsinfo *nsip;
221
222 if (str) {
223 errno = 0;
224 ns_pid = (pid_t)strtol(str, NULL, 10);
225 if (errno != 0) {
226 ret = -errno;
227 pr_warning("Failed to parse %s as a pid: %s\n", str,
228 strerror(errno));
229 return ret;
230 }
231 nsip = nsinfo__new(ns_pid);
232 if (nsip && nsip->need_setns)
233 params.nsi = nsinfo__get(nsip);
234 nsinfo__put(nsip);
235
236 ret = 0;
237 }
238
239 return ret;
240}
241
242
211/* Command option callbacks */ 243/* Command option callbacks */
212 244
213#ifdef HAVE_DWARF_SUPPORT 245#ifdef HAVE_DWARF_SUPPORT
@@ -299,6 +331,7 @@ static void cleanup_params(void)
299 line_range__clear(&params.line_range); 331 line_range__clear(&params.line_range);
300 free(params.target); 332 free(params.target);
301 strfilter__delete(params.filter); 333 strfilter__delete(params.filter);
334 nsinfo__put(params.nsi);
302 memset(&params, 0, sizeof(params)); 335 memset(&params, 0, sizeof(params));
303} 336}
304 337
@@ -554,6 +587,8 @@ __cmd_probe(int argc, const char **argv)
554 OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"), 587 OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
555 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 588 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
556 "Look for files with symbols relative to this directory"), 589 "Look for files with symbols relative to this directory"),
590 OPT_CALLBACK(0, "target-ns", NULL, "pid",
591 "target pid for namespace contexts", opt_set_target_ns),
557 OPT_END() 592 OPT_END()
558 }; 593 };
559 int ret; 594 int ret;
@@ -634,15 +669,15 @@ __cmd_probe(int argc, const char **argv)
634 pr_err_with_code(" Error: Failed to show event list.", ret); 669 pr_err_with_code(" Error: Failed to show event list.", ret);
635 return ret; 670 return ret;
636 case 'F': 671 case 'F':
637 ret = show_available_funcs(params.target, params.filter, 672 ret = show_available_funcs(params.target, params.nsi,
638 params.uprobes); 673 params.filter, params.uprobes);
639 if (ret < 0) 674 if (ret < 0)
640 pr_err_with_code(" Error: Failed to show functions.", ret); 675 pr_err_with_code(" Error: Failed to show functions.", ret);
641 return ret; 676 return ret;
642#ifdef HAVE_DWARF_SUPPORT 677#ifdef HAVE_DWARF_SUPPORT
643 case 'L': 678 case 'L':
644 ret = show_line_range(&params.line_range, params.target, 679 ret = show_line_range(&params.line_range, params.target,
645 params.uprobes); 680 params.nsi, params.uprobes);
646 if (ret < 0) 681 if (ret < 0)
647 pr_err_with_code(" Error: Failed to show lines.", ret); 682 pr_err_with_code(" Error: Failed to show lines.", ret);
648 return ret; 683 return ret;
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
index fc5f398779a4..a58e91197729 100644
--- a/tools/perf/util/namespaces.c
+++ b/tools/perf/util/namespaces.c
@@ -11,6 +11,7 @@
11#include "event.h" 11#include "event.h"
12#include <sys/types.h> 12#include <sys/types.h>
13#include <sys/stat.h> 13#include <sys/stat.h>
14#include <limits.h>
14#include <sched.h> 15#include <sched.h>
15#include <stdlib.h> 16#include <stdlib.h>
16#include <stdio.h> 17#include <stdio.h>
@@ -233,3 +234,15 @@ void nsinfo__mountns_exit(struct nscookie *nc)
233 nc->newns = -1; 234 nc->newns = -1;
234 } 235 }
235} 236}
237
238char *nsinfo__realpath(const char *path, struct nsinfo *nsi)
239{
240 char *rpath;
241 struct nscookie nsc;
242
243 nsinfo__mountns_enter(nsi, &nsc);
244 rpath = realpath(path, NULL);
245 nsinfo__mountns_exit(&nsc);
246
247 return rpath;
248}
diff --git a/tools/perf/util/namespaces.h b/tools/perf/util/namespaces.h
index f19aa41119ae..05d82601c9a6 100644
--- a/tools/perf/util/namespaces.h
+++ b/tools/perf/util/namespaces.h
@@ -49,6 +49,8 @@ void nsinfo__put(struct nsinfo *nsi);
49void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc); 49void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc);
50void nsinfo__mountns_exit(struct nscookie *nc); 50void nsinfo__mountns_exit(struct nscookie *nc);
51 51
52char *nsinfo__realpath(const char *path, struct nsinfo *nsi);
53
52static inline void __nsinfo__zput(struct nsinfo **nsip) 54static inline void __nsinfo__zput(struct nsinfo **nsip)
53{ 55{
54 if (nsip) { 56 if (nsip) {
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index a2670e9d652d..a80895a7e611 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -184,13 +184,19 @@ static struct map *kernel_get_module_map(const char *module)
184 return NULL; 184 return NULL;
185} 185}
186 186
187struct map *get_target_map(const char *target, bool user) 187struct map *get_target_map(const char *target, struct nsinfo *nsi, bool user)
188{ 188{
189 /* Init maps of given executable or kernel */ 189 /* Init maps of given executable or kernel */
190 if (user) 190 if (user) {
191 return dso__new_map(target); 191 struct map *map;
192 else 192
193 map = dso__new_map(target);
194 if (map && map->dso)
195 map->dso->nsinfo = nsinfo__get(nsi);
196 return map;
197 } else {
193 return kernel_get_module_map(target); 198 return kernel_get_module_map(target);
199 }
194} 200}
195 201
196static int convert_exec_to_group(const char *exec, char **result) 202static int convert_exec_to_group(const char *exec, char **result)
@@ -366,7 +372,8 @@ found:
366static int find_alternative_probe_point(struct debuginfo *dinfo, 372static int find_alternative_probe_point(struct debuginfo *dinfo,
367 struct perf_probe_point *pp, 373 struct perf_probe_point *pp,
368 struct perf_probe_point *result, 374 struct perf_probe_point *result,
369 const char *target, bool uprobes) 375 const char *target, struct nsinfo *nsi,
376 bool uprobes)
370{ 377{
371 struct map *map = NULL; 378 struct map *map = NULL;
372 struct symbol *sym; 379 struct symbol *sym;
@@ -377,7 +384,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
377 if (!pp->function || pp->file) 384 if (!pp->function || pp->file)
378 return -ENOTSUP; 385 return -ENOTSUP;
379 386
380 map = get_target_map(target, uprobes); 387 map = get_target_map(target, nsi, uprobes);
381 if (!map) 388 if (!map)
382 return -EINVAL; 389 return -EINVAL;
383 390
@@ -421,8 +428,8 @@ static int get_alternative_probe_event(struct debuginfo *dinfo,
421 428
422 memcpy(tmp, &pev->point, sizeof(*tmp)); 429 memcpy(tmp, &pev->point, sizeof(*tmp));
423 memset(&pev->point, 0, sizeof(pev->point)); 430 memset(&pev->point, 0, sizeof(pev->point));
424 ret = find_alternative_probe_point(dinfo, tmp, &pev->point, 431 ret = find_alternative_probe_point(dinfo, tmp, &pev->point, pev->target,
425 pev->target, pev->uprobes); 432 pev->nsi, pev->uprobes);
426 if (ret < 0) 433 if (ret < 0)
427 memcpy(&pev->point, tmp, sizeof(*tmp)); 434 memcpy(&pev->point, tmp, sizeof(*tmp));
428 435
@@ -444,7 +451,7 @@ static int get_alternative_line_range(struct debuginfo *dinfo,
444 if (lr->end != INT_MAX) 451 if (lr->end != INT_MAX)
445 len = lr->end - lr->start; 452 len = lr->end - lr->start;
446 ret = find_alternative_probe_point(dinfo, &pp, &result, 453 ret = find_alternative_probe_point(dinfo, &pp, &result,
447 target, user); 454 target, NULL, user);
448 if (!ret) { 455 if (!ret) {
449 lr->function = result.function; 456 lr->function = result.function;
450 lr->file = result.file; 457 lr->file = result.file;
@@ -457,12 +464,14 @@ static int get_alternative_line_range(struct debuginfo *dinfo,
457} 464}
458 465
459/* Open new debuginfo of given module */ 466/* Open new debuginfo of given module */
460static struct debuginfo *open_debuginfo(const char *module, bool silent) 467static struct debuginfo *open_debuginfo(const char *module, struct nsinfo *nsi,
468 bool silent)
461{ 469{
462 const char *path = module; 470 const char *path = module;
463 char reason[STRERR_BUFSIZE]; 471 char reason[STRERR_BUFSIZE];
464 struct debuginfo *ret = NULL; 472 struct debuginfo *ret = NULL;
465 struct dso *dso = NULL; 473 struct dso *dso = NULL;
474 struct nscookie nsc;
466 int err; 475 int err;
467 476
468 if (!module || !strchr(module, '/')) { 477 if (!module || !strchr(module, '/')) {
@@ -480,6 +489,7 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent)
480 } 489 }
481 path = dso->long_name; 490 path = dso->long_name;
482 } 491 }
492 nsinfo__mountns_enter(nsi, &nsc);
483 ret = debuginfo__new(path); 493 ret = debuginfo__new(path);
484 if (!ret && !silent) { 494 if (!ret && !silent) {
485 pr_warning("The %s file has no debug information.\n", path); 495 pr_warning("The %s file has no debug information.\n", path);
@@ -489,6 +499,7 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent)
489 pr_warning("Rebuild with -g, "); 499 pr_warning("Rebuild with -g, ");
490 pr_warning("or install an appropriate debuginfo package.\n"); 500 pr_warning("or install an appropriate debuginfo package.\n");
491 } 501 }
502 nsinfo__mountns_exit(&nsc);
492 return ret; 503 return ret;
493} 504}
494 505
@@ -516,7 +527,7 @@ static struct debuginfo *debuginfo_cache__open(const char *module, bool silent)
516 goto out; 527 goto out;
517 } 528 }
518 529
519 debuginfo_cache = open_debuginfo(module, silent); 530 debuginfo_cache = open_debuginfo(module, NULL, silent);
520 if (!debuginfo_cache) 531 if (!debuginfo_cache)
521 zfree(&debuginfo_cache_path); 532 zfree(&debuginfo_cache_path);
522out: 533out:
@@ -531,14 +542,18 @@ static void debuginfo_cache__exit(void)
531} 542}
532 543
533 544
534static int get_text_start_address(const char *exec, unsigned long *address) 545static int get_text_start_address(const char *exec, unsigned long *address,
546 struct nsinfo *nsi)
535{ 547{
536 Elf *elf; 548 Elf *elf;
537 GElf_Ehdr ehdr; 549 GElf_Ehdr ehdr;
538 GElf_Shdr shdr; 550 GElf_Shdr shdr;
539 int fd, ret = -ENOENT; 551 int fd, ret = -ENOENT;
552 struct nscookie nsc;
540 553
554 nsinfo__mountns_enter(nsi, &nsc);
541 fd = open(exec, O_RDONLY); 555 fd = open(exec, O_RDONLY);
556 nsinfo__mountns_exit(&nsc);
542 if (fd < 0) 557 if (fd < 0)
543 return -errno; 558 return -errno;
544 559
@@ -582,7 +597,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
582 ret = -EINVAL; 597 ret = -EINVAL;
583 goto error; 598 goto error;
584 } 599 }
585 ret = get_text_start_address(tp->module, &stext); 600 ret = get_text_start_address(tp->module, &stext, NULL);
586 if (ret < 0) 601 if (ret < 0)
587 goto error; 602 goto error;
588 addr += stext; 603 addr += stext;
@@ -659,7 +674,7 @@ post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
659 674
660 /* Prepare a map for offline binary */ 675 /* Prepare a map for offline binary */
661 map = dso__new_map(pathname); 676 map = dso__new_map(pathname);
662 if (!map || get_text_start_address(pathname, &stext) < 0) { 677 if (!map || get_text_start_address(pathname, &stext, NULL) < 0) {
663 pr_warning("Failed to get ELF symbols for %s\n", pathname); 678 pr_warning("Failed to get ELF symbols for %s\n", pathname);
664 return -EINVAL; 679 return -EINVAL;
665 } 680 }
@@ -676,7 +691,8 @@ post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
676} 691}
677 692
678static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, 693static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
679 int ntevs, const char *exec) 694 int ntevs, const char *exec,
695 struct nsinfo *nsi)
680{ 696{
681 int i, ret = 0; 697 int i, ret = 0;
682 unsigned long stext = 0; 698 unsigned long stext = 0;
@@ -684,7 +700,7 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
684 if (!exec) 700 if (!exec)
685 return 0; 701 return 0;
686 702
687 ret = get_text_start_address(exec, &stext); 703 ret = get_text_start_address(exec, &stext, nsi);
688 if (ret < 0) 704 if (ret < 0)
689 return ret; 705 return ret;
690 706
@@ -715,7 +731,7 @@ post_process_module_probe_trace_events(struct probe_trace_event *tevs,
715 if (!module) 731 if (!module)
716 return 0; 732 return 0;
717 733
718 map = get_target_map(module, false); 734 map = get_target_map(module, NULL, false);
719 if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) { 735 if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) {
720 pr_warning("Failed to get ELF symbols for %s\n", module); 736 pr_warning("Failed to get ELF symbols for %s\n", module);
721 return -EINVAL; 737 return -EINVAL;
@@ -802,7 +818,8 @@ static int post_process_probe_trace_events(struct perf_probe_event *pev,
802 int ret; 818 int ret;
803 819
804 if (uprobe) 820 if (uprobe)
805 ret = add_exec_to_probe_trace_events(tevs, ntevs, module); 821 ret = add_exec_to_probe_trace_events(tevs, ntevs, module,
822 pev->nsi);
806 else if (module) 823 else if (module)
807 /* Currently ref_reloc_sym based probe is not for drivers */ 824 /* Currently ref_reloc_sym based probe is not for drivers */
808 ret = post_process_module_probe_trace_events(tevs, ntevs, 825 ret = post_process_module_probe_trace_events(tevs, ntevs,
@@ -825,7 +842,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
825 struct debuginfo *dinfo; 842 struct debuginfo *dinfo;
826 int ntevs, ret = 0; 843 int ntevs, ret = 0;
827 844
828 dinfo = open_debuginfo(pev->target, !need_dwarf); 845 dinfo = open_debuginfo(pev->target, pev->nsi, !need_dwarf);
829 if (!dinfo) { 846 if (!dinfo) {
830 if (need_dwarf) 847 if (need_dwarf)
831 return -ENOENT; 848 return -ENOENT;
@@ -945,7 +962,7 @@ static int __show_line_range(struct line_range *lr, const char *module,
945 char sbuf[STRERR_BUFSIZE]; 962 char sbuf[STRERR_BUFSIZE];
946 963
947 /* Search a line range */ 964 /* Search a line range */
948 dinfo = open_debuginfo(module, false); 965 dinfo = open_debuginfo(module, NULL, false);
949 if (!dinfo) 966 if (!dinfo)
950 return -ENOENT; 967 return -ENOENT;
951 968
@@ -1021,14 +1038,18 @@ end:
1021 return ret; 1038 return ret;
1022} 1039}
1023 1040
1024int show_line_range(struct line_range *lr, const char *module, bool user) 1041int show_line_range(struct line_range *lr, const char *module,
1042 struct nsinfo *nsi, bool user)
1025{ 1043{
1026 int ret; 1044 int ret;
1045 struct nscookie nsc;
1027 1046
1028 ret = init_probe_symbol_maps(user); 1047 ret = init_probe_symbol_maps(user);
1029 if (ret < 0) 1048 if (ret < 0)
1030 return ret; 1049 return ret;
1050 nsinfo__mountns_enter(nsi, &nsc);
1031 ret = __show_line_range(lr, module, user); 1051 ret = __show_line_range(lr, module, user);
1052 nsinfo__mountns_exit(&nsc);
1032 exit_probe_symbol_maps(); 1053 exit_probe_symbol_maps();
1033 1054
1034 return ret; 1055 return ret;
@@ -1111,7 +1132,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
1111 if (ret < 0) 1132 if (ret < 0)
1112 return ret; 1133 return ret;
1113 1134
1114 dinfo = open_debuginfo(pevs->target, false); 1135 dinfo = open_debuginfo(pevs->target, pevs->nsi, false);
1115 if (!dinfo) { 1136 if (!dinfo) {
1116 ret = -ENOENT; 1137 ret = -ENOENT;
1117 goto out; 1138 goto out;
@@ -1155,6 +1176,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
1155 1176
1156int show_line_range(struct line_range *lr __maybe_unused, 1177int show_line_range(struct line_range *lr __maybe_unused,
1157 const char *module __maybe_unused, 1178 const char *module __maybe_unused,
1179 struct nsinfo *nsi __maybe_unused,
1158 bool user __maybe_unused) 1180 bool user __maybe_unused)
1159{ 1181{
1160 pr_warning("Debuginfo-analysis is not supported.\n"); 1182 pr_warning("Debuginfo-analysis is not supported.\n");
@@ -2703,6 +2725,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2703 struct probe_trace_event *tev = NULL; 2725 struct probe_trace_event *tev = NULL;
2704 struct probe_cache *cache = NULL; 2726 struct probe_cache *cache = NULL;
2705 struct strlist *namelist[2] = {NULL, NULL}; 2727 struct strlist *namelist[2] = {NULL, NULL};
2728 struct nscookie nsc;
2706 2729
2707 up = pev->uprobes ? 1 : 0; 2730 up = pev->uprobes ? 1 : 0;
2708 fd[up] = __open_probe_file_and_namelist(up, &namelist[up]); 2731 fd[up] = __open_probe_file_and_namelist(up, &namelist[up]);
@@ -2729,7 +2752,9 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2729 if (ret < 0) 2752 if (ret < 0)
2730 break; 2753 break;
2731 2754
2755 nsinfo__mountns_enter(pev->nsi, &nsc);
2732 ret = probe_file__add_event(fd[up], tev); 2756 ret = probe_file__add_event(fd[up], tev);
2757 nsinfo__mountns_exit(&nsc);
2733 if (ret < 0) 2758 if (ret < 0)
2734 break; 2759 break;
2735 2760
@@ -2805,7 +2830,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2805 int ret, i, j, skipped = 0; 2830 int ret, i, j, skipped = 0;
2806 char *mod_name; 2831 char *mod_name;
2807 2832
2808 map = get_target_map(pev->target, pev->uprobes); 2833 map = get_target_map(pev->target, pev->nsi, pev->uprobes);
2809 if (!map) { 2834 if (!map) {
2810 ret = -EINVAL; 2835 ret = -EINVAL;
2811 goto out; 2836 goto out;
@@ -3345,13 +3370,16 @@ int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs)
3345void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs) 3370void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs)
3346{ 3371{
3347 int i, j; 3372 int i, j;
3373 struct perf_probe_event *pev;
3348 3374
3349 /* Loop 3: cleanup and free trace events */ 3375 /* Loop 3: cleanup and free trace events */
3350 for (i = 0; i < npevs; i++) { 3376 for (i = 0; i < npevs; i++) {
3377 pev = &pevs[i];
3351 for (j = 0; j < pevs[i].ntevs; j++) 3378 for (j = 0; j < pevs[i].ntevs; j++)
3352 clear_probe_trace_event(&pevs[i].tevs[j]); 3379 clear_probe_trace_event(&pevs[i].tevs[j]);
3353 zfree(&pevs[i].tevs); 3380 zfree(&pevs[i].tevs);
3354 pevs[i].ntevs = 0; 3381 pevs[i].ntevs = 0;
3382 nsinfo__zput(pev->nsi);
3355 clear_perf_probe_event(&pevs[i]); 3383 clear_perf_probe_event(&pevs[i]);
3356 } 3384 }
3357} 3385}
@@ -3409,8 +3437,8 @@ out:
3409 return ret; 3437 return ret;
3410} 3438}
3411 3439
3412int show_available_funcs(const char *target, struct strfilter *_filter, 3440int show_available_funcs(const char *target, struct nsinfo *nsi,
3413 bool user) 3441 struct strfilter *_filter, bool user)
3414{ 3442{
3415 struct rb_node *nd; 3443 struct rb_node *nd;
3416 struct map *map; 3444 struct map *map;
@@ -3421,7 +3449,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
3421 return ret; 3449 return ret;
3422 3450
3423 /* Get a symbol map */ 3451 /* Get a symbol map */
3424 map = get_target_map(target, user); 3452 map = get_target_map(target, nsi, user);
3425 if (!map) { 3453 if (!map) {
3426 pr_err("Failed to get a map for %s\n", (target) ? : "kernel"); 3454 pr_err("Failed to get a map for %s\n", (target) ? : "kernel");
3427 return -EINVAL; 3455 return -EINVAL;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 5812947418dd..078681d12168 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -4,6 +4,7 @@
4#include <linux/compiler.h> 4#include <linux/compiler.h>
5#include <stdbool.h> 5#include <stdbool.h>
6#include "intlist.h" 6#include "intlist.h"
7#include "namespaces.h"
7 8
8/* Probe related configurations */ 9/* Probe related configurations */
9struct probe_conf { 10struct probe_conf {
@@ -92,6 +93,7 @@ struct perf_probe_event {
92 struct perf_probe_arg *args; /* Arguments */ 93 struct perf_probe_arg *args; /* Arguments */
93 struct probe_trace_event *tevs; 94 struct probe_trace_event *tevs;
94 int ntevs; 95 int ntevs;
96 struct nsinfo *nsi; /* Target namespace */
95}; 97};
96 98
97/* Line range */ 99/* Line range */
@@ -163,10 +165,12 @@ int show_perf_probe_event(const char *group, const char *event,
163 struct perf_probe_event *pev, 165 struct perf_probe_event *pev,
164 const char *module, bool use_stdout); 166 const char *module, bool use_stdout);
165int show_perf_probe_events(struct strfilter *filter); 167int show_perf_probe_events(struct strfilter *filter);
166int show_line_range(struct line_range *lr, const char *module, bool user); 168int show_line_range(struct line_range *lr, const char *module,
169 struct nsinfo *nsi, bool user);
167int show_available_vars(struct perf_probe_event *pevs, int npevs, 170int show_available_vars(struct perf_probe_event *pevs, int npevs,
168 struct strfilter *filter); 171 struct strfilter *filter);
169int show_available_funcs(const char *module, struct strfilter *filter, bool user); 172int show_available_funcs(const char *module, struct nsinfo *nsi,
173 struct strfilter *filter, bool user);
170void arch__fix_tev_from_maps(struct perf_probe_event *pev, 174void arch__fix_tev_from_maps(struct perf_probe_event *pev,
171 struct probe_trace_event *tev, struct map *map, 175 struct probe_trace_event *tev, struct map *map,
172 struct symbol *sym); 176 struct symbol *sym);
@@ -180,7 +184,7 @@ int e_snprintf(char *str, size_t size, const char *format, ...) __printf(3, 4);
180int copy_to_probe_trace_arg(struct probe_trace_arg *tvar, 184int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
181 struct perf_probe_arg *pvar); 185 struct perf_probe_arg *pvar);
182 186
183struct map *get_target_map(const char *target, bool user); 187struct map *get_target_map(const char *target, struct nsinfo *nsi, bool user);
184 188
185void arch__post_process_probe_trace_events(struct perf_probe_event *pev, 189void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
186 int ntevs); 190 int ntevs);