diff options
author | Jay Vosburgh <fubar@us.ibm.com> | 2007-10-17 20:37:49 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-10-23 20:32:00 -0400 |
commit | 059fe7a578fba5bbb0fdc0365bfcf6218fa25eb0 (patch) | |
tree | 02e508e0094f93a318ead711cf7fe6725e8bf7fe | |
parent | 0b0eef66419e9abe6fd62bc958ab7cd0a18f858e (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>
-rw-r--r-- | drivers/net/bonding/bond_alb.c | 69 | ||||
-rw-r--r-- | drivers/net/bonding/bond_main.c | 78 |
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 | |||
963 | static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct slave *slave2) | 969 | static 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 | */ | ||
984 | static 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 | */ |
1576 | void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave) | 1598 | void 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 | */ | ||
1626 | int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) | 1676 | int 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 | ||
2780 | re_arm: | 2801 | re_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; |