Skip to content

Commit bd1a5c8

Browse files
Masami Hiramatsufweisbec
authored andcommitted
tracing: Ftrace dynamic ftrace_event_call support
Add dynamic ftrace_event_call support to ftrace. Trace engines can add new ftrace_event_call to ftrace on the fly. Each operator function of the call takes an ftrace_event_call data structure as an argument, because these functions may be shared among several ftrace_event_calls. Changes from v13: - Define remove_subsystem_dir() always (revirt a2ca5e0), because trace_remove_event_call() uses it. - Modify syscall tracer because of ftrace_event_call change. [[email protected]: Fixed conflict against latest tracing/core] Signed-off-by: Masami Hiramatsu <[email protected]> Cc: Ananth N Mavinakayanahalli <[email protected]> Cc: Avi Kivity <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: Frank Ch. Eigler <[email protected]> Cc: H. Peter Anvin <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Jason Baron <[email protected]> Cc: Jim Keniston <[email protected]> Cc: K.Prasad <[email protected]> Cc: Lai Jiangshan <[email protected]> Cc: Li Zefan <[email protected]> Cc: Przemysław Pawełczyk <[email protected]> Cc: Roland McGrath <[email protected]> Cc: Sam Ravnborg <[email protected]> Cc: Srikar Dronamraju <[email protected]> Cc: Steven Rostedt <[email protected]> Cc: Tom Zanussi <[email protected]> Cc: Vegard Nossum <[email protected]> LKML-Reference: <[email protected]> Signed-off-by: Frederic Weisbecker <[email protected]>
1 parent b1cf540 commit bd1a5c8

File tree

7 files changed

+130
-79
lines changed

7 files changed

+130
-79
lines changed

