Commit 6603a6f2 authored by Jay Vosburgh's avatar Jay Vosburgh Committed by Jeff Garzik

bonding: Convert more locks to _bh, acquire rtnl, for new locking

	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: default avatarAndy Gospodarek <andy@greyhouse.net>
Signed-off-by: default avatarJay Vosburgh <fubar@us.ibm.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 059fe7a5
...@@ -128,12 +128,12 @@ static inline u8 _simple_hash(const u8 *hash_start, int hash_size) ...@@ -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) 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) 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 */ /* Caller must hold tx_hashtbl lock */
...@@ -305,12 +305,12 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u3 ...@@ -305,12 +305,12 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u3
/*********************** rlb specific functions ***************************/ /*********************** rlb specific functions ***************************/
static inline void _lock_rx_hashtbl(struct bonding *bond) 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) 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 /* 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) ...@@ -472,13 +472,13 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
_unlock_rx_hashtbl(bond); _unlock_rx_hashtbl(bond);
write_lock(&bond->curr_slave_lock); write_lock_bh(&bond->curr_slave_lock);
if (slave != bond->curr_active_slave) { if (slave != bond->curr_active_slave) {
rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr); 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) 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) ...@@ -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 /* caller must hold the bond lock for write since the mac addresses
* are compared and may be swapped. * are compared and may be swapped.
*/ */
write_lock_bh(&bond->lock); read_lock(&bond->lock);
res = alb_handle_addr_collision_on_attach(bond, slave); res = alb_handle_addr_collision_on_attach(bond, slave);
write_unlock_bh(&bond->lock); read_unlock(&bond->lock);
if (res) { if (res) {
return res; return res;
......
...@@ -1846,9 +1846,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1846,9 +1846,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
*/ */
void bond_destroy(struct bonding *bond) void bond_destroy(struct bonding *bond)
{ {
unregister_netdevice(bond->dev);
bond_deinit(bond->dev); bond_deinit(bond->dev);
bond_destroy_sysfs_entry(bond); 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) ...@@ -2057,9 +2057,9 @@ static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
info->bond_mode = bond->params.mode; info->bond_mode = bond->params.mode;
info->miimon = bond->params.miimon; info->miimon = bond->params.miimon;
read_lock_bh(&bond->lock); read_lock(&bond->lock);
info->num_slaves = bond->slave_cnt; info->num_slaves = bond->slave_cnt;
read_unlock_bh(&bond->lock); read_unlock(&bond->lock);
return 0; return 0;
} }
...@@ -2074,7 +2074,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in ...@@ -2074,7 +2074,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
return -ENODEV; return -ENODEV;
} }
read_lock_bh(&bond->lock); read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i) { bond_for_each_slave(bond, slave, i) {
if (i == (int)info->slave_id) { if (i == (int)info->slave_id) {
...@@ -2083,7 +2083,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in ...@@ -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) { if (found) {
strcpy(info->slave_name, slave->dev->name); strcpy(info->slave_name, slave->dev->name);
...@@ -3078,7 +3078,7 @@ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos) ...@@ -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 */ /* make sure the bond won't be taken away */
read_lock(&dev_base_lock); read_lock(&dev_base_lock);
read_lock_bh(&bond->lock); read_lock(&bond->lock);
if (*pos == 0) { if (*pos == 0) {
return SEQ_START_TOKEN; return SEQ_START_TOKEN;
...@@ -3112,7 +3112,7 @@ static void bond_info_seq_stop(struct seq_file *seq, void *v) ...@@ -3112,7 +3112,7 @@ static void bond_info_seq_stop(struct seq_file *seq, void *v)
{ {
struct bonding *bond = seq->private; struct bonding *bond = seq->private;
read_unlock_bh(&bond->lock); read_unlock(&bond->lock);
read_unlock(&dev_base_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 ...@@ -3821,13 +3821,13 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
if (mii->reg_num == 1) { if (mii->reg_num == 1) {
struct bonding *bond = bond_dev->priv; struct bonding *bond = bond_dev->priv;
mii->val_out = 0; mii->val_out = 0;
read_lock_bh(&bond->lock); read_lock(&bond->lock);
read_lock(&bond->curr_slave_lock); read_lock(&bond->curr_slave_lock);
if (netif_carrier_ok(bond->dev)) { if (netif_carrier_ok(bond->dev)) {
mii->val_out = BMSR_LSTATUS; mii->val_out = BMSR_LSTATUS;
} }
read_unlock(&bond->curr_slave_lock); read_unlock(&bond->curr_slave_lock);
read_unlock_bh(&bond->lock); read_unlock(&bond->lock);
} }
return 0; return 0;
...@@ -4473,8 +4473,8 @@ static void bond_free_all(void) ...@@ -4473,8 +4473,8 @@ static void bond_free_all(void)
bond_mc_list_destroy(bond); bond_mc_list_destroy(bond);
/* Release the bonded slaves */ /* Release the bonded slaves */
bond_release_all(bond_dev); bond_release_all(bond_dev);
bond_deinit(bond_dev);
unregister_netdevice(bond_dev); unregister_netdevice(bond_dev);
bond_deinit(bond_dev);
} }
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
......
...@@ -229,7 +229,7 @@ static ssize_t bonding_show_slaves(struct device *d, ...@@ -229,7 +229,7 @@ static ssize_t bonding_show_slaves(struct device *d,
int i, res = 0; int i, res = 0;
struct bonding *bond = to_bond(d); struct bonding *bond = to_bond(d);
read_lock_bh(&bond->lock); read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i) { bond_for_each_slave(bond, slave, i) {
if (res > (PAGE_SIZE - IFNAMSIZ)) { if (res > (PAGE_SIZE - IFNAMSIZ)) {
/* not enough space for another interface name */ /* not enough space for another interface name */
...@@ -240,7 +240,7 @@ static ssize_t bonding_show_slaves(struct device *d, ...@@ -240,7 +240,7 @@ static ssize_t bonding_show_slaves(struct device *d,
} }
res += sprintf(buf + res, "%s ", slave->dev->name); res += sprintf(buf + res, "%s ", slave->dev->name);
} }
read_unlock_bh(&bond->lock); read_unlock(&bond->lock);
res += sprintf(buf + res, "\n"); res += sprintf(buf + res, "\n");
res++; res++;
return res; return res;
...@@ -282,18 +282,18 @@ static ssize_t bonding_store_slaves(struct device *d, ...@@ -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? */ /* Got a slave name in ifname. Is it already in the list? */
found = 0; found = 0;
read_lock_bh(&bond->lock); read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i) bond_for_each_slave(bond, slave, i)
if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
printk(KERN_ERR DRV_NAME printk(KERN_ERR DRV_NAME
": %s: Interface %s is already enslaved!\n", ": %s: Interface %s is already enslaved!\n",
bond->dev->name, ifname); bond->dev->name, ifname);
ret = -EPERM; ret = -EPERM;
read_unlock_bh(&bond->lock); read_unlock(&bond->lock);
goto out; goto out;
} }
read_unlock_bh(&bond->lock); read_unlock(&bond->lock);
printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n", printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n",
bond->dev->name, ifname); bond->dev->name, ifname);
dev = dev_get_by_name(&init_net, ifname); dev = dev_get_by_name(&init_net, ifname);
...@@ -1133,6 +1133,9 @@ static ssize_t bonding_store_primary(struct device *d, ...@@ -1133,6 +1133,9 @@ static ssize_t bonding_store_primary(struct device *d,
} }
out: out:
write_unlock_bh(&bond->lock); write_unlock_bh(&bond->lock);
rtnl_unlock();
return count; return count;
} }
static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary); 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, ...@@ -1190,6 +1193,7 @@ static ssize_t bonding_show_active_slave(struct device *d,
struct bonding *bond = to_bond(d); struct bonding *bond = to_bond(d);
int count; int count;
rtnl_lock();
read_lock(&bond->curr_slave_lock); read_lock(&bond->curr_slave_lock);
curr = bond->curr_active_slave; curr = bond->curr_active_slave;
...@@ -1269,6 +1273,8 @@ static ssize_t bonding_store_active_slave(struct device *d, ...@@ -1269,6 +1273,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
} }
out: out:
write_unlock_bh(&bond->lock); write_unlock_bh(&bond->lock);
rtnl_unlock();
return count; return count;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment