Skip to content

Commit

Permalink
bonding: remove bond read lock for bond_activebackup_arp_mon()
Browse files Browse the repository at this point in the history
The bond slave list may change when the monitor is running, the slave list is no longer
protected by bond->lock, only protected by rtnl lock(), so we have 3 ways to modify it:
1.add bond_master_upper_dev_link() and bond_upper_dev_unlink() in bond->lock, but it is unsafe
to call call_netdevice_notifiers() in write lock.
2.remove unused bond->lock for monitor function, only use the existing rtnl lock().
3.use rcu_read_lock() to protect it, of course, it will transform bond_for_each_slave to
bond_for_each_slave_rcu() and performance is better, but in slow path, it is ignored.
so I remove the bond->lock and move the rtnl lock to protect the whole monitor function.

Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
dingtianhong authored and David S. Miller committed Oct 27, 2013
1 parent 7f1bb57 commit 80b9d23
Showing 1 changed file with 13 additions and 33 deletions.
46 changes: 13 additions & 33 deletions drivers/net/bonding/bond_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2726,51 +2726,31 @@ void bond_activebackup_arp_mon(struct work_struct *work)
struct bonding *bond = container_of(work, struct bonding,
arp_work.work);
bool should_notify_peers = false;
int delta_in_ticks;

read_lock(&bond->lock);

delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
if (!rtnl_trylock())
goto re_arm;

if (!bond_has_slaves(bond))
if (!bond_has_slaves(bond)) {
rtnl_unlock();
goto re_arm;
}

should_notify_peers = bond_should_notify_peers(bond);

if (bond_ab_arp_inspect(bond)) {
read_unlock(&bond->lock);

/* Race avoidance with bond_close flush of workqueue */
if (!rtnl_trylock()) {
read_lock(&bond->lock);
delta_in_ticks = 1;
should_notify_peers = false;
goto re_arm;
}

read_lock(&bond->lock);

if (bond_ab_arp_inspect(bond))
bond_ab_arp_commit(bond);

read_unlock(&bond->lock);
rtnl_unlock();
read_lock(&bond->lock);
}

bond_ab_arp_probe(bond);

re_arm:
if (bond->params.arp_interval)
queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
if (should_notify_peers)
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev);

read_unlock(&bond->lock);
rtnl_unlock();

if (should_notify_peers) {
if (!rtnl_trylock())
return;
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev);
rtnl_unlock();
}
re_arm:
if (bond->params.arp_interval)
queue_delayed_work(bond->wq, &bond->arp_work,
msecs_to_jiffies(bond->params.arp_interval));
}

/*-------------------------- netdev event handling --------------------------*/
Expand Down

0 comments on commit 80b9d23

Please sign in to comment.