include/linux/ftrace_event.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,12 @@ struct ftrace_event_call {
112112
struct dentry *dir;
113113
struct trace_event *event;
114114
int enabled;
115-
int (*regfunc)(void *);
116-
void (*unregfunc)(void *);
115+
int (*regfunc)(struct ftrace_event_call *);
116+
void (*unregfunc)(struct ftrace_event_call *);
117117
int id;
118-
int (*raw_init)(void);
119-
int (*show_format)(struct ftrace_event_call *call,
120-
struct trace_seq *s);
118+
int (*raw_init)(struct ftrace_event_call *);
119+
int (*show_format)(struct ftrace_event_call *,
120+
struct trace_seq *);
121121
int (*define_fields)(struct ftrace_event_call *);
122122
struct list_head fields;
123123
int filter_active;
@@ -147,11 +147,12 @@ enum {
147147
FILTER_PTR_STRING,
148148
};
149149

150-
extern int trace_define_field(struct ftrace_event_call *call,
151-
const char *type, const char *name,
152-
int offset, int size, int is_signed,
153-
int filter_type);
154150
extern int trace_define_common_fields(struct ftrace_event_call *call);
151+
extern int trace_define_field(struct ftrace_event_call *call, char *type,
152+
char *name, int offset, int size, int is_signed,
153+
int filter_type);
154+
extern int trace_add_event_call(struct ftrace_event_call *call);
155+
extern void trace_remove_event_call(struct ftrace_event_call *call);
155156

156157
#define is_signed_type(type) (((type)(-1)) < 0)
157158

include/linux/syscalls.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ static void prof_sysexit_disable_##sname(struct ftrace_event_call *event_call) \
165165
struct trace_event enter_syscall_print_##sname = { \
166166
.trace = print_syscall_enter, \
167167
}; \
168-
static int init_enter_##sname(void) \
168+
static int init_enter_##sname(struct ftrace_event_call *call) \
169169
{ \
170170
int num, id; \
171171
num = syscall_name_to_nr("sys"#sname); \
@@ -202,7 +202,7 @@ static void prof_sysexit_disable_##sname(struct ftrace_event_call *event_call) \
202202
struct trace_event exit_syscall_print_##sname = { \
203203
.trace = print_syscall_exit, \
204204
}; \
205-
static int init_exit_##sname(void) \
205+
static int init_exit_##sname(struct ftrace_event_call *call) \
206206
{ \
207207
int num, id; \
208208
num = syscall_name_to_nr("sys"#sname); \

include/trace/ftrace.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\
434434
* event_trace_printk(_RET_IP_, "<call>: " <fmt>);
435435
* }
436436
*
437-
* static int ftrace_reg_event_<call>(void)
437+
* static int ftrace_reg_event_<call>(struct ftrace_event_call *unused)
438438
* {
439439
* int ret;
440440
*
@@ -445,7 +445,7 @@ static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\
445445
* return ret;
446446
* }
447447
*
448-
* static void ftrace_unreg_event_<call>(void)
448+
* static void ftrace_unreg_event_<call>(struct ftrace_event_call *unused)
449449
* {
450450
* unregister_trace_<call>(ftrace_event_<call>);
451451
* }
@@ -478,7 +478,7 @@ static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\
478478
* trace_current_buffer_unlock_commit(event, irq_flags, pc);
479479
* }
480480
*
481-
* static int ftrace_raw_reg_event_<call>(void)
481+
* static int ftrace_raw_reg_event_<call>(struct ftrace_event_call *unused)
482482
* {
483483
* int ret;
484484
*
@@ -489,7 +489,7 @@ static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\
489489
* return ret;
490490
* }
491491
*
492-
* static void ftrace_unreg_event_<call>(void)
492+
* static void ftrace_unreg_event_<call>(struct ftrace_event_call *unused)
493493
* {
494494
* unregister_trace_<call>(ftrace_raw_event_<call>);
495495
* }
@@ -498,7 +498,7 @@ static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\
498498
* .trace = ftrace_raw_output_<call>, <-- stage 2
499499
* };
500500
*
501-
* static int ftrace_raw_init_event_<call>(void)
501+
* static int ftrace_raw_init_event_<call>(struct ftrace_event_call *unused)
502502
* {
503503
* int id;
504504
*
@@ -592,7 +592,7 @@ static void ftrace_raw_event_##call(proto) \
592592
trace_nowake_buffer_unlock_commit(event, irq_flags, pc); \
593593
} \
594594
\
595-
static int ftrace_raw_reg_event_##call(void *ptr) \
595+
static int ftrace_raw_reg_event_##call(struct ftrace_event_call *unused)\
596596
{ \
597597
int ret; \
598598
\
@@ -603,7 +603,7 @@ static int ftrace_raw_reg_event_##call(void *ptr) \
603603
return ret; \
604604
} \
605605
\
606-
static void ftrace_raw_unreg_event_##call(void *ptr) \
606+
static void ftrace_raw_unreg_event_##call(struct ftrace_event_call *unused)\
607607
{ \
608608
unregister_trace_##call(ftrace_raw_event_##call); \
609609
} \
@@ -612,7 +612,7 @@ static struct trace_event ftrace_event_type_##call = { \
612612
.trace = ftrace_raw_output_##call, \
613613
}; \
614614
\
615-
static int ftrace_raw_init_event_##call(void) \
615+
static int ftrace_raw_init_event_##call(struct ftrace_event_call *unused)\
616616
{ \
617617
int id; \
618618
\

include/trace/syscall.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,19 @@ void set_syscall_enter_id(int num, int id);
3939
void set_syscall_exit_id(int num, int id);
4040
extern struct trace_event event_syscall_enter;
4141
extern struct trace_event event_syscall_exit;
42-
extern int reg_event_syscall_enter(void *ptr);
43-
extern void unreg_event_syscall_enter(void *ptr);
44-
extern int reg_event_syscall_exit(void *ptr);
45-
extern void unreg_event_syscall_exit(void *ptr);
42+
4643
extern int syscall_enter_format(struct ftrace_event_call *call,
4744
struct trace_seq *s);
4845
extern int syscall_exit_format(struct ftrace_event_call *call,
4946
struct trace_seq *s);
5047
extern int syscall_enter_define_fields(struct ftrace_event_call *call);
5148
extern int syscall_exit_define_fields(struct ftrace_event_call *call);
49+
extern int reg_event_syscall_enter(struct ftrace_event_call *call);
50+
extern void unreg_event_syscall_enter(struct ftrace_event_call *call);
51+
extern int reg_event_syscall_exit(struct ftrace_event_call *call);
52+
extern void unreg_event_syscall_exit(struct ftrace_event_call *call);
53+
extern int
54+
ftrace_format_syscall(struct ftrace_event_call *call, struct trace_seq *s);
5255
enum print_line_t print_syscall_enter(struct trace_iterator *iter, int flags);
5356
enum print_line_t print_syscall_exit(struct trace_iterator *iter, int flags);
5457
#endif

kernel/trace/trace_events.c

Lines changed: 84 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ DEFINE_MUTEX(event_mutex);
2727

2828
LIST_HEAD(ftrace_events);
2929

30-
int trace_define_field(struct ftrace_event_call *call, const char *type,
31-
const char *name, int offset, int size, int is_signed,
30+
int trace_define_field(struct ftrace_event_call *call, char *type,
31+
char *name, int offset, int size, int is_signed,
3232
int filter_type)
3333
{
3434
struct ftrace_event_field *field;
@@ -92,9 +92,7 @@ int trace_define_common_fields(struct ftrace_event_call *call)
9292
}
9393
EXPORT_SYMBOL_GPL(trace_define_common_fields);
9494

95-
#ifdef CONFIG_MODULES
96-
97-
static void trace_destroy_fields(struct ftrace_event_call *call)
95+
void trace_destroy_fields(struct ftrace_event_call *call)
9896
{
9997
struct ftrace_event_field *field, *next;
10098

@@ -106,8 +104,6 @@ static void trace_destroy_fields(struct ftrace_event_call *call)
106104
}
107105
}
108106

109-
#endif /* CONFIG_MODULES */
110-
111107
static void ftrace_event_enable_disable(struct ftrace_event_call *call,
112108
int enable)
113109
{
@@ -116,14 +112,14 @@ static void ftrace_event_enable_disable(struct ftrace_event_call *call,
116112
if (call->enabled) {
117113
call->enabled = 0;
118114
tracing_stop_cmdline_record();
119-
call->unregfunc(call->data);
115+
call->unregfunc(call);
120116
}
121117
break;
122118
case 1:
123119
if (!call->enabled) {
124120
call->enabled = 1;
125121
tracing_start_cmdline_record();
126-
call->regfunc(call->data);
122+
call->regfunc(call);
127123
}
128124
break;
129125
}
@@ -991,27 +987,43 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
991987
return 0;
992988
}
993989

994-
#define for_each_event(event, start, end) \
995-
for (event = start; \
996-
(unsigned long)event < (unsigned long)end; \
997-
event++)
990+
static int __trace_add_event_call(struct ftrace_event_call *call)
991+
{
992+
struct dentry *d_events;
993+
int ret;
998994

999-
#ifdef CONFIG_MODULES
995+
if (!call->name)
996+
return -EINVAL;
1000997

1001-
static LIST_HEAD(ftrace_module_file_list);
998+
if (call->raw_init) {
999+
ret = call->raw_init(call);
1000+
if (ret < 0) {
1001+
if (ret != -ENOSYS)
1002+
pr_warning("Could not initialize trace "
1003+
"events/%s\n", call->name);
1004+
return ret;
1005+
}
1006+
}
10021007

1003-
/*
1004-
* Modules must own their file_operations to keep up with
1005-
* reference counting.
1006-
*/
1007-
struct ftrace_module_file_ops {
1008-
struct list_head list;
1009-
struct module *mod;
1010-
struct file_operations id;
1011-
struct file_operations enable;
1012-
struct file_operations format;
1013-
struct file_operations filter;
1014-
};
1008+
d_events = event_trace_events_dir();
1009+
if (!d_events)
1010+
return -ENOENT;
1011+
1012+
list_add(&call->list, &ftrace_events);
1013+
return event_create_dir(call, d_events, &ftrace_event_id_fops,
1014+
&ftrace_enable_fops, &ftrace_event_filter_fops,
1015+
&ftrace_event_format_fops);
1016+
}
1017+
1018+
/* Add an additional event_call dynamically */
1019+
int trace_add_event_call(struct ftrace_event_call *call)
1020+
{
1021+
int ret;
1022+
mutex_lock(&event_mutex);
1023+
ret = __trace_add_event_call(call);
1024+
mutex_unlock(&event_mutex);
1025+
return ret;
1026+
}
10151027

10161028
static void remove_subsystem_dir(const char *name)
10171029
{
@@ -1039,6 +1051,48 @@ static void remove_subsystem_dir(const char *name)
10391051
}
10401052
}
10411053

