perf/core improvements and fixes
Subsystems (2)
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit d2d61ed55f8375a10ff606e83e2196880a775fb4:
Merge branch 'perf/rbtree_copy' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent (2015-07-06 09:24:41 +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 ab85785aa13c36440a91a8e9f7616357de411a1f:
tools lib api debugfs: Check for tracefs when reporting errors (2015-07-06 12:22:14 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
User visible:
- Take tracefs into account when reporting errors about accessing tracepoint information in tools like 'perf trace' (Arnaldo Carvalho de Melo)
- Let user have timestamps with per-thread recording in 'perf record' (Adrian Hunter)
Infrastructure:
- Introduce series of functions to build event filters so that we can set them in just one ioctl call, useful to set up common_pid, raw_syscalls:sys_{enter,exit}'s "id" filters to use with 'perf trace' (Arnaldo Carvalho de Melo)
- Delete an unnecessary check before calling strfilter__delete() (Markus Elfring)
----------------------------------------------------------------
Adrian Hunter (1):
perf record: Let user have timestamps with per-thread recording
Arnaldo Carvalho de Melo (9):
perf tools: Asprintf like functions to format integer filter expression perf trace: Remember what are the syscalls tracepoint evsels perf trace: Store the syscall ids for the event qualifiers in a table perf evsel: Rename set_filter to apply_filter
perf evsel: Introduce set_filter method
perf evlist: Make perf_evlist__set_filter use perf_evsel__set_filter perf evsel: Introduce append_filter() method
perf trace: Use event filters for the event qualifier list tools lib api debugfs: Check for tracefs when reporting errors
Markus Elfring (1):
perf probe: Delete an unnecessary check before the function call "strfilter__delete"
tools/lib/api/fs/debugfs.c | 15 +++- tools/perf/builtin-probe.c | 3 +- tools/perf/builtin-record.c | 4 +- tools/perf/builtin-trace.c | 178 ++++++++++++++++++++++++++--------------- tools/perf/perf.h | 1 + tools/perf/util/evlist.c | 6 +- tools/perf/util/evsel.c | 37 ++++++++- tools/perf/util/evsel.h | 7 +- tools/perf/util/parse-events.c | 3 +- tools/perf/util/string.c | 39 +++++++++ tools/perf/util/util.h | 12 +++ 11 files changed, 224 insertions(+), 81 deletions(-)
Arnaldo Carvalho de Melo
maintainerPATCH 1/11 perf tools: Asprintf like functions to format integer filter expression
From: Arnaldo Carvalho de Melo <[email protected]>
char *asprintf_expr_in_ints(const char *var, size_t nints, int *ints); char *asprintf_expr_not_in_ints(const char *var, size_t nints, int *ints);
Example of output formatted with those functions:
# ./tp_filter 6 12 2015 asprintf_expr_in_ints: id == 6 || id == 12 || id == 2015 asprintf_expr_not_in_ints: id != 6 && id != 12 && id != 2015 #
It'll be used with, for instance, perf_evsel__set_filter_in_ints(), that will be used in turn to ask the kernel to filter out all raw_syscalls:* except for the ones specified by the user via:
$ perf trace -e some,list,of,syscalls
--- tools/perf/util/string.c | 39 +++++++++++++++++++++++++++++++++++++++ tools/perf/util/util.h | 12 ++++++++++++ 2 files changed, 51 insertions(+)
tools/perf/util/string.c +39 -0
@@ -357,3 +357,42 @@ void *memdup(const void *src, size_t len)return p; } + +char *asprintf_expr_inout_ints (const char *var,bool in,size_t nints,int *ints) +{ +/* +* FIXME: replace this with an expression using log10() when we +* find a suitable implementation, maybe the one in the dvb drivers... +* +* "%s == %d || " = log10(MAXINT) * 2 + 8 chars for the operators +*/ +size_t size = nints *28 +1 ;/* \0 */ +size_t i, printed =0 ; +char *expr =malloc (size); + +if (expr) { +const char *or_and ="||" , *eq_neq ="==" ; +char *e = expr; + +if (!in) { + or_and ="&&" ; + eq_neq ="!=" ; + } + +for (i =0 ; i < nints; ++i) { +if (printed == size) + goto out_err_overflow; + +if (i >0 ) + printed +=snprintf (e + printed, size - printed," %s " , or_and); + printed +=scnprintf (e + printed, size - printed, +"%s %s %d" , var, eq_neq, ints[i]); + } + } + +return expr; + +out_err_overflow: +free (expr); +return NULL ; +}
tools/perf/util/util.h +12 -0
@@ -339,4 +339,16 @@ int gzip_decompress_to_file(const char *input, int output_fd);int lzma_decompress_to_file (const char *input,int output_fd);#endif +char *asprintf_expr_inout_ints (const char *var,bool in,size_t nints,int *ints); + +static inline char *asprintf_expr_in_ints (const char *var,size_t nints,int *ints) +{ +return asprintf_expr_inout_ints (var, true, nints, ints); +} + +static inline char *asprintf_expr_not_in_ints (const char *var,size_t nints,int *ints) +{ +return asprintf_expr_inout_ints (var, false, nints, ints); +} +#endif /* GIT_COMPAT_UTIL_H */
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 2/11 perf trace: Remember what are the syscalls tracepoint evsels
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We will need to set filters on then.
--- tools/perf/builtin-trace.c | 82 ++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 39 deletions(-)
tools/perf/builtin-trace.c +43 -39
@@ -247,42 +247,6 @@ out_delete: ({struct syscall_tp *fields = evsel->priv; \ fields->name.pointer(&fields->name, sample); }) -static int perf_evlist__add_syscall_newtp (struct perf_evlist *evlist, -void *sys_enter_handler, -void *sys_exit_handler) -{ -int ret =-1 ; -struct perf_evsel *sys_enter, *sys_exit; - - sys_enter =perf_evsel__syscall_newtp ("sys_enter" , sys_enter_handler); -if (sys_enter ==NULL ) - goto out; - -if (perf_evsel__init_sc_tp_ptr_field (sys_enter, args)) - goto out_delete_sys_enter; - - sys_exit =perf_evsel__syscall_newtp ("sys_exit" , sys_exit_handler); -if (sys_exit ==NULL ) - goto out_delete_sys_enter; - -if (perf_evsel__init_sc_tp_uint_field (sys_exit, ret)) - goto out_delete_sys_exit; - -perf_evlist__add (evlist, sys_enter); -perf_evlist__add (evlist, sys_exit); - - ret =0 ; -out: -return ret; - -out_delete_sys_exit: -perf_evsel__delete_priv (sys_exit); -out_delete_sys_enter: -perf_evsel__delete_priv (sys_enter); - goto out; -} - -struct syscall_arg {unsigned long val;struct thread *thread;
@@ -1307,6 +1271,10 @@ struct trace {struct {int max;struct syscall *table; +struct { +struct perf_evsel *enter, + *exit; + } events; } syscalls;struct record_opts opts;struct perf_evlist *evlist;
@@ -2283,6 +2251,44 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st } } +static int trace__add_syscall_newtp (struct trace *trace) +{ +int ret =-1 ; +struct perf_evlist *evlist = trace->evlist; +struct perf_evsel *sys_enter, *sys_exit; + + sys_enter =perf_evsel__syscall_newtp ("sys_enter" , trace__sys_enter); +if (sys_enter ==NULL ) + goto out; + +if (perf_evsel__init_sc_tp_ptr_field (sys_enter, args)) + goto out_delete_sys_enter; + + sys_exit =perf_evsel__syscall_newtp ("sys_exit" , trace__sys_exit); +if (sys_exit ==NULL ) + goto out_delete_sys_enter; + +if (perf_evsel__init_sc_tp_uint_field (sys_exit, ret)) + goto out_delete_sys_exit; + +perf_evlist__add (evlist, sys_enter); +perf_evlist__add (evlist, sys_exit); + + trace->syscalls.events.enter = sys_enter; + trace->syscalls.events.exit = sys_exit; + + ret =0 ; +out: +return ret; + +out_delete_sys_exit: +perf_evsel__delete_priv (sys_exit); +out_delete_sys_enter: +perf_evsel__delete_priv (sys_enter); + goto out; +} + +static int trace__run (struct trace *trace,int argc,const char **argv) {struct perf_evlist *evlist = trace->evlist;
@@ -2293,9 +2299,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) trace->live = true; -if (trace->trace_syscalls && -perf_evlist__add_syscall_newtp (evlist, trace__sys_enter, - trace__sys_exit)) +if (trace->trace_syscalls &&trace__add_syscall_newtp (trace)) goto out_error_raw_syscalls;if (trace->trace_syscalls)
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 3/11 perf trace: Store the syscall ids for the event qualifiers in a table
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
That we will use to set a filter on raw_syscalls:sys_{enter,exit} events.
--- tools/perf/builtin-trace.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-)
tools/perf/builtin-trace.c +29 -7
@@ -1272,8 +1272,8 @@ struct trace {int max;struct syscall *table;struct { -struct perf_evsel *enter, - *exit; +struct perf_evsel *sys_enter, + *sys_exit; } events; } syscalls;struct record_opts opts;
@@ -1284,6 +1284,10 @@ struct trace {FILE *output;unsigned long nr_events;struct strlist *ev_qualifier; +struct { +size_t nr; +int *entries; + } ev_qualifier_ids;const char *last_vfs_getname;struct intlist *tid_list;struct intlist *pid_list;
@@ -1587,13 +1591,27 @@ static int trace__read_syscall_info(struct trace *trace, int id)static int trace__validate_ev_qualifier (struct trace *trace) { -int err =0 ; +int err =0 , i;struct str_node *pos; + trace->ev_qualifier_ids.nr =strlist__nr_entries (trace->ev_qualifier); + trace->ev_qualifier_ids.entries =malloc (trace->ev_qualifier_ids.nr * +sizeof (trace->ev_qualifier_ids.entries[0 ])); + +if (trace->ev_qualifier_ids.entries ==NULL ) { +fputs ("Error:\tNot enough memory for allocating events qualifier ids\n" , + trace->output); + err = -EINVAL ; + goto out; + } + + i =0 ; +strlist__for_each (pos, trace->ev_qualifier) {const char *sc = pos->s; +int id =audit_name_to_syscall (sc, trace->audit.machine); -if (audit_name_to_syscall (sc, trace->audit.machine) <0 ) { +if (id <0 ) {if (err ==0 ) {fputs ("Error:\tInvalid syscall " , trace->output); err = -EINVAL ;
@@ -1603,13 +1621,17 @@ static int trace__validate_ev_qualifier(struct trace *trace)fputs (sc, trace->output); } + + trace->ev_qualifier_ids.entries[i++] = id; }if (err <0 ) {fputs ("\nHint:\ttry 'perf list syscalls:sys_enter_*'" "\nHint:\tand: 'man syscalls'\n" , trace->output); +zfree (&trace->ev_qualifier_ids.entries); + trace->ev_qualifier_ids.nr =0 ; } - +out:return err; }
@@ -2274,8 +2296,8 @@ static int trace__add_syscall_newtp(struct trace *trace)perf_evlist__add (evlist, sys_enter);perf_evlist__add (evlist, sys_exit); - trace->syscalls.events.enter = sys_enter; - trace->syscalls.events.exit = sys_exit; + trace->syscalls.events.sys_enter = sys_enter; + trace->syscalls.events.sys_exit = sys_exit; ret =0 ; out:
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 4/11 perf evsel: Rename set_filter to apply_filter
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We need to be able to go on constructing a complex filter in multiple stages, since we can only set one filter per event.
For instance, we need to be able, in 'perf trace' to filter by the 'common_pid' field all the time, if only for the tracer itself, to avoid a feedback loop, and, in addition, we may want to filter the raw_syscalls:sys_{enter,exit} events by its 'id' filter, when using 'perf trace -e open,close' or 'perf trace -e !open,close', i.e. when we are interested in just a subset of syscalls or when we are not interested in it.
So we will have:
perf_evsel__set_filter(evsel, char *filter)
Replaces whatever is in evsel->filter.
perf_evsel__append_filter(evsel, const char *op, char *filter)
Appends, using op ("&&" or "||") with what is in evsel->filter. perf_evsel__apply_filter(evsel, filter):
That actually applies a filter, be it the one being constructed in evsel->filter, or any other, for tools with more specific ways to build the filter, issuing the appropriate ioctl for all the evsel fds.
The same changes will be made to the evlist__{set,apply} variants to keep everything consistent.
--- tools/perf/util/evlist.c | 4 ++-- tools/perf/util/evsel.c | 4 ++-- tools/perf/util/evsel.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-)
tools/perf/util/evlist.c +2 -2
@@ -1161,7 +1161,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **eif (evsel->filter ==NULL )continue ; - err =perf_evsel__set_filter (evsel, ncpus, nthreads, evsel->filter); + err =perf_evsel__apply_filter (evsel, ncpus, nthreads, evsel->filter);if (err) { *err_evsel = evsel;break ;
@@ -1179,7 +1179,7 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter) nthreads =thread_map__nr (evlist->threads);evlist__for_each (evlist, evsel) { - err =perf_evsel__set_filter (evsel, ncpus, nthreads, filter); + err =perf_evsel__apply_filter (evsel, ncpus, nthreads, filter);if (err)break ; }
tools/perf/util/evsel.c +2 -2
@@ -815,8 +815,8 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ncpus, int nthreareturn 0 ; } -int perf_evsel__set_filter (struct perf_evsel *evsel,int ncpus,int nthreads, -const char *filter) +int perf_evsel__apply_filter (struct perf_evsel *evsel,int ncpus,int nthreads, +const char *filter) { return perf_evsel__run_ioctl(evsel, ncpus, nthreads, PERF_EVENT_IOC_SET_FILTER,
tools/perf/util/evsel.h +2 -2
@@ -182,8 +182,8 @@ void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,void perf_evsel__set_sample_id (struct perf_evsel *evsel,bool use_sample_identifier); -int perf_evsel__set_filter (struct perf_evsel *evsel,int ncpus,int nthreads, -const char *filter); +int perf_evsel__apply_filter (struct perf_evsel *evsel,int ncpus,int nthreads, +const char *filter);int perf_evsel__enable (struct perf_evsel *evsel,int ncpus,int nthreads); int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 5/11 perf evsel: Introduce set_filter method
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Replaces existing filter string with the one provided.
--- tools/perf/util/evsel.c | 13 +++++++++++++ tools/perf/util/evsel.h | 1 + tools/perf/util/parse-events.c | 3 +-- 3 files changed, 15 insertions(+), 2 deletions(-)
tools/perf/util/evsel.c +13 -0
@@ -823,6 +823,19 @@ int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads, (void *)filter); } +int perf_evsel__set_filter (struct perf_evsel *evsel,const char *filter) +{ +char *new_filter =strdup (filter); + +if (new_filter !=NULL ) { +free (evsel->filter); + evsel->filter = new_filter; +return 0 ; + } + +return -1 ; +} +int perf_evsel__enable (struct perf_evsel *evsel,int ncpus,int nthreads) { return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
tools/perf/util/evsel.h +1 -0
@@ -182,6 +182,7 @@ void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,void perf_evsel__set_sample_id (struct perf_evsel *evsel,bool use_sample_identifier); +int perf_evsel__set_filter (struct perf_evsel *evsel,const char *filter);int perf_evsel__apply_filter (struct perf_evsel *evsel,int ncpus,int nthreads,const char *filter);int perf_evsel__enable (struct perf_evsel *evsel,int ncpus,int nthreads);
tools/perf/util/parse-events.c +1 -2
@@ -1177,8 +1177,7 @@ int parse_filter(const struct option *opt, const char *str,return -1 ; } - last->filter =strdup (str); -if (last->filter ==NULL ) { +if (perf_evsel__set_filter (last, str) <0 ) {fprintf (stderr,"not enough memory to hold filter string\n" );return -1 ; }
Signature · 1 line
2.1.0
Quoted 57 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit
d2d61ed55f8375a10ff606e83e2196880a775fb4:Merge branch 'perf/rbtree_copy' of
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxinto perf/urgent (2015-07-06 09:24:41 +0200)are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingofor you to fetch changes up to
ab85785aa13c36440a91a8e9f7616357de411a1f:tools lib api debugfs: Check for tracefs when reporting errors (2015-07-06 12:22:14 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:User visible:
- Take tracefs into account when reporting errors about accessing tracepoint information in tools like 'perf trace' (Arnaldo Carvalho de Melo)
- Let user have timestamps with per-thread recording in 'perf record' (Adrian Hunter)
Infrastructure:
- Introduce series of functions to build event filters so that we can set them in just one ioctl call, useful to set up
common_pid, raw_syscalls:sys_{enter,exit}'s "id" filters to use with 'perf trace' (Arnaldo Carvalho de Melo)- Delete an unnecessary check before calling
strfilter__delete()(Markus Elfring)Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Adrian Hunter (1):
perf record: Let user have timestamps with per-thread recordingArnaldo Carvalho de Melo (9):
perf tools: Asprintf like functions to format integer filter expression perf trace: Remember what are the syscalls tracepoint evsels perf trace: Store the syscall ids for the event qualifiers in a table perf evsel: Renameset_filtertoapply_filter
perf evsel: Introduceset_filtermethod
perf evlist: Makeperf_evlist__set_filteruseperf_evsel__set_filterperf evsel: Introduceappend_filter()method
perf trace: Use event filters for the event qualifier list tools lib api debugfs: Check for tracefs when reporting errorsMarkus Elfring (1):
perf probe: Delete an unnecessary check before the function call "strfilter__delete"
Quoted 12 lines
tools/lib/api/fs/debugfs.c | 15 +++- tools/perf/builtin-probe.c | 3 +- tools/perf/builtin-record.c | 4 +- tools/perf/builtin-trace.c | 178 ++++++++++++++++++++++++++--------------- tools/perf/perf.h | 1 + tools/perf/util/evlist.c | 6 +- tools/perf/util/evsel.c | 37 ++++++++- tools/perf/util/evsel.h | 7 +- tools/perf/util/parse-events.c | 3 +- tools/perf/util/string.c | 39 +++++++++ tools/perf/util/util.h | 12 +++ 11 files changed, 224 insertions(+), 81 deletions(-)
Pulled, thanks a lot Arnaldo!
Ingo
Arnaldo Carvalho de Melo
maintainerPATCH 6/11 perf evlist: Make perf_evlist__set_filter use perf_evsel__set_filter
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Instead of calling perf_evsel__apply_filter straight away, so that we can, in the next patches, expand the filter with more conditions before actually calling the ioctl to pass the end result filter to the kernel.
Now we need to call perf_evlist__apply_filters() after the filter is completely setup, i.e. do the ioctl calls.
The perf_evlist__apply_filters() method was already in place, because that is the model for the other tools that receives filters in the command line: go on setting then in the evsel->filter and only at the end, after parsing the whole command line, apply them.
We get, as a bonus, a more expressive message that states which event, if any, failed to have the filter applied to, with an error message stating what happened.
--- tools/perf/builtin-trace.c | 18 ++++++++++++++---- tools/perf/util/evlist.c | 4 +--- 2 files changed, 15 insertions(+), 7 deletions(-)
tools/perf/builtin-trace.c +14 -4
@@ -2314,6 +2314,7 @@ out_delete_sys_enter:static int trace__run (struct trace *trace,int argc,const char **argv) {struct perf_evlist *evlist = trace->evlist; +struct perf_evsel *evsel;int err =-1 , i;unsigned long before;const bool forks = argc >0 ;
@@ -2382,10 +2383,12 @@ static int trace__run(struct trace *trace, int argc, const char **argv)else if (thread_map__pid (evlist->threads,0 ) ==-1 ) err =perf_evlist__set_filter_pid (evlist,getpid ()); -if (err <0 ) { -printf ("err=%d,%s\n" , -err,strerror (-err)); -exit (1 ); - } +if (err <0 ) + goto out_error_mem; + + err =perf_evlist__apply_filters (evlist, &evsel); +if (err <0 ) + goto out_error_apply_filters; err =perf_evlist__mmap (evlist, trace->opts.mmap_pages, false);if (err <0 )
@@ -2488,6 +2491,13 @@ out_error_open: out_error:fprintf (trace->output,"%s\n" , errbuf); goto out_delete_evlist; + +out_error_apply_filters: +fprintf (trace->output, +"Failed to set filter \"%s\" on event %s with %d (%s)\n" , + evsel->filter,perf_evsel__name (evsel), errno, +strerror_r (errno, errbuf,sizeof (errbuf))); + goto out_delete_evlist; } out_error_mem:fprintf (trace->output,"Not enough memory to run!\n" );
tools/perf/util/evlist.c +1 -3
@@ -1175,11 +1175,9 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter) {struct perf_evsel *evsel;int err =0 ; -const int ncpus =cpu_map__nr (evlist->cpus), - nthreads =thread_map__nr (evlist->threads);evlist__for_each (evlist, evsel) { - err =perf_evsel__apply_filter (evsel, ncpus, nthreads, filter); + err =perf_evsel__set_filter (evsel, filter);if (err)break ; }
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 7/11 perf evsel: Introduce append_filter() method
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
To allow building filters in evsel->filter, that will eventually be applied via perf_evsel__apply_filter().
--- tools/perf/util/evsel.c | 17 +++++++++++++++++ tools/perf/util/evsel.h | 2 ++ 2 files changed, 19 insertions(+)
tools/perf/util/evsel.c +17 -0
@@ -836,6 +836,23 @@ int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter)return -1 ; } +int perf_evsel__append_filter (struct perf_evsel *evsel, +const char *op,const char *filter) +{ +char *new_filter; + +if (evsel->filter ==NULL ) +return perf_evsel__set_filter (evsel, filter); + +if (asprintf (&new_filter,"(%s) %s (%s)" , evsel->filter, op, filter) >0 ) { +free (evsel->filter); + evsel->filter = new_filter; +return 0 ; + } + +return -1 ; +} +int perf_evsel__enable (struct perf_evsel *evsel,int ncpus,int nthreads) { return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
tools/perf/util/evsel.h +2 -0
@@ -183,6 +183,8 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel, bool use_sample_identifier);int perf_evsel__set_filter (struct perf_evsel *evsel,const char *filter); +int perf_evsel__append_filter (struct perf_evsel *evsel, +const char *op,const char *filter);int perf_evsel__apply_filter (struct perf_evsel *evsel,int ncpus,int nthreads,const char *filter);int perf_evsel__enable (struct perf_evsel *evsel,int ncpus,int nthreads);
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 8/11 perf trace: Use event filters for the event qualifier list
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We use raw_syscalls:sys_{enter,exit} events to show the syscalls, but were using a rather lazy/inneficient way to implement our 'strace -e' equivalent:
filter out after reading the events in the ring buffer.
Deflect more work to the kernel by appending a filter expression for that, that, together with the pid list, that is always present, if only to filter the tracer itself, reduces pressure on the ring buffer and otherwise use infrastructure already in place in the kernel to do early filtering.
If we use it with -v we can see the filter passed to the kernel, for instance, for this contrieved case:
# trace -v -e \!open,close,write,poll,recvfrom,select,recvmsg,writev,sendmsg,read,futex,epoll_wait,ioctl,eventfd --filter-pids 2189,2566,1398,2692,4475,4532
<SNIP>
(common_pid != 2514 && common_pid != 1398 && common_pid != 2189 && common_pid != 2566 && common_pid != 2692 && common_pid != 4475 && common_pid != 4532) && (id != 3 && id != 232 && id != 284 && id != 202 && id != 16 && id != 2 && id != 7 && id != 0 && id != 45 && id != 47 && id != 23 && id != 46 && id != 1 && id != 20)
0.011 (0.011 ms): caribou/2295 eventfd2(flags: CLOEXEC|NONBLOCK) = 18
16.946 (0.019 ms): caribou/2295 eventfd2(flags: CLOEXEC|NONBLOCK) = 18
38.598 (0.167 ms): chronyd/794 socket(family: INET, type: DGRAM ) = 4
38.603 (0.002 ms): chronyd/794 fcntl(fd: 4<socket:[239307]>, cmd: GETFD) = 0
38.605 (0.001 ms): chronyd/794 fcntl(fd: 4<socket:[239307]>, cmd: SETFD, arg: 1) = 0
^C
#--- tools/perf/builtin-trace.c | 52 ++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 20 deletions(-)
tools/perf/builtin-trace.c +32 -20
@@ -1187,7 +1187,6 @@ struct syscall {int nr_args;struct format_field *args;const char *name; -bool filtered;bool is_exit;struct syscall_fmt *fmt;size_t (**arg_scnprintf)(char *bf,size_t size,struct syscall_arg *arg);
@@ -1550,19 +1549,6 @@ static int trace__read_syscall_info(struct trace *trace, int id) sc = trace->syscalls.table + id; sc->name = name; -if (trace->ev_qualifier) { -bool in =strlist__find (trace->ev_qualifier, name) !=NULL ; - -if (!(in ^ trace->not_ev_qualifier)) { - sc->filtered = true; -/* -* No need to do read tracepoint information since this will be -* filtered out. -*/ -return 0 ; - } - } - sc->fmt =syscall_fmt__find (sc->name);snprintf (tp_name,sizeof (tp_name),"sys_enter_%s" , sc->name);
@@ -1823,9 +1809,6 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,if (sc ==NULL )return -1 ; -if (sc->filtered) -return 0 ; - thread =machine__findnew_thread (trace->host, sample->pid, sample->tid); ttrace =thread__trace (thread, trace->output);if (ttrace ==NULL )
@@ -1881,9 +1864,6 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,if (sc ==NULL )return -1 ; -if (sc->filtered) -return 0 ; - thread =machine__findnew_thread (trace->host, sample->pid, sample->tid); ttrace =thread__trace (thread, trace->output);if (ttrace ==NULL )
@@ -2310,6 +2290,26 @@ out_delete_sys_enter: goto out; } +static int trace__set_ev_qualifier_filter (struct trace *trace) +{ +int err =-1 ; +char *filter =asprintf_expr_inout_ints ("id" , !trace->not_ev_qualifier, + trace->ev_qualifier_ids.nr, + trace->ev_qualifier_ids.entries); + +if (filter ==NULL ) + goto out_enomem; + +if (!perf_evsel__append_filter (trace->syscalls.events.sys_enter,"&&" , filter)) + err =perf_evsel__append_filter (trace->syscalls.events.sys_exit,"&&" , filter); + +free (filter); +out: +return err; +out_enomem: + errno =ENOMEM ; + goto out; +}static int trace__run (struct trace *trace,int argc,const char **argv) {
@@ -2386,6 +2386,14 @@ static int trace__run(struct trace *trace, int argc, const char **argv)if (err <0 ) goto out_error_mem; +if (trace->ev_qualifier_ids.nr >0 ) { + err =trace__set_ev_qualifier_filter (trace); +if (err <0 ) + goto out_errno; + } + +pr_debug ("%s\n" , trace->syscalls.events.sys_exit->filter); + err =perf_evlist__apply_filters (evlist, &evsel);if (err <0 ) goto out_error_apply_filters;
@@ -2502,6 +2510,10 @@ out_error_apply_filters: out_error_mem:fprintf (trace->output,"Not enough memory to run!\n" ); goto out_delete_evlist; + +out_errno: +fprintf (trace->output,"errno=%d,%s\n" , errno,strerror (errno)); + goto out_delete_evlist; }static int trace__replay (struct trace *trace)
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 9/11 perf probe: Delete an unnecessary check before the function call "strfilter__delete"
In reply to Arnaldo Carvalho de MeloFrom: Markus Elfring <[email protected]>
The strfilter__delete() function tests whether its argument is NULL and then returns immediately. Thus the test around the call is not needed.
This issue was detected by using the Coccinelle software.
--- tools/perf/builtin-probe.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
tools/perf/builtin-probe.c +1 -2
@@ -297,8 +297,7 @@ static void cleanup_params(void)clear_perf_probe_event (params.events + i);line_range__clear (¶ms.line_range);free (params.target); -if (params.filter) -strfilter__delete (params.filter); +strfilter__delete (params.filter);memset (¶ms,0 ,sizeof (params)); }
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 10/11 perf record: Let user have timestamps with per-thread recording
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
If the option -T is used with option --per-thread, then time is still not sampled. Fix that by using OPT_BOOLEAN_SET to distinguish when the user used the -T option as opposed to the default case when timestamps are enabled but only for per-cpu recording.
--- tools/perf/builtin-record.c | 4 +++- tools/perf/perf.h | 1 + tools/perf/util/evsel.c | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-)
tools/perf/builtin-record.c +3 -1
@@ -1030,7 +1030,9 @@ struct option __record_options[] = {OPT_BOOLEAN ('s' ,"stat" , &record.opts.inherit_stat,"per thread counts" ),OPT_BOOLEAN ('d' ,"data" , &record.opts.sample_address,"Record the sample addresses" ), -OPT_BOOLEAN ('T' ,"timestamp" , &record.opts.sample_time,"Record the sample timestamps" ), +OPT_BOOLEAN_SET ('T' ,"timestamp" , &record.opts.sample_time, + &record.opts.sample_time_set, +"Record the sample timestamps" ),OPT_BOOLEAN ('P' ,"period" , &record.opts.period,"Record the sample period" ),OPT_BOOLEAN ('n' ,"no-samples" , &record.opts.no_samples, "don't sample"),
tools/perf/perf.h +1 -0
@@ -51,6 +51,7 @@ struct record_opts {bool sample_address;bool sample_weight;bool sample_time; +bool sample_time_set;bool period;bool sample_intr_regs;bool running_time;
tools/perf/util/evsel.c +2 -1
@@ -707,7 +707,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)*/ if (opts->sample_time && (!perf_missing_features.sample_id_all && - (!opts->no_inherit ||target__has_cpu (&opts->target) || per_cpu))) + (!opts->no_inherit ||target__has_cpu (&opts->target) || per_cpu || + opts->sample_time_set)))perf_evsel__set_sample_bit (evsel,TIME );if (opts->raw_samples && !evsel->no_aux_samples) {
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 11/11 tools lib api debugfs: Check for tracefs when reporting errors
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Now that we have two mountpoints, one for debugfs and another, for tracefs, we end up needing to check permissions for both, so, on a system with default config we were always asking the user to check the permission of the debugfs mountpoint, even when it was already sufficient. Fix it.
E.g.:
$ trace -e nanosleep usleep 1 Error: No permissions to read /sys/kernel/debug/tracing/events/raw_syscalls/sys_(enter|exit) Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'
$ sudo mount -o remount,mode=755 /sys/kernel/debug $ trace -e nanosleep usleep 1 Error: No permissions to read /sys/kernel/debug/tracing/events/raw_syscalls/sys_(enter|exit) Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug/tracing'
$ sudo mount -o remount,mode=755 /sys/kernel/debug/tracing
$ trace -e nanosleep usleep 1
0.326 ( 0.061 ms): usleep/11961 nanosleep(rqtp: 0x7ffef1081c50) = 0
$--- tools/lib/api/fs/debugfs.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
tools/lib/api/fs/debugfs.c +13 -2
@@ -12,6 +12,7 @@#include <linux/kernel.h> #include "debugfs.h" +#include "tracefs.h" #ifndef DEBUGFS_DEFAULT_PATH #define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
@@ -94,11 +95,21 @@ int debugfs__strerror_open(int err, char *buf, size_t size, const char *filename"Hint:\tIs the debugfs filesystem mounted?\n" "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");break ; -case EACCES : +case EACCES : { +const char *mountpoint = debugfs_mountpoint; + +if (!access (debugfs_mountpoint,R_OK ) &&strncmp (filename,"tracing/" ,8 ) ==0 ) { +const char *tracefs_mntpoint =tracefs_find_mountpoint (); + +if (tracefs_mntpoint) + mountpoint = tracefs_mntpoint; + } +snprintf (buf, size,"Error:\tNo permissions to read %s/%s\n" "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n" , - debugfs_mountpoint, filename, debugfs_mountpoint); + debugfs_mountpoint, filename, mountpoint); + }break ;default :snprintf (buf, size,"%s" ,strerror_r (err, sbuf,sizeof (sbuf)));
Signature · 1 line
2.1.0