diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-07-23 11:26:06 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@rostedt.homelinux.com> | 2013-07-24 11:22:52 -0400 |
commit | 0bc392ee46d0fd8e6b678457ef71f074f19a03c5 (patch) | |
tree | e0f516c200ab6f1eea2f31323c6e4d24000d7e93 /kernel/trace/trace.c | |
parent | 4d3435b8a4c3357695e09c5e7a3bf73a19fca5b0 (diff) |
tracing: Change tracing_entries_fops to rely on tracing_get_cpu()
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>
Diffstat (limited to 'kernel/trace/trace.c')
-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 e29dc8f69aac..68b46851666f 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -2984,23 +2984,6 @@ static int tracing_open_generic_tr(struct inode *inode, struct file *filp) | |||
2984 | return 0; | 2984 | return 0; |
2985 | } | 2985 | } |
2986 | 2986 | ||
2987 | static int tracing_open_generic_tc(struct inode *inode, struct file *filp) | ||
2988 | { | ||
2989 | struct trace_cpu *tc = inode->i_private; | ||
2990 | struct trace_array *tr = tc->tr; | ||
2991 | |||
2992 | if (tracing_disabled) | ||
2993 | return -ENODEV; | ||
2994 | |||
2995 | if (trace_array_get(tr) < 0) | ||
2996 | return -ENODEV; | ||
2997 | |||
2998 | filp->private_data = inode->i_private; | ||
2999 | |||
3000 | return 0; | ||
3001 | |||
3002 | } | ||
3003 | |||
3004 | static int tracing_release(struct inode *inode, struct file *file) | 2987 | static int tracing_release(struct inode *inode, struct file *file) |
3005 | { | 2988 | { |
3006 | struct seq_file *m = file->private_data; | 2989 | struct seq_file *m = file->private_data; |
@@ -3054,15 +3037,6 @@ static int tracing_release_generic_tr(struct inode *inode, struct file *file) | |||
3054 | return 0; | 3037 | return 0; |
3055 | } | 3038 | } |
3056 | 3039 | ||
3057 | static int tracing_release_generic_tc(struct inode *inode, struct file *file) | ||
3058 | { | ||
3059 | struct trace_cpu *tc = inode->i_private; | ||
3060 | struct trace_array *tr = tc->tr; | ||
3061 | |||
3062 | trace_array_put(tr); | ||
3063 | return 0; | ||
3064 | } | ||
3065 | |||
3066 | static int tracing_single_release_tr(struct inode *inode, struct file *file) | 3040 | static int tracing_single_release_tr(struct inode *inode, struct file *file) |
3067 | { | 3041 | { |
3068 | struct trace_array *tr = inode->i_private; | 3042 | struct trace_array *tr = inode->i_private; |
@@ -4382,15 +4356,16 @@ static ssize_t | |||
4382 | tracing_entries_read(struct file *filp, char __user *ubuf, | 4356 | tracing_entries_read(struct file *filp, char __user *ubuf, |
4383 | size_t cnt, loff_t *ppos) | 4357 | size_t cnt, loff_t *ppos) |
4384 | { | 4358 | { |
4385 | struct trace_cpu *tc = filp->private_data; | 4359 | struct inode *inode = file_inode(filp); |
4386 | struct trace_array *tr = tc->tr; | 4360 | struct trace_array *tr = inode->i_private; |
4361 | int cpu = tracing_get_cpu(inode); | ||
4387 | char buf[64]; | 4362 | char buf[64]; |
4388 | int r = 0; | 4363 | int r = 0; |
4389 | ssize_t ret; | 4364 | ssize_t ret; |
4390 | 4365 | ||
4391 | mutex_lock(&trace_types_lock); | 4366 | mutex_lock(&trace_types_lock); |
4392 | 4367 | ||
4393 | if (tc->cpu == RING_BUFFER_ALL_CPUS) { | 4368 | if (cpu == RING_BUFFER_ALL_CPUS) { |
4394 | int cpu, buf_size_same; | 4369 | int cpu, buf_size_same; |
4395 | unsigned long size; | 4370 | unsigned long size; |
4396 | 4371 | ||
@@ -4417,7 +4392,7 @@ tracing_entries_read(struct file *filp, char __user *ubuf, | |||
4417 | } else | 4392 | } else |
4418 | r = sprintf(buf, "X\n"); | 4393 | r = sprintf(buf, "X\n"); |
4419 | } else | 4394 | } else |
4420 | r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->trace_buffer.data, tc->cpu)->entries >> 10); | 4395 | r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->trace_buffer.data, cpu)->entries >> 10); |
4421 | 4396 | ||
4422 | mutex_unlock(&trace_types_lock); | 4397 | mutex_unlock(&trace_types_lock); |
4423 | 4398 | ||
@@ -4429,7 +4404,8 @@ static ssize_t | |||
4429 | tracing_entries_write(struct file *filp, const char __user *ubuf, | 4404 | tracing_entries_write(struct file *filp, const char __user *ubuf, |
4430 | size_t cnt, loff_t *ppos) | 4405 | size_t cnt, loff_t *ppos) |
4431 | { | 4406 | { |
4432 | struct trace_cpu *tc = filp->private_data; | 4407 | struct inode *inode = file_inode(filp); |
4408 | struct trace_array *tr = inode->i_private; | ||
4433 | unsigned long val; | 4409 | unsigned long val; |
4434 | int ret; | 4410 | int ret; |
4435 | 4411 | ||
@@ -4443,8 +4419,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
4443 | 4419 | ||
4444 | /* value is in KB */ | 4420 | /* value is in KB */ |
4445 | val <<= 10; | 4421 | val <<= 10; |
4446 | 4422 | ret = tracing_resize_ring_buffer(tr, val, tracing_get_cpu(inode)); | |
4447 | ret = tracing_resize_ring_buffer(tc->tr, val, tc->cpu); | ||
4448 | if (ret < 0) | 4423 | if (ret < 0) |
4449 | return ret; | 4424 | return ret; |
4450 | 4425 | ||
@@ -4892,11 +4867,11 @@ static const struct file_operations tracing_pipe_fops = { | |||
4892 | }; | 4867 | }; |
4893 | 4868 | ||
4894 | static const struct file_operations tracing_entries_fops = { | 4869 | static const struct file_operations tracing_entries_fops = { |
4895 | .open = tracing_open_generic_tc, | 4870 | .open = tracing_open_generic_tr, |
4896 | .read = tracing_entries_read, | 4871 | .read = tracing_entries_read, |
4897 | .write = tracing_entries_write, | 4872 | .write = tracing_entries_write, |
4898 | .llseek = generic_file_llseek, | 4873 | .llseek = generic_file_llseek, |
4899 | .release = tracing_release_generic_tc, | 4874 | .release = tracing_release_generic_tr, |
4900 | }; | 4875 | }; |
4901 | 4876 | ||
4902 | static const struct file_operations tracing_total_entries_fops = { | 4877 | static const struct file_operations tracing_total_entries_fops = { |
@@ -5580,7 +5555,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu) | |||
5580 | tr, cpu, &tracing_stats_fops); | 5555 | tr, cpu, &tracing_stats_fops); |
5581 | 5556 | ||
5582 | trace_create_cpu_file("buffer_size_kb", 0444, d_cpu, | 5557 | trace_create_cpu_file("buffer_size_kb", 0444, d_cpu, |
5583 | &data->trace_cpu, cpu, &tracing_entries_fops); | 5558 | tr, cpu, &tracing_entries_fops); |
5584 | 5559 | ||
5585 | #ifdef CONFIG_TRACER_SNAPSHOT | 5560 | #ifdef CONFIG_TRACER_SNAPSHOT |
5586 | trace_create_cpu_file("snapshot", 0644, d_cpu, | 5561 | trace_create_cpu_file("snapshot", 0644, d_cpu, |
@@ -6156,7 +6131,7 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer) | |||
6156 | tr, &tracing_pipe_fops); | 6131 | tr, &tracing_pipe_fops); |
6157 | 6132 | ||
6158 | trace_create_file("buffer_size_kb", 0644, d_tracer, | 6133 | trace_create_file("buffer_size_kb", 0644, d_tracer, |
6159 | (void *)&tr->trace_cpu, &tracing_entries_fops); | 6134 | tr, &tracing_entries_fops); |
6160 | 6135 | ||
6161 | trace_create_file("buffer_total_size_kb", 0444, d_tracer, | 6136 | trace_create_file("buffer_total_size_kb", 0444, d_tracer, |
6162 | tr, &tracing_total_entries_fops); | 6137 | tr, &tracing_total_entries_fops); |