|
@@ -95,7 +95,7 @@ static __kprobes bool trace_probe_is_on_module(struct trace_probe *tp)
|
|
|
}
|
|
|
|
|
|
static int register_probe_event(struct trace_probe *tp);
|
|
|
-static void unregister_probe_event(struct trace_probe *tp);
|
|
|
+static int unregister_probe_event(struct trace_probe *tp);
|
|
|
|
|
|
static DEFINE_MUTEX(probe_lock);
|
|
|
static LIST_HEAD(probe_list);
|
|
@@ -351,9 +351,12 @@ static int unregister_trace_probe(struct trace_probe *tp)
|
|
|
if (trace_probe_is_enabled(tp))
|
|
|
return -EBUSY;
|
|
|
|
|
|
+ /* Will fail if probe is being used by ftrace or perf */
|
|
|
+ if (unregister_probe_event(tp))
|
|
|
+ return -EBUSY;
|
|
|
+
|
|
|
__unregister_trace_probe(tp);
|
|
|
list_del(&tp->list);
|
|
|
- unregister_probe_event(tp);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -632,7 +635,9 @@ static int release_all_trace_probes(void)
|
|
|
/* TODO: Use batch unregistration */
|
|
|
while (!list_empty(&probe_list)) {
|
|
|
tp = list_entry(probe_list.next, struct trace_probe, list);
|
|
|
- unregister_trace_probe(tp);
|
|
|
+ ret = unregister_trace_probe(tp);
|
|
|
+ if (ret)
|
|
|
+ goto end;
|
|
|
free_trace_probe(tp);
|
|
|
}
|
|
|
|
|
@@ -1247,11 +1252,15 @@ static int register_probe_event(struct trace_probe *tp)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static void unregister_probe_event(struct trace_probe *tp)
|
|
|
+static int unregister_probe_event(struct trace_probe *tp)
|
|
|
{
|
|
|
+ int ret;
|
|
|
+
|
|
|
/* tp->event is unregistered in trace_remove_event_call() */
|
|
|
- trace_remove_event_call(&tp->call);
|
|
|
- kfree(tp->call.print_fmt);
|
|
|
+ ret = trace_remove_event_call(&tp->call);
|
|
|
+ if (!ret)
|
|
|
+ kfree(tp->call.print_fmt);
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
/* Make a debugfs interface for controlling probe points */
|