aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding/bond_alb.c
diff options
context:
space:
mode:
authorJay Vosburgh <fubar@us.ibm.com>2007-10-17 20:37:49 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-23 20:32:00 -0400
commit059fe7a578fba5bbb0fdc0365bfcf6218fa25eb0 (patch)
tree02e508e0094f93a318ead711cf7fe6725e8bf7fe /drivers/net/bonding/bond_alb.c
parent0b0eef66419e9abe6fd62bc958ab7cd0a18f858e (diff)
bonding: Convert locks to _bh, rework alb locking for new locking
Convert locking-related activity to new & improved system. Convert some lock acquisitions to _bh and rework parts of ALB mode, both to avoid deadlocks with workqueue activity. 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>
Diffstat (limited to 'drivers/net/bonding/bond_alb.c')
-rw-r--r--drivers/net/bonding/bond_alb.c69
1 files changed, 63 insertions, 6 deletions
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index eb320c3cbdde..f2e2872c9b17 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -959,19 +959,34 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
959 return 0; 959 return 0;
960} 960}
961 961
962/* Caller must hold bond lock for write or curr_slave_lock for write*/ 962/*
963 * Swap MAC addresses between two slaves.
964 *
965 * Called with RTNL held, and no other locks.
966 *
967 */
968
963static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct slave *slave2) 969static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct slave *slave2)
964{ 970{
965 struct slave *disabled_slave = NULL;
966 u8 tmp_mac_addr[ETH_ALEN]; 971 u8 tmp_mac_addr[ETH_ALEN];
967 int slaves_state_differ;
968
969 slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2));
970 972
971 memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN); 973 memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN);
972 alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled); 974 alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled);
973 alb_set_slave_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled); 975 alb_set_slave_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled);
974 976
977}
978
979/*
980 * Send learning packets after MAC address swap.
981 *
982 * Called with RTNL and bond->lock held for read.
983 */
984static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1,
985 struct slave *slave2)
986{
987 int slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2));
988 struct slave *disabled_slave = NULL;
989
975 /* fasten the change in the switch */ 990 /* fasten the change in the switch */
976 if (SLAVE_IS_OK(slave1)) { 991 if (SLAVE_IS_OK(slave1)) {
977 alb_send_learning_packets(slave1, slave1->dev->dev_addr); 992 alb_send_learning_packets(slave1, slave1->dev->dev_addr);
@@ -1044,7 +1059,9 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla
1044 } 1059 }
1045 1060
1046 if (found) { 1061 if (found) {
1062 /* locking: needs RTNL and nothing else */
1047 alb_swap_mac_addr(bond, slave, tmp_slave); 1063 alb_swap_mac_addr(bond, slave, tmp_slave);
1064 alb_fasten_mac_swap(bond, slave, tmp_slave);
1048 } 1065 }
1049 } 1066 }
1050} 1067}
@@ -1571,13 +1588,21 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char
1571 * Set the bond->curr_active_slave to @new_slave and handle 1588 * Set the bond->curr_active_slave to @new_slave and handle
1572 * mac address swapping and promiscuity changes as needed. 1589 * mac address swapping and promiscuity changes as needed.
1573 * 1590 *
1574 * Caller must hold bond curr_slave_lock for write (or bond lock for write) 1591 * If new_slave is NULL, caller must hold curr_slave_lock or
1592 * bond->lock for write.
1593 *
1594 * If new_slave is not NULL, caller must hold RTNL, bond->lock for
1595 * read and curr_slave_lock for write. Processing here may sleep, so
1596 * no other locks may be held.
1575 */ 1597 */
1576void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave) 1598void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave)
1577{ 1599{
1578 struct slave *swap_slave; 1600 struct slave *swap_slave;
1579 int i; 1601 int i;
1580 1602
1603 if (new_slave)
1604 ASSERT_RTNL();
1605
1581 if (bond->curr_active_slave == new_slave) { 1606 if (bond->curr_active_slave == new_slave) {
1582 return; 1607 return;
1583 } 1608 }
@@ -1610,6 +1635,19 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
1610 } 1635 }
1611 } 1636 }
1612 1637
1638 /*
1639 * Arrange for swap_slave and new_slave to temporarily be
1640 * ignored so we can mess with their MAC addresses without
1641 * fear of interference from transmit activity.
1642 */
1643 if (swap_slave) {
1644 tlb_clear_slave(bond, swap_slave, 1);
1645 }
1646 tlb_clear_slave(bond, new_slave, 1);
1647
1648 write_unlock_bh(&bond->curr_slave_lock);
1649 read_unlock(&bond->lock);
1650
1613 /* curr_active_slave must be set before calling alb_swap_mac_addr */ 1651 /* curr_active_slave must be set before calling alb_swap_mac_addr */
1614 if (swap_slave) { 1652 if (swap_slave) {
1615 /* swap mac address */ 1653 /* swap mac address */
@@ -1618,11 +1656,23 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
1618 /* set the new_slave to the bond mac address */ 1656 /* set the new_slave to the bond mac address */
1619 alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr, 1657 alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr,
1620 bond->alb_info.rlb_enabled); 1658 bond->alb_info.rlb_enabled);
1659 }
1660
1661 read_lock(&bond->lock);
1662
1663 if (swap_slave) {
1664 alb_fasten_mac_swap(bond, swap_slave, new_slave);
1665 } else {
1621 /* fasten bond mac on new current slave */ 1666 /* fasten bond mac on new current slave */
1622 alb_send_learning_packets(new_slave, bond->dev->dev_addr); 1667 alb_send_learning_packets(new_slave, bond->dev->dev_addr);
1623 } 1668 }
1669
1670 write_lock_bh(&bond->curr_slave_lock);
1624} 1671}
1625 1672
1673/*
1674 * Called with RTNL
1675 */
1626int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) 1676int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
1627{ 1677{
1628 struct bonding *bond = bond_dev->priv; 1678 struct bonding *bond = bond_dev->priv;
@@ -1659,8 +1709,12 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
1659 } 1709 }
1660 } 1710 }
1661 1711
1712 write_unlock_bh(&bond->curr_slave_lock);
1713 read_unlock(&bond->lock);
1714
1662 if (swap_slave) { 1715 if (swap_slave) {
1663 alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave); 1716 alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
1717 alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
1664 } else { 1718 } else {
1665 alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr, 1719 alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
1666 bond->alb_info.rlb_enabled); 1720 bond->alb_info.rlb_enabled);
@@ -1672,6 +1726,9 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
1672 } 1726 }
1673 } 1727 }
1674 1728
1729 read_lock(&bond->lock);
1730 write_lock_bh(&bond->curr_slave_lock);
1731
1675 return 0; 1732 return 0;
1676} 1733}
1677 1734