perf/sdt: Directly record cached SDT events
PATCH 1/1 perf/sdt: Directly record cached SDT events
This patch adds support for directly recording SDT events which are present in the probe cache. This patch is based on current SDT enablement patchset (v5) by Masami :
https://lkml.org/lkml/2016/4/27/828
and it implements two points in the TODO list mentioned in the cover note :
"- (perf record) Support SDT event recording directly" "- (perf record) Try to unregister SDT events after record."
Without this patch, we could probe into SDT events using "perf probe" and "perf record". With this patch, we can probe the SDT events directly using "perf record".
For example :
# perf list sdt // List the SDT events ... sdt_mysql:update__row__done [SDT event] sdt_mysql:update__row__start [SDT event] sdt_mysql:update__start [SDT event] sdt_python:function__entry [SDT event] sdt_python:function__return [SDT event] sdt_test:marker1 [SDT event] sdt_test:marker2 [SDT event] ...
# perf record -e %sdt_test:marker1 -e %sdt_test:marker2 -a ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 2.087 MB perf.data (22 samples) ]
# perf script
test_sdt 29230 [002] 405550.548017: sdt_test:marker1: (400534)
test_sdt 29230 [002] 405550.548064: sdt_test:marker2: (40053f)
test_sdt 29231 [002] 405550.962806: sdt_test:marker1: (400534)
test_sdt 29231 [002] 405550.962841: sdt_test:marker2: (40053f)
test_sdt 29232 [001] 405551.379327: sdt_test:marker1: (400534)
...After invoking "perf record", behind the scenes, it checks whether the event specified is an SDT event using the flag '%'. After that, it does a lookup of the probe cache to find out the SDT event. If its not present, it throws an error. Otherwise, it goes on and writes the event into the uprobe_events file and sets up the probe event, trace events, etc and starts recording. It also maintains a list of the event names that were written to uprobe_events file. After finishing the record session, it removes the events from the uprobe_events file using the maintained name list.
--- tools/perf/builtin-probe.c | 44 +++++++++++++++++++--- tools/perf/builtin-record.c | 24 ++++++++++++ tools/perf/util/bpf-loader.c | 2 +- tools/perf/util/build-id.c | 1 + tools/perf/util/parse-events.c | 36 +++++++++++++++++- tools/perf/util/parse-events.h | 2 + tools/perf/util/probe-event.c | 24 +++++++++--- tools/perf/util/probe-event.h | 4 +- tools/perf/util/probe-file.c | 85 ++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/probe-file.h | 8 ++++ 10 files changed, 217 insertions(+), 13 deletions(-)
tools/perf/builtin-probe.c +39 -5
@@ -322,7 +322,7 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)if (ret <0 )return ret; - ret =convert_perf_probe_events (pevs, npevs); + ret =convert_perf_probe_events (pevs, npevs, false);if (ret <0 ) goto out_cleanup;
@@ -387,7 +387,7 @@ static int del_perf_probe_caches(struct strfilter *filter)return 0 ; } -static int perf_del_probe_events (struct strfilter *filter) +static int perf_del_probe_events (struct strfilter *filter,bool show) {int ret, ret2, ufd =-1 , kfd =-1 ;char *str =strfilter__string (filter);
@@ -417,7 +417,8 @@ static int perf_del_probe_events(struct strfilter *filter) ret =probe_file__get_events (kfd, filter, klist);if (ret ==0 ) {strlist__for_each (ent, klist) -pr_info ("Removed event: %s\n" , ent->s); +if (show) +pr_info ("Removed event: %s\n" , ent->s); ret =probe_file__del_strlist (kfd, klist);if (ret <0 )
@@ -427,7 +428,8 @@ static int perf_del_probe_events(struct strfilter *filter) ret2 =probe_file__get_events (ufd, filter, ulist);if (ret2 ==0 ) {strlist__for_each (ent, ulist) -pr_info ("Removed event: %s\n" , ent->s); +if (show) +pr_info ("Removed event: %s\n" , ent->s); ret2 =probe_file__del_strlist (ufd, ulist);if (ret2 <0 )
@@ -452,6 +454,38 @@ out:return ret; } +/* +* Record session for SDT events has ended. Delete the SDT events +* from uprobe_events file that were created initially. +*/ +void remove_sdt_event_list (struct list_head *sdt_events) +{ +struct sdt_event_list *event; +struct strfilter *filter =NULL ; +const char *err =NULL ; +int ret =0 ; + +if (list_empty (sdt_events)) +return ; + +list_for_each_entry (event, sdt_events, list) { +if (!filter) { + filter =strfilter__new (event->event_name, &err); +if (!filter) + goto free_list; + }else { + ret =strfilter__or (filter, event->event_name, &err); + } + } + + ret =perf_del_probe_events (filter, false); +if (ret) +pr_err ("Error in deleting the SDT list\n" ); + +free_list: +free_sdt_list (sdt_events); +} +static int __cmd_probe (int argc,const char **argv,const char *prefix__maybe_unused ) {
@@ -635,7 +669,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)return ret;#endif case 'd' : - ret =perf_del_probe_events (params.filter); + ret =perf_del_probe_events (params.filter, true);if (ret <0 ) {pr_err_with_code (" Error: Failed to delete events." , ret);return ret;
tools/perf/builtin-record.c +24 -0
@@ -34,6 +34,7 @@#include "util/llvm-utils.h" #include "util/bpf-loader.h" #include "asm/bug.h" +#include "util/probe-file.h" #include <unistd.h> #include <sched.h>
@@ -56,6 +57,7 @@ struct record {bool no_buildid_cache_set;bool buildid_all;unsigned long long samples; +struct list_head sdt_event_list; };static int record__write (struct record *rec,void *bf,size_t size)
@@ -1077,6 +1079,26 @@ static struct record record = { }, }; +void sdt_event_list__add (struct list_head *sdt_event_list) +{ +if (list_empty (sdt_event_list)) +return ; +list_splice (sdt_event_list, &record.sdt_event_list); +} + +bool is_cmd_record (void ) +{ +return (record.evlist !=NULL ); +} + +static void sdt_event_list__remove (struct list_head *sdt_event_list) +{ +if (list_empty (sdt_event_list)) +return ; + +remove_sdt_event_list (sdt_event_list); +} +const char record_callchain_help[] =CALLCHAIN_RECORD_HELP "\n\t\t\t\tDefault: fp" ;
@@ -1231,6 +1253,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)if (rec->evlist ==NULL )return -ENOMEM ; +INIT_LIST_HEAD (&rec->sdt_event_list);perf_config (perf_record_config, rec); argc = parse_options(argc, argv, record_options, record_usage,
@@ -1330,6 +1353,7 @@ out_symbol_exit:perf_evlist__delete (rec->evlist);symbol__exit ();auxtrace_record__free (rec->itr); +sdt_event_list__remove (&rec->sdt_event_list);return err; }
tools/perf/util/bpf-loader.c +1 -1
@@ -612,7 +612,7 @@ int bpf__probe(struct bpf_object *obj) goto out; pev = &priv->pev; - err =convert_perf_probe_events (pev,1 ); + err =convert_perf_probe_events (pev,1 , false);if (err <0 ) {pr_debug ("bpf_probe: failed to convert perf probe events" ); goto out;
tools/perf/util/build-id.c +1 -0
@@ -569,6 +569,7 @@ static void build_id_cache__add_sdt_cache(const char *sbuild_id,probe_cache__commit (cache); probe_cache__delete(cache); } +#else #define build_id_cache__add_sdt_cache (sbuild_id, realname) do { } while (0)#endif
tools/perf/util/parse-events.c +35 -1
@@ -1687,7 +1687,41 @@ int parse_events_option(const struct option *opt, const char *str, {struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;struct parse_events_error err = { .idx =0 , }; -int ret =parse_events (evlist, str, &err); +int ret =0 ; + +if (*str =='%' &&is_cmd_record ()) { +char *ptr =NULL ; +struct list_head *sdt_list; + + ptr =zalloc (strlen (str)); +if (ptr ==NULL ) +return -ENOMEM ; +strcpy (ptr, str); + + sdt_list =zalloc (sizeof (*sdt_list)); +if (!sdt_list) { +free (ptr); +pr_err ("Error in sdt_list memory allocation\n" ); +return -ENOMEM ; + } +INIT_LIST_HEAD (sdt_list); + +/* +* If there is an error in this call, no need to free +* up sdt_list, its already free'ed up in the previous +* call. Free up 'ptr' though. +*/ + ret =add_sdt_event (ptr, sdt_list); +if (!ret) +sdt_event_list__add (sdt_list); +free (ptr); + } +if (!ret) { + ret =parse_events (evlist, str +1 , &err); +if (ret >0 ) + ret =0 ; + }else + ret =parse_events (evlist, str, &err);if (ret)parse_events_print_error (&err, str);
tools/perf/util/parse-events.h +2 -0
@@ -189,4 +189,6 @@ int is_valid_tracepoint(const char *event_string);int valid_event_mount (const char *eventfs);char *parse_events_formats_error_string (char *additional_terms); +void sdt_event_list__add (struct list_head *sdt_event_list); +bool is_cmd_record (void );#endif /* __PERF_PARSE_EVENTS_H */
tools/perf/util/probe-event.c +19 -5
@@ -1144,7 +1144,7 @@ err:return err; } -static int parse_perf_probe_event_name (char **arg,struct perf_probe_event *pev) +int parse_perf_probe_event_name (char **arg,struct perf_probe_event *pev) {char *ptr;
@@ -3008,7 +3008,8 @@ out: }static int convert_to_probe_trace_events (struct perf_probe_event *pev, -struct probe_trace_event **tevs) +struct probe_trace_event **tevs, +bool rec_enabled) {int ret;
@@ -3033,6 +3034,17 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, ret =find_probe_trace_events_from_cache (pev, tevs);if (ret >0 )return ret;/* Found in probe cache */ +else if (rec_enabled) { +/* +* Can't find in probe cache, and, since, +* recording for sdt events is only enabled for +* cached events, we need to return throwing an error. +*/ +pr_err ("Can't find %s in cache.\n" , pev->event); +pr_err ("Use \"perf list sdt\" to see the available events\n" ); +return -EINVAL ; + } +if (arch__prefers_symtab () && !perf_probe_event_need_dwarf (pev)) { ret =find_probe_trace_events_from_map (pev, tevs);
@@ -3048,7 +3060,8 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,return find_probe_trace_events_from_map (pev, tevs); } -int convert_perf_probe_events (struct perf_probe_event *pevs,int npevs) +int convert_perf_probe_events (struct perf_probe_event *pevs,int npevs, +bool rec_enabled) {int i, ret;
@@ -3058,7 +3071,8 @@ int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs)if (!pevs[i].uprobes)kprobe_blacklist__init ();/* Convert with or without debuginfo */ - ret =convert_to_probe_trace_events (&pevs[i], &pevs[i].tevs); + ret =convert_to_probe_trace_events (&pevs[i], &pevs[i].tevs, + rec_enabled);if (ret <0 )return ret; pevs[i].ntevs = ret;
@@ -3106,7 +3120,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs)if (ret <0 )return ret; - ret =convert_perf_probe_events (pevs, npevs); + ret =convert_perf_probe_events (pevs, npevs, false);if (ret ==0 ) ret =apply_perf_probe_events (pevs, npevs);
tools/perf/util/probe-event.h +3 -1
@@ -146,7 +146,8 @@ void line_range__clear(struct line_range *lr);int line_range__init (struct line_range *lr);int add_perf_probe_events (struct perf_probe_event *pevs,int npevs); -int convert_perf_probe_events (struct perf_probe_event *pevs,int npevs); +int convert_perf_probe_events (struct perf_probe_event *pevs,int npevs, +bool rec);int apply_perf_probe_events (struct perf_probe_event *pevs,int npevs);void cleanup_perf_probe_events (struct perf_probe_event *pevs,int npevs);int del_perf_probe_events (struct strfilter *filter);
@@ -173,4 +174,5 @@ int e_snprintf(char *str, size_t size, const char *format, ...)int copy_to_probe_trace_arg (struct probe_trace_arg *tvar,struct perf_probe_arg *pvar); +int parse_perf_probe_event_name (char **arg,struct perf_probe_event *pev);#endif /*_PROBE_EVENT_H */
tools/perf/util/probe-file.c +85 -0
94 lines not on this page · raw message
tools/perf/util/probe-file.h +8 -0
@@ -32,6 +32,11 @@ struct probe_cache {struct list_head list; }; +struct sdt_event_list { +char *event_name; +struct list_head list; +}; +int probe_cache_entry__get_event (struct probe_cache_entry *entry,struct probe_trace_event **tevs);#define for_each_probe_cache_entry (entry, pcache) \
@@ -51,4 +56,7 @@ struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,struct probe_cache_entry *probe_cache__find_by_name (struct probe_cache *pcache,const char *group,const char *event);int probe_cache__show_all_caches (struct strfilter *filter); +int add_sdt_event (char *event,struct list_head *sdt_event_list); +void remove_sdt_event_list (struct list_head *sdt_event_list); +void free_sdt_list (struct list_head *sdt_events);#endif
Signature · 1 line
1.9.3
Hi Hemant,
Quoted 9 lines · On Fri, 29 Apr 2016 19:10:41 +0530 Hemant Kumar <[email protected]>…
This patch adds support for directly recording SDT events which are present in the probe cache. This patch is based on current SDT enablement patchset (v5) by Masami :
https://lkml.org/lkml/2016/4/27/828
and it implements two points in the TODO list mentioned in the cover note :
"- (perf record) Support SDT event recording directly" "- (perf record) Try to unregister SDT events after record."
Quoted 3 lines
Without this patch, we could probe into SDT events using "perf probe" and "perf record". With this patch, we can probe the SDT events directly using "perf record".
Thanks! However, before looking over each part of this patch, I think this is not enough for supporting SDT for perf record.
If there are several SDTs which have same eventname but differnt addresses (e.g. libc:memory_memalign_retry), how are those handled? Currently, to support this, we'll need to enable those events in different names, or just pick one of them. It could confuse users in each case.
To solve this issue, we need to introduce multiple SDTs on single ftrace event. Please read my comment on v3 patch (https://lkml.org/lkml/2015/8/15/52)
So, at this point, I've decided to introduce only perf-probe side. If user want to record SDT, they can use perf-probe to add SDT events and see what events are generated by SDT, so that they can specify those events via perf-record.
e.g.
# perf probe -a %sdt_libc:* ... sdt_libc:lll_futex_wake_1 (on %* in /usr/lib64/libc-2.20.so) sdt_libc:lll_lock_wait_private (on %* in /usr/lib64/libc-2.20.so)
You can now use it in all perf tools, such as:
perf record -e sdt_libc:lll_lock_wait_private -aR sleep 1
# perf record -e sdt_libc:* -a ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 1.461 MB perf.data (6195 samples) ]
# perf script
plugin_audio_th 11119 [000] 16059.864654: sdt_libc:setjmp: (7f37bf55b6c1)
chrome 4650 [000] 16059.881345: sdt_libc:setjmp: (7f37bf55b6c1)
chrome 4650 [000] 16059.881350: sdt_libc:setjmp: (7f37bf55b6c1)
chrome 4650 [000] 16059.881411: sdt_libc:setjmp: (7f37bf55b6c1)
...BTW, see below comments on the code for implementation issues.
[...]
Quoted 23 lines
tools/perf/builtin-probe.c +2
-2@@ -322,7 +322,7 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)if (ret <0 )return ret; - ret =convert_perf_probe_events (pevs, npevs); + ret =convert_perf_probe_events (pevs, npevs, false);if (ret <0 ) goto out_cleanup;@@ -387,7 +387,7 @@ static int del_perf_probe_caches(struct strfilter *filter)return 0 ; } -static int perf_del_probe_events (struct strfilter *filter) +static int perf_del_probe_events (struct strfilter *filter,bool show) {int ret, ret2, ufd =-1 , kfd =-1 ;char *str =strfilter__string (filter);
tools/perf/builtin-probe.c static int perf_del_probe_events(struct strfilter *filter) · line 421
Quoted 6 lines
tools/perf/builtin-probe.c +2
-1@@ -417,7 +417,8 @@ static int perf_del_probe_events(struct strfilter *filter) ret =probe_file__get_events (kfd, filter, klist);if (ret ==0 ) {strlist__for_each (ent, klist) -pr_info ("Removed event: %s\n" , ent->s); +if (show) +pr_info ("Removed event: %s\n" , ent->s);
No, please don't do this. we have del_perf_probe_events(struct strfilter *filter) for internal and silent version.
Quoted 37 lines
tools/perf/builtin-probe.c +23
-1ret =probe_file__del_strlist (kfd, klist);if (ret <0 )@@ -427,7 +428,8 @@ static int perf_del_probe_events(struct strfilter *filter) ret2 =probe_file__get_events (ufd, filter, ulist);if (ret2 ==0 ) {strlist__for_each (ent, ulist) -pr_info ("Removed event: %s\n" , ent->s); +if (show) +pr_info ("Removed event: %s\n" , ent->s); ret2 =probe_file__del_strlist (ufd, ulist);if (ret2 <0 )@@ -452,6 +454,38 @@ out:return ret; } +/* +* Record session for SDT events has ended. Delete the SDT events +* from uprobe_events file that were created initially. +*/ +void remove_sdt_event_list (struct list_head *sdt_events) +{ +struct sdt_event_list *event; +struct strfilter *filter =NULL ; +const char *err =NULL ; +int ret =0 ; + +if (list_empty (sdt_events)) +return ; + +list_for_each_entry (event, sdt_events, list) { +if (!filter) { + filter =strfilter__new (event->event_name, &err); +if (!filter) + goto free_list; + }else { + ret =strfilter__or (filter, event->event_name, &err);
tools/perf/builtin-probe.c out: · line 487
Quoted 10 lines
tools/perf/builtin-probe.c +10
-0+ } + } + + ret =perf_del_probe_events (filter, false); +if (ret) +pr_err ("Error in deleting the SDT list\n" ); + +free_list: +free_sdt_list (sdt_events); +}
And, this has to move to util/probe-event.c
[...]
Quoted 28 lines
tools/perf/util/parse-events.c +19
-1@@ -1687,7 +1687,41 @@ int parse_events_option(const struct option *opt, const char *str, {struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;struct parse_events_error err = { .idx =0 , }; -int ret =parse_events (evlist, str, &err); +int ret =0 ; + +if (*str =='%' &&is_cmd_record ()) { +char *ptr =NULL ; +struct list_head *sdt_list; + + ptr =zalloc (strlen (str)); +if (ptr ==NULL ) +return -ENOMEM ; +strcpy (ptr, str); + + sdt_list =zalloc (sizeof (*sdt_list)); +if (!sdt_list) { +free (ptr); +pr_err ("Error in sdt_list memory allocation\n" ); +return -ENOMEM ; + } +INIT_LIST_HEAD (sdt_list); +
tools/perf/util/parse-events.c int parse_events_option(const struct option *opt, const char *str, · line 1718
Quoted 10 lines
tools/perf/util/parse-events.c +10
-0+/* +* If there is an error in this call, no need to free +* up sdt_list, its already free'ed up in the previous +* call. Free up 'ptr' though. +*/ + ret =add_sdt_event (ptr, sdt_list); +if (!ret) +sdt_event_list__add (sdt_list); +free (ptr); + }
This part should be another function, like parse_sdt_events().
Quoted 48 lines
tools/perf/util/parse-events.c +6
-0+if (!ret) { + ret =parse_events (evlist, str +1 , &err); +if (ret >0 ) + ret =0 ; + }else + ret =parse_events (evlist, str, &err);if (ret)parse_events_print_error (&err, str);tools/perf/util/parse-events.h +2
-0@@ -189,4 +189,6 @@ int is_valid_tracepoint(const char *event_string);int valid_event_mount (const char *eventfs);char *parse_events_formats_error_string (char *additional_terms); +void sdt_event_list__add (struct list_head *sdt_event_list); +bool is_cmd_record (void );#endif /* __PERF_PARSE_EVENTS_H */ tools/perf/util/probe-event.c +4
-2@@ -1144,7 +1144,7 @@ err:return err; } -static int parse_perf_probe_event_name (char **arg,struct perf_probe_event *pev) +int parse_perf_probe_event_name (char **arg,struct perf_probe_event *pev) {char *ptr;@@ -3008,7 +3008,8 @@ out: }static int convert_to_probe_trace_events (struct perf_probe_event *pev, -struct probe_trace_event **tevs) +struct probe_trace_event **tevs, +bool rec_enabled) {int ret;@@ -3033,6 +3034,17 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, ret =find_probe_trace_events_from_cache (pev, tevs);if (ret >0 )return ret;/* Found in probe cache */ +else if (rec_enabled) {
tools/perf/util/probe-event.c static int convert_to_probe_trace_events(struct perf_probe_event *pev, · line 3047
Quoted 10 lines
tools/perf/util/probe-event.c +10
-0+/* +* Can't find in probe cache, and, since, +* recording for sdt events is only enabled for +* cached events, we need to return throwing an error. +*/ +pr_err ("Can't find %s in cache.\n" , pev->event); +pr_err ("Use \"perf list sdt\" to see the available events\n" ); +return -EINVAL ; + } +
No, please don't add this flag. Instead, you can show this message in the caller. And also, you should use find_cached_events_all() for this purpose, since this is not only for SDT.
[...]
Quoted 39 lines
tools/perf/util/probe-event.c +39
-0+/* +* Find the SDT event from the cache and if found add it/them +* to the uprobe_events file +*/ +int add_sdt_event (char *event,struct list_head *sdt_events) +{ +struct perf_probe_event *pev; +int ret, i; +char *str = event +1 ; +struct sdt_event_list *tmp; + + pev =zalloc (sizeof (*pev)); +if (!pev) +return -ENOMEM ; + + pev->sdt = true; + pev->uprobes = true; + +/* +* Parse str to find the group name and event name of +* the sdt event. +*/ + ret =parse_perf_probe_event_name (&str, pev); +if (ret) { +pr_err ("Error in parsing sdt event %s\n" , str); +free (pev); +return ret; + } + + probe_conf.max_probes =MAX_PROBES ; + probe_conf.force_add =1 ; + +/* +* Find the sdt event from the cache, only cached SDT +* events can be directly recorded. +*/ + ret =convert_perf_probe_events (pev,1 , true); +if (ret <0 ) { + goto free_pev;
tools/perf/util/probe-event.c static int convert_to_probe_trace_events(struct perf_probe_event *pev,
Quoted 10 lines
tools/perf/util/probe-event.c +10
-0+ }else if (!ret) { + ret =apply_perf_probe_events (pev,1 ); +if (ret) { +pr_err ("Error in adding SDT event : %s\n" , event); + goto free_pev; + } + } + +if (pev->ntevs) { +/* Add the event name to "sdt_events" */
I think this should be done before applying probe events, so that easy to roll it back.
tools/perf/util/probe-event.c
Quoted 8 lines
tools/perf/util/probe-event.c +8
-0+for (i =0 ; i < pev->ntevs; i++) { + tmp =zalloc (sizeof (*tmp)); +if (!tmp) { + ret = -ENOMEM ; + goto free_pev; + } +INIT_LIST_HEAD (&tmp->list); + tmp->event_name =strdup (pev->tevs[i].event);
What? would you only care the event name?
Quoted 18 lines
tools/perf/util/probe-event.c +13
-0+if (!tmp->event_name) { +free_sdt_list (sdt_events); + ret = -ENOMEM ; + goto free_pev; + } +list_add (&tmp->list, sdt_events); + } + } + +free_pev: +cleanup_perf_probe_events (pev,1 ); +return 0 ; +}tools/perf/util/probe-file.h +0
-0
tools/perf/util/probe-file.h struct probe_cache { · line 36
Quoted 5 lines
tools/perf/util/probe-file.h +2
-0@@ -32,6 +32,11 @@ struct probe_cache {struct list_head list; }; +struct sdt_event_list { +char *event_name;
This should hold the filter pattern itself.
If possible, it should be the actual command which you've write to probe-file (kprobe_events/uprobe_events in ftrace)
Thank you,
Signature · 1 line
Masami Hiramatsu <[email protected]>
Hi Masami,
Quoted 14 lines · Masami Hiramatsu
Hi Hemant,
Quoted 9 lines · On Fri, 29 Apr 2016 19:10:41 +0530 Hemant Kumar <[email protected]>…
This patch adds support for directly recording SDT events which are present in the probe cache. This patch is based on current SDT enablement patchset (v5) by Masami :
https://lkml.org/lkml/2016/4/27/828
and it implements two points in the TODO list mentioned in the cover note :
"- (perf record) Support SDT event recording directly" "- (perf record) Try to unregister SDT events after record."
Quoted 5 lines
Quoted 3 lines
Without this patch, we could probe into SDT events using "perf probe" and "perf record". With this patch, we can probe the SDT events directly using "perf record".
Thanks! However, before looking over each part of this patch, I think this is not enough for supporting SDT for perf record.
Hmm.
Quoted 5 lines
If there are several SDTs which have same eventname but differnt addresses (e.g. libc:memory_memalign_retry), how are those handled? Currently, to support this, we'll need to enable those events in different names, or just pick one of them. It could confuse users in each case.
Right. But now, its the same case with a binary having multiple symbols with same names, isn't it?
# nm ./multi | grep foo 0000000000400530 t foo 0000000000400560 t foo
# perf probe -x ./multi foo Added new events: probe_multi:foo (on foo in /home/hemant/work/linux/tools/perf/multi) probe_multi:foo_1 (on foo in /home/hemant/work/linux/tools/perf/multi)
You can now use it in all perf tools, such as:
perf record -e probe_multi:foo_1 -aR sleep 1
My point being, the user can still know, if its shown that there are two or more probes being placed and the o/p of perf report/script shows that the probes are placed at two or more different addresses.
Quoted 2 lines
To solve this issue, we need to introduce multiple SDTs on single ftrace event. Please read my comment on v3 patch (https://lkml.org/lkml/2015/8/15/52)
Ok. But, I think, for initial direct recording support, we can go with this IMHO.
Quoted 19 lines
So, at this point, I've decided to introduce only perf-probe side. If user want to record SDT, they can use perf-probe to add SDT events and see what events are generated by SDT, so that they can specify those events via perf-record.
e.g.# perf probe -a %sdt_libc:* ... sdt_libc:lll_futex_wake_1 (on %* in /usr/lib64/libc-2.20.so) sdt_libc:lll_lock_wait_private (on %* in /usr/lib64/libc-2.20.so)You can now use it in all perf tools, such as:
perf record -e sdt_libc:lll_lock_wait_private -aR sleep 1
# perf record -e sdt_libc:* -a ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 1.461 MB perf.data (6195 samples) ]
Quoted 8 lines
# perf script plugin_audio_th 11119 [000] 16059.864654: sdt_libc:setjmp: (7f37bf55b6c1) chrome 4650 [000] 16059.881345: sdt_libc:setjmp: (7f37bf55b6c1) chrome 4650 [000] 16059.881350: sdt_libc:setjmp: (7f37bf55b6c1) chrome 4650 [000] 16059.881411: sdt_libc:setjmp: (7f37bf55b6c1) ...BTW, see below comments on the code for implementation issues.
Will fix the issues and send a v2.
Thanks a lot for the review.
Signature · 2 lines
Thanks, Hemant Kumar
Quoted 25 lines · On Tue, 03 May 2016 05:06:24 +0530 Hemant Kumar <[email protected]>…
Hi Masami,
Quoted 14 lines · Masami Hiramatsu
Hi Hemant,
Quoted 9 lines · On Fri, 29 Apr 2016 19:10:41 +0530 Hemant Kumar <[email protected]>…
This patch adds support for directly recording SDT events which are present in the probe cache. This patch is based on current SDT enablement patchset (v5) by Masami :
https://lkml.org/lkml/2016/4/27/828
and it implements two points in the TODO list mentioned in the cover note :
"- (perf record) Support SDT event recording directly" "- (perf record) Try to unregister SDT events after record."Quoted 5 lines
Quoted 3 lines
Without this patch, we could probe into SDT events using "perf probe" and "perf record". With this patch, we can probe the SDT events directly using "perf record".
Thanks! However, before looking over each part of this patch, I think this is not enough for supporting SDT for perf record.
Hmm.
Quoted 8 lines
Quoted 5 lines
If there are several SDTs which have same eventname but differnt addresses (e.g. libc:memory_memalign_retry), how are those handled? Currently, to support this, we'll need to enable those events in different names, or just pick one of them. It could confuse users in each case.
Right. But now, its the same case with a binary having multiple symbols with same names, isn't it?
Yes, but for the symbols or lines etc., user can not directly specify it via perf record. And as you showed below, perf-probe expresses there are 2 events on the probe point. So user is forced to aware of it.
Quoted 10 lines
# nm ./multi | grep foo 0000000000400530 t foo 0000000000400560 t foo# perf probe -x ./multi foo Added new events: probe_multi:foo (on foo in /home/hemant/work/linux/tools/perf/multi) probe_multi:foo_1 (on foo in /home/hemant/work/linux/tools/perf/multi)
Quoted 8 lines
You can now use it in all perf tools, such as:
perf record -e probe_multi:foo_1 -aR sleep 1
My point being, the user can still know, if its shown that there are two or more probes being placed and the o/p of perf report/script shows that the probes are placed at two or more different addresses.
Not only the different address, but also they will see the different event names. That may be no good for making a script on it.
My point is, if the user only uses "perf record -e sdt_something:sdtevent", they will think that there is one event recorded. it can easily misleading them.
Quoted 5 lines
Quoted 2 lines
To solve this issue, we need to introduce multiple SDTs on single ftrace event. Please read my comment on v3 patch (https://lkml.org/lkml/2015/8/15/52)
Ok. But, I think, for initial direct recording support, we can go with this IMHO.
So, at least this should be noticed to users carefully. (e.g. warn if there are more than two SDTs defined)
Thank you,
Quoted 36 lines
Quoted 19 lines
So, at this point, I've decided to introduce only perf-probe side. If user want to record SDT, they can use perf-probe to add SDT events and see what events are generated by SDT, so that they can specify those events via perf-record.
e.g.# perf probe -a %sdt_libc:* ... sdt_libc:lll_futex_wake_1 (on %* in /usr/lib64/libc-2.20.so) sdt_libc:lll_lock_wait_private (on %* in /usr/lib64/libc-2.20.so)You can now use it in all perf tools, such as:
perf record -e sdt_libc:lll_lock_wait_private -aR sleep 1
# perf record -e sdt_libc:* -a ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 1.461 MB perf.data (6195 samples) ]Quoted 8 lines
# perf script plugin_audio_th 11119 [000] 16059.864654: sdt_libc:setjmp: (7f37bf55b6c1) chrome 4650 [000] 16059.881345: sdt_libc:setjmp: (7f37bf55b6c1) chrome 4650 [000] 16059.881350: sdt_libc:setjmp: (7f37bf55b6c1) chrome 4650 [000] 16059.881411: sdt_libc:setjmp: (7f37bf55b6c1) ...BTW, see below comments on the code for implementation issues.
Will fix the issues and send a v2.
Thanks a lot for the review.
Signature · 2 lines
Thanks, Hemant Kumar
Signature · 1 line
Masami Hiramatsu <[email protected]>
Quoted 32 lines · Masami Hiramatsu
Quoted 29 lines · On Tue, 03 May 2016 05:06:24 +0530 Hemant Kumar <[email protected]>…
Hi Masami,
Quoted 14 lines · Masami Hiramatsu
Hi Hemant,
Quoted 9 lines · On Fri, 29 Apr 2016 19:10:41 +0530 Hemant Kumar <[email protected]>…
This patch adds support for directly recording SDT events which are present in the probe cache. This patch is based on current SDT enablement patchset (v5) by Masami :
https://lkml.org/lkml/2016/4/27/828
and it implements two points in the TODO list mentioned in the cover note :
"- (perf record) Support SDT event recording directly" "- (perf record) Try to unregister SDT events after record."Quoted 5 lines
Quoted 3 lines
Without this patch, we could probe into SDT events using "perf probe" and "perf record". With this patch, we can probe the SDT events directly using "perf record".
Thanks! However, before looking over each part of this patch, I think this is not enough for supporting SDT for perf record.
Hmm.
Quoted 5 lines
If there are several SDTs which have same eventname but differnt addresses (e.g. libc:memory_memalign_retry), how are those handled? Currently, to support this, we'll need to enable those events in different names, or just pick one of them. It could confuse users in each case.
Quoted 5 lines
Quoted 2 lines
Right. But now, its the same case with a binary having multiple symbols with same names, isn't it?
Yes, but for the symbols or lines etc., user can not directly specify it via perf record. And as you showed below, perf-probe expresses there are 2 events on the probe point. So user is forced to aware of it.
Right.
Quoted 17 lines
Quoted 9 lines
# nm ./multi | grep foo 0000000000400530 t foo 0000000000400560 t foo# perf probe -x ./multi foo Added new events: probe_multi:foo (on foo in /home/hemant/work/linux/tools/perf/multi) probe_multi:foo_1 (on foo in /home/hemant/work/linux/tools/perf/multi)Quoted 8 lines
You can now use it in all perf tools, such as:
perf record -e probe_multi:foo_1 -aR sleep 1
My point being, the user can still know, if its shown that there are two or more probes being placed and the o/p of perf report/script shows that the probes are placed at two or more different addresses.
Quoted 6 lines
Not only the different address, but also they will see the different event names. That may be no good for making a script on it.
My point is, if the user only uses "perf record -e sdt_something:sdtevent", they will think that there is one event recorded. it can easily misleading them.
Ok. Makes sense. With a warning message then, we can make the user aware in this case.
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
To solve this issue, we need to introduce multiple SDTs on single ftrace event. Please read my comment on v3 patch (https://lkml.org/lkml/2015/8/15/52)
Ok. But, I think, for initial direct recording support, we can go with this IMHO.
So, at least this should be noticed to users carefully. (e.g. warn if there are more than two SDTs defined)
Ok. I have made the changes and also added a warning message if the user tries to record on an sdt event, which has multiple occurences with the same event and group name. I have sent a v2 for this patch.
Signature · 2 lines
Thanks, Hemant Kumar
Quoted 26 lines · Hemant Kumar
This patch adds support for directly recording SDT events which are present in the probe cache. This patch is based on current SDT enablement patchset (v5) by Masami :
https://lkml.org/lkml/2016/4/27/828
and it implements two points in the TODO list mentioned in the cover note :
"- (perf record) Support SDT event recording directly" "- (perf record) Try to unregister SDT events after record."Without this patch, we could probe into SDT events using "perf probe" and "perf record". With this patch, we can probe the SDT events directly using "perf record".
For example :
# perf list sdt // List the SDT events ... sdt_mysql:update__row__done [SDT event] sdt_mysql:update__row__start [SDT event] sdt_mysql:update__start [SDT event] sdt_python:function__entry [SDT event] sdt_python:function__return [SDT event] sdt_test:marker1 [SDT event] sdt_test:marker2 [SDT event] ...
Quoted 1 line
# perf record -e %sdt_test:marker1 -e %sdt_test:marker2 -a
Why do we need the '%'? Can't the "sdt_" prefix be sufficient? ie:
# perf record -e sdt_test:marker1 -e sdt_test:marker2 -a
I find it a bit weird to define it using %sdt_, but then use it using sdt_. I'd also be inclined to use it for probe creation, ie:
# perf probe -x /lib/libc-2.17.so sdt_libc:lll_lock_wait_private
That way, the user only learns one way to specify the probe, with the sdt_ prefix. It's fine if % existed too, but optional.
Quoted 11 lines
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 2.087 MB perf.data (22 samples) ]# perf script test_sdt 29230 [002] 405550.548017: sdt_test:marker1: (400534) test_sdt 29230 [002] 405550.548064: sdt_test:marker2: (40053f) test_sdt 29231 [002] 405550.962806: sdt_test:marker1: (400534) test_sdt 29231 [002] 405550.962841: sdt_test:marker2: (40053f) test_sdt 29232 [001] 405551.379327: sdt_test:marker1: (400534) ...
Quoted 9 lines
After invoking "perf record", behind the scenes, it checks whether the event specified is an SDT event using the flag '%'. After that, it does a lookup of the probe cache to find out the SDT event. If its not present, it throws an error. Otherwise, it goes on and writes the event into the
uprobe_eventsfile and sets up the probe event, trace events, etc and starts recording. It also maintains a list of the event names that were written touprobe_eventsfile. After finishing the record session, it removes the events from theuprobe_eventsfile using the maintained name list.
Does this support semaphore SDT probes (is-enabled)? Those need the semaphore incremented when enabled, then decremented when disabled.
Brendan
Quoted 27 lines · On Mon, 2 May 2016 11:19:34 -0700 Brendan Gregg <[email protected]>…
Quoted 26 lines · Hemant Kumar
This patch adds support for directly recording SDT events which are present in the probe cache. This patch is based on current SDT enablement patchset (v5) by Masami :
https://lkml.org/lkml/2016/4/27/828
and it implements two points in the TODO list mentioned in the cover note :
"- (perf record) Support SDT event recording directly" "- (perf record) Try to unregister SDT events after record."Without this patch, we could probe into SDT events using "perf probe" and "perf record". With this patch, we can probe the SDT events directly using "perf record".
For example :
# perf list sdt // List the SDT events ... sdt_mysql:update__row__done [SDT event] sdt_mysql:update__row__start [SDT event] sdt_mysql:update__start [SDT event] sdt_python:function__entry [SDT event] sdt_python:function__return [SDT event] sdt_test:marker1 [SDT event] sdt_test:marker2 [SDT event] ...
Quoted 5 lines
Quoted 1 line
# perf record -e %sdt_test:marker1 -e %sdt_test:marker2 -aWhy do we need the '%'? Can't the "
sdt_" prefix be sufficient? ie:# perf record -e sdt_test:marker1 -e sdt_test:marker2 -a
For the perf-record side, "sdt_test:marker1" gives just a normal tracepoint event name (which is common with probe events on ftrace/perftools). For example, if I add a probe event by perf probe, it is shown same as other tracepoint events. This means I can make "sdt_test:marker1" with other address in principle.
----
$ sudo ./perf probe -a "sdt_test:marker1=vmalloc" Added new event: sdt_test:marker1 (on vmalloc)
You can now use it in all perf tools, such as:
perf record -e sdt_test:marker1 -aR sleep 1
----
So, you can shot you feet, easily:)
One possible solution is reserving "sdt_" prefix for SDT, then we can avoid using "%" for that.
However, what I intended was more generic solution including probe-cache, so that user can freely replay on cached probes once the user defines a probe, even after rebooting the machine. Of course, we can search such events automatically if a user gives a non-existing event name.
Quoted 7 lines
I find it a bit weird to define it using %sdt_, but then use it using
sdt_. I'd also be inclined to use it for probe creation, ie:# perf probe -x /lib/libc-2.17.so sdt_libc:lll_lock_wait_privateThat way, the user only learns one way to specify the probe, with the
sdt_prefix. It's fine if % existed too, but optional.
OK, if we can see "sdt_" prefix on the first place, we can treat as there is "%" :)
Quoted 21 lines
Quoted 11 lines
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 2.087 MB perf.data (22 samples) ]# perf script test_sdt 29230 [002] 405550.548017: sdt_test:marker1: (400534) test_sdt 29230 [002] 405550.548064: sdt_test:marker2: (40053f) test_sdt 29231 [002] 405550.962806: sdt_test:marker1: (400534) test_sdt 29231 [002] 405550.962841: sdt_test:marker2: (40053f) test_sdt 29232 [001] 405551.379327: sdt_test:marker1: (400534) ...Quoted 9 lines
After invoking "perf record", behind the scenes, it checks whether the event specified is an SDT event using the flag '%'. After that, it does a lookup of the probe cache to find out the SDT event. If its not present, it throws an error. Otherwise, it goes on and writes the event into the
uprobe_eventsfile and sets up the probe event, trace events, etc and starts recording. It also maintains a list of the event names that were written touprobe_eventsfile. After finishing the record session, it removes the events from theuprobe_eventsfile using the maintained name list.
Quoted 2 lines
Does this support semaphore SDT probes (is-enabled)? Those need the semaphore incremented when enabled, then decremented when disabled.
No, not actually supported yet. Semaphore and SDT parameters will be supported afterwards.
Thank you!
Signature · 1 line
Masami Hiramatsu <[email protected]>