diff options
author | Li Zefan <lizf@cn.fujitsu.com> | 2009-05-05 22:33:04 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-05-06 04:38:19 -0400 |
commit | 2df75e415709ad12862028916c772c1f377f6a7c (patch) | |
tree | 3374a78cb06fe096e82d9e4d03ad03d048784967 /kernel | |
parent | 96d17980fabeb757706d2d6db5a28580a6156bfc (diff) |
tracing/events: fix memory leak when unloading module
When unloading a module, memory allocated by init_preds() and
trace_define_field() is not freed.
[ Impact: fix memory leak ]
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Acked-by: Frederic Weisbecker <fweisbec@gmail.com>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <4A00F6E0.3040503@cn.fujitsu.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/trace_events.c | 18 | ||||
-rw-r--r-- | kernel/trace/trace_events_filter.c | 22 |
2 files changed, 33 insertions, 7 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index f789ca540fe1..f251a150e75e 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -60,6 +60,22 @@ err: | |||
60 | } | 60 | } |
61 | EXPORT_SYMBOL_GPL(trace_define_field); | 61 | EXPORT_SYMBOL_GPL(trace_define_field); |
62 | 62 | ||
63 | #ifdef CONFIG_MODULES | ||
64 | |||
65 | static void trace_destroy_fields(struct ftrace_event_call *call) | ||
66 | { | ||
67 | struct ftrace_event_field *field, *next; | ||
68 | |||
69 | list_for_each_entry_safe(field, next, &call->fields, link) { | ||
70 | list_del(&field->link); | ||
71 | kfree(field->type); | ||
72 | kfree(field->name); | ||
73 | kfree(field); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | #endif /* CONFIG_MODULES */ | ||
78 | |||
63 | static void ftrace_clear_events(void) | 79 | static void ftrace_clear_events(void) |
64 | { | 80 | { |
65 | struct ftrace_event_call *call; | 81 | struct ftrace_event_call *call; |
@@ -925,6 +941,8 @@ static void trace_module_remove_events(struct module *mod) | |||
925 | unregister_ftrace_event(call->event); | 941 | unregister_ftrace_event(call->event); |
926 | debugfs_remove_recursive(call->dir); | 942 | debugfs_remove_recursive(call->dir); |
927 | list_del(&call->list); | 943 | list_del(&call->list); |
944 | trace_destroy_fields(call); | ||
945 | destroy_preds(call); | ||
928 | } | 946 | } |
929 | } | 947 | } |
930 | 948 | ||
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index f49486687ee2..ce07b8186710 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c | |||
@@ -346,6 +346,20 @@ static void filter_disable_preds(struct ftrace_event_call *call) | |||
346 | filter->preds[i]->fn = filter_pred_none; | 346 | filter->preds[i]->fn = filter_pred_none; |
347 | } | 347 | } |
348 | 348 | ||
349 | void destroy_preds(struct ftrace_event_call *call) | ||
350 | { | ||
351 | struct event_filter *filter = call->filter; | ||
352 | int i; | ||
353 | |||
354 | for (i = 0; i < MAX_FILTER_PRED; i++) { | ||
355 | if (filter->preds[i]) | ||
356 | filter_free_pred(filter->preds[i]); | ||
357 | } | ||
358 | kfree(filter->preds); | ||
359 | kfree(filter); | ||
360 | call->filter = NULL; | ||
361 | } | ||
362 | |||
349 | int init_preds(struct ftrace_event_call *call) | 363 | int init_preds(struct ftrace_event_call *call) |
350 | { | 364 | { |
351 | struct event_filter *filter; | 365 | struct event_filter *filter; |
@@ -374,13 +388,7 @@ int init_preds(struct ftrace_event_call *call) | |||
374 | return 0; | 388 | return 0; |
375 | 389 | ||
376 | oom: | 390 | oom: |
377 | for (i = 0; i < MAX_FILTER_PRED; i++) { | 391 | destroy_preds(call); |
378 | if (filter->preds[i]) | ||
379 | filter_free_pred(filter->preds[i]); | ||
380 | } | ||
381 | kfree(filter->preds); | ||
382 | kfree(call->filter); | ||
383 | call->filter = NULL; | ||
384 | 392 | ||
385 | return -ENOMEM; | 393 | return -ENOMEM; |
386 | } | 394 | } |