diff options
author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2014-06-06 00:01:46 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2014-06-06 04:53:40 -0400 |
commit | 23aaa3c18e33fe048671b419781b5e44175efafe (patch) | |
tree | 03a3129a3bf0b04061d2904789a87c668de755c6 | |
parent | 748ec3a20eb44fce19af3cef04f8db8a8e7aead3 (diff) |
tracing: Fix leak of ring buffer data when new instances creation fails
Yoshihiro Yunomae reported that the ring buffer data for a trace
instance does not get properly cleaned up when it fails. He proposed
a patch that manually cleaned the data up and addad a bunch of labels.
The labels are not needed because all trace array is allocated with
a kzalloc which initializes it to 0 and all kfree()s can take a NULL
pointer and will ignore it.
Adding a new helper function free_trace_buffers() that can also take
null buffers to free the buffers that were allocated by
allocate_trace_buffers().
Link: http://lkml.kernel.org/r/20140605223522.32311.31664.stgit@yunodevel
Reported-by: Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | kernel/trace/trace.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index e29edee1542a..26cfff38e2ab 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -6232,6 +6232,25 @@ static int allocate_trace_buffers(struct trace_array *tr, int size) | |||
6232 | return 0; | 6232 | return 0; |
6233 | } | 6233 | } |
6234 | 6234 | ||
6235 | static void free_trace_buffers(struct trace_array *tr) | ||
6236 | { | ||
6237 | if (!tr) | ||
6238 | return; | ||
6239 | |||
6240 | if (tr->trace_buffer.buffer) { | ||
6241 | ring_buffer_free(tr->trace_buffer.buffer); | ||
6242 | tr->trace_buffer.buffer = NULL; | ||
6243 | free_percpu(tr->trace_buffer.data); | ||
6244 | } | ||
6245 | |||
6246 | #ifdef CONFIG_TRACER_MAX_TRACE | ||
6247 | if (tr->max_buffer.buffer) { | ||
6248 | ring_buffer_free(tr->max_buffer.buffer); | ||
6249 | tr->max_buffer.buffer = NULL; | ||
6250 | } | ||
6251 | #endif | ||
6252 | } | ||
6253 | |||
6235 | static int new_instance_create(const char *name) | 6254 | static int new_instance_create(const char *name) |
6236 | { | 6255 | { |
6237 | struct trace_array *tr; | 6256 | struct trace_array *tr; |
@@ -6290,8 +6309,7 @@ static int new_instance_create(const char *name) | |||
6290 | return 0; | 6309 | return 0; |
6291 | 6310 | ||
6292 | out_free_tr: | 6311 | out_free_tr: |
6293 | if (tr->trace_buffer.buffer) | 6312 | free_trace_buffers(tr); |
6294 | ring_buffer_free(tr->trace_buffer.buffer); | ||
6295 | free_cpumask_var(tr->tracing_cpumask); | 6313 | free_cpumask_var(tr->tracing_cpumask); |
6296 | kfree(tr->name); | 6314 | kfree(tr->name); |
6297 | kfree(tr); | 6315 | kfree(tr); |