net: pktgen: fix race between pktgen_thread_worker() and kthread_stop()
[pandora-kernel.git] / net / core / fib_rules.c
index 27071ee..6af54f2 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/list.h>
+#include <linux/module.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <net/fib_rules.h>
@@ -442,7 +443,8 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
                if (frh->action && (frh->action != rule->action))
                        continue;
 
-               if (frh->table && (frh_get_table(frh, tb) != rule->table))
+               if (frh_get_table(frh, tb) &&
+                   (frh_get_table(frh, tb) != rule->table))
                        continue;
 
                if (tb[FRA_PRIORITY] &&
@@ -490,7 +492,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 (rtnl_dereference(tmp->ctarget) == rule) {
-                                       rcu_assign_pointer(tmp->ctarget, NULL);
+                                       RCU_INIT_POINTER(tmp->ctarget, NULL);
                                        ops->unresolved_rules++;
                                }
                        }
@@ -548,7 +550,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
        frh->flags = rule->flags;
 
        if (rule->action == FR_ACT_GOTO &&
-           rcu_dereference_raw(rule->ctarget) == NULL)
+           rcu_access_pointer(rule->ctarget) == NULL)
                frh->flags |= FIB_RULE_UNRESOLVED;
 
        if (rule->iifname[0]) {
@@ -716,6 +718,13 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event,
                        attach_rules(&ops->rules_list, dev);
                break;
 
+       case NETDEV_CHANGENAME:
+               list_for_each_entry(ops, &net->rules_ops, list) {
+                       detach_rules(&ops->rules_list, dev);
+                       attach_rules(&ops->rules_list, dev);
+               }
+               break;
+
        case NETDEV_UNREGISTER:
                list_for_each_entry(ops, &net->rules_ops, list)
                        detach_rules(&ops->rules_list, dev);