perf/core improvements and fixes
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling, way more to process in the next days, with the
patchkit for eBPF looking good, perf stat stuff from Jiri and some new hardware stuff from Andi.
- Arnaldo
The following changes since commit 75f80859b130a1cc84e59e71295ce2dd51fe1c81:
perf/x86/intel/pebs: Robustify PEBS buffer drain (2015-08-04 10:17:01 +0200)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo
for you to fetch changes up to f151f53aa4f54a647353e1935e4c6cef7f094dd4:
perf tools: Fix build errors with mipsel-linux-uclibc compiler (2015-08-05 16:56:16 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
New features:
- Deref sys_enter pointer args with contents from probe:vfs_getname, showing pathnames instead of pointers in many syscalls in 'perf trace' (Arnaldo Carvalho de Melo)
- Make 'perf trace' write to stderr by default, just like 'strace' (Milian Woff)
Infrastructure:
- color_vfprintf() fixes (Andi Kleen, Jiri Olsa)
- Allow enabling/disabling PERF_SAMPLE_TIME per event (Kan Liang)
- Fix build errors with mipsel-linux-uclibc compiler (Petri Gynther)
----------------------------------------------------------------
Andi Kleen (1):
perf tools: Do not include escape sequences in color_vfprintf return
Arnaldo Carvalho de Melo (6):
perf script: No tracepoints? Don't call libtraceevent.
perf trace: Do not show syscall tracepoint filter in the --no-syscalls case perf trace: Remember if the vfs_getname tracepoint/kprobe is in place perf trace: Use a constant for the syscall formatting buffer perf trace: Deref sys_enter pointer args with contents from probe:vfs_getname perf trace: Use vfs_getname syscall arg beautifier in more syscalls
Jiri Olsa (1):
perf tools: Remove trail argument to color vsprintf
Kan Liang (2):
perf tools: Per-event time support
perf tools: Refine parse/config callchain functions
Milian Wolff (1):
perf trace: Write to stderr by default
Petri Gynther (1):
perf tools: Fix build errors with mipsel-linux-uclibc compiler
tools/build/feature/test-glibc.c | 11 ++ tools/perf/Documentation/perf-record.txt | 4 +- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-script.c | 3 +- tools/perf/builtin-trace.c | 175 +++++++++++++++++++++++++++---- tools/perf/util/callchain.c | 14 +-- tools/perf/util/callchain.h | 2 +- tools/perf/util/cloexec.h | 2 +- tools/perf/util/color.c | 21 +--- tools/perf/util/color.h | 1 - tools/perf/util/evsel.c | 25 +++-- tools/perf/util/evsel.h | 2 + tools/perf/util/parse-events.c | 12 +++ tools/perf/util/parse-events.h | 1 + tools/perf/util/parse-events.l | 1 + tools/perf/util/pmu.c | 2 +- 16 files changed, 220 insertions(+), 58 deletions(-)
Arnaldo Carvalho de Melo
maintainerPATCH 1/12 perf script: No tracepoints? Don't call libtraceevent.
From: Arnaldo Carvalho de Melo <[email protected]>
The libtraceevent handler (session->tevent) is only initialized when there are tracepoints in a perf.data event list, so do not call pevent_set_function_resolve() in those cases, fixing a segfault.
Report-link: http://lkml.kernel.org/r/[email protected]
--- tools/perf/builtin-script.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/builtin-script.c +2 -1
@@ -1861,7 +1861,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)else symbol_conf.use_callchain = false; -if (pevent_set_function_resolver (session->tevent.pevent, +if (session->tevent.pevent && +pevent_set_function_resolver (session->tevent.pevent, machine__resolve_kernel_addr, &session->machines.host) <0 ) {pr_err ("%s: failed to set libtraceevent function resolver\n" , __func__);
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 2/12 perf trace: Do not show syscall tracepoint filter in the --no-syscalls case
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We were accessing trace->syscalls.events members even when that struct wasn't initialized, i.e. --no-syscalls was specified on the command line, fix it to show that, still in debug mode, when we have an event qualifier list, i.e. when we actually are doing subset syscall tracing.
--- tools/perf/builtin-trace.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
tools/perf/builtin-trace.c +3 -2
@@ -2394,9 +2394,10 @@ static int trace__run(struct trace *trace, int argc, const char **argv) err =trace__set_ev_qualifier_filter (trace);if (err <0 ) goto out_errno; - } -pr_debug ("%s\n" , trace->syscalls.events.sys_exit->filter); +pr_debug ("event qualifier tracepoint filter: %s\n" , + trace->syscalls.events.sys_exit->filter); + } err =perf_evlist__apply_filters (evlist, &evsel);if (err <0 )
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 3/12 perf trace: Remember if the vfs_getname tracepoint/kprobe is in place
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
So that we can later decide if we will store where to expand the pathname once we are handling vfs_getname or if we should instead just go on and straight away print the pointer.
--- tools/perf/builtin-trace.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
tools/perf/builtin-trace.c +6 -4
@@ -1312,6 +1312,7 @@ struct trace {bool show_tool_stats;bool trace_syscalls;bool force; +bool vfs_getname;int trace_pgfaults; };
@@ -2188,19 +2189,20 @@ static int trace__record(struct trace *trace, int argc, const char **argv)static size_t trace__fprintf_thread_summary (struct trace *trace,FILE *fp); -static void perf_evlist__add_vfs_getname (struct perf_evlist *evlist) +static bool perf_evlist__add_vfs_getname (struct perf_evlist *evlist) {struct perf_evsel *evsel =perf_evsel__newtp ("probe" ,"vfs_getname" );if (evsel ==NULL ) -return ; +return false;if (perf_evsel__field (evsel,"pathname" ) ==NULL ) {perf_evsel__delete (evsel); -return ; +return false; } evsel->handler = trace__vfs_getname;perf_evlist__add (evlist, evsel); +return true; } static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
@@ -2330,7 +2332,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) goto out_error_raw_syscalls;if (trace->trace_syscalls) -perf_evlist__add_vfs_getname (evlist); + trace->vfs_getname =perf_evlist__add_vfs_getname (evlist);if ((trace->trace_pgfaults &TRACE_PFMAJ ) &&perf_evlist__add_pgfault (evlist,PERF_COUNT_SW_PAGE_FAULTS_MAJ )) {
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 4/12 perf trace: Use a constant for the syscall formatting buffer
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We were using it as a magic number, 1024, fix that.
Eventually we need to stop doing it per line, and do it per arg, traversing the args at output time, to avoid the memmove() calls that will be used in the next cset to replace pointers present at raw_syscalls:sys_enter time with its contents that appear at probe:vfs_getname time, before raw_syscalls:sys_exit time.
--- tools/perf/builtin-trace.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
tools/perf/builtin-trace.c +5 -3
@@ -1262,6 +1262,8 @@ fail:#define TRACE_PFMAJ (1 << 0)#define TRACE_PFMIN (1 << 1) +static const size_t trace__entry_str_size =2048 ; +struct trace {struct perf_tool tool;struct {
@@ -1822,7 +1824,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, args =perf_evsel__sc_tp_ptr (evsel, args, sample);if (ttrace->entry_str ==NULL ) { - ttrace->entry_str =malloc (1024 ); + ttrace->entry_str =malloc (trace__entry_str_size);if (!ttrace->entry_str) goto out_put; }
@@ -1832,9 +1834,9 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, ttrace->entry_time = sample->time; msg = ttrace->entry_str; - printed +=scnprintf (msg + printed,1024 - printed,"%s(" , sc->name); + printed +=scnprintf (msg + printed, trace__entry_str_size - printed,"%s(" , sc->name); - printed +=syscall__scnprintf_args (sc, msg + printed,1024 - printed, + printed +=syscall__scnprintf_args (sc, msg + printed, trace__entry_str_size - printed, args, trace, thread);if (sc->is_exit) {
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 5/12 perf trace: Deref sys_enter pointer args with contents from probe:vfs_getname
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
To work like strace and dereference syscall pointer args we need to insert probes (or tracepoints) right after we copy those bytes from userspace.
Since we're formatting the syscall args at raw_syscalls:sys_enter time, we need to have a formatter that just stores the position where, later, when we get the probe:vfs_getname, we can insert the pointer contents.
Now, if a probe:vfs_getname with this format is in place:
# perf probe -l probe:vfs_getname (on getname_flags:72@/home/git/linux/fs/namei.c with pathname)
That was, in this case, put in place with:
# perf probe 'vfs_getname=getname_flags:72 pathname=filename:string' Added new event: probe:vfs_getname (on getname_flags:72 with pathname=filename:string)
You can now use it in all perf tools, such as:
perf record -e probe:vfs_getname -aR sleep 1
#
Then 'perf trace' will notice that and do the pointer -> contents expansion:
# trace -e open touch /tmp/bla 0.165 (0.010 ms): touch/17752 open(filename: /etc/ld.so.cache, flags: CLOEXEC) = 3 0.195 (0.011 ms): touch/17752 open(filename: /lib64/libc.so.6, flags: CLOEXEC) = 3 0.512 (0.012 ms): touch/17752 open(filename: /usr/lib/locale/locale-archive, flags: CLOEXEC) = 3 0.582 (0.012 ms): touch/17752 open(filename: /tmp/bla, flags: CREAT|NOCTTY|NONBLOCK|WRONLY, mode: 438) = 3 #
Roughly equivalent to strace's output:
# strace -rT -e open touch /tmp/bla
0.000000 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 <0.000039>
0.000317 open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000102>
0.001461 open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 <0.000072>
0.000405 open("/tmp/bla", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = 3 <0.000055>
0.000641 +++ exited with 0 +++
#Now we need to either look for at all syscalls that are marked as pointers and have some well known names ("filename", "pathname", etc) and set the arg formatter to the one used for the "open" syscall in this patch.
This implementation works for syscalls with just a string being copied from userspace, for matching syscalls with more than one string being copied via the same probe/trace point (vfs_getname) we need to extend the vfs_getname probe spec to include the pointer too, but there are some problems with that in 'perf probe' or the kernel kprobes code, need to investigate before considering supporting multiple strings per syscall.
--- tools/perf/builtin-trace.c | 76 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-)
tools/perf/builtin-trace.c +75 -1
@@ -744,6 +744,11 @@ static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,#define SCA_ACCMODE syscall_arg__scnprintf_access_mode +static size_t syscall_arg__scnprintf_filename (char *bf,size_t size, +struct syscall_arg *arg); + +#define SCA_FILENAME syscall_arg__scnprintf_filename +static size_t syscall_arg__scnprintf_open_flags (char *bf,size_t size,struct syscall_arg *arg) {
@@ -1088,7 +1093,8 @@ static struct syscall_fmt { { .name = "newfstatat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, { .name = "open", .errmsg = true, - .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, }, + .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ + [1] = SCA_OPEN_FLAGS, /* flags */ }, }, { .name = "open_by_handle_at", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ [2] = SCA_OPEN_FLAGS, /* flags */ }, },
@@ -1208,6 +1214,11 @@ static size_t fprintf_duration(unsigned long t, FILE *fp)return printed +fprintf (fp,"): " ); } +/** +* filename.ptr: The filename char pointer that will be vfs_getname'd +* filename.entry_str_pos: Where to insert the string translated from +* filename.ptr by the vfs_getname tracepoint/kprobe. +*/ struct thread_trace {u64 entry_time;u64 exit_time;
@@ -1216,6 +1227,10 @@ struct thread_trace {unsigned long pfmaj, pfmin;char *entry_str;double runtime_ms; +struct { +unsigned long ptr; +int entry_str_pos; + } filename;struct {int max;char **table;
@@ -1418,6 +1433,27 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,return printed; } +static void thread__set_filename_pos (struct thread *thread,const char *bf, +unsigned long ptr) +{ +struct thread_trace *ttrace =thread__priv (thread); + + ttrace->filename.ptr = ptr; + ttrace->filename.entry_str_pos = bf - ttrace->entry_str; +} + +static size_t syscall_arg__scnprintf_filename (char *bf,size_t size, +struct syscall_arg *arg) +{ +unsigned long ptr = arg->val; + +if (!arg->trace->vfs_getname) +return scnprintf (bf, size,"%#x" , ptr); + +thread__set_filename_pos (arg->thread, bf, ptr); +return 0 ; +} +static bool trace__filter_duration (struct trace *trace,double t) {return t < (trace->duration_filter *NSEC_PER_MSEC );
@@ -1938,7 +1974,45 @@ static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,union perf_event *event__maybe_unused , struct perf_sample *sample) { + struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); +struct thread_trace *ttrace; +size_t filename_len, entry_str_len, to_move; +ssize_t remaining_space; +char *pos; +const char *filename; + trace->last_vfs_getname =perf_evsel__rawptr (evsel, sample,"pathname" ); + +if (!thread) + goto out; + + ttrace =thread__priv (thread); +if (!ttrace) + goto out; + +if (!ttrace->filename.ptr) + goto out; + + entry_str_len =strlen (ttrace->entry_str); + remaining_space = trace__entry_str_size - entry_str_len -1 ;/* \0 */ +if (remaining_space <=0 ) + goto out; + + filename = trace->last_vfs_getname; + filename_len =strlen (filename); +if (filename_len > (size_t )remaining_space) { + filename += filename_len - remaining_space; + filename_len = remaining_space; + } + + to_move = entry_str_len - ttrace->filename.entry_str_pos +1 ;/* \0 */ + pos = ttrace->entry_str + ttrace->filename.entry_str_pos; +memmove (pos + filename_len, pos, to_move); +memcpy (pos, filename, filename_len); + + ttrace->filename.ptr =0 ; + ttrace->filename.entry_str_pos =0 ; +out:return 0 ; }
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 6/12 perf trace: Use vfs_getname syscall arg beautifier in more syscalls
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Those were covered and tested in this cset:
access, chdir, chmod, chown, chroot, creat, getxattr, inotify_add_watch, lchown, lgetxattr, listxattr, lsetxattr, mkdir, mkdirat, mknod, rmdir, faccessat, newfstatat, openat, readlink, readlinkat, removexattr, setxattr, statfs, swapon, swapoff, truncate, unlinkat, utime, utimes, utimensat.
E.g.:
# trace -e statfs,access,mkdir mkdir /tmp/bla 0.285 (0.020 ms): mkdir/2799 access(filename: /etc/ld.so.preload, mode: R ) = -1 ENOENT No such file or directory 1.070 (0.032 ms): mkdir/2799 statfs(pathname: /sys/fs/selinux, buf: 0x7ffeafbdc930) = 0 1.087 (0.013 ms): mkdir/2799 statfs(pathname: /sys/fs/selinux, buf: 0x7ffeafbdc820) = 0 1.189 (0.014 ms): mkdir/2799 access(filename: /etc/selinux/config ) = 0 1.905 (0.610 ms): mkdir/2799 mkdir(pathname: /tmp/bla, mode: 511 ) = 0 #
and an empty message aborts the commit.
--- tools/perf/builtin-trace.c | 74 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 9 deletions(-)
tools/perf/builtin-trace.c +65 -9
@@ -976,14 +976,23 @@ static struct syscall_fmt {bool hexret; } syscall_fmts[] = { { .name = "access", .errmsg = true, - .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, }, + .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ + [1] = SCA_ACCMODE, /* mode */ }, }, { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, { .name = "brk", .hexret = true, .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, + { .name = "chdir", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, + { .name = "chmod", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, + { .name = "chroot", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, { .name = "close", .errmsg = true, .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, { .name = "connect", .errmsg = true, }, + { .name = "creat", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, { .name = "dup", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "dup2", .errmsg = true,
@@ -994,7 +1003,8 @@ static struct syscall_fmt { { .name = "eventfd2", .errmsg = true, .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, { .name = "faccessat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ + [1] = SCA_FILENAME, /* filename */ }, }, { .name = "fadvise64", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "fallocate", .errmsg = true,
@@ -1008,7 +1018,8 @@ static struct syscall_fmt { { .name = "fchown", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "fchownat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ + [1] = SCA_FILENAME, /* filename */ }, }, { .name = "fcntl", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ [1] = SCA_STRARRAY, /* cmd */ },
@@ -1023,7 +1034,8 @@ static struct syscall_fmt { { .name = "fstat", .errmsg = true, .alias = "newfstat", .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "fstatat", .errmsg = true, .alias = "newfstatat", - .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ + [1] = SCA_FILENAME, /* filename */ }, }, { .name = "fstatfs", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "fsync", .errmsg = true,
@@ -1040,6 +1052,10 @@ static struct syscall_fmt { .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, + { .name = "getxattr", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, + { .name = "inotify_add_watch", .errmsg = true, + .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, }, { .name = "ioctl", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */#if defined(__i386__) || defined(__x86_64__)
@@ -1054,18 +1070,33 @@ static struct syscall_fmt {#endif { .name = "kill", .errmsg = true, .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, + { .name = "lchown", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, + { .name = "lgetxattr", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, { .name = "linkat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, + { .name = "listxattr", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, { .name = "lseek", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ [2] = SCA_STRARRAY, /* whence */ }, .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, + { .name = "lsetxattr", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, { .name = "lstat", .errmsg = true, .alias = "newlstat", }, + { .name = "lsxattr", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, { .name = "madvise", .errmsg = true, .arg_scnprintf = { [0] = SCA_HEX, /* start */ [2] = SCA_MADV_BHV, /* behavior */ }, }, + { .name = "mkdir", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, { .name = "mkdirat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ + [1] = SCA_FILENAME, /* pathname */ }, }, + { .name = "mknod", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, { .name = "mknodat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, { .name = "mlock", .errmsg = true,
@@ -1091,7 +1122,8 @@ static struct syscall_fmt { { .name = "name_to_handle_at", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, { .name = "newfstatat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ + [1] = SCA_FILENAME, /* filename */ }, }, { .name = "open", .errmsg = true, .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ [1] = SCA_OPEN_FLAGS, /* flags */ }, },
@@ -1100,6 +1132,7 @@ static struct syscall_fmt { [2] = SCA_OPEN_FLAGS, /* flags */ }, }, { .name = "openat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ + [1] = SCA_FILENAME, /* filename */ [2] = SCA_OPEN_FLAGS, /* flags */ }, }, { .name = "perf_event_open", .errmsg = true, .arg_scnprintf = { [1] = SCA_INT, /* pid */
@@ -1121,8 +1154,11 @@ static struct syscall_fmt { .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "read", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, + { .name = "readlink", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, }, { .name = "readlinkat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ + [1] = SCA_FILENAME, /* pathname */ }, }, { .name = "readv", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "recvfrom", .errmsg = true,
@@ -1131,8 +1167,12 @@ static struct syscall_fmt { .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, { .name = "recvmsg", .errmsg = true, .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, + { .name = "removexattr", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, { .name = "renameat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, + { .name = "rmdir", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, { .name = "rt_sigaction", .errmsg = true, .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
@@ -1149,6 +1189,8 @@ static struct syscall_fmt { .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, + { .name = "setxattr", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, { .name = "shutdown", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "socket", .errmsg = true,
@@ -1160,17 +1202,31 @@ static struct syscall_fmt { [1] = SCA_SK_TYPE, /* type */ }, .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, { .name = "stat", .errmsg = true, .alias = "newstat", }, + { .name = "statfs", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, + { .name = "swapoff", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, + { .name = "swapon", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, { .name = "symlinkat", .errmsg = true, .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, { .name = "tgkill", .errmsg = true, .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, { .name = "tkill", .errmsg = true, .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, + { .name = "truncate", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, }, { .name = "uname", .errmsg = true, .alias = "newuname", }, { .name = "unlinkat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ + [1] = SCA_FILENAME, /* pathname */ }, }, + { .name = "utime", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, { .name = "utimensat", .errmsg = true, - .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, }, + .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ + [1] = SCA_FILENAME, /* filename */ }, }, + { .name = "utimes", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, { .name = "write", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, { .name = "writev", .errmsg = true,
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 7/12 perf tools: Per-event time support
In reply to Arnaldo Carvalho de MeloFrom: Kan Liang <[email protected]>
This patchkit adds the ability to turn off time stamps per event.
One usaful case for partial time is to work with per-event callgraph to enable "PEBS threshold > 1" (https://lkml.org/lkml/2015/5/10/196), which can significantly reduce the sampling overhead.
The event samples with time stamps off will not be ordered.
--- tools/perf/Documentation/perf-record.txt | 4 +++- tools/perf/util/evsel.c | 14 +++++++++++--- tools/perf/util/evsel.h | 2 ++ tools/perf/util/parse-events.c | 12 ++++++++++++ tools/perf/util/parse-events.h | 1 + tools/perf/util/parse-events.l | 1 + tools/perf/util/pmu.c | 2 +- 7 files changed, 31 insertions(+), 5 deletions(-)
tools/perf/Documentation/perf-record.txt +3 -1
@@ -49,7 +49,9 @@ OPTIONS These params can be used to overload default config values per event. Here is a list of the params. - 'period': Set event sampling period - + - 'time': Disable/enable time stamping. Acceptable values are 1 for + enabling time stamping. 0 for disabling time stamping. + The default is 1. Note: If user explicitly sets options which conflict with the params, the value set by the params will be overridden.
tools/perf/util/evsel.c +11 -3
@@ -587,15 +587,23 @@ perf_evsel__config_callgraph(struct perf_evsel *evsel, } } -static void apply_config_terms (struct perf_event_attr *attr__maybe_unused , -struct list_head *config_terms) +static void apply_config_terms (struct perf_evsel *evsel) {struct perf_evsel_config_term *term; +struct list_head *config_terms = &evsel->config_terms; +struct perf_event_attr *attr = &evsel->attr;list_for_each_entry (term, config_terms, list) {switch (term->type) {case PERF_EVSEL__CONFIG_TERM_PERIOD : attr->sample_period = term->val.period; +break ; +case PERF_EVSEL__CONFIG_TERM_TIME : +if (term->val.time) +perf_evsel__set_sample_bit (evsel,TIME ); +else +perf_evsel__reset_sample_bit (evsel,TIME ); +break ;default :break ; }
@@ -798,7 +806,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)* Apply event specific term settings, * it overloads any global configuration. */ -apply_config_terms (attr, &evsel->config_terms); +apply_config_terms (evsel); }static int perf_evsel__alloc_fd (struct perf_evsel *evsel,int ncpus,int nthreads)
tools/perf/util/evsel.h +2 -0
@@ -39,6 +39,7 @@ struct cgroup_sel;*/ enum {PERF_EVSEL__CONFIG_TERM_PERIOD , +PERF_EVSEL__CONFIG_TERM_TIME ,PERF_EVSEL__CONFIG_TERM_MAX , };
@@ -47,6 +48,7 @@ struct perf_evsel_config_term {int type;union {u64 period; +bool time; } val; };
tools/perf/util/parse-events.c +12 -0
@@ -603,6 +603,14 @@ do { \* attr->branch_sample_type = term->val.num; */ break ; +case PARSE_EVENTS__TERM_TYPE_TIME : +CHECK_TYPE_VAL (NUM ); +if (term->val.num >1 ) { + err->str =strdup ("expected 0 or 1" ); + err->idx = term->err_val; +return -EINVAL ; + } +break ;case PARSE_EVENTS__TERM_TYPE_NAME :CHECK_TYPE_VAL (STR );break ;
@@ -650,6 +658,10 @@ do { \switch (term->type_term) {case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD :ADD_CONFIG_TERM (PERIOD , period, term->val.num); +break ; +case PARSE_EVENTS__TERM_TYPE_TIME : +ADD_CONFIG_TERM (TIME , time, term->val.num); +break ;default :break ; }
tools/perf/util/parse-events.h +1 -0
@@ -63,6 +63,7 @@ enum {PARSE_EVENTS__TERM_TYPE_NAME ,PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD ,PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE , + PARSE_EVENTS__TERM_TYPE_TIME, }; struct parse_events_term {
tools/perf/util/parse-events.l +1 -0
@@ -183,6 +183,7 @@ config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); } name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); } period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } +time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } , { return ','; } "/" { BEGIN(INITIAL); return '/'; } {name_minus} { return str(yyscanner, PE_NAME); }
tools/perf/util/pmu.c +1 -1
@@ -607,7 +607,7 @@ static char *formats_error_string(struct list_head *formats) {struct perf_pmu_format *format;char *err, *str; -static const char *static_terms ="config,config1,config2,name,period,branch_type\n" ; +static const char *static_terms ="config,config1,config2,name,period,branch_type,time\n" ;unsigned i =0 ;if (!asprintf (&str,"valid terms:" ))
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 8/12 perf tools: Refine parse/config callchain functions
In reply to Arnaldo Carvalho de MeloFrom: Kan Liang <[email protected]>
Pass global callchain_param into parse_callchain_record_opt and perf_evsel__config_callgraph as parameter. So we can reuse these functions to parse/config local param for callchain.
--- tools/perf/builtin-record.c | 2 +- tools/perf/util/callchain.c | 14 +++++++------- tools/perf/util/callchain.h | 2 +- tools/perf/util/evsel.c | 11 ++++++----- 4 files changed, 15 insertions(+), 14 deletions(-)
tools/perf/builtin-record.c +1 -1
@@ -779,7 +779,7 @@ int record_parse_callchain_opt(const struct option *opt,return 0 ; } - ret =parse_callchain_record_opt (arg); + ret =parse_callchain_record_opt (arg, &callchain_param);if (!ret)callchain_debug ();
tools/perf/util/callchain.c +7 -7
@@ -53,7 +53,7 @@ static int get_stack_size(const char *str, unsigned long *_size) }#endif /* HAVE_DWARF_UNWIND_SUPPORT */ -int parse_callchain_record_opt (const char *arg) +int parse_callchain_record_opt (const char *arg,struct callchain_param *param) {char *tok, *name, *saveptr =NULL ;char *buf;
@@ -73,7 +73,7 @@ int parse_callchain_record_opt(const char *arg)/* Framepointer style */ if (!strncmp (name,"fp" ,sizeof ("fp" ))) {if (!strtok_r (NULL ,"," , &saveptr)) { - callchain_param.record_mode =CALLCHAIN_FP ; + param->record_mode =CALLCHAIN_FP ; ret =0 ; }else pr_err("callchain: No more arguments "
@@ -86,20 +86,20 @@ int parse_callchain_record_opt(const char *arg)const unsigned long default_stack_dump_size =8192 ; ret =0 ; - callchain_param.record_mode =CALLCHAIN_DWARF ; - callchain_param.dump_size = default_stack_dump_size; + param->record_mode =CALLCHAIN_DWARF ; + param->dump_size = default_stack_dump_size; tok =strtok_r (NULL ,"," , &saveptr);if (tok) {unsigned long size =0 ; ret =get_stack_size (tok, &size); - callchain_param.dump_size = size; + param->dump_size = size; }#endif /* HAVE_DWARF_UNWIND_SUPPORT */ }else if (!strncmp (name,"lbr" ,sizeof ("lbr" ))) {if (!strtok_r (NULL ,"," , &saveptr)) { - callchain_param.record_mode =CALLCHAIN_LBR ; + param->record_mode =CALLCHAIN_LBR ; ret =0 ; }else pr_err("callchain: No more arguments "
@@ -219,7 +219,7 @@ int perf_callchain_config(const char *var, const char *value) var +=sizeof ("call-graph." ) -1 ;if (!strcmp (var,"record-mode" )) -return parse_callchain_record_opt (value); +return parse_callchain_record_opt (value, &callchain_param);#ifdef HAVE_DWARF_UNWIND_SUPPORT if (!strcmp (var,"dump-size" )) {unsigned long size =0 ;
tools/perf/util/callchain.h +1 -1
@@ -177,7 +177,7 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * bool hide_unresolved);extern const char record_callchain_help[]; -int parse_callchain_record_opt (const char *arg); +int parse_callchain_record_opt (const char *arg,struct callchain_param *param);int parse_callchain_report_opt (const char *arg);int perf_callchain_config (const char *var,const char *value);
tools/perf/util/evsel.c +6 -5
@@ -545,14 +545,15 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)static void perf_evsel__config_callgraph (struct perf_evsel *evsel, -struct record_opts *opts) +struct record_opts *opts, +struct callchain_param *param) {bool function =perf_evsel__is_function_event (evsel);struct perf_event_attr *attr = &evsel->attr;perf_evsel__set_sample_bit (evsel,CALLCHAIN ); -if (callchain_param.record_mode ==CALLCHAIN_LBR ) { +if (param->record_mode ==CALLCHAIN_LBR ) {if (!opts->branch_stack) {if (attr->exclude_user) { pr_warning("LBR callstack option is only available "
@@ -568,12 +569,12 @@ perf_evsel__config_callgraph(struct perf_evsel *evsel, "Falling back to framepointers.\n"); } -if (callchain_param.record_mode ==CALLCHAIN_DWARF ) { +if (param->record_mode ==CALLCHAIN_DWARF ) {if (!function) {perf_evsel__set_sample_bit (evsel,REGS_USER );perf_evsel__set_sample_bit (evsel,STACK_USER ); attr->sample_regs_user =PERF_REGS_MASK ; - attr->sample_stack_user = callchain_param.dump_size; + attr->sample_stack_user = param->dump_size; attr->exclude_callchain_user =1 ; }else { pr_info("Cannot use DWARF unwind for function trace event,"
@@ -714,7 +715,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) evsel->attr.exclude_callchain_user =1 ;if (callchain_param.enabled && !evsel->no_aux_samples) -perf_evsel__config_callgraph (evsel, opts); +perf_evsel__config_callgraph (evsel, opts, &callchain_param);if (opts->sample_intr_regs) { attr->sample_regs_intr =PERF_REGS_MASK ;
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 9/12 perf tools: Remove trail argument to color vsprintf
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Seems like it's always '\n' through color_fprintf_ln, which is not used at all, removing.. ;-)
--- tools/perf/util/color.c | 16 ++-------------- tools/perf/util/color.h | 1 - 2 files changed, 2 insertions(+), 15 deletions(-)
tools/perf/util/color.c +2 -14
@@ -68,7 +68,7 @@ static int __color_vsnprintf(char *bf, size_t size, const char *color, }static int __color_vfprintf (FILE *fp,const char *color,const char *fmt, -va_list args,const char *trail) +va_list args) {int r =0 ;
@@ -87,8 +87,6 @@ static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, r +=vfprintf (fp, fmt, args);if (perf_use_color_default && *color) r +=fprintf (fp,"%s" ,PERF_COLOR_RESET ); -if (trail) - r +=fprintf (fp,"%s" , trail);return r; }
@@ -100,7 +98,7 @@ int color_vsnprintf(char *bf, size_t size, const char *color,int color_vfprintf (FILE *fp,const char *color,const char *fmt,va_list args) { -return __color_vfprintf (fp, color, fmt, args,NULL ); +return __color_vfprintf (fp, color, fmt, args); } int color_snprintf(char *bf, size_t size, const char *color,
@@ -126,16 +124,6 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)return r; } -int color_fprintf_ln (FILE *fp,const char *color,const char *fmt, ...) -{ -va_list args; -int r; -va_start (args, fmt); - r =__color_vfprintf (fp, color, fmt, args,"\n" ); -va_end (args); -return r; -} -/* * This function splits the buffer by newlines and colors the lines individually. *
tools/perf/util/color.h +0 -1
@@ -35,7 +35,6 @@ int color_vsnprintf(char *bf, size_t size, const char *color,int color_vfprintf (FILE *fp,const char *color,const char *fmt,va_list args);int color_fprintf (FILE *fp,const char *color,const char *fmt, ...);int color_snprintf (char *bf,size_t size,const char *color,const char *fmt, ...); -int color_fprintf_ln (FILE *fp,const char *color,const char *fmt, ...);int color_fwrite_lines (FILE *fp,const char *color,size_t count,const char *buf);int value_color_snprintf (char *bf,size_t size,const char *fmt,double value);int percent_color_snprintf (char *bf,size_t size,const char *fmt, ...);
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 10/12 perf tools: Do not include escape sequences in color_vfprintf return
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
color_vprintf was including the length of the invisible escape sequences in its return argument. Don't include them to make the return value usable for indentation calculations.
v2: Add comment, rebase
--- tools/perf/util/color.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
tools/perf/util/color.c +3 -2
@@ -67,6 +67,7 @@ static int __color_vsnprintf(char *bf, size_t size, const char *color,return r; } +/* Colors are not included in return value */ static int __color_vfprintf (FILE *fp,const char *color,const char *fmt,va_list args) {
@@ -83,10 +84,10 @@ static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, }if (perf_use_color_default && *color) - r +=fprintf (fp,"%s" , color); +fprintf (fp,"%s" , color); r +=vfprintf (fp, fmt, args);if (perf_use_color_default && *color) - r +=fprintf (fp,"%s" ,PERF_COLOR_RESET ); +fprintf (fp,"%s" ,PERF_COLOR_RESET );return r; }
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 11/12 perf trace: Write to stderr by default
In reply to Arnaldo Carvalho de MeloFrom: Milian Wolff <[email protected]>
Without this patch, it is cumbersome to read the trace output but ignoring the normal, potentially verbose, output of the debuggee. One common example is doing something like the following:
perf trace -s find /tmp > /dev/null
Without this patch, the trace summary will be lost. Now, it will still be printed at the end. This behavior is also applied by strace.
--- tools/perf/builtin-trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/builtin-trace.c +1 -1
@@ -2965,7 +2965,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) .mmap_pages = UINT_MAX, .proc_map_timeout = 500, }, - .output = stdout, + .output = stderr, .show_comm = true, .trace_syscalls = true, };
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 12/12 perf tools: Fix build errors with mipsel-linux-uclibc compiler
In reply to Arnaldo Carvalho de MeloFrom: Petri Gynther <[email protected]>
linux/tools$ make ARCH=mips CROSS_COMPILE=mipsel-linux- perf
...
config/Makefile:256: *** No gnu/libc-version.h found, please install glibc-dev[el]. Stop.
make[1]: *** [all] Error 2
make: *** [perf] Error 2
...
In file included from builtin-sched.c:13:0:util/cloexec.h:8:12: error: redundant redeclaration of ‘sched_getcpu’
[-Werror=redundant-decls]
extern int sched_getcpu(void) __THROW;
mipsel-buildroot-linux-uclibc/sysroot/usr/include/bits/sched.h:88:12:
note: previous declaration of ‘sched_getcpu’ was here extern int sched_getcpu (void) __THROW;
uclibc info:sysroot/usr/include/bits/uClibc_config.h__UCLIBC_MAJOR__ 0__UCLIBC_MINOR__ 9__UCLIBC_SUBLEVEL__ 33
sysroot/usr/include/features.h__UCLIBC__ 1__GLIBC__ 2__GLIBC_MINOR__ 2
--- tools/build/feature/test-glibc.c | 11 +++++++++++ tools/perf/util/cloexec.h | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-)
tools/build/feature/test-glibc.c +11 -0
@@ -1,8 +1,19 @@ +#include <stdlib.h> + +#if !defined(__UCLIBC__)#include <gnu/libc-version.h> +#else +#define XSTR (s) STR(s) +#define STR (s) #s +#endif int main (void ) { +#if !defined(__UCLIBC__)const char *version =gnu_get_libc_version (); +#else + const char *version = XSTR(__GLIBC__) "." XSTR(__GLIBC_MINOR__); +#endif return (long )version; }
tools/perf/util/cloexec.h +1 -1
@@ -4,7 +4,7 @@unsigned long perf_event_open_cloexec_flag (void );#ifdef __GLIBC_PREREQ -#if !__GLIBC_PREREQ (2 ,6 ) +#if !__GLIBC_PREREQ (2 ,6 ) && !defined(__UCLIBC__) extern int sched_getcpu(void) __THROW;#endif #endif
Signature · 1 line
2.1.0