diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2006-02-09 04:29:00 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2006-02-09 04:29:00 -0500 |
commit | 9caafa6c8686e319cf4d5f3757b3972c6c522b7c (patch) | |
tree | b38979b835b5d22e681b175d0b98a3c7560d9c59 /net/bridge/br_if.c | |
parent | 51e9f2ff83df6b1c81c5c44f4486c68ed87aa20e (diff) | |
parent | cac0e8e8bb2e7a086643bdd00c41d900a79bb4fa (diff) | |
download | kernel-crypto-9caafa6c8686e319cf4d5f3757b3972c6c522b7c.tar.gz kernel-crypto-9caafa6c8686e319cf4d5f3757b3972c6c522b7c.tar.xz kernel-crypto-9caafa6c8686e319cf4d5f3757b3972c6c522b7c.zip |
Merge branch 'upstream-fixes'
Diffstat (limited to 'net/bridge/br_if.c')
-rw-r--r-- | net/bridge/br_if.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index ba442883e87..da687c8dc6f 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -104,6 +104,7 @@ static void destroy_nbp(struct net_bridge_port *p) { struct net_device *dev = p->dev; + dev->br_port = NULL; p->br = NULL; p->dev = NULL; dev_put(dev); @@ -118,13 +119,24 @@ static void destroy_nbp_rcu(struct rcu_head *head) destroy_nbp(p); } -/* called with RTNL */ +/* Delete port(interface) from bridge is done in two steps. + * via RCU. First step, marks device as down. That deletes + * all the timers and stops new packets from flowing through. + * + * Final cleanup doesn't occur until after all CPU's finished + * processing packets. + * + * Protected from multiple admin operations by RTNL mutex + */ static void del_nbp(struct net_bridge_port *p) { struct net_bridge *br = p->br; struct net_device *dev = p->dev; - dev->br_port = NULL; + /* Race between RTNL notify and RCU callback */ + if (p->deleted) + return; + dev_set_promiscuity(dev, -1); cancel_delayed_work(&p->carrier_check); @@ -132,16 +144,13 @@ static void del_nbp(struct net_bridge_port *p) spin_lock_bh(&br->lock); br_stp_disable_port(p); + p->deleted = 1; spin_unlock_bh(&br->lock); br_fdb_delete_by_port(br, p); list_del_rcu(&p->list); - del_timer_sync(&p->message_age_timer); - del_timer_sync(&p->forward_delay_timer); - del_timer_sync(&p->hold_timer); - call_rcu(&p->rcu, destroy_nbp_rcu); } |