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 | |
| 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>
| -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 | ||
