diff options
| author | Li Zefan <lizf@cn.fujitsu.com> | 2009-08-31 04:49:41 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-08-31 04:58:08 -0400 |
| commit | 8e254c1d183f0225ad21f9049641529e56cce4da (patch) | |
| tree | 5b559726a38b60c6bc92b3c8667c676db1038701 /kernel | |
| parent | 73222acf966792c7fda219724af963339be32e62 (diff) | |
tracing/filters: Defer pred allocation
init_preds() allocates about 5392 bytes of memory (on x86_32) for
a TRACE_EVENT. With my config, at system boot total memory occupied
is:
5392 * (642 + 15) == 3459KB
642 == cat available_events | wc -l
15 == number of dirs in events/ftrace
That's quite a lot, so we'd better defer memory allocation util
it's needed, that's when filter is used.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
Cc: Masami Hiramatsu <mhiramat@redhat.com>
LKML-Reference: <4A9B8EA5.6020700@cn.fujitsu.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/trace/trace_events_filter.c | 50 | ||||
| -rw-r--r-- | kernel/trace/trace_export.c | 1 |
2 files changed, 41 insertions, 10 deletions
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 9f03082c81d8..c6b2edfb7fe9 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c | |||
| @@ -309,7 +309,7 @@ void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s) | |||
| 309 | struct event_filter *filter = call->filter; | 309 | struct event_filter *filter = call->filter; |
| 310 | 310 | ||
| 311 | mutex_lock(&event_mutex); | 311 | mutex_lock(&event_mutex); |
| 312 | if (filter->filter_string) | 312 | if (filter && filter->filter_string) |
| 313 | trace_seq_printf(s, "%s\n", filter->filter_string); | 313 | trace_seq_printf(s, "%s\n", filter->filter_string); |
| 314 | else | 314 | else |
| 315 | trace_seq_printf(s, "none\n"); | 315 | trace_seq_printf(s, "none\n"); |
| @@ -322,7 +322,7 @@ void print_subsystem_event_filter(struct event_subsystem *system, | |||
| 322 | struct event_filter *filter = system->filter; | 322 | struct event_filter *filter = system->filter; |
| 323 | 323 | ||
| 324 | mutex_lock(&event_mutex); | 324 | mutex_lock(&event_mutex); |
| 325 | if (filter->filter_string) | 325 | if (filter && filter->filter_string) |
| 326 | trace_seq_printf(s, "%s\n", filter->filter_string); | 326 | trace_seq_printf(s, "%s\n", filter->filter_string); |
| 327 | else | 327 | else |
| 328 | trace_seq_printf(s, "none\n"); | 328 | trace_seq_printf(s, "none\n"); |
| @@ -390,6 +390,9 @@ void destroy_preds(struct ftrace_event_call *call) | |||
| 390 | struct event_filter *filter = call->filter; | 390 | struct event_filter *filter = call->filter; |
| 391 | int i; | 391 | int i; |
| 392 | 392 | ||
| 393 | if (!filter) | ||
| 394 | return; | ||
| 395 | |||
| 393 | for (i = 0; i < MAX_FILTER_PRED; i++) { | 396 | for (i = 0; i < MAX_FILTER_PRED; i++) { |
| 394 | if (filter->preds[i]) | 397 | if (filter->preds[i]) |
| 395 | filter_free_pred(filter->preds[i]); | 398 | filter_free_pred(filter->preds[i]); |
| @@ -400,7 +403,7 @@ void destroy_preds(struct ftrace_event_call *call) | |||
| 400 | call->filter = NULL; | 403 | call->filter = NULL; |
| 401 | } | 404 | } |
| 402 | 405 | ||
| 403 | int init_preds(struct ftrace_event_call *call) | 406 | static int init_preds(struct ftrace_event_call *call) |
| 404 | { | 407 | { |
| 405 | struct event_filter *filter; | 408 | struct event_filter *filter; |
| 406 | struct filter_pred *pred; | 409 | struct filter_pred *pred; |
| @@ -410,7 +413,6 @@ int init_preds(struct ftrace_event_call *call) | |||
| 410 | if (!call->filter) | 413 | if (!call->filter) |
| 411 | return -ENOMEM; | 414 | return -ENOMEM; |
| 412 | 415 | ||
| 413 | call->filter_active = 0; | ||
| 414 | filter->n_preds = 0; | 416 | filter->n_preds = 0; |
| 415 | 417 | ||
| 416 | filter->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), GFP_KERNEL); | 418 | filter->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), GFP_KERNEL); |
| @@ -432,7 +434,28 @@ oom: | |||
| 432 | 434 | ||
| 433 | return -ENOMEM; | 435 | return -ENOMEM; |
| 434 | } | 436 | } |
| 435 | EXPORT_SYMBOL_GPL(init_preds); | 437 | |
| 438 | static int init_subsystem_preds(struct event_subsystem *system) | ||
| 439 | { | ||
| 440 | struct ftrace_event_call *call; | ||
| 441 | int err; | ||
| 442 | |||
| 443 | list_for_each_entry(call, &ftrace_events, list) { | ||
| 444 | if (!call->define_fields) | ||
| 445 | continue; | ||
| 446 | |||
| 447 | if (strcmp(call->system, system->name) != 0) | ||
| 448 | continue; | ||
| 449 | |||
| 450 | if (!call->filter) { | ||
| 451 | err = init_preds(call); | ||
| 452 | if (err) | ||
| 453 | return err; | ||
| 454 | } | ||
| 455 | } | ||
| 456 | |||
| 457 | return 0; | ||
| 458 | } | ||
| 436 | 459 | ||
| 437 | enum { | 460 | enum { |
| 438 | FILTER_DISABLE_ALL, | 461 | FILTER_DISABLE_ALL, |
| @@ -449,6 +472,9 @@ static void filter_free_subsystem_preds(struct event_subsystem *system, | |||
| 449 | if (!call->define_fields) | 472 | if (!call->define_fields) |
| 450 | continue; | 473 | continue; |
| 451 | 474 | ||
| 475 | if (strcmp(call->system, system->name) != 0) | ||
| 476 | continue; | ||
| 477 | |||
| 452 | if (flag == FILTER_INIT_NO_RESET) { | 478 | if (flag == FILTER_INIT_NO_RESET) { |
| 453 | call->filter->no_reset = false; | 479 | call->filter->no_reset = false; |
| 454 | continue; | 480 | continue; |
| @@ -457,10 +483,8 @@ static void filter_free_subsystem_preds(struct event_subsystem *system, | |||
| 457 | if (flag == FILTER_SKIP_NO_RESET && call->filter->no_reset) | 483 | if (flag == FILTER_SKIP_NO_RESET && call->filter->no_reset) |
| 458 | continue; | 484 | continue; |
| 459 | 485 | ||
| 460 | if (!strcmp(call->system, system->name)) { | 486 | filter_disable_preds(call); |
| 461 | filter_disable_preds(call); | 487 | remove_filter_string(call->filter); |
| 462 | remove_filter_string(call->filter); | ||
| 463 | } | ||
| 464 | } | 488 | } |
| 465 | } | 489 | } |
| 466 | 490 | ||
| @@ -1094,6 +1118,10 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string) | |||
| 1094 | 1118 | ||
| 1095 | mutex_lock(&event_mutex); | 1119 | mutex_lock(&event_mutex); |
| 1096 | 1120 | ||
| 1121 | err = init_preds(call); | ||
| 1122 | if (err) | ||
| 1123 | goto out_unlock; | ||
| 1124 | |||
| 1097 | if (!strcmp(strstrip(filter_string), "0")) { | 1125 | if (!strcmp(strstrip(filter_string), "0")) { |
| 1098 | filter_disable_preds(call); | 1126 | filter_disable_preds(call); |
| 1099 | remove_filter_string(call->filter); | 1127 | remove_filter_string(call->filter); |
| @@ -1139,6 +1167,10 @@ int apply_subsystem_event_filter(struct event_subsystem *system, | |||
| 1139 | 1167 | ||
| 1140 | mutex_lock(&event_mutex); | 1168 | mutex_lock(&event_mutex); |
| 1141 | 1169 | ||
| 1170 | err = init_subsystem_preds(system); | ||
| 1171 | if (err) | ||
| 1172 | goto out_unlock; | ||
| 1173 | |||
| 1142 | if (!strcmp(strstrip(filter_string), "0")) { | 1174 | if (!strcmp(strstrip(filter_string), "0")) { |
| 1143 | filter_free_subsystem_preds(system, FILTER_DISABLE_ALL); | 1175 | filter_free_subsystem_preds(system, FILTER_DISABLE_ALL); |
| 1144 | remove_filter_string(system->filter); | 1176 | remove_filter_string(system->filter); |
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c index 029a91f42287..df1bf6e48bb9 100644 --- a/kernel/trace/trace_export.c +++ b/kernel/trace/trace_export.c | |||
| @@ -135,7 +135,6 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ | |||
| 135 | static int ftrace_raw_init_event_##call(void) \ | 135 | static int ftrace_raw_init_event_##call(void) \ |
| 136 | { \ | 136 | { \ |
| 137 | INIT_LIST_HEAD(&event_##call.fields); \ | 137 | INIT_LIST_HEAD(&event_##call.fields); \ |
| 138 | init_preds(&event_##call); \ | ||
| 139 | return 0; \ | 138 | return 0; \ |
| 140 | } \ | 139 | } \ |
| 141 | 140 | ||
