Skip to content

Commit

Permalink
tracing: Replace trace_event struct array with pointer array
Browse files Browse the repository at this point in the history
Currently the trace_event structures are placed in the _ftrace_events
section, and at link time, the linker makes one large array of all
the trace_event structures. On boot up, this array is read (much like
the initcall sections) and the events are processed.

The problem is that there is no guarantee that gcc will place complex
structures nicely together in an array format. Two structures in the
same file may be placed awkwardly, because gcc has no clue that they
are suppose to be in an array.

A hack was used previous to force the alignment to 4, to pack the
structures together. But this caused alignment issues with other
architectures (sparc).

Instead of packing the structures into an array, the structures' addresses
are now put into the _ftrace_event section. As pointers are always the
natural alignment, gcc should always pack them tightly together
(otherwise initcall, extable, etc would also fail).

By having the pointers to the structures in the section, we can still
iterate the trace_events without causing unnecessary alignment problems
with other architectures, or depending on the current behaviour of
gcc that will likely change in the future just to tick us kernel developers
off a little more.

The _ftrace_event section is also moved into the .init.data section
as it is now only needed at boot up.

Suggested-by: David Miller <[email protected]>
Cc: Mathieu Desnoyers <[email protected]>
Acked-by: David S. Miller <[email protected]>
Signed-off-by: Steven Rostedt <[email protected]>
  • Loading branch information
Steven Rostedt authored and rostedt committed Feb 3, 2011
1 parent 9ffdc6c commit e4a9ea5
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 29 deletions.
7 changes: 3 additions & 4 deletions include/asm-generic/vmlinux.lds.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@
#endif

#ifdef CONFIG_EVENT_TRACING
#define FTRACE_EVENTS() VMLINUX_SYMBOL(__start_ftrace_events) = .; \
#define FTRACE_EVENTS() . = ALIGN(8); \
VMLINUX_SYMBOL(__start_ftrace_events) = .; \
*(_ftrace_events) \
VMLINUX_SYMBOL(__stop_ftrace_events) = .;
#else
Expand Down Expand Up @@ -179,9 +180,6 @@
TRACE_PRINTKS() \
\
STRUCT_ALIGN(); \
FTRACE_EVENTS() \
\
STRUCT_ALIGN(); \
TRACE_SYSCALLS()

/*
Expand Down Expand Up @@ -482,6 +480,7 @@
KERNEL_CTORS() \
*(.init.rodata) \
MCOUNT_REC() \
FTRACE_EVENTS() \
DEV_DISCARD(init.rodata) \
CPU_DISCARD(init.rodata) \
MEM_DISCARD(init.rodata) \
Expand Down
2 changes: 1 addition & 1 deletion include/linux/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ struct module
unsigned int num_trace_bprintk_fmt;
#endif
#ifdef CONFIG_EVENT_TRACING
struct ftrace_event_call *trace_events;
struct ftrace_event_call **trace_events;
unsigned int num_trace_events;
#endif
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
Expand Down
10 changes: 6 additions & 4 deletions include/linux/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,28 +128,30 @@ extern struct trace_event_functions exit_syscall_print_funcs;
static struct syscall_metadata \
__attribute__((__aligned__(4))) __syscall_meta_##sname; \
static struct ftrace_event_call __used \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) \
event_enter_##sname = { \
.name = "sys_enter"#sname, \
.class = &event_class_syscall_enter, \
.event.funcs = &enter_syscall_print_funcs, \
.data = (void *)&__syscall_meta_##sname,\
}; \
static struct ftrace_event_call __used \
__attribute__((section("_ftrace_events"))) \
*__event_enter_##sname = &event_enter_##sname; \
__TRACE_EVENT_FLAGS(enter_##sname, TRACE_EVENT_FL_CAP_ANY)

#define SYSCALL_TRACE_EXIT_EVENT(sname) \
static struct syscall_metadata \
__attribute__((__aligned__(4))) __syscall_meta_##sname; \
static struct ftrace_event_call __used \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) \
event_exit_##sname = { \
.name = "sys_exit"#sname, \
.class = &event_class_syscall_exit, \
.event.funcs = &exit_syscall_print_funcs, \
.data = (void *)&__syscall_meta_##sname,\
}; \
static struct ftrace_event_call __used \
__attribute__((section("_ftrace_events"))) \
*__event_exit_##sname = &event_exit_##sname; \
__TRACE_EVENT_FLAGS(exit_##sname, TRACE_EVENT_FL_CAP_ANY)

#define SYSCALL_METADATA(sname, nb) \
Expand Down
24 changes: 13 additions & 11 deletions include/trace/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -446,14 +446,16 @@ static inline notrace int ftrace_get_offsets_##call( \
* .reg = ftrace_event_reg,
* };
*
* static struct ftrace_event_call __used
* __attribute__((__aligned__(4)))
* __attribute__((section("_ftrace_events"))) event_<call> = {
* static struct ftrace_event_call event_<call> = {
* .name = "<call>",
* .class = event_class_<template>,
* .event = &ftrace_event_type_<call>,
* .print_fmt = print_fmt_<call>,
* };
* // its only safe to use pointers when doing linker tricks to
* // create an array.
* static struct ftrace_event_call __used
* __attribute__((section("_ftrace_events"))) *__event_<call> = &event_<call>;
*
*/

