]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - kernel/trace/trace_kprobe.c
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch
[karo-tx-linux.git] / kernel / trace / trace_kprobe.c
index 7ed6976493c87ec2d31637a60a285bc39b4925b8..3811487e7a7a1d58f23b6e04b49fda0dbf06c9b0 100644 (file)
@@ -243,11 +243,11 @@ find_event_file_link(struct trace_probe *tp, struct ftrace_event_file *file)
 static int
 disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
 {
+       struct event_file_link *link = NULL;
+       int wait = 0;
        int ret = 0;
 
        if (file) {
-               struct event_file_link *link;
-
                link = find_event_file_link(tp, file);
                if (!link) {
                        ret = -EINVAL;
@@ -255,10 +255,7 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
                }
 
                list_del_rcu(&link->list);
-               /* synchronize with kprobe_trace_func/kretprobe_trace_func */
-               synchronize_sched();
-               kfree(link);
-
+               wait = 1;
                if (!list_empty(&tp->files))
                        goto out;
 
@@ -271,8 +268,22 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
                        disable_kretprobe(&tp->rp);
                else
                        disable_kprobe(&tp->rp.kp);
+               wait = 1;
        }
  out:
+       if (wait) {
+               /*
+                * Synchronize with kprobe_trace_func/kretprobe_trace_func
+                * to ensure disabled (all running handlers are finished).
+                * This is not only for kfree(), but also the caller,
+                * trace_remove_event_call() supposes it for releasing
+                * event_call related objects, which will be accessed in
+                * the kprobe_trace_func/kretprobe_trace_func.
+                */
+               synchronize_sched();
+               kfree(link);    /* Ignored if link == NULL */
+       }
+
        return ret;
 }
 
@@ -1087,9 +1098,6 @@ kprobe_perf_func(struct trace_probe *tp, struct pt_regs *regs)
        __size = sizeof(*entry) + tp->size + dsize;
        size = ALIGN(__size + sizeof(u32), sizeof(u64));
        size -= sizeof(u32);
-       if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,
-                    "profile buffer not large enough"))
-               return;
 
        entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx);
        if (!entry)
@@ -1120,9 +1128,6 @@ kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri,
        __size = sizeof(*entry) + tp->size + dsize;
        size = ALIGN(__size + sizeof(u32), sizeof(u64));
        size -= sizeof(u32);
-       if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,
-                    "profile buffer not large enough"))
-               return;
 
        entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx);
        if (!entry)