|
@@ -1713,16 +1713,47 @@ static void __trace_remove_event_call(struct ftrace_event_call *call)
|
|
|
destroy_preds(call);
|
|
|
}
|
|
|
|
|
|
+static int probe_remove_event_call(struct ftrace_event_call *call)
|
|
|
+{
|
|
|
+ struct trace_array *tr;
|
|
|
+ struct ftrace_event_file *file;
|
|
|
+
|
|
|
+#ifdef CONFIG_PERF_EVENTS
|
|
|
+ if (call->perf_refcount)
|
|
|
+ return -EBUSY;
|
|
|
+#endif
|
|
|
+ do_for_each_event_file(tr, file) {
|
|
|
+ if (file->event_call != call)
|
|
|
+ continue;
|
|
|
+ /*
|
|
|
+ * We can't rely on ftrace_event_enable_disable(enable => 0)
|
|
|
+ * we are going to do, FTRACE_EVENT_FL_SOFT_MODE can suppress
|
|
|
+ * TRACE_REG_UNREGISTER.
|
|
|
+ */
|
|
|
+ if (file->flags & FTRACE_EVENT_FL_ENABLED)
|
|
|
+ return -EBUSY;
|
|
|
+ break;
|
|
|
+ } while_for_each_event_file();
|
|
|
+
|
|
|
+ __trace_remove_event_call(call);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/* Remove an event_call */
|
|
|
-void trace_remove_event_call(struct ftrace_event_call *call)
|
|
|
+int trace_remove_event_call(struct ftrace_event_call *call)
|
|
|
{
|
|
|
+ int ret;
|
|
|
+
|
|
|
mutex_lock(&trace_types_lock);
|
|
|
mutex_lock(&event_mutex);
|
|
|
down_write(&trace_event_sem);
|
|
|
- __trace_remove_event_call(call);
|
|
|
+ ret = probe_remove_event_call(call);
|
|
|
up_write(&trace_event_sem);
|
|
|
mutex_unlock(&event_mutex);
|
|
|
mutex_unlock(&trace_types_lock);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
#define for_each_event(event, start, end) \
|