diff options
author | Masami Hiramatsu <mhiramat@kernel.org> | 2019-05-31 17:17:26 +0200 |
---|---|---|
committer | Steven Rostedt (VMware) <rostedt@goodmis.org> | 2019-07-16 21:14:47 +0200 |
commit | b5f935ee133911b3ed2d4429dd86d2bd5385519d (patch) | |
tree | 249b7db4c9568ec2856843d5c9288c3bc36728c4 /kernel/trace/trace_probe.c | |
parent | tracing/probe: Add trace_event_call register API for trace_probe (diff) | |
download | linux-b5f935ee133911b3ed2d4429dd86d2bd5385519d.tar.xz linux-b5f935ee133911b3ed2d4429dd86d2bd5385519d.zip |
tracing/probe: Add trace_event_file access APIs for trace_probe
Add trace_event_file access APIs for trace_probe data structure.
This simplifies enabling/disabling operations in uprobe and kprobe
events so that those don't touch deep inside the trace_probe.
This also removing a redundant synchronization when the
kprobe event is used from perf, since the perf itself uses
tracepoint_synchronize_unregister() after disabling (ftrace-
defined) event, thus we don't have to synchronize in that
path. Also we don't need to identify local trace_kprobe too
anymore.
Link: http://lkml.kernel.org/r/155931584587.28323.372301976283354629.stgit@devnote2
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/trace_probe.c')
-rw-r--r-- | kernel/trace/trace_probe.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 509a26024b4f..abb05608a09d 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -936,3 +936,50 @@ int trace_probe_register_event_call(struct trace_probe *tp) return ret; } + +int trace_probe_add_file(struct trace_probe *tp, struct trace_event_file *file) +{ + struct event_file_link *link; + + link = kmalloc(sizeof(*link), GFP_KERNEL); + if (!link) + return -ENOMEM; + + link->file = file; + INIT_LIST_HEAD(&link->list); + list_add_tail_rcu(&link->list, &tp->files); + tp->flags |= TP_FLAG_TRACE; + return 0; +} + +struct event_file_link *trace_probe_get_file_link(struct trace_probe *tp, + struct trace_event_file *file) +{ + struct event_file_link *link; + + trace_probe_for_each_link(link, tp) { + if (link->file == file) + return link; + } + + return NULL; +} + +int trace_probe_remove_file(struct trace_probe *tp, + struct trace_event_file *file) +{ + struct event_file_link *link; + + link = trace_probe_get_file_link(tp, file); + if (!link) + return -ENOENT; + + list_del_rcu(&link->list); + synchronize_rcu(); + kfree(link); + + if (list_empty(&tp->files)) + tp->flags &= ~TP_FLAG_TRACE; + + return 0; +} |