diff options
author | Jay Vosburgh <fubar@us.ibm.com> | 2008-01-17 19:24:59 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-01-18 14:38:38 -0500 |
commit | 2543331d367c9fe54f4ba73300894bc21e0a08f4 (patch) | |
tree | 83c43c448b7f18541dbe70ca4ff80138f8e695d4 /drivers/net/bonding/bond_alb.c | |
parent | e0138a66e18c6755ee29ce13b3f1142af775dc5f (diff) |
bonding: fix locking during alb failover and slave removal
alb_fasten_mac_swap (actually rlb_teach_disabled_mac_on_primary)
requries RTNL and no other locks. This could cause dev_set_promiscuity
and/or dev_set_mac_address to be called with improper locking.
Changed callers to hold only RTNL during calls to alb_fasten_mac_swap
or functions calling it. Updated header comments in affected functions to
reflect proper reality of locking requirements.
Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/bonding/bond_alb.c')
-rw-r--r-- | drivers/net/bonding/bond_alb.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 9b55a123c08f..b57bc9467dbe 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c | |||
@@ -979,7 +979,7 @@ static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct | |||
979 | /* | 979 | /* |
980 | * Send learning packets after MAC address swap. | 980 | * Send learning packets after MAC address swap. |
981 | * | 981 | * |
982 | * Called with RTNL and bond->lock held for read. | 982 | * Called with RTNL and no other locks |
983 | */ | 983 | */ |
984 | static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1, | 984 | static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1, |
985 | struct slave *slave2) | 985 | struct slave *slave2) |
@@ -987,6 +987,8 @@ static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1, | |||
987 | int slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2)); | 987 | int slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2)); |
988 | struct slave *disabled_slave = NULL; | 988 | struct slave *disabled_slave = NULL; |
989 | 989 | ||
990 | ASSERT_RTNL(); | ||
991 | |||
990 | /* fasten the change in the switch */ | 992 | /* fasten the change in the switch */ |
991 | if (SLAVE_IS_OK(slave1)) { | 993 | if (SLAVE_IS_OK(slave1)) { |
992 | alb_send_learning_packets(slave1, slave1->dev->dev_addr); | 994 | alb_send_learning_packets(slave1, slave1->dev->dev_addr); |
@@ -1031,7 +1033,7 @@ static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1, | |||
1031 | * a slave that has @slave's permanet address as its current address. | 1033 | * a slave that has @slave's permanet address as its current address. |
1032 | * We'll make sure that that slave no longer uses @slave's permanent address. | 1034 | * We'll make sure that that slave no longer uses @slave's permanent address. |
1033 | * | 1035 | * |
1034 | * Caller must hold bond lock | 1036 | * Caller must hold RTNL and no other locks |
1035 | */ | 1037 | */ |
1036 | static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *slave) | 1038 | static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *slave) |
1037 | { | 1039 | { |
@@ -1542,7 +1544,12 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave) | |||
1542 | return 0; | 1544 | return 0; |
1543 | } | 1545 | } |
1544 | 1546 | ||
1545 | /* Caller must hold bond lock for write */ | 1547 | /* |
1548 | * Remove slave from tlb and rlb hash tables, and fix up MAC addresses | ||
1549 | * if necessary. | ||
1550 | * | ||
1551 | * Caller must hold RTNL and no other locks | ||
1552 | */ | ||
1546 | void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave) | 1553 | void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave) |
1547 | { | 1554 | { |
1548 | if (bond->slave_cnt > 1) { | 1555 | if (bond->slave_cnt > 1) { |
@@ -1658,12 +1665,11 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave | |||
1658 | bond->alb_info.rlb_enabled); | 1665 | bond->alb_info.rlb_enabled); |
1659 | } | 1666 | } |
1660 | 1667 | ||
1661 | read_lock(&bond->lock); | ||
1662 | |||
1663 | if (swap_slave) { | 1668 | if (swap_slave) { |
1664 | alb_fasten_mac_swap(bond, swap_slave, new_slave); | 1669 | alb_fasten_mac_swap(bond, swap_slave, new_slave); |
1670 | read_lock(&bond->lock); | ||
1665 | } else { | 1671 | } else { |
1666 | /* fasten bond mac on new current slave */ | 1672 | read_lock(&bond->lock); |
1667 | alb_send_learning_packets(new_slave, bond->dev->dev_addr); | 1673 | alb_send_learning_packets(new_slave, bond->dev->dev_addr); |
1668 | } | 1674 | } |
1669 | 1675 | ||