blob: 85ec10fbb38dc1c9cf8b841caae9253dde135aec [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 Rostedt91729ef92009-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
144 ret = get_user(ch, ubuf++);
145 if (ret)
146 return ret;
147 read++;
148 cnt--;
149
150 /* skip white space */
151 while (cnt && isspace(ch)) {
152 ret = get_user(ch, ubuf++);
153 if (ret)
154 return ret;
155 read++;
156 cnt--;
157 }
158
159 /* Only white space found? */
160 if (isspace(ch)) {
161 file->f_pos += read;
162 ret = read;
163 return ret;
164 }
165
166 buf = kmalloc(EVENT_BUF_SIZE+1, GFP_KERNEL);
167 if (!buf)
168 return -ENOMEM;
169
170 if (cnt > EVENT_BUF_SIZE)
171 cnt = EVENT_BUF_SIZE;
172
173 i = 0;
174 while (cnt && !isspace(ch)) {
175 if (!i && ch == '!')
176 set = 0;
177 else
178 buf[i++] = ch;
179
180 ret = get_user(ch, ubuf++);
181 if (ret)
182 goto out_free;
183 read++;
184 cnt--;
185 }
186 buf[i] = 0;
187
188 file->f_pos += read;
189
190 ret = ftrace_set_clr_event(buf, set);
191 if (ret)
192 goto out_free;
193
194 ret = read;
195
196 out_free:
197 kfree(buf);
198
199 return ret;
200}
201
202static void *
203t_next(struct seq_file *m, void *v, loff_t *pos)
204{
205 struct ftrace_event_call *call = m->private;
206 struct ftrace_event_call *next = call;
207
208 (*pos)++;
209
Steven Rostedt40e26812009-03-10 11:32:40 -0400210 for (;;) {
211 if ((unsigned long)call >= (unsigned long)__stop_ftrace_events)
212 return NULL;
213
214 /*
215 * The ftrace subsystem is for showing formats only.
216 * They can not be enabled or disabled via the event files.
217 */
218 if (call->regfunc)
219 break;
220
221 call++;
222 next = call;
223 }
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500224
225 m->private = ++next;
226
227 return call;
228}
229
230static void *t_start(struct seq_file *m, loff_t *pos)
231{
232 return t_next(m, NULL, pos);
233}
234
235static void *
236s_next(struct seq_file *m, void *v, loff_t *pos)
237{
238 struct ftrace_event_call *call = m->private;
239 struct ftrace_event_call *next;
240
241 (*pos)++;
242
243 retry:
244 if ((unsigned long)call >= (unsigned long)__stop_ftrace_events)
245 return NULL;
246
247 if (!call->enabled) {
248 call++;
249 goto retry;
250 }
251
252 next = call;
253 m->private = ++next;
254
255 return call;
256}
257
258static void *s_start(struct seq_file *m, loff_t *pos)
259{
260 return s_next(m, NULL, pos);
261}
262
263static int t_show(struct seq_file *m, void *v)
264{
265 struct ftrace_event_call *call = v;
266
Steven Rostedtb628b3e2009-02-27 23:32:58 -0500267 if (strcmp(call->system, TRACE_SYSTEM) != 0)
268 seq_printf(m, "%s:", call->system);
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500269 seq_printf(m, "%s\n", call->name);
270
271 return 0;
272}
273
274static void t_stop(struct seq_file *m, void *p)
275{
276}
277
278static int
279ftrace_event_seq_open(struct inode *inode, struct file *file)
280{
281 int ret;
282 const struct seq_operations *seq_ops;
283
284 if ((file->f_mode & FMODE_WRITE) &&
285 !(file->f_flags & O_APPEND))
286 ftrace_clear_events();
287
288 seq_ops = inode->i_private;
289 ret = seq_open(file, seq_ops);
290 if (!ret) {
291 struct seq_file *m = file->private_data;
292
293 m->private = __start_ftrace_events;
294 }
295 return ret;
296}
297
Steven Rostedt1473e442009-02-24 14:15:08 -0500298static ssize_t
299event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
300 loff_t *ppos)
301{
302 struct ftrace_event_call *call = filp->private_data;
303 char *buf;
304
Steven Rostedtda4d0302009-03-09 17:14:30 -0400305 if (call->enabled)
Steven Rostedt1473e442009-02-24 14:15:08 -0500306 buf = "1\n";
307 else
308 buf = "0\n";
309
310 return simple_read_from_buffer(ubuf, cnt, ppos, buf, 2);
311}
312
313static ssize_t
314event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
315 loff_t *ppos)
316{
317 struct ftrace_event_call *call = filp->private_data;
318 char buf[64];
319 unsigned long val;
320 int ret;
321
322 if (cnt >= sizeof(buf))
323 return -EINVAL;
324
325 if (copy_from_user(&buf, ubuf, cnt))
326 return -EFAULT;
327
328 buf[cnt] = 0;
329
330 ret = strict_strtoul(buf, 10, &val);
331 if (ret < 0)
332 return ret;
333
334 switch (val) {
335 case 0:
Steven Rostedt1473e442009-02-24 14:15:08 -0500336 case 1:
Steven Rostedt11a241a2009-03-02 11:49:04 -0500337 mutex_lock(&event_mutex);
Steven Rostedtfd994982009-02-28 02:41:25 -0500338 ftrace_event_enable_disable(call, val);
Steven Rostedt11a241a2009-03-02 11:49:04 -0500339 mutex_unlock(&event_mutex);
Steven Rostedt1473e442009-02-24 14:15:08 -0500340 break;
341
342 default:
343 return -EINVAL;
344 }
345
346 *ppos += cnt;
347
348 return cnt;
349}
350
Steven Rostedt91729ef92009-03-02 15:03:01 -0500351#undef FIELD
Steven Rostedt156b5f12009-03-06 10:50:53 -0500352#define FIELD(type, name) \
Steven Rostedtce8eb2b2009-03-10 10:14:35 -0400353 #type, #name, offsetof(typeof(field), name), sizeof(field.name)
Steven Rostedt91729ef92009-03-02 15:03:01 -0500354
355static int trace_write_header(struct trace_seq *s)
356{
357 struct trace_entry field;
358
359 /* struct trace_entry */
360 return trace_seq_printf(s,
Steven Rostedtce8eb2b2009-03-10 10:14:35 -0400361 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
362 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
363 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
364 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
365 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
Steven Rostedt91729ef92009-03-02 15:03:01 -0500366 "\n",
367 FIELD(unsigned char, type),
368 FIELD(unsigned char, flags),
369 FIELD(unsigned char, preempt_count),
370 FIELD(int, pid),
371 FIELD(int, tgid));
372}
Steven Rostedtda4d0302009-03-09 17:14:30 -0400373
Steven Rostedt981d0812009-03-02 13:53:59 -0500374static ssize_t
375event_format_read(struct file *filp, char __user *ubuf, size_t cnt,
376 loff_t *ppos)
377{
378 struct ftrace_event_call *call = filp->private_data;
379 struct trace_seq *s;
380 char *buf;
381 int r;
382
383 s = kmalloc(sizeof(*s), GFP_KERNEL);
384 if (!s)
385 return -ENOMEM;
386
387 trace_seq_init(s);
388
389 if (*ppos)
390 return 0;
391
Steven Rostedtc5e4e192009-03-02 15:10:02 -0500392 /* If any of the first writes fail, so will the show_format. */
393
394 trace_seq_printf(s, "name: %s\n", call->name);
395 trace_seq_printf(s, "ID: %d\n", call->id);
396 trace_seq_printf(s, "format:\n");
Steven Rostedt91729ef92009-03-02 15:03:01 -0500397 trace_write_header(s);
398
Steven Rostedt981d0812009-03-02 13:53:59 -0500399 r = call->show_format(s);
400 if (!r) {
401 /*
402 * ug! The format output is bigger than a PAGE!!
403 */
404 buf = "FORMAT TOO BIG\n";
405 r = simple_read_from_buffer(ubuf, cnt, ppos,
406 buf, strlen(buf));
407 goto out;
408 }
409
410 r = simple_read_from_buffer(ubuf, cnt, ppos,
411 s->buffer, s->len);
412 out:
413 kfree(s);
414 return r;
415}
416
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500417static const struct seq_operations show_event_seq_ops = {
418 .start = t_start,
419 .next = t_next,
420 .show = t_show,
421 .stop = t_stop,
422};
423
424static const struct seq_operations show_set_event_seq_ops = {
425 .start = s_start,
426 .next = s_next,
427 .show = t_show,
428 .stop = t_stop,
429};
430
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500431static const struct file_operations ftrace_set_event_fops = {
432 .open = ftrace_event_seq_open,
433 .read = seq_read,
434 .write = ftrace_event_write,
435 .llseek = seq_lseek,
436 .release = seq_release,
437};
438
Steven Rostedt1473e442009-02-24 14:15:08 -0500439static const struct file_operations ftrace_enable_fops = {
440 .open = tracing_open_generic,
441 .read = event_enable_read,
442 .write = event_enable_write,
443};
444
Steven Rostedt981d0812009-03-02 13:53:59 -0500445static const struct file_operations ftrace_event_format_fops = {
446 .open = tracing_open_generic,
447 .read = event_format_read,
448};
449
Steven Rostedt1473e442009-02-24 14:15:08 -0500450static struct dentry *event_trace_events_dir(void)
451{
452 static struct dentry *d_tracer;
453 static struct dentry *d_events;
454
455 if (d_events)
456 return d_events;
457
458 d_tracer = tracing_init_dentry();
459 if (!d_tracer)
460 return NULL;
461
462 d_events = debugfs_create_dir("events", d_tracer);
463 if (!d_events)
464 pr_warning("Could not create debugfs "
465 "'events' directory\n");
466
467 return d_events;
468}
469
Steven Rostedt6ecc2d12009-02-27 21:33:02 -0500470struct event_subsystem {
471 struct list_head list;
472 const char *name;
473 struct dentry *entry;
474};
475
476static LIST_HEAD(event_subsystems);
477
478static struct dentry *
479event_subsystem_dir(const char *name, struct dentry *d_events)
480{
481 struct event_subsystem *system;
482
483 /* First see if we did not already create this dir */
484 list_for_each_entry(system, &event_subsystems, list) {
485 if (strcmp(system->name, name) == 0)
486 return system->entry;
487 }
488
489 /* need to create new entry */
490 system = kmalloc(sizeof(*system), GFP_KERNEL);
491 if (!system) {
492 pr_warning("No memory to create event subsystem %s\n",
493 name);
494 return d_events;
495 }
496
497 system->entry = debugfs_create_dir(name, d_events);
498 if (!system->entry) {
499 pr_warning("Could not create event subsystem %s\n",
500 name);
501 kfree(system);
502 return d_events;
503 }
504
505 system->name = name;
506 list_add(&system->list, &event_subsystems);
507
508 return system->entry;
509}
510
Steven Rostedt1473e442009-02-24 14:15:08 -0500511static int
512event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
513{
514 struct dentry *entry;
Steven Rostedtfd994982009-02-28 02:41:25 -0500515 int ret;
Steven Rostedt1473e442009-02-24 14:15:08 -0500516
Steven Rostedt6ecc2d12009-02-27 21:33:02 -0500517 /*
518 * If the trace point header did not define TRACE_SYSTEM
519 * then the system would be called "TRACE_SYSTEM".
520 */
521 if (strcmp(call->system, "TRACE_SYSTEM") != 0)
522 d_events = event_subsystem_dir(call->system, d_events);
523
Steven Rostedtfd994982009-02-28 02:41:25 -0500524 if (call->raw_init) {
525 ret = call->raw_init();
526 if (ret < 0) {
527 pr_warning("Could not initialize trace point"
528 " events/%s\n", call->name);
529 return ret;
530 }
531 }
532
Steven Rostedt1473e442009-02-24 14:15:08 -0500533 call->dir = debugfs_create_dir(call->name, d_events);
534 if (!call->dir) {
535 pr_warning("Could not create debugfs "
536 "'%s' directory\n", call->name);
537 return -1;
538 }
539
Steven Rostedt770cb242009-03-05 21:35:29 -0500540 if (call->regfunc) {
541 entry = debugfs_create_file("enable", 0644, call->dir, call,
542 &ftrace_enable_fops);
543 if (!entry)
544 pr_warning("Could not create debugfs "
545 "'%s/enable' entry\n", call->name);
546 }
Steven Rostedt1473e442009-02-24 14:15:08 -0500547
Steven Rostedt981d0812009-03-02 13:53:59 -0500548 /* A trace may not want to export its format */
549 if (!call->show_format)
550 return 0;
551
552 entry = debugfs_create_file("format", 0444, call->dir, call,
553 &ftrace_event_format_fops);
554 if (!entry)
555 pr_warning("Could not create debugfs "
556 "'%s/format' entry\n", call->name);
Steven Rostedtfd994982009-02-28 02:41:25 -0500557
Steven Rostedt1473e442009-02-24 14:15:08 -0500558 return 0;
559}
560
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500561static __init int event_trace_init(void)
562{
Steven Rostedt1473e442009-02-24 14:15:08 -0500563 struct ftrace_event_call *call = __start_ftrace_events;
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500564 struct dentry *d_tracer;
565 struct dentry *entry;
Steven Rostedt1473e442009-02-24 14:15:08 -0500566 struct dentry *d_events;
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500567
568 d_tracer = tracing_init_dentry();
569 if (!d_tracer)
570 return 0;
571
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500572 entry = debugfs_create_file("set_event", 0644, d_tracer,
573 (void *)&show_set_event_seq_ops,
574 &ftrace_set_event_fops);
575 if (!entry)
576 pr_warning("Could not create debugfs "
577 "'set_event' entry\n");
578
Steven Rostedt1473e442009-02-24 14:15:08 -0500579 d_events = event_trace_events_dir();
580 if (!d_events)
581 return 0;
582
583 events_for_each(call) {
584 /* The linker may leave blanks */
585 if (!call->name)
586 continue;
587 event_create_dir(call, d_events);
588 }
589
Steven Rostedtb77e38a2009-02-24 10:21:36 -0500590 return 0;
591}
592fs_initcall(event_trace_init);