lkml.org 
[lkml]   [2013]   [Jun]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subject[PATCH] tracing/kprobe: Recover old array if fails to enable kprobe
From
Date
Make enable_trace_probe to recover (writeback) the old file array
and free new one if we fail to enable the kprobe.
However, this MUST NOT happen at this time except for unknown
bug or changing the implementation of enable_kprobe(), because
usual failure cases (not registered or gone) are already filtered.
Thus I just add a WARN_ON() on the error path.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Reported-by: Oleg Nesterov <oleg@redhat.com>
Reported-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: "zhangwei(Jovi)" <jovi.zhangwei@huawei.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
---
kernel/trace/trace_kprobe.c | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index f237417..d29773e 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -202,6 +202,20 @@ static int trace_probe_nr_files(struct trace_probe *tp)

static DEFINE_MUTEX(probe_enable_lock);

+static int __enable_trace_probe(struct trace_probe *tp)
+{
+ int ret = 0;
+
+ if (trace_probe_is_registered(tp) && !trace_probe_has_gone(tp)) {
+ if (trace_probe_is_return(tp))
+ ret = enable_kretprobe(&tp->rp);
+ else
+ ret = enable_kprobe(&tp->rp.kp);
+ WARN_ON(ret);/* This must succeed. */
+ }
+ return ret;
+}
+
/*
* Enable trace_probe
* if the file is NULL, enable "perf" handler, or enable "trace" handler.
@@ -232,19 +246,21 @@ enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
rcu_assign_pointer(tp->files, new);
tp->flags |= TP_FLAG_TRACE;

+ ret = __enable_trace_probe(tp);
+ if (ret < 0) {
+ /* Write back the old list */
+ rcu_assign_pointer(tp->files, old);
+ old = new; /* "new" must be freed */
+ }
+
if (old) {
/* Make sure the probe is done with old files */
synchronize_sched();
kfree(old);
}
- } else
+ } else {
tp->flags |= TP_FLAG_PROFILE;
-
- if (trace_probe_is_registered(tp) && !trace_probe_has_gone(tp)) {
- if (trace_probe_is_return(tp))
- ret = enable_kretprobe(&tp->rp);
- else
- ret = enable_kprobe(&tp->rp.kp);
+ ret = __enable_trace_probe(tp);
}

out_unlock:


\
 
 \ /
  Last update: 2013-06-28 15:21    [W:0.543 / U:0.068 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site