diff options
author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2013-07-09 05:35:26 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2013-07-18 21:31:29 -0400 |
commit | a232e270dcb55a70ad3241bc6fc160fd9b5c9e6c (patch) | |
tree | f2eba68c4e863ab55584abfd91cce3389c6c9433 /kernel/trace | |
parent | cd92bf61d6d70bd3eb33b46d600e3f3eb9c5778a (diff) |
tracing/kprobe: Wait for disabling all running kprobe handlers
Wait for disabling all running kprobe handlers when a kprobe
event is disabled, since the caller, trace_remove_event_call()
supposes that a removing event is disabled completely by
disabling the event.
With this change, ftrace can ensure that there is no running
event handlers after disabling it.
Link: http://lkml.kernel.org/r/20130709093526.20138.93100.stgit@mhiramat-M0-7522
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/trace_kprobe.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index ae6ce835b023..3811487e7a7a 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -243,11 +243,11 @@ find_event_file_link(struct trace_probe *tp, struct ftrace_event_file *file) | |||
243 | static int | 243 | static int |
244 | disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | 244 | disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) |
245 | { | 245 | { |
246 | struct event_file_link *link = NULL; | ||
247 | int wait = 0; | ||
246 | int ret = 0; | 248 | int ret = 0; |
247 | 249 | ||
248 | if (file) { | 250 | if (file) { |
249 | struct event_file_link *link; | ||
250 | |||
251 | link = find_event_file_link(tp, file); | 251 | link = find_event_file_link(tp, file); |
252 | if (!link) { | 252 | if (!link) { |
253 | ret = -EINVAL; | 253 | ret = -EINVAL; |
@@ -255,10 +255,7 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | |||
255 | } | 255 | } |
256 | 256 | ||
257 | list_del_rcu(&link->list); | 257 | list_del_rcu(&link->list); |
258 | /* synchronize with kprobe_trace_func/kretprobe_trace_func */ | 258 | wait = 1; |
259 | synchronize_sched(); | ||
260 | kfree(link); | ||
261 | |||
262 | if (!list_empty(&tp->files)) | 259 | if (!list_empty(&tp->files)) |
263 | goto out; | 260 | goto out; |
264 | 261 | ||
@@ -271,8 +268,22 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | |||
271 | disable_kretprobe(&tp->rp); | 268 | disable_kretprobe(&tp->rp); |
272 | else | 269 | else |
273 | disable_kprobe(&tp->rp.kp); | 270 | disable_kprobe(&tp->rp.kp); |
271 | wait = 1; | ||
274 | } | 272 | } |
275 | out: | 273 | out: |
274 | if (wait) { | ||
275 | /* | ||
276 | * Synchronize with kprobe_trace_func/kretprobe_trace_func | ||
277 | * to ensure disabled (all running handlers are finished). | ||
278 | * This is not only for kfree(), but also the caller, | ||
279 | * trace_remove_event_call() supposes it for releasing | ||
280 | * event_call related objects, which will be accessed in | ||
281 | * the kprobe_trace_func/kretprobe_trace_func. | ||
282 | */ | ||
283 | synchronize_sched(); | ||
284 | kfree(link); /* Ignored if link == NULL */ | ||
285 | } | ||
286 | |||
276 | return ret; | 287 | return ret; |
277 | } | 288 | } |
278 | 289 | ||