aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_events.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2009-08-13 16:34:53 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2009-08-26 18:46:40 -0400
commitbd1a5c849bdcc5c89e4a6a18216cd2b9a7a8a78f (patch)
tree1a807fef00b8a700d90683d4f1d480d95eec9669 /kernel/trace/trace_events.c
parentb1cf540f0e5278ecfe8532557e547d833ed269d7 (diff)
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 a2ca5e03), because trace_remove_event_call() uses it. - Modify syscall tracer because of ftrace_event_call change. [fweisbec@gmail.com: Fixed conflict against latest tracing/core] Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Avi Kivity <avi@redhat.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Christoph Hellwig <hch@infradead.org> Cc: Frank Ch. Eigler <fche@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Jason Baron <jbaron@redhat.com> Cc: Jim Keniston <jkenisto@us.ibm.com> Cc: K.Prasad <prasad@linux.vnet.ibm.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Przemysław Pawełczyk <przemyslaw@pawelczyk.it> Cc: Roland McGrath <roland@redhat.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Tom Zanussi <tzanussi@gmail.com> Cc: Vegard Nossum <vegard.nossum@gmail.com> LKML-Reference: <20090813203453.31965.71901.stgit@localhost.localdomain> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'kernel/trace/trace_events.c')
-rw-r--r--kernel/trace/trace_events.c121
1 files changed, 84 insertions, 37 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index d33bcdeffe69..8079bb511c43 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -27,8 +27,8 @@ DEFINE_MUTEX(event_mutex);
27 27
28LIST_HEAD(ftrace_events); 28LIST_HEAD(ftrace_events);
29 29
30int trace_define_field(struct ftrace_event_call *call, const char *type, 30int trace_define_field(struct ftrace_event_call *call, char *type,
31 const char *name, int offset, int size, int is_signed, 31 char *name, int offset, int size, int is_signed,
32 int filter_type) 32 int filter_type)
33{ 33{
34 struct ftrace_event_field *field; 34 struct ftrace_event_field *field;
@@ -92,9 +92,7 @@ int trace_define_common_fields(struct ftrace_event_call *call)
92} 92}
93EXPORT_SYMBOL_GPL(trace_define_common_fields); 93EXPORT_SYMBOL_GPL(trace_define_common_fields);
94 94
95#ifdef CONFIG_MODULES 95void trace_destroy_fields(struct ftrace_event_call *call)
96
97static void trace_destroy_fields(struct ftrace_event_call *call)
98{ 96{
99 struct ftrace_event_field *field, *next; 97 struct ftrace_event_field *field, *next;
100 98
@@ -106,8 +104,6 @@ static void trace_destroy_fields(struct ftrace_event_call *call)
106 } 104 }
107} 105}
108 106
109#endif /* CONFIG_MODULES */
110
111static void ftrace_event_enable_disable(struct ftrace_event_call *call, 107static void ftrace_event_enable_disable(struct ftrace_event_call *call,
112 int enable) 108 int enable)
113{ 109{
@@ -116,14 +112,14 @@ static void ftrace_event_enable_disable(struct ftrace_event_call *call,
116 if (call->enabled) { 112 if (call->enabled) {
117 call->enabled = 0; 113 call->enabled = 0;
118 tracing_stop_cmdline_record(); 114 tracing_stop_cmdline_record();
119 call->unregfunc(call->data); 115 call->unregfunc(call);
120 } 116 }
121 break; 117 break;
122 case 1: 118 case 1:
123 if (!call->enabled) { 119 if (!call->enabled) {
124 call->enabled = 1; 120 call->enabled = 1;
125 tracing_start_cmdline_record(); 121 tracing_start_cmdline_record();
126 call->regfunc(call->data); 122 call->regfunc(call);
127 } 123 }
128 break; 124 break;
129 } 125 }
@@ -991,27 +987,43 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
991 return 0; 987 return 0;
992} 988}
993 989
994#define for_each_event(event, start, end) \ 990static int __trace_add_event_call(struct ftrace_event_call *call)
995 for (event = start; \ 991{
996 (unsigned long)event < (unsigned long)end; \ 992 struct dentry *d_events;
997 event++) 993 int ret;
998 994
999#ifdef CONFIG_MODULES 995 if (!call->name)
996 return -EINVAL;
1000 997
1001static 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 }
1002 1007
1003/* 1008 d_events = event_trace_events_dir();
1004 * Modules must own their file_operations to keep up with 1009 if (!d_events)
1005 * reference counting. 1010 return -ENOENT;
1006 */ 1011
1007struct ftrace_module_file_ops { 1012 list_add(&call->list, &ftrace_events);
1008 struct list_head list; 1013 return event_create_dir(call, d_events, &ftrace_event_id_fops,
1009 struct module *mod; 1014 &ftrace_enable_fops, &ftrace_event_filter_fops,
1010 struct file_operations id; 1015 &ftrace_event_format_fops);
1011 struct file_operations enable; 1016}
1012 struct file_operations format; 1017
1013 struct file_operations filter; 1018/* Add an additional event_call dynamically */
1014}; 1019int 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}
1015 1027
1016static void remove_subsystem_dir(const char *name) 1028static void remove_subsystem_dir(const char *name)
1017{ 1029{
@@ -1039,6 +1051,48 @@ static void remove_subsystem_dir(const char *name)
1039 } 1051 }
1040} 1052}
1041 1053
1054static 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 */
1067void 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
1081static LIST_HEAD(ftrace_module_file_list);
1082
1083/*
1084 * Modules must own their file_operations to keep up with
1085 * reference counting.
1086 */
1087struct 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
1042static struct ftrace_module_file_ops * 1096static struct ftrace_module_file_ops *
1043trace_create_file_ops(struct module *mod) 1097trace_create_file_ops(struct module *mod)
1044{ 1098{
@@ -1096,7 +1150,7 @@ static void trace_module_add_events(struct module *mod)
1096 if (!call->name) 1150 if (!call->name)
1097 continue; 1151 continue;
1098 if (call->raw_init) { 1152 if (call->raw_init) {
1099 ret = call->raw_init(); 1153 ret = call->raw_init(call);
1100 if (ret < 0) { 1154 if (ret < 0) {
1101 if (ret != -ENOSYS) 1155 if (ret != -ENOSYS)
1102 pr_warning("Could not initialize trace " 1156 pr_warning("Could not initialize trace "
@@ -1131,14 +1185,7 @@ static void trace_module_remove_events(struct module *mod)
1131 list_for_each_entry_safe(call, p, &ftrace_events, list) { 1185 list_for_each_entry_safe(call, p, &ftrace_events, list) {
1132 if (call->mod == mod) { 1186 if (call->mod == mod) {
1133 found = true; 1187 found = true;
1134 ftrace_event_enable_disable(call, 0); 1188 __trace_remove_event_call(call);
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);
1142 } 1189 }
1143 } 1190 }
1144 1191
@@ -1256,7 +1303,7 @@ static __init int event_trace_init(void)
1256 if (!call->name) 1303 if (!call->name)
1257 continue; 1304 continue;
1258 if (call->raw_init) { 1305 if (call->raw_init) {
1259 ret = call->raw_init(); 1306 ret = call->raw_init(call);
1260 if (ret < 0) { 1307 if (ret < 0) {
1261 if (ret != -ENOSYS) 1308 if (ret != -ENOSYS)
1262 pr_warning("Could not initialize trace " 1309 pr_warning("Could not initialize trace "