aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Vosburgh <fubar@us.ibm.com>2007-10-17 20:37:48 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-23 20:32:00 -0400
commit0b0eef66419e9abe6fd62bc958ab7cd0a18f858e (patch)
tree2b334288d26198e18df867b01c880320d7ba9f5f
parentcf5f9044934658dd3ffc628a60cd37c70f8168b1 (diff)
bonding: Convert miimon to new locking
Convert mii (link state) monitor to acquire correct locks for failover events. In particular, failovers generally require RTNL at a low level (when manipulating device MAC addresses, for example) and no other locks. The high level monitor is responsible for acquiring a known set of locks, RTNL, the bond->lock for read and the slave_lock for write, and the low level failover processing can then release appropriate locks as needed. This patch provides the high level portion. As it is undesirable to acquire RTNL for every monitor pass (which may occur as often as every 10 ms), the miimon has been converted to do conditional locking. A first pass inspects all slaves to determine if any action is required, and if so, a second pass (after acquring RTNL) is done to perform any actions (doing a complete rescan, as the situation may have changed when all locks were released). Signed-off-by: Andy Gospodarek <andy@greyhouse.net> Signed-off-by: Jay Vosburgh <fubar@us.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/net/bonding/bond_main.c70
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/*
2092void 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 */
2102static 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
2334re_arm:
2335 if (bond->params.miimon)
2336 queue_delayed_work(bond->wq, &bond->mii_work, delta_in_ticks);
2337out: 2338out:
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 */
2350void 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
2342static __be32 bond_glean_dev_ip(struct net_device *dev) 2374static __be32 bond_glean_dev_ip(struct net_device *dev)
2343{ 2375{