aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace.h3
-rw-r--r--kernel/trace/trace_events.c48
-rw-r--r--kernel/trace/trace_events_filter.c10
-rw-r--r--kernel/trace/trace_export.c14
-rw-r--r--kernel/trace/trace_kprobe.c8
-rw-r--r--kernel/trace/trace_syscalls.c31
6 files changed, 83 insertions, 31 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 911e9864e94a..c88c563a59a5 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -794,6 +794,9 @@ extern void print_subsystem_event_filter(struct event_subsystem *system,
794 struct trace_seq *s); 794 struct trace_seq *s);
795extern int filter_assign_type(const char *type); 795extern int filter_assign_type(const char *type);
796 796
797struct list_head *
798trace_get_fields(struct ftrace_event_call *event_call);
799
797static inline int 800static inline int
798filter_check_discard(struct ftrace_event_call *call, void *rec, 801filter_check_discard(struct ftrace_event_call *call, void *rec,
799 struct ring_buffer *buffer, 802 struct ring_buffer *buffer,
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 19d1eb0a7188..acc0f55742c3 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -29,11 +29,23 @@ DEFINE_MUTEX(event_mutex);
29 29
30LIST_HEAD(ftrace_events); 30LIST_HEAD(ftrace_events);
31 31
32struct list_head *
33trace_get_fields(struct ftrace_event_call *event_call)
34{
35 if (!event_call->class->get_fields)
36 return &event_call->class->fields;
37 return event_call->class->get_fields(event_call);
38}
39
32int trace_define_field(struct ftrace_event_call *call, const char *type, 40int trace_define_field(struct ftrace_event_call *call, const char *type,
33 const char *name, int offset, int size, int is_signed, 41 const char *name, int offset, int size, int is_signed,
34 int filter_type) 42 int filter_type)
35{ 43{
36 struct ftrace_event_field *field; 44 struct ftrace_event_field *field;
45 struct list_head *head;
46
47 if (WARN_ON(!call->class))
48 return 0;
37 49
38 field = kzalloc(sizeof(*field), GFP_KERNEL); 50 field = kzalloc(sizeof(*field), GFP_KERNEL);
39 if (!field) 51 if (!field)
@@ -56,7 +68,8 @@ int trace_define_field(struct ftrace_event_call *call, const char *type,
56 field->size = size; 68 field->size = size;
57 field->is_signed = is_signed; 69 field->is_signed = is_signed;
58 70
59 list_add(&field->link, &call->fields); 71 head = trace_get_fields(call);
72 list_add(&field->link, head);
60 73
61 return 0; 74 return 0;
62 75
@@ -94,8 +107,10 @@ static int trace_define_common_fields(struct ftrace_event_call *call)
94void trace_destroy_fields(struct ftrace_event_call *call) 107void trace_destroy_fields(struct ftrace_event_call *call)
95{ 108{
96 struct ftrace_event_field *field, *next; 109 struct ftrace_event_field *field, *next;
110 struct list_head *head;
97 111
98 list_for_each_entry_safe(field, next, &call->fields, link) { 112 head = trace_get_fields(call);
113 list_for_each_entry_safe(field, next, head, link) {
99 list_del(&field->link); 114 list_del(&field->link);
100 kfree(field->type); 115 kfree(field->type);
101 kfree(field->name); 116 kfree(field->name);
@@ -111,7 +126,6 @@ int trace_event_raw_init(struct ftrace_event_call *call)
111 if (!id) 126 if (!id)
112 return -ENODEV; 127 return -ENODEV;
113 call->id = id; 128 call->id = id;
114 INIT_LIST_HEAD(&call->fields);
115 129
116 return 0; 130 return 0;
117} 131}
@@ -537,6 +551,7 @@ event_format_read(struct file *filp, char __user *ubuf, size_t cnt,
537{ 551{
538 struct ftrace_event_call *call = filp->private_data; 552 struct ftrace_event_call *call = filp->private_data;
539 struct ftrace_event_field *field; 553 struct ftrace_event_field *field;
554 struct list_head *head;
540 struct trace_seq *s; 555 struct trace_seq *s;
541 int common_field_count = 5; 556 int common_field_count = 5;
542 char *buf; 557 char *buf;
@@ -555,7 +570,8 @@ event_format_read(struct file *filp, char __user *ubuf, size_t cnt,
555 trace_seq_printf(s, "ID: %d\n", call->id); 570 trace_seq_printf(s, "ID: %d\n", call->id);
556 trace_seq_printf(s, "format:\n"); 571 trace_seq_printf(s, "format:\n");
557 572
558 list_for_each_entry_reverse(field, &call->fields, link) { 573 head = trace_get_fields(call);
574 list_for_each_entry_reverse(field, head, link) {
559 /* 575 /*
560 * Smartly shows the array type(except dynamic array). 576 * Smartly shows the array type(except dynamic array).
561 * Normal: 577 * Normal:
@@ -931,6 +947,7 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
931 const struct file_operations *filter, 947 const struct file_operations *filter,
932 const struct file_operations *format) 948 const struct file_operations *format)
933{ 949{
950 struct list_head *head;
934 int ret; 951 int ret;
935 952
936 /* 953 /*
@@ -957,14 +974,21 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
957 id); 974 id);
958#endif 975#endif
959 976
960 if (call->define_fields) { 977 if (call->class->define_fields) {
961 ret = trace_define_common_fields(call); 978 /*
962 if (!ret) 979 * Other events may have the same class. Only update
963 ret = call->define_fields(call); 980 * the fields if they are not already defined.
964 if (ret < 0) { 981 */
965 pr_warning("Could not initialize trace point" 982 head = trace_get_fields(call);
966 " events/%s\n", call->name); 983 if (list_empty(head)) {
967 return ret; 984 ret = trace_define_common_fields(call);
985 if (!ret)
986 ret = call->class->define_fields(call);
987 if (ret < 0) {
988 pr_warning("Could not initialize trace point"
989 " events/%s\n", call->name);
990 return ret;
991 }
968 } 992 }
969 trace_create_file("filter", 0644, call->dir, call, 993 trace_create_file("filter", 0644, call->dir, call,
970 filter); 994 filter);
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index ca329603d0bf..961f99b74bdd 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -500,8 +500,10 @@ static struct ftrace_event_field *
500find_event_field(struct ftrace_event_call *call, char *name) 500find_event_field(struct ftrace_event_call *call, char *name)
501{ 501{
502 struct ftrace_event_field *field; 502 struct ftrace_event_field *field;
503 struct list_head *head;
503 504
504 list_for_each_entry(field, &call->fields, link) { 505 head = trace_get_fields(call);
506 list_for_each_entry(field, head, link) {
505 if (!strcmp(field->name, name)) 507 if (!strcmp(field->name, name))
506 return field; 508 return field;
507 } 509 }
@@ -625,7 +627,7 @@ static int init_subsystem_preds(struct event_subsystem *system)
625 int err; 627 int err;
626 628
627 list_for_each_entry(call, &ftrace_events, list) { 629 list_for_each_entry(call, &ftrace_events, list) {
628 if (!call->define_fields) 630 if (!call->class || !call->class->define_fields)
629 continue; 631 continue;
630 632
631 if (strcmp(call->class->system, system->name) != 0) 633 if (strcmp(call->class->system, system->name) != 0)
@@ -644,7 +646,7 @@ static void filter_free_subsystem_preds(struct event_subsystem *system)
644 struct ftrace_event_call *call; 646 struct ftrace_event_call *call;
645 647
646 list_for_each_entry(call, &ftrace_events, list) { 648 list_for_each_entry(call, &ftrace_events, list) {
647 if (!call->define_fields) 649 if (!call->class || !call->class->define_fields)
648 continue; 650 continue;
649 651
650 if (strcmp(call->class->system, system->name) != 0) 652 if (strcmp(call->class->system, system->name) != 0)
@@ -1249,7 +1251,7 @@ static int replace_system_preds(struct event_subsystem *system,
1249 list_for_each_entry(call, &ftrace_events, list) { 1251 list_for_each_entry(call, &ftrace_events, list) {
1250 struct event_filter *filter = call->filter; 1252 struct event_filter *filter = call->filter;
1251 1253
1252 if (!call->define_fields) 1254 if (!call->class || !call->class->define_fields)
1253 continue; 1255 continue;
1254 1256
1255 if (strcmp(call->class->system, system->name) != 0) 1257 if (strcmp(call->class->system, system->name) != 0)
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c
index 7f16e2163817..e700a0c1803f 100644
--- a/kernel/trace/trace_export.c
+++ b/kernel/trace/trace_export.c
@@ -18,10 +18,6 @@
18#undef TRACE_SYSTEM 18#undef TRACE_SYSTEM
19#define TRACE_SYSTEM ftrace 19#define TRACE_SYSTEM ftrace
20 20
21struct ftrace_event_class event_class_ftrace = {
22 .system = __stringify(TRACE_SYSTEM),
23};
24
25/* not needed for this file */ 21/* not needed for this file */
26#undef __field_struct 22#undef __field_struct
27#define __field_struct(type, item) 23#define __field_struct(type, item)
@@ -131,7 +127,7 @@ ftrace_define_fields_##name(struct ftrace_event_call *event_call) \
131 127
132static int ftrace_raw_init_event(struct ftrace_event_call *call) 128static int ftrace_raw_init_event(struct ftrace_event_call *call)
133{ 129{
134 INIT_LIST_HEAD(&call->fields); 130 INIT_LIST_HEAD(&call->class->fields);
135 return 0; 131 return 0;
136} 132}
137 133
@@ -159,15 +155,19 @@ static int ftrace_raw_init_event(struct ftrace_event_call *call)
159#undef FTRACE_ENTRY 155#undef FTRACE_ENTRY
160#define FTRACE_ENTRY(call, struct_name, type, tstruct, print) \ 156#define FTRACE_ENTRY(call, struct_name, type, tstruct, print) \
161 \ 157 \
158struct ftrace_event_class event_class_ftrace_##call = { \
159 .system = __stringify(TRACE_SYSTEM), \
160 .define_fields = ftrace_define_fields_##call, \
161}; \
162 \
162struct ftrace_event_call __used \ 163struct ftrace_event_call __used \
163__attribute__((__aligned__(4))) \ 164__attribute__((__aligned__(4))) \
164__attribute__((section("_ftrace_events"))) event_##call = { \ 165__attribute__((section("_ftrace_events"))) event_##call = { \
165 .name = #call, \ 166 .name = #call, \
166 .id = type, \ 167 .id = type, \
167 .class = &event_class_ftrace, \ 168 .class = &event_class_ftrace_##call, \
168 .raw_init = ftrace_raw_init_event, \ 169 .raw_init = ftrace_raw_init_event, \
169 .print_fmt = print, \ 170 .print_fmt = print, \
170 .define_fields = ftrace_define_fields_##call, \
171}; \ 171}; \
172 172
173#include "trace_entries.h" 173#include "trace_entries.h"
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index f8af21a53f0c..b14bf745356f 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -1112,8 +1112,6 @@ static void probe_event_disable(struct ftrace_event_call *call)
1112 1112
1113static int probe_event_raw_init(struct ftrace_event_call *event_call) 1113static int probe_event_raw_init(struct ftrace_event_call *event_call)
1114{ 1114{
1115 INIT_LIST_HEAD(&event_call->fields);
1116
1117 return 0; 1115 return 0;
1118} 1116}
1119 1117
@@ -1362,11 +1360,13 @@ static int register_probe_event(struct trace_probe *tp)
1362 if (probe_is_return(tp)) { 1360 if (probe_is_return(tp)) {
1363 tp->event.trace = print_kretprobe_event; 1361 tp->event.trace = print_kretprobe_event;
1364 call->raw_init = probe_event_raw_init; 1362 call->raw_init = probe_event_raw_init;
1365 call->define_fields = kretprobe_event_define_fields; 1363 INIT_LIST_HEAD(&call->class->fields);
1364 call->class->define_fields = kretprobe_event_define_fields;
1366 } else { 1365 } else {
1367 tp->event.trace = print_kprobe_event; 1366 tp->event.trace = print_kprobe_event;
1368 call->raw_init = probe_event_raw_init; 1367 call->raw_init = probe_event_raw_init;
1369 call->define_fields = kprobe_event_define_fields; 1368 INIT_LIST_HEAD(&call->class->fields);
1369 call->class->define_fields = kprobe_event_define_fields;
1370 } 1370 }
1371 if (set_print_fmt(tp) < 0) 1371 if (set_print_fmt(tp) < 0)
1372 return -ENOMEM; 1372 return -ENOMEM;
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index a21d366cae46..cceccf0d2e91 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -20,14 +20,37 @@ static int syscall_enter_register(struct ftrace_event_call *event,
20static int syscall_exit_register(struct ftrace_event_call *event, 20static int syscall_exit_register(struct ftrace_event_call *event,
21 enum trace_reg type); 21 enum trace_reg type);
22 22
23static int syscall_enter_define_fields(struct ftrace_event_call *call);
24static int syscall_exit_define_fields(struct ftrace_event_call *call);
25
26static struct list_head *
27syscall_get_enter_fields(struct ftrace_event_call *call)
28{
29 struct syscall_metadata *entry = call->data;
30
31 return &entry->enter_fields;
32}
33
34static struct list_head *
35syscall_get_exit_fields(struct ftrace_event_call *call)
36{
37 struct syscall_metadata *entry = call->data;
38
39 return &entry->exit_fields;
40}
41
23struct ftrace_event_class event_class_syscall_enter = { 42struct ftrace_event_class event_class_syscall_enter = {
24 .system = "syscalls", 43 .system = "syscalls",
25 .reg = syscall_enter_register 44 .reg = syscall_enter_register,
45 .define_fields = syscall_enter_define_fields,
46 .get_fields = syscall_get_enter_fields,
26}; 47};
27 48
28struct ftrace_event_class event_class_syscall_exit = { 49struct ftrace_event_class event_class_syscall_exit = {
29 .system = "syscalls", 50 .system = "syscalls",
30 .reg = syscall_exit_register 51 .reg = syscall_exit_register,
52 .define_fields = syscall_exit_define_fields,
53 .get_fields = syscall_get_exit_fields,
31}; 54};
32 55
33extern unsigned long __start_syscalls_metadata[]; 56extern unsigned long __start_syscalls_metadata[];
@@ -220,7 +243,7 @@ static void free_syscall_print_fmt(struct ftrace_event_call *call)
220 kfree(call->print_fmt); 243 kfree(call->print_fmt);
221} 244}
222 245
223int syscall_enter_define_fields(struct ftrace_event_call *call) 246static int syscall_enter_define_fields(struct ftrace_event_call *call)
224{ 247{
225 struct syscall_trace_enter trace; 248 struct syscall_trace_enter trace;
226 struct syscall_metadata *meta = call->data; 249 struct syscall_metadata *meta = call->data;
@@ -243,7 +266,7 @@ int syscall_enter_define_fields(struct ftrace_event_call *call)
243 return ret; 266 return ret;
244} 267}
245 268
246int syscall_exit_define_fields(struct ftrace_event_call *call) 269static int syscall_exit_define_fields(struct ftrace_event_call *call)
247{ 270{
248 struct syscall_trace_exit trace; 271 struct syscall_trace_exit trace;
249 int ret; 272 int ret;