tracing: Miscellaneous fixes for trace_array ref counting
PATCH v2 1/1 tracing: Miscellaneous fixes for trace_array ref counting
Some error paths did not handle ref counting properly, and some trace files need ref counting.
Cc Vaibhav Nagarnaik <[email protected]>
Cc David Sharp <[email protected]>
Cc Alexander Z Lam <[email protected]>
Signed-off-by Alexander Z Lam <[email protected]>
--- kernel/trace/trace.c | 32 ++++++++++++++++++++++---------- kernel/trace/trace_events.c | 21 +++++++++++++++++++-- 2 files changed, 41 insertions(+), 12 deletions(-)
kernel/trace/trace.c +22 -10
@@ -3008,7 +3008,6 @@ static int tracing_release(struct inode *inode, struct file *file) iter = m->private; tr = iter->tr; -trace_array_put (tr);mutex_lock (&trace_types_lock);
@@ -3023,6 +3022,9 @@ static int tracing_release(struct inode *inode, struct file *file)if (!iter->snapshot)/* reenable tracing if it was previously enabled */ tracing_start_tr (tr); + +__trace_array_put (tr); +mutex_unlock (&trace_types_lock);mutex_destroy (&iter->mutex);
@@ -3447,6 +3449,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,static int tracing_trace_options_open (struct inode *inode,struct file *file) {struct trace_array *tr = inode->i_private; +int ret;if (tracing_disabled)return -ENODEV ;
@@ -3454,7 +3457,11 @@ static int tracing_trace_options_open(struct inode *inode, struct file *file)if (trace_array_get (tr) <0 )return -ENODEV ; -return single_open (file, tracing_trace_options_show, inode->i_private); + ret =single_open (file, tracing_trace_options_show, inode->i_private); +if (ret <0 ) +trace_array_put (tr); + +return ret; }static const struct file_operations tracing_iter_fops = {
@@ -3958,7 +3965,7 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp) iter =kzalloc (sizeof (*iter),GFP_KERNEL );if (!iter) { ret = -ENOMEM ; - goto out; + goto fail_iter; }/*
@@ -3968,13 +3975,13 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp) iter->trace =kmalloc (sizeof (*iter->trace),GFP_KERNEL );if (!iter->trace) { ret = -ENOMEM ; - goto fail; + goto fail_trace; } *iter->trace = *tr->current_trace;if (!alloc_cpumask_var (&iter->started,GFP_KERNEL )) { ret = -ENOMEM ; - goto fail; + goto fail_trace; }/* trace pipe does not show start of buffer */
@@ -4001,9 +4008,10 @@ out:mutex_unlock (&trace_types_lock);return ret; -fail: +fail_trace:kfree (iter->trace);kfree (iter); +fail_iter:__trace_array_put (tr);mutex_unlock (&trace_types_lock);return ret;
@@ -4704,21 +4712,24 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file) ret =PTR_ERR (iter); }else {/* Writes still need the seq_file to hold the private data */ + ret = -ENOMEM ; m =kzalloc (sizeof (*m),GFP_KERNEL );if (!m) -return -ENOMEM ; + goto out; iter =kzalloc (sizeof (*iter),GFP_KERNEL );if (!iter) {kfree (m); -return -ENOMEM ; + goto out; } + ret =0 ; + iter->tr = tr; iter->trace_buffer = &tc->tr->max_buffer; iter->cpu_file = tc->cpu; m->private = iter; file->private_data = m; } - +out:if (ret <0 )trace_array_put (tr);
@@ -5328,9 +5339,10 @@ tracing_stats_read(struct file *filp, char __user *ubuf, }static const struct file_operations tracing_stats_fops = { - .open = tracing_open_generic, + .open = tracing_open_generic_tc, .read = tracing_stats_read, .llseek = generic_file_llseek, + .release = tracing_release_generic_tc, };#ifdef CONFIG_DYNAMIC_FTRACE
kernel/trace/trace_events.c +19 -2
@@ -1218,6 +1218,7 @@ show_header(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)static int ftrace_event_avail_open (struct inode *inode,struct file *file);static int ftrace_event_set_open (struct inode *inode,struct file *file); +static int ftrace_event_release (struct inode *inode,struct file *file);static const struct seq_operations show_event_seq_ops = { .start = t_start,
@@ -1245,7 +1246,7 @@ static const struct file_operations ftrace_set_event_fops = { .read = seq_read, .write = ftrace_event_write, .llseek = seq_lseek, - .release = seq_release, + .release = ftrace_event_release, };static const struct file_operations ftrace_enable_fops = {
@@ -1323,6 +1324,15 @@ ftrace_event_open(struct inode *inode, struct file *file,return ret; } +static int ftrace_event_release (struct inode *inode,struct file *file) +{ +struct trace_array *tr = inode->i_private; + +trace_array_put (tr); + +return seq_release (inode, file); +} +static int ftrace_event_avail_open (struct inode *inode,struct file *file) {
@@ -1336,12 +1346,19 @@ ftrace_event_set_open(struct inode *inode, struct file *file) {const struct seq_operations *seq_ops = &show_set_event_seq_ops;struct trace_array *tr = inode->i_private; +int ret; + +if (trace_array_get (tr) <0 ) +return -ENODEV ;if ((file->f_mode &FMODE_WRITE ) && (file->f_flags &O_TRUNC ))ftrace_clear_events (tr); -return ftrace_event_open (inode, file, seq_ops); + ret =ftrace_event_open (inode, file, seq_ops); +if (ret <0 ) +trace_array_put (tr); +return ret; } static struct event_subsystem *
Signature · 1 line
1.8.3
Steven Rostedt
maintainerQuoted 29 lines · Alexander Z Lam
static const struct
file_operationstracing_iter_fops= {kernel/trace/trace.c +3
-3@@ -3958,7 +3965,7 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp) iter =kzalloc (sizeof (*iter),GFP_KERNEL );if (!iter) { ret = -ENOMEM ; - goto out; + goto fail_iter; }/* @@ -3968,13 +3975,13 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp) iter->trace =kmalloc (sizeof (*iter->trace),GFP_KERNEL );if (!iter->trace) { ret = -ENOMEM ; - goto fail; + goto fail_trace; } *iter->trace = *tr->current_trace;if (!alloc_cpumask_var (&iter->started,GFP_KERNEL )) { ret = -ENOMEM ; - goto fail; + goto fail_trace; }/* trace pipe does not show start of buffer */ @@ -4001,9 +4008,10 @@ out:mutex_unlock (&trace_types_lock);
kernel/trace/trace.c out: · line 4017
Quoted 10 lines
kernel/trace/trace.c +2
-1return ret; -fail: +fail_trace:kfree (iter->trace);kfree (iter); +fail_iter:__trace_array_put (tr);mutex_unlock (&trace_types_lock);return ret;
You missed my comment about not adding the extra label. The only change to the code above should have been:
if (!iter) {
ret = -ENOMEM;
+ __trace_array_put(tr);
goto out;
}A one liner.
-- Steve