aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_events.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/trace_events.c')
-rw-r--r--kernel/trace/trace_events.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 6d2c842a0248..87feb0117ce2 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -400,6 +400,133 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
400 return cnt; 400 return cnt;
401} 401}
402 402
403static ssize_t
404system_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
405 loff_t *ppos)
406{
407 const char *system = filp->private_data;
408 struct ftrace_event_call *call;
409 char buf[2];
410 int set = -1;
411 int all = 0;
412 int ret;
413
414 if (system[0] == '*')
415 all = 1;
416
417 mutex_lock(&event_mutex);
418 list_for_each_entry(call, &ftrace_events, list) {
419 if (!call->name || !call->regfunc)
420 continue;
421
422 if (!all && strcmp(call->system, system) != 0)
423 continue;
424
425 /*
426 * We need to find out if all the events are set
427 * or if all events or cleared, or if we have
428 * a mixture.
429 */
430 if (call->enabled) {
431 switch (set) {
432 case -1:
433 set = 1;
434 break;
435 case 0:
436 set = 2;
437 break;
438 }
439 } else {
440 switch (set) {
441 case -1:
442 set = 0;
443 break;
444 case 1:
445 set = 2;
446 break;
447 }
448 }
449 /*
450 * If we have a mixture, no need to look further.
451 */
452 if (set == 2)
453 break;
454 }
455 mutex_unlock(&event_mutex);
456
457 buf[1] = '\n';
458 switch (set) {
459 case 0:
460 buf[0] = '0';
461 break;
462 case 1:
463 buf[0] = '1';
464 break;
465 case 2:
466 buf[0] = 'X';
467 break;
468 default:
469 buf[0] = '?';
470 }
471
472 ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, 2);
473
474 return ret;
475}
476
477static ssize_t
478system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
479 loff_t *ppos)
480{
481 const char *system = filp->private_data;
482 unsigned long val;
483 char *command;
484 char buf[64];
485 ssize_t ret;
486
487 if (cnt >= sizeof(buf))
488 return -EINVAL;
489
490 if (copy_from_user(&buf, ubuf, cnt))
491 return -EFAULT;
492
493 buf[cnt] = 0;
494
495 ret = strict_strtoul(buf, 10, &val);
496 if (ret < 0)
497 return ret;
498
499 ret = tracing_update_buffers();
500 if (ret < 0)
501 return ret;
502
503 switch (val) {
504 case 0:
505 case 1:
506 break;
507
508 default:
509 return -EINVAL;
510 }
511
512 command = kstrdup(system, GFP_KERNEL);
513 if (!command)
514 return -ENOMEM;
515
516 ret = ftrace_set_clr_event(command, val);
517 if (ret)
518 goto out_free;
519
520 ret = cnt;
521
522 out_free:
523 kfree(command);
524
525 *ppos += cnt;
526
527 return ret;
528}
529
403extern char *__bad_type_size(void); 530extern char *__bad_type_size(void);
404 531
405#undef FIELD 532#undef FIELD
@@ -686,6 +813,12 @@ static const struct file_operations ftrace_subsystem_filter_fops = {
686 .write = subsystem_filter_write, 813 .write = subsystem_filter_write,
687}; 814};
688 815
816static const struct file_operations ftrace_system_enable_fops = {
817 .open = tracing_open_generic,
818 .read = system_enable_read,
819 .write = system_enable_write,
820};
821
689static const struct file_operations ftrace_show_header_fops = { 822static const struct file_operations ftrace_show_header_fops = {
690 .open = tracing_open_generic, 823 .open = tracing_open_generic,
691 .read = show_header, 824 .read = show_header,
@@ -768,6 +901,10 @@ event_subsystem_dir(const char *name, struct dentry *d_events)
768 "'%s/filter' entry\n", name); 901 "'%s/filter' entry\n", name);
769 } 902 }
770 903
904 entry = trace_create_file("enable", 0644, system->entry,
905 (void *)system->name,
906 &ftrace_system_enable_fops);
907
771 return system->entry; 908 return system->entry;
772} 909}
773 910
@@ -1041,6 +1178,9 @@ static __init int event_trace_init(void)
1041 ring_buffer_print_entry_header, 1178 ring_buffer_print_entry_header,
1042 &ftrace_show_header_fops); 1179 &ftrace_show_header_fops);
1043 1180
1181 trace_create_file("enable", 0644, d_events,
1182 "*:*", &ftrace_system_enable_fops);
1183
1044 for_each_event(call, __start_ftrace_events, __stop_ftrace_events) { 1184 for_each_event(call, __start_ftrace_events, __stop_ftrace_events) {
1045 /* The linker may leave blanks */ 1185 /* The linker may leave blanks */
1046 if (!call->name) 1186 if (!call->name)