|
@@ -815,7 +815,11 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
|
|
|
|
|
|
static bool bond_should_notify_peers(struct bonding *bond)
|
|
|
{
|
|
|
- struct slave *slave = bond->curr_active_slave;
|
|
|
+ struct slave *slave;
|
|
|
+
|
|
|
+ rcu_read_lock();
|
|
|
+ slave = rcu_dereference(bond->curr_active_slave);
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
|
pr_debug("bond_should_notify_peers: bond %s slave %s\n",
|
|
|
bond->dev->name, slave ? slave->dev->name : "NULL");
|
|
@@ -1919,7 +1923,7 @@ static int bond_miimon_inspect(struct bonding *bond)
|
|
|
|
|
|
ignore_updelay = !bond->curr_active_slave ? true : false;
|
|
|
|
|
|
- bond_for_each_slave(bond, slave, iter) {
|
|
|
+ bond_for_each_slave_rcu(bond, slave, iter) {
|
|
|
slave->new_link = BOND_LINK_NOCHANGE;
|
|
|
|
|
|
link_state = bond_check_dev_link(bond, slave->dev, 0);
|
|
@@ -2117,41 +2121,35 @@ void bond_mii_monitor(struct work_struct *work)
|
|
|
bool should_notify_peers = false;
|
|
|
unsigned long delay;
|
|
|
|
|
|
- read_lock(&bond->lock);
|
|
|
-
|
|
|
delay = msecs_to_jiffies(bond->params.miimon);
|
|
|
|
|
|
if (!bond_has_slaves(bond))
|
|
|
goto re_arm;
|
|
|
|
|
|
+ rcu_read_lock();
|
|
|
+
|
|
|
should_notify_peers = bond_should_notify_peers(bond);
|
|
|
|
|
|
if (bond_miimon_inspect(bond)) {
|
|
|
- read_unlock(&bond->lock);
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
|
/* Race avoidance with bond_close cancel of workqueue */
|
|
|
if (!rtnl_trylock()) {
|
|
|
- read_lock(&bond->lock);
|
|
|
delay = 1;
|
|
|
should_notify_peers = false;
|
|
|
goto re_arm;
|
|
|
}
|
|
|
|
|
|
- read_lock(&bond->lock);
|
|
|
-
|
|
|
bond_miimon_commit(bond);
|
|
|
|
|
|
- read_unlock(&bond->lock);
|
|
|
rtnl_unlock(); /* might sleep, hold no other locks */
|
|
|
- read_lock(&bond->lock);
|
|
|
- }
|
|
|
+ } else
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
|
re_arm:
|
|
|
if (bond->params.miimon)
|
|
|
queue_delayed_work(bond->wq, &bond->mii_work, delay);
|
|
|
|
|
|
- read_unlock(&bond->lock);
|
|
|
-
|
|
|
if (should_notify_peers) {
|
|
|
if (!rtnl_trylock())
|
|
|
return;
|