diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-07-23 11:26:06 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-08-29 12:47:32 -0400 |
commit | e5dd03c411713c066b94e1d448359e5216115c1c (patch) | |
tree | 3d48fdc9a0a333614a5a68ead416780619a61e3b /kernel | |
parent | 6dafb0f13798c998ec344bf910b2d89c51961481 (diff) |
tracing: Change tracing_entries_fops to rely on tracing_get_cpu()
commit 0bc392ee46d0fd8e6b678457ef71f074f19a03c5 upstream.
tracing_open_generic_tc() is racy, the memory inode->i_private
points to can be already freed.
1. Change its last user, tracing_entries_fops, to use
tracing_*_generic_tr() instead.
2. Change debugfs_create_file("buffer_size_kb", data) callers
to pass "data = tr".
3. Change tracing_entries_read() and tracing_entries_write() to
use tracing_get_cpu().
4. Kill the no longer used tracing_open_generic_tc() and
tracing_release_generic_tc().
Link: http://lkml.kernel.org/r/20130723152606.GA23730@redhat.com
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/trace.c | 49 |
1 files changed, 12 insertions, 37 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 801d72b84a2a..83fba3c576e8 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -2975,23 +2975,6 @@ int tracing_open_generic_tr(struct inode *inode, struct file *filp) | |||
2975 | return 0; | 2975 | return 0; |
2976 | } | 2976 | } |
2977 | 2977 | ||
2978 | int tracing_open_generic_tc(struct inode *inode, struct file *filp) | ||
2979 | { | ||
2980 | struct trace_cpu *tc = inode->i_private; | ||
2981 | struct trace_array *tr = tc->tr; | ||
2982 | |||
2983 | if (tracing_disabled) | ||
2984 | return -ENODEV; | ||
2985 | |||
2986 | if (trace_array_get(tr) < 0) | ||
2987 | return -ENODEV; | ||
2988 | |||
2989 | filp->private_data = inode->i_private; | ||
2990 | |||
2991 | return 0; | ||
2992 | |||
2993 | } | ||
2994 | |||
2995 | static int tracing_release(struct inode *inode, struct file *file) | 2978 | static int tracing_release(struct inode *inode, struct file *file) |
2996 | { | 2979 | { |
2997 | struct seq_file *m = file->private_data; | 2980 | struct seq_file *m = file->private_data; |
@@ -3045,15 +3028,6 @@ static int tracing_release_generic_tr(struct inode *inode, struct file *file) | |||
3045 | return 0; | 3028 | return 0; |
3046 | } | 3029 | } |
3047 | 3030 | ||
3048 | static int tracing_release_generic_tc(struct inode *inode, struct file *file) | ||
3049 | { | ||
3050 | struct trace_cpu *tc = inode->i_private; | ||
3051 | struct trace_array *tr = tc->tr; | ||
3052 | |||
3053 | trace_array_put(tr); | ||
3054 | return 0; | ||
3055 | } | ||
3056 | |||
3057 | static int tracing_single_release_tr(struct inode *inode, struct file *file) | 3031 | static int tracing_single_release_tr(struct inode *inode, struct file *file) |
3058 | { | 3032 | { |
3059 | struct trace_array *tr = inode->i_private; | 3033 | struct trace_array *tr = inode->i_private; |
@@ -4374,15 +4348,16 @@ static ssize_t | |||
4374 | tracing_entries_read(struct file *filp, char __user *ubuf, | 4348 | tracing_entries_read(struct file *filp, char __user *ubuf, |
4375 | size_t cnt, loff_t *ppos) | 4349 | size_t cnt, loff_t *ppos) |
4376 | { | 4350 | { |
4377 | struct trace_cpu *tc = filp->private_data; | 4351 | struct inode *inode = file_inode(filp); |
4378 | struct trace_array *tr = tc->tr; | 4352 | struct trace_array *tr = inode->i_private; |
4353 | int cpu = tracing_get_cpu(inode); | ||
4379 | char buf[64]; | 4354 | char buf[64]; |
4380 | int r = 0; | 4355 | int r = 0; |
4381 | ssize_t ret; | 4356 | ssize_t ret; |
4382 | 4357 | ||
4383 | mutex_lock(&trace_types_lock); | 4358 | mutex_lock(&trace_types_lock); |
4384 | 4359 | ||
4385 | if (tc->cpu == RING_BUFFER_ALL_CPUS) { | 4360 | if (cpu == RING_BUFFER_ALL_CPUS) { |
4386 | int cpu, buf_size_same; | 4361 | int cpu, buf_size_same; |
4387 | unsigned long size; | 4362 | unsigned long size; |
4388 | 4363 | ||
@@ -4409,7 +4384,7 @@ tracing_entries_read(struct file *filp, char __user *ubuf, | |||
4409 | } else | 4384 | } else |
4410 | r = sprintf(buf, "X\n"); | 4385 | r = sprintf(buf, "X\n"); |
4411 | } else | 4386 | } else |
4412 | r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->trace_buffer.data, tc->cpu)->entries >> 10); | 4387 | r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->trace_buffer.data, cpu)->entries >> 10); |
4413 | 4388 | ||
4414 | mutex_unlock(&trace_types_lock); | 4389 | mutex_unlock(&trace_types_lock); |
4415 | 4390 | ||
@@ -4421,7 +4396,8 @@ static ssize_t | |||
4421 | tracing_entries_write(struct file *filp, const char __user *ubuf, | 4396 | tracing_entries_write(struct file *filp, const char __user *ubuf, |
4422 | size_t cnt, loff_t *ppos) | 4397 | size_t cnt, loff_t *ppos) |
4423 | { | 4398 | { |
4424 | struct trace_cpu *tc = filp->private_data; | 4399 | struct inode *inode = file_inode(filp); |
4400 | struct trace_array *tr = inode->i_private; | ||
4425 | unsigned long val; | 4401 | unsigned long val; |
4426 | int ret; | 4402 | int ret; |
4427 | 4403 | ||
@@ -4435,8 +4411,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
4435 | 4411 | ||
4436 | /* value is in KB */ | 4412 | /* value is in KB */ |
4437 | val <<= 10; | 4413 | val <<= 10; |
4438 | 4414 | 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) | 4415 | if (ret < 0) |
4441 | return ret; | 4416 | return ret; |
4442 | 4417 | ||
@@ -4884,11 +4859,11 @@ static const struct file_operations tracing_pipe_fops = { | |||
4884 | }; | 4859 | }; |
4885 | 4860 | ||
4886 | static const struct file_operations tracing_entries_fops = { | 4861 | static const struct file_operations tracing_entries_fops = { |
4887 | .open = tracing_open_generic_tc, | 4862 | .open = tracing_open_generic_tr, |
4888 | .read = tracing_entries_read, | 4863 | .read = tracing_entries_read, |
4889 | .write = tracing_entries_write, | 4864 | .write = tracing_entries_write, |
4890 | .llseek = generic_file_llseek, | 4865 | .llseek = generic_file_llseek, |
4891 | .release = tracing_release_generic_tc, | 4866 | .release = tracing_release_generic_tr, |
4892 | }; | 4867 | }; |
4893 | 4868 | ||
4894 | static const struct file_operations tracing_total_entries_fops = { | 4869 | static const struct file_operations tracing_total_entries_fops = { |
@@ -5572,7 +5547,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu) | |||
5572 | tr, cpu, &tracing_stats_fops); | 5547 | tr, cpu, &tracing_stats_fops); |
5573 | 5548 | ||
5574 | trace_create_cpu_file("buffer_size_kb", 0444, d_cpu, | 5549 | trace_create_cpu_file("buffer_size_kb", 0444, d_cpu, |
5575 | &data->trace_cpu, cpu, &tracing_entries_fops); | 5550 | tr, cpu, &tracing_entries_fops); |
5576 | 5551 | ||
5577 | #ifdef CONFIG_TRACER_SNAPSHOT | 5552 | #ifdef CONFIG_TRACER_SNAPSHOT |
5578 | trace_create_cpu_file("snapshot", 0644, d_cpu, | 5553 | trace_create_cpu_file("snapshot", 0644, d_cpu, |
@@ -6148,7 +6123,7 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer) | |||
6148 | tr, &tracing_pipe_fops); | 6123 | tr, &tracing_pipe_fops); |
6149 | 6124 | ||
6150 | trace_create_file("buffer_size_kb", 0644, d_tracer, | 6125 | trace_create_file("buffer_size_kb", 0644, d_tracer, |
6151 | (void *)&tr->trace_cpu, &tracing_entries_fops); | 6126 | tr, &tracing_entries_fops); |
6152 | 6127 | ||
6153 | trace_create_file("buffer_total_size_kb", 0444, d_tracer, | 6128 | trace_create_file("buffer_total_size_kb", 0444, d_tracer, |
6154 | tr, &tracing_total_entries_fops); | 6129 | tr, &tracing_total_entries_fops); |