bonding: Convert more locks to _bh, acquire rtnl, for new locking
authorJay Vosburgh <fubar@us.ibm.com>
Thu, 18 Oct 2007 00:37:50 +0000 (17:37 -0700)
committerJeff Garzik <jeff@garzik.org>
Wed, 24 Oct 2007 00:32:00 +0000 (20:32 -0400)
Convert more lock acquisitions to _bh flavor to avoid deadlock
with workqueue activity and add acquisition of RTNL in appropriate places.
Affects ALB mode, as well as core bonding functions and sysfs.

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

index f2e2872c9b175caa7b417bb4581f3f85ddd59a9c..6db5d763f6b612c02685e076b37b0b1d180e2fb0 100644 (file)
@@ -128,12 +128,12 @@ static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
 
 static inline void _lock_tx_hashtbl(struct bonding *bond)
 {
-       spin_lock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
+       spin_lock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
 }
 
 static inline void _unlock_tx_hashtbl(struct bonding *bond)
 {
-       spin_unlock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
+       spin_unlock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
 }
 
 /* Caller must hold tx_hashtbl lock */
@@ -305,12 +305,12 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u3
 /*********************** rlb specific functions ***************************/
 static inline void _lock_rx_hashtbl(struct bonding *bond)
 {
-       spin_lock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+       spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
 }
 
 static inline void _unlock_rx_hashtbl(struct bonding *bond)
 {
-       spin_unlock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+       spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
 }
 
 /* when an ARP REPLY is received from a client update its info
@@ -472,13 +472,13 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
 
        _unlock_rx_hashtbl(bond);
 
-       write_lock(&bond->curr_slave_lock);
+       write_lock_bh(&bond->curr_slave_lock);
 
        if (slave != bond->curr_active_slave) {
                rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
        }
 
-       write_unlock(&bond->curr_slave_lock);
+       write_unlock_bh(&bond->curr_slave_lock);
 }
 
 static void rlb_update_client(struct rlb_client_info *client_info)
@@ -1519,11 +1519,11 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
        /* caller must hold the bond lock for write since the mac addresses
         * are compared and may be swapped.
         */
-       write_lock_bh(&bond->lock);
+       read_lock(&bond->lock);
 
        res = alb_handle_addr_collision_on_attach(bond, slave);
 
