fib_rules: __rcu annotates ctarget
Eric Dumazet [Tue, 26 Oct 2010 09:24:55 +0000 (09:24 +0000)]
Adds __rcu annotation to (struct fib_rule)->ctarget

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

include/net/fib_rules.h
net/core/fib_rules.c

index 106f309..075f1e3 100644 (file)
@@ -20,7 +20,7 @@ struct fib_rule {
        u32                     table;
        u8                      action;
        u32                     target;
-       struct fib_rule *       ctarget;
+       struct fib_rule __rcu   *ctarget;
        char                    iifname[IFNAMSIZ];
        char                    oifname[IFNAMSIZ];
        struct rcu_head         rcu;
index 12b43cc..82a4369 100644 (file)
@@ -351,12 +351,12 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 
                list_for_each_entry(r, &ops->rules_list, list) {
                        if (r->pref == rule->target) {
-                               rule->ctarget = r;
+                               RCU_INIT_POINTER(rule->ctarget, r);
                                break;
                        }
                }
 
-               if (rule->ctarget == NULL)
+               if (rcu_dereference_protected(rule->ctarget, 1) == NULL)
                        unresolved = 1;
        } else if (rule->action == FR_ACT_GOTO)
                goto errout_free;
@@ -386,7 +386,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
                list_for_each_entry(r, &ops->rules_list, list) {
                        if (r->action == FR_ACT_GOTO &&
                            r->target == rule->pref) {
-                               BUG_ON(r->ctarget != NULL);
+                               BUG_ON(rtnl_dereference(r->ctarget) != NULL);
                                rcu_assign_pointer(r->ctarget, rule);
                                if (--ops->unresolved_rules == 0)
                                        break;
@@ -487,7 +487,7 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
                 */
                if (ops->nr_goto_rules > 0) {
                        list_for_each_entry(tmp, &ops->rules_list, list) {
-                               if (tmp->ctarget == rule) {
+                               if (rtnl_dereference(tmp->ctarget) == rule) {
                                        rcu_assign_pointer(tmp->ctarget, NULL);
                                        ops->unresolved_rules++;
                                }
@@ -545,7 +545,8 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
        frh->action = rule->action;
        frh->flags = rule->flags;
 
-       if (rule->action == FR_ACT_GOTO && rule->ctarget == NULL)
+       if (rule->action == FR_ACT_GOTO &&
+           rcu_dereference_raw(rule->ctarget) == NULL)
                frh->flags |= FIB_RULE_UNRESOLVED;
 
        if (rule->iifname[0]) {