aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_events.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-04-22 10:35:55 -0400
committerSteven Rostedt <rostedt@goodmis.org>2010-05-14 14:20:23 -0400
commit2e33af029556cb8bd22bf4f86f42d540249177ea (patch)
tree8a479d21300c7692d61093846054f626e3e71ed5 /kernel/trace/trace_events.c
parent2239291aeb0379fe47980b0e560e0eb9fd7e82ec (diff)
tracing: Move fields from event to class structure
Move the defined fields from the event to the class structure. Since the fields of the event are defined by the class they belong to, it makes sense to have the class hold the information instead of the individual events. The events of the same class would just hold duplicate information. After this change the size of the kernel dropped another 3K: text data bss dec hex filename 4913961 1088356 861512 6863829 68bbd5 vmlinux.orig 4900252 1057412 861512 6819176 680d68 vmlinux.regs 4900375 1053380 861512 6815267 67fe23 vmlinux.fields Although the text increased, this was mainly due to the C files having to adapt to the change. This is a constant increase, where new tracepoints will not increase the Text. But the big drop is in the data size (as well as needed allocations to hold the fields). This will give even more savings as more tracepoints are created. Note, if just TRACE_EVENT()s are used and not DECLARE_EVENT_CLASS() with several DEFINE_EVENT()s, then the savings will be lost. But we are pushing developers to consolidate events with DEFINE_EVENT() so this should not be an issue. The kprobes define a unique class to every new event, but are dynamic so it should not be a issue. The syscalls however have a single class but the fields for the individual events are different. The syscalls use a metadata to define the fields. I moved the fields list from the event to the metadata and added a "get_fields()" function to the class. This function is used to find the fields. For normal events and kprobes, get_fields() just returns a pointer to the fields list_head in the class. For syscall events, it returns the fields list_head in the metadata for the event. v2: Fixed the syscall fields. The syscall metadata needs a list of fields for both enter and exit. Acked-by: Frederic Weisbecker <fweisbec@gmail.com> Acked-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Acked-by: Masami Hiramatsu <mhiramat@redhat.com> Cc: Tom Zanussi <tzanussi@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/trace_events.c')
-rw-r--r--kernel/trace/trace_events.c48
1 files changed, 36 insertions, 12 deletions
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);