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>
This commit is contained in:
parent
73222acf96
commit
8e254c1d18
|
@ -133,7 +133,6 @@ struct ftrace_event_call {
|
|||
#define MAX_FILTER_PRED 32
|
||||
#define MAX_FILTER_STR_VAL 128
|
||||
|
||||
extern int init_preds(struct ftrace_event_call *call);
|
||||
extern void destroy_preds(struct ftrace_event_call *call);
|
||||
extern int filter_match_preds(struct ftrace_event_call *call, void *rec);
|
||||
extern int filter_current_check_discard(struct ftrace_event_call *call,
|
||||
|
|
|
@ -177,7 +177,6 @@ static void prof_sysexit_disable_##sname(struct ftrace_event_call *event_call) \
|
|||
event_enter_##sname.id = id; \
|
||||
set_syscall_enter_id(num, id); \
|
||||
INIT_LIST_HEAD(&event_enter_##sname.fields); \
|
||||
init_preds(&event_enter_##sname); \
|
||||
return 0; \
|
||||
} \
|
||||
TRACE_SYS_ENTER_PROFILE(sname); \
|
||||
|
@ -214,7 +213,6 @@ static void prof_sysexit_disable_##sname(struct ftrace_event_call *event_call) \
|
|||
event_exit_##sname.id = id; \
|
||||
set_syscall_exit_id(num, id); \
|
||||
INIT_LIST_HEAD(&event_exit_##sname.fields); \
|
||||
init_preds(&event_exit_##sname); \
|
||||
return 0; \
|
||||
} \
|
||||
TRACE_SYS_EXIT_PROFILE(sname); \
|
||||
|
|
|
@ -622,7 +622,6 @@ static int ftrace_raw_init_event_##call(void) \
|
|||
return -ENODEV; \
|
||||
event_##call.id = id; \
|
||||
INIT_LIST_HEAD(&event_##call.fields); \
|
||||
init_preds(&event_##call); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
|
|
|
@ -309,7 +309,7 @@ void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s)
|
|||
struct event_filter *filter = call->filter;
|
||||
|
||||
mutex_lock(&event_mutex);
|
||||
if (filter->filter_string)
|
||||
if (filter && filter->filter_string)
|
||||
trace_seq_printf(s, "%s\n", filter->filter_string);
|
||||
else
|
||||
trace_seq_printf(s, "none\n");
|
||||
|
@ -322,7 +322,7 @@ void print_subsystem_event_filter(struct event_subsystem *system,
|
|||
struct event_filter *filter = system->filter;
|
||||
|
||||
mutex_lock(&event_mutex);
|
||||
if (filter->filter_string)
|
||||
if (filter && filter->filter_string)
|
||||
trace_seq_printf(s, "%s\n", filter->filter_string);
|
||||
else
|
||||
trace_seq_printf(s, "none\n");
|
||||
|
@ -390,6 +390,9 @@ void destroy_preds(struct ftrace_event_call *call)
|
|||
struct event_filter *filter = call->filter;
|
||||
int i;
|
||||
|
||||
if (!filter)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAX_FILTER_PRED; i++) {
|
||||
if (filter->preds[i])
|
||||
filter_free_pred(filter->preds[i]);
|
||||
|
@ -400,7 +403,7 @@ void destroy_preds(struct ftrace_event_call *call)
|
|||
call->filter = NULL;
|
||||
}
|
||||
|
||||
int init_preds(struct ftrace_event_call *call)
|
||||
static int init_preds(struct ftrace_event_call *call)
|
||||
{
|
||||
struct event_filter *filter;
|
||||
struct filter_pred *pred;
|
||||
|
@ -410,7 +413,6 @@ int init_preds(struct ftrace_event_call *call)
|
|||
if (!call->filter)
|
||||
return -ENOMEM;
|
||||
|
||||
call->filter_active = 0;
|
||||
filter->n_preds = 0;
|
||||
|
||||
filter->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), GFP_KERNEL);
|
||||
|
@ -432,7 +434,28 @@ oom:
|
|||
|
||||
return -ENOMEM;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(init_preds);
|
||||
|
||||
static int init_subsystem_preds(struct event_subsystem *system)
|
||||
{
|
||||
struct ftrace_event_call *call;
|
||||
int err;
|
||||
|
||||
list_for_each_entry(call, &ftrace_events, list) {
|
||||
if (!call->define_fields)
|
||||
continue;
|
||||
|
||||
if (strcmp(call->system, system->name) != 0)
|
||||
continue;
|
||||
|
||||
if (!call->filter) {
|
||||
err = init_preds(call);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum {
|
||||
FILTER_DISABLE_ALL,
|
||||
|
@ -449,6 +472,9 @@ static void filter_free_subsystem_preds(struct event_subsystem *system,
|
|||
if (!call->define_fields)
|
||||
continue;
|
||||
|
||||
if (strcmp(call->system, system->name) != 0)
|
||||
continue;
|
||||
|
||||
if (flag == FILTER_INIT_NO_RESET) {
|
||||
call->filter->no_reset = false;
|
||||
continue;
|
||||
|
@ -457,11 +483,9 @@ static void filter_free_subsystem_preds(struct event_subsystem *system,
|
|||
if (flag == FILTER_SKIP_NO_RESET && call->filter->no_reset)
|
||||
continue;
|
||||
|
||||
if (!strcmp(call->system, system->name)) {
|
||||
filter_disable_preds(call);
|
||||
remove_filter_string(call->filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int filter_add_pred_fn(struct filter_parse_state *ps,
|
||||
|
@ -1094,6 +1118,10 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
|
|||
|
||||
mutex_lock(&event_mutex);
|
||||
|
||||
err = init_preds(call);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
|
||||
if (!strcmp(strstrip(filter_string), "0")) {
|
||||
filter_disable_preds(call);
|
||||
remove_filter_string(call->filter);
|
||||
|
@ -1139,6 +1167,10 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
|
|||
|
||||
mutex_lock(&event_mutex);
|
||||
|
||||
err = init_subsystem_preds(system);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
|
||||
if (!strcmp(strstrip(filter_string), "0")) {
|
||||
filter_free_subsystem_preds(system, FILTER_DISABLE_ALL);
|
||||
remove_filter_string(system->filter);
|
||||
|
|
|
@ -135,7 +135,6 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
|
|||
static int ftrace_raw_init_event_##call(void) \
|
||||
{ \
|
||||
INIT_LIST_HEAD(&event_##call.fields); \
|
||||
init_preds(&event_##call); \
|
||||
return 0; \
|
||||
} \
|
||||
|
||||
|
|
Loading…
Reference in New Issue