diff options
| -rw-r--r-- | kernel/trace/ftrace.c | 18 | ||||
| -rw-r--r-- | kernel/trace/trace.c | 197 | ||||
| -rw-r--r-- | kernel/trace/trace.h | 8 |
3 files changed, 95 insertions, 128 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 67708f46baae..8ce9eefc5bb4 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -1441,12 +1441,22 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable, | |||
| 1441 | * the hashes are freed with call_rcu_sched(). | 1441 | * the hashes are freed with call_rcu_sched(). |
| 1442 | */ | 1442 | */ |
| 1443 | static int | 1443 | static int |
| 1444 | ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip) | 1444 | ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs) |
| 1445 | { | 1445 | { |
| 1446 | struct ftrace_hash *filter_hash; | 1446 | struct ftrace_hash *filter_hash; |
| 1447 | struct ftrace_hash *notrace_hash; | 1447 | struct ftrace_hash *notrace_hash; |
| 1448 | int ret; | 1448 | int ret; |
| 1449 | 1449 | ||
| 1450 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS | ||
| 1451 | /* | ||
| 1452 | * There's a small race when adding ops that the ftrace handler | ||
| 1453 | * that wants regs, may be called without them. We can not | ||
| 1454 | * allow that handler to be called if regs is NULL. | ||
| 1455 | */ | ||
| 1456 | if (regs == NULL && (ops->flags & FTRACE_OPS_FL_SAVE_REGS)) | ||
| 1457 | return 0; | ||
| 1458 | #endif | ||
| 1459 | |||
| 1450 | filter_hash = rcu_dereference_raw_notrace(ops->filter_hash); | 1460 | filter_hash = rcu_dereference_raw_notrace(ops->filter_hash); |
| 1451 | notrace_hash = rcu_dereference_raw_notrace(ops->notrace_hash); | 1461 | notrace_hash = rcu_dereference_raw_notrace(ops->notrace_hash); |
| 1452 | 1462 | ||
| @@ -4218,7 +4228,7 @@ static inline void ftrace_startup_enable(int command) { } | |||
| 4218 | # define ftrace_shutdown_sysctl() do { } while (0) | 4228 | # define ftrace_shutdown_sysctl() do { } while (0) |
| 4219 | 4229 | ||
| 4220 | static inline int | 4230 | static inline int |
| 4221 | ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip) | 4231 | ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs) |
| 4222 | { | 4232 | { |
| 4223 | return 1; | 4233 | return 1; |
| 4224 | } | 4234 | } |
| @@ -4241,7 +4251,7 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip, | |||
| 4241 | do_for_each_ftrace_op(op, ftrace_control_list) { | 4251 | do_for_each_ftrace_op(op, ftrace_control_list) { |
| 4242 | if (!(op->flags & FTRACE_OPS_FL_STUB) && | 4252 | if (!(op->flags & FTRACE_OPS_FL_STUB) && |
| 4243 | !ftrace_function_local_disabled(op) && | 4253 | !ftrace_function_local_disabled(op) && |
| 4244 | ftrace_ops_test(op, ip)) | 4254 | ftrace_ops_test(op, ip, regs)) |
| 4245 | op->func(ip, parent_ip, op, regs); | 4255 | op->func(ip, parent_ip, op, regs); |
| 4246 | } while_for_each_ftrace_op(op); | 4256 | } while_for_each_ftrace_op(op); |
| 4247 | trace_recursion_clear(TRACE_CONTROL_BIT); | 4257 | trace_recursion_clear(TRACE_CONTROL_BIT); |
| @@ -4274,7 +4284,7 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, | |||
| 4274 | */ | 4284 | */ |
| 4275 | preempt_disable_notrace(); | 4285 | preempt_disable_notrace(); |
| 4276 | do_for_each_ftrace_op(op, ftrace_ops_list) { | 4286 | do_for_each_ftrace_op(op, ftrace_ops_list) { |
| 4277 | if (ftrace_ops_test(op, ip)) | 4287 | if (ftrace_ops_test(op, ip, regs)) |
| 4278 | op->func(ip, parent_ip, op, regs); | 4288 | op->func(ip, parent_ip, op, regs); |
| 4279 | } while_for_each_ftrace_op(op); | 4289 | } while_for_each_ftrace_op(op); |
| 4280 | preempt_enable_notrace(); | 4290 | preempt_enable_notrace(); |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 3f2477713aca..882ec1dd1515 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
| @@ -1224,18 +1224,17 @@ void tracing_reset_current(int cpu) | |||
| 1224 | tracing_reset(&global_trace.trace_buffer, cpu); | 1224 | tracing_reset(&global_trace.trace_buffer, cpu); |
| 1225 | } | 1225 | } |
| 1226 | 1226 | ||
| 1227 | /* Must have trace_types_lock held */ | ||
| 1227 | void tracing_reset_all_online_cpus(void) | 1228 | void tracing_reset_all_online_cpus(void) |
| 1228 | { | 1229 | { |
| 1229 | struct trace_array *tr; | 1230 | struct trace_array *tr; |
| 1230 | 1231 | ||
| 1231 | mutex_lock(&trace_types_lock); | ||
| 1232 | list_for_each_entry(tr, &ftrace_trace_arrays, list) { | 1232 | list_for_each_entry(tr, &ftrace_trace_arrays, list) { |
| 1233 | tracing_reset_online_cpus(&tr->trace_buffer); | 1233 | tracing_reset_online_cpus(&tr->trace_buffer); |
| 1234 | #ifdef CONFIG_TRACER_MAX_TRACE | 1234 | #ifdef CONFIG_TRACER_MAX_TRACE |
| 1235 | tracing_reset_online_cpus(&tr->max_buffer); | 1235 | tracing_reset_online_cpus(&tr->max_buffer); |
| 1236 | #endif | 1236 | #endif |
| 1237 | } | 1237 | } |
| 1238 | mutex_unlock(&trace_types_lock); | ||
| 1239 | } | 1238 | } |
| 1240 | 1239 | ||
| 1241 | #define SAVED_CMDLINES 128 | 1240 | #define SAVED_CMDLINES 128 |
| @@ -2843,6 +2842,17 @@ static int s_show(struct seq_file *m, void *v) | |||
| 2843 | return 0; | 2842 | return 0; |
| 2844 | } | 2843 | } |
| 2845 | 2844 | ||
| 2845 | /* | ||
| 2846 | * Should be used after trace_array_get(), trace_types_lock | ||
| 2847 | * ensures that i_cdev was already initialized. | ||
| 2848 | */ | ||
| 2849 | static inline int tracing_get_cpu(struct inode *inode) | ||
| 2850 | { | ||
| 2851 | if (inode->i_cdev) /* See trace_create_cpu_file() */ | ||
| 2852 | return (long)inode->i_cdev - 1; | ||
| 2853 | return RING_BUFFER_ALL_CPUS; | ||
| 2854 | } | ||
| 2855 | |||
| 2846 | static const struct seq_operations tracer_seq_ops = { | 2856 | static const struct seq_operations tracer_seq_ops = { |
| 2847 | .start = s_start, | 2857 | .start = s_start, |
| 2848 | .next = s_next, | 2858 | .next = s_next, |
| @@ -2851,9 +2861,9 @@ static const struct seq_operations tracer_seq_ops = { | |||
| 2851 | }; | 2861 | }; |
| 2852 | 2862 | ||
| 2853 | static struct trace_iterator * | 2863 | static struct trace_iterator * |
| 2854 | __tracing_open(struct trace_array *tr, struct trace_cpu *tc, | 2864 | __tracing_open(struct inode *inode, struct file *file, bool snapshot) |
| 2855 | struct inode *inode, struct file *file, bool snapshot) | ||
| 2856 | { | 2865 | { |
| 2866 | struct trace_array *tr = inode->i_private; | ||
| 2857 | struct trace_iterator *iter; | 2867 | struct trace_iterator *iter; |
| 2858 | int cpu; | 2868 | int cpu; |
| 2859 | 2869 | ||
| @@ -2894,8 +2904,8 @@ __tracing_open(struct trace_array *tr, struct trace_cpu *tc, | |||
| 2894 | iter->trace_buffer = &tr->trace_buffer; | 2904 | iter->trace_buffer = &tr->trace_buffer; |
| 2895 | iter->snapshot = snapshot; | 2905 | iter->snapshot = snapshot; |
| 2896 | iter->pos = -1; | 2906 | iter->pos = -1; |
| 2907 | iter->cpu_file = tracing_get_cpu(inode); | ||
| 2897 | mutex_init(&iter->mutex); | 2908 | mutex_init(&iter->mutex); |
| 2898 | iter->cpu_file = tc->cpu; | ||
| 2899 | 2909 | ||
| 2900 | /* Notify the tracer early; before we stop tracing. */ | 2910 | /* Notify the tracer early; before we stop tracing. */ |
| 2901 | if (iter->trace && iter->trace->open) | 2911 | if (iter->trace && iter->trace->open) |
| @@ -2971,44 +2981,22 @@ static int tracing_open_generic_tr(struct inode *inode, struct file *filp) | |||
| 2971 | filp->private_data = inode->i_private; | 2981 | filp->private_data = inode->i_private; |
| 2972 | 2982 | ||
| 2973 | return 0; | 2983 | return 0; |
| 2974 | |||
| 2975 | } | ||
| 2976 | |||
| 2977 | static int tracing_open_generic_tc(struct inode *inode, struct file *filp) | ||
| 2978 | { | ||
| 2979 | struct trace_cpu *tc = inode->i_private; | ||
| 2980 | struct trace_array *tr = tc->tr; | ||
| 2981 | |||
| 2982 | if (tracing_disabled) | ||
| 2983 | return -ENODEV; | ||
| 2984 | |||
| 2985 | if (trace_array_get(tr) < 0) | ||
| 2986 | return -ENODEV; | ||
| 2987 | |||
| 2988 | filp->private_data = inode->i_private; | ||
| 2989 | |||
| 2990 | return 0; | ||
| 2991 | |||
| 2992 | } | 2984 | } |
| 2993 | 2985 | ||
| 2994 | static int tracing_release(struct inode *inode, struct file *file) | 2986 | static int tracing_release(struct inode *inode, struct file *file) |
| 2995 | { | 2987 | { |
| 2988 | struct trace_array *tr = inode->i_private; | ||
| 2996 | struct seq_file *m = file->private_data; | 2989 | struct seq_file *m = file->private_data; |
| 2997 | struct trace_iterator *iter; | 2990 | struct trace_iterator *iter; |
| 2998 | struct trace_array *tr; | ||
| 2999 | int cpu; | 2991 | int cpu; |
| 3000 | 2992 | ||
| 3001 | /* Writes do not use seq_file, need to grab tr from inode */ | ||
| 3002 | if (!(file->f_mode & FMODE_READ)) { | 2993 | if (!(file->f_mode & FMODE_READ)) { |
| 3003 | struct trace_cpu *tc = inode->i_private; | 2994 | trace_array_put(tr); |
| 3004 | |||
| 3005 | trace_array_put(tc->tr); | ||
| 3006 | return 0; | 2995 | return 0; |
| 3007 | } | 2996 | } |
| 3008 | 2997 | ||
| 2998 | /* Writes do not use seq_file */ | ||
| 3009 | iter = m->private; | 2999 | iter = m->private; |
| 3010 | tr = iter->tr; | ||
| 3011 | |||
| 3012 | mutex_lock(&trace_types_lock); | 3000 | mutex_lock(&trace_types_lock); |
| 3013 | 3001 | ||
| 3014 | for_each_tracing_cpu(cpu) { | 3002 | for_each_tracing_cpu(cpu) { |
| @@ -3044,15 +3032,6 @@ static int tracing_release_generic_tr(struct inode *inode, struct file *file) | |||
| 3044 | return 0; | 3032 | return 0; |
| 3045 | } | 3033 | } |
| 3046 | 3034 | ||
| 3047 | static int tracing_release_generic_tc(struct inode *inode, struct file *file) | ||
| 3048 | { | ||
| 3049 | struct trace_cpu *tc = inode->i_private; | ||
| 3050 | struct trace_array *tr = tc->tr; | ||
| 3051 | |||
| 3052 | trace_array_put(tr); | ||
| 3053 | return 0; | ||
| 3054 | } | ||
| 3055 | |||
| 3056 | static int tracing_single_release_tr(struct inode *inode, struct file *file) | 3035 | static int tracing_single_release_tr(struct inode *inode, struct file *file) |
| 3057 | { | 3036 | { |
| 3058 | struct trace_array *tr = inode->i_private; | 3037 | struct trace_array *tr = inode->i_private; |
| @@ -3064,8 +3043,7 @@ static int tracing_single_release_tr(struct inode *inode, struct file *file) | |||
| 3064 | 3043 | ||
| 3065 | static int tracing_open(struct inode *inode, struct file *file) | 3044 | static int tracing_open(struct inode *inode, struct file *file) |
| 3066 | { | 3045 | { |
| 3067 | struct trace_cpu *tc = inode->i_private; | 3046 | struct trace_array *tr = inode->i_private; |
| 3068 | struct trace_array *tr = tc->tr; | ||
| 3069 | struct trace_iterator *iter; | 3047 | struct trace_iterator *iter; |
| 3070 | int ret = 0; | 3048 | int ret = 0; |
| 3071 | 3049 | ||
| @@ -3073,16 +3051,17 @@ static int tracing_open(struct inode *inode, struct file *file) | |||
| 3073 | return -ENODEV; | 3051 | return -ENODEV; |
| 3074 | 3052 | ||
| 3075 | /* If this file was open for write, then erase contents */ | 3053 | /* If this file was open for write, then erase contents */ |
| 3076 | if ((file->f_mode & FMODE_WRITE) && | 3054 | if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { |
| 3077 | (file->f_flags & O_TRUNC)) { | 3055 | int cpu = tracing_get_cpu(inode); |
| 3078 | if (tc->cpu == RING_BUFFER_ALL_CPUS) | 3056 | |
| 3057 | if (cpu == RING_BUFFER_ALL_CPUS) | ||
| 3079 | tracing_reset_online_cpus(&tr->trace_buffer); | 3058 | tracing_reset_online_cpus(&tr->trace_buffer); |
| 3080 | else | 3059 | else |
| 3081 | tracing_reset(&tr->trace_buffer, tc->cpu); | 3060 | tracing_reset(&tr->trace_buffer, cpu); |
| 3082 | } | 3061 | } |
| 3083 | 3062 | ||
| 3084 | if (file->f_mode & FMODE_READ) { | 3063 | if (file->f_mode & FMODE_READ) { |
| 3085 | iter = __tracing_open(tr, tc, inode, file, false); | 3064 | iter = __tracing_open(inode, file, false); |
| 3086 | if (IS_ERR(iter)) | 3065 | if (IS_ERR(iter)) |
| 3087 | ret = PTR_ERR(iter); | 3066 | ret = PTR_ERR(iter); |
| 3088 | else if (trace_flags & TRACE_ITER_LATENCY_FMT) | 3067 | else if (trace_flags & TRACE_ITER_LATENCY_FMT) |
| @@ -3948,8 +3927,7 @@ tracing_max_lat_write(struct file *filp, const char __user *ubuf, | |||
| 3948 | 3927 | ||
| 3949 | static int tracing_open_pipe(struct inode *inode, struct file *filp) | 3928 | static int tracing_open_pipe(struct inode *inode, struct file *filp) |
| 3950 | { | 3929 | { |
| 3951 | struct trace_cpu *tc = inode->i_private; | 3930 | struct trace_array *tr = inode->i_private; |
| 3952 | struct trace_array *tr = tc->tr; | ||
| 3953 | struct trace_iterator *iter; | 3931 | struct trace_iterator *iter; |
| 3954 | int ret = 0; | 3932 | int ret = 0; |
| 3955 | 3933 | ||
| @@ -3995,9 +3973,9 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp) | |||
| 3995 | if (trace_clocks[tr->clock_id].in_ns) | 3973 | if (trace_clocks[tr->clock_id].in_ns) |
| 3996 | iter->iter_flags |= TRACE_FILE_TIME_IN_NS; | 3974 | iter->iter_flags |= TRACE_FILE_TIME_IN_NS; |
| 3997 | 3975 | ||
| 3998 | iter->cpu_file = tc->cpu; | 3976 | iter->tr = tr; |
| 3999 | iter->tr = tc->tr; | 3977 | iter->trace_buffer = &tr->trace_buffer; |
| 4000 | iter->trace_buffer = &tc->tr->trace_buffer; | 3978 | iter->cpu_file = tracing_get_cpu(inode); |
| 4001 | mutex_init(&iter->mutex); | 3979 | mutex_init(&iter->mutex); |
| 4002 | filp->private_data = iter; | 3980 | filp->private_data = iter; |
| 4003 | 3981 | ||
| @@ -4020,8 +3998,7 @@ fail: | |||
| 4020 | static int tracing_release_pipe(struct inode *inode, struct file *file) | 3998 | static int tracing_release_pipe(struct inode *inode, struct file *file) |
| 4021 | { | 3999 | { |
| 4022 | struct trace_iterator *iter = file->private_data; | 4000 | struct trace_iterator *iter = file->private_data; |
| 4023 | struct trace_cpu *tc = inode->i_private; | 4001 | struct trace_array *tr = inode->i_private; |
| 4024 | struct trace_array *tr = tc->tr; | ||
| 4025 | 4002 | ||
| 4026 | mutex_lock(&trace_types_lock); | 4003 | mutex_lock(&trace_types_lock); |
| 4027 | 4004 | ||
| @@ -4374,15 +4351,16 @@ static ssize_t | |||
| 4374 | tracing_entries_read(struct file *filp, char __user *ubuf, | 4351 | tracing_entries_read(struct file *filp, char __user *ubuf, |
| 4375 | size_t cnt, loff_t *ppos) | 4352 | size_t cnt, loff_t *ppos) |
| 4376 | { | 4353 | { |
| 4377 | struct trace_cpu *tc = filp->private_data; | 4354 | struct inode *inode = file_inode(filp); |
| 4378 | struct trace_array *tr = tc->tr; | 4355 | struct trace_array *tr = inode->i_private; |
| 4356 | int cpu = tracing_get_cpu(inode); | ||
| 4379 | char buf[64]; | 4357 | char buf[64]; |
| 4380 | int r = 0; | 4358 | int r = 0; |
| 4381 | ssize_t ret; | 4359 | ssize_t ret; |
| 4382 | 4360 | ||
| 4383 | mutex_lock(&trace_types_lock); | 4361 | mutex_lock(&trace_types_lock); |
| 4384 | 4362 | ||
| 4385 | if (tc->cpu == RING_BUFFER_ALL_CPUS) { | 4363 | if (cpu == RING_BUFFER_ALL_CPUS) { |
| 4386 | int cpu, buf_size_same; | 4364 | int cpu, buf_size_same; |
| 4387 | unsigned long size; | 4365 | unsigned long size; |
| 4388 | 4366 | ||
| @@ -4409,7 +4387,7 @@ tracing_entries_read(struct file *filp, char __user *ubuf, | |||
| 4409 | } else | 4387 | } else |
| 4410 | r = sprintf(buf, "X\n"); | 4388 | r = sprintf(buf, "X\n"); |
| 4411 | } else | 4389 | } else |
| 4412 | r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->trace_buffer.data, tc->cpu)->entries >> 10); | 4390 | r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->trace_buffer.data, cpu)->entries >> 10); |
| 4413 | 4391 | ||
| 4414 | mutex_unlock(&trace_types_lock); | 4392 | mutex_unlock(&trace_types_lock); |
| 4415 | 4393 | ||
| @@ -4421,7 +4399,8 @@ static ssize_t | |||
| 4421 | tracing_entries_write(struct file *filp, const char __user *ubuf, | 4399 | tracing_entries_write(struct file *filp, const char __user *ubuf, |
| 4422 | size_t cnt, loff_t *ppos) | 4400 | size_t cnt, loff_t *ppos) |
| 4423 | { | 4401 | { |
| 4424 | struct trace_cpu *tc = filp->private_data; | 4402 | struct inode *inode = file_inode(filp); |
| 4403 | struct trace_array *tr = inode->i_private; | ||
| 4425 | unsigned long val; | 4404 | unsigned long val; |
| 4426 | int ret; | 4405 | int ret; |
| 4427 | 4406 | ||
| @@ -4435,8 +4414,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
| 4435 | 4414 | ||
| 4436 | /* value is in KB */ | 4415 | /* value is in KB */ |
| 4437 | val <<= 10; | 4416 | val <<= 10; |
| 4438 | 4417 | ret = tracing_resize_ring_buffer(tr, val, tracing_get_cpu(inode)); | |
| 4439 | ret = tracing_resize_ring_buffer(tc->tr, val, tc->cpu); | ||
| 4440 | if (ret < 0) | 4418 | if (ret < 0) |
| 4441 | return ret; | 4419 | return ret; |
| 4442 | 4420 | ||
| @@ -4697,8 +4675,7 @@ struct ftrace_buffer_info { | |||
| 4697 | #ifdef CONFIG_TRACER_SNAPSHOT | 4675 | #ifdef CONFIG_TRACER_SNAPSHOT |
| 4698 | static int tracing_snapshot_open(struct inode *inode, struct file *file) | 4676 | static int tracing_snapshot_open(struct inode *inode, struct file *file) |
| 4699 | { | 4677 | { |
| 4700 | struct trace_cpu *tc = inode->i_private; | 4678 | struct trace_array *tr = inode->i_private; |
| 4701 | struct trace_array *tr = tc->tr; | ||
| 4702 | struct trace_iterator *iter; | 4679 | struct trace_iterator *iter; |
| 4703 | struct seq_file *m; | 4680 | struct seq_file *m; |
| 4704 | int ret = 0; | 4681 | int ret = 0; |
| @@ -4707,7 +4684,7 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file) | |||
| 4707 | return -ENODEV; | 4684 | return -ENODEV; |
| 4708 | 4685 | ||
| 4709 | if (file->f_mode & FMODE_READ) { | 4686 | if (file->f_mode & FMODE_READ) { |
| 4710 | iter = __tracing_open(tr, tc, inode, file, true); | 4687 | iter = __tracing_open(inode, file, true); |
| 4711 | if (IS_ERR(iter)) | 4688 | if (IS_ERR(iter)) |
| 4712 | ret = PTR_ERR(iter); | 4689 | ret = PTR_ERR(iter); |
| 4713 | } else { | 4690 | } else { |
| @@ -4724,8 +4701,8 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file) | |||
| 4724 | ret = 0; | 4701 | ret = 0; |
| 4725 | 4702 | ||
| 4726 | iter->tr = tr; | 4703 | iter->tr = tr; |
| 4727 | iter->trace_buffer = &tc->tr->max_buffer; | 4704 | iter->trace_buffer = &tr->max_buffer; |
| 4728 | iter->cpu_file = tc->cpu; | 4705 | iter->cpu_file = tracing_get_cpu(inode); |
| 4729 | m->private = iter; | 4706 | m->private = iter; |
| 4730 | file->private_data = m; | 4707 | file->private_data = m; |
| 4731 | } | 4708 | } |
| @@ -4884,11 +4861,11 @@ static const struct file_operations tracing_pipe_fops = { | |||
| 4884 | }; | 4861 | }; |
| 4885 | 4862 | ||
| 4886 | static const struct file_operations tracing_entries_fops = { | 4863 | static const struct file_operations tracing_entries_fops = { |
| 4887 | .open = tracing_open_generic_tc, | 4864 | .open = tracing_open_generic_tr, |
| 4888 | .read = tracing_entries_read, | 4865 | .read = tracing_entries_read, |
| 4889 | .write = tracing_entries_write, | 4866 | .write = tracing_entries_write, |
| 4890 | .llseek = generic_file_llseek, | 4867 | .llseek = generic_file_llseek, |
| 4891 | .release = tracing_release_generic_tc, | 4868 | .release = tracing_release_generic_tr, |
| 4892 | }; | 4869 | }; |
| 4893 | 4870 | ||
| 4894 | static const struct file_operations tracing_total_entries_fops = { | 4871 | static const struct file_operations tracing_total_entries_fops = { |
| @@ -4940,8 +4917,7 @@ static const struct file_operations snapshot_raw_fops = { | |||
| 4940 | 4917 | ||
| 4941 | static int tracing_buffers_open(struct inode *inode, struct file *filp) | 4918 | static int tracing_buffers_open(struct inode *inode, struct file *filp) |
| 4942 | { | 4919 | { |
| 4943 | struct trace_cpu *tc = inode->i_private; | 4920 | struct trace_array *tr = inode->i_private; |
| 4944 | struct trace_array *tr = tc->tr; | ||
| 4945 | struct ftrace_buffer_info *info; | 4921 | struct ftrace_buffer_info *info; |
| 4946 | int ret; | 4922 | int ret; |
| 4947 | 4923 | ||
| @@ -4960,7 +4936,7 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp) | |||
| 4960 | mutex_lock(&trace_types_lock); | 4936 | mutex_lock(&trace_types_lock); |
| 4961 | 4937 | ||
| 4962 | info->iter.tr = tr; | 4938 | info->iter.tr = tr; |
| 4963 | info->iter.cpu_file = tc->cpu; | 4939 | info->iter.cpu_file = tracing_get_cpu(inode); |
| 4964 | info->iter.trace = tr->current_trace; | 4940 | info->iter.trace = tr->current_trace; |
| 4965 | info->iter.trace_buffer = &tr->trace_buffer; | 4941 | info->iter.trace_buffer = &tr->trace_buffer; |
| 4966 | info->spare = NULL; | 4942 | info->spare = NULL; |
| @@ -5277,14 +5253,14 @@ static ssize_t | |||
| 5277 | tracing_stats_read(struct file *filp, char __user *ubuf, | 5253 | tracing_stats_read(struct file *filp, char __user *ubuf, |
| 5278 | size_t count, loff_t *ppos) | 5254 | size_t count, loff_t *ppos) |
| 5279 | { | 5255 | { |
| 5280 | struct trace_cpu *tc = filp->private_data; | 5256 | struct inode *inode = file_inode(filp); |
| 5281 | struct trace_array *tr = tc->tr; | 5257 | struct trace_array *tr = inode->i_private; |
| 5282 | struct trace_buffer *trace_buf = &tr->trace_buffer; | 5258 | struct trace_buffer *trace_buf = &tr->trace_buffer; |
| 5259 | int cpu = tracing_get_cpu(inode); | ||
| 5283 | struct trace_seq *s; | 5260 | struct trace_seq *s; |
| 5284 | unsigned long cnt; | 5261 | unsigned long cnt; |
| 5285 | unsigned long long t; | 5262 | unsigned long long t; |
| 5286 | unsigned long usec_rem; | 5263 | unsigned long usec_rem; |
| 5287 | int cpu = tc->cpu; | ||
| 5288 | 5264 | ||
| 5289 | s = kmalloc(sizeof(*s), GFP_KERNEL); | 5265 | s = kmalloc(sizeof(*s), GFP_KERNEL); |
| 5290 | if (!s) | 5266 | if (!s) |
| @@ -5337,10 +5313,10 @@ tracing_stats_read(struct file *filp, char __user *ubuf, | |||
| 5337 | } | 5313 | } |
| 5338 | 5314 | ||
| 5339 | static const struct file_operations tracing_stats_fops = { | 5315 | static const struct file_operations tracing_stats_fops = { |
| 5340 | .open = tracing_open_generic_tc, | 5316 | .open = tracing_open_generic_tr, |
| 5341 | .read = tracing_stats_read, | 5317 | .read = tracing_stats_read, |
| 5342 | .llseek = generic_file_llseek, | 5318 | .llseek = generic_file_llseek, |
| 5343 | .release = tracing_release_generic_tc, | 5319 | .release = tracing_release_generic_tr, |
| 5344 | }; | 5320 | }; |
| 5345 | 5321 | ||
| 5346 | #ifdef CONFIG_DYNAMIC_FTRACE | 5322 | #ifdef CONFIG_DYNAMIC_FTRACE |
| @@ -5529,10 +5505,20 @@ static struct dentry *tracing_dentry_percpu(struct trace_array *tr, int cpu) | |||
| 5529 | return tr->percpu_dir; | 5505 | return tr->percpu_dir; |
| 5530 | } | 5506 | } |
| 5531 | 5507 | ||
| 5508 | static struct dentry * | ||
| 5509 | trace_create_cpu_file(const char *name, umode_t mode, struct dentry *parent, | ||
| 5510 | void *data, long cpu, const struct file_operations *fops) | ||
| 5511 | { | ||
| 5512 | struct dentry *ret = trace_create_file(name, mode, parent, data, fops); | ||
| 5513 | |||
| 5514 | if (ret) /* See tracing_get_cpu() */ | ||
| 5515 | ret->d_inode->i_cdev = (void *)(cpu + 1); | ||
| 5516 | return ret; | ||
| 5517 | } | ||
| 5518 | |||
| 5532 | static void | 5519 | static void |
| 5533 | tracing_init_debugfs_percpu(struct trace_array *tr, long cpu) | 5520 | tracing_init_debugfs_percpu(struct trace_array *tr, long cpu) |
| 5534 | { | 5521 | { |
| 5535 | struct trace_array_cpu *data = per_cpu_ptr(tr->trace_buffer.data, cpu); | ||
| 5536 | struct dentry *d_percpu = tracing_dentry_percpu(tr, cpu); | 5522 | struct dentry *d_percpu = tracing_dentry_percpu(tr, cpu); |
| 5537 | struct dentry *d_cpu; | 5523 | struct dentry *d_cpu; |
| 5538 | char cpu_dir[30]; /* 30 characters should be more than enough */ | 5524 | char cpu_dir[30]; /* 30 characters should be more than enough */ |
| @@ -5548,28 +5534,28 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu) | |||
| 5548 | } | 5534 | } |
| 5549 | 5535 | ||
| 5550 | /* per cpu trace_pipe */ | 5536 | /* per cpu trace_pipe */ |
| 5551 | trace_create_file("trace_pipe", 0444, d_cpu, | 5537 | trace_create_cpu_file("trace_pipe", 0444, d_cpu, |
| 5552 | (void *)&data->trace_cpu, &tracing_pipe_fops); | 5538 | tr, cpu, &tracing_pipe_fops); |
| 5553 | 5539 | ||
| 5554 | /* per cpu trace */ | 5540 | /* per cpu trace */ |
| 5555 | trace_create_file("trace", 0644, d_cpu, | 5541 | trace_create_cpu_file("trace", 0644, d_cpu, |
| 5556 | (void *)&data->trace_cpu, &tracing_fops); | 5542 | tr, cpu, &tracing_fops); |
| 5557 | 5543 | ||
| 5558 | trace_create_file("trace_pipe_raw", 0444, d_cpu, | 5544 | trace_create_cpu_file("trace_pipe_raw", 0444, d_cpu, |
| 5559 | (void *)&data->trace_cpu, &tracing_buffers_fops); | 5545 | tr, cpu, &tracing_buffers_fops); |
| 5560 | 5546 | ||
| 5561 | trace_create_file("stats", 0444, d_cpu, | 5547 | trace_create_cpu_file("stats", 0444, d_cpu, |
| 5562 | (void *)&data->trace_cpu, &tracing_stats_fops); | 5548 | tr, cpu, &tracing_stats_fops); |
| 5563 | 5549 | ||
| 5564 | trace_create_file("buffer_size_kb", 0444, d_cpu, | 5550 | trace_create_cpu_file("buffer_size_kb", 0444, d_cpu, |
| 5565 | (void *)&data->trace_cpu, &tracing_entries_fops); | 5551 | tr, cpu, &tracing_entries_fops); |
| 5566 | 5552 | ||
| 5567 | #ifdef CONFIG_TRACER_SNAPSHOT | 5553 | #ifdef CONFIG_TRACER_SNAPSHOT |
| 5568 | trace_create_file("snapshot", 0644, d_cpu, | 5554 | trace_create_cpu_file("snapshot", 0644, d_cpu, |
| 5569 | (void *)&data->trace_cpu, &snapshot_fops); | 5555 | tr, cpu, &snapshot_fops); |
| 5570 | 5556 | ||
| 5571 | trace_create_file("snapshot_raw", 0444, d_cpu, | 5557 | trace_create_cpu_file("snapshot_raw", 0444, d_cpu, |
| 5572 | (void *)&data->trace_cpu, &snapshot_raw_fops); | 5558 | tr, cpu, &snapshot_raw_fops); |
| 5573 | #endif | 5559 | #endif |
| 5574 | } | 5560 | } |
| 5575 | 5561 | ||
| @@ -5878,17 +5864,6 @@ struct dentry *trace_instance_dir; | |||
| 5878 | static void | 5864 | static void |
| 5879 | init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer); | 5865 | init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer); |
| 5880 | 5866 | ||
| 5881 | static void init_trace_buffers(struct trace_array *tr, struct trace_buffer *buf) | ||
| 5882 | { | ||
| 5883 | int cpu; | ||
| 5884 | |||
| 5885 | for_each_tracing_cpu(cpu) { | ||
| 5886 | memset(per_cpu_ptr(buf->data, cpu), 0, sizeof(struct trace_array_cpu)); | ||
| 5887 | per_cpu_ptr(buf->data, cpu)->trace_cpu.cpu = cpu; | ||
| 5888 | per_cpu_ptr(buf->data, cpu)->trace_cpu.tr = tr; | ||
| 5889 | } | ||
| 5890 | } | ||
| 5891 | |||
| 5892 | static int | 5867 | static int |
| 5893 | allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int size) | 5868 | allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int size) |
| 5894 | { | 5869 | { |
| @@ -5906,8 +5881,6 @@ allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int size | |||
| 5906 | return -ENOMEM; | 5881 | return -ENOMEM; |
| 5907 | } | 5882 | } |
| 5908 | 5883 | ||
| 5909 | init_trace_buffers(tr, buf); | ||
| 5910 | |||
| 5911 | /* Allocate the first page for all buffers */ | 5884 | /* Allocate the first page for all buffers */ |
| 5912 | set_buffer_entries(&tr->trace_buffer, | 5885 | set_buffer_entries(&tr->trace_buffer, |
| 5913 | ring_buffer_size(tr->trace_buffer.buffer, 0)); | 5886 | ring_buffer_size(tr->trace_buffer.buffer, 0)); |
| @@ -5974,10 +5947,6 @@ static int new_instance_create(const char *name) | |||
| 5974 | if (allocate_trace_buffers(tr, trace_buf_size) < 0) | 5947 | if (allocate_trace_buffers(tr, trace_buf_size) < 0) |
| 5975 | goto out_free_tr; | 5948 | goto out_free_tr; |
| 5976 | 5949 | ||
| 5977 | /* Holder for file callbacks */ | ||
| 5978 | tr->trace_cpu.cpu = RING_BUFFER_ALL_CPUS; | ||
| 5979 | tr->trace_cpu.tr = tr; | ||
| 5980 | |||
| 5981 | tr->dir = debugfs_create_dir(name, trace_instance_dir); | 5950 | tr->dir = debugfs_create_dir(name, trace_instance_dir); |
| 5982 | if (!tr->dir) | 5951 | if (!tr->dir) |
| 5983 | goto out_free_tr; | 5952 | goto out_free_tr; |
| @@ -6132,13 +6101,13 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer) | |||
| 6132 | tr, &tracing_iter_fops); | 6101 | tr, &tracing_iter_fops); |
| 6133 | 6102 | ||
| 6134 | trace_create_file("trace", 0644, d_tracer, | 6103 | trace_create_file("trace", 0644, d_tracer, |
| 6135 | (void *)&tr->trace_cpu, &tracing_fops); | 6104 | tr, &tracing_fops); |
| 6136 | 6105 | ||
| 6137 | trace_create_file("trace_pipe", 0444, d_tracer, | 6106 | trace_create_file("trace_pipe", 0444, d_tracer, |
| 6138 | (void *)&tr->trace_cpu, &tracing_pipe_fops); | 6107 | tr, &tracing_pipe_fops); |
| 6139 | 6108 | ||
| 6140 | trace_create_file("buffer_size_kb", 0644, d_tracer, | 6109 | trace_create_file("buffer_size_kb", 0644, d_tracer, |
| 6141 | (void *)&tr->trace_cpu, &tracing_entries_fops); | 6110 | tr, &tracing_entries_fops); |
| 6142 | 6111 | ||
| 6143 | trace_create_file("buffer_total_size_kb", 0444, d_tracer, | 6112 | trace_create_file("buffer_total_size_kb", 0444, d_tracer, |
| 6144 | tr, &tracing_total_entries_fops); | 6113 | tr, &tracing_total_entries_fops); |
| @@ -6153,11 +6122,11 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer) | |||
| 6153 | &trace_clock_fops); | 6122 | &trace_clock_fops); |
| 6154 | 6123 | ||
| 6155 | trace_create_file("tracing_on", 0644, d_tracer, | 6124 | trace_create_file("tracing_on", 0644, d_tracer, |
| 6156 | tr, &rb_simple_fops); | 6125 | tr, &rb_simple_fops); |
| 6157 | 6126 | ||
| 6158 | #ifdef CONFIG_TRACER_SNAPSHOT | 6127 | #ifdef CONFIG_TRACER_SNAPSHOT |
| 6159 | trace_create_file("snapshot", 0644, d_tracer, | 6128 | trace_create_file("snapshot", 0644, d_tracer, |
| 6160 | (void *)&tr->trace_cpu, &snapshot_fops); | 6129 | tr, &snapshot_fops); |
| 6161 | #endif | 6130 | #endif |
| 6162 | 6131 | ||
| 6163 | for_each_tracing_cpu(cpu) | 6132 | for_each_tracing_cpu(cpu) |
| @@ -6451,10 +6420,6 @@ __init static int tracer_alloc_buffers(void) | |||
| 6451 | 6420 | ||
| 6452 | global_trace.flags = TRACE_ARRAY_FL_GLOBAL; | 6421 | global_trace.flags = TRACE_ARRAY_FL_GLOBAL; |
| 6453 | 6422 | ||
| 6454 | /* Holder for file callbacks */ | ||
| 6455 | global_trace.trace_cpu.cpu = RING_BUFFER_ALL_CPUS; | ||
| 6456 | global_trace.trace_cpu.tr = &global_trace; | ||
| 6457 | |||
| 6458 | INIT_LIST_HEAD(&global_trace.systems); | 6423 | INIT_LIST_HEAD(&global_trace.systems); |
| 6459 | INIT_LIST_HEAD(&global_trace.events); | 6424 | INIT_LIST_HEAD(&global_trace.events); |
| 6460 | list_add(&global_trace.list, &ftrace_trace_arrays); | 6425 | list_add(&global_trace.list, &ftrace_trace_arrays); |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index e7d643b8a907..afaae41b0a02 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
| @@ -130,19 +130,12 @@ enum trace_flag_type { | |||
| 130 | 130 | ||
| 131 | struct trace_array; | 131 | struct trace_array; |
| 132 | 132 | ||
| 133 | struct trace_cpu { | ||
| 134 | struct trace_array *tr; | ||
| 135 | struct dentry *dir; | ||
| 136 | int cpu; | ||
| 137 | }; | ||
| 138 | |||
| 139 | /* | 133 | /* |
| 140 | * The CPU trace array - it consists of thousands of trace entries | 134 | * The CPU trace array - it consists of thousands of trace entries |
| 141 | * plus some other descriptor data: (for example which task started | 135 | * plus some other descriptor data: (for example which task started |
| 142 | * the trace, etc.) | 136 | * the trace, etc.) |
| 143 | */ | 137 | */ |
| 144 | struct trace_array_cpu { | 138 | struct trace_array_cpu { |
| 145 | struct trace_cpu trace_cpu; | ||
| 146 | atomic_t disabled; | 139 | atomic_t disabled; |
| 147 | void *buffer_page; /* ring buffer spare */ | 140 | void *buffer_page; /* ring buffer spare */ |
| 148 | 141 | ||
| @@ -196,7 +189,6 @@ struct trace_array { | |||
| 196 | bool allocated_snapshot; | 189 | bool allocated_snapshot; |
| 197 | #endif | 190 | #endif |
| 198 | int buffer_disabled; | 191 | int buffer_disabled; |
| 199 | struct trace_cpu trace_cpu; /* place holder */ | ||
| 200 | #ifdef CONFIG_FTRACE_SYSCALLS | 192 | #ifdef CONFIG_FTRACE_SYSCALLS |
| 201 | int sys_refcount_enter; | 193 | int sys_refcount_enter; |
| 202 | int sys_refcount_exit; | 194 | int sys_refcount_exit; |
