[BRIDGE]: Fix device delete race.
This is a simpler fix for the two races in bridge device removal. The Xen race of delif and notify is managed now by a new deleted flag. No need for barriers or other locking because of rtnl mutex. The del_timer_sync()'s are unnecessary, because br_stp_disable_port delete's the timers, and they will finish running before RCU callback. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5d39a795bf
commit
3f4cfc2d11
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ struct net_bridge_port
|
|||
/* STP */
|
||||
u8 priority;
|
||||
u8 state;
|
||||
u8 deleted;
|
||||
u16 port_no;
|
||||
unsigned char topology_change_ack;
|
||||
unsigned char config_pending;
|
||||
|
|
Loading…
Reference in New Issue
Block a user