* [PATCH 1/6] kprobes: Init kprobes in early_initcall
2020-09-10 12:38 [PATCH 0/6] tracing/boot: Start boot-time tracing in earlier stage Masami Hiramatsu
@ 2020-09-10 12:38 ` Masami Hiramatsu
2020-09-10 12:38 ` [PATCH 2/6] tracing: Define event fields early stage Masami Hiramatsu
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Masami Hiramatsu @ 2020-09-10 12:38 UTC (permalink / raw)
To: Steven Rostedt, Jonathan Corbet
Cc: mhiramat, linux-kernel, linux-doc, Randy Dunlap, Ingo Molnar
Init kprobes feature in early_initcall as same as jump_label and
dynamic_debug does, so that we can use kprobes events in earlier
boot stage.
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
kernel/kprobes.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 2880cdf37c47..7d1fbdaa7a08 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2528,7 +2528,7 @@ static int __init init_kprobes(void)
init_test_probes();
return err;
}
-subsys_initcall(init_kprobes);
+early_initcall(init_kprobes);
#ifdef CONFIG_DEBUG_FS
static void report_probe(struct seq_file *pi, struct kprobe *p,
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/6] tracing: Define event fields early stage
2020-09-10 12:38 [PATCH 0/6] tracing/boot: Start boot-time tracing in earlier stage Masami Hiramatsu
2020-09-10 12:38 ` [PATCH 1/6] kprobes: Init kprobes in early_initcall Masami Hiramatsu
@ 2020-09-10 12:38 ` Masami Hiramatsu
2020-09-10 12:38 ` [PATCH 3/6] tracing: Enable adding dynamic events " Masami Hiramatsu
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Masami Hiramatsu @ 2020-09-10 12:38 UTC (permalink / raw)
To: Steven Rostedt, Jonathan Corbet
Cc: mhiramat, linux-kernel, linux-doc, Randy Dunlap, Ingo Molnar
Define event fields at early stage so that boot-time tracing can
access the event fields (like per-event filter setting).
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
kernel/trace/trace_events.c | 92 ++++++++++++++++++++++++++-----------------
1 file changed, 55 insertions(+), 37 deletions(-)
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index a85effb2373b..a2531301b44f 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -2123,12 +2123,48 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
return NULL;
}
+static int
+event_define_fields(struct trace_event_call *call)
+{
+ struct list_head *head;
+ int ret = 0;
+
+ /*
+ * Other events may have the same class. Only update
+ * the fields if they are not already defined.
+ */
+ head = trace_get_fields(call);
+ if (list_empty(head)) {
+ struct trace_event_fields *field = call->class->fields_array;
+ unsigned int offset = sizeof(struct trace_entry);
+
+ for (; field->type; field++) {
+ if (field->type == TRACE_FUNCTION_TYPE) {
+ field->define_fields(call);
+ break;
+ }
+
+ offset = ALIGN(offset, field->align);
+ ret = trace_define_field(call, field->type, field->name,
+ offset, field->size,
+ field->is_signed, field->filter_type);
+ if (WARN_ON_ONCE(ret)) {
+ pr_err("error code is %d\n", ret);
+ break;
+ }
+
+ offset += field->size;
+ }
+ }
+
+ return ret;
+}
+
static int
event_create_dir(struct dentry *parent, struct trace_event_file *file)
{
struct trace_event_call *call = file->event_call;
struct trace_array *tr = file->tr;
- struct list_head *head;
struct dentry *d_events;
const char *name;
int ret;
@@ -2162,35 +2198,10 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file)
&ftrace_event_id_fops);
#endif
- /*
- * Other events may have the same class. Only update
- * the fields if they are not already defined.
- */
- head = trace_get_fields(call);
- if (list_empty(head)) {
- struct trace_event_fields *field = call->class->fields_array;
- unsigned int offset = sizeof(struct trace_entry);
-
- for (; field->type; field++) {
- if (field->type == TRACE_FUNCTION_TYPE) {
- ret = field->define_fields(call);
- break;
- }
-
- offset = ALIGN(offset, field->align);
- ret = trace_define_field(call, field->type, field->name,
- offset, field->size,
- field->is_signed, field->filter_type);
- if (ret)
- break;
-
- offset += field->size;
- }
- if (ret < 0) {
- pr_warn("Could not initialize trace point events/%s\n",
- name);
- return -1;
- }
+ ret = event_define_fields(call);
+ if (ret < 0) {
+ pr_warn("Could not initialize trace point events/%s\n", name);
+ return ret;
}
/*
@@ -2493,7 +2504,7 @@ __trace_early_add_new_event(struct trace_event_call *call,
if (!file)
return -ENOMEM;
- return 0;
+ return event_define_fields(call);
}
struct ftrace_module_file_ops;
@@ -3431,6 +3442,18 @@ static __init int event_trace_enable_again(void)
early_initcall(event_trace_enable_again);
+/* Init fields which doesn't related to the tracefs */
+static __init int event_trace_init_fields(void)
+{
+ if (trace_define_generic_fields())
+ pr_warn("tracing: Failed to allocated generic fields");
+
+ if (trace_define_common_fields())
+ pr_warn("tracing: Failed to allocate common fields");
+
+ return 0;
+}
+
__init int event_trace_init(void)
{
struct trace_array *tr;
@@ -3451,12 +3474,6 @@ __init int event_trace_init(void)
if (!entry)
pr_warn("Could not create tracefs 'available_events' entry\n");
- if (trace_define_generic_fields())
- pr_warn("tracing: Failed to allocated generic fields");
-
- if (trace_define_common_fields())
- pr_warn("tracing: Failed to allocate common fields");
-
ret = early_event_add_tracer(d_tracer, tr);
if (ret)
return ret;
@@ -3474,6 +3491,7 @@ void __init trace_event_init(void)
event_trace_memsetup();
init_ftrace_syscalls();
event_trace_enable();
+ event_trace_init_fields();
}
#ifdef CONFIG_EVENT_TRACE_STARTUP_TEST
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/6] tracing: Enable adding dynamic events early stage
2020-09-10 12:38 [PATCH 0/6] tracing/boot: Start boot-time tracing in earlier stage Masami Hiramatsu
2020-09-10 12:38 ` [PATCH 1/6] kprobes: Init kprobes in early_initcall Masami Hiramatsu
2020-09-10 12:38 ` [PATCH 2/6] tracing: Define event fields early stage Masami Hiramatsu
@ 2020-09-10 12:38 ` Masami Hiramatsu
2020-09-10 12:39 ` [PATCH 4/6] tracing: Enable creating new instance early boot Masami Hiramatsu
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Masami Hiramatsu @ 2020-09-10 12:38 UTC (permalink / raw)
To: Steven Rostedt, Jonathan Corbet
Cc: mhiramat, linux-kernel, linux-doc, Randy Dunlap, Ingo Molnar
Split the event fields initialization from creating new
event directory.
This allows the boot-time tracing to define dynamic events
before initializing events directory on tracefs.
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
kernel/trace/trace_events.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index a2531301b44f..720b0d72ea52 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -38,6 +38,7 @@ DEFINE_MUTEX(event_mutex);
LIST_HEAD(ftrace_events);
static LIST_HEAD(ftrace_generic_fields);
static LIST_HEAD(ftrace_common_fields);
+static bool eventdir_initialized;
#define GFP_TRACE (GFP_KERNEL | __GFP_ZERO)
@@ -2486,7 +2487,10 @@ __trace_add_new_event(struct trace_event_call *call, struct trace_array *tr)
if (!file)
return -ENOMEM;
- return event_create_dir(tr->event_dir, file);
+ if (eventdir_initialized)
+ return event_create_dir(tr->event_dir, file);
+ else
+ return event_define_fields(call);
}
/*
@@ -3483,6 +3487,9 @@ __init int event_trace_init(void)
if (ret)
pr_warn("Failed to register trace events module notifier\n");
#endif
+
+ eventdir_initialized = true;
+
return 0;
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/6] tracing: Enable creating new instance early boot
2020-09-10 12:38 [PATCH 0/6] tracing/boot: Start boot-time tracing in earlier stage Masami Hiramatsu
` (2 preceding siblings ...)
2020-09-10 12:38 ` [PATCH 3/6] tracing: Enable adding dynamic events " Masami Hiramatsu
@ 2020-09-10 12:39 ` Masami Hiramatsu
2020-09-10 12:39 ` [PATCH 5/6] tracing/boot,kprobe,synth: Initialize boot-time tracing earlier Masami Hiramatsu
2020-09-10 12:39 ` [PATCH 6/6] Documentation: tracing: Add the startup timing of boot-time tracing Masami Hiramatsu
5 siblings, 0 replies; 7+ messages in thread
From: Masami Hiramatsu @ 2020-09-10 12:39 UTC (permalink / raw)
To: Steven Rostedt, Jonathan Corbet
Cc: mhiramat, linux-kernel, linux-doc, Randy Dunlap, Ingo Molnar
Enable creating new trace_array instance in early boot stage.
If the instances directory is not created, postpone it until
the tracefs is initialized.
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
kernel/trace/trace.c | 53 ++++++++++++++++++++++++++++++++--------
kernel/trace/trace.h | 7 +++++
kernel/trace/trace_functions.c | 22 +++++++++++------
3 files changed, 63 insertions(+), 19 deletions(-)
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index faf55f5dd99d..f7696db52e7d 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -8636,6 +8636,24 @@ struct trace_array *trace_array_find_get(const char *instance)
return tr;
}
+static int trace_array_create_dir(struct trace_array *tr)
+{
+ int ret;
+
+ tr->dir = tracefs_create_dir(tr->name, trace_instance_dir);
+ if (!tr->dir)
+ return -EINVAL;
+
+ ret = event_trace_add_tracer(tr->dir, tr);
+ if (ret)
+ tracefs_remove(tr->dir);
+
+ init_tracer_tracefs(tr, tr->dir);
+ __update_tracer_options(tr);
+
+ return ret;
+}
+
static struct trace_array *trace_array_create(const char *name)
{
struct trace_array *tr;
@@ -8671,30 +8689,27 @@ static struct trace_array *trace_array_create(const char *name)
if (allocate_trace_buffers(tr, trace_buf_size) < 0)
goto out_free_tr;
- tr->dir = tracefs_create_dir(name, trace_instance_dir);
- if (!tr->dir)
- goto out_free_tr;
-
- ret = event_trace_add_tracer(tr->dir, tr);
- if (ret) {
- tracefs_remove(tr->dir);
+ if (ftrace_allocate_ftrace_ops(tr) < 0)
goto out_free_tr;
- }
ftrace_init_trace_array(tr);
- init_tracer_tracefs(tr, tr->dir);
init_trace_flags_index(tr);
- __update_tracer_options(tr);
+
+ if (trace_instance_dir) {
+ ret = trace_array_create_dir(tr);
+ if (ret)
+ goto out_free_tr;
+ }
list_add(&tr->list, &ftrace_trace_arrays);
tr->ref++;
-
return tr;
out_free_tr:
+ ftrace_free_ftrace_ops(tr);
free_trace_buffers(tr);
free_cpumask_var(tr->tracing_cpumask);
kfree(tr->name);
@@ -8853,11 +8868,27 @@ static int instance_rmdir(const char *name)
static __init void create_trace_instances(struct dentry *d_tracer)
{
+ struct trace_array *tr;
+
trace_instance_dir = tracefs_create_instance_dir("instances", d_tracer,
instance_mkdir,
instance_rmdir);
if (MEM_FAIL(!trace_instance_dir, "Failed to create instances directory\n"))
return;
+
+ mutex_lock(&event_mutex);
+ mutex_lock(&trace_types_lock);
+
+ list_for_each_entry(tr, &ftrace_trace_arrays, list) {
+ if (!tr->name)
+ continue;
+ if (MEM_FAIL(trace_array_create_dir(tr) < 0,
+ "Failed to create instance directory\n"))
+ break;
+ }
+
+ mutex_unlock(&trace_types_lock);
+ mutex_unlock(&event_mutex);
}
static void
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 610d21355526..e1b3061ce06d 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -1125,6 +1125,8 @@ extern int ftrace_is_dead(void);
int ftrace_create_function_files(struct trace_array *tr,
struct dentry *parent);
void ftrace_destroy_function_files(struct trace_array *tr);
+int ftrace_allocate_ftrace_ops(struct trace_array *tr);
+void ftrace_free_ftrace_ops(struct trace_array *tr);
void ftrace_init_global_array_ops(struct trace_array *tr);
void ftrace_init_array_ops(struct trace_array *tr, ftrace_func_t func);
void ftrace_reset_array_ops(struct trace_array *tr);
@@ -1146,6 +1148,11 @@ ftrace_create_function_files(struct trace_array *tr,
{
return 0;
}
+static inline int ftrace_allocate_ftrace_ops(struct trace_array *tr)
+{
+ return 0;
+}
+static inline void ftrace_free_ftrace_ops(struct trace_array *tr) { }
static inline void ftrace_destroy_function_files(struct trace_array *tr) { }
static inline __init void
ftrace_init_global_array_ops(struct trace_array *tr) { }
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index dd4dff71d89a..2c2126e1871d 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -34,10 +34,14 @@ enum {
TRACE_FUNC_OPT_STACK = 0x1,
};
-static int allocate_ftrace_ops(struct trace_array *tr)
+int ftrace_allocate_ftrace_ops(struct trace_array *tr)
{
struct ftrace_ops *ops;
+ /* The top level array uses the "global_ops" */
+ if (tr->flags & TRACE_ARRAY_FL_GLOBAL)
+ return 0;
+
ops = kzalloc(sizeof(*ops), GFP_KERNEL);
if (!ops)
return -ENOMEM;
@@ -48,15 +52,19 @@ static int allocate_ftrace_ops(struct trace_array *tr)
tr->ops = ops;
ops->private = tr;
+
return 0;
}
+void ftrace_free_ftrace_ops(struct trace_array *tr)
+{
+ kfree(tr->ops);
+ tr->ops = NULL;
+}
int ftrace_create_function_files(struct trace_array *tr,
struct dentry *parent)
{
- int ret;
-
/*
* The top level array uses the "global_ops", and the files are
* created on boot up.
@@ -64,9 +72,8 @@ int ftrace_create_function_files(struct trace_array *tr,
if (tr->flags & TRACE_ARRAY_FL_GLOBAL)
return 0;
- ret = allocate_ftrace_ops(tr);
- if (ret)
- return ret;
+ if (!tr->ops)
+ return -EINVAL;
ftrace_create_filter_files(tr->ops, parent);
@@ -76,8 +83,7 @@ int ftrace_create_function_files(struct trace_array *tr,
void ftrace_destroy_function_files(struct trace_array *tr)
{
ftrace_destroy_filter_files(tr->ops);
- kfree(tr->ops);
- tr->ops = NULL;
+ ftrace_free_ftrace_ops(tr);
}
static int function_trace_init(struct trace_array *tr)
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/6] tracing/boot,kprobe,synth: Initialize boot-time tracing earlier
2020-09-10 12:38 [PATCH 0/6] tracing/boot: Start boot-time tracing in earlier stage Masami Hiramatsu
` (3 preceding siblings ...)
2020-09-10 12:39 ` [PATCH 4/6] tracing: Enable creating new instance early boot Masami Hiramatsu
@ 2020-09-10 12:39 ` Masami Hiramatsu
2020-09-10 12:39 ` [PATCH 6/6] Documentation: tracing: Add the startup timing of boot-time tracing Masami Hiramatsu
5 siblings, 0 replies; 7+ messages in thread
From: Masami Hiramatsu @ 2020-09-10 12:39 UTC (permalink / raw)
To: Steven Rostedt, Jonathan Corbet
Cc: mhiramat, linux-kernel, linux-doc, Randy Dunlap, Ingo Molnar
Initialize boot-time tracing in core_initcall_sync instead of
fs_initcall, and initialize required tracers (kprobes and synth)
in core_initcall. This will allow the boot-time tracing to trace
__init code from the beginning of postcore_initcall stage.
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
kernel/trace/trace_boot.c | 7 +++++--
kernel/trace/trace_events_synth.c | 22 ++++++++++++++++------
kernel/trace/trace_kprobe.c | 6 +++---
3 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c
index d52d441a17e8..754e3cf2df3a 100644
--- a/kernel/trace/trace_boot.c
+++ b/kernel/trace/trace_boot.c
@@ -340,5 +340,8 @@ static int __init trace_boot_init(void)
return 0;
}
-
-fs_initcall(trace_boot_init);
+/*
+ * Start tracing at the end of core-initcall, so that it starts tracing
+ * from the beginning of postcore_initcall.
+ */
+core_initcall_sync(trace_boot_init);
diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c
index c6cca0d1d584..6eb77d95fd64 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -1754,17 +1754,27 @@ static const struct file_operations synth_events_fops = {
.release = seq_release,
};
-static __init int trace_events_synth_init(void)
+/*
+ * Register dynevent at core_initcall. This allows kernel to setup kprobe
+ * events in postcore_initcall without tracefs.
+ */
+static __init int trace_events_synth_init_early(void)
{
- struct dentry *entry = NULL;
- struct dentry *d_tracer;
int err = 0;
err = dyn_event_register(&synth_event_ops);
- if (err) {
+ if (err)
pr_warn("Could not register synth_event_ops\n");
- return err;
- }
+
+ return err;
+}
+core_initcall(trace_events_synth_init_early);
+
+static __init int trace_events_synth_init(void)
+{
+ struct dentry *entry = NULL;
+ struct dentry *d_tracer;
+ int err = 0;
d_tracer = tracing_init_dentry();
if (IS_ERR(d_tracer)) {
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index e33690a12255..a6a08199e79f 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -1896,8 +1896,8 @@ static __init void setup_boot_kprobe_events(void)
}
/*
- * Register dynevent at subsys_initcall. This allows kernel to setup kprobe
- * events in fs_initcall without tracefs.
+ * Register dynevent at core_initcall. This allows kernel to setup kprobe
+ * events in postcore_initcall without tracefs.
*/
static __init int init_kprobe_trace_early(void)
{
@@ -1912,7 +1912,7 @@ static __init int init_kprobe_trace_early(void)
return 0;
}
-subsys_initcall(init_kprobe_trace_early);
+core_initcall(init_kprobe_trace_early);
/* Make a tracefs interface for controlling probe points */
static __init int init_kprobe_trace(void)
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6/6] Documentation: tracing: Add the startup timing of boot-time tracing
2020-09-10 12:38 [PATCH 0/6] tracing/boot: Start boot-time tracing in earlier stage Masami Hiramatsu
` (4 preceding siblings ...)
2020-09-10 12:39 ` [PATCH 5/6] tracing/boot,kprobe,synth: Initialize boot-time tracing earlier Masami Hiramatsu
@ 2020-09-10 12:39 ` Masami Hiramatsu
5 siblings, 0 replies; 7+ messages in thread
From: Masami Hiramatsu @ 2020-09-10 12:39 UTC (permalink / raw)
To: Steven Rostedt, Jonathan Corbet
Cc: mhiramat, linux-kernel, linux-doc, Randy Dunlap, Ingo Molnar
Add the note about when to start the boot-time tracing.
This will be needed for the people who wants to trace
earlier boot sequence.
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
Documentation/trace/boottime-trace.rst | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/Documentation/trace/boottime-trace.rst b/Documentation/trace/boottime-trace.rst
index c216f5695ae2..3931b43f902c 100644
--- a/Documentation/trace/boottime-trace.rst
+++ b/Documentation/trace/boottime-trace.rst
@@ -120,6 +120,20 @@ instance node, but those are also visible from other instances. So please
take care for event name conflict.
+When to Start
+=============
+
+All boot-time tracing options starting with ``ftrace`` will be enabled at the
+end of core_initcall. This means you can trace the events from postcore_initcall.
+Most of the subsystems and architecture dependent drivers will be initialized
+after that (arch_initcall or subsys_initcall). Thus, you can trace those with
+boot-time tracing.
+If you want to trace events before core_initcall, you can use the options
+starting with ``kernel``. Some of them will be enabled eariler than the initcall
+processing (for example,. ``kernel.ftrace=function`` and ``kernel.trace_event``
+will start before the initcall.)
+
+
Examples
========
^ permalink raw reply related [flat|nested] 7+ messages in thread