|
@@ -2429,12 +2429,39 @@ static __init int event_trace_memsetup(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static __init void
|
|
|
+early_enable_events(struct trace_array *tr, bool disable_first)
|
|
|
+{
|
|
|
+ char *buf = bootup_event_buf;
|
|
|
+ char *token;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ while (true) {
|
|
|
+ token = strsep(&buf, ",");
|
|
|
+
|
|
|
+ if (!token)
|
|
|
+ break;
|
|
|
+ if (!*token)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /* Restarting syscalls requires that we stop them first */
|
|
|
+ if (disable_first)
|
|
|
+ ftrace_set_clr_event(tr, token, 0);
|
|
|
+
|
|
|
+ ret = ftrace_set_clr_event(tr, token, 1);
|
|
|
+ if (ret)
|
|
|
+ pr_warn("Failed to enable trace event: %s\n", token);
|
|
|
+
|
|
|
+ /* Put back the comma to allow this to be called again */
|
|
|
+ if (buf)
|
|
|
+ *(buf - 1) = ',';
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static __init int event_trace_enable(void)
|
|
|
{
|
|
|
struct trace_array *tr = top_trace_array();
|
|
|
struct ftrace_event_call **iter, *call;
|
|
|
- char *buf = bootup_event_buf;
|
|
|
- char *token;
|
|
|
int ret;
|
|
|
|
|
|
if (!tr)
|
|
@@ -2456,18 +2483,7 @@ static __init int event_trace_enable(void)
|
|
|
*/
|
|
|
__trace_early_add_events(tr);
|
|
|
|
|
|
- while (true) {
|
|
|
- token = strsep(&buf, ",");
|
|
|
-
|
|
|
- if (!token)
|
|
|
- break;
|
|
|
- if (!*token)
|
|
|
- continue;
|
|
|
-
|
|
|
- ret = ftrace_set_clr_event(tr, token, 1);
|
|
|
- if (ret)
|
|
|
- pr_warn("Failed to enable trace event: %s\n", token);
|
|
|
- }
|
|
|
+ early_enable_events(tr, false);
|
|
|
|
|
|
trace_printk_start_comm();
|
|
|
|
|
@@ -2478,6 +2494,31 @@ static __init int event_trace_enable(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * event_trace_enable() is called from trace_event_init() first to
|
|
|
+ * initialize events and perhaps start any events that are on the
|
|
|
+ * command line. Unfortunately, there are some events that will not
|
|
|
+ * start this early, like the system call tracepoints that need
|
|
|
+ * to set the TIF_SYSCALL_TRACEPOINT flag of pid 1. But event_trace_enable()
|
|
|
+ * is called before pid 1 starts, and this flag is never set, making
|
|
|
+ * the syscall tracepoint never get reached, but the event is enabled
|
|
|
+ * regardless (and not doing anything).
|
|
|
+ */
|
|
|
+static __init int event_trace_enable_again(void)
|
|
|
+{
|
|
|
+ struct trace_array *tr;
|
|
|
+
|
|
|
+ tr = top_trace_array();
|
|
|
+ if (!tr)
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ early_enable_events(tr, true);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+early_initcall(event_trace_enable_again);
|
|
|
+
|
|
|
static __init int event_trace_init(void)
|
|
|
{
|
|
|
struct trace_array *tr;
|