| From b6fe8f1d88450b44fe8e9553fb107ec9a92a8000 Mon Sep 17 00:00:00 2001 |
| From: Arnaldo Carvalho de Melo <acme@redhat.com> |
| Date: Tue, 29 Jan 2019 15:12:34 +0100 |
| Subject: perf trace: Support multiple "vfs_getname" probes |
| |
| [ Upstream commit 6ab3bc240ade47a0f52bc16d97edd9accbe0024e ] |
| |
| With a suitably defined "probe:vfs_getname" probe, 'perf trace' can |
| "beautify" its output, so syscalls like open() or openat() can print the |
| "filename" argument instead of just its hex address, like: |
| |
| $ perf trace -e open -- touch /dev/null |
| [...] |
| 0.590 ( 0.014 ms): touch/18063 open(filename: /dev/null, flags: CREAT|NOCTTY|NONBLOCK|WRONLY, mode: IRUGO|IWUGO) = 3 |
| [...] |
| |
| The output without such beautifier looks like: |
| |
| 0.529 ( 0.011 ms): touch/18075 open(filename: 0xc78cf288, flags: CREAT|NOCTTY|NONBLOCK|WRONLY, mode: IRUGO|IWUGO) = 3 |
| |
| However, when the vfs_getname probe expands to multiple probes and it is |
| not the first one that is hit, the beautifier fails, as following: |
| |
| 0.326 ( 0.010 ms): touch/18072 open(filename: , flags: CREAT|NOCTTY|NONBLOCK|WRONLY, mode: IRUGO|IWUGO) = 3 |
| |
| Fix it by hooking into all the expanded probes (inlines), now, for instance: |
| |
| [root@quaco ~]# perf probe -l |
| probe:vfs_getname (on getname_flags:73@fs/namei.c with pathname) |
| probe:vfs_getname_1 (on getname_flags:73@fs/namei.c with pathname) |
| [root@quaco ~]# perf trace -e open* sleep 1 |
| 0.010 ( 0.005 ms): sleep/5588 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: RDONLY|CLOEXEC) = 3 |
| 0.029 ( 0.006 ms): sleep/5588 openat(dfd: CWD, filename: /lib64/libc.so.6, flags: RDONLY|CLOEXEC) = 3 |
| 0.194 ( 0.008 ms): sleep/5588 openat(dfd: CWD, filename: /usr/lib/locale/locale-archive, flags: RDONLY|CLOEXEC) = 3 |
| [root@quaco ~]# |
| |
| Works, further verified with: |
| |
| [root@quaco ~]# perf test vfs |
| 65: Use vfs_getname probe to get syscall args filenames : Ok |
| 66: Add vfs_getname probe to get syscall args filenames : Ok |
| 67: Check open filename arg using perf trace + vfs_getname: Ok |
| [root@quaco ~]# |
| |
| Reported-by: Michael Petlan <mpetlan@redhat.com> |
| Tested-by: Michael Petlan <mpetlan@redhat.com> |
| Cc: Adrian Hunter <adrian.hunter@intel.com> |
| Cc: Jiri Olsa <jolsa@redhat.com> |
| Cc: Namhyung Kim <namhyung@kernel.org> |
| Link: https://lkml.kernel.org/n/tip-mv8kolk17xla1smvmp3qabv1@git.kernel.org |
| Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| tools/perf/builtin-trace.c | 25 ++++++++++++++++++------- |
| 1 file changed, 18 insertions(+), 7 deletions(-) |
| |
| diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c |
| index 22ab8e67c760..3f43aedb384d 100644 |
| --- a/tools/perf/builtin-trace.c |
| +++ b/tools/perf/builtin-trace.c |
| @@ -2263,19 +2263,30 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); |
| |
| static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist) |
| { |
| - struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname"); |
| + bool found = false; |
| + struct perf_evsel *evsel, *tmp; |
| + struct parse_events_error err = { .idx = 0, }; |
| + int ret = parse_events(evlist, "probe:vfs_getname*", &err); |
| |
| - if (IS_ERR(evsel)) |
| + if (ret) |
| return false; |
| |
| - if (perf_evsel__field(evsel, "pathname") == NULL) { |
| + evlist__for_each_entry_safe(evlist, evsel, tmp) { |
| + if (!strstarts(perf_evsel__name(evsel), "probe:vfs_getname")) |
| + continue; |
| + |
| + if (perf_evsel__field(evsel, "pathname")) { |
| + evsel->handler = trace__vfs_getname; |
| + found = true; |
| + continue; |
| + } |
| + |
| + list_del_init(&evsel->node); |
| + evsel->evlist = NULL; |
| perf_evsel__delete(evsel); |
| - return false; |
| } |
| |
| - evsel->handler = trace__vfs_getname; |
| - perf_evlist__add(evlist, evsel); |
| - return true; |
| + return found; |
| } |
| |
| static struct perf_evsel *perf_evsel__new_pgfault(u64 config) |
| -- |
| 2.19.1 |
| |