Skip to content

Commit

Permalink
perf probe: Allow placing uprobes in alternate namespaces.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Krister Johansen authored and Arnaldo Carvalho de Melo committed Jul 19, 2017
1 parent bf2e710 commit 544abd4
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 34 deletions.
9 changes: 9 additions & 0 deletions tools/perf/Documentation/perf-probe.txt
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ OPTIONS
--max-probes=NUM::
Set the maximum number of probe points for an event. Default is 128.

--target-ns=PID:
Obtain mount namespace information from the target pid. This is
used when creating a uprobe for a process that resides in a
different mount namespace from the perf(1) utility.

-x::
--exec=PATH::
Specify path to the executable or shared library file for user
Expand Down Expand Up @@ -264,6 +269,10 @@ Add probes at malloc() function on libc

./perf probe -x /lib/libc.so.6 malloc or ./perf probe /lib/libc.so.6 malloc

Add a uprobe to a target process running in a different mount namespace

./perf probe --target-ns <target pid> -x /lib64/libc.so.6 malloc

SEE ALSO
--------
linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1]
2 changes: 1 addition & 1 deletion tools/perf/arch/powerpc/util/sym-handling.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
struct rb_node *tmp;
int i = 0;

map = get_target_map(pev->target, pev->uprobes);
map = get_target_map(pev->target, pev->nsi, pev->uprobes);
if (!map || map__load(map) < 0)
return;

Expand Down
43 changes: 39 additions & 4 deletions tools/perf/builtin-probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ static struct {
struct line_range line_range;
char *target;
struct strfilter *filter;
struct nsinfo *nsi;
} params;

/* Parse an event definition. Note that any error must die. */
Expand All @@ -80,6 +81,9 @@ static int parse_probe_event(const char *str)
params.target_used = true;
}

if (params.nsi)
pev->nsi = nsinfo__get(params.nsi);

/* Parse a perf-probe command into event */
ret = parse_perf_probe_command(str, pev);
pr_debug("%d arguments\n", pev->nargs);
Expand Down Expand Up @@ -189,7 +193,7 @@ static int opt_set_target(const struct option *opt, const char *str,

/* Expand given path to absolute path, except for modulename */
if (params.uprobes || strchr(str, '/')) {
tmp = realpath(str, NULL);
tmp = nsinfo__realpath(str, params.nsi);
if (!tmp) {
pr_warning("Failed to get the absolute path of %s: %m\n", str);
return ret;
Expand All @@ -208,6 +212,34 @@ static int opt_set_target(const struct option *opt, const char *str,
return ret;
}

static int opt_set_target_ns(const struct option *opt __maybe_unused,
const char *str, int unset __maybe_unused)
{
int ret = -ENOENT;
pid_t ns_pid;
struct nsinfo *nsip;

if (str) {
errno = 0;
ns_pid = (pid_t)strtol(str, NULL, 10);
if (errno != 0) {
ret = -errno;
pr_warning("Failed to parse %s as a pid: %s\n", str,
strerror(errno));
return ret;
}
nsip = nsinfo__new(ns_pid);
if (nsip && nsip->need_setns)
params.nsi = nsinfo__get(nsip);
nsinfo__put(nsip);

ret = 0;
}

return ret;
}


/* Command option callbacks */

#ifdef HAVE_DWARF_SUPPORT
Expand Down Expand Up @@ -299,6 +331,7 @@ static void cleanup_params(void)
line_range__clear(&params.line_range);
free(params.target);
strfilter__delete(params.filter);
nsinfo__put(params.nsi);
memset(&params, 0, sizeof(params));
}

Expand Down Expand Up @@ -554,6 +587,8 @@ __cmd_probe(int argc, const char **argv)
OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
"Look for files with symbols relative to this directory"),
OPT_CALLBACK(0, "target-ns", NULL, "pid",
"target pid for namespace contexts", opt_set_target_ns),
OPT_END()
};
int ret;
Expand Down Expand Up @@ -634,15 +669,15 @@ __cmd_probe(int argc, const char **argv)
pr_err_with_code(" Error: Failed to show event list.", ret);
return ret;
case 'F':
ret = show_available_funcs(params.target, params.filter,
params.uprobes);
ret = show_available_funcs(params.target, params.nsi,
params.filter, params.uprobes);
if (ret < 0)
pr_err_with_code(" Error: Failed to show functions.", ret);
return ret;
#ifdef HAVE_DWARF_SUPPORT
case 'L':
ret = show_line_range(&params.line_range, params.target,
params.uprobes);
params.nsi, params.uprobes);
if (ret < 0)
pr_err_with_code(" Error: Failed to show lines.", ret);
return ret;
Expand Down
13 changes: 13 additions & 0 deletions tools/perf/util/namespaces.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "event.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <sched.h>
#include <stdlib.h>
#include <stdio.h>
Expand Down Expand Up @@ -233,3 +234,15 @@ void nsinfo__mountns_exit(struct nscookie *nc)
nc->newns = -1;
}
}

char *nsinfo__realpath(const char *path, struct nsinfo *nsi)
{
char *rpath;
struct nscookie nsc;

nsinfo__mountns_enter(nsi, &nsc);
rpath = realpath(path, NULL);
nsinfo__mountns_exit(&nsc);

return rpath;
}
2 changes: 2 additions & 0 deletions tools/perf/util/namespaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ void nsinfo__put(struct nsinfo *nsi);
void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc);
void nsinfo__mountns_exit(struct nscookie *nc);

char *nsinfo__realpath(const char *path, struct nsinfo *nsi);

static inline void __nsinfo__zput(struct nsinfo **nsip)
{
if (nsip) {
Expand Down
Loading

0 comments on commit 544abd4

Please sign in to comment.