|
@@ -393,6 +393,20 @@ static struct trace_kprobe *find_trace_kprobe(const char *event,
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+static inline int __enable_trace_kprobe(struct trace_kprobe *tk)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if (trace_probe_is_registered(&tk->tp) && !trace_kprobe_has_gone(tk)) {
|
|
|
+ if (trace_kprobe_is_return(tk))
|
|
|
+ ret = enable_kretprobe(&tk->rp);
|
|
|
+ else
|
|
|
+ ret = enable_kprobe(&tk->rp.kp);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Enable trace_probe
|
|
|
* if the file is NULL, enable "perf" handler, or enable "trace" handler.
|
|
@@ -400,7 +414,7 @@ static struct trace_kprobe *find_trace_kprobe(const char *event,
|
|
|
static int
|
|
|
enable_trace_kprobe(struct trace_kprobe *tk, struct trace_event_file *file)
|
|
|
{
|
|
|
- struct event_file_link *link = NULL;
|
|
|
+ struct event_file_link *link;
|
|
|
int ret = 0;
|
|
|
|
|
|
if (file) {
|
|
@@ -414,26 +428,18 @@ enable_trace_kprobe(struct trace_kprobe *tk, struct trace_event_file *file)
|
|
|
list_add_tail_rcu(&link->list, &tk->tp.files);
|
|
|
|
|
|
tk->tp.flags |= TP_FLAG_TRACE;
|
|
|
- } else
|
|
|
- tk->tp.flags |= TP_FLAG_PROFILE;
|
|
|
-
|
|
|
- if (trace_probe_is_registered(&tk->tp) && !trace_kprobe_has_gone(tk)) {
|
|
|
- if (trace_kprobe_is_return(tk))
|
|
|
- ret = enable_kretprobe(&tk->rp);
|
|
|
- else
|
|
|
- ret = enable_kprobe(&tk->rp.kp);
|
|
|
- }
|
|
|
-
|
|
|
- if (ret) {
|
|
|
- if (file) {
|
|
|
- /* Notice the if is true on not WARN() */
|
|
|
- if (!WARN_ON_ONCE(!link))
|
|
|
- list_del_rcu(&link->list);
|
|
|
+ ret = __enable_trace_kprobe(tk);
|
|
|
+ if (ret) {
|
|
|
+ list_del_rcu(&link->list);
|
|
|
kfree(link);
|
|
|
tk->tp.flags &= ~TP_FLAG_TRACE;
|
|
|
- } else {
|
|
|
- tk->tp.flags &= ~TP_FLAG_PROFILE;
|
|
|
}
|
|
|
+
|
|
|
+ } else {
|
|
|
+ tk->tp.flags |= TP_FLAG_PROFILE;
|
|
|
+ ret = __enable_trace_kprobe(tk);
|
|
|
+ if (ret)
|
|
|
+ tk->tp.flags &= ~TP_FLAG_PROFILE;
|
|
|
}
|
|
|
out:
|
|
|
return ret;
|