1054+
static void __trace_remove_event_call(struct ftrace_event_call *call)
1055+
{
1056+
ftrace_event_enable_disable(call, 0);
1057+
if (call->event)
1058+
__unregister_ftrace_event(call->event);
1059+
debugfs_remove_recursive(call->dir);
1060+
list_del(&call->list);
1061+
trace_destroy_fields(call);
1062+
destroy_preds(call);
1063+
remove_subsystem_dir(call->system);
1064+
}
1065+
1066+
/* Remove an event_call */
1067+
void trace_remove_event_call(struct ftrace_event_call *call)
1068+
{
1069+
mutex_lock(&event_mutex);
1070+
__trace_remove_event_call(call);
1071+
mutex_unlock(&event_mutex);
1072+
}
1073+
1074+
#define for_each_event(event, start, end) \
1075+
for (event = start; \
1076+
(unsigned long)event < (unsigned long)end; \
1077+
event++)
1078+
1079+
#ifdef CONFIG_MODULES
1080+
1081+
static LIST_HEAD(ftrace_module_file_list);
1082+
1083+
/*
1084+
* Modules must own their file_operations to keep up with
1085+
* reference counting.
1086+
*/
1087+
struct ftrace_module_file_ops {
1088+
struct list_head list;
1089+
struct module *mod;
1090+
struct file_operations id;
1091+
struct file_operations enable;
1092+
struct file_operations format;
1093+
struct file_operations filter;
1094+
};
1095+
10421096
static struct ftrace_module_file_ops *
10431097
trace_create_file_ops(struct module *mod)
10441098
{
@@ -1096,7 +1150,7 @@ static void trace_module_add_events(struct module *mod)
10961150
if (!call->name)
10971151
continue;
10981152
if (call->raw_init) {
1099-
ret = call->raw_init();
1153+
ret = call->raw_init(call);
11001154
if (ret < 0) {
11011155
if (ret != -ENOSYS)
11021156
pr_warning("Could not initialize trace "
@@ -1131,14 +1185,7 @@ static void trace_module_remove_events(struct module *mod)
11311185
list_for_each_entry_safe(call, p, &ftrace_events, list) {
11321186
if (call->mod == mod) {
11331187
found = true;
1134-
ftrace_event_enable_disable(call, 0);
1135-
if (call->event)
1136-
__unregister_ftrace_event(call->event);
1137-
debugfs_remove_recursive(call->dir);
1138-
list_del(&call->list);
1139-
trace_destroy_fields(call);
1140-
destroy_preds(call);
1141-
remove_subsystem_dir(call->system);
1188+
__trace_remove_event_call(call);
11421189
}
11431190
}
11441191

@@ -1256,7 +1303,7 @@ static __init int event_trace_init(void)
12561303
if (!call->name)
12571304
continue;
12581305
if (call->raw_init) {
1259-
ret = call->raw_init();
1306+
ret = call->raw_init(call);
12601307
if (ret < 0) {
12611308
if (ret != -ENOSYS)
12621309
pr_warning("Could not initialize trace "

kernel/trace/trace_export.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,27 +117,27 @@ ftrace_format_##call(struct ftrace_event_call *unused, \
117117
#define TRACE_FIELD_SPECIAL(type_item, item, len, cmd) \
118118
cmd;
119119

120+
static int ftrace_raw_init_event(struct ftrace_event_call *event_call)
121+
{
122+
INIT_LIST_HEAD(&event_call->fields);
123+
init_preds(event_call);
124+
return 0;
125+
}
126+
120127
#undef TRACE_EVENT_FORMAT
121128
#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
122129
int ftrace_define_fields_##call(struct ftrace_event_call *event_call); \
123-
static int ftrace_raw_init_event_##call(void); \
124130
\
125131
struct ftrace_event_call __used \
126132
__attribute__((__aligned__(4))) \
127133
__attribute__((section("_ftrace_events"))) event_##call = { \
128134
.name = #call, \
129135
.id = proto, \
130136
.system = __stringify(TRACE_SYSTEM), \
131-
.raw_init = ftrace_raw_init_event_##call, \
137+
.raw_init = ftrace_raw_init_event, \
132138
.show_format = ftrace_format_##call, \
133139
.define_fields = ftrace_define_fields_##call, \
134-
}; \
135-
static int ftrace_raw_init_event_##call(void) \
136-
{ \
137-
INIT_LIST_HEAD(&event_##call.fields); \
138-
init_preds(&event_##call); \
139-
return 0; \
140-
} \
140+
};
141141

142142
#undef TRACE_EVENT_FORMAT_NOFILTER
143143
#define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct, \

0 commit comments

Comments
 (0)