aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJay Vosburgh <fubar@us.ibm.com>2008-01-17 19:24:59 -0500
committerJeff Garzik <jeff@garzik.org>2008-01-18 14:38:38 -0500
commit2543331d367c9fe54f4ba73300894bc21e0a08f4 (patch)
tree83c43c448b7f18541dbe70ca4ff80138f8e695d4 /drivers/net
parente0138a66e18c6755ee29ce13b3f1142af775dc5f (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')
-rw-r--r--drivers/net/bonding/bond_alb.c18
-rw-r--r--drivers/net/bonding/bond_main.c14
2 files changed, 20 insertions, 12 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 */
984static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1, 984static 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 */
1036static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *slave) 1038static 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 */
1546void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave) 1553void 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
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index b0b26036266b..77d004d3c554 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1746,7 +1746,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
1746 * has been cleared (if our_slave == old_current), 1746 * has been cleared (if our_slave == old_current),
1747 * but before a new active slave is selected. 1747 * but before a new active slave is selected.
1748 */ 1748 */
1749 write_unlock_bh(&bond->lock);
1749 bond_alb_deinit_slave(bond, slave); 1750 bond_alb_deinit_slave(bond, slave);
1751 write_lock_bh(&bond->lock);
1750 } 1752 }
1751 1753
1752 if (oldcurrent == slave) { 1754 if (oldcurrent == slave) {
@@ -1905,6 +1907,12 @@ static int bond_release_all(struct net_device *bond_dev)
1905 slave_dev = slave->dev; 1907 slave_dev = slave->dev;
1906 bond_detach_slave(bond, slave); 1908 bond_detach_slave(bond, slave);
1907 1909
1910 /* now that the slave is detached, unlock and perform
1911 * all the undo steps that should not be called from
1912 * within a lock.
1913 */
1914 write_unlock_bh(&bond->lock);
1915
1908 if ((bond->params.mode == BOND_MODE_TLB) || 1916 if ((bond->params.mode == BOND_MODE_TLB) ||
1909 (bond->params.mode == BOND_MODE_ALB)) { 1917 (bond->params.mode == BOND_MODE_ALB)) {
1910 /* must be called only after the slave 1918 /* must be called only after the slave
@@ -1915,12 +1923,6 @@ static int bond_release_all(struct net_device *bond_dev)
1915 1923
1916 bond_compute_features(bond); 1924 bond_compute_features(bond);
1917 1925
1918 /* now that the slave is detached, unlock and perform
1919 * all the undo steps that should not be called from
1920 * within a lock.
1921 */
1922 write_unlock_bh(&bond->lock);
1923
1924 bond_destroy_slave_symlinks(bond_dev, slave_dev); 1926 bond_destroy_slave_symlinks(bond_dev, slave_dev);
1925 bond_del_vlans_from_slave(bond, slave_dev); 1927 bond_del_vlans_from_slave(bond, slave_dev);
1926 1928