aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Baron <jbaron@redhat.com>2009-08-10 16:52:53 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2009-08-11 14:35:28 -0400
commit64c12e0444fcc6b75eb49144ba46d43dbdc6bc8f (patch)
tree8fe7b546fe787061fca8f97ed2051f40f9b16a57
parentfb34a08c3469b2be9eae626ccb96476b4687b810 (diff)
tracing: Add individual syscalls tracepoint id support
The current state of syscalls tracepoints generates only one event id for every syscall events. This patch associates an id with each syscall trace event, so that we can identify each syscall trace event using the 'perf' tool. Signed-off-by: Jason Baron <jbaron@redhat.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> Cc: Jiaying Zhang <jiayingz@google.com> Cc: Martin Bligh <mbligh@google.com> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Masami Hiramatsu <mhiramat@redhat.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
-rw-r--r--arch/x86/kernel/ftrace.c10
-rw-r--r--include/linux/syscalls.h22
-rw-r--r--include/trace/syscall.h8
-rw-r--r--kernel/trace/trace.h6
-rw-r--r--kernel/trace/trace_syscalls.c26
5 files changed, 52 insertions, 20 deletions
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 0d93d409b8d2..3cff1214e176 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -516,6 +516,16 @@ int syscall_name_to_nr(char *name)
516 return -1; 516 return -1;
517} 517}
518 518
519void set_syscall_enter_id(int num, int id)
520{
521 syscalls_metadata[num]->enter_id = id;
522}
523
524void set_syscall_exit_id(int num, int id)
525{
526 syscalls_metadata[num]->exit_id = id;
527}
528
519static int __init arch_init_ftrace_syscalls(void) 529static int __init arch_init_ftrace_syscalls(void)
520{ 530{
521 int i; 531 int i;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 5e5b4d33a31c..ce4b01c658eb 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -116,13 +116,20 @@ struct perf_counter_attr;
116 116
117#define SYSCALL_TRACE_ENTER_EVENT(sname) \ 117#define SYSCALL_TRACE_ENTER_EVENT(sname) \
118 static struct ftrace_event_call event_enter_##sname; \ 118 static struct ftrace_event_call event_enter_##sname; \
119 struct trace_event enter_syscall_print_##sname = { \
120 .trace = print_syscall_enter, \
121 }; \
119 static int init_enter_##sname(void) \ 122 static int init_enter_##sname(void) \
120 { \ 123 { \
121 int num; \ 124 int num, id; \
122 num = syscall_name_to_nr("sys"#sname); \ 125 num = syscall_name_to_nr("sys"#sname); \
123 if (num < 0) \ 126 if (num < 0) \
124 return -ENOSYS; \ 127 return -ENOSYS; \
125 register_ftrace_event(&event_syscall_enter); \ 128 id = register_ftrace_event(&enter_syscall_print_##sname);\
129 if (!id) \
130 return -ENODEV; \
131 event_enter_##sname.id = id; \
132 set_syscall_enter_id(num, id); \
126 INIT_LIST_HEAD(&event_enter_##sname.fields); \ 133 INIT_LIST_HEAD(&event_enter_##sname.fields); \
127 init_preds(&event_enter_##sname); \ 134 init_preds(&event_enter_##sname); \
128 return 0; \ 135 return 0; \
@@ -142,13 +149,20 @@ struct perf_counter_attr;
142 149
143#define SYSCALL_TRACE_EXIT_EVENT(sname) \ 150#define SYSCALL_TRACE_EXIT_EVENT(sname) \
144 static struct ftrace_event_call event_exit_##sname; \ 151 static struct ftrace_event_call event_exit_##sname; \
152 struct trace_event exit_syscall_print_##sname = { \
153 .trace = print_syscall_exit, \
154 }; \
145 static int init_exit_##sname(void) \ 155 static int init_exit_##sname(void) \
146 { \ 156 { \
147 int num; \ 157 int num, id; \
148 num = syscall_name_to_nr("sys"#sname); \ 158 num = syscall_name_to_nr("sys"#sname); \
149 if (num < 0) \ 159 if (num < 0) \
150 return -ENOSYS; \ 160 return -ENOSYS; \
151 register_ftrace_event(&event_syscall_exit); \ 161 id = register_ftrace_event(&exit_syscall_print_##sname);\
162 if (!id) \
163 return -ENODEV; \
164 event_exit_##sname.id = id; \
165 set_syscall_exit_id(num, id); \
152 INIT_LIST_HEAD(&event_exit_##sname.fields); \ 166 INIT_LIST_HEAD(&event_exit_##sname.fields); \
153 init_preds(&event_exit_##sname); \ 167 init_preds(&event_exit_##sname); \
154 return 0; \ 168 return 0; \
diff --git a/include/trace/syscall.h b/include/trace/syscall.h
index 73fb8b4a9955..df628404241a 100644
--- a/include/trace/syscall.h
+++ b/include/trace/syscall.h
@@ -32,23 +32,31 @@ DECLARE_TRACE_WITH_CALLBACK(syscall_exit,
32 * @nb_args: number of parameters it takes 32 * @nb_args: number of parameters it takes
33 * @types: list of types as strings 33 * @types: list of types as strings
34 * @args: list of args as strings (args[i] matches types[i]) 34 * @args: list of args as strings (args[i] matches types[i])
35 * @enter_id: associated ftrace enter event id
36 * @exit_id: associated ftrace exit event id
35 */ 37 */
36struct syscall_metadata { 38struct syscall_metadata {
37 const char *name; 39 const char *name;
38 int nb_args; 40 int nb_args;
39 const char **types; 41 const char **types;
40 const char **args; 42 const char **args;
43 int enter_id;
44 int exit_id;
41}; 45};
42 46
43#ifdef CONFIG_FTRACE_SYSCALLS 47#ifdef CONFIG_FTRACE_SYSCALLS
44extern struct syscall_metadata *syscall_nr_to_meta(int nr); 48extern struct syscall_metadata *syscall_nr_to_meta(int nr);
45extern int syscall_name_to_nr(char *name); 49extern int syscall_name_to_nr(char *name);
50void set_syscall_enter_id(int num, int id);
51void set_syscall_exit_id(int num, int id);
46extern struct trace_event event_syscall_enter; 52extern struct trace_event event_syscall_enter;
47extern struct trace_event event_syscall_exit; 53extern struct trace_event event_syscall_exit;
48extern int reg_event_syscall_enter(void *ptr); 54extern int reg_event_syscall_enter(void *ptr);
49extern void unreg_event_syscall_enter(void *ptr); 55extern void unreg_event_syscall_enter(void *ptr);
50extern int reg_event_syscall_exit(void *ptr); 56extern int reg_event_syscall_exit(void *ptr);
51extern void unreg_event_syscall_exit(void *ptr); 57extern void unreg_event_syscall_exit(void *ptr);
58enum print_line_t print_syscall_enter(struct trace_iterator *iter, int flags);
59enum print_line_t print_syscall_exit(struct trace_iterator *iter, int flags);
52#endif 60#endif
53 61
54#endif /* _TRACE_SYSCALL_H */ 62#endif /* _TRACE_SYSCALL_H */
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index d682357e4b1f..300ef788c976 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -34,8 +34,6 @@ enum trace_type {
34 TRACE_GRAPH_ENT, 34 TRACE_GRAPH_ENT,
35 TRACE_USER_STACK, 35 TRACE_USER_STACK,
36 TRACE_HW_BRANCHES, 36 TRACE_HW_BRANCHES,
37 TRACE_SYSCALL_ENTER,
38 TRACE_SYSCALL_EXIT,
39 TRACE_KMEM_ALLOC, 37 TRACE_KMEM_ALLOC,
40 TRACE_KMEM_FREE, 38 TRACE_KMEM_FREE,
41 TRACE_POWER, 39 TRACE_POWER,
@@ -319,10 +317,6 @@ extern void __ftrace_bad_type(void);
319 TRACE_KMEM_ALLOC); \ 317 TRACE_KMEM_ALLOC); \
320 IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \ 318 IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \
321 TRACE_KMEM_FREE); \ 319 TRACE_KMEM_FREE); \
322 IF_ASSIGN(var, ent, struct syscall_trace_enter, \
323 TRACE_SYSCALL_ENTER); \
324 IF_ASSIGN(var, ent, struct syscall_trace_exit, \
325 TRACE_SYSCALL_EXIT); \
326 __ftrace_bad_type(); \ 320 __ftrace_bad_type(); \
327 } while (0) 321 } while (0)
328 322
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index c7ae25ee95d8..e58a9c11ba85 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -36,14 +36,18 @@ print_syscall_enter(struct trace_iterator *iter, int flags)
36 struct syscall_metadata *entry; 36 struct syscall_metadata *entry;
37 int i, ret, syscall; 37 int i, ret, syscall;
38 38
39 trace_assign_type(trace, ent); 39 trace = (typeof(trace))ent;
40
41 syscall = trace->nr; 40 syscall = trace->nr;
42
43 entry = syscall_nr_to_meta(syscall); 41 entry = syscall_nr_to_meta(syscall);
42
44 if (!entry) 43 if (!entry)
45 goto end; 44 goto end;
46 45
46 if (entry->enter_id != ent->type) {
47 WARN_ON_ONCE(1);
48 goto end;
49 }
50
47 ret = trace_seq_printf(s, "%s(", entry->name); 51 ret = trace_seq_printf(s, "%s(", entry->name);
48 if (!ret) 52 if (!ret)
49 return TRACE_TYPE_PARTIAL_LINE; 53 return TRACE_TYPE_PARTIAL_LINE;
@@ -78,16 +82,20 @@ print_syscall_exit(struct trace_iterator *iter, int flags)
78 struct syscall_metadata *entry; 82 struct syscall_metadata *entry;
79 int ret; 83 int ret;
80 84
81 trace_assign_type(trace, ent); 85 trace = (typeof(trace))ent;
82
83 syscall = trace->nr; 86 syscall = trace->nr;
84
85 entry = syscall_nr_to_meta(syscall); 87 entry = syscall_nr_to_meta(syscall);
88
86 if (!entry) { 89 if (!entry) {
87 trace_seq_printf(s, "\n"); 90 trace_seq_printf(s, "\n");
88 return TRACE_TYPE_HANDLED; 91 return TRACE_TYPE_HANDLED;
89 } 92 }
90 93
94 if (entry->exit_id != ent->type) {
95 WARN_ON_ONCE(1);
96 return TRACE_TYPE_UNHANDLED;
97 }
98
91 ret = trace_seq_printf(s, "%s -> 0x%lx\n", entry->name, 99 ret = trace_seq_printf(s, "%s -> 0x%lx\n", entry->name,
92 trace->ret); 100 trace->ret);
93 if (!ret) 101 if (!ret)
@@ -114,7 +122,7 @@ void ftrace_syscall_enter(struct pt_regs *regs, long id)
114 122
115 size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args; 123 size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args;
116 124
117 event = trace_current_buffer_lock_reserve(TRACE_SYSCALL_ENTER, size, 125 event = trace_current_buffer_lock_reserve(sys_data->enter_id, size,
118 0, 0); 126 0, 0);
119 if (!event) 127 if (!event)
120 return; 128 return;
@@ -142,7 +150,7 @@ void ftrace_syscall_exit(struct pt_regs *regs, long ret)
142 if (!sys_data) 150 if (!sys_data)
143 return; 151 return;
144 152
145 event = trace_current_buffer_lock_reserve(TRACE_SYSCALL_EXIT, 153 event = trace_current_buffer_lock_reserve(sys_data->exit_id,
146 sizeof(*entry), 0, 0); 154 sizeof(*entry), 0, 0);
147 if (!event) 155 if (!event)
148 return; 156 return;
@@ -239,10 +247,8 @@ void unreg_event_syscall_exit(void *ptr)
239 247
240struct trace_event event_syscall_enter = { 248struct trace_event event_syscall_enter = {
241 .trace = print_syscall_enter, 249 .trace = print_syscall_enter,
242 .type = TRACE_SYSCALL_ENTER
243}; 250};
244 251
245struct trace_event event_syscall_exit = { 252struct trace_event event_syscall_exit = {
246 .trace = print_syscall_exit, 253 .trace = print_syscall_exit,
247 .type = TRACE_SYSCALL_EXIT
248}; 254};