bonding: Acquire correct locks in alb for promisc change
authorJay Vosburgh <fubar@us.ibm.com>
Thu, 18 Oct 2007 00:37:51 +0000 (17:37 -0700)
committerJeff Garzik <jeff@garzik.org>
Wed, 24 Oct 2007 00:32:01 +0000 (20:32 -0400)
Update ALB mode monitor to hold correct locks (RTNL and nothing
else) when calling dev_set_promiscuity.

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>
drivers/net/bonding/bond_alb.c

index 6db5d763f6b612c02685e076b37b0b1d180e2fb0..25b8dbf6cfd73c0193fd12add9da4d4906956926 100644 (file)
@@ -1455,16 +1455,16 @@ void bond_alb_monitor(struct work_struct *work)
 
        /* handle rlb stuff */
        if (bond_info->rlb_enabled) {
-               /* the following code changes the promiscuity of the
-                * the curr_active_slave. It needs to be locked with a
-                * write lock to protect from other code that also
-                * sets the promiscuity.
-                */
-               write_lock_bh(&bond->curr_slave_lock);
-
                if (bond_info->primary_is_promisc &&
                    (++bond_info->rlb_promisc_timeout_counter >= RLB_PROMISC_TIMEOUT)) {
 
+                       /*
+                        * dev_set_promiscuity requires rtnl and
+                        * nothing else.
+                        */
+                       read_unlock(&bond->lock);
+                       rtnl_lock();
+
                        bond_info->rlb_promisc_timeout_counter = 0;
 
                        /* If the primary was set to promiscuous mode
@@ -1473,9 +1473,10 @@ void bond_alb_monitor(struct work_struct *work)
                         */
                        dev_set_promiscuity(bond->curr_active_slave->dev, -1);
                        bond_info->primary_is_promisc = 0;
-               }
 
-               write_unlock_bh(&bond->curr_slave_lock);
+                       rtnl_unlock();
+                       read_lock(&bond->lock);
+               }
 
                if (bond_info->rlb_rebalance) {
                        bond_info->rlb_rebalance = 0;