tracing/filters: move preds into event_filter object
Create a new event_filter object, and move the pred-related members out of the call and subsystem objects and into the filter object - the details of the filter implementation don't need to be exposed in the call and subsystem in any case, and it will also help make the new parser implementation a little cleaner. [ Impact: refactor trace-filter code to prepare for new features ] Signed-off-by: Tom Zanussi <tzanussi@gmail.com> Acked-by: Steven Rostedt <rostedt@goodmis.org> Cc: fweisbec@gmail.com Cc: Li Zefan <lizf@cn.fujitsu.com> LKML-Reference: <1240905887.6416.119.camel@tropicana> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@@ -101,8 +101,8 @@ struct ftrace_event_call {
|
|||||||
int (*show_format)(struct trace_seq *s);
|
int (*show_format)(struct trace_seq *s);
|
||||||
int (*define_fields)(void);
|
int (*define_fields)(void);
|
||||||
struct list_head fields;
|
struct list_head fields;
|
||||||
int n_preds;
|
int filter_active;
|
||||||
struct filter_pred **preds;
|
void *filter;
|
||||||
void *mod;
|
void *mod;
|
||||||
|
|
||||||
#ifdef CONFIG_EVENT_PROFILE
|
#ifdef CONFIG_EVENT_PROFILE
|
||||||
|
@@ -731,12 +731,16 @@ struct ftrace_event_field {
|
|||||||
int size;
|
int size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct event_filter {
|
||||||
|
int n_preds;
|
||||||
|
struct filter_pred **preds;
|
||||||
|
};
|
||||||
|
|
||||||
struct event_subsystem {
|
struct event_subsystem {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
const char *name;
|
const char *name;
|
||||||
struct dentry *entry;
|
struct dentry *entry;
|
||||||
int n_preds;
|
void *filter;
|
||||||
struct filter_pred **preds;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct filter_pred;
|
struct filter_pred;
|
||||||
@@ -774,7 +778,7 @@ filter_check_discard(struct ftrace_event_call *call, void *rec,
|
|||||||
struct ring_buffer *buffer,
|
struct ring_buffer *buffer,
|
||||||
struct ring_buffer_event *event)
|
struct ring_buffer_event *event)
|
||||||
{
|
{
|
||||||
if (unlikely(call->n_preds) && !filter_match_preds(call, rec)) {
|
if (unlikely(call->filter_active) && !filter_match_preds(call, rec)) {
|
||||||
ring_buffer_discard_commit(buffer, event);
|
ring_buffer_discard_commit(buffer, event);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@@ -757,8 +757,7 @@ event_subsystem_dir(const char *name, struct dentry *d_events)
|
|||||||
|
|
||||||
list_add(&system->list, &event_subsystems);
|
list_add(&system->list, &event_subsystems);
|
||||||
|
|
||||||
system->preds = NULL;
|
system->filter = NULL;
|
||||||
system->n_preds = 0;
|
|
||||||
|
|
||||||
entry = debugfs_create_file("filter", 0644, system->entry, system,
|
entry = debugfs_create_file("filter", 0644, system->entry, system,
|
||||||
&ftrace_subsystem_filter_fops);
|
&ftrace_subsystem_filter_fops);
|
||||||
|
@@ -93,11 +93,12 @@ static int filter_pred_none(struct filter_pred *pred, void *event)
|
|||||||
/* return 1 if event matches, 0 otherwise (discard) */
|
/* return 1 if event matches, 0 otherwise (discard) */
|
||||||
int filter_match_preds(struct ftrace_event_call *call, void *rec)
|
int filter_match_preds(struct ftrace_event_call *call, void *rec)
|
||||||
{
|
{
|
||||||
|
struct event_filter *filter = call->filter;
|
||||||
int i, matched, and_failed = 0;
|
int i, matched, and_failed = 0;
|
||||||
struct filter_pred *pred;
|
struct filter_pred *pred;
|
||||||
|
|
||||||
for (i = 0; i < call->n_preds; i++) {
|
for (i = 0; i < filter->n_preds; i++) {
|
||||||
pred = call->preds[i];
|
pred = filter->preds[i];
|
||||||
if (and_failed && !pred->or)
|
if (and_failed && !pred->or)
|
||||||
continue;
|
continue;
|
||||||
matched = pred->fn(pred, rec);
|
matched = pred->fn(pred, rec);
|
||||||
@@ -115,20 +116,20 @@ int filter_match_preds(struct ftrace_event_call *call, void *rec)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(filter_match_preds);
|
EXPORT_SYMBOL_GPL(filter_match_preds);
|
||||||
|
|
||||||
static void __filter_print_preds(struct filter_pred **preds, int n_preds,
|
static void __filter_print_preds(struct event_filter *filter,
|
||||||
struct trace_seq *s)
|
struct trace_seq *s)
|
||||||
{
|
{
|
||||||
char *field_name;
|
|
||||||
struct filter_pred *pred;
|
struct filter_pred *pred;
|
||||||
|
char *field_name;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!n_preds) {
|
if (!filter || !filter->n_preds) {
|
||||||
trace_seq_printf(s, "none\n");
|
trace_seq_printf(s, "none\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < n_preds; i++) {
|
for (i = 0; i < filter->n_preds; i++) {
|
||||||
pred = preds[i];
|
pred = filter->preds[i];
|
||||||
field_name = pred->field_name;
|
field_name = pred->field_name;
|
||||||
if (i)
|
if (i)
|
||||||
trace_seq_printf(s, pred->or ? "|| " : "&& ");
|
trace_seq_printf(s, pred->or ? "|| " : "&& ");
|
||||||
@@ -144,7 +145,7 @@ static void __filter_print_preds(struct filter_pred **preds, int n_preds,
|
|||||||
void filter_print_preds(struct ftrace_event_call *call, struct trace_seq *s)
|
void filter_print_preds(struct ftrace_event_call *call, struct trace_seq *s)
|
||||||
{
|
{
|
||||||
mutex_lock(&filter_mutex);
|
mutex_lock(&filter_mutex);
|
||||||
__filter_print_preds(call->preds, call->n_preds, s);
|
__filter_print_preds(call->filter, s);
|
||||||
mutex_unlock(&filter_mutex);
|
mutex_unlock(&filter_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +153,7 @@ void filter_print_subsystem_preds(struct event_subsystem *system,
|
|||||||
struct trace_seq *s)
|
struct trace_seq *s)
|
||||||
{
|
{
|
||||||
mutex_lock(&filter_mutex);
|
mutex_lock(&filter_mutex);
|
||||||
__filter_print_preds(system->preds, system->n_preds, s);
|
__filter_print_preds(system->filter, s);
|
||||||
mutex_unlock(&filter_mutex);
|
mutex_unlock(&filter_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,12 +201,14 @@ static int filter_set_pred(struct filter_pred *dest,
|
|||||||
|
|
||||||
static void __filter_disable_preds(struct ftrace_event_call *call)
|
static void __filter_disable_preds(struct ftrace_event_call *call)
|
||||||
{
|
{
|
||||||
|
struct event_filter *filter = call->filter;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
call->n_preds = 0;
|
call->filter_active = 0;
|
||||||
|
filter->n_preds = 0;
|
||||||
|
|
||||||
for (i = 0; i < MAX_FILTER_PRED; i++)
|
for (i = 0; i < MAX_FILTER_PRED; i++)
|
||||||
call->preds[i]->fn = filter_pred_none;
|
filter->preds[i]->fn = filter_pred_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter_disable_preds(struct ftrace_event_call *call)
|
void filter_disable_preds(struct ftrace_event_call *call)
|
||||||
@@ -217,32 +220,39 @@ void filter_disable_preds(struct ftrace_event_call *call)
|
|||||||
|
|
||||||
int init_preds(struct ftrace_event_call *call)
|
int init_preds(struct ftrace_event_call *call)
|
||||||
{
|
{
|
||||||
|
struct event_filter *filter;
|
||||||
struct filter_pred *pred;
|
struct filter_pred *pred;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
call->n_preds = 0;
|
filter = call->filter = kzalloc(sizeof(*filter), GFP_KERNEL);
|
||||||
|
if (!call->filter)
|
||||||
call->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), GFP_KERNEL);
|
|
||||||
if (!call->preds)
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
call->filter_active = 0;
|
||||||
|
filter->n_preds = 0;
|
||||||
|
|
||||||
|
filter->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), GFP_KERNEL);
|
||||||
|
if (!filter->preds)
|
||||||
|
goto oom;
|
||||||
|
|
||||||
for (i = 0; i < MAX_FILTER_PRED; i++) {
|
for (i = 0; i < MAX_FILTER_PRED; i++) {
|
||||||
pred = kzalloc(sizeof(*pred), GFP_KERNEL);
|
pred = kzalloc(sizeof(*pred), GFP_KERNEL);
|
||||||
if (!pred)
|
if (!pred)
|
||||||
goto oom;
|
goto oom;
|
||||||
pred->fn = filter_pred_none;
|
pred->fn = filter_pred_none;
|
||||||
call->preds[i] = pred;
|
filter->preds[i] = pred;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
oom:
|
oom:
|
||||||
for (i = 0; i < MAX_FILTER_PRED; i++) {
|
for (i = 0; i < MAX_FILTER_PRED; i++) {
|
||||||
if (call->preds[i])
|
if (filter->preds[i])
|
||||||
filter_free_pred(call->preds[i]);
|
filter_free_pred(filter->preds[i]);
|
||||||
}
|
}
|
||||||
kfree(call->preds);
|
kfree(filter->preds);
|
||||||
call->preds = NULL;
|
kfree(call->filter);
|
||||||
|
call->filter = NULL;
|
||||||
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
@@ -250,15 +260,16 @@ EXPORT_SYMBOL_GPL(init_preds);
|
|||||||
|
|
||||||
static void __filter_free_subsystem_preds(struct event_subsystem *system)
|
static void __filter_free_subsystem_preds(struct event_subsystem *system)
|
||||||
{
|
{
|
||||||
|
struct event_filter *filter = system->filter;
|
||||||
struct ftrace_event_call *call;
|
struct ftrace_event_call *call;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (system->n_preds) {
|
if (filter && filter->n_preds) {
|
||||||
for (i = 0; i < system->n_preds; i++)
|
for (i = 0; i < filter->n_preds; i++)
|
||||||
filter_free_pred(system->preds[i]);
|
filter_free_pred(filter->preds[i]);
|
||||||
kfree(system->preds);
|
kfree(filter->preds);
|
||||||
system->preds = NULL;
|
kfree(filter);
|
||||||
system->n_preds = 0;
|
system->filter = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(call, &ftrace_events, list) {
|
list_for_each_entry(call, &ftrace_events, list) {
|
||||||
@@ -281,21 +292,23 @@ static int filter_add_pred_fn(struct ftrace_event_call *call,
|
|||||||
struct filter_pred *pred,
|
struct filter_pred *pred,
|
||||||
filter_pred_fn_t fn)
|
filter_pred_fn_t fn)
|
||||||
{
|
{
|
||||||
|
struct event_filter *filter = call->filter;
|
||||||
int idx, err;
|
int idx, err;
|
||||||
|
|
||||||
if (call->n_preds && !pred->compound)
|
if (filter->n_preds && !pred->compound)
|
||||||
__filter_disable_preds(call);
|
__filter_disable_preds(call);
|
||||||
|
|
||||||
if (call->n_preds == MAX_FILTER_PRED)
|
if (filter->n_preds == MAX_FILTER_PRED)
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
|
|
||||||
idx = call->n_preds;
|
idx = filter->n_preds;
|
||||||
filter_clear_pred(call->preds[idx]);
|
filter_clear_pred(filter->preds[idx]);
|
||||||
err = filter_set_pred(call->preds[idx], pred, fn);
|
err = filter_set_pred(filter->preds[idx], pred, fn);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
call->n_preds++;
|
filter->n_preds++;
|
||||||
|
call->filter_active = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -366,29 +379,41 @@ int filter_add_pred(struct ftrace_event_call *call, struct filter_pred *pred)
|
|||||||
int filter_add_subsystem_pred(struct event_subsystem *system,
|
int filter_add_subsystem_pred(struct event_subsystem *system,
|
||||||
struct filter_pred *pred)
|
struct filter_pred *pred)
|
||||||
{
|
{
|
||||||
|
struct event_filter *filter = system->filter;
|
||||||
struct ftrace_event_call *call;
|
struct ftrace_event_call *call;
|
||||||
|
|
||||||
mutex_lock(&filter_mutex);
|
mutex_lock(&filter_mutex);
|
||||||
|
|
||||||
if (system->n_preds && !pred->compound)
|
if (filter && filter->n_preds && !pred->compound) {
|
||||||
__filter_free_subsystem_preds(system);
|
__filter_free_subsystem_preds(system);
|
||||||
|
filter = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!system->n_preds) {
|
if (!filter) {
|
||||||
system->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred),
|
system->filter = kzalloc(sizeof(*filter), GFP_KERNEL);
|
||||||
|
if (!system->filter) {
|
||||||
|
mutex_unlock(&filter_mutex);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
filter = system->filter;
|
||||||
|
filter->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!system->preds) {
|
|
||||||
|
if (!filter->preds) {
|
||||||
|
kfree(system->filter);
|
||||||
|
system->filter = NULL;
|
||||||
mutex_unlock(&filter_mutex);
|
mutex_unlock(&filter_mutex);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system->n_preds == MAX_FILTER_PRED) {
|
if (filter->n_preds == MAX_FILTER_PRED) {
|
||||||
mutex_unlock(&filter_mutex);
|
mutex_unlock(&filter_mutex);
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
system->preds[system->n_preds] = pred;
|
filter->preds[filter->n_preds] = pred;
|
||||||
system->n_preds++;
|
filter->n_preds++;
|
||||||
|
|
||||||
list_for_each_entry(call, &ftrace_events, list) {
|
list_for_each_entry(call, &ftrace_events, list) {
|
||||||
int err;
|
int err;
|
||||||
@@ -401,8 +426,8 @@ int filter_add_subsystem_pred(struct event_subsystem *system,
|
|||||||
|
|
||||||
err = __filter_add_pred(call, pred);
|
err = __filter_add_pred(call, pred);
|
||||||
if (err == -ENOMEM) {
|
if (err == -ENOMEM) {
|
||||||
system->preds[system->n_preds] = NULL;
|
filter->preds[filter->n_preds] = NULL;
|
||||||
system->n_preds--;
|
filter->n_preds--;
|
||||||
mutex_unlock(&filter_mutex);
|
mutex_unlock(&filter_mutex);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user