tracing: Unifying dynamic event interface
Subsystems (3)
Masami Hiramatsu
maintainerv2 cover tracing: Unifying dynamic event interface
Hi,
This is v2 series of unifying dynamic event interface on ftrace. Currently ftrace has 3 dynamic event interfaces, kprobes, uprobes and synthetic. This series unifies those dynamic event interfaces to "dynamic_events" so that we can add other dynamic events easily on same interface, e.g. function events.
The older interfaces are left on the tracefs for backward compatibility.
dynamic_events syntax has no difference from kprobe_events and uprobe_events. You can use same syntax for dynamic_events interface. For synthetic events, similar to the probe events, dynamic_events adds "s:[GROUP/]" prefix, where the "GROUP/" must be "synthetic/".
s:[synthetic/]<event-name> type arg [type arg]...
E.g.
$ echo 'wakeup_latency u64 lat pid_t pid char' > synthetic_events
is same as
$ echo 's:wakeup_latency u64 lat pid_t pid char' > dynamic_events
Or
$ echo 's:synthetic/wakeup_latency u64 lat pid_t pid char' > dynamic_events
This series modifies synthetic event interface behavior a bit, reorder lock dependency and related cleanups so that we can integrate the synthetic event to dynamic_events interface.
In this version, I changed the generic '!' erase command, which now supports entire line style like other interfaces. So you can delete events via dynamic_events as below
$ cat dynamic_events | while read line; \ do echo "!$line" >> dynamic_events; done
Also, the big change will be removing dyn_event_mutex and synth_event_mutex because all those parts are protected by event_mutex.
Changes from v2 are here;
New patches:
- Reorder event_mutex and synth_event_mutex to solve
AB-BA deadlock correctly. ([2/12])
- Simplify creation and deletion of synthetic event. ([3/12])
- Retern -ENOENT if there is no synthetic event when deleting ([4/12])
- Integrate similar probe argument parsers ([5/12])
- Use dyn_event framework for synthetic events ([9/12])
- Remove synth_event_mutex ([10/12])
- Remove unused APIs ([11/12])
Modified patches:
[6/12] - [8/12]
- Generalize delete event and export as dyn_event_release_all().
- Add match operation for find deleting event.
- Reorder event_mutex and dyn_event_mutex to solve lock dependency issue.
- Pass const char **argv for create operation and use -ECANCELED to signal for trying next dyn_event_operations.
- Remove dyn_event_mutex.
[12/12]
- Accept entire line, but instead of checking the given entire line strictly, simply checking the event and group name.
Tom, thanks for your Ack for v1 series. Since I changed many things from v1 (not only minor change), I decided to not add your Ack for this version. Anyway, what I've added in this version are related to synthetic events. I need your review for those. (especially removing synth_event_mutex)
You can try it from my git tree.
https://github.com/mhiramat/linux/tree/unify-dynamic-events-v2
Thank you,
---
Masami Hiramatsu (12):
tracing/uprobes: Add busy check when cleanup all uprobes
tracing: Lock event_mutex before synth_event_mutex
tracing: Simplify creation and deletion of synthetic event
tracing: Integrate similar probe argument parsers
tracing: Add unified dynamic event framework tracing/kprobes: Use dyn_event framework for kprobe events tracing/uprobes: Use dyn_event framework for uprobe events
tracing: Use dyn_event framework for synthetic events
tracing: Remove unneeded synth_event_mutex
tracing: Remove orphaned trace_add/remove_event_call functions
tracing: Add generic event-name based remove event method selftests/ftrace: Add testcases for dynamic event
Documentation/trace/kprobetrace.rst | 3 Documentation/trace/uprobetracer.rst | 4 include/linux/trace_events.h | 4 kernel/trace/Kconfig | 6 kernel/trace/Makefile | 1 kernel/trace/trace.c | 12 + kernel/trace/trace_dynevent.c | 217 ++++++++++++ kernel/trace/trace_dynevent.h | 119 +++++++ kernel/trace/trace_events.c | 12 - kernel/trace/trace_events_hist.c | 322 ++++++++++-------- kernel/trace/trace_kprobe.c | 357 ++++++++++---------- kernel/trace/trace_probe.c | 74 ++++ kernel/trace/trace_probe.h | 9 - kernel/trace/trace_uprobe.c | 305 ++++++++--------- .../ftrace/test.d/dynevent/add_remove_kprobe.tc | 30 ++ .../ftrace/test.d/dynevent/add_remove_synth.tc | 27 ++ .../ftrace/test.d/dynevent/clear_select_events.tc | 50 +++ .../ftrace/test.d/dynevent/generic_clear_event.tc | 49 +++ 18 files changed, 1094 insertions(+), 507 deletions(-) create mode 100644 kernel/trace/trace_dynevent.c create mode 100644 kernel/trace/trace_dynevent.h create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/add_remove_kprobe.tc create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/add_remove_synth.tc create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/clear_select_events.tc create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/generic_clear_event.tc
--
Masami Hiramatsu (Linaro) <[email protected]>
Masami Hiramatsu
maintainerPATCH v2 1/12 tracing/uprobes: Add busy check when cleanup all uprobes
Add a busy check loop in cleanup_all_probes() before trying to remove all events in uprobe_events as same as kprobe_events does.
Without this change, writing null to uprobe_events will try to remove events but if one of them is enabled, it stopped there but some of events are already cleared.
With this change, writing null to uprobe_events make sure all events are not enabled before removing events. So, it clears all events, or return an error (-EBUSY) with keeping all events.
--- kernel/trace/trace_uprobe.c | 7 +++++++ 1 file changed, 7 insertions(+)
kernel/trace/trace_uprobe.c +7 -0
@@ -587,12 +587,19 @@ static int cleanup_all_probes(void)int ret =0 ;mutex_lock (&uprobe_lock); +/* Ensure no probe is in use. */ +list_for_each_entry (tu, &uprobe_list, list) +if (trace_probe_is_enabled (&tu->tp)) { + ret = -EBUSY ; + goto end; + }while (!list_empty (&uprobe_list)) { tu = list_entry(uprobe_list.next, struct trace_uprobe, list); ret =unregister_trace_uprobe (tu);if (ret)break ; } +end:mutex_unlock (&uprobe_lock);return ret; }
Steven Rostedt
maintainerRe: [PATCH v2 01/12] tracing/uprobes: Add busy check when cleanup all uprobes
Quoted 4 lines · On Mon, 5 Nov 2018 18:00:15 +0900 Masami Hiramatsu <[email protected]> wrote:
Add a busy check loop in
cleanup_all_probes()before trying to remove all events inuprobe_eventsas same askprobe_eventsdoes.
Quoted 9 lines
Without this change, writing null to
uprobe_eventswill try to remove events but if one of them is enabled, it stopped there but some of events are already cleared.With this change, writing null to
uprobe_eventsmake sure all events are not enabled before removing events. So, it clears all events, or return an error (-EBUSY) with keeping all events.
Hmm, should this patch be marked as stable?
-- Steve
Quoted 29 lines
Signed-off-by Masami Hiramatsu <[email protected]>--- kernel/trace/trace_uprobe.c | 7 +++++++ 1 file changed, 7 insertions(+)kernel/trace/trace_uprobe.c +7
-0@@ -587,12 +587,19 @@ static int cleanup_all_probes(void)int ret =0 ;mutex_lock (&uprobe_lock); +/* Ensure no probe is in use. */ +list_for_each_entry (tu, &uprobe_list, list) +if (trace_probe_is_enabled (&tu->tp)) { + ret = -EBUSY ; + goto end; + }while (!list_empty (&uprobe_list)) { tu = list_entry(uprobe_list.next, struct trace_uprobe, list); ret =unregister_trace_uprobe (tu);if (ret)break ; } +end:mutex_unlock (&uprobe_lock);return ret; }
Masami Hiramatsu
maintainerRe: [PATCH v2 01/12] tracing/uprobes: Add busy check when cleanup all uprobes
Quoted 11 lines · On Tue, 4 Dec 2018 12:43:33 -0500 Steven Rostedt <[email protected]> wrote:
Quoted 8 lines · On Mon, 5 Nov 2018 18:00:15 +0900 Masami Hiramatsu <[email protected]> wrote:
Add a busy check loop in
cleanup_all_probes()before trying to remove all events inuprobe_eventsas same askprobe_eventsdoes.Without this change, writing null to
uprobe_eventswill try to remove events but if one of them is enabled, it stopped there but some of events are already cleared.
Quoted 7 lines
Quoted 5 lines
With this change, writing null to
uprobe_eventsmake sure all events are not enabled before removing events. So, it clears all events, or return an error (-EBUSY) with keeping all events.Hmm, should this patch be marked as stable?
Hmm, OK, let this go to stable. Since anyway, this will cause a wired result on uprobe_events from user point of view.
Thank you!
Quoted 33 lines
-- Steve
Quoted 29 lines
Signed-off-by Masami Hiramatsu <[email protected]>--- kernel/trace/trace_uprobe.c | 7 +++++++ 1 file changed, 7 insertions(+)kernel/trace/trace_uprobe.c +7
-0@@ -587,12 +587,19 @@ static int cleanup_all_probes(void)int ret =0 ;mutex_lock (&uprobe_lock); +/* Ensure no probe is in use. */ +list_for_each_entry (tu, &uprobe_list, list) +if (trace_probe_is_enabled (&tu->tp)) { + ret = -EBUSY ; + goto end; + }while (!list_empty (&uprobe_list)) { tu = list_entry(uprobe_list.next, struct trace_uprobe, list); ret =unregister_trace_uprobe (tu);if (ret)break ; } +end:mutex_unlock (&uprobe_lock);return ret; }
Signature · 1 line
Masami Hiramatsu <[email protected]>
Masami Hiramatsu
maintainerPATCH v2 2/12 tracing: Lock event_mutex before synth_event_mutex
In reply to Masami Hiramatsusynthetic event is using synth_event_mutex for protecting synth_event_list, and event_trigger_write() path acquires locks as below order.
event_trigger_write(event_mutex)
->trigger_process_regex(trigger_cmd_mutex)
->event_hist_trigger_func(synth_event_mutex)
On the other hand, synthetic event creation and deletion paths finally calls trace_add_event_call() and trace_remove_event_call() which acquires event_mutex. In that case, if we keep the synth_event_mutex locked while registering/unregistering synthetic events, its dependency will be inversed.
To avoid this issue, current synthetic event is using 2 phases process to create/delete events. For example, it searches existing event under synth_event_mutex to checking event-name conflict, and unlock synth_event_mutex, then register new event under event_mutex locked. Finally, it locks synth_event_mutex and tries to add the new event to the list. But it can introduce complexity and a chance of name conflict.
To solve this simpler, this introduces trace_add_event_call_nolock() and trace_remove_event_call_nolock() which don't acquires event_mutex inside. synthetic event can lock event_mutex before synth_event_mutex for solving lock dependency issue simpler.
--- include/linux/trace_events.h | 2 ++ kernel/trace/trace_events.c | 34 ++++++++++++++++++++++++++++------ kernel/trace/trace_events_hist.c | 24 ++++++++++-------------- 3 files changed, 40 insertions(+), 20 deletions(-)
include/linux/trace_events.h +2 -0
@@ -529,6 +529,8 @@ extern int trace_event_raw_init(struct trace_event_call *call);extern int trace_define_field (struct trace_event_call *call,const char *type,const char *name,int offset,int size,int is_signed,int filter_type); +extern int trace_add_event_call_nolock (struct trace_event_call *call); +extern int trace_remove_event_call_nolock (struct trace_event_call *call);extern int trace_add_event_call (struct trace_event_call *call);extern int trace_remove_event_call (struct trace_event_call *call);extern int trace_event_get_offsets (struct trace_event_call *call);
kernel/trace/trace_events.c +28 -6
@@ -2305,11 +2305,11 @@ __trace_early_add_new_event(struct trace_event_call *call,struct ftrace_module_file_ops ;static void __add_event_to_tracers (struct trace_event_call *call); -/* Add an additional event_call dynamically */ -int trace_add_event_call (struct trace_event_call *call) +int trace_add_event_call_nolock (struct trace_event_call *call) {int ret; -mutex_lock (&event_mutex); +lockdep_assert_held (&event_mutex); +mutex_lock (&trace_types_lock); ret =__register_event (call,NULL );
@@ -2317,6 +2317,16 @@ int trace_add_event_call(struct trace_event_call *call)__add_event_to_tracers (call);mutex_unlock (&trace_types_lock); +return ret; +} + +/* Add an additional event_call dynamically */ +int trace_add_event_call (struct trace_event_call *call) +{ +int ret; + +mutex_lock (&event_mutex); + ret =trace_add_event_call_nolock (call);mutex_unlock (&event_mutex);return ret; }
@@ -2366,17 +2376,29 @@ static int probe_remove_event_call(struct trace_event_call *call)return 0 ; } -/* Remove an event_call */ -int trace_remove_event_call (struct trace_event_call *call) +/* no event_mutex version */ +int trace_remove_event_call_nolock (struct trace_event_call *call) {int ret; -mutex_lock (&event_mutex); +lockdep_assert_held (&event_mutex); +mutex_lock (&trace_types_lock);down_write (&trace_event_sem); ret =probe_remove_event_call (call);up_write (&trace_event_sem);mutex_unlock (&trace_types_lock); + +return ret; +} + +/* Remove an event_call */ +int trace_remove_event_call (struct trace_event_call *call) +{ +int ret; + +mutex_lock (&event_mutex); + ret =trace_remove_event_call_nolock (call);mutex_unlock (&event_mutex);return ret;
kernel/trace/trace_events_hist.c +10 -14
@@ -912,7 +912,7 @@ static int register_synth_event(struct synth_event *event) call->data = event; call->tp = event->tp; - ret =trace_add_event_call (call); + ret =trace_add_event_call_nolock (call);if (ret) {pr_warn ("Failed to register synthetic event: %s\n" ,trace_event_name (call));
@@ -936,7 +936,7 @@ static int unregister_synth_event(struct synth_event *event)struct trace_event_call *call = &event->call;int ret; - ret =trace_remove_event_call (call); + ret =trace_remove_event_call_nolock (call);return ret; }
@@ -1013,12 +1013,10 @@ static void add_or_delete_synth_event(struct synth_event *event, int delete)if (delete)free_synth_event (event);else { -mutex_lock (&synth_event_mutex);if (!find_synth_event (event->name))list_add (&event->list, &synth_event_list);else free_synth_event (event); -mutex_unlock (&synth_event_mutex); } }
@@ -1030,6 +1028,7 @@ static int create_synth_event(int argc, char **argv)int i, consumed =0 , n_fields =0 , ret =0 ;char *name; +mutex_lock (&event_mutex);mutex_lock (&synth_event_mutex);/*
@@ -1102,8 +1101,6 @@ static int create_synth_event(int argc, char **argv) goto err; } out: -mutex_unlock (&synth_event_mutex); -if (event) {if (delete_event) { ret =unregister_synth_event (event);
@@ -1113,10 +1110,13 @@ static int create_synth_event(int argc, char **argv)add_or_delete_synth_event (event, ret); } } +mutex_unlock (&synth_event_mutex); +mutex_unlock (&event_mutex);return ret; err:mutex_unlock (&synth_event_mutex); +mutex_unlock (&event_mutex);for (i =0 ; i < n_fields; i++)free_synth_field (fields[i]);
@@ -1127,12 +1127,10 @@ static int create_synth_event(int argc, char **argv)static int release_all_synth_events (void ) { -struct list_head release_events;struct synth_event *event, *e;int ret =0 ; -INIT_LIST_HEAD (&release_events); - +mutex_lock (&event_mutex);mutex_lock (&synth_event_mutex);list_for_each_entry (event, &synth_event_list, list) {
@@ -1142,16 +1140,14 @@ static int release_all_synth_events(void) } } -list_splice_init (&event->list, &release_events); - -mutex_unlock (&synth_event_mutex); - -list_for_each_entry_safe (event, e, &release_events, list) { +list_for_each_entry_safe (event, e, &synth_event_list, list) {list_del (&event->list); ret =unregister_synth_event (event);add_or_delete_synth_event (event, !ret); } +mutex_unlock (&synth_event_mutex); +mutex_unlock (&event_mutex);return ret; }
Masami Hiramatsu
maintainerPATCH v2 3/12 tracing: Simplify creation and deletion of synthetic event
In reply to Masami HiramatsuSimplify creation and deletion code of synthetic event.
Since the event_mutex and synth_event_mutex ordering issue is gone, we can skip existing event check when adding or deleting event, and some redundant code in error path.
This changes release_all_synth_events() to abort the process when it hits any error and returns the error code. It succeeds only if it has no error.
--- kernel/trace/trace_events_hist.c | 53 +++++++++++++------------------------- 1 file changed, 18 insertions(+), 35 deletions(-)
kernel/trace/trace_events_hist.c +18 -35
@@ -1008,18 +1008,6 @@ struct hist_var_data {struct hist_trigger_data *hist_data; }; -static void add_or_delete_synth_event (struct synth_event *event,int delete) -{ -if (delete) -free_synth_event (event); -else { -if (!find_synth_event (event->name)) -list_add (&event->list, &synth_event_list); -else -free_synth_event (event); - } -} -static int create_synth_event (int argc,char **argv) {struct synth_field *field, *fields[SYNTH_FIELDS_MAX ];
@@ -1052,15 +1040,16 @@ static int create_synth_event(int argc, char **argv)if (event) {if (delete_event) {if (event->ref) { - event =NULL ; ret = -EBUSY ; goto out; } -list_del (&event->list); - goto out; - } - event =NULL ; - ret = -EEXIST ; + ret =unregister_synth_event (event); +if (!ret) { +list_del (&event->list); +free_synth_event (event); + } + }else + ret = -EEXIST ; goto out; }else if (delete_event) { ret = -ENOENT ;
@@ -1100,29 +1089,21 @@ static int create_synth_event(int argc, char **argv) event =NULL ; goto err; } + ret =register_synth_event (event); +if (!ret) +list_add (&event->list, &synth_event_list); +else +free_synth_event (event); out: -if (event) { -if (delete_event) { - ret =unregister_synth_event (event); -add_or_delete_synth_event (event, !ret); - }else { - ret =register_synth_event (event); -add_or_delete_synth_event (event, ret); - } - }mutex_unlock (&synth_event_mutex);mutex_unlock (&event_mutex);return ret; err: -mutex_unlock (&synth_event_mutex); -mutex_unlock (&event_mutex); -for (i =0 ; i < n_fields; i++)free_synth_field (fields[i]); -free_synth_event (event); -return ret; + goto out; }static int release_all_synth_events (void )
@@ -1141,10 +1122,12 @@ static int release_all_synth_events(void) }list_for_each_entry_safe (event, e, &synth_event_list, list) { -list_del (&event->list); - ret =unregister_synth_event (event); -add_or_delete_synth_event (event, !ret); +if (!ret) { +list_del (&event->list); +free_synth_event (event); + }else +break ; }mutex_unlock (&synth_event_mutex);mutex_unlock (&event_mutex);
Masami Hiramatsu
maintainerPATCH v2 4/12 tracing: Integrate similar probe argument parsers
In reply to Masami HiramatsuIntegrate similar argument parsers for kprobes and uprobes events into traceprobe_parse_probe_arg().
--- kernel/trace/trace_kprobe.c | 48 ++----------------------------------------- kernel/trace/trace_probe.c | 47 +++++++++++++++++++++++++++++++++++++++--- kernel/trace/trace_probe.h | 7 ++---- kernel/trace/trace_uprobe.c | 44 ++------------------------------------- 4 files changed, 50 insertions(+), 96 deletions(-)
kernel/trace/trace_kprobe.c +2 -46
@@ -548,7 +548,6 @@ static int create_trace_kprobe(int argc, char **argv)bool is_return = false, is_delete = false;char *symbol =NULL , *event =NULL , *group =NULL ;int maxactive =0 ; -char *arg;long offset =0 ;void *addr =NULL ;char buf[MAX_EVENT_NAME_LEN ];
@@ -676,53 +675,10 @@ static int create_trace_kprobe(int argc, char **argv) }/* parse arguments */ - ret =0 ;for (i =0 ; i < argc && i <MAX_TRACE_ARGS ; i++) { -struct probe_arg *parg = &tk->tp.args[i]; - -/* Increment count for freeing args in error case */ - tk->tp.nr_args++; - -/* Parse argument name */ - arg =strchr (argv[i],'=' ); -if (arg) { - *arg++ ='\0' ; - parg->name =kstrdup (argv[i],GFP_KERNEL ); - }else { - arg = argv[i]; -/* If argument name is omitted, set "argN" */ -snprintf (buf,MAX_EVENT_NAME_LEN ,"arg%d" , i +1 ); - parg->name =kstrdup (buf,GFP_KERNEL ); - } - -if (!parg->name) { -pr_info ("Failed to allocate argument[%d] name.\n" , i); - ret = -ENOMEM ; - goto error; - } - -if (!is_good_name (parg->name)) { -pr_info ("Invalid argument[%d] name: %s\n" , - i, parg->name); - ret = -EINVAL ; - goto error; - } - -if (traceprobe_conflict_field_name (parg->name, - tk->tp.args, i)) { -pr_info ("Argument[%d] name '%s' conflicts with " -"another field.\n" , i, argv[i]); - ret = -EINVAL ; - goto error; - } - -/* Parse fetch argument */ - ret =traceprobe_parse_probe_arg (arg, &tk->tp.size, parg, - flags); -if (ret) { -pr_info ("Parse error at argument[%d]. (%d)\n" , i, ret); + ret =traceprobe_parse_probe_arg (&tk->tp, i, argv[i], flags); +if (ret) goto error; - } } ret =register_trace_kprobe (tk);
kernel/trace/trace_probe.c +44 -3
65 lines not on this page · raw message
kernel/trace/trace_probe.h +2 -5
@@ -272,11 +272,8 @@ find_event_file_link(struct trace_probe *tp, struct trace_event_file *file)#define TPARG_FL_FENTRY BIT(2)#define TPARG_FL_MASK GENMASK(2, 0) -extern int traceprobe_parse_probe_arg (char *arg,ssize_t *size, -struct probe_arg *parg,unsigned int flags); - -extern int traceprobe_conflict_field_name (const char *name, -struct probe_arg *args,int narg); +extern int traceprobe_parse_probe_arg (struct trace_probe *tp,int i, +char *arg,unsigned int flags);extern int traceprobe_update_arg (struct probe_arg *arg);extern void traceprobe_free_probe_arg (struct probe_arg *arg);
kernel/trace/trace_uprobe.c +2 -42
53 lines not on this page · raw message
Masami Hiramatsu
maintainerPATCH v2 5/12 tracing: Add unified dynamic event framework
In reply to Masami HiramatsuAdd unified dynamic event framework for ftrace kprobes, uprobes and synthetic events. Those dynamic events can be co-exist on same file because those syntax doesn't over-wrapped.
This introduces a framework part which provides a unified tracefs interface and operations.
---
Changes in v2:
- Fix to lock dyn_event_mutex when freeing all events.
- Generalize and export dyn_event_release_all().
- To fix dependency issue, lock event_mutex before dyn_event_mutex.
- Separate create and delete operation.
- If create operation returns -ECANCELED, try next operation.
- Pass const argv to create operation for safety.
- Add .match operation and generic delete API.
- Add precise description for data structures.
- Remove dyn_event_mutex, use event_mutex instead.
--- kernel/trace/Kconfig | 3 + kernel/trace/Makefile | 1 kernel/trace/trace.c | 4 + kernel/trace/trace_dynevent.c | 210 +++++++++++++++++++++++++++++++++++++++++ kernel/trace/trace_dynevent.h | 119 +++++++++++++++++++++++ 5 files changed, 337 insertions(+) create mode 100644 kernel/trace/trace_dynevent.c create mode 100644 kernel/trace/trace_dynevent.h
kernel/trace/Kconfig +3 -0
@@ -518,6 +518,9 @@ config BPF_EVENTS help This allows the user to attach BPF programs to kprobe events. +config DYNAMIC_EVENTS + def_bool n + config PROBE_EVENTS def_bool n
kernel/trace/Makefile +1 -0
@@ -78,6 +78,7 @@ endif ifeq ($(CONFIG_TRACING),y) obj-$(CONFIG_KGDB_KDB) += trace_kdb.o endif +obj-$(CONFIG_DYNAMIC_EVENTS) += trace_dynevent.o obj-$(CONFIG_PROBE_EVENTS) += trace_probe.o obj-$(CONFIG_UPROBE_EVENTS) += trace_uprobe.o
kernel/trace/trace.c +4 -0
@@ -4604,6 +4604,10 @@ static const char readme_msg[] = "\t\t\t traces\n"#endif #endif /* CONFIG_STACK_TRACER */ +#ifdef CONFIG_DYNAMIC_EVENTS +" dynamic_events\t\t- Add/remove/show the generic dynamic events\n" + "\t\t\t Write into this file to define/undefine new trace events.\n" +#endif #ifdef CONFIG_KPROBE_EVENTS " kprobe_events\t\t- Add/remove/show the kernel dynamic events\n" "\t\t\t Write into this file to define/undefine new trace events.\n"
kernel/trace/trace_dynevent.c new file +210 -0
210 lines not on this page · raw message
kernel/trace/trace_dynevent.h new file +119 -0
119 lines not on this page · raw message
Masami Hiramatsu
maintainerPATCH v2 6/12 tracing/kprobes: Use dyn_event framework for kprobe events
In reply to Masami HiramatsuUse dyn_event framework for kprobe events. This shows kprobe events on "tracing/dynamic_events" file.
User can also define new events via tracing/dynamic_events.
---
Changes in v2:
- Use dyn_events_release_all() for clearing events.
- Use nolock event_call register/unregister and lock event_mutex before dyn_event_mutex to avoid lock dependency error.
- Check probe cleanup result in self-check.
- Rewrite trace_kprobe_create not to destroy arguments.
- Add match operation and new APIs for deleting event.
- Return -ECANCEL if given definition is not for kprobes.
- Remove unused for_each_trace_kprobe_safe.
--- Documentation/trace/kprobetrace.rst | 3 kernel/trace/Kconfig | 1 kernel/trace/trace_kprobe.c | 319 +++++++++++++++++++---------------- kernel/trace/trace_probe.c | 27 +++ kernel/trace/trace_probe.h | 2 5 files changed, 207 insertions(+), 145 deletions(-)
Documentation/trace/kprobetrace.rst +3 -0
@@ -20,6 +20,9 @@ current_tracer. Instead of that, add probe points via /sys/kernel/debug/tracing/kprobe_events, and enable it via /sys/kernel/debug/tracing/events/kprobes/<EVENT>/enable. +You can also use /sys/kernel/debug/tracing/dynamic_events instead of +kprobe_events. That interface will provide unified access to other +dynamic events too. Synopsis of kprobe_events -------------------------
kernel/trace/Kconfig +1 -0
@@ -461,6 +461,7 @@ config KPROBE_EVENTS bool "Enable kprobes-based dynamic events" select TRACING select PROBE_EVENTS + select DYNAMIC_EVENTS default y help This allows the user to add tracing events (similar to tracepoints)
kernel/trace/trace_kprobe.c +174 -145
591 lines not on this page · raw message
kernel/trace/trace_probe.c +27 -0
@@ -154,6 +154,33 @@ int traceprobe_split_symbol_offset(char *symbol, long *offset)return 0 ; } +/* @buf must has MAX_EVENT_NAME_LEN size */ +int traceprobe_parse_event_name (const char **pevent,const char **pgroup, +char *buf) +{ +const char *slash, *event = *pevent; + + slash =strchr (event,'/' ); +if (slash) { +if (slash == event) { +pr_info ("Group name is not specified\n" ); +return -EINVAL ; + } +if (slash - event +1 >MAX_EVENT_NAME_LEN ) { +pr_info ("Group name is too long\n" ); +return -E2BIG ; + } +strlcpy (buf, event, slash - event +1 ); + *pgroup = buf; + *pevent = slash +1 ; + } +if (strlen (event) ==0 ) { +pr_info ("Event name is not specified\n" ); +return -EINVAL ; + } +return 0 ; +} +#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) static int parse_probe_vars(char *arg, const struct fetch_type *t,
kernel/trace/trace_probe.h +2 -0
@@ -279,6 +279,8 @@ extern int traceprobe_update_arg(struct probe_arg *arg);extern void traceprobe_free_probe_arg (struct probe_arg *arg);extern int traceprobe_split_symbol_offset (char *symbol,long *offset); +extern int traceprobe_parse_event_name (const char **pevent, +const char **pgroup,char *buf);extern int traceprobe_set_print_fmt (struct trace_probe *tp,bool is_return);
Masami Hiramatsu
maintainerPATCH v2 7/12 tracing/uprobes: Use dyn_event framework for uprobe events
In reply to Masami HiramatsuUse dyn_event framework for uprobe events. This shows uprobe events on "dynamic_events" file.
User can also define new uprobe events via dynamic_events.
---
Changes in v2:
- Use dyn_events_release_all() for clearing events.
- Use nolock event_call register/unregister and lock event_mutex before dyn_event_mutex to avoid lock dependency error.
- Select CONFIG_DYNAMIC_EVENTS in Kconfig
- Add match operation and use new API for event deletion
- Return -ECANCELED if given event is not for uprobe.
- Remove unused for_each_trace_uprobe_safe.
--- Documentation/trace/uprobetracer.rst | 4 kernel/trace/Kconfig | 1 kernel/trace/trace_uprobe.c | 278 ++++++++++++++++++---------------- 3 files changed, 153 insertions(+), 130 deletions(-)
Documentation/trace/uprobetracer.rst +4 -0
@@ -18,6 +18,10 @@ current_tracer. Instead of that, add probe points via However unlike kprobe-event tracer, the uprobe event interface expects the user to calculate the offset of the probepoint in the object. +You can also use /sys/kernel/debug/tracing/dynamic_events instead of +uprobe_events. That interface will provide unified access to other +dynamic events too. + Synopsis of uprobe_tracer ------------------------- ::
kernel/trace/Kconfig +1 -0
@@ -501,6 +501,7 @@ config UPROBE_EVENTS depends on PERF_EVENTS select UPROBES select PROBE_EVENTS + select DYNAMIC_EVENTS select TRACING default y help
kernel/trace/trace_uprobe.c +148 -130
498 lines not on this page · raw message
Masami Hiramatsu
maintainerPATCH v2 8/12 tracing: Use dyn_event framework for synthetic events
In reply to Masami HiramatsuUse dyn_event framework for synthetic events. This shows synthetic events on "tracing/dynamic_events" file in addition to tracing/synthetic_events interface.
User can also define new events via tracing/dynamic_events with "s:" prefix. So, the new syntax is below;
s:[synthetic/]EVENT_NAME TYPE ARG; [TYPE ARG;]...
To remove events via tracing/dynamic_events, you can use "-:" prefix as same as other events.
--- kernel/trace/Kconfig | 1 kernel/trace/trace.c | 8 + kernel/trace/trace_events_hist.c | 265 ++++++++++++++++++++++++-------------- 3 files changed, 176 insertions(+), 98 deletions(-)
kernel/trace/Kconfig +1 -0
@@ -635,6 +635,7 @@ config HIST_TRIGGERS depends on ARCH_HAVE_NMI_SAFE_CMPXCHG select TRACING_MAP select TRACING + select DYNAMIC_EVENTS default n help Hist triggers allow one or more arbitrary trace event fields
kernel/trace/trace.c +8 -0
@@ -4620,6 +4620,9 @@ static const char readme_msg[] = "\t accepts: event-definitions (one definition per line)\n" "\t Format: p[:[<group>/]<event>] <place> [<args>]\n" "\t r[maxactive][:[<group>/]<event>] <place> [<args>]\n" +#ifdef CONFIG_HIST_TRIGGERS + "\t s:[synthetic/]<event> <field> [<field>]\n" +#endif "\t -:[<group>/]<event>\n"#ifdef CONFIG_KPROBE_EVENTS "\t place: [<module>:]<symbol>[+<offset>]|<memaddr>\n"
@@ -4638,6 +4641,11 @@ static const char readme_msg[] ="\t type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string, symbol,\n" "\t b<bit-width>@<bit-offset>/<container-size>,\n" "\t <type>\\[<array-size>\\]\n" +#ifdef CONFIG_HIST_TRIGGERS +"\t field: <stype> <name>;\n" +"\t stype: u8/u16/u32/u64, s8/s16/s32/s64, pid_t,\n" + "\t [unsigned] char/int/long\n" +#endif #endif " events/\t\t- Directory containing all trace event subsystems:\n" " enable\t\t- Write 0/1 to enable/disable tracing of all events\n"
kernel/trace/trace_events_hist.c +167 -98
441 lines not on this page · raw message
Masami Hiramatsu
maintainerPATCH v2 9/12 tracing: Remove unneeded synth_event_mutex
In reply to Masami HiramatsuRmove unneeded synth_event_mutex. This mutex protects the reference count in synth_event, however, those operational points are already protected by event_mutex.
1. In __create_synth_event() and create_or_delete_synth_event(), those synth_event_mutex clearly obtained right after event_mutex.
2. event_hist_trigger_func() is trigger_hist_cmd.func() which is called by trigger_process_regex(), which is a part of event_trigger_regex_write() and this function takes event_mutex.
3. hist_unreg_all() is trigger_hist_cmd.unreg_all() which is called by event_trigger_regex_open() and it takes event_mutex.
4. onmatch_destroy() and onmatch_create() have long call tree, but both are finally invoked from event_trigger_regex_write() and event_trace_del_tracer(), former takes event_mutex, and latter ensures called under event_mutex locked.
Finally, I ensured there is no resource conflict. For safety, I added lockdep_assert_held(&event_mutex) for each function.
--- kernel/trace/trace_events_hist.c | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-)
kernel/trace/trace_events_hist.c +7 -23
@@ -444,8 +444,6 @@ static bool have_hist_err(void)return false; } -static DEFINE_MUTEX (synth_event_mutex); -struct synth_trace_event {struct trace_entry ent;u64 fields[];
@@ -1077,7 +1075,6 @@ static int __create_synth_event(int argc, const char *name, const char **argv)return -EINVAL ;mutex_lock (&event_mutex); -mutex_lock (&synth_event_mutex); event =find_synth_event (name);if (event) {
@@ -1119,7 +1116,6 @@ static int __create_synth_event(int argc, const char *name, const char **argv)else free_synth_event (event); out: -mutex_unlock (&synth_event_mutex);mutex_unlock (&event_mutex);return ret;
@@ -1139,7 +1135,6 @@ static int create_or_delete_synth_event(int argc, char **argv)/* trace_run_command() ensures argc != 0 */ if (name[0 ] =='!' ) {mutex_lock (&event_mutex); -mutex_lock (&synth_event_mutex); event =find_synth_event (name +1 );if (event) {if (event->ref)
@@ -1153,7 +1148,6 @@ static int create_or_delete_synth_event(int argc, char **argv) } }else ret = -ENOENT ; -mutex_unlock (&synth_event_mutex);mutex_unlock (&event_mutex);return ret; }
@@ -3535,7 +3529,7 @@ static void onmatch_destroy(struct action_data *data) {unsigned int i; -mutex_lock (&synth_event_mutex); +lockdep_assert_held (&event_mutex);kfree (data->onmatch.match_event);kfree (data->onmatch.match_event_system);
@@ -3548,8 +3542,6 @@ static void onmatch_destroy(struct action_data *data) data->onmatch.synth_event->ref--;kfree (data); - -mutex_unlock (&synth_event_mutex); }static void destroy_field_var (struct field_var *field_var)
@@ -3700,15 +3692,14 @@ static int onmatch_create(struct hist_trigger_data *hist_data,struct synth_event *event;int ret =0 ; -mutex_lock (&synth_event_mutex); +lockdep_assert_held (&event_mutex); + event =find_synth_event (data->onmatch.synth_event_name);if (!event) {hist_err ("onmatch: Couldn't find synthetic event: " , data->onmatch.synth_event_name); -mutex_unlock (&synth_event_mutex);return -EINVAL ; } event->ref++; -mutex_unlock (&synth_event_mutex); var_ref_idx = hist_data->n_var_refs;
@@ -3782,9 +3773,7 @@ static int onmatch_create(struct hist_trigger_data *hist_data, out:return ret; err: -mutex_lock (&synth_event_mutex); event->ref--; -mutex_unlock (&synth_event_mutex); goto out; }
@@ -5492,6 +5481,8 @@ static void hist_unreg_all(struct trace_event_file *file)struct synth_event *se;const char *se_name; +lockdep_assert_held (&event_mutex); +if (hist_file_check_refs (file))return ;
@@ -5501,12 +5492,10 @@ static void hist_unreg_all(struct trace_event_file *file)list_del_rcu (&test->list);trace_event_trigger_enable_disable (file,0 ); -mutex_lock (&synth_event_mutex); se_name =trace_event_name (file->event_call); se =find_synth_event (se_name);if (se) se->ref--; -mutex_unlock (&synth_event_mutex);update_cond_flag (file);if (hist_data->enable_timestamps)
@@ -5532,6 +5521,8 @@ static int event_hist_trigger_func(struct event_command *cmd_ops,char *trigger, *p;int ret =0 ; +lockdep_assert_held (&event_mutex); +if (glob &&strlen (glob)) {last_cmd_set (param);hist_err_clear ();
@@ -5622,14 +5613,10 @@ static int event_hist_trigger_func(struct event_command *cmd_ops, } cmd_ops->unreg (glob+1 , trigger_ops, trigger_data, file); - -mutex_lock (&synth_event_mutex); se_name =trace_event_name (file->event_call); se =find_synth_event (se_name);if (se) se->ref--; -mutex_unlock (&synth_event_mutex); - ret =0 ; goto out_free; }
@@ -5665,13 +5652,10 @@ static int event_hist_trigger_func(struct event_command *cmd_ops,if (ret) goto out_unreg; -mutex_lock (&synth_event_mutex); se_name =trace_event_name (file->event_call); se =find_synth_event (se_name);if (se) se->ref++; -mutex_unlock (&synth_event_mutex); -/* Just return zero, not the number of registered triggers */ ret =0 ; out:
Masami Hiramatsu
maintainerPATCH v2 10/12 tracing: Remove orphaned trace_add/remove_event_call functions
In reply to Masami HiramatsuRemove trace_add_event_call() and trace_remove_event_call() functions since those are not used anymore.
--- include/linux/trace_events.h | 2 -- kernel/trace/trace_events.c | 26 ++------------------------ 2 files changed, 2 insertions(+), 26 deletions(-)
include/linux/trace_events.h +0 -2
@@ -531,8 +531,6 @@ extern int trace_define_field(struct trace_event_call *call, const char *type, int is_signed, int filter_type);extern int trace_add_event_call_nolock (struct trace_event_call *call);extern int trace_remove_event_call_nolock (struct trace_event_call *call); -extern int trace_add_event_call (struct trace_event_call *call); -extern int trace_remove_event_call (struct trace_event_call *call);extern int trace_event_get_offsets (struct trace_event_call *call);#define is_signed_type (type) (((type)(-1)) < (type)1)
kernel/trace/trace_events.c +2 -24
@@ -2305,6 +2305,7 @@ __trace_early_add_new_event(struct trace_event_call *call,struct ftrace_module_file_ops ;static void __add_event_to_tracers (struct trace_event_call *call); +/* Add an additional event_call dynamically */ int trace_add_event_call_nolock (struct trace_event_call *call) {int ret;
@@ -2320,17 +2321,6 @@ int trace_add_event_call_nolock(struct trace_event_call *call)return ret; } -/* Add an additional event_call dynamically */ -int trace_add_event_call (struct trace_event_call *call) -{ -int ret; - -mutex_lock (&event_mutex); - ret =trace_add_event_call_nolock (call); -mutex_unlock (&event_mutex); -return ret; -} -/* * Must be called under locking of trace_types_lock, event_mutex and * trace_event_sem.
@@ -2376,7 +2366,7 @@ static int probe_remove_event_call(struct trace_event_call *call)return 0 ; } -/* no event_mutex version */ +/* Remove an event_call */ int trace_remove_event_call_nolock (struct trace_event_call *call) {int ret;
@@ -2392,18 +2382,6 @@ int trace_remove_event_call_nolock(struct trace_event_call *call)return ret; } -/* Remove an event_call */ -int trace_remove_event_call (struct trace_event_call *call) -{ -int ret; - -mutex_lock (&event_mutex); - ret =trace_remove_event_call_nolock (call); -mutex_unlock (&event_mutex); - -return ret; -} -#define for_each_event (event, start, end) \ for (event = start; \ (unsigned long)event < (unsigned long)end; \
Steven Rostedt
maintainerRe: [PATCH v2 10/12] tracing: Remove orphaned trace_add/remove_event_call functions
Quoted 4 lines · On Mon, 5 Nov 2018 18:04:29 +0900 Masami Hiramatsu <[email protected]> wrote:
Remove
trace_add_event_call()andtrace_remove_event_call()functions since those are not used anymore.Signed-off-by Masami Hiramatsu <[email protected]>
Hi Masami,
I've applied the series locally (need to test it) except for this patch. Honestly, I hate the "_nolock" name, and it makes no sense when
1) they still grab locks
2) there's no version without "_nolock"
I added this patch in its place:
-- Steve
From: "Steven Rostedt (VMware)" <[email protected]>
Date: Tue, 4 Dec 2018 13:35:45 -0500
Subject: [PATCH] tracing: Consolidate trace_add/remove_event_call back to the
nolock functions
The trace_add/remove_event_call_nolock() functions were added to allow the tace_add/remove_event_call() code be called when the event_mutex lock was already taken. Now that all callers are done within the event_mutex, there's no reason to have two different interfaces.
Remove the current wrapper trace_add/remove_event_call()s and rename the _nolock versions back to the original names.
--- include/linux/trace_events.h | 2 -- kernel/trace/trace_events.c | 30 ++++-------------------------- kernel/trace/trace_events_hist.c | 6 +++--- kernel/trace/trace_kprobe.c | 4 ++-- kernel/trace/trace_uprobe.c | 4 ++-- 5 files changed, 11 insertions(+), 35 deletions(-)
include/linux/trace_events.h +0 -2
@@ -529,8 +529,6 @@ extern int trace_event_raw_init(struct trace_event_call *call);extern int trace_define_field (struct trace_event_call *call,const char *type,const char *name,int offset,int size,int is_signed,int filter_type); -extern int trace_add_event_call_nolock (struct trace_event_call *call); -extern int trace_remove_event_call_nolock (struct trace_event_call *call);extern int trace_add_event_call (struct trace_event_call *call);extern int trace_remove_event_call (struct trace_event_call *call);extern int trace_event_get_offsets (struct trace_event_call *call);
kernel/trace/trace_events.c +4 -26
@@ -2305,7 +2305,8 @@ __trace_early_add_new_event(struct trace_event_call *call,struct ftrace_module_file_ops ;static void __add_event_to_tracers (struct trace_event_call *call); -int trace_add_event_call_nolock (struct trace_event_call *call) +/* Add an additional event_call dynamically */ +int trace_add_event_call (struct trace_event_call *call) {int ret;lockdep_assert_held (&event_mutex);
@@ -2320,17 +2321,6 @@ int trace_add_event_call_nolock(struct trace_event_call *call)return ret; } -/* Add an additional event_call dynamically */ -int trace_add_event_call (struct trace_event_call *call) -{ -int ret; - -mutex_lock (&event_mutex); - ret =trace_add_event_call_nolock (call); -mutex_unlock (&event_mutex); -return ret; -} -/* * Must be called under locking of trace_types_lock, event_mutex and * trace_event_sem.
@@ -2376,8 +2366,8 @@ static int probe_remove_event_call(struct trace_event_call *call)return 0 ; } -/* no event_mutex version */ -int trace_remove_event_call_nolock (struct trace_event_call *call) +/* Remove an event_call */ +int trace_remove_event_call (struct trace_event_call *call) {int ret;
@@ -2392,18 +2382,6 @@ int trace_remove_event_call_nolock(struct trace_event_call *call)return ret; } -/* Remove an event_call */ -int trace_remove_event_call (struct trace_event_call *call) -{ -int ret; - -mutex_lock (&event_mutex); - ret =trace_remove_event_call_nolock (call); -mutex_unlock (&event_mutex); - -return ret; -} -#define for_each_event (event, start, end) \ for (event = start; \ (unsigned long)event < (unsigned long)end; \
kernel/trace/trace_events_hist.c +3 -3
@@ -960,7 +960,7 @@ static int register_synth_event(struct synth_event *event) call->data = event; call->tp = event->tp; - ret =trace_add_event_call_nolock (call); + ret =trace_add_event_call (call);if (ret) {pr_warn ("Failed to register synthetic event: %s\n" ,trace_event_name (call));
@@ -969,7 +969,7 @@ static int register_synth_event(struct synth_event *event) ret =set_synth_event_print_fmt (call);if (ret <0 ) { -trace_remove_event_call_nolock (call); +trace_remove_event_call (call); goto err; } out:
@@ -984,7 +984,7 @@ static int unregister_synth_event(struct synth_event *event)struct trace_event_call *call = &event->call;int ret; - ret =trace_remove_event_call_nolock (call); + ret =trace_remove_event_call (call);return ret; }
kernel/trace/trace_kprobe.c +2 -2
@@ -1353,7 +1353,7 @@ static int register_kprobe_event(struct trace_kprobe *tk)kfree (call->print_fmt);return -ENODEV ; } - ret =trace_add_event_call_nolock (call); + ret =trace_add_event_call (call);if (ret) {pr_info ("Failed to register kprobe event: %s\n" ,trace_event_name (call));
@@ -1368,7 +1368,7 @@ static int unregister_kprobe_event(struct trace_kprobe *tk)int ret;/* tp->event is unregistered in trace_remove_event_call() */ - ret =trace_remove_event_call_nolock (&tk->tp.call); + ret =trace_remove_event_call (&tk->tp.call);if (!ret)kfree (tk->tp.call.print_fmt);return ret;
kernel/trace/trace_uprobe.c +2 -2
@@ -1320,7 +1320,7 @@ static int register_uprobe_event(struct trace_uprobe *tu)return -ENODEV ; } - ret =trace_add_event_call_nolock (call); + ret =trace_add_event_call (call);if (ret) { pr_info("Failed to register uprobe event: %s\n",
@@ -1337,7 +1337,7 @@ static int unregister_uprobe_event(struct trace_uprobe *tu)int ret;/* tu->event is unregistered in trace_remove_event_call() */ - ret =trace_remove_event_call_nolock (&tu->tp.call); + ret =trace_remove_event_call (&tu->tp.call);if (ret)return ret;kfree (tu->tp.call.print_fmt);
Signature · 1 line
2.19.2
Re: [PATCH v2 10/12] tracing: Remove orphaned trace_add/remove_event_call functions
Quoted 8 lines · On Tue, 4 Dec 2018 13:51:20 -0500 Steven Rostedt <[email protected]> wrote:
Quoted 4 lines · On Mon, 5 Nov 2018 18:04:29 +0900 Masami Hiramatsu <[email protected]> wrote:
Remove
trace_add_event_call()andtrace_remove_event_call()functions since those are not used anymore.Signed-off-by Masami Hiramatsu <[email protected]>
Quoted 7 lines
Hi Masami,
I've applied the series locally (need to test it) except for this patch. Honestly, I hate the "
_nolock" name, and it makes no sense when1) they still grab locks
2) there's no version without "_nolock"
Agreed.
Quoted 2 lines
I added this patch in its place:
That looks good to me too. I thought to add similar patch, but just waited for the comment.
Thank you!
Quoted 180 lines
-- Steve
From: "Steven Rostedt (VMware)" <[email protected]>
Date: Tue, 4 Dec 2018 13:35:45 -0500
Subject: [PATCH] tracing: Consolidate trace_add/remove_event_call back to the
nolock functionsThe trace_add/remove_event_call_nolock() functions were added to allow the tace_add/remove_event_call() code be called when the
event_mutexlock was already taken. Now that all callers are done within theevent_mutex, there's no reason to have two different interfaces.Remove the current wrapper trace_add/remove_event_call()s and rename the
_nolockversions back to the original names.Signed-off-by Steven Rostedt (VMware) <[email protected]>--- include/linux/trace_events.h | 2 -- kernel/trace/trace_events.c | 30 ++++-------------------------- kernel/trace/trace_events_hist.c | 6 +++--- kernel/trace/trace_kprobe.c | 4 ++-- kernel/trace/trace_uprobe.c | 4 ++-- 5 files changed, 11 insertions(+), 35 deletions(-)include/linux/trace_events.h +0
-2@@ -529,8 +529,6 @@ extern int trace_event_raw_init(struct trace_event_call *call);extern int trace_define_field (struct trace_event_call *call,const char *type,const char *name,int offset,int size,int is_signed,int filter_type); -extern int trace_add_event_call_nolock (struct trace_event_call *call); -extern int trace_remove_event_call_nolock (struct trace_event_call *call);extern int trace_add_event_call (struct trace_event_call *call);extern int trace_remove_event_call (struct trace_event_call *call);extern int trace_event_get_offsets (struct trace_event_call *call);kernel/trace/trace_events.c +4
-26@@ -2305,7 +2305,8 @@ __trace_early_add_new_event(struct trace_event_call *call,struct ftrace_module_file_ops ;static void __add_event_to_tracers (struct trace_event_call *call); -int trace_add_event_call_nolock (struct trace_event_call *call) +/* Add an additional event_call dynamically */ +int trace_add_event_call (struct trace_event_call *call) {int ret;lockdep_assert_held (&event_mutex);@@ -2320,17 +2321,6 @@ int trace_add_event_call_nolock(struct trace_event_call *call)return ret; } -/* Add an additional event_call dynamically */ -int trace_add_event_call (struct trace_event_call *call) -{ -int ret; - -mutex_lock (&event_mutex); - ret =trace_add_event_call_nolock (call); -mutex_unlock (&event_mutex); -return ret; -} -/* * Must be called under locking of trace_types_lock, event_mutex and * trace_event_sem. @@ -2376,8 +2366,8 @@ static int probe_remove_event_call(struct trace_event_call *call)return 0 ; } -/* no event_mutex version */ -int trace_remove_event_call_nolock (struct trace_event_call *call) +/* Remove an event_call */ +int trace_remove_event_call (struct trace_event_call *call) {int ret;@@ -2392,18 +2382,6 @@ int trace_remove_event_call_nolock(struct trace_event_call *call)return ret; } -/* Remove an event_call */ -int trace_remove_event_call (struct trace_event_call *call) -{ -int ret; - -mutex_lock (&event_mutex); - ret =trace_remove_event_call_nolock (call); -mutex_unlock (&event_mutex); - -return ret; -} -#define for_each_event (event, start, end) \ for (event = start; \ (unsigned long)event < (unsigned long)end; \kernel/trace/trace_events_hist.c +3
-3@@ -960,7 +960,7 @@ static int register_synth_event(struct synth_event *event) call->data = event; call->tp = event->tp; - ret =trace_add_event_call_nolock (call); + ret =trace_add_event_call (call);if (ret) {pr_warn ("Failed to register synthetic event: %s\n" ,trace_event_name (call));@@ -969,7 +969,7 @@ static int register_synth_event(struct synth_event *event) ret =set_synth_event_print_fmt (call);if (ret <0 ) { -trace_remove_event_call_nolock (call); +trace_remove_event_call (call); goto err; } out:@@ -984,7 +984,7 @@ static int unregister_synth_event(struct synth_event *event)struct trace_event_call *call = &event->call;int ret; - ret =trace_remove_event_call_nolock (call); + ret =trace_remove_event_call (call);return ret; }kernel/trace/trace_kprobe.c +2
-2@@ -1353,7 +1353,7 @@ static int register_kprobe_event(struct trace_kprobe *tk)kfree (call->print_fmt);return -ENODEV ; } - ret =trace_add_event_call_nolock (call); + ret =trace_add_event_call (call);if (ret) {pr_info ("Failed to register kprobe event: %s\n" ,trace_event_name (call));@@ -1368,7 +1368,7 @@ static int unregister_kprobe_event(struct trace_kprobe *tk)int ret;/* tp->event is unregistered in trace_remove_event_call() */ - ret =trace_remove_event_call_nolock (&tk->tp.call); + ret =trace_remove_event_call (&tk->tp.call);if (!ret)kfree (tk->tp.call.print_fmt);return ret;kernel/trace/trace_uprobe.c +2
-2@@ -1320,7 +1320,7 @@ static int register_uprobe_event(struct trace_uprobe *tu)return -ENODEV ; } - ret =trace_add_event_call_nolock (call); + ret =trace_add_event_call (call);if (ret) { pr_info("Failed to register uprobe event: %s\n",@@ -1337,7 +1337,7 @@ static int unregister_uprobe_event(struct trace_uprobe *tu)int ret;/* tu->event is unregistered in trace_remove_event_call() */ - ret =trace_remove_event_call_nolock (&tu->tp.call); + ret =trace_remove_event_call (&tu->tp.call);if (ret)return ret;kfree (tu->tp.call.print_fmt);Signature · 1 line
2.19.2
Signature · 1 line
Masami Hiramatsu <[email protected]>
Masami Hiramatsu
maintainerPATCH v2 11/12 tracing: Add generic event-name based remove event method
In reply to Masami HiramatsuAdd a generic method to remove event from dynamic event list. This is same as other system under ftrace. You just need to pass the event name with '!', e.g.
# echo p:new_grp/new_event _do_fork > dynamic_events
This creates an event, and
# echo '!p:new_grp/new_event _do_fork' > dynamic_events
Or,
# echo '!p:new_grp/new_event' > dynamic_events
will remove new_grp/new_event event.
Note that this doesn't check the event prefix (e.g. "p:") strictly, because the "group/event" name must be unique.
---
Changes in v2:
- Instead of checking the given entire line strictly, simply checking the event and group name.
--- kernel/trace/trace_dynevent.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
kernel/trace/trace_dynevent.c +11 -4
@@ -37,10 +37,17 @@ int dyn_event_release(int argc, char **argv, struct dyn_event_operations *type)char *system =NULL , *event, *p;int ret = -ENOENT ; -if (argv[0 ][1 ] !=':' ) -return -EINVAL ; +if (argv[0 ][0 ] =='-' ) { +if (argv[0 ][1 ] !=':' ) +return -EINVAL ; + event = &argv[0 ][2 ]; + }else { + event =strchr (argv[0 ],':' ); +if (!event) +return -EINVAL ; + event++; + } - event = &argv[0 ][2 ]; p =strchr (event,'/' );if (p) { system = event;
@@ -69,7 +76,7 @@ static int create_dyn_event(int argc, char **argv)struct dyn_event_operations *ops;int ret; -if (argv[0 ][0 ] =='-' ) +if (argv[0 ][0 ] =='-' || argv[0 ][0 ] =='!' )return dyn_event_release (argc, argv,NULL );mutex_lock (&dyn_event_ops_mutex);
Masami Hiramatsu
maintainerPATCH v2 12/12 selftests/ftrace: Add testcases for dynamic event
In reply to Masami HiramatsuAdd common testcases for dynamic_events interface.
- Add/remove kprobe events via dynamic_events
- Add/remove synthetic events via dynamic_events
- Selective clear events (clear events other interfaces)
- Genelic clear events ("!LINE" syntax)
--- .../ftrace/test.d/dynevent/add_remove_kprobe.tc | 30 ++++++++++++ .../ftrace/test.d/dynevent/add_remove_synth.tc | 27 +++++++++++ .../ftrace/test.d/dynevent/clear_select_events.tc | 50 ++++++++++++++++++++ .../ftrace/test.d/dynevent/generic_clear_event.tc | 49 ++++++++++++++++++++ 4 files changed, 156 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/add_remove_kprobe.tc create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/add_remove_synth.tc create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/clear_select_events.tc create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/generic_clear_event.tc
tools/testing/selftests/ftrace/test.d/dynevent/add_remove_kprobe.tc new file +30 -0
@@ -0,0 +1,30 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Generic dynamic event - add/remove kprobe events + +[ -f dynamic_events ] || exit_unsupported + +grep -q "place: \[<module>:\]<symbol>" README || exit_unsupported +grep -q "place (kretprobe): \[<module>:\]<symbol>" README || exit_unsupported + +echo 0 > events/enable +echo > dynamic_events + +PLACE=_do_fork + +echo "p:myevent1 $PLACE" >> dynamic_events +echo "r:myevent2 $PLACE" >> dynamic_events + +grep -q myevent1 dynamic_events +grep -q myevent2 dynamic_events +test -d events/kprobes/myevent1 +test -d events/kprobes/myevent2 + +echo "-:myevent2" >> dynamic_events + +grep -q myevent1 dynamic_events +! grep -q myevent2 dynamic_events + +echo > dynamic_events + +clear_trace
tools/testing/selftests/ftrace/test.d/dynevent/add_remove_synth.tc new file +27 -0
@@ -0,0 +1,27 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Generic dynamic event - add/remove synthetic events + +[ -f dynamic_events ] || exit_unsupported + +grep -q "s:\[synthetic/\]" README || exit_unsupported + +echo 0 > events/enable +echo > dynamic_events + +echo "s:latency1 u64 lat; pid_t pid;" >> dynamic_events +echo "s:latency2 u64 lat; pid_t pid;" >> dynamic_events + +grep -q latency1 dynamic_events +grep -q latency2 dynamic_events +test -d events/synthetic/latency1 +test -d events/synthetic/latency2 + +echo "-:synthetic/latency2" >> dynamic_events + +grep -q latency1 dynamic_events +! grep -q latency2 dynamic_events + +echo > dynamic_events + +clear_trace
tools/testing/selftests/ftrace/test.d/dynevent/clear_select_events.tc new file +50 -0
50 lines not on this page · raw message
tools/testing/selftests/ftrace/test.d/dynevent/generic_clear_event.tc new file +49 -0
49 lines not on this page · raw message
Masami Hiramatsu
maintainerPing?
Hi Tom,
This series, especially [09/12] tracing: Remove unneeded synth_event_mutex will effect your current working series. Please tell me your opinion.
Thank you,
Quoted 127 lines · On Mon, 5 Nov 2018 17:59:46 +0900 Masami Hiramatsu <[email protected]> wrote:
Hi,
This is v2 series of unifying dynamic event interface on ftrace. Currently ftrace has 3 dynamic event interfaces, kprobes, uprobes and synthetic. This series unifies those dynamic event interfaces to "
dynamic_events" so that we can add other dynamic events easily on same interface, e.g. function events.
The older interfaces are left on the tracefs for backward compatibility.
dynamic_eventssyntax has no difference fromkprobe_eventsanduprobe_events. You can use same syntax fordynamic_eventsinterface. For synthetic events, similar to the probe events,dynamic_eventsadds "s:[GROUP/]" prefix, where the "GROUP/" must be "synthetic/".s:[synthetic/]<event-name> type arg [type arg]...
E.g.
$ echo 'wakeup_latency u64 lat pid_t pid char' > synthetic_eventsis same as
$ echo 's:wakeup_latency u64 lat pid_t pid char' > dynamic_eventsOr
$ echo 's:synthetic/wakeup_latency u64 lat pid_t pid char' > dynamic_eventsThis series modifies synthetic event interface behavior a bit, reorder lock dependency and related cleanups so that we can integrate the synthetic event to
dynamic_eventsinterface.In this version, I changed the generic '!' erase command, which now supports entire line style like other interfaces. So you can delete events via
dynamic_eventsas below$ cat dynamic_events | while read line; \ do echo "!$line" >> dynamic_events; doneAlso, the big change will be removing
dyn_event_mutexandsynth_event_mutexbecause all those parts are protected byevent_mutex.Changes from v2 are here;
New patches:
- Reorderevent_mutexandsynth_event_mutexto solve
AB-BA deadlock correctly. ([2/12])
- Simplify creation and deletion of synthetic event. ([3/12])
- Retern-ENOENTif there is no synthetic event when deleting ([4/12])
- Integrate similar probe argument parsers ([5/12])
- Usedyn_eventframework for synthetic events ([9/12])
- Removesynth_event_mutex([10/12])
- Remove unused APIs ([11/12])Modified patches:
[6/12] - [8/12]
- Generalize delete event and export asdyn_event_release_all().
- Add match operation for find deleting event.
- Reorderevent_mutexanddyn_event_mutexto solve lock dependency issue.
- Pass const char **argv for create operation and use-ECANCELEDto signal for trying nextdyn_event_operations.
- Removedyn_event_mutex.[12/12]
- Accept entire line, but instead of checking the given entire line strictly, simply checking the event and group name.Tom, thanks for your Ack for v1 series. Since I changed many things from v1 (not only minor change), I decided to not add your Ack for this version. Anyway, what I've added in this version are related to synthetic events. I need your review for those. (especially removing
synth_event_mutex)You can try it from my git tree.
https://github.com/mhiramat/linux/tree/unify-dynamic-events-v2
Thank you,
---
Masami Hiramatsu (12):
tracing/uprobes: Add busy check when cleanup all uprobes
tracing: Lockevent_mutexbeforesynth_event_mutex
tracing: Simplify creation and deletion of synthetic event
tracing: Integrate similar probe argument parsers
tracing: Add unified dynamic event framework tracing/kprobes: Usedyn_eventframework for kprobe events tracing/uprobes: Usedyn_eventframework for uprobe events
tracing: Usedyn_eventframework for synthetic events
tracing: Remove unneededsynth_event_mutex
tracing: Remove orphaned trace_add/remove_event_call functions
tracing: Add generic event-name based remove event method selftests/ftrace: Add testcases for dynamic eventDocumentation/trace/kprobetrace.rst | 3 Documentation/trace/uprobetracer.rst | 4 include/linux/trace_events.h | 4 kernel/trace/Kconfig | 6 kernel/trace/Makefile | 1 kernel/trace/trace.c | 12 + kernel/trace/trace_dynevent.c | 217 ++++++++++++ kernel/trace/trace_dynevent.h | 119 +++++++ kernel/trace/trace_events.c | 12 - kernel/trace/trace_events_hist.c | 322 ++++++++++-------- kernel/trace/trace_kprobe.c | 357 ++++++++++---------- kernel/trace/trace_probe.c | 74 ++++ kernel/trace/trace_probe.h | 9 - kernel/trace/trace_uprobe.c | 305 ++++++++--------- .../ftrace/test.d/dynevent/add_remove_kprobe.tc | 30 ++ .../ftrace/test.d/dynevent/add_remove_synth.tc | 27 ++ .../ftrace/test.d/dynevent/clear_select_events.tc | 50 +++ .../ftrace/test.d/dynevent/generic_clear_event.tc | 49 +++ 18 files changed, 1094 insertions(+), 507 deletions(-) create mode 100644 kernel/trace/trace_dynevent.c create mode 100644 kernel/trace/trace_dynevent.h create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/add_remove_kprobe.tc create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/add_remove_synth.tc create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/clear_select_events.tc create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/generic_clear_event.tc--
Masami Hiramatsu (Linaro) <[email protected]>
Signature · 1 line
Masami Hiramatsu <[email protected]>
Hi Masami,
Quoted 8 lines · Masami Hiramatsu
Ping?
Hi Tom,
This series, especially [09/12] tracing: Remove unneeded
synth_event_mutex
will effect your current working series. Please tell me your opinion.
Sorry for the delay in reviewing this - I completely forgot about it in my inbox.
It's all very nice, and the mutex updates along with the dyn_event management make that part of the code much cleaner, thanks!
In any case, you can have my
Thanks,
Tom
Quoted 152 lines
Thank you,
Quoted 145 lines · On Mon, 5 Nov 2018 17:59:46 +0900 Masami Hiramatsu <[email protected]> wrote:
Hi,
This is v2 series of unifying dynamic event interface on ftrace. Currently ftrace has 3 dynamic event interfaces, kprobes, uprobes and synthetic. This series unifies those dynamic event interfaces to "
dynamic_events" so that we can add other dynamic events easily on same interface, e.g. function events.
The older interfaces are left on the tracefs for backward compatibility.
dynamic_eventssyntax has no difference fromkprobe_eventsanduprobe_events. You can use same syntax fordynamic_eventsinterface.
For synthetic events, similar to the probe events,dynamic_eventsadds "s:[GROUP/]" prefix, where the "GROUP/" must be "synthetic/".s:[synthetic/]<event-name> type arg [type arg]...
E.g.
$ echo 'wakeup_latency u64 lat pid_t pid char' > synthetic_eventsis same as
$ echo 's:wakeup_latency u64 lat pid_t pid char' > dynamic_eventsOr
$ echo 's:synthetic/wakeup_latency u64 lat pid_t pid char' > dynamic_eventsThis series modifies synthetic event interface behavior a bit, reorder lock dependency and related cleanups so that we can integrate
the synthetic event todynamic_eventsinterface.In this version, I changed the generic '!' erase command, which now supports entire line style like other interfaces. So you can delete events via
dynamic_eventsas below$ cat dynamic_events | while read line; \ do echo "!$line" >> dynamic_events; doneAlso, the big change will be removing
dyn_event_mutexandsynth_event_mutexbecause all those parts are protected byevent_mutex.Changes from v2 are here;
New patches:
- Reorderevent_mutexandsynth_event_mutexto solve AB-BA deadlock correctly. ([2/12])
- Simplify creation and deletion of synthetic event. ([3/12])
- Retern-ENOENTif there is no synthetic event when deleting
([4/12])
- Integrate similar probe argument parsers ([5/12])
- Usedyn_eventframework for synthetic events ([9/12])
- Removesynth_event_mutex([10/12])
- Remove unused APIs ([11/12])Modified patches:
[6/12] - [8/12]
- Generalize delete event and export asdyn_event_release_all().
- Add match operation for find deleting event.
- Reorderevent_mutexanddyn_event_mutexto solve lock dependency issue.
- Pass const char **argv for create operation and use-ECANCELED
to
signal for trying nextdyn_event_operations.
- Removedyn_event_mutex.[12/12]
- Accept entire line, but instead of checking the given entire
line
strictly, simply checking the event and group name.Tom, thanks for your Ack for v1 series. Since I changed many things from v1 (not only minor change), I decided to not add your Ack for this version. Anyway, what I've added in this version are related to
synthetic events. I need your review for those. (especially removingsynth_event_mutex)You can try it from my git tree.
https://github.com/mhiramat/linux/tree/unify-dynamic-events-v2
Thank you,
---
Masami Hiramatsu (12):
tracing/uprobes: Add busy check when cleanup all uprobes
tracing: Lockevent_mutexbeforesynth_event_mutex
tracing: Simplify creation and deletion of synthetic event
tracing: Integrate similar probe argument parsers
tracing: Add unified dynamic event framework tracing/kprobes: Usedyn_eventframework for kprobe events tracing/uprobes: Usedyn_eventframework for uprobe events
tracing: Usedyn_eventframework for synthetic events
tracing: Remove unneededsynth_event_mutex
tracing: Remove orphaned trace_add/remove_event_call
functions
tracing: Add generic event-name based remove event method selftests/ftrace: Add testcases for dynamic eventDocumentation/trace/kprobetrace.rst | 3 Documentation/trace/uprobetracer.rst | 4 include/linux/trace_events.h | 4 kernel/trace/Kconfig | 6 kernel/trace/Makefile | 1 kernel/trace/trace.c | 12 + kernel/trace/trace_dynevent.c | 217 ++++++++++++ kernel/trace/trace_dynevent.h | 119 +++++++ kernel/trace/trace_events.c | 12 - kernel/trace/trace_events_hist.c | 322 ++++++++++-------- kernel/trace/trace_kprobe.c | 357 ++++++++++---------- kernel/trace/trace_probe.c | 74 ++++ kernel/trace/trace_probe.h | 9 - kernel/trace/trace_uprobe.c | 305 ++++++++--------- .../ftrace/test.d/dynevent/add_remove_kprobe.tc | 30 ++ .../ftrace/test.d/dynevent/add_remove_synth.tc | 27 ++ .../ftrace/test.d/dynevent/clear_select_events.tc | 50 +++ .../ftrace/test.d/dynevent/generic_clear_event.tc | 49 +++ 18 files changed, 1094 insertions(+), 507 deletions(-) create mode 100644 kernel/trace/trace_dynevent.c create mode 100644 kernel/trace/trace_dynevent.h create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/add_remove_kprobe.tc create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/add_remove_synth.tc create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/clear_select_events. tc create mode 100644
tools/testing/selftests/ftrace/test.d/dynevent/generic_clear_event. tc--
Masami Hiramatsu (Linaro) <[email protected]>
Steven Rostedt
maintainerQuoted 15 lines · On Wed, 28 Nov 2018 17:42:22 -0600 Tom Zanussi <[email protected]>…
Hi Masami,
Quoted 8 lines · Masami Hiramatsu
Ping?
Hi Tom,
This series, especially [09/12] tracing: Remove unneeded
synth_event_mutex
will effect your current working series. Please tell me your opinion.Sorry for the delay in reviewing this - I completely forgot about it in my inbox.
Quoted 9 lines
It's all very nice, and the mutex updates along with the
dyn_eventmanagement make that part of the code much cleaner, thanks!In any case, you can have my
Reviewed-by Tom Zanussi <[email protected]>Tested-by Tom Zanussi <[email protected]>
Thanks Tom! I'll take a look at this tomorrow.
-- Steve
Masami Hiramatsu
maintainerHi Tom,
Quoted 15 lines · On Wed, 28 Nov 2018 17:42:22 -0600 Tom Zanussi <[email protected]>…
Hi Masami,
Quoted 8 lines · Masami Hiramatsu
Ping?
Hi Tom,
This series, especially [09/12] tracing: Remove unneeded
synth_event_mutex
will effect your current working series. Please tell me your opinion.Sorry for the delay in reviewing this - I completely forgot about it in my inbox.
Quoted 7 lines
It's all very nice, and the mutex updates along with the
dyn_eventmanagement make that part of the code much cleaner, thanks!In any case, you can have my
Reviewed-by Tom Zanussi <[email protected]>Tested-by Tom Zanussi <[email protected]>
Thank you!
And as I pointed, synth_event_mutex is removed by this series, it may affect your hist trigger series too.
Thanks,
Signature · 1 line
Masami Hiramatsu <[email protected]>
Hi Masami,
Quoted 25 lines · Masami Hiramatsu
Hi Tom,
Quoted 20 lines · On Wed, 28 Nov 2018 17:42:22 -0600 Tom Zanussi <[email protected]>…
Hi Masami,
Quoted 9 lines · Masami Hiramatsu
Ping?
Hi Tom,
This series, especially [09/12] tracing: Remove unneeded
synth_event_mutex
will effect your current working series. Please tell me your opinion.Sorry for the delay in reviewing this - I completely forgot about it in
my inbox.It's all very nice, and the mutex updates along with the
dyn_eventmanagement make that part of the code much cleaner, thanks!
Quoted 9 lines
Quoted 4 lines
In any case, you can have my
Reviewed-by Tom Zanussi <[email protected]>Tested-by Tom Zanussi <[email protected]>Thank you!
And as I pointed,synth_event_mutexis removed by this series, it may affect your hist trigger series too.
Yes, thanks for pointing that out - I'll rebase mine on top of this.
Tom