diff options
-rw-r--r-- | drivers/net/bonding/bond_main.c | 70 |
1 files changed, 51 insertions, 19 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 862ed8ece14e..a3577271b1b8 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -2088,27 +2088,25 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in | |||
2088 | 2088 | ||
2089 | /*-------------------------------- Monitoring -------------------------------*/ | 2089 | /*-------------------------------- Monitoring -------------------------------*/ |
2090 | 2090 | ||
2091 | /* this function is called regularly to monitor each slave's link. */ | 2091 | /* |
2092 | void bond_mii_monitor(struct work_struct *work) | 2092 | * if !have_locks, return nonzero if a failover is necessary. if |
2093 | * have_locks, do whatever failover activities are needed. | ||
2094 | * | ||
2095 | * This is to separate the inspection and failover steps for locking | ||
2096 | * purposes; failover requires rtnl, but acquiring it for every | ||
2097 | * inspection is undesirable, so a wrapper first does inspection, and | ||
2098 | * the acquires the necessary locks and calls again to perform | ||
2099 | * failover if needed. Since all locks are dropped, a complete | ||
2100 | * restart is needed between calls. | ||
2101 | */ | ||
2102 | static int __bond_mii_monitor(struct bonding *bond, int have_locks) | ||
2093 | { | 2103 | { |
2094 | struct bonding *bond = container_of(work, struct bonding, | ||
2095 | mii_work.work); | ||
2096 | struct slave *slave, *oldcurrent; | 2104 | struct slave *slave, *oldcurrent; |
2097 | int do_failover = 0; | 2105 | int do_failover = 0; |
2098 | int delta_in_ticks; | ||
2099 | int i; | 2106 | int i; |
2100 | 2107 | ||
2101 | read_lock(&bond->lock); | 2108 | if (bond->slave_cnt == 0) |
2102 | |||
2103 | delta_in_ticks = (bond->params.miimon * HZ) / 1000; | ||
2104 | |||
2105 | if (bond->kill_timers) { | ||
2106 | goto out; | 2109 | goto out; |
2107 | } | ||
2108 | |||
2109 | if (bond->slave_cnt == 0) { | ||
2110 | goto re_arm; | ||
2111 | } | ||
2112 | 2110 | ||
2113 | /* we will try to read the link status of each of our slaves, and | 2111 | /* we will try to read the link status of each of our slaves, and |
2114 | * set their IFF_RUNNING flag appropriately. For each slave not | 2112 | * set their IFF_RUNNING flag appropriately. For each slave not |
@@ -2175,6 +2173,9 @@ void bond_mii_monitor(struct work_struct *work) | |||
2175 | if (link_state != BMSR_LSTATUS) { | 2173 | if (link_state != BMSR_LSTATUS) { |
2176 | /* link stays down */ | 2174 | /* link stays down */ |
2177 | if (slave->delay <= 0) { | 2175 | if (slave->delay <= 0) { |
2176 | if (!have_locks) | ||
2177 | return 1; | ||
2178 | |||
2178 | /* link down for too long time */ | 2179 | /* link down for too long time */ |
2179 | slave->link = BOND_LINK_DOWN; | 2180 | slave->link = BOND_LINK_DOWN; |
2180 | 2181 | ||
@@ -2258,6 +2259,9 @@ void bond_mii_monitor(struct work_struct *work) | |||
2258 | } else { | 2259 | } else { |
2259 | /* link stays up */ | 2260 | /* link stays up */ |
2260 | if (slave->delay == 0) { | 2261 | if (slave->delay == 0) { |
2262 | if (!have_locks) | ||
2263 | return 1; | ||
2264 | |||
2261 | /* now the link has been up for long time enough */ | 2265 | /* now the link has been up for long time enough */ |
2262 | slave->link = BOND_LINK_UP; | 2266 | slave->link = BOND_LINK_UP; |
2263 | slave->jiffies = jiffies; | 2267 | slave->jiffies = jiffies; |
@@ -2331,13 +2335,41 @@ void bond_mii_monitor(struct work_struct *work) | |||
2331 | } else | 2335 | } else |
2332 | bond_set_carrier(bond); | 2336 | bond_set_carrier(bond); |
2333 | 2337 | ||
2334 | re_arm: | ||
2335 | if (bond->params.miimon) | ||
2336 | queue_delayed_work(bond->wq, &bond->mii_work, delta_in_ticks); | ||
2337 | out: | 2338 | out: |
2338 | read_unlock(&bond->lock); | 2339 | return 0; |
2339 | } | 2340 | } |
2340 | 2341 | ||
2342 | /* | ||
2343 | * bond_mii_monitor | ||
2344 | * | ||
2345 | * Really a wrapper that splits the mii monitor into two phases: an | ||
2346 | * inspection, then (if inspection indicates something needs to be | ||
2347 | * done) an acquisition of appropriate locks followed by another pass | ||
2348 | * to implement whatever link state changes are indicated. | ||
2349 | */ | ||
2350 | void bond_mii_monitor(struct work_struct *work) | ||
2351 | { | ||
2352 | struct bonding *bond = container_of(work, struct bonding, | ||
2353 | mii_work.work); | ||
2354 | unsigned long delay; | ||
2355 | |||
2356 | read_lock(&bond->lock); | ||
2357 | if (bond->kill_timers) { | ||
2358 | read_unlock(&bond->lock); | ||
2359 | return; | ||
2360 | } | ||
2361 | if (__bond_mii_monitor(bond, 0)) { | ||
2362 | read_unlock(&bond->lock); | ||
2363 | rtnl_lock(); | ||
2364 | read_lock(&bond->lock); | ||
2365 | __bond_mii_monitor(bond, 1); | ||
2366 | rtnl_unlock(); | ||
2367 | } | ||
2368 | |||
2369 | delay = ((bond->params.miimon * HZ) / 1000) ? : 1; | ||
2370 | read_unlock(&bond->lock); | ||
2371 | queue_delayed_work(bond->wq, &bond->mii_work, delay); | ||
2372 | } | ||
2341 | 2373 | ||
2342 | static __be32 bond_glean_dev_ip(struct net_device *dev) | 2374 | static __be32 bond_glean_dev_ip(struct net_device *dev) |
2343 | { | 2375 | { |