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 | } |