aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-16 15:23:18 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-16 15:23:18 -0500
commitb29c8306a368cf65782669eba079f81dc861c54d (patch)
tree35d75aa0e671070d4024f11338d3ae89b078b1ed /kernel/trace/ftrace.c
parent0bde7294e2ada03d0f1cc61cec51274081d9a9cf (diff)
parent3a81a5210b7d33bb6d836b4c4952a54166a336f3 (diff)
Merge tag 'trace-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracing update from Steven Rostedt: "This batch of changes is mostly clean ups and small bug fixes. The only real feature that was added this release is from Namhyung Kim, who introduced "set_graph_notrace" filter that lets you run the function graph tracer and not trace particular functions and their call chain. Tom Zanussi added some updates to the ftrace multibuffer tracing that made it more consistent with the top level tracing. One of the fixes for perf function tracing required an API change in RCU; the addition of "rcu_is_watching()". As Paul McKenney is pushing that change in this release too, he gave me a branch that included all the changes to get that working, and I pulled that into my tree in order to complete the perf function tracing fix" * tag 'trace-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: tracing: Add rcu annotation for syscall trace descriptors tracing: Do not use signed enums with unsigned long long in fgragh output tracing: Remove unused function ftrace_off_permanent() tracing: Do not assign filp->private_data to freed memory tracing: Add helper function tracing_is_disabled() tracing: Open tracer when ftrace_dump_on_oops is used tracing: Add support for SOFT_DISABLE to syscall events tracing: Make register/unregister_ftrace_command __init tracing: Update event filters for multibuffer recordmcount.pl: Add support for __fentry__ ftrace: Have control op function callback only trace when RCU is watching rcu: Do not trace rcu_is_watching() functions ftrace/x86: skip over the breakpoint for ftrace caller trace/trace_stat: use rbtree postorder iteration helper instead of opencoding ftrace: Add set_graph_notrace filter ftrace: Narrow down the protected area of graph_lock ftrace: Introduce struct ftrace_graph_data ftrace: Get rid of ftrace_graph_filter_enabled tracing: Fix potential out-of-bounds in trace_get_user() tracing: Show more exact help information about snapshot
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r--kernel/trace/ftrace.c161
1 files changed, 123 insertions, 38 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 03cf44ac54d3..22fa55696760 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3307,7 +3307,11 @@ void unregister_ftrace_function_probe_all(char *glob)
3307static LIST_HEAD(ftrace_commands); 3307static LIST_HEAD(ftrace_commands);
3308static DEFINE_MUTEX(ftrace_cmd_mutex); 3308static DEFINE_MUTEX(ftrace_cmd_mutex);
3309 3309
3310int register_ftrace_command(struct ftrace_func_command *cmd) 3310/*
3311 * Currently we only register ftrace commands from __init, so mark this
3312 * __init too.
3313 */
3314__init int register_ftrace_command(struct ftrace_func_command *cmd)
3311{ 3315{
3312 struct ftrace_func_command *p; 3316 struct ftrace_func_command *p;
3313 int ret = 0; 3317 int ret = 0;
@@ -3326,7 +3330,11 @@ int register_ftrace_command(struct ftrace_func_command *cmd)
3326 return ret; 3330 return ret;
3327} 3331}
3328 3332
3329int unregister_ftrace_command(struct ftrace_func_command *cmd) 3333/*
3334 * Currently we only unregister ftrace commands from __init, so mark
3335 * this __init too.
3336 */
3337__init int unregister_ftrace_command(struct ftrace_func_command *cmd)
3330{ 3338{
3331 struct ftrace_func_command *p, *n; 3339 struct ftrace_func_command *p, *n;
3332 int ret = -ENODEV; 3340 int ret = -ENODEV;
@@ -3641,7 +3649,7 @@ __setup("ftrace_filter=", set_ftrace_filter);
3641 3649
3642#ifdef CONFIG_FUNCTION_GRAPH_TRACER 3650#ifdef CONFIG_FUNCTION_GRAPH_TRACER
3643static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata; 3651static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata;
3644static int ftrace_set_func(unsigned long *array, int *idx, char *buffer); 3652static int ftrace_set_func(unsigned long *array, int *idx, int size, char *buffer);
3645 3653
3646static int __init set_graph_function(char *str) 3654static int __init set_graph_function(char *str)
3647{ 3655{
@@ -3659,7 +3667,7 @@ static void __init set_ftrace_early_graph(char *buf)
3659 func = strsep(&buf, ","); 3667 func = strsep(&buf, ",");
3660 /* we allow only one expression at a time */ 3668 /* we allow only one expression at a time */
3661 ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count, 3669 ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
3662 func); 3670 FTRACE_GRAPH_MAX_FUNCS, func);
3663 if (ret) 3671 if (ret)
3664 printk(KERN_DEBUG "ftrace: function %s not " 3672 printk(KERN_DEBUG "ftrace: function %s not "
3665 "traceable\n", func); 3673 "traceable\n", func);
@@ -3776,15 +3784,25 @@ static const struct file_operations ftrace_notrace_fops = {
3776static DEFINE_MUTEX(graph_lock); 3784static DEFINE_MUTEX(graph_lock);
3777 3785
3778int ftrace_graph_count; 3786int ftrace_graph_count;
3779int ftrace_graph_filter_enabled; 3787int ftrace_graph_notrace_count;
3780unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly; 3788unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
3789unsigned long ftrace_graph_notrace_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
3790
3791struct ftrace_graph_data {
3792 unsigned long *table;
3793 size_t size;
3794 int *count;
3795 const struct seq_operations *seq_ops;
3796};
3781 3797
3782static void * 3798static void *
3783__g_next(struct seq_file *m, loff_t *pos) 3799__g_next(struct seq_file *m, loff_t *pos)
3784{ 3800{
3785 if (*pos >= ftrace_graph_count) 3801 struct ftrace_graph_data *fgd = m->private;
3802
3803 if (*pos >= *fgd->count)
3786 return NULL; 3804 return NULL;
3787 return &ftrace_graph_funcs[*pos]; 3805 return &fgd->table[*pos];
3788} 3806}
3789 3807
3790static void * 3808static void *
@@ -3796,10 +3814,12 @@ g_next(struct seq_file *m, void *v, loff_t *pos)
3796 3814
3797static void *g_start(struct seq_file *m, loff_t *pos) 3815static void *g_start(struct seq_file *m, loff_t *pos)
3798{ 3816{
3817 struct ftrace_graph_data *fgd = m->private;
3818
3799 mutex_lock(&graph_lock); 3819 mutex_lock(&graph_lock);
3800 3820
3801 /* Nothing, tell g_show to print all functions are enabled */ 3821 /* Nothing, tell g_show to print all functions are enabled */
3802 if (!ftrace_graph_filter_enabled && !*pos) 3822 if (!*fgd->count && !*pos)
3803 return (void *)1; 3823 return (void *)1;
3804 3824
3805 return __g_next(m, pos); 3825 return __g_next(m, pos);
@@ -3835,38 +3855,88 @@ static const struct seq_operations ftrace_graph_seq_ops = {
3835}; 3855};
3836 3856
3837static int 3857static int
3838ftrace_graph_open(struct inode *inode, struct file *file) 3858__ftrace_graph_open(struct inode *inode, struct file *file,
3859 struct ftrace_graph_data *fgd)
3839{ 3860{
3840 int ret = 0; 3861 int ret = 0;
3841 3862
3842 if (unlikely(ftrace_disabled))
3843 return -ENODEV;
3844
3845 mutex_lock(&graph_lock); 3863 mutex_lock(&graph_lock);
3846 if ((file->f_mode & FMODE_WRITE) && 3864 if ((file->f_mode & FMODE_WRITE) &&
3847 (file->f_flags & O_TRUNC)) { 3865 (file->f_flags & O_TRUNC)) {
3848 ftrace_graph_filter_enabled = 0; 3866 *fgd->count = 0;
3849 ftrace_graph_count = 0; 3867 memset(fgd->table, 0, fgd->size * sizeof(*fgd->table));
3850 memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs));
3851 } 3868 }
3852 mutex_unlock(&graph_lock); 3869 mutex_unlock(&graph_lock);
3853 3870
3854 if (file->f_mode & FMODE_READ) 3871 if (file->f_mode & FMODE_READ) {
3855 ret = seq_open(file, &ftrace_graph_seq_ops); 3872 ret = seq_open(file, fgd->seq_ops);
3873 if (!ret) {
3874 struct seq_file *m = file->private_data;
3875 m->private = fgd;
3876 }
3877 } else
3878 file->private_data = fgd;
3856 3879
3857 return ret; 3880 return ret;
3858} 3881}
3859 3882
3860static int 3883static int
3884ftrace_graph_open(struct inode *inode, struct file *file)
3885{
3886 struct ftrace_graph_data *fgd;
3887
3888 if (unlikely(ftrace_disabled))
3889 return -ENODEV;
3890
3891 fgd = kmalloc(sizeof(*fgd), GFP_KERNEL);
3892 if (fgd == NULL)
3893 return -ENOMEM;
3894
3895 fgd->table = ftrace_graph_funcs;
3896 fgd->size = FTRACE_GRAPH_MAX_FUNCS;
3897 fgd->count = &ftrace_graph_count;
3898 fgd->seq_ops = &ftrace_graph_seq_ops;
3899
3900 return __ftrace_graph_open(inode, file, fgd);
3901}
3902
3903static int
3904ftrace_graph_notrace_open(struct inode *inode, struct file *file)
3905{
3906 struct ftrace_graph_data *fgd;
3907
3908 if (unlikely(ftrace_disabled))
3909 return -ENODEV;
3910
3911 fgd = kmalloc(sizeof(*fgd), GFP_KERNEL);
3912 if (fgd == NULL)
3913 return -ENOMEM;
3914
3915 fgd->table = ftrace_graph_notrace_funcs;
3916 fgd->size = FTRACE_GRAPH_MAX_FUNCS;
3917 fgd->count = &ftrace_graph_notrace_count;
3918 fgd->seq_ops = &ftrace_graph_seq_ops;
3919
3920 return __ftrace_graph_open(inode, file, fgd);
3921}
3922
3923static int
3861ftrace_graph_release(struct inode *inode, struct file *file) 3924ftrace_graph_release(struct inode *inode, struct file *file)
3862{ 3925{
3863 if (file->f_mode & FMODE_READ) 3926 if (file->f_mode & FMODE_READ) {
3927 struct seq_file *m = file->private_data;
3928
3929 kfree(m->private);
3864 seq_release(inode, file); 3930 seq_release(inode, file);
3931 } else {
3932 kfree(file->private_data);
3933 }
3934
3865 return 0; 3935 return 0;
3866} 3936}
3867 3937
3868static int 3938static int
3869ftrace_set_func(unsigned long *array, int *idx, char *buffer) 3939ftrace_set_func(unsigned long *array, int *idx, int size, char *buffer)
3870{ 3940{
3871 struct dyn_ftrace *rec; 3941 struct dyn_ftrace *rec;
3872 struct ftrace_page *pg; 3942 struct ftrace_page *pg;
@@ -3879,7 +3949,7 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
3879 3949
3880 /* decode regex */ 3950 /* decode regex */
3881 type = filter_parse_regex(buffer, strlen(buffer), &search, &not); 3951 type = filter_parse_regex(buffer, strlen(buffer), &search, &not);
3882 if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS) 3952 if (!not && *idx >= size)
3883 return -EBUSY; 3953 return -EBUSY;
3884 3954
3885 search_len = strlen(search); 3955 search_len = strlen(search);
@@ -3907,7 +3977,7 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
3907 fail = 0; 3977 fail = 0;
3908 if (!exists) { 3978 if (!exists) {
3909 array[(*idx)++] = rec->ip; 3979 array[(*idx)++] = rec->ip;
3910 if (*idx >= FTRACE_GRAPH_MAX_FUNCS) 3980 if (*idx >= size)
3911 goto out; 3981 goto out;
3912 } 3982 }
3913 } else { 3983 } else {
@@ -3925,8 +3995,6 @@ out:
3925 if (fail) 3995 if (fail)
3926 return -EINVAL; 3996 return -EINVAL;
3927 3997
3928 ftrace_graph_filter_enabled = !!(*idx);
3929
3930 return 0; 3998 return 0;
3931} 3999}
3932 4000
@@ -3935,36 +4003,33 @@ ftrace_graph_write(struct file *file, const char __user *ubuf,
3935 size_t cnt, loff_t *ppos) 4003 size_t cnt, loff_t *ppos)
3936{ 4004{
3937 struct trace_parser parser; 4005 struct trace_parser parser;
3938 ssize_t read, ret; 4006 ssize_t read, ret = 0;
4007 struct ftrace_graph_data *fgd = file->private_data;
3939 4008
3940 if (!cnt) 4009 if (!cnt)
3941 return 0; 4010 return 0;
3942 4011
3943 mutex_lock(&graph_lock); 4012 if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX))
3944 4013 return -ENOMEM;
3945 if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) {
3946 ret = -ENOMEM;
3947 goto out_unlock;
3948 }
3949 4014
3950 read = trace_get_user(&parser, ubuf, cnt, ppos); 4015 read = trace_get_user(&parser, ubuf, cnt, ppos);
3951 4016
3952 if (read >= 0 && trace_parser_loaded((&parser))) { 4017 if (read >= 0 && trace_parser_loaded((&parser))) {
3953 parser.buffer[parser.idx] = 0; 4018 parser.buffer[parser.idx] = 0;
3954 4019
4020 mutex_lock(&graph_lock);
4021
3955 /* we allow only one expression at a time */ 4022 /* we allow only one expression at a time */
3956 ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count, 4023 ret = ftrace_set_func(fgd->table, fgd->count, fgd->size,
3957 parser.buffer); 4024 parser.buffer);
3958 if (ret) 4025
3959 goto out_free; 4026 mutex_unlock(&graph_lock);
3960 } 4027 }
3961 4028
3962 ret = read; 4029 if (!ret)
4030 ret = read;
3963 4031
3964out_free:
3965 trace_parser_put(&parser); 4032 trace_parser_put(&parser);
3966out_unlock:
3967 mutex_unlock(&graph_lock);
3968 4033
3969 return ret; 4034 return ret;
3970} 4035}
@@ -3976,6 +4041,14 @@ static const struct file_operations ftrace_graph_fops = {
3976 .llseek = ftrace_filter_lseek, 4041 .llseek = ftrace_filter_lseek,
3977 .release = ftrace_graph_release, 4042 .release = ftrace_graph_release,
3978}; 4043};
4044
4045static const struct file_operations ftrace_graph_notrace_fops = {
4046 .open = ftrace_graph_notrace_open,
4047 .read = seq_read,
4048 .write = ftrace_graph_write,
4049 .llseek = ftrace_filter_lseek,
4050 .release = ftrace_graph_release,
4051};
3979#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 4052#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
3980 4053
3981static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer) 4054static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
@@ -3997,6 +4070,9 @@ static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
3997 trace_create_file("set_graph_function", 0444, d_tracer, 4070 trace_create_file("set_graph_function", 0444, d_tracer,
3998 NULL, 4071 NULL,
3999 &ftrace_graph_fops); 4072 &ftrace_graph_fops);
4073 trace_create_file("set_graph_notrace", 0444, d_tracer,
4074 NULL,
4075 &ftrace_graph_notrace_fops);
4000#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 4076#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
4001 4077
4002 return 0; 4078 return 0;
@@ -4320,12 +4396,21 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,
4320 */ 4396 */
4321 preempt_disable_notrace(); 4397 preempt_disable_notrace();
4322 trace_recursion_set(TRACE_CONTROL_BIT); 4398 trace_recursion_set(TRACE_CONTROL_BIT);
4399
4400 /*
4401 * Control funcs (perf) uses RCU. Only trace if
4402 * RCU is currently active.
4403 */
4404 if (!rcu_is_watching())
4405 goto out;
4406
4323 do_for_each_ftrace_op(op, ftrace_control_list) { 4407 do_for_each_ftrace_op(op, ftrace_control_list) {
4324 if (!(op->flags & FTRACE_OPS_FL_STUB) && 4408 if (!(op->flags & FTRACE_OPS_FL_STUB) &&
4325 !ftrace_function_local_disabled(op) && 4409 !ftrace_function_local_disabled(op) &&
4326 ftrace_ops_test(op, ip, regs)) 4410 ftrace_ops_test(op, ip, regs))
4327 op->func(ip, parent_ip, op, regs); 4411 op->func(ip, parent_ip, op, regs);
4328 } while_for_each_ftrace_op(op); 4412 } while_for_each_ftrace_op(op);
4413 out:
4329 trace_recursion_clear(TRACE_CONTROL_BIT); 4414 trace_recursion_clear(TRACE_CONTROL_BIT);
4330 preempt_enable_notrace(); 4415 preempt_enable_notrace();
4331} 4416}