]> Pileus Git - ~andy/linux/commitdiff
tracing: Fix rcu handling of event_trigger_data filter field
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>
Sun, 22 Dec 2013 02:55:17 +0000 (21:55 -0500)
committerSteven Rostedt <rostedt@goodmis.org>
Thu, 2 Jan 2014 21:17:22 +0000 (16:17 -0500)
The filter field of the event_trigger_data structure is protected under
RCU sched locks. It was not annotated as such, and after doing so,
sparse pointed out several locations that required fix ups.

Reported-by: kbuild test robot <fengguang.wu@intel.com>
Tested-by: Tom Zanussi <tom.zanussi@linux.intel.com>
Acked-by: Tom Zanussi <tom.zanussi@linux.intel.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
kernel/trace/trace.h
kernel/trace/trace_events_trigger.c

index 0380cab0af9bbf0ce5777e0c1f02fd0faa7bb953..02b592f2d4b7925af2d25407a4b4d879c816b412 100644 (file)
@@ -1057,7 +1057,7 @@ struct event_trigger_data {
        int                             ref;
        struct event_trigger_ops        *ops;
        struct event_command            *cmd_ops;
-       struct event_filter             *filter;
+       struct event_filter __rcu       *filter;
        char                            *filter_str;
        void                            *private_data;
        struct list_head                list;
index 12ac8a5d4d951f0320cefc2c5e174507d4c949ad..f6dd115b958dd8c029445d0e1071153824a7fbbd 100644 (file)
@@ -67,6 +67,7 @@ event_triggers_call(struct ftrace_event_file *file, void *rec)
 {
        struct event_trigger_data *data;
        enum event_trigger_type tt = ETT_NONE;
+       struct event_filter *filter;
 
        if (list_empty(&file->triggers))
                return tt;
@@ -76,7 +77,8 @@ event_triggers_call(struct ftrace_event_file *file, void *rec)
                        data->ops->func(data);
                        continue;
                }
-               if (data->filter && !filter_match_preds(data->filter, rec))
+               filter = rcu_dereference(data->filter);
+               if (filter && !filter_match_preds(filter, rec))
                        continue;
                if (data->cmd_ops->post_trigger) {
                        tt |= data->cmd_ops->trigger_type;
@@ -703,7 +705,7 @@ static int set_trigger_filter(char *filter_str,
        if (ret)
                goto out;
  assign:
-       tmp = data->filter;
+       tmp = rcu_access_pointer(data->filter);
 
        rcu_assign_pointer(data->filter, filter);
 
@@ -719,7 +721,7 @@ static int set_trigger_filter(char *filter_str,
        if (filter_str) {
                data->filter_str = kstrdup(filter_str, GFP_KERNEL);
                if (!data->filter_str) {
-                       free_event_filter(data->filter);
+                       free_event_filter(rcu_access_pointer(data->filter));
                        data->filter = NULL;
                        ret = -ENOMEM;
                }