]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/bridge/br_if.c
bridge: fix RCU races with bridge port
[net-next-2.6.git] / net / bridge / br_if.c
index c03d2c3ff03ed6cb99dc05d7a4cde5033d951190..427f90a8ab7b9e457a074702ecbcd80def55846c 100644 (file)
@@ -61,30 +61,27 @@ static int port_cost(struct net_device *dev)
 }
 
 
-/*
- * Check for port carrier transistions.
- * Called from work queue to allow for calling functions that
- * might sleep (such as speed check), and to debounce.
- */
+/* Check for port carrier transistions. */
 void br_port_carrier_check(struct net_bridge_port *p)
 {
        struct net_device *dev = p->dev;
        struct net_bridge *br = p->br;
 
-       if (netif_carrier_ok(dev))
+       if (netif_running(dev) && netif_carrier_ok(dev))
                p->path_cost = port_cost(dev);
 
-       if (netif_running(br->dev)) {
-               spin_lock_bh(&br->lock);
-               if (netif_carrier_ok(dev)) {
-                       if (p->state == BR_STATE_DISABLED)
-                               br_stp_enable_port(p);
-               } else {
-                       if (p->state != BR_STATE_DISABLED)
-                               br_stp_disable_port(p);
-               }
-               spin_unlock_bh(&br->lock);
+       if (!netif_running(br->dev))
+               return;
+
+       spin_lock_bh(&br->lock);
+       if (netif_running(dev) && netif_carrier_ok(dev)) {
+               if (p->state == BR_STATE_DISABLED)
+                       br_stp_enable_port(p);
+       } else {
+               if (p->state != BR_STATE_DISABLED)
+                       br_stp_disable_port(p);
        }
+       spin_unlock_bh(&br->lock);
 }
 
 static void release_nbp(struct kobject *kobj)
@@ -478,11 +475,8 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
 {
        struct net_bridge_port *p;
 
-       if (!br_port_exists(dev))
-               return -EINVAL;
-
        p = br_port_get(dev);
-       if (p->br != br)
+       if (!p || p->br != br)
                return -EINVAL;
 
        del_nbp(p);