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>

authored by Jay Vosburgh and committed by Jeff Garzik 6603a6f2 059fe7a5

+29 -23
+8 -8
drivers/net/bonding/bond_alb.c
··· 128 129 static inline void _lock_tx_hashtbl(struct bonding *bond) 130 { 131 - spin_lock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); 132 } 133 134 static inline void _unlock_tx_hashtbl(struct bonding *bond) 135 { 136 - spin_unlock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); 137 } 138 139 /* Caller must hold tx_hashtbl lock */ ··· 305 /*********************** rlb specific functions ***************************/ 306 static inline void _lock_rx_hashtbl(struct bonding *bond) 307 { 308 - spin_lock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); 309 } 310 311 static inline void _unlock_rx_hashtbl(struct bonding *bond) 312 { 313 - spin_unlock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); 314 } 315 316 /* when an ARP REPLY is received from a client update its info ··· 472 473 _unlock_rx_hashtbl(bond); 474 475 - write_lock(&bond->curr_slave_lock); 476 477 if (slave != bond->curr_active_slave) { 478 rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr); 479 } 480 481 - write_unlock(&bond->curr_slave_lock); 482 } 483 484 static void rlb_update_client(struct rlb_client_info *client_info) ··· 1519 /* caller must hold the bond lock for write since the mac addresses 1520 * are compared and may be swapped. 1521 */ 1522 - write_lock_bh(&bond->lock); 1523 1524 res = alb_handle_addr_collision_on_attach(bond, slave); 1525 1526 - write_unlock_bh(&bond->lock); 1527 1528 if (res) { 1529 return res;
··· 128 129 static inline void _lock_tx_hashtbl(struct bonding *bond) 130 { 131 + spin_lock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); 132 } 133 134 static inline void _unlock_tx_hashtbl(struct bonding *bond) 135 { 136 + spin_unlock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); 137 } 138 139 /* Caller must hold tx_hashtbl lock */ ··· 305 /*********************** rlb specific functions ***************************/ 306 static inline void _lock_rx_hashtbl(struct bonding *bond) 307 { 308 + spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); 309 } 310 311 static inline void _unlock_rx_hashtbl(struct bonding *bond) 312 { 313 + spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); 314 } 315 316 /* when an ARP REPLY is received from a client update its info ··· 472 473 _unlock_rx_hashtbl(bond); 474 475 + write_lock_bh(&bond->curr_slave_lock); 476 477 if (slave != bond->curr_active_slave) { 478 rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr); 479 } 480 481 + write_unlock_bh(&bond->curr_slave_lock); 482 } 483 484 static void rlb_update_client(struct rlb_client_info *client_info) ··· 1519 /* caller must hold the bond lock for write since the mac addresses 1520 * are compared and may be swapped. 1521 */ 1522 + read_lock(&bond->lock); 1523 1524 res = alb_handle_addr_collision_on_attach(bond, slave); 1525 1526 + read_unlock(&bond->lock); 1527 1528 if (res) { 1529 return res;
+10 -10
drivers/net/bonding/bond_main.c
··· 1846 */ 1847 void bond_destroy(struct bonding *bond) 1848 { 1849 bond_deinit(bond->dev); 1850 bond_destroy_sysfs_entry(bond); 1851 - unregister_netdevice(bond->dev); 1852 } 1853 1854 /* ··· 2057 info->bond_mode = bond->params.mode; 2058 info->miimon = bond->params.miimon; 2059 2060 - read_lock_bh(&bond->lock); 2061 info->num_slaves = bond->slave_cnt; 2062 - read_unlock_bh(&bond->lock); 2063 2064 return 0; 2065 } ··· 2074 return -ENODEV; 2075 } 2076 2077 - read_lock_bh(&bond->lock); 2078 2079 bond_for_each_slave(bond, slave, i) { 2080 if (i == (int)info->slave_id) { ··· 2083 } 2084 } 2085 2086 - read_unlock_bh(&bond->lock); 2087 2088 if (found) { 2089 strcpy(info->slave_name, slave->dev->name); ··· 3078 3079 /* make sure the bond won't be taken away */ 3080 read_lock(&dev_base_lock); 3081 - read_lock_bh(&bond->lock); 3082 3083 if (*pos == 0) { 3084 return SEQ_START_TOKEN; ··· 3112 { 3113 struct bonding *bond = seq->private; 3114 3115 - read_unlock_bh(&bond->lock); 3116 read_unlock(&dev_base_lock); 3117 } 3118 ··· 3821 if (mii->reg_num == 1) { 3822 struct bonding *bond = bond_dev->priv; 3823 mii->val_out = 0; 3824 - read_lock_bh(&bond->lock); 3825 read_lock(&bond->curr_slave_lock); 3826 if (netif_carrier_ok(bond->dev)) { 3827 mii->val_out = BMSR_LSTATUS; 3828 } 3829 read_unlock(&bond->curr_slave_lock); 3830 - read_unlock_bh(&bond->lock); 3831 } 3832 3833 return 0; ··· 4473 bond_mc_list_destroy(bond); 4474 /* Release the bonded slaves */ 4475 bond_release_all(bond_dev); 4476 - bond_deinit(bond_dev); 4477 unregister_netdevice(bond_dev); 4478 } 4479 4480 #ifdef CONFIG_PROC_FS
··· 1846 */ 1847 void bond_destroy(struct bonding *bond) 1848 { 1849 + unregister_netdevice(bond->dev); 1850 bond_deinit(bond->dev); 1851 bond_destroy_sysfs_entry(bond); 1852 } 1853 1854 /* ··· 2057 info->bond_mode = bond->params.mode; 2058 info->miimon = bond->params.miimon; 2059 2060 + read_lock(&bond->lock); 2061 info->num_slaves = bond->slave_cnt; 2062 + read_unlock(&bond->lock); 2063 2064 return 0; 2065 } ··· 2074 return -ENODEV; 2075 } 2076 2077 + read_lock(&bond->lock); 2078 2079 bond_for_each_slave(bond, slave, i) { 2080 if (i == (int)info->slave_id) { ··· 2083 } 2084 } 2085 2086 + read_unlock(&bond->lock); 2087 2088 if (found) { 2089 strcpy(info->slave_name, slave->dev->name); ··· 3078 3079 /* make sure the bond won't be taken away */ 3080 read_lock(&dev_base_lock); 3081 + read_lock(&bond->lock); 3082 3083 if (*pos == 0) { 3084 return SEQ_START_TOKEN; ··· 3112 { 3113 struct bonding *bond = seq->private; 3114 3115 + read_unlock(&bond->lock); 3116 read_unlock(&dev_base_lock); 3117 } 3118 ··· 3821 if (mii->reg_num == 1) { 3822 struct bonding *bond = bond_dev->priv; 3823 mii->val_out = 0; 3824 + read_lock(&bond->lock); 3825 read_lock(&bond->curr_slave_lock); 3826 if (netif_carrier_ok(bond->dev)) { 3827 mii->val_out = BMSR_LSTATUS; 3828 } 3829 read_unlock(&bond->curr_slave_lock); 3830 + read_unlock(&bond->lock); 3831 } 3832 3833 return 0; ··· 4473 bond_mc_list_destroy(bond); 4474 /* Release the bonded slaves */ 4475 bond_release_all(bond_dev); 4476 unregister_netdevice(bond_dev); 4477 + bond_deinit(bond_dev); 4478 } 4479 4480 #ifdef CONFIG_PROC_FS
+11 -5
drivers/net/bonding/bond_sysfs.c
··· 229 int i, res = 0; 230 struct bonding *bond = to_bond(d); 231 232 - read_lock_bh(&bond->lock); 233 bond_for_each_slave(bond, slave, i) { 234 if (res > (PAGE_SIZE - IFNAMSIZ)) { 235 /* not enough space for another interface name */ ··· 240 } 241 res += sprintf(buf + res, "%s ", slave->dev->name); 242 } 243 - read_unlock_bh(&bond->lock); 244 res += sprintf(buf + res, "\n"); 245 res++; 246 return res; ··· 282 283 /* Got a slave name in ifname. Is it already in the list? */ 284 found = 0; 285 - read_lock_bh(&bond->lock); 286 bond_for_each_slave(bond, slave, i) 287 if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { 288 printk(KERN_ERR DRV_NAME 289 ": %s: Interface %s is already enslaved!\n", 290 bond->dev->name, ifname); 291 ret = -EPERM; 292 - read_unlock_bh(&bond->lock); 293 goto out; 294 } 295 296 - read_unlock_bh(&bond->lock); 297 printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n", 298 bond->dev->name, ifname); 299 dev = dev_get_by_name(&init_net, ifname); ··· 1133 } 1134 out: 1135 write_unlock_bh(&bond->lock); 1136 return count; 1137 } 1138 static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary); ··· 1193 struct bonding *bond = to_bond(d); 1194 int count; 1195 1196 1197 read_lock(&bond->curr_slave_lock); 1198 curr = bond->curr_active_slave; ··· 1273 } 1274 out: 1275 write_unlock_bh(&bond->lock); 1276 return count; 1277 1278 }
··· 229 int i, res = 0; 230 struct bonding *bond = to_bond(d); 231 232 + read_lock(&bond->lock); 233 bond_for_each_slave(bond, slave, i) { 234 if (res > (PAGE_SIZE - IFNAMSIZ)) { 235 /* not enough space for another interface name */ ··· 240 } 241 res += sprintf(buf + res, "%s ", slave->dev->name); 242 } 243 + read_unlock(&bond->lock); 244 res += sprintf(buf + res, "\n"); 245 res++; 246 return res; ··· 282 283 /* Got a slave name in ifname. Is it already in the list? */ 284 found = 0; 285 + read_lock(&bond->lock); 286 bond_for_each_slave(bond, slave, i) 287 if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { 288 printk(KERN_ERR DRV_NAME 289 ": %s: Interface %s is already enslaved!\n", 290 bond->dev->name, ifname); 291 ret = -EPERM; 292 + read_unlock(&bond->lock); 293 goto out; 294 } 295 296 + read_unlock(&bond->lock); 297 printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n", 298 bond->dev->name, ifname); 299 dev = dev_get_by_name(&init_net, ifname); ··· 1133 } 1134 out: 1135 write_unlock_bh(&bond->lock); 1136 + 1137 + rtnl_unlock(); 1138 + 1139 return count; 1140 } 1141 static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary); ··· 1190 struct bonding *bond = to_bond(d); 1191 int count; 1192 1193 + rtnl_lock(); 1194 1195 read_lock(&bond->curr_slave_lock); 1196 curr = bond->curr_active_slave; ··· 1269 } 1270 out: 1271 write_unlock_bh(&bond->lock); 1272 + rtnl_unlock(); 1273 + 1274 return count; 1275 1276 }