aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_events.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-02-24 14:15:08 -0500
committerSteven Rostedt <srostedt@redhat.com>2009-02-24 21:54:08 -0500
commit1473e4417c79f12d91ef91a469699bfa911f510f (patch)
tree07ae02d5383367ed883616646f885be71f7431dd /kernel/trace/trace_events.c
parentf3fe8e4a38fd19dbb3f8ffb1826aa840ae304a65 (diff)
tracing: make event directory structure
This patch adds the directory /debug/tracing/events/ that will contain all the registered trace points. # ls /debug/tracing/events/ sched_kthread_stop sched_process_fork sched_switch sched_kthread_stop_ret sched_process_free sched_wait_task sched_migrate_task sched_process_wait sched_wakeup sched_process_exit sched_signal_send sched_wakeup_new # ls /debug/tracing/events/sched_switch/ enable # cat /debug/tracing/events/sched_switch/enable 1 # cat /debug/tracing/set_event sched_switch Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Diffstat (limited to 'kernel/trace/trace_events.c')
-rw-r--r--kernel/trace/trace_events.c137
1 files changed, 132 insertions, 5 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 05bc80ec8d2c..3bcb9df93342 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -12,6 +12,11 @@
12 12
13#include "trace_events.h" 13#include "trace_events.h"
14 14
15#define events_for_each(event) \
16 for (event = __start_ftrace_events; \
17 (unsigned long)event < (unsigned long)__stop_ftrace_events; \
18 event++)
19
15void event_trace_printk(unsigned long ip, const char *fmt, ...) 20void event_trace_printk(unsigned long ip, const char *fmt, ...)
16{ 21{
17 va_list ap; 22 va_list ap;
@@ -39,15 +44,16 @@ static void ftrace_clear_events(void)
39 44
40static int ftrace_set_clr_event(char *buf, int set) 45static int ftrace_set_clr_event(char *buf, int set)
41{ 46{
42 struct ftrace_event_call *call = (void *)__start_ftrace_events; 47 struct ftrace_event_call *call = __start_ftrace_events;
43 48
44 49
45 while ((unsigned long)call < (unsigned long)__stop_ftrace_events) { 50 events_for_each(call) {
46 51
47 if (strcmp(buf, call->name) != 0) { 52 if (!call->name)
48 call++; 53 continue;
54
55 if (strcmp(buf, call->name) != 0)
49 continue; 56 continue;
50 }
51 57
52 if (set) { 58 if (set) {
53 /* Already set? */ 59 /* Already set? */
@@ -223,6 +229,67 @@ ftrace_event_seq_open(struct inode *inode, struct file *file)
223 return ret; 229 return ret;
224} 230}
225 231
232static ssize_t
233event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
234 loff_t *ppos)
235{
236 struct ftrace_event_call *call = filp->private_data;
237 char *buf;
238
239 if (call->enabled)
240 buf = "1\n";
241 else
242 buf = "0\n";
243
244 return simple_read_from_buffer(ubuf, cnt, ppos, buf, 2);
245}
246
247static ssize_t
248event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
249 loff_t *ppos)
250{
251 struct ftrace_event_call *call = filp->private_data;
252 char buf[64];
253 unsigned long val;
254 int ret;
255
256 if (cnt >= sizeof(buf))
257 return -EINVAL;
258
259 if (copy_from_user(&buf, ubuf, cnt))
260 return -EFAULT;
261
262 buf[cnt] = 0;
263
264 ret = strict_strtoul(buf, 10, &val);
265 if (ret < 0)
266 return ret;
267
268 switch (val) {
269 case 0:
270 if (!call->enabled)
271 break;
272
273 call->enabled = 0;
274 call->unregfunc();
275 break;
276 case 1:
277 if (call->enabled)
278 break;
279
280 call->enabled = 1;
281 call->regfunc();
282 break;
283
284 default:
285 return -EINVAL;
286 }
287
288 *ppos += cnt;
289
290 return cnt;
291}
292
226static const struct seq_operations show_event_seq_ops = { 293static const struct seq_operations show_event_seq_ops = {
227 .start = t_start, 294 .start = t_start,
228 .next = t_next, 295 .next = t_next,
@@ -252,10 +319,59 @@ static const struct file_operations ftrace_set_event_fops = {
252 .release = seq_release, 319 .release = seq_release,
253}; 320};
254 321
322static const struct file_operations ftrace_enable_fops = {
323 .open = tracing_open_generic,
324 .read = event_enable_read,
325 .write = event_enable_write,
326};
327
328static struct dentry *event_trace_events_dir(void)
329{
330 static struct dentry *d_tracer;
331 static struct dentry *d_events;
332
333 if (d_events)
334 return d_events;
335
336 d_tracer = tracing_init_dentry();
337 if (!d_tracer)
338 return NULL;
339
340 d_events = debugfs_create_dir("events", d_tracer);
341 if (!d_events)
342 pr_warning("Could not create debugfs "
343 "'events' directory\n");
344
345 return d_events;
346}
347
348static int
349event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
350{
351 struct dentry *entry;
352
353 call->dir = debugfs_create_dir(call->name, d_events);
354 if (!call->dir) {
355 pr_warning("Could not create debugfs "
356 "'%s' directory\n", call->name);
357 return -1;
358 }
359
360 entry = debugfs_create_file("enable", 0644, call->dir, call,
361 &ftrace_enable_fops);
362 if (!entry)
363 pr_warning("Could not create debugfs "
364 "'%s/enable' entry\n", call->name);
365
366 return 0;
367}
368
255static __init int event_trace_init(void) 369static __init int event_trace_init(void)
256{ 370{
371 struct ftrace_event_call *call = __start_ftrace_events;
257 struct dentry *d_tracer; 372 struct dentry *d_tracer;
258 struct dentry *entry; 373 struct dentry *entry;
374 struct dentry *d_events;
259 375
260 d_tracer = tracing_init_dentry(); 376 d_tracer = tracing_init_dentry();
261 if (!d_tracer) 377 if (!d_tracer)
@@ -275,6 +391,17 @@ static __init int event_trace_init(void)
275 pr_warning("Could not create debugfs " 391 pr_warning("Could not create debugfs "
276 "'set_event' entry\n"); 392 "'set_event' entry\n");
277 393
394 d_events = event_trace_events_dir();
395 if (!d_events)
396 return 0;
397
398 events_for_each(call) {
399 /* The linker may leave blanks */
400 if (!call->name)
401 continue;
402 event_create_dir(call, d_events);
403 }
404
278 return 0; 405 return 0;
279} 406}
280fs_initcall(event_trace_init); 407fs_initcall(event_trace_init);