diff options
| author | Jay Vosburgh <fubar@us.ibm.com> | 2007-10-17 20:37:50 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2007-10-23 20:32:00 -0400 |
| commit | 6603a6f25e4bca922a7dfbf0bf03072d98850176 (patch) | |
| tree | 1e62ef0fe037036542def53dca162618a8345132 | |
| parent | 059fe7a578fba5bbb0fdc0365bfcf6218fa25eb0 (diff) | |
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>
| -rw-r--r-- | drivers/net/bonding/bond_alb.c | 16 | ||||
| -rw-r--r-- | drivers/net/bonding/bond_main.c | 20 | ||||
| -rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 16 |
3 files changed, 29 insertions, 23 deletions
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index f2e2872c9b17..6db5d763f6b6 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c | |||
| @@ -128,12 +128,12 @@ static inline u8 _simple_hash(const u8 *hash_start, int hash_size) | |||
| 128 | 128 | ||
| 129 | static inline void _lock_tx_hashtbl(struct bonding *bond) | 129 | static inline void _lock_tx_hashtbl(struct bonding *bond) |
| 130 | { | 130 | { |
| 131 | spin_lock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); | 131 | spin_lock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | static inline void _unlock_tx_hashtbl(struct bonding *bond) | 134 | static inline void _unlock_tx_hashtbl(struct bonding *bond) |
| 135 | { | 135 | { |
| 136 | spin_unlock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); | 136 | spin_unlock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | /* Caller must hold tx_hashtbl lock */ | 139 | /* Caller must hold tx_hashtbl lock */ |
| @@ -305,12 +305,12 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u3 | |||
| 305 | /*********************** rlb specific functions ***************************/ | 305 | /*********************** rlb specific functions ***************************/ |
| 306 | static inline void _lock_rx_hashtbl(struct bonding *bond) | 306 | static inline void _lock_rx_hashtbl(struct bonding *bond) |
| 307 | { | 307 | { |
| 308 | spin_lock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); | 308 | spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | static inline void _unlock_rx_hashtbl(struct bonding *bond) | 311 | static inline void _unlock_rx_hashtbl(struct bonding *bond) |
| 312 | { | 312 | { |
| 313 | spin_unlock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); | 313 | spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | /* when an ARP REPLY is received from a client update its info | 316 | /* 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 | 472 | ||
| 473 | _unlock_rx_hashtbl(bond); | 473 | _unlock_rx_hashtbl(bond); |
| 474 | 474 | ||
| 475 | write_lock(&bond->curr_slave_lock); | 475 | write_lock_bh(&bond->curr_slave_lock); |
| 476 | 476 | ||
| 477 | if (slave != bond->curr_active_slave) { | 477 | if (slave != bond->curr_active_slave) { |
| 478 | rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr); | 478 | rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr); |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | write_unlock(&bond->curr_slave_lock); | 481 | write_unlock_bh(&bond->curr_slave_lock); |
| 482 | } | 482 | } |
| 483 | 483 | ||
| 484 | static void rlb_update_client(struct rlb_client_info *client_info) | 484 | 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 | /* caller must hold the bond lock for write since the mac addresses | 1519 | /* caller must hold the bond lock for write since the mac addresses |
| 1520 | * are compared and may be swapped. | 1520 | * are compared and may be swapped. |
| 1521 | */ | 1521 | */ |
| 1522 | write_lock_bh(&bond->lock); | 1522 | read_lock(&bond->lock); |
| 1523 | 1523 | ||
| 1524 | res = alb_handle_addr_collision_on_attach(bond, slave); | 1524 | res = alb_handle_addr_collision_on_attach(bond, slave); |
| 1525 | 1525 | ||
| 1526 | write_unlock_bh(&bond->lock); | 1526 | read_unlock(&bond->lock); |
| 1527 | 1527 | ||
| 1528 | if (res) { | 1528 | if (res) { |
| 1529 | return res; | 1529 | return res; |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 15c1f7ad222b..6909becb10f6 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
| @@ -1846,9 +1846,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | |||
| 1846 | */ | 1846 | */ |
| 1847 | void bond_destroy(struct bonding *bond) | 1847 | void bond_destroy(struct bonding *bond) |
| 1848 | { | 1848 | { |
| 1849 | unregister_netdevice(bond->dev); | ||
| 1849 | bond_deinit(bond->dev); | 1850 | bond_deinit(bond->dev); |
| 1850 | bond_destroy_sysfs_entry(bond); | 1851 | bond_destroy_sysfs_entry(bond); |
| 1851 | unregister_netdevice(bond->dev); | ||
| 1852 | } | 1852 | } |
| 1853 | 1853 | ||
| 1854 | /* | 1854 | /* |
| @@ -2057,9 +2057,9 @@ static int bond_info_query(struct net_device *bond_dev, struct ifbond *info) | |||
| 2057 | info->bond_mode = bond->params.mode; | 2057 | info->bond_mode = bond->params.mode; |
| 2058 | info->miimon = bond->params.miimon; | 2058 | info->miimon = bond->params.miimon; |
| 2059 | 2059 | ||
| 2060 | read_lock_bh(&bond->lock); | 2060 | read_lock(&bond->lock); |
| 2061 | info->num_slaves = bond->slave_cnt; | 2061 | info->num_slaves = bond->slave_cnt; |
| 2062 | read_unlock_bh(&bond->lock); | 2062 | read_unlock(&bond->lock); |
| 2063 | 2063 | ||
| 2064 | return 0; | 2064 | return 0; |
| 2065 | } | 2065 | } |
| @@ -2074,7 +2074,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in | |||
| 2074 | return -ENODEV; | 2074 | return -ENODEV; |
| 2075 | } | 2075 | } |
| 2076 | 2076 | ||
| 2077 | read_lock_bh(&bond->lock); | 2077 | read_lock(&bond->lock); |
| 2078 | 2078 | ||
| 2079 | bond_for_each_slave(bond, slave, i) { | 2079 | bond_for_each_slave(bond, slave, i) { |
| 2080 | if (i == (int)info->slave_id) { | 2080 | 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 | } | 2083 | } |
| 2084 | } | 2084 | } |
| 2085 | 2085 | ||
| 2086 | read_unlock_bh(&bond->lock); | 2086 | read_unlock(&bond->lock); |
| 2087 | 2087 | ||
| 2088 | if (found) { | 2088 | if (found) { |
| 2089 | strcpy(info->slave_name, slave->dev->name); | 2089 | 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 | 3078 | ||
| 3079 | /* make sure the bond won't be taken away */ | 3079 | /* make sure the bond won't be taken away */ |
| 3080 | read_lock(&dev_base_lock); | 3080 | read_lock(&dev_base_lock); |
| 3081 | read_lock_bh(&bond->lock); | 3081 | read_lock(&bond->lock); |
| 3082 | 3082 | ||
| 3083 | if (*pos == 0) { | 3083 | if (*pos == 0) { |
| 3084 | return SEQ_START_TOKEN; | 3084 | return SEQ_START_TOKEN; |
| @@ -3112,7 +3112,7 @@ static void bond_info_seq_stop(struct seq_file *seq, void *v) | |||
| 3112 | { | 3112 | { |
| 3113 | struct bonding *bond = seq->private; | 3113 | struct bonding *bond = seq->private; |
| 3114 | 3114 | ||
| 3115 | read_unlock_bh(&bond->lock); | 3115 | read_unlock(&bond->lock); |
| 3116 | read_unlock(&dev_base_lock); | 3116 | read_unlock(&dev_base_lock); |
| 3117 | } | 3117 | } |
| 3118 | 3118 | ||
| @@ -3821,13 +3821,13 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd | |||
| 3821 | if (mii->reg_num == 1) { | 3821 | if (mii->reg_num == 1) { |
| 3822 | struct bonding *bond = bond_dev->priv; | 3822 | struct bonding *bond = bond_dev->priv; |
| 3823 | mii->val_out = 0; | 3823 | mii->val_out = 0; |
| 3824 | read_lock_bh(&bond->lock); | 3824 | read_lock(&bond->lock); |
| 3825 | read_lock(&bond->curr_slave_lock); | 3825 | read_lock(&bond->curr_slave_lock); |
| 3826 | if (netif_carrier_ok(bond->dev)) { | 3826 | if (netif_carrier_ok(bond->dev)) { |
| 3827 | mii->val_out = BMSR_LSTATUS; | 3827 | mii->val_out = BMSR_LSTATUS; |
| 3828 | } | 3828 | } |
| 3829 | read_unlock(&bond->curr_slave_lock); | 3829 | read_unlock(&bond->curr_slave_lock); |
| 3830 | read_unlock_bh(&bond->lock); | 3830 | read_unlock(&bond->lock); |
| 3831 | } | 3831 | } |
| 3832 | 3832 | ||
| 3833 | return 0; | 3833 | return 0; |
| @@ -4473,8 +4473,8 @@ static void bond_free_all(void) | |||
| 4473 | bond_mc_list_destroy(bond); | 4473 | bond_mc_list_destroy(bond); |
| 4474 | /* Release the bonded slaves */ | 4474 | /* Release the bonded slaves */ |
| 4475 | bond_release_all(bond_dev); | 4475 | bond_release_all(bond_dev); |
| 4476 | bond_deinit(bond_dev); | ||
| 4477 | unregister_netdevice(bond_dev); | 4476 | unregister_netdevice(bond_dev); |
| 4477 | bond_deinit(bond_dev); | ||
| 4478 | } | 4478 | } |
| 4479 | 4479 | ||
| 4480 | #ifdef CONFIG_PROC_FS | 4480 | #ifdef CONFIG_PROC_FS |
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 19d970e0cbb8..7a06ade85b02 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c | |||
| @@ -229,7 +229,7 @@ static ssize_t bonding_show_slaves(struct device *d, | |||
| 229 | int i, res = 0; | 229 | int i, res = 0; |
| 230 | struct bonding *bond = to_bond(d); | 230 | struct bonding *bond = to_bond(d); |
| 231 | 231 | ||
| 232 | read_lock_bh(&bond->lock); | 232 | read_lock(&bond->lock); |
| 233 | bond_for_each_slave(bond, slave, i) { | 233 | bond_for_each_slave(bond, slave, i) { |
| 234 | if (res > (PAGE_SIZE - IFNAMSIZ)) { | 234 | if (res > (PAGE_SIZE - IFNAMSIZ)) { |
| 235 | /* not enough space for another interface name */ | 235 | /* not enough space for another interface name */ |
| @@ -240,7 +240,7 @@ static ssize_t bonding_show_slaves(struct device *d, | |||
| 240 | } | 240 | } |
| 241 | res += sprintf(buf + res, "%s ", slave->dev->name); | 241 | res += sprintf(buf + res, "%s ", slave->dev->name); |
| 242 | } | 242 | } |
| 243 | read_unlock_bh(&bond->lock); | 243 | read_unlock(&bond->lock); |
| 244 | res += sprintf(buf + res, "\n"); | 244 | res += sprintf(buf + res, "\n"); |
| 245 | res++; | 245 | res++; |
| 246 | return res; | 246 | return res; |
| @@ -282,18 +282,18 @@ static ssize_t bonding_store_slaves(struct device *d, | |||
| 282 | 282 | ||
| 283 | /* Got a slave name in ifname. Is it already in the list? */ | 283 | /* Got a slave name in ifname. Is it already in the list? */ |
| 284 | found = 0; | 284 | found = 0; |
| 285 | read_lock_bh(&bond->lock); | 285 | read_lock(&bond->lock); |
| 286 | bond_for_each_slave(bond, slave, i) | 286 | bond_for_each_slave(bond, slave, i) |
| 287 | if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { | 287 | if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { |
| 288 | printk(KERN_ERR DRV_NAME | 288 | printk(KERN_ERR DRV_NAME |
| 289 | ": %s: Interface %s is already enslaved!\n", | 289 | ": %s: Interface %s is already enslaved!\n", |
| 290 | bond->dev->name, ifname); | 290 | bond->dev->name, ifname); |
| 291 | ret = -EPERM; | 291 | ret = -EPERM; |
| 292 | read_unlock_bh(&bond->lock); | 292 | read_unlock(&bond->lock); |
| 293 | goto out; | 293 | goto out; |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | read_unlock_bh(&bond->lock); | 296 | read_unlock(&bond->lock); |
| 297 | printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n", | 297 | printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n", |
| 298 | bond->dev->name, ifname); | 298 | bond->dev->name, ifname); |
| 299 | dev = dev_get_by_name(&init_net, ifname); | 299 | dev = dev_get_by_name(&init_net, ifname); |
| @@ -1133,6 +1133,9 @@ static ssize_t bonding_store_primary(struct device *d, | |||
| 1133 | } | 1133 | } |
| 1134 | out: | 1134 | out: |
| 1135 | write_unlock_bh(&bond->lock); | 1135 | write_unlock_bh(&bond->lock); |
| 1136 | |||
| 1137 | rtnl_unlock(); | ||
| 1138 | |||
| 1136 | return count; | 1139 | return count; |
| 1137 | } | 1140 | } |
| 1138 | static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary); | 1141 | 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 | struct bonding *bond = to_bond(d); | 1193 | struct bonding *bond = to_bond(d); |
| 1191 | int count; | 1194 | int count; |
| 1192 | 1195 | ||
| 1196 | rtnl_lock(); | ||
| 1193 | 1197 | ||
| 1194 | read_lock(&bond->curr_slave_lock); | 1198 | read_lock(&bond->curr_slave_lock); |
| 1195 | curr = bond->curr_active_slave; | 1199 | curr = bond->curr_active_slave; |
| @@ -1269,6 +1273,8 @@ static ssize_t bonding_store_active_slave(struct device *d, | |||
| 1269 | } | 1273 | } |
| 1270 | out: | 1274 | out: |
| 1271 | write_unlock_bh(&bond->lock); | 1275 | write_unlock_bh(&bond->lock); |
| 1276 | rtnl_unlock(); | ||
| 1277 | |||
| 1272 | return count; | 1278 | return count; |
| 1273 | 1279 | ||
| 1274 | } | 1280 | } |
