diff options
author | Li Zefan <lizf@cn.fujitsu.com> | 2009-03-26 22:20:24 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-31 11:27:58 -0400 |
commit | ad5dd5493a55e462796e42e50a49e76df76fdb05 (patch) | |
tree | 3073af1836aaa7ba1d8df4cb6b2f287b31e27d72 /kernel/trace/blktrace.c | |
parent | 17ba97e347bec9bbc47a0877c7a098708982129d (diff) |
blktrace: fix memory leak when freeing struct blk_io_trace
Impact: fix mixed ioctl and ftrace-plugin blktrace use memory leak
When mixing the use of ioctl-based blktrace and ftrace-based blktrace,
we can leak memory in this way:
# btrace /dev/sda > /dev/null &
# echo 0 > /sys/block/sda/sda1/trace/enable
now we leak bt->dropped_file, bt->msg_file, bt->rchan...
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Acked-by: Jens Axboe <jens.axboe@oracle.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace/blktrace.c')
-rw-r--r-- | kernel/trace/blktrace.c | 29 |
1 files changed, 12 insertions, 17 deletions
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 8d6bd12aab10..2f21d7761600 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c | |||
@@ -247,7 +247,7 @@ record_it: | |||
247 | static struct dentry *blk_tree_root; | 247 | static struct dentry *blk_tree_root; |
248 | static DEFINE_MUTEX(blk_tree_mutex); | 248 | static DEFINE_MUTEX(blk_tree_mutex); |
249 | 249 | ||
250 | static void blk_trace_cleanup(struct blk_trace *bt) | 250 | static void blk_trace_free(struct blk_trace *bt) |
251 | { | 251 | { |
252 | debugfs_remove(bt->msg_file); | 252 | debugfs_remove(bt->msg_file); |
253 | debugfs_remove(bt->dropped_file); | 253 | debugfs_remove(bt->dropped_file); |
@@ -255,6 +255,11 @@ static void blk_trace_cleanup(struct blk_trace *bt) | |||
255 | free_percpu(bt->sequence); | 255 | free_percpu(bt->sequence); |
256 | free_percpu(bt->msg_data); | 256 | free_percpu(bt->msg_data); |
257 | kfree(bt); | 257 | kfree(bt); |
258 | } | ||
259 | |||
260 | static void blk_trace_cleanup(struct blk_trace *bt) | ||
261 | { | ||
262 | blk_trace_free(bt); | ||
258 | if (atomic_dec_and_test(&blk_probes_ref)) | 263 | if (atomic_dec_and_test(&blk_probes_ref)) |
259 | blk_unregister_tracepoints(); | 264 | blk_unregister_tracepoints(); |
260 | } | 265 | } |
@@ -410,11 +415,11 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, | |||
410 | if (buts->name[i] == '/') | 415 | if (buts->name[i] == '/') |
411 | buts->name[i] = '_'; | 416 | buts->name[i] = '_'; |
412 | 417 | ||
413 | ret = -ENOMEM; | ||
414 | bt = kzalloc(sizeof(*bt), GFP_KERNEL); | 418 | bt = kzalloc(sizeof(*bt), GFP_KERNEL); |
415 | if (!bt) | 419 | if (!bt) |
416 | goto err; | 420 | return -ENOMEM; |
417 | 421 | ||
422 | ret = -ENOMEM; | ||
418 | bt->sequence = alloc_percpu(unsigned long); | 423 | bt->sequence = alloc_percpu(unsigned long); |
419 | if (!bt->sequence) | 424 | if (!bt->sequence) |
420 | goto err; | 425 | goto err; |
@@ -483,17 +488,7 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, | |||
483 | 488 | ||
484 | return 0; | 489 | return 0; |
485 | err: | 490 | err: |
486 | if (bt) { | 491 | blk_trace_free(bt); |
487 | if (bt->msg_file) | ||
488 | debugfs_remove(bt->msg_file); | ||
489 | if (bt->dropped_file) | ||
490 | debugfs_remove(bt->dropped_file); | ||
491 | free_percpu(bt->sequence); | ||
492 | free_percpu(bt->msg_data); | ||
493 | if (bt->rchan) | ||
494 | relay_close(bt->rchan); | ||
495 | kfree(bt); | ||
496 | } | ||
497 | return ret; | 492 | return ret; |
498 | } | 493 | } |
499 | 494 | ||
@@ -1091,6 +1086,7 @@ static void blk_tracer_print_header(struct seq_file *m) | |||
1091 | 1086 | ||
1092 | static void blk_tracer_start(struct trace_array *tr) | 1087 | static void blk_tracer_start(struct trace_array *tr) |
1093 | { | 1088 | { |
1089 | blk_tracer_enabled = true; | ||
1094 | trace_flags &= ~TRACE_ITER_CONTEXT_INFO; | 1090 | trace_flags &= ~TRACE_ITER_CONTEXT_INFO; |
1095 | } | 1091 | } |
1096 | 1092 | ||
@@ -1098,18 +1094,17 @@ static int blk_tracer_init(struct trace_array *tr) | |||
1098 | { | 1094 | { |
1099 | blk_tr = tr; | 1095 | blk_tr = tr; |
1100 | blk_tracer_start(tr); | 1096 | blk_tracer_start(tr); |
1101 | blk_tracer_enabled = true; | ||
1102 | return 0; | 1097 | return 0; |
1103 | } | 1098 | } |
1104 | 1099 | ||
1105 | static void blk_tracer_stop(struct trace_array *tr) | 1100 | static void blk_tracer_stop(struct trace_array *tr) |
1106 | { | 1101 | { |
1102 | blk_tracer_enabled = false; | ||
1107 | trace_flags |= TRACE_ITER_CONTEXT_INFO; | 1103 | trace_flags |= TRACE_ITER_CONTEXT_INFO; |
1108 | } | 1104 | } |
1109 | 1105 | ||
1110 | static void blk_tracer_reset(struct trace_array *tr) | 1106 | static void blk_tracer_reset(struct trace_array *tr) |
1111 | { | 1107 | { |
1112 | blk_tracer_enabled = false; | ||
1113 | blk_tracer_stop(tr); | 1108 | blk_tracer_stop(tr); |
1114 | } | 1109 | } |
1115 | 1110 | ||
@@ -1250,7 +1245,7 @@ static int blk_trace_remove_queue(struct request_queue *q) | |||
1250 | if (atomic_dec_and_test(&blk_probes_ref)) | 1245 | if (atomic_dec_and_test(&blk_probes_ref)) |
1251 | blk_unregister_tracepoints(); | 1246 | blk_unregister_tracepoints(); |
1252 | 1247 | ||
1253 | kfree(bt); | 1248 | blk_trace_free(bt); |
1254 | return 0; | 1249 | return 0; |
1255 | } | 1250 | } |
1256 | 1251 | ||