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: Andy Gospodarek <andy@greyhouse.net> Signed-off-by: Jay Vosburgh <fubar@us.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
059fe7a578
commit
6603a6f25e
3 changed files with 29 additions and 23 deletions
|
@ -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
|
||||||
/*********************** 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)
|
||||||
|
|
||||||
_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)
|
||||||
/* 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)
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
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
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
/* 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)
|
||||||
{
|
{
|
||||||
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
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
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,
|
||||||
|
|
||||||
/* 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,
|
||||||
}
|
}
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
write_unlock_bh(&bond->lock);
|
write_unlock_bh(&bond->lock);
|
||||||
|
rtnl_unlock();
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue