]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv4/ip_gre.c
[BRIDGE]: fix race on bridge del if
[linux-2.6-omap-h63xx.git] / net / ipv4 / ip_gre.c
index 8848355222241cbd1763330a88183a2b45b34966..896ce3f8f53addd02db7e6beaaa205a7275da262 100644 (file)
@@ -290,7 +290,6 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int
 
        dev_hold(dev);
        ipgre_tunnel_link(nt);
-       /* Do not decrement MOD_USE_COUNT here. */
        return nt;
 
 failed:
@@ -1105,10 +1104,10 @@ static int ipgre_open(struct net_device *dev)
                        return -EADDRNOTAVAIL;
                dev = rt->u.dst.dev;
                ip_rt_put(rt);
-               if (__in_dev_get(dev) == NULL)
+               if (__in_dev_get_rtnl(dev) == NULL)
                        return -EADDRNOTAVAIL;
                t->mlink = dev->ifindex;
-               ip_mc_inc_group(__in_dev_get(dev), t->parms.iph.daddr);
+               ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
        }
        return 0;
 }
@@ -1277,12 +1276,28 @@ err1:
        goto out;
 }
 
-static void ipgre_fini(void)
+static void __exit ipgre_destroy_tunnels(void)
+{
+       int prio;
+
+       for (prio = 0; prio < 4; prio++) {
+               int h;
+               for (h = 0; h < HASH_SIZE; h++) {
+                       struct ip_tunnel *t;
+                       while ((t = tunnels[prio][h]) != NULL)
+                               unregister_netdevice(t->dev);
+               }
+       }
+}
+
+static void __exit ipgre_fini(void)
 {
        if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
                printk(KERN_INFO "ipgre close: can't remove protocol\n");
 
-       unregister_netdev(ipgre_fb_tunnel_dev);
+       rtnl_lock();
+       ipgre_destroy_tunnels();
+       rtnl_unlock();
 }
 
 module_init(ipgre_init);