diff options
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
-rw-r--r-- | kernel/trace/trace_kprobe.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 9f46e98ba8f2..c209c6ec34ca 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -281,6 +281,8 @@ trace_probe_file_index(struct trace_probe *tp, struct ftrace_event_file *file) | |||
281 | static int | 281 | static int |
282 | disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | 282 | disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) |
283 | { | 283 | { |
284 | struct ftrace_event_file **old = NULL; | ||
285 | int wait = 0; | ||
284 | int ret = 0; | 286 | int ret = 0; |
285 | 287 | ||
286 | mutex_lock(&probe_enable_lock); | 288 | mutex_lock(&probe_enable_lock); |
@@ -314,10 +316,7 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | |||
314 | } | 316 | } |
315 | 317 | ||
316 | rcu_assign_pointer(tp->files, new); | 318 | rcu_assign_pointer(tp->files, new); |
317 | 319 | wait = 1; | |
318 | /* Make sure the probe is done with old files */ | ||
319 | synchronize_sched(); | ||
320 | kfree(old); | ||
321 | } else | 320 | } else |
322 | tp->flags &= ~TP_FLAG_PROFILE; | 321 | tp->flags &= ~TP_FLAG_PROFILE; |
323 | 322 | ||
@@ -326,11 +325,25 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | |||
326 | disable_kretprobe(&tp->rp); | 325 | disable_kretprobe(&tp->rp); |
327 | else | 326 | else |
328 | disable_kprobe(&tp->rp.kp); | 327 | disable_kprobe(&tp->rp.kp); |
328 | wait = 1; | ||
329 | } | 329 | } |
330 | 330 | ||
331 | out_unlock: | 331 | out_unlock: |
332 | mutex_unlock(&probe_enable_lock); | 332 | mutex_unlock(&probe_enable_lock); |
333 | 333 | ||
334 | if (wait) { | ||
335 | /* | ||
336 | * Synchronize with kprobe_trace_func/kretprobe_trace_func | ||
337 | * to ensure disabled (all running handlers are finished). | ||
338 | * This is not only for kfree(), but also the caller, | ||
339 | * trace_remove_event_call() supposes it for releasing | ||
340 | * event_call related objects, which will be accessed in | ||
341 | * the kprobe_trace_func/kretprobe_trace_func. | ||
342 | */ | ||
343 | synchronize_sched(); | ||
344 | kfree(old); /* Ignored if link == NULL */ | ||
345 | } | ||
346 | |||
334 | return ret; | 347 | return ret; |
335 | } | 348 | } |
336 | 349 | ||