aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c83
1 files changed, 65 insertions, 18 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 10d3f0871b48..9d076a1ffa0b 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -193,6 +193,37 @@ static struct trace_array global_trace;
193 193
194LIST_HEAD(ftrace_trace_arrays); 194LIST_HEAD(ftrace_trace_arrays);
195 195
196int trace_array_get(struct trace_array *this_tr)
197{
198 struct trace_array *tr;
199 int ret = -ENODEV;
200
201 mutex_lock(&trace_types_lock);
202 list_for_each_entry(tr, &ftrace_trace_arrays, list) {
203 if (tr == this_tr) {
204 tr->ref++;
205 ret = 0;
206 break;
207 }
208 }
209 mutex_unlock(&trace_types_lock);
210
211 return ret;
212}
213
214static void __trace_array_put(struct trace_array *this_tr)
215{
216 WARN_ON(!this_tr->ref);
217 this_tr->ref--;
218}
219
220void trace_array_put(struct trace_array *this_tr)
221{
222 mutex_lock(&trace_types_lock);
223 __trace_array_put(this_tr);
224 mutex_unlock(&trace_types_lock);
225}
226
196int filter_current_check_discard(struct ring_buffer *buffer, 227int filter_current_check_discard(struct ring_buffer *buffer,
197 struct ftrace_event_call *call, void *rec, 228 struct ftrace_event_call *call, void *rec,
198 struct ring_buffer_event *event) 229 struct ring_buffer_event *event)
@@ -2768,10 +2799,9 @@ static const struct seq_operations tracer_seq_ops = {
2768}; 2799};
2769 2800
2770static struct trace_iterator * 2801static struct trace_iterator *
2771__tracing_open(struct inode *inode, struct file *file, bool snapshot) 2802__tracing_open(struct trace_array *tr, struct trace_cpu *tc,
2803 struct inode *inode, struct file *file, bool snapshot)
2772{ 2804{
2773 struct trace_cpu *tc = inode->i_private;
2774 struct trace_array *tr = tc->tr;
2775 struct trace_iterator *iter; 2805 struct trace_iterator *iter;
2776 int cpu; 2806 int cpu;
2777 2807
@@ -2850,8 +2880,6 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
2850 tracing_iter_reset(iter, cpu); 2880 tracing_iter_reset(iter, cpu);
2851 } 2881 }
2852 2882
2853 tr->ref++;
2854
2855 mutex_unlock(&trace_types_lock); 2883 mutex_unlock(&trace_types_lock);
2856 2884
2857 return iter; 2885 return iter;
@@ -2881,17 +2909,20 @@ static int tracing_release(struct inode *inode, struct file *file)
2881 struct trace_array *tr; 2909 struct trace_array *tr;
2882 int cpu; 2910 int cpu;
2883 2911
2884 if (!(file->f_mode & FMODE_READ)) 2912 /* Writes do not use seq_file, need to grab tr from inode */
2913 if (!(file->f_mode & FMODE_READ)) {
2914 struct trace_cpu *tc = inode->i_private;
2915
2916 trace_array_put(tc->tr);
2885 return 0; 2917 return 0;
2918 }
2886 2919
2887 iter = m->private; 2920 iter = m->private;
2888 tr = iter->tr; 2921 tr = iter->tr;
2922 trace_array_put(tr);
2889 2923
2890 mutex_lock(&trace_types_lock); 2924 mutex_lock(&trace_types_lock);
2891 2925
2892 WARN_ON(!tr->ref);
2893 tr->ref--;
2894
2895 for_each_tracing_cpu(cpu) { 2926 for_each_tracing_cpu(cpu) {
2896 if (iter->buffer_iter[cpu]) 2927 if (iter->buffer_iter[cpu])
2897 ring_buffer_read_finish(iter->buffer_iter[cpu]); 2928 ring_buffer_read_finish(iter->buffer_iter[cpu]);
@@ -2910,20 +2941,23 @@ static int tracing_release(struct inode *inode, struct file *file)
2910 kfree(iter->trace); 2941 kfree(iter->trace);
2911 kfree(iter->buffer_iter); 2942 kfree(iter->buffer_iter);
2912 seq_release_private(inode, file); 2943 seq_release_private(inode, file);
2944
2913 return 0; 2945 return 0;
2914} 2946}
2915 2947
2916static int tracing_open(struct inode *inode, struct file *file) 2948static int tracing_open(struct inode *inode, struct file *file)
2917{ 2949{
2950 struct trace_cpu *tc = inode->i_private;
2951 struct trace_array *tr = tc->tr;
2918 struct trace_iterator *iter; 2952 struct trace_iterator *iter;
2919 int ret = 0; 2953 int ret = 0;
2920 2954
2955 if (trace_array_get(tr) < 0)
2956 return -ENODEV;
2957
2921 /* If this file was open for write, then erase contents */ 2958 /* If this file was open for write, then erase contents */
2922 if ((file->f_mode & FMODE_WRITE) && 2959 if ((file->f_mode & FMODE_WRITE) &&
2923 (file->f_flags & O_TRUNC)) { 2960 (file->f_flags & O_TRUNC)) {
2924 struct trace_cpu *tc = inode->i_private;
2925 struct trace_array *tr = tc->tr;
2926
2927 if (tc->cpu == RING_BUFFER_ALL_CPUS) 2961 if (tc->cpu == RING_BUFFER_ALL_CPUS)
2928 tracing_reset_online_cpus(&tr->trace_buffer); 2962 tracing_reset_online_cpus(&tr->trace_buffer);
2929 else 2963 else
@@ -2931,12 +2965,16 @@ static int tracing_open(struct inode *inode, struct file *file)
2931 } 2965 }
2932 2966
2933 if (file->f_mode & FMODE_READ) { 2967 if (file->f_mode & FMODE_READ) {
2934 iter = __tracing_open(inode, file, false); 2968 iter = __tracing_open(tr, tc, inode, file, false);
2935 if (IS_ERR(iter)) 2969 if (IS_ERR(iter))
2936 ret = PTR_ERR(iter); 2970 ret = PTR_ERR(iter);
2937 else if (trace_flags & TRACE_ITER_LATENCY_FMT) 2971 else if (trace_flags & TRACE_ITER_LATENCY_FMT)
2938 iter->iter_flags |= TRACE_FILE_LAT_FMT; 2972 iter->iter_flags |= TRACE_FILE_LAT_FMT;
2939 } 2973 }
2974
2975 if (ret < 0)
2976 trace_array_put(tr);
2977
2940 return ret; 2978 return ret;
2941} 2979}
2942 2980
@@ -4512,12 +4550,16 @@ struct ftrace_buffer_info {
4512static int tracing_snapshot_open(struct inode *inode, struct file *file) 4550static int tracing_snapshot_open(struct inode *inode, struct file *file)
4513{ 4551{
4514 struct trace_cpu *tc = inode->i_private; 4552 struct trace_cpu *tc = inode->i_private;
4553 struct trace_array *tr = tc->tr;
4515 struct trace_iterator *iter; 4554 struct trace_iterator *iter;
4516 struct seq_file *m; 4555 struct seq_file *m;
4517 int ret = 0; 4556 int ret = 0;
4518 4557
4558 if (trace_array_get(tr) < 0)
4559 return -ENODEV;
4560
4519 if (file->f_mode & FMODE_READ) { 4561 if (file->f_mode & FMODE_READ) {
4520 iter = __tracing_open(inode, file, true); 4562 iter = __tracing_open(tr, tc, inode, file, true);
4521 if (IS_ERR(iter)) 4563 if (IS_ERR(iter))
4522 ret = PTR_ERR(iter); 4564 ret = PTR_ERR(iter);
4523 } else { 4565 } else {
@@ -4530,13 +4572,16 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file)
4530 kfree(m); 4572 kfree(m);
4531 return -ENOMEM; 4573 return -ENOMEM;
4532 } 4574 }
4533 iter->tr = tc->tr; 4575 iter->tr = tr;
4534 iter->trace_buffer = &tc->tr->max_buffer; 4576 iter->trace_buffer = &tc->tr->max_buffer;
4535 iter->cpu_file = tc->cpu; 4577 iter->cpu_file = tc->cpu;
4536 m->private = iter; 4578 m->private = iter;
4537 file->private_data = m; 4579 file->private_data = m;
4538 } 4580 }
4539 4581
4582 if (ret < 0)
4583 trace_array_put(tr);
4584
4540 return ret; 4585 return ret;
4541} 4586}
4542 4587
@@ -4617,9 +4662,12 @@ out:
4617static int tracing_snapshot_release(struct inode *inode, struct file *file) 4662static int tracing_snapshot_release(struct inode *inode, struct file *file)
4618{ 4663{
4619 struct seq_file *m = file->private_data; 4664 struct seq_file *m = file->private_data;
4665 int ret;
4666
4667 ret = tracing_release(inode, file);
4620 4668
4621 if (file->f_mode & FMODE_READ) 4669 if (file->f_mode & FMODE_READ)
4622 return tracing_release(inode, file); 4670 return ret;
4623 4671
4624 /* If write only, the seq_file is just a stub */ 4672 /* If write only, the seq_file is just a stub */
4625 if (m) 4673 if (m)
@@ -4864,8 +4912,7 @@ static int tracing_buffers_release(struct inode *inode, struct file *file)
4864 4912
4865 mutex_lock(&trace_types_lock); 4913 mutex_lock(&trace_types_lock);
4866 4914
4867 WARN_ON(!iter->tr->ref); 4915 __trace_array_put(iter->tr);
4868 iter->tr->ref--;
4869 4916
4870 if (info->spare) 4917 if (info->spare)
4871 ring_buffer_free_read_page(iter->trace_buffer->buffer, info->spare); 4918 ring_buffer_free_read_page(iter->trace_buffer->buffer, info->spare);