-       write_unlock_bh(&bond->lock);
+       read_unlock(&bond->lock);
 
        if (res) {
                return res;
index 15c1f7ad222b45b1927d9406f8af44e4d28be860..6909becb10f6a5d46b53bdf3dcf1d80b9a2f6e1f 100644 (file)
@@ -1846,9 +1846,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 */
 void bond_destroy(struct bonding *bond)
 {
+       unregister_netdevice(bond->dev);
        bond_deinit(bond->dev);
        bond_destroy_sysfs_entry(bond);
-       unregister_netdevice(bond->dev);
 }
 
 /*
@@ -2057,9 +2057,9 @@ static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
        info->bond_mode = bond->params.mode;
        info->miimon = bond->params.miimon;
 
-       read_lock_bh(&bond->lock);
+       read_lock(&bond->lock);
        info->num_slaves = bond->slave_cnt;
-       read_unlock_bh(&bond->lock);
+       read_unlock(&bond->lock);
 
        return 0;
 }
@@ -2074,7 +2074,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
                return -ENODEV;
        }
 
-       read_lock_bh(&bond->lock);
+       read_lock(&bond->lock);
 
        bond_for_each_slave(bond, slave, i) {
                if (i == (int)info->slave_id) {
@@ -2083,7 +2083,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
                }
        }
 
-       read_unlock_bh(&bond->lock);
+       read_unlock(&bond->lock);
 
        if (found) {
                strcpy(info->slave_name, slave->dev->name);
@@ -3078,7 +3078,7 @@ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
 
        /* make sure the bond won't be taken away */
        read_lock(&dev_base_lock);
-       read_lock_bh(&bond->lock);
+       read_lock(&bond->lock);
 
        if (*pos == 0) {
                return SEQ_START_TOKEN;
@@ -3112,7 +3112,7 @@ static void bond_info_seq_stop(struct seq_file *seq, void *v)
 {
        struct bonding *bond = seq->private;
 
-       read_unlock_bh(&bond->lock);
+       read_unlock(&bond->lock);
        read_unlock(&dev_base_lock);
 }
 
@@ -3821,13 +3821,13 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
                if (mii->reg_num == 1) {
                        struct bonding *bond = bond_dev->priv;
                        mii->val_out = 0;
-                       read_lock_bh(&bond->lock);
+                       read_lock(&bond->lock);
                        read_lock(&bond->curr_slave_lock);
                        if (netif_carrier_ok(bond->dev)) {
                                mii->val_out = BMSR_LSTATUS;
                        }
                        read_unlock(&bond->curr_slave_lock);
-                       read_unlock_bh(&bond->lock);
+                       read_unlock(&bond->lock);
                }
 
                return 0;
@@ -4473,8 +4473,8 @@ static void bond_free_all(void)
                bond_mc_list_destroy(bond);
                /* Release the bonded slaves */
                bond_release_all(bond_dev);
-               bond_deinit(bond_dev);
                unregister_netdevice(bond_dev);
+               bond_deinit(bond_dev);
        }
 
 #ifdef CONFIG_PROC_FS
index 19d970e0cbb829611b3b2c789031f8101e3a7f38..7a06ade85b02e79279244da770921243f83bfd0f 100644 (file)
@@ -229,7 +229,7 @@ static ssize_t bonding_show_slaves(struct device *d,
        int i, res = 0;
        struct bonding *bond = to_bond(d);
 
-       read_lock_bh(&bond->lock);
+       read_lock(&bond->lock);
        bond_for_each_slave(bond, slave, i) {
                if (res > (PAGE_SIZE - IFNAMSIZ)) {
                        /* not enough space for another interface name */
@@ -240,7 +240,7 @@ static ssize_t bonding_show_slaves(struct device *d,
                }
                res += sprintf(buf + res, "%s ", slave->dev->name);
        }
-       read_unlock_bh(&bond->lock);
+       read_unlock(&bond->lock);
        res += sprintf(buf + res, "\n");
        res++;
        return res;
@@ -282,18 +282,18 @@ static ssize_t bonding_store_slaves(struct device *d,
 
                /* Got a slave name in ifname.  Is it already in the list? */
                found = 0;
-               read_lock_bh(&bond->lock);
+               read_lock(&bond->lock);
                bond_for_each_slave(bond, slave, i)
                        if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
                                printk(KERN_ERR DRV_NAME
                                       ": %s: Interface %s is already enslaved!\n",
                                       bond->dev->name, ifname);
                                ret = -EPERM;
-                               read_unlock_bh(&bond->lock);
+                               read_unlock(&bond->lock);
                                goto out;
                        }
 
-               read_unlock_bh(&bond->lock);
+               read_unlock(&bond->lock);
                printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n",
                       bond->dev->name, ifname);
                dev = dev_get_by_name(&init_net, ifname);
@@ -1133,6 +1133,9 @@ static ssize_t bonding_store_primary(struct device *d,
        }
 out:
        write_unlock_bh(&bond->lock);
+
+       rtnl_unlock();
+
        return count;
 }
 static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary);
@@ -1190,6 +1193,7 @@ static ssize_t bonding_show_active_slave(struct device *d,
        struct bonding *bond = to_bond(d);
        int count;
 
+       rtnl_lock();
 
        read_lock(&bond->curr_slave_lock);
        curr = bond->curr_active_slave;
@@ -1269,6 +1273,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
        }
 out:
        write_unlock_bh(&bond->lock);
+       rtnl_unlock();
+
        return count;
 
 }