Expand Down Expand Up @@ -579,28 +581,28 @@ static struct ftrace_event_class __used event_class_##call = { \
#undef DEFINE_EVENT
#define DEFINE_EVENT(template, call, proto, args) \
\
static struct ftrace_event_call __used \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) event_##call = { \
static struct ftrace_event_call __used event_##call = { \
.name = #call, \
.class = &event_class_##template, \
.event.funcs = &ftrace_event_type_funcs_##template, \
.print_fmt = print_fmt_##template, \
};
}; \
static struct ftrace_event_call __used \
__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call

#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, call, proto, args, print) \
\
static const char print_fmt_##call[] = print; \
\
static struct ftrace_event_call __used \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) event_##call = { \
static struct ftrace_event_call __used event_##call = { \
.name = #call, \
.class = &event_class_##template, \
.event.funcs = &ftrace_event_type_funcs_##call, \
.print_fmt = print_fmt_##call, \
}
}; \
static struct ftrace_event_call __used \
__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call

#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)

Expand Down
12 changes: 6 additions & 6 deletions kernel/trace/trace_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,7 @@ trace_create_file_ops(struct module *mod)
static void trace_module_add_events(struct module *mod)
{
struct ftrace_module_file_ops *file_ops = NULL;
struct ftrace_event_call *call, *start, *end;
struct ftrace_event_call **call, **start, **end;

start = mod->trace_events;
end = mod->trace_events + mod->num_trace_events;
Expand All @@ -1297,7 +1297,7 @@ static void trace_module_add_events(struct module *mod)
return;

for_each_event(call, start, end) {
__trace_add_event_call(call, mod,
__trace_add_event_call(*call, mod,
&file_ops->id, &file_ops->enable,
&file_ops->filter, &file_ops->format);
}
Expand Down Expand Up @@ -1367,8 +1367,8 @@ static struct notifier_block trace_module_nb = {
.priority = 0,
};

extern struct ftrace_event_call __start_ftrace_events[];
extern struct ftrace_event_call __stop_ftrace_events[];
extern struct ftrace_event_call *__start_ftrace_events[];
extern struct ftrace_event_call *__stop_ftrace_events[];

static char bootup_event_buf[COMMAND_LINE_SIZE] __initdata;

Expand All @@ -1384,7 +1384,7 @@ __setup("trace_event=", setup_trace_event);

static __init int event_trace_init(void)
{
struct ftrace_event_call *call;
struct ftrace_event_call **call;
struct dentry *d_tracer;
struct dentry *entry;
struct dentry *d_events;
Expand Down Expand Up @@ -1430,7 +1430,7 @@ static __init int event_trace_init(void)
pr_warning("tracing: Failed to allocate common fields");

for_each_event(call, __start_ftrace_events, __stop_ftrace_events) {
__trace_add_event_call(call, NULL, &ftrace_event_id_fops,
__trace_add_event_call(*call, NULL, &ftrace_event_id_fops,
&ftrace_enable_fops,
&ftrace_event_filter_fops,
&ftrace_event_format_fops);
Expand Down
6 changes: 3 additions & 3 deletions kernel/trace/trace_export.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,13 @@ struct ftrace_event_class event_class_ftrace_##call = { \
.fields = LIST_HEAD_INIT(event_class_ftrace_##call.fields),\
}; \
\
struct ftrace_event_call __used \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) event_##call = { \
struct ftrace_event_call __used event_##call = { \
.name = #call, \
.event.type = etype, \
.class = &event_class_ftrace_##call, \
.print_fmt = print, \
}; \
struct ftrace_event_call __used \
__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call;

#include "trace_entries.h"

0 comments on commit e4a9ea5

Please sign in to comment.