blob: ca624df735916d3264d6d2a7f3f273f8972d265c [file] [log] [blame]
Steven Rostedtb77e38a2009-02-24 10:21:36 -05001/*
2 * event tracer
3 *
4 * Copyright (C) 2008 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
5 *
Steven Rostedt981d0812009-03-02 13:53:59 -05006 * - Added format output of fields of the trace point.
7 * This was based off of work by Tom Zanussi <tzanussi@gmail.com>.
8 *
Steven Rostedtb77e38a2009-02-24 10:21:36 -05009 */
10
11#include <linux/debugfs.h>
12#include <linux/uaccess.h>
13#include <linux/module.h>
14#include <linux/ctype.h>
15
Steven Rostedt91729ef2009-03-02 15:03:01 -050016#include "trace_output.h"
Steven Rostedtb77e38a2009-02-24 10:21:36 -050017
Steven Rostedtb628b3e2009-02-27 23:32:58 -050018#define TRACE_SYSTEM "TRACE_SYSTEM"
19
Steven Rostedt11a241a2009-03-02 11:49:04 -050020static DEFINE_MUTEX(event_mutex);
21
Steven Rostedt1473e442009-02-24 14:15:08 -050022#define events_for_each(event) \
23 for (event = __start_ftrace_events; \
24 (unsigned long)event < (unsigned long)__stop_ftrace_events; \
25 event++)
26
Steven Rostedtb77e38a2009-02-24 10:21:36 -050027void event_trace_printk(unsigned long ip, const char *fmt, ...)
28{
29 va_list ap;
30
31 va_start(ap, fmt);
32 tracing_record_cmdline(current);
33 trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap);
34 va_end(ap);
35}
36
37static void ftrace_clear_events(void)
38{
39 struct ftrace_event_call *call = (void *)__start_ftrace_events;
40
41
42 while ((unsigned long)call < (unsigned long)__stop_ftrace_events) {
43
44 if (call->enabled) {
45 call->enabled = 0;
46 call->unregfunc();
47 }
48 call++;
49 }
50}
51
Steven Rostedtfd994982009-02-28 02:41:25 -050052static void ftrace_event_enable_disable(struct ftrace_event_call *call,
53 int enable)
54{
55
56 switch (enable) {
57 case 0:
58 if (call->enabled) {
59 call->enabled = 0;
60 call->unregfunc();
61 }
Steven Rostedtfd994982009-02-28 02:41:25 -050062 break;
63 case 1:
Steven Rostedtda4d0302009-03-09 17:14:30 -040064 if (!call->enabled) {
Steven Rostedtfd994982009-02-28 02:41:25 -050065 call->enabled = 1;
66 call->regfunc();
67 }
Steven Rostedtfd994982009-02-28 02:41:25 -050068 break;
69 }
70}
71
Steven Rostedtb77e38a2009-02-24 10:21:36 -050072static int ftrace_set_clr_event(char *buf, int set)
73{
Steven Rostedt1473e442009-02-24 14:15:08 -050074 struct ftrace_event_call *call = __start_ftrace_events;
Steven Rostedtb628b3e2009-02-27 23:32:58 -050075 char *event = NULL, *sub = NULL, *match;
76 int ret = -EINVAL;
Steven Rostedtb77e38a2009-02-24 10:21:36 -050077
Steven Rostedtb628b3e2009-02-27 23:32:58 -050078 /*
79 * The buf format can be <subsystem>:<event-name>
80 * *:<event-name> means any event by that name.
81 * :<event-name> is the same.
82 *
83 * <subsystem>:* means all events in that subsystem
84 * <subsystem>: means the same.
85 *
86 * <name> (no ':') means all events in a subsystem with
87 * the name <name> or any event that matches <name>
88 */
89
90 match = strsep(&buf, ":");
91 if (buf) {
92 sub = match;
93 event = buf;
94 match = NULL;
95
96 if (!strlen(sub) || strcmp(sub, "*") == 0)
97 sub = NULL;
98 if (!strlen(event) || strcmp(event, "*") == 0)
99 event = NULL;
100 }
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500101
Steven Rostedt11a241a2009-03-02 11:49:04 -0500102 mutex_lock(&event_mutex);
Steven Rostedt1473e442009-02-24 14:15:08 -0500103 events_for_each(call) {
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500104
Steven Rostedt40e26812009-03-10 11:32:40 -0400105 if (!call->name || !call->regfunc)
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500106 continue;
Steven Rostedt1473e442009-02-24 14:15:08 -0500107
Steven Rostedtb628b3e2009-02-27 23:32:58 -0500108 if (match &&
109 strcmp(match, call->name) != 0 &&
110 strcmp(match, call->system) != 0)
111 continue;
112
113 if (sub && strcmp(sub, call->system) != 0)
114 continue;
115
116 if (event && strcmp(event, call->name) != 0)
Steven Rostedt1473e442009-02-24 14:15:08 -0500117 continue;
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500118
Steven Rostedtfd994982009-02-28 02:41:25 -0500119 ftrace_event_enable_disable(call, set);
120
Steven Rostedtb628b3e2009-02-27 23:32:58 -0500121 ret = 0;
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500122 }
Steven Rostedt11a241a2009-03-02 11:49:04 -0500123 mutex_unlock(&event_mutex);
124
Steven Rostedtb628b3e2009-02-27 23:32:58 -0500125 return ret;
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500126}
127
128/* 128 should be much more than enough */
129#define EVENT_BUF_SIZE 127
130
131static ssize_t
132ftrace_event_write(struct file *file, const char __user *ubuf,
133 size_t cnt, loff_t *ppos)
134{
135 size_t read = 0;
136 int i, set = 1;
137 ssize_t ret;
138 char *buf;
139 char ch;
140
141 if (!cnt || cnt < 0)
142 return 0;
143
Steven Rostedt1852fcc2009-03-11 14:33:00 -0400144 ret = tracing_update_buffers();
145 if (ret < 0)
146 return ret;
147
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500148 ret = get_user(ch, ubuf++);
149 if (ret)
150 return ret;
151 read++;
152 cnt--;
153
154 /* skip white space */
155 while (cnt && isspace(ch)) {
156 ret = get_user(ch, ubuf++);
157 if (ret)
158 return ret;
159 read++;
160 cnt--;
161 }
162
163 /* Only white space found? */
164 if (isspace(ch)) {
165 file->f_pos += read;
166 ret = read;
167 return ret;
168 }
169
170 buf = kmalloc(EVENT_BUF_SIZE+1, GFP_KERNEL);
171 if (!buf)
172 return -ENOMEM;
173
174 if (cnt > EVENT_BUF_SIZE)
175 cnt = EVENT_BUF_SIZE;
176
177 i = 0;
178 while (cnt && !isspace(ch)) {
179 if (!i && ch == '!')
180 set = 0;
181 else
182 buf[i++] = ch;
183
184 ret = get_user(ch, ubuf++);
185 if (ret)
186 goto out_free;
187 read++;
188 cnt--;
189 }
190 buf[i] = 0;
191
192 file->f_pos += read;
193
194 ret = ftrace_set_clr_event(buf, set);
195 if (ret)
196 goto out_free;
197
198 ret = read;
199
200 out_free:
201 kfree(buf);
202
203 return ret;
204}
205
206static void *
207t_next(struct seq_file *m, void *v, loff_t *pos)
208{
209 struct ftrace_event_call *call = m->private;
210 struct ftrace_event_call *next = call;
211
212 (*pos)++;
213
Steven Rostedt40e26812009-03-10 11:32:40 -0400214 for (;;) {
215 if ((unsigned long)call >= (unsigned long)__stop_ftrace_events)
216 return NULL;
217
218 /*
219 * The ftrace subsystem is for showing formats only.
220 * They can not be enabled or disabled via the event files.
221 */
222 if (call->regfunc)
223 break;
224
225 call++;
226 next = call;
227 }
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500228
229 m->private = ++next;
230
231 return call;
232}
233
234static void *t_start(struct seq_file *m, loff_t *pos)
235{
236 return t_next(m, NULL, pos);
237}
238
239static void *
240s_next(struct seq_file *m, void *v, loff_t *pos)
241{
242 struct ftrace_event_call *call = m->private;
243 struct ftrace_event_call *next;
244
245 (*pos)++;
246
247 retry:
248 if ((unsigned long)call >= (unsigned long)__stop_ftrace_events)
249 return NULL;
250
251 if (!call->enabled) {
252 call++;
253 goto retry;
254 }
255
256 next = call;
257 m->private = ++next;
258
259 return call;
260}
261
262static void *s_start(struct seq_file *m, loff_t *pos)
263{
264 return s_next(m, NULL, pos);
265}
266
267static int t_show(struct seq_file *m, void *v)
268{
269 struct ftrace_event_call *call = v;
270
Steven Rostedtb628b3e2009-02-27 23:32:58 -0500271 if (strcmp(call->system, TRACE_SYSTEM) != 0)
272 seq_printf(m, "%s:", call->system);
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500273 seq_printf(m, "%s\n", call->name);
274
275 return 0;
276}
277
278static void t_stop(struct seq_file *m, void *p)
279{
280}
281
282static int
283ftrace_event_seq_open(struct inode *inode, struct file *file)
284{
285 int ret;
286 const struct seq_operations *seq_ops;
287
288 if ((file->f_mode & FMODE_WRITE) &&
289 !(file->f_flags & O_APPEND))
290 ftrace_clear_events();
291
292 seq_ops = inode->i_private;
293 ret = seq_open(file, seq_ops);
294 if (!ret) {
295 struct seq_file *m = file->private_data;
296
297 m->private = __start_ftrace_events;
298 }
299 return ret;
300}
301
Steven Rostedt1473e442009-02-24 14:15:08 -0500302static ssize_t
303event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
304 loff_t *ppos)
305{
306 struct ftrace_event_call *call = filp->private_data;
307 char *buf;
308
Steven Rostedtda4d0302009-03-09 17:14:30 -0400309 if (call->enabled)
Steven Rostedt1473e442009-02-24 14:15:08 -0500310 buf = "1\n";
311 else
312 buf = "0\n";
313
314 return simple_read_from_buffer(ubuf, cnt, ppos, buf, 2);
315}
316
317static ssize_t
318event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
319 loff_t *ppos)
320{
321 struct ftrace_event_call *call = filp->private_data;
322 char buf[64];
323 unsigned long val;
324 int ret;
325
326 if (cnt >= sizeof(buf))
327 return -EINVAL;
328
329 if (copy_from_user(&buf, ubuf, cnt))
330 return -EFAULT;
331
332 buf[cnt] = 0;
333
334 ret = strict_strtoul(buf, 10, &val);
335 if (ret < 0)
336 return ret;
337
Steven Rostedt1852fcc2009-03-11 14:33:00 -0400338 ret = tracing_update_buffers();
339 if (ret < 0)
340 return ret;
341
Steven Rostedt1473e442009-02-24 14:15:08 -0500342 switch (val) {
343 case 0:
Steven Rostedt1473e442009-02-24 14:15:08 -0500344 case 1:
Steven Rostedt11a241a2009-03-02 11:49:04 -0500345 mutex_lock(&event_mutex);
Steven Rostedtfd994982009-02-28 02:41:25 -0500346 ftrace_event_enable_disable(call, val);
Steven Rostedt11a241a2009-03-02 11:49:04 -0500347 mutex_unlock(&event_mutex);
Steven Rostedt1473e442009-02-24 14:15:08 -0500348 break;
349
350 default:
351 return -EINVAL;
352 }
353
354 *ppos += cnt;
355
356 return cnt;
357}
358
Steven Rostedt91729ef2009-03-02 15:03:01 -0500359#undef FIELD
Steven Rostedt156b5f12009-03-06 10:50:53 -0500360#define FIELD(type, name) \
Steven Rostedtce8eb2b2009-03-10 10:14:35 -0400361 #type, #name, offsetof(typeof(field), name), sizeof(field.name)
Steven Rostedt91729ef2009-03-02 15:03:01 -0500362
363static int trace_write_header(struct trace_seq *s)
364{
365 struct trace_entry field;
366
367 /* struct trace_entry */
368 return trace_seq_printf(s,
Steven Rostedtce8eb2b2009-03-10 10:14:35 -0400369 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
370 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
371 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
372 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
373 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
Steven Rostedt91729ef2009-03-02 15:03:01 -0500374 "\n",
375 FIELD(unsigned char, type),
376 FIELD(unsigned char, flags),
377 FIELD(unsigned char, preempt_count),
378 FIELD(int, pid),
379 FIELD(int, tgid));
380}
Steven Rostedtda4d0302009-03-09 17:14:30 -0400381
Steven Rostedt981d0812009-03-02 13:53:59 -0500382static ssize_t
383event_format_read(struct file *filp, char __user *ubuf, size_t cnt,
384 loff_t *ppos)
385{
386 struct ftrace_event_call *call = filp->private_data;
387 struct trace_seq *s;
388 char *buf;
389 int r;
390
391 s = kmalloc(sizeof(*s), GFP_KERNEL);
392 if (!s)
393 return -ENOMEM;
394
395 trace_seq_init(s);
396
397 if (*ppos)
398 return 0;
399
Steven Rostedtc5e4e192009-03-02 15:10:02 -0500400 /* If any of the first writes fail, so will the show_format. */
401
402 trace_seq_printf(s, "name: %s\n", call->name);
403 trace_seq_printf(s, "ID: %d\n", call->id);
404 trace_seq_printf(s, "format:\n");
Steven Rostedt91729ef2009-03-02 15:03:01 -0500405 trace_write_header(s);
406
Steven Rostedt981d0812009-03-02 13:53:59 -0500407 r = call->show_format(s);
408 if (!r) {
409 /*
410 * ug! The format output is bigger than a PAGE!!
411 */
412 buf = "FORMAT TOO BIG\n";
413 r = simple_read_from_buffer(ubuf, cnt, ppos,
414 buf, strlen(buf));
415 goto out;
416 }
417
418 r = simple_read_from_buffer(ubuf, cnt, ppos,
419 s->buffer, s->len);
420 out:
421 kfree(s);
422 return r;
423}
424
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500425static const struct seq_operations show_event_seq_ops = {
426 .start = t_start,
427 .next = t_next,
428 .show = t_show,
429 .stop = t_stop,
430};
431
432static const struct seq_operations show_set_event_seq_ops = {
433 .start = s_start,
434 .next = s_next,
435 .show = t_show,
436 .stop = t_stop,
437};
438
Steven Rostedt2314c4a2009-03-10 12:04:02 -0400439static const struct file_operations ftrace_avail_fops = {
440 .open = ftrace_event_seq_open,
441 .read = seq_read,
442 .llseek = seq_lseek,
443 .release = seq_release,
444};
445
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500446static const struct file_operations ftrace_set_event_fops = {
447 .open = ftrace_event_seq_open,
448 .read = seq_read,
449 .write = ftrace_event_write,
450 .llseek = seq_lseek,
451 .release = seq_release,
452};
453
Steven Rostedt1473e442009-02-24 14:15:08 -0500454static const struct file_operations ftrace_enable_fops = {
455 .open = tracing_open_generic,
456 .read = event_enable_read,
457 .write = event_enable_write,
458};
459
Steven Rostedt981d0812009-03-02 13:53:59 -0500460static const struct file_operations ftrace_event_format_fops = {
461 .open = tracing_open_generic,
462 .read = event_format_read,
463};
464
Steven Rostedt1473e442009-02-24 14:15:08 -0500465static struct dentry *event_trace_events_dir(void)
466{
467 static struct dentry *d_tracer;
468 static struct dentry *d_events;
469
470 if (d_events)
471 return d_events;
472
473 d_tracer = tracing_init_dentry();
474 if (!d_tracer)
475 return NULL;
476
477 d_events = debugfs_create_dir("events", d_tracer);
478 if (!d_events)
479 pr_warning("Could not create debugfs "
480 "'events' directory\n");
481
482 return d_events;
483}
484
Steven Rostedt6ecc2d12009-02-27 21:33:02 -0500485struct event_subsystem {
486 struct list_head list;
487 const char *name;
488 struct dentry *entry;
489};
490
491static LIST_HEAD(event_subsystems);
492
493static struct dentry *
494event_subsystem_dir(const char *name, struct dentry *d_events)
495{
496 struct event_subsystem *system;
497
498 /* First see if we did not already create this dir */
499 list_for_each_entry(system, &event_subsystems, list) {
500 if (strcmp(system->name, name) == 0)
501 return system->entry;
502 }
503
504 /* need to create new entry */
505 system = kmalloc(sizeof(*system), GFP_KERNEL);
506 if (!system) {
507 pr_warning("No memory to create event subsystem %s\n",
508 name);
509 return d_events;
510 }
511
512 system->entry = debugfs_create_dir(name, d_events);
513 if (!system->entry) {
514 pr_warning("Could not create event subsystem %s\n",
515 name);
516 kfree(system);
517 return d_events;
518 }
519
520 system->name = name;
521 list_add(&system->list, &event_subsystems);
522
523 return system->entry;
524}
525
Steven Rostedt1473e442009-02-24 14:15:08 -0500526static int
527event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
528{
529 struct dentry *entry;
Steven Rostedtfd994982009-02-28 02:41:25 -0500530 int ret;
Steven Rostedt1473e442009-02-24 14:15:08 -0500531
Steven Rostedt6ecc2d12009-02-27 21:33:02 -0500532 /*
533 * If the trace point header did not define TRACE_SYSTEM
534 * then the system would be called "TRACE_SYSTEM".
535 */
536 if (strcmp(call->system, "TRACE_SYSTEM") != 0)
537 d_events = event_subsystem_dir(call->system, d_events);
538
Steven Rostedtfd994982009-02-28 02:41:25 -0500539 if (call->raw_init) {
540 ret = call->raw_init();
541 if (ret < 0) {
542 pr_warning("Could not initialize trace point"
543 " events/%s\n", call->name);
544 return ret;
545 }
546 }
547
Steven Rostedt1473e442009-02-24 14:15:08 -0500548 call->dir = debugfs_create_dir(call->name, d_events);
549 if (!call->dir) {
550 pr_warning("Could not create debugfs "
551 "'%s' directory\n", call->name);
552 return -1;
553 }
554
Steven Rostedt770cb242009-03-05 21:35:29 -0500555 if (call->regfunc) {
556 entry = debugfs_create_file("enable", 0644, call->dir, call,
557 &ftrace_enable_fops);
558 if (!entry)
559 pr_warning("Could not create debugfs "
560 "'%s/enable' entry\n", call->name);
561 }
Steven Rostedt1473e442009-02-24 14:15:08 -0500562
Steven Rostedt981d0812009-03-02 13:53:59 -0500563 /* A trace may not want to export its format */
564 if (!call->show_format)
565 return 0;
566
567 entry = debugfs_create_file("format", 0444, call->dir, call,
568 &ftrace_event_format_fops);
569 if (!entry)
570 pr_warning("Could not create debugfs "
571 "'%s/format' entry\n", call->name);
Steven Rostedtfd994982009-02-28 02:41:25 -0500572
Steven Rostedt1473e442009-02-24 14:15:08 -0500573 return 0;
574}
575
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500576static __init int event_trace_init(void)
577{
Steven Rostedt1473e442009-02-24 14:15:08 -0500578 struct ftrace_event_call *call = __start_ftrace_events;
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500579 struct dentry *d_tracer;
580 struct dentry *entry;
Steven Rostedt1473e442009-02-24 14:15:08 -0500581 struct dentry *d_events;
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500582
583 d_tracer = tracing_init_dentry();
584 if (!d_tracer)
585 return 0;
586
Steven Rostedt2314c4a2009-03-10 12:04:02 -0400587 entry = debugfs_create_file("available_events", 0444, d_tracer,
588 (void *)&show_event_seq_ops,
589 &ftrace_avail_fops);
590 if (!entry)
591 pr_warning("Could not create debugfs "
592 "'available_events' entry\n");
593
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500594 entry = debugfs_create_file("set_event", 0644, d_tracer,
595 (void *)&show_set_event_seq_ops,
596 &ftrace_set_event_fops);
597 if (!entry)
598 pr_warning("Could not create debugfs "
599 "'set_event' entry\n");
600
Steven Rostedt1473e442009-02-24 14:15:08 -0500601 d_events = event_trace_events_dir();
602 if (!d_events)
603 return 0;
604
605 events_for_each(call) {
606 /* The linker may leave blanks */
607 if (!call->name)
608 continue;
609 event_create_dir(call, d_events);
610 }
611
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500612 return 0;
613}
614fs_initcall(event_trace_init);