tracing: Kill the buggy trace_cpu
v2 cover tracing: Kill the buggy trace_cpu
Hello.
This series kills tracing_open_generic_tc/trace_cpu/etc.
trace_array_get(inode->i_private) is mostly fine, we do not dereference this pointer untill trace_array_get() succeeds. But trace_array_get(tc->tr) is wrong by the same reason why tracing_open_generic_file/etc are wrong, see 1/7.
(Steven, I think you are right and we can also remove the
list_for_each_entry() loop from trace_array_get() later, and avoid the (harmless but still) race with rmdir + mkdir. Lets discuss this after we fix the problems with file/call).
Changes:
1/7: Fix the whitespace problems.
Add the comment above tracing_get_cpu() and update the changelog. tracing_get_cpu() is always safe but the code like
cpu = tracing_get_cpu(inode);
if (trace_array_get(tr) == 0)
do_something(tr, cpu);
is racy, it can wrongly use RING_BUFFER_ALL_CPUS. IOW, tracing_get_cpu() should be used only after trace_array_get() or something else which takes trace_types_lock at least once.
5/7: No changes. checkpatch.pl complains, but that
"line over 80 characters" in tracing_entries_read() was not added by this patch and I do not know how can I make checkpatch.pl happy without adding a helper for per_cpu_ptr(tr->trace_buffer.data).
6/7: Incorporated the fix from Steven (thanks!).
Oleg.
kernel/trace/trace.c | 194 +++++++++++++++++++++----------------------------- kernel/trace/trace.h | 8 -- 2 files changed, 80 insertions(+), 122 deletions(-)
PATCH v2 1/7 tracing: Introduce trace_create_cpu_file() and tracing_get_cpu()
Every "file_operations" used by tracing_init_debugfs_percpu is buggy. f_op->open/etc does:
1. struct trace_cpu *tc = inode->i_private; struct trace_array *tr = tc->tr;
2. trace_array_get(tr) or fail;
3. do_something(tc);
But tc (and tr) can be already freed before trace_array_get() is called. And it doesn't matter whether this file is per-cpu or it was created by init_tracer_debugfs(), free_percpu() or kfree() are equally bad.
Note that even 1. is not safe, the freed memory can be unmapped. But even if it was safe trace_array_get() can wrongly succeed if we also race with the next new_instance_create() which can re-allocate the same tr, or tc was overwritten and ->tr points to the valid tr. In this case 3. uses the freed/reused memory.
Add the new trivial helper, trace_create_cpu_file() which simply calls trace_create_file() and encodes "cpu" in "struct inode". Another helper, tracing_get_cpu() will be used to read cpu_nr-or-RING_BUFFER_ALL_CPUS.
The patch abuses ->i_cdev to encode the number, it is never used unless the file is S_ISCHR(). But we could use something else, say, i_bytes or even ->d_fsdata. In any case this hack is hidden inside these 2 helpers, it would be trivial to change them if needed.
This patch only changes tracing_init_debugfs_percpu() to use the new trace_create_cpu_file(), the next patches will change file_operations.
Note: tracing_get_cpu(inode) is always safe but you can't trust the result unless trace_array_get() was called, without trace_types_lock which acts as a barrier it can wrongly return RING_BUFFER_ALL_CPUS.
--- kernel/trace/trace.c | 50 ++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 36 insertions(+), 14 deletions(-)
kernel/trace/trace.c +36 -14
@@ -2843,6 +2843,17 @@ static int s_show(struct seq_file *m, void *v)return 0 ; } +/* +* Should be used after trace_array_get(), trace_types_lock +* ensures that i_cdev was already initialized. +*/ +static inline int tracing_get_cpu (struct inode *inode) +{ +if (inode->i_cdev)/* See trace_create_cpu_file() */ +return (long )inode->i_cdev -1 ; +return RING_BUFFER_ALL_CPUS ; +} +static const struct seq_operations tracer_seq_ops = { .start = s_start, .next = s_next,
@@ -5529,6 +5540,17 @@ static struct dentry *tracing_dentry_percpu(struct trace_array *tr, int cpu)return tr->percpu_dir; } +static struct dentry * +trace_create_cpu_file (const char *name,umode_t mode,struct dentry *parent, +void *data,long cpu,const struct file_operations *fops) +{ +struct dentry *ret =trace_create_file (name, mode, parent, data, fops); + +if (ret)/* See tracing_get_cpu() */ + ret->d_inode->i_cdev = (void *)(cpu +1 ); +return ret; +} +static void tracing_init_debugfs_percpu (struct trace_array *tr,long cpu) {
@@ -5548,28 +5570,28 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu) }/* per cpu trace_pipe */ -trace_create_file ("trace_pipe" ,0444 , d_cpu, - (void *)&data->trace_cpu, &tracing_pipe_fops); +trace_create_cpu_file ("trace_pipe" ,0444 , d_cpu, + &data->trace_cpu, cpu, &tracing_pipe_fops);/* per cpu trace */ -trace_create_file ("trace" ,0644 , d_cpu, - (void *)&data->trace_cpu, &tracing_fops); +trace_create_cpu_file ("trace" ,0644 , d_cpu, + &data->trace_cpu, cpu, &tracing_fops); -trace_create_file ("trace_pipe_raw" ,0444 , d_cpu, - (void *)&data->trace_cpu, &tracing_buffers_fops); +trace_create_cpu_file ("trace_pipe_raw" ,0444 , d_cpu, + &data->trace_cpu, cpu, &tracing_buffers_fops); -trace_create_file ("stats" ,0444 , d_cpu, - (void *)&data->trace_cpu, &tracing_stats_fops); +trace_create_cpu_file ("stats" ,0444 , d_cpu, + &data->trace_cpu, cpu, &tracing_stats_fops); -trace_create_file ("buffer_size_kb" ,0444 , d_cpu, - (void *)&data->trace_cpu, &tracing_entries_fops); +trace_create_cpu_file ("buffer_size_kb" ,0444 , d_cpu, + &data->trace_cpu, cpu, &tracing_entries_fops);#ifdef CONFIG_TRACER_SNAPSHOT -trace_create_file ("snapshot" ,0644 , d_cpu, - (void *)&data->trace_cpu, &snapshot_fops); +trace_create_cpu_file ("snapshot" ,0644 , d_cpu, + &data->trace_cpu, cpu, &snapshot_fops); -trace_create_file ("snapshot_raw" ,0444 , d_cpu, - (void *)&data->trace_cpu, &snapshot_raw_fops); +trace_create_cpu_file ("snapshot_raw" ,0444 , d_cpu, + &data->trace_cpu, cpu, &snapshot_raw_fops);#endif }
Signature · 1 line
1.5.5.1
PATCH v2 2/7 tracing: Change tracing_pipe_fops() to rely on tracing_get_cpu()
In reply to Oleg Nesterovtracing_open_pipe() is racy, the memory inode->i_private points to can be already freed.
Change debugfs_create_file("trace_pipe", data) callers to to pass "data = tr", tracing_open_pipe() can use tracing_get_cpu().
--- kernel/trace/trace.c | 16 +++++++--------- 1 files changed, 7 insertions(+), 9 deletions(-)
kernel/trace/trace.c +7 -9
@@ -3959,8 +3959,7 @@ tracing_max_lat_write(struct file *filp, const char __user *ubuf,static int tracing_open_pipe (struct inode *inode,struct file *filp) { -struct trace_cpu *tc = inode->i_private; -struct trace_array *tr = tc->tr; +struct trace_array *tr = inode->i_private;struct trace_iterator *iter;int ret =0 ;
@@ -4006,9 +4005,9 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)if (trace_clocks[tr->clock_id].in_ns) iter->iter_flags |=TRACE_FILE_TIME_IN_NS ; - iter->cpu_file = tc->cpu; - iter->tr = tc->tr; - iter->trace_buffer = &tc->tr->trace_buffer; + iter->tr = tr; + iter->trace_buffer = &tr->trace_buffer; + iter->cpu_file =tracing_get_cpu (inode);mutex_init (&iter->mutex); filp->private_data = iter;
@@ -4031,8 +4030,7 @@ fail:static int tracing_release_pipe (struct inode *inode,struct file *file) {struct trace_iterator *iter = file->private_data; -struct trace_cpu *tc = inode->i_private; -struct trace_array *tr = tc->tr; +struct trace_array *tr = inode->i_private;mutex_lock (&trace_types_lock);
@@ -5571,7 +5569,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)/* per cpu trace_pipe */ trace_create_cpu_file ("trace_pipe" ,0444 , d_cpu, - &data->trace_cpu, cpu, &tracing_pipe_fops); + tr, cpu, &tracing_pipe_fops);/* per cpu trace */ trace_create_cpu_file("trace", 0644, d_cpu,
@@ -6157,7 +6155,7 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer) (void *)&tr->trace_cpu, &tracing_fops);trace_create_file ("trace_pipe" ,0444 , d_tracer, - (void *)&tr->trace_cpu, &tracing_pipe_fops); + tr, &tracing_pipe_fops);trace_create_file ("buffer_size_kb" ,0644 , d_tracer, (void *)&tr->trace_cpu, &tracing_entries_fops);
Signature · 1 line
1.5.5.1
PATCH v2 3/7 tracing: Change tracing_buffers_fops to rely on tracing_get_cpu()
In reply to Oleg Nesterovtracing_buffers_open() is racy, the memory inode->i_private points to can be already freed.
Change debugfs_create_file("trace_pipe_raw", data) caller to pass "data = tr", tracing_buffers_open() can use tracing_get_cpu().
Change debugfs_create_file("snapshot_raw_fops", data) caller too, this file uses tracing_buffers_open/release.
--- kernel/trace/trace.c | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-)
kernel/trace/trace.c +4 -5
@@ -4949,8 +4949,7 @@ static const struct file_operations snapshot_raw_fops = {static int tracing_buffers_open (struct inode *inode,struct file *filp) { -struct trace_cpu *tc = inode->i_private; -struct trace_array *tr = tc->tr; +struct trace_array *tr = inode->i_private;struct ftrace_buffer_info *info;int ret;
@@ -4969,7 +4968,7 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)mutex_lock (&trace_types_lock); info->iter.tr = tr; - info->iter.cpu_file = tc->cpu; + info->iter.cpu_file =tracing_get_cpu (inode); info->iter.trace = tr->current_trace; info->iter.trace_buffer = &tr->trace_buffer; info->spare =NULL ;
@@ -5576,7 +5575,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu) &data->trace_cpu, cpu, &tracing_fops);trace_create_cpu_file ("trace_pipe_raw" ,0444 , d_cpu, - &data->trace_cpu, cpu, &tracing_buffers_fops); + tr, cpu, &tracing_buffers_fops);trace_create_cpu_file ("stats" ,0444 , d_cpu, &data->trace_cpu, cpu, &tracing_stats_fops);
@@ -5589,7 +5588,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu) &data->trace_cpu, cpu, &snapshot_fops);trace_create_cpu_file ("snapshot_raw" ,0444 , d_cpu, - &data->trace_cpu, cpu, &snapshot_raw_fops); + tr, cpu, &snapshot_raw_fops);#endif }
Signature · 1 line
1.5.5.1
PATCH v2 4/7 tracing: Change tracing_stats_fops to rely on tracing_get_cpu()
In reply to Oleg Nesterovtracing_open_generic_tc() is racy, the memory inode->i_private points to can be already freed.
1. Change one of its users, tracing_stats_fops, to use tracing_*_generic_tr() instead.
2. Change trace_create_cpu_file("stats", data) to pass "data = tr".
3. Change tracing_stats_read() to use tracing_get_cpu().
--- kernel/trace/trace.c | 13 ++++++------- 1 files changed, 6 insertions(+), 7 deletions(-)
kernel/trace/trace.c +6 -7
@@ -2982,7 +2982,6 @@ static int tracing_open_generic_tr(struct inode *inode, struct file *filp) filp->private_data = inode->i_private;return 0 ; - }static int tracing_open_generic_tc (struct inode *inode,struct file *filp)
@@ -5285,14 +5284,14 @@ static ssize_t tracing_stats_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos) { - struct trace_cpu *tc = filp->private_data; -struct trace_array *tr = tc->tr; + struct inode *inode = file_inode(filp); +struct trace_array *tr = inode->i_private;struct trace_buffer *trace_buf = &tr->trace_buffer; +int cpu =tracing_get_cpu (inode);struct trace_seq *s;unsigned long cnt;unsigned long long t;unsigned long usec_rem; -int cpu = tc->cpu; s =kmalloc (sizeof (*s),GFP_KERNEL );if (!s)
@@ -5345,10 +5344,10 @@ tracing_stats_read(struct file *filp, char __user *ubuf, }static const struct file_operations tracing_stats_fops = { - .open = tracing_open_generic_tc, + .open = tracing_open_generic_tr, .read = tracing_stats_read, .llseek = generic_file_llseek, - .release = tracing_release_generic_tc, + .release = tracing_release_generic_tr, };#ifdef CONFIG_DYNAMIC_FTRACE
@@ -5578,7 +5577,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu) tr, cpu, &tracing_buffers_fops);trace_create_cpu_file ("stats" ,0444 , d_cpu, - &data->trace_cpu, cpu, &tracing_stats_fops); + tr, cpu, &tracing_stats_fops);trace_create_cpu_file ("buffer_size_kb" ,0444 , d_cpu, &data->trace_cpu, cpu, &tracing_entries_fops);
Signature · 1 line
1.5.5.1
PATCH v2 5/7 tracing: Change tracing_entries_fops to rely on tracing_get_cpu()
In reply to Oleg Nesterovtracing_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().
--- kernel/trace/trace.c | 49 ++++++++++++------------------------------------- 1 files changed, 12 insertions(+), 37 deletions(-)
kernel/trace/trace.c +12 -37
@@ -2984,23 +2984,6 @@ static int tracing_open_generic_tr(struct inode *inode, struct file *filp)return 0 ; } -static int tracing_open_generic_tc (struct inode *inode,struct file *filp) -{ -struct trace_cpu *tc = inode->i_private; -struct trace_array *tr = tc->tr; - -if (tracing_disabled) -return -ENODEV ; - -if (trace_array_get (tr) <0 ) -return -ENODEV ; - - filp->private_data = inode->i_private; - -return 0 ; - -} -static int tracing_release (struct inode *inode,struct file *file) {struct seq_file *m = file->private_data;
@@ -3054,15 +3037,6 @@ static int tracing_release_generic_tr(struct inode *inode, struct file *file)return 0 ; } -static int tracing_release_generic_tc (struct inode *inode,struct file *file) -{ -struct trace_cpu *tc = inode->i_private; -struct trace_array *tr = tc->tr; - -trace_array_put (tr); -return 0 ; -} -static int tracing_single_release_tr (struct inode *inode,struct file *file) {struct trace_array *tr = inode->i_private;
@@ -4382,15 +4356,16 @@ static ssize_t tracing_entries_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { - struct trace_cpu *tc = filp->private_data; -struct trace_array *tr = tc->tr; + struct inode *inode = file_inode(filp); +struct trace_array *tr = inode->i_private; +int cpu =tracing_get_cpu (inode);char buf[64 ];int r =0 ;ssize_t ret;mutex_lock (&trace_types_lock); -if (tc->cpu ==RING_BUFFER_ALL_CPUS ) { +if (cpu ==RING_BUFFER_ALL_CPUS ) {int cpu, buf_size_same;unsigned long size;
@@ -4417,7 +4392,7 @@ tracing_entries_read(struct file *filp, char __user *ubuf, }else r =sprintf (buf,"X\n" ); }else - r =sprintf (buf,"%lu\n" ,per_cpu_ptr (tr->trace_buffer.data, tc->cpu)->entries >>10 ); + r =sprintf (buf,"%lu\n" ,per_cpu_ptr (tr->trace_buffer.data, cpu)->entries >>10 );mutex_unlock (&trace_types_lock);
@@ -4429,7 +4404,8 @@ static ssize_t tracing_entries_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { - struct trace_cpu *tc = filp->private_data; + struct inode *inode = file_inode(filp); +struct trace_array *tr = inode->i_private;unsigned long val;int ret;
@@ -4443,8 +4419,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,/* value is in KB */ val <<=10 ; - - ret =tracing_resize_ring_buffer (tc->tr, val, tc->cpu); + ret =tracing_resize_ring_buffer (tr, val,tracing_get_cpu (inode));if (ret <0 )return ret;
@@ -4892,11 +4867,11 @@ static const struct file_operations tracing_pipe_fops = { };static const struct file_operations tracing_entries_fops = { - .open = tracing_open_generic_tc, + .open = tracing_open_generic_tr, .read = tracing_entries_read, .write = tracing_entries_write, .llseek = generic_file_llseek, - .release = tracing_release_generic_tc, + .release = tracing_release_generic_tr, };static const struct file_operations tracing_total_entries_fops = {
@@ -5580,7 +5555,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu) tr, cpu, &tracing_stats_fops);trace_create_cpu_file ("buffer_size_kb" ,0444 , d_cpu, - &data->trace_cpu, cpu, &tracing_entries_fops); + tr, cpu, &tracing_entries_fops);#ifdef CONFIG_TRACER_SNAPSHOT trace_create_cpu_file("snapshot", 0644, d_cpu,
@@ -6156,7 +6131,7 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer) tr, &tracing_pipe_fops);trace_create_file ("buffer_size_kb" ,0644 , d_tracer, - (void *)&tr->trace_cpu, &tracing_entries_fops); + tr, &tracing_entries_fops);trace_create_file ("buffer_total_size_kb" ,0444 , d_tracer, tr, &tracing_total_entries_fops);
Signature · 1 line
1.5.5.1
PATCH v2 6/7 tracing: Change tracing_fops/snapshot_fops to rely on tracing_get_cpu()
In reply to Oleg Nesterovtracing_open() and tracing_snapshot_open() are racy, the memory inode->i_private points to can be already freed.
Convert these last users of "inode->i_private == trace_cpu" to use "i_private = trace_array" and rely on tracing_get_cpu().
v2: incorporate the fix from Steven, tracing_release() must not
blindly dereference file->private_data unless we know that the file was opened for reading.
--- kernel/trace/trace.c | 50 ++++++++++++++++++++++---------------------------- 1 files changed, 22 insertions(+), 28 deletions(-)
kernel/trace/trace.c +22 -28
@@ -2862,9 +2862,9 @@ static const struct seq_operations tracer_seq_ops = { };static struct trace_iterator * -__tracing_open (struct trace_array *tr,struct trace_cpu *tc, -struct inode *inode,struct file *file,bool snapshot) +__tracing_open (struct inode *inode,struct file *file,bool snapshot) { +struct trace_array *tr = inode->i_private;struct trace_iterator *iter;int cpu;
@@ -2905,8 +2905,8 @@ __tracing_open(struct trace_array *tr, struct trace_cpu *tc, iter->trace_buffer = &tr->trace_buffer; iter->snapshot = snapshot; iter->pos =-1 ; + iter->cpu_file =tracing_get_cpu (inode);mutex_init (&iter->mutex); - iter->cpu_file = tc->cpu;/* Notify the tracer early; before we stop tracing. */ if (iter->trace && iter->trace->open)
@@ -2986,22 +2986,18 @@ static int tracing_open_generic_tr(struct inode *inode, struct file *filp)static int tracing_release (struct inode *inode,struct file *file) { +struct trace_array *tr = inode->i_private;struct seq_file *m = file->private_data;struct trace_iterator *iter; -struct trace_array *tr;int cpu; -/* Writes do not use seq_file, need to grab tr from inode */ if (!(file->f_mode &FMODE_READ )) { -struct trace_cpu *tc = inode->i_private; - -trace_array_put (tc->tr); +trace_array_put (tr);return 0 ; } +/* Writes do not use seq_file */ iter = m->private; - tr = iter->tr; -mutex_lock (&trace_types_lock);for_each_tracing_cpu (cpu) {
@@ -3048,8 +3044,7 @@ static int tracing_single_release_tr(struct inode *inode, struct file *file)static int tracing_open (struct inode *inode,struct file *file) { -struct trace_cpu *tc = inode->i_private; -struct trace_array *tr = tc->tr; +struct trace_array *tr = inode->i_private;struct trace_iterator *iter;int ret =0 ;
@@ -3057,16 +3052,17 @@ static int tracing_open(struct inode *inode, struct file *file)return -ENODEV ;/* If this file was open for write, then erase contents */ -if ((file->f_mode &FMODE_WRITE ) && - (file->f_flags &O_TRUNC )) { -if (tc->cpu ==RING_BUFFER_ALL_CPUS ) +if ((file->f_mode &FMODE_WRITE ) && (file->f_flags &O_TRUNC )) { +int cpu =tracing_get_cpu (inode); + +if (cpu ==RING_BUFFER_ALL_CPUS )tracing_reset_online_cpus (&tr->trace_buffer);else -tracing_reset (&tr->trace_buffer, tc->cpu); +tracing_reset (&tr->trace_buffer, cpu); }if (file->f_mode &FMODE_READ ) { - iter =__tracing_open (tr, tc, inode, file, false); + iter =__tracing_open (inode, file, false);if (IS_ERR (iter)) ret =PTR_ERR (iter);else if (trace_flags &TRACE_ITER_LATENCY_FMT )
@@ -4680,8 +4676,7 @@ struct ftrace_buffer_info {#ifdef CONFIG_TRACER_SNAPSHOT static int tracing_snapshot_open (struct inode *inode,struct file *file) { -struct trace_cpu *tc = inode->i_private; -struct trace_array *tr = tc->tr; +struct trace_array *tr = inode->i_private;struct trace_iterator *iter;struct seq_file *m;int ret =0 ;
@@ -4690,7 +4685,7 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file)return -ENODEV ;if (file->f_mode &FMODE_READ ) { - iter =__tracing_open (tr, tc, inode, file, true); + iter =__tracing_open (inode, file, true);if (IS_ERR (iter)) ret =PTR_ERR (iter); }else {
@@ -4707,8 +4702,8 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file) ret =0 ; iter->tr = tr; - iter->trace_buffer = &tc->tr->max_buffer; - iter->cpu_file = tc->cpu; + iter->trace_buffer = &tr->max_buffer; + iter->cpu_file =tracing_get_cpu (inode); m->private = iter; file->private_data = m; }
@@ -5525,7 +5520,6 @@ trace_create_cpu_file(const char *name, umode_t mode, struct dentry *parent,static void tracing_init_debugfs_percpu (struct trace_array *tr,long cpu) { -struct trace_array_cpu *data =per_cpu_ptr (tr->trace_buffer.data, cpu);struct dentry *d_percpu =tracing_dentry_percpu (tr, cpu);struct dentry *d_cpu;char cpu_dir[30 ];/* 30 characters should be more than enough */
@@ -5546,7 +5540,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)/* per cpu trace */ trace_create_cpu_file ("trace" ,0644 , d_cpu, - &data->trace_cpu, cpu, &tracing_fops); + tr, cpu, &tracing_fops);trace_create_cpu_file ("trace_pipe_raw" ,0444 , d_cpu, tr, cpu, &tracing_buffers_fops);
@@ -5559,7 +5553,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)#ifdef CONFIG_TRACER_SNAPSHOT trace_create_cpu_file ("snapshot" ,0644 , d_cpu, - &data->trace_cpu, cpu, &snapshot_fops); + tr, cpu, &snapshot_fops);trace_create_cpu_file ("snapshot_raw" ,0444 , d_cpu, tr, cpu, &snapshot_raw_fops);
@@ -6125,7 +6119,7 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer) tr, &tracing_iter_fops);trace_create_file ("trace" ,0644 , d_tracer, - (void *)&tr->trace_cpu, &tracing_fops); + tr, &tracing_fops);trace_create_file ("trace_pipe" ,0444 , d_tracer, tr, &tracing_pipe_fops);
@@ -6146,11 +6140,11 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer) &trace_clock_fops);trace_create_file ("tracing_on" ,0644 , d_tracer, - tr, &rb_simple_fops); + tr, &rb_simple_fops);#ifdef CONFIG_TRACER_SNAPSHOT trace_create_file ("snapshot" ,0644 , d_tracer, - (void *)&tr->trace_cpu, &snapshot_fops); + tr, &snapshot_fops);#endif for_each_tracing_cpu (cpu)
Signature · 1 line
1.5.5.1
PATCH v2 7/7 tracing: Kill trace_cpu struct/members
In reply to Oleg NesterovAfter the previous changes trace_array_cpu->trace_cpu and trace_array->trace_cpu becomes write-only. Remove these members and kill "struct trace_cpu" as well.
As a side effect this also removes memset(per_cpu_memory, 0). It was not needed, alloc_percpu() returns zero-filled memory.
--- kernel/trace/trace.c | 21 --------------------- kernel/trace/trace.h | 8 -------- 2 files changed, 0 insertions(+), 29 deletions(-)
kernel/trace/trace.c +0 -21
@@ -5865,17 +5865,6 @@ struct dentry *trace_instance_dir;static void init_tracer_debugfs (struct trace_array *tr,struct dentry *d_tracer); -static void init_trace_buffers (struct trace_array *tr,struct trace_buffer *buf) -{ -int cpu; - -for_each_tracing_cpu (cpu) { -memset (per_cpu_ptr (buf->data, cpu),0 ,sizeof (struct trace_array_cpu )); -per_cpu_ptr (buf->data, cpu)->trace_cpu.cpu = cpu; -per_cpu_ptr (buf->data, cpu)->trace_cpu.tr = tr; - } -} -static int allocate_trace_buffer (struct trace_array *tr,struct trace_buffer *buf,int size) {
@@ -5893,8 +5882,6 @@ allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int sizereturn -ENOMEM ; } -init_trace_buffers (tr, buf); -/* Allocate the first page for all buffers */ set_buffer_entries (&tr->trace_buffer,ring_buffer_size (tr->trace_buffer.buffer,0 ));
@@ -5961,10 +5948,6 @@ static int new_instance_create(const char *name)if (allocate_trace_buffers (tr, trace_buf_size) <0 ) goto out_free_tr; -/* Holder for file callbacks */ - tr->trace_cpu.cpu =RING_BUFFER_ALL_CPUS ; - tr->trace_cpu.tr = tr; - tr->dir =debugfs_create_dir (name, trace_instance_dir);if (!tr->dir) goto out_free_tr;
@@ -6438,10 +6421,6 @@ __init static int tracer_alloc_buffers(void) global_trace.flags =TRACE_ARRAY_FL_GLOBAL ; -/* Holder for file callbacks */ - global_trace.trace_cpu.cpu =RING_BUFFER_ALL_CPUS ; - global_trace.trace_cpu.tr = &global_trace; -INIT_LIST_HEAD (&global_trace.systems);INIT_LIST_HEAD (&global_trace.events);list_add (&global_trace.list, &ftrace_trace_arrays);
kernel/trace/trace.h +0 -8
@@ -130,19 +130,12 @@ enum trace_flag_type {struct trace_array ; -struct trace_cpu { -struct trace_array *tr; -struct dentry *dir; -int cpu; -}; -/* * The CPU trace array - it consists of thousands of trace entries * plus some other descriptor data: (for example which task started * the trace, etc.) */ struct trace_array_cpu { -struct trace_cpu trace_cpu;atomic_t disabled;void *buffer_page;/* ring buffer spare */
@@ -196,7 +189,6 @@ struct trace_array {bool allocated_snapshot;#endif int buffer_disabled; -struct trace_cpu trace_cpu;/* place holder */ #ifdef CONFIG_FTRACE_SYSCALLS int sys_refcount_enter;int sys_refcount_exit;
Signature · 1 line
1.5.5.1
Steven Rostedt
maintainerQuoted 5 lines · Oleg Nesterov
5/7: No changes. checkpatch.pl complains, but that
"line over 80 characters" intracing_entries_read()was not added by this patch and I do not know how can I make checkpatch.pl happy without adding a helper forper_cpu_ptr(tr->trace_buffer.data).
I take those as guidelines not rules. Especially if the fix to 80 characters is uglier than the original.
-- Steve