aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_kprobe.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2013-06-20 13:38:09 -0400
committerSteven Rostedt <rostedt@goodmis.org>2013-07-01 20:34:24 -0400
commit3fe3d6193e7cd7b4dd2bde10772f048bdefea4ee (patch)
treef7623a40ffb23ffab302a8cb9ed6c5716ec1d691 /kernel/trace/trace_kprobe.c
parent288e984e622336bab8bc3dfdf2f190816362d9a1 (diff)
tracing/kprobes: Kill probe_enable_lock
enable_trace_probe() and disable_trace_probe() should not worry about serialization, the caller (perf_trace_init or __ftrace_set_clr_event) holds event_mutex. They are also called by kprobe_trace_self_tests_init(), but this __init function can't race with itself or trace_events.c And note that this code depended on event_mutex even before 41a7dd420c which introduced probe_enable_lock. In fact it assumes that the caller kprobe_register() can never race with itself. Otherwise, say, tp->flags manipulations are racy. Link: http://lkml.kernel.org/r/20130620173809.GA13158@redhat.com Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
-rw-r--r--kernel/trace/trace_kprobe.c43
1 files changed, 20 insertions, 23 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index c35bebe53ffe..282f86cfd304 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -183,16 +183,15 @@ static struct trace_probe *find_trace_probe(const char *event,
183 return NULL; 183 return NULL;
184} 184}
185 185
186/*
187 * This and enable_trace_probe/disable_trace_probe rely on event_mutex
188 * held by the caller, __ftrace_set_clr_event().
189 */
186static int trace_probe_nr_files(struct trace_probe *tp) 190static int trace_probe_nr_files(struct trace_probe *tp)
187{ 191{
188 struct ftrace_event_file **file; 192 struct ftrace_event_file **file = rcu_dereference_raw(tp->files);
189 int ret = 0; 193 int ret = 0;
190 194
191 /*
192 * Since all tp->files updater is protected by probe_enable_lock,
193 * we don't need to lock an rcu_read_lock.
194 */
195 file = rcu_dereference_raw(tp->files);
196 if (file) 195 if (file)
197 while (*(file++)) 196 while (*(file++))
198 ret++; 197 ret++;
@@ -200,8 +199,6 @@ static int trace_probe_nr_files(struct trace_probe *tp)
200 return ret; 199 return ret;
201} 200}
202 201
203static DEFINE_MUTEX(probe_enable_lock);
204
205/* 202/*
206 * Enable trace_probe 203 * Enable trace_probe
207 * if the file is NULL, enable "perf" handler, or enable "trace" handler. 204 * if the file is NULL, enable "perf" handler, or enable "trace" handler.
@@ -211,8 +208,6 @@ enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
211{ 208{
212 int ret = 0; 209 int ret = 0;
213 210
214 mutex_lock(&probe_enable_lock);
215
216 if (file) { 211 if (file) {
217 struct ftrace_event_file **new, **old; 212 struct ftrace_event_file **new, **old;
218 int n = trace_probe_nr_files(tp); 213 int n = trace_probe_nr_files(tp);
@@ -223,7 +218,7 @@ enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
223 GFP_KERNEL); 218 GFP_KERNEL);
224 if (!new) { 219 if (!new) {
225 ret = -ENOMEM; 220 ret = -ENOMEM;
226 goto out_unlock; 221 goto out;
227 } 222 }
228 memcpy(new, old, n * sizeof(struct ftrace_event_file *)); 223 memcpy(new, old, n * sizeof(struct ftrace_event_file *));
229 new[n] = file; 224 new[n] = file;
@@ -246,10 +241,7 @@ enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
246 else 241 else
247 ret = enable_kprobe(&tp->rp.kp); 242 ret = enable_kprobe(&tp->rp.kp);
248 } 243 }
249 244 out:
250 out_unlock:
251 mutex_unlock(&probe_enable_lock);
252
253 return ret; 245 return ret;
254} 246}
255 247
@@ -282,8 +274,6 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
282{ 274{
283 int ret = 0; 275 int ret = 0;
284 276
285 mutex_lock(&probe_enable_lock);
286
287 if (file) { 277 if (file) {
288 struct ftrace_event_file **new, **old; 278 struct ftrace_event_file **new, **old;
289 int n = trace_probe_nr_files(tp); 279 int n = trace_probe_nr_files(tp);
@@ -292,7 +282,7 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
292 old = rcu_dereference_raw(tp->files); 282 old = rcu_dereference_raw(tp->files);
293 if (n == 0 || trace_probe_file_index(tp, file) < 0) { 283 if (n == 0 || trace_probe_file_index(tp, file) < 0) {
294 ret = -EINVAL; 284 ret = -EINVAL;
295 goto out_unlock; 285 goto out;
296 } 286 }
297 287
298 if (n == 1) { /* Remove the last file */ 288 if (n == 1) { /* Remove the last file */
@@ -303,7 +293,7 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
303 GFP_KERNEL); 293 GFP_KERNEL);
304 if (!new) { 294 if (!new) {
305 ret = -ENOMEM; 295 ret = -ENOMEM;
306 goto out_unlock; 296 goto out;
307 } 297 }
308 298
309 /* This copy & check loop copies the NULL stopper too */ 299 /* This copy & check loop copies the NULL stopper too */
@@ -326,10 +316,7 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
326 else 316 else
327 disable_kprobe(&tp->rp.kp); 317 disable_kprobe(&tp->rp.kp);
328 } 318 }
329 319 out:
330 out_unlock:
331 mutex_unlock(&probe_enable_lock);
332
333 return ret; 320 return ret;
334} 321}
335 322
@@ -1214,6 +1201,12 @@ kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri,
1214} 1201}
1215#endif /* CONFIG_PERF_EVENTS */ 1202#endif /* CONFIG_PERF_EVENTS */
1216 1203
1204/*
1205 * called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex.
1206 *
1207 * kprobe_trace_self_tests_init() does enable_trace_probe/disable_trace_probe
1208 * lockless, but we can't race with this __init function.
1209 */
1217static __kprobes 1210static __kprobes
1218int kprobe_register(struct ftrace_event_call *event, 1211int kprobe_register(struct ftrace_event_call *event,
1219 enum trace_reg type, void *data) 1212 enum trace_reg type, void *data)
@@ -1379,6 +1372,10 @@ find_trace_probe_file(struct trace_probe *tp, struct trace_array *tr)
1379 return NULL; 1372 return NULL;
1380} 1373}
1381 1374
1375/*
1376 * Nobody but us can call enable_trace_probe/disable_trace_probe at this
1377 * stage, we can do this lockless.
1378 */
1382static __init int kprobe_trace_self_tests_init(void) 1379static __init int kprobe_trace_self_tests_init(void)
1383{ 1380{
1384 int ret, warn = 0; 1381 int ret, warn = 0;