]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
tracing/kprobe: Add per-probe delete from event
authorMasami Hiramatsu <mhiramat@kernel.org>
Wed, 19 Jun 2019 15:08:08 +0000 (00:08 +0900)
committerSteven Rostedt (VMware) <rostedt@goodmis.org>
Sat, 31 Aug 2019 16:19:38 +0000 (12:19 -0400)
Allow user to delete a probe from event. This is done by head
match. For example, if we have 2 probes on an event

$ cat kprobe_events
p:kprobes/testprobe _do_fork r1=%ax r2=%dx
p:kprobes/testprobe idle_fork r1=%ax r2=%cx

Then you can remove one of them by passing the head of definition
which identify the probe.

$ echo "-:kprobes/testprobe idle_fork" >> kprobe_events

Link: http://lkml.kernel.org/r/156095688848.28024.15798690082378432435.stgit@devnote2
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
kernel/trace/trace_kprobe.c
kernel/trace/trace_probe.c
kernel/trace/trace_probe.h

index f43098bf62dd49018a617cd9256b62c932e51d90..18c4175b6585976f052e8c16290eb36df2ea7007 100644 (file)
@@ -137,13 +137,36 @@ static bool trace_kprobe_is_busy(struct dyn_event *ev)
        return trace_probe_is_enabled(&tk->tp);
 }
 
+static bool trace_kprobe_match_command_head(struct trace_kprobe *tk,
+                                           int argc, const char **argv)
+{
+       char buf[MAX_ARGSTR_LEN + 1];
+
+       if (!argc)
+               return true;
+
+       if (!tk->symbol)
+               snprintf(buf, sizeof(buf), "0x%p", tk->rp.kp.addr);
+       else if (tk->rp.kp.offset)
+               snprintf(buf, sizeof(buf), "%s+%u",
+                        trace_kprobe_symbol(tk), tk->rp.kp.offset);
+       else
+               snprintf(buf, sizeof(buf), "%s", trace_kprobe_symbol(tk));
+       if (strcmp(buf, argv[0]))
+               return false;
+       argc--; argv++;
+
+       return trace_probe_match_command_args(&tk->tp, argc, argv);
+}
+
 static bool trace_kprobe_match(const char *system, const char *event,
                        int argc, const char **argv, struct dyn_event *ev)
 {
        struct trace_kprobe *tk = to_trace_kprobe(ev);
 
        return strcmp(trace_probe_name(&tk->tp), event) == 0 &&
-           (!system || strcmp(trace_probe_group_name(&tk->tp), system) == 0);
+           (!system || strcmp(trace_probe_group_name(&tk->tp), system) == 0) &&
+           trace_kprobe_match_command_head(tk, argc, argv);
 }
 
 static nokprobe_inline unsigned long trace_kprobe_nhit(struct trace_kprobe *tk)
index 651a1449acdee084870f8044a13da62a2cbd1aa8..f8c3c65c035dbfd91616f6882c2b803da43dfa92 100644 (file)
@@ -1047,3 +1047,21 @@ int trace_probe_compare_arg_type(struct trace_probe *a, struct trace_probe *b)
 
        return 0;
 }
+
+bool trace_probe_match_command_args(struct trace_probe *tp,
+                                   int argc, const char **argv)
+{
+       char buf[MAX_ARGSTR_LEN + 1];
+       int i;
+
+       if (tp->nr_args < argc)
+               return false;
+
+       for (i = 0; i < argc; i++) {
+               snprintf(buf, sizeof(buf), "%s=%s",
+                        tp->args[i].name, tp->args[i].comm);
+               if (strcmp(buf, argv[i]))
+                       return false;
+       }
+       return true;
+}
index 39926e8a344b5aa93864abed5253d46a10c81ec5..2dcc4e3177875cd93d29bcd9a8ff48292249ddd0 100644 (file)
@@ -332,6 +332,8 @@ int trace_probe_remove_file(struct trace_probe *tp,
 struct event_file_link *trace_probe_get_file_link(struct trace_probe *tp,
                                                struct trace_event_file *file);
 int trace_probe_compare_arg_type(struct trace_probe *a, struct trace_probe *b);
+bool trace_probe_match_command_args(struct trace_probe *tp,
+                                   int argc, const char **argv);
 
 #define trace_probe_for_each_link(pos, tp)     \
        list_for_each_entry(pos, &(tp)->event->files, list)