aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Vosburgh <fubar@us.ibm.com>2007-10-17 20:37:50 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-23 20:32:00 -0400
commit6603a6f25e4bca922a7dfbf0bf03072d98850176 (patch)
tree1e62ef0fe037036542def53dca162618a8345132
parent059fe7a578fba5bbb0fdc0365bfcf6218fa25eb0 (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.c16
-rw-r--r--drivers/net/bonding/bond_main.c20
-rw-r--r--drivers/net/bonding/bond_sysfs.c16
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
129static inline void _lock_tx_hashtbl(struct bonding *bond) 129static 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
134static inline void _unlock_tx_hashtbl(struct bonding *bond) 134static 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 ***************************/
306static inline void _lock_rx_hashtbl(struct bonding *bond) 306static 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
311static inline void _unlock_rx_hashtbl(struct bonding *bond) 311static 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
484static void rlb_update_client(struct rlb_client_info *client_info) 484static 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*/
1847void bond_destroy(struct bonding *bond) 1847void 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 }
1134out: 1134out:
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}
1138static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary); 1141static 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 }
1270out: 1274out:
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}