aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
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
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')
-rw-r--r--drivers/net/bonding/bond_alb.c69
-rw-r--r--drivers/net/bonding/bond_main.c78
2 files changed, 117 insertions, 30 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
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a3577271b1b8..15c1f7ad222b 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1590,15 +1590,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
1590 case BOND_MODE_TLB: 1590 case BOND_MODE_TLB:
1591 case BOND_MODE_ALB: 1591 case BOND_MODE_ALB:
1592 new_slave->state = BOND_STATE_ACTIVE; 1592 new_slave->state = BOND_STATE_ACTIVE;
1593 if ((!bond->curr_active_slave) && 1593 bond_set_slave_inactive_flags(new_slave);
1594 (new_slave->link != BOND_LINK_DOWN)) {
1595 /* first slave or no active slave yet, and this link
1596 * is OK, so make this interface the active one
1597 */
1598 bond_change_active_slave(bond, new_slave);
1599 } else {
1600 bond_set_slave_inactive_flags(new_slave);
1601 }
1602 break; 1594 break;
1603 default: 1595 default:
1604 dprintk("This slave is always active in trunk mode\n"); 1596 dprintk("This slave is always active in trunk mode\n");
@@ -1754,9 +1746,23 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
1754 bond_alb_deinit_slave(bond, slave); 1746 bond_alb_deinit_slave(bond, slave);
1755 } 1747 }
1756 1748
1757 if (oldcurrent == slave) 1749 if (oldcurrent == slave) {
1750 /*
1751 * Note that we hold RTNL over this sequence, so there
1752 * is no concern that another slave add/remove event
1753 * will interfere.
1754 */
1755 write_unlock_bh(&bond->lock);
1756 read_lock(&bond->lock);
1757 write_lock_bh(&bond->curr_slave_lock);
1758
1758 bond_select_active_slave(bond); 1759 bond_select_active_slave(bond);
1759 1760
1761 write_unlock_bh(&bond->curr_slave_lock);
1762 read_unlock(&bond->lock);
1763 write_lock_bh(&bond->lock);
1764 }
1765
1760 if (bond->slave_cnt == 0) { 1766 if (bond->slave_cnt == 0) {
1761 bond_set_carrier(bond); 1767 bond_set_carrier(bond);
1762 1768
@@ -2012,16 +2018,19 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi
2012 return -EINVAL; 2018 return -EINVAL;
2013 } 2019 }
2014 2020
2015 write_lock_bh(&bond->lock); 2021 read_lock(&bond->lock);
2016 2022
2023 read_lock(&bond->curr_slave_lock);
2017 old_active = bond->curr_active_slave; 2024 old_active = bond->curr_active_slave;
2025 read_unlock(&bond->curr_slave_lock);
2026
2018 new_active = bond_get_slave_by_dev(bond, slave_dev); 2027 new_active = bond_get_slave_by_dev(bond, slave_dev);
2019 2028
2020 /* 2029 /*
2021 * Changing to the current active: do nothing; return success. 2030 * Changing to the current active: do nothing; return success.
2022 */ 2031 */
2023 if (new_active && (new_active == old_active)) { 2032 if (new_active && (new_active == old_active)) {
2024 write_unlock_bh(&bond->lock); 2033 read_unlock(&bond->lock);
2025 return 0; 2034 return 0;
2026 } 2035 }
2027 2036
@@ -2029,12 +2038,14 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi
2029 (old_active) && 2038 (old_active) &&
2030 (new_active->link == BOND_LINK_UP) && 2039 (new_active->link == BOND_LINK_UP) &&
2031 IS_UP(new_active->dev)) { 2040 IS_UP(new_active->dev)) {
2041 write_lock_bh(&bond->curr_slave_lock);
2032 bond_change_active_slave(bond, new_active); 2042 bond_change_active_slave(bond, new_active);
2043 write_unlock_bh(&bond->curr_slave_lock);
2033 } else { 2044 } else {
2034 res = -EINVAL; 2045 res = -EINVAL;
2035 } 2046 }
2036 2047
2037 write_unlock_bh(&bond->lock); 2048 read_unlock(&bond->lock);
2038 2049
2039 return res; 2050 return res;
2040} 2051}
@@ -2140,7 +2151,11 @@ static int __bond_mii_monitor(struct bonding *bond, int have_locks)
2140 switch (slave->link) { 2151 switch (slave->link) {
2141 case BOND_LINK_UP: /* the link was up */ 2152 case BOND_LINK_UP: /* the link was up */
2142 if (link_state == BMSR_LSTATUS) { 2153 if (link_state == BMSR_LSTATUS) {
2143 /* link stays up, nothing more to do */ 2154 if (!oldcurrent) {
2155 if (!have_locks)
2156 return 1;
2157 do_failover = 1;
2158 }
2144 break; 2159 break;
2145 } else { /* link going down */ 2160 } else { /* link going down */
2146 slave->link = BOND_LINK_FAIL; 2161 slave->link = BOND_LINK_FAIL;
@@ -2327,11 +2342,14 @@ static int __bond_mii_monitor(struct bonding *bond, int have_locks)
2327 } /* end of for */ 2342 } /* end of for */
2328 2343
2329 if (do_failover) { 2344 if (do_failover) {
2330 write_lock(&bond->curr_slave_lock); 2345 ASSERT_RTNL();
2346
2347 write_lock_bh(&bond->curr_slave_lock);
2331 2348
2332 bond_select_active_slave(bond); 2349 bond_select_active_slave(bond);
2333 2350
2334 write_unlock(&bond->curr_slave_lock); 2351 write_unlock_bh(&bond->curr_slave_lock);
2352
2335 } else 2353 } else
2336 bond_set_carrier(bond); 2354 bond_set_carrier(bond);
2337 2355
@@ -2770,11 +2788,14 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
2770 } 2788 }
2771 2789
2772 if (do_failover) { 2790 if (do_failover) {
2773 write_lock(&bond->curr_slave_lock); 2791 rtnl_lock();
2792 write_lock_bh(&bond->curr_slave_lock);
2774 2793
2775 bond_select_active_slave(bond); 2794 bond_select_active_slave(bond);
2776 2795
2777 write_unlock(&bond->curr_slave_lock); 2796 write_unlock_bh(&bond->curr_slave_lock);
2797 rtnl_unlock();
2798
2778 } 2799 }
2779 2800
2780re_arm: 2801re_arm:
@@ -2831,7 +2852,9 @@ void bond_activebackup_arp_mon(struct work_struct *work)
2831 2852
2832 slave->link = BOND_LINK_UP; 2853 slave->link = BOND_LINK_UP;
2833 2854
2834 write_lock(&bond->curr_slave_lock); 2855 rtnl_lock();
2856
2857 write_lock_bh(&bond->curr_slave_lock);
2835 2858
2836 if ((!bond->curr_active_slave) && 2859 if ((!bond->curr_active_slave) &&
2837 ((jiffies - slave->dev->trans_start) <= delta_in_ticks)) { 2860 ((jiffies - slave->dev->trans_start) <= delta_in_ticks)) {
@@ -2865,7 +2888,8 @@ void bond_activebackup_arp_mon(struct work_struct *work)
2865 slave->dev->name); 2888 slave->dev->name);
2866 } 2889 }
2867 2890
2868 write_unlock(&bond->curr_slave_lock); 2891 write_unlock_bh(&bond->curr_slave_lock);
2892 rtnl_unlock();
2869 } 2893 }
2870 } else { 2894 } else {
2871 read_lock(&bond->curr_slave_lock); 2895 read_lock(&bond->curr_slave_lock);
@@ -2935,12 +2959,15 @@ void bond_activebackup_arp_mon(struct work_struct *work)
2935 bond->dev->name, 2959 bond->dev->name,
2936 slave->dev->name); 2960 slave->dev->name);
2937 2961
2938 write_lock(&bond->curr_slave_lock); 2962 rtnl_lock();
2963 write_lock_bh(&bond->curr_slave_lock);
2939 2964
2940 bond_select_active_slave(bond); 2965 bond_select_active_slave(bond);
2941 slave = bond->curr_active_slave; 2966 slave = bond->curr_active_slave;
2942 2967
2943 write_unlock(&bond->curr_slave_lock); 2968 write_unlock_bh(&bond->curr_slave_lock);
2969
2970 rtnl_unlock();
2944 2971
2945 bond->current_arp_slave = slave; 2972 bond->current_arp_slave = slave;
2946 2973
@@ -2959,9 +2986,12 @@ void bond_activebackup_arp_mon(struct work_struct *work)
2959 bond->primary_slave->dev->name); 2986 bond->primary_slave->dev->name);
2960 2987
2961 /* primary is up so switch to it */ 2988 /* primary is up so switch to it */
2962 write_lock(&bond->curr_slave_lock); 2989 rtnl_lock();
2990 write_lock_bh(&bond->curr_slave_lock);
2963 bond_change_active_slave(bond, bond->primary_slave); 2991 bond_change_active_slave(bond, bond->primary_slave);
2964 write_unlock(&bond->curr_slave_lock); 2992 write_unlock_bh(&bond->curr_slave_lock);
2993
2994 rtnl_unlock();
2965 2995
2966 slave = bond->primary_slave; 2996 slave = bond->primary_slave;
2967 slave->jiffies = jiffies; 2997 slave->jiffies = jiffies;