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>

authored by Jay Vosburgh and committed by Jeff Garzik 059fe7a5 0b0eef66

+117 -30
+63 -6
drivers/net/bonding/bond_alb.c
··· 959 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 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 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 973 memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN); 972 974 alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled); 973 975 alb_set_slave_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled); 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; 974 989 975 990 /* fasten the change in the switch */ 976 991 if (SLAVE_IS_OK(slave1)) { ··· 1059 1044 } 1060 1045 1061 1046 if (found) { 1047 + /* locking: needs RTNL and nothing else */ 1062 1048 alb_swap_mac_addr(bond, slave, tmp_slave); 1049 + alb_fasten_mac_swap(bond, slave, tmp_slave); 1063 1050 } 1064 1051 } 1065 1052 } ··· 1588 1571 * Set the bond->curr_active_slave to @new_slave and handle 1589 1572 * mac address swapping and promiscuity changes as needed. 1590 1573 * 1591 - * Caller must hold bond curr_slave_lock for write (or bond lock for write) 1574 + * If new_slave is NULL, caller must hold curr_slave_lock or 1575 + * bond->lock for write. 1576 + * 1577 + * If new_slave is not NULL, caller must hold RTNL, bond->lock for 1578 + * read and curr_slave_lock for write. Processing here may sleep, so 1579 + * no other locks may be held. 1592 1580 */ 1593 1581 void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave) 1594 1582 { 1595 1583 struct slave *swap_slave; 1596 1584 int i; 1585 + 1586 + if (new_slave) 1587 + ASSERT_RTNL(); 1597 1588 1598 1589 if (bond->curr_active_slave == new_slave) { 1599 1590 return; ··· 1635 1610 } 1636 1611 } 1637 1612 1613 + /* 1614 + * Arrange for swap_slave and new_slave to temporarily be 1615 + * ignored so we can mess with their MAC addresses without 1616 + * fear of interference from transmit activity. 1617 + */ 1618 + if (swap_slave) { 1619 + tlb_clear_slave(bond, swap_slave, 1); 1620 + } 1621 + tlb_clear_slave(bond, new_slave, 1); 1622 + 1623 + write_unlock_bh(&bond->curr_slave_lock); 1624 + read_unlock(&bond->lock); 1625 + 1638 1626 /* curr_active_slave must be set before calling alb_swap_mac_addr */ 1639 1627 if (swap_slave) { 1640 1628 /* swap mac address */ ··· 1656 1618 /* set the new_slave to the bond mac address */ 1657 1619 alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr, 1658 1620 bond->alb_info.rlb_enabled); 1621 + } 1622 + 1623 + read_lock(&bond->lock); 1624 + 1625 + if (swap_slave) { 1626 + alb_fasten_mac_swap(bond, swap_slave, new_slave); 1627 + } else { 1659 1628 /* fasten bond mac on new current slave */ 1660 1629 alb_send_learning_packets(new_slave, bond->dev->dev_addr); 1661 1630 } 1631 + 1632 + write_lock_bh(&bond->curr_slave_lock); 1662 1633 } 1663 1634 1635 + /* 1636 + * Called with RTNL 1637 + */ 1664 1638 int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) 1665 1639 { 1666 1640 struct bonding *bond = bond_dev->priv; ··· 1709 1659 } 1710 1660 } 1711 1661 1662 + write_unlock_bh(&bond->curr_slave_lock); 1663 + read_unlock(&bond->lock); 1664 + 1712 1665 if (swap_slave) { 1713 1666 alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave); 1667 + alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave); 1714 1668 } else { 1715 1669 alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr, 1716 1670 bond->alb_info.rlb_enabled); ··· 1725 1671 rlb_req_update_slave_clients(bond, bond->curr_active_slave); 1726 1672 } 1727 1673 } 1674 + 1675 + read_lock(&bond->lock); 1676 + write_lock_bh(&bond->curr_slave_lock); 1728 1677 1729 1678 return 0; 1730 1679 }
+54 -24
drivers/net/bonding/bond_main.c
··· 1590 1590 case BOND_MODE_TLB: 1591 1591 case BOND_MODE_ALB: 1592 1592 new_slave->state = BOND_STATE_ACTIVE; 1593 - if ((!bond->curr_active_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 - } 1593 + bond_set_slave_inactive_flags(new_slave); 1602 1594 break; 1603 1595 default: 1604 1596 dprintk("This slave is always active in trunk mode\n"); ··· 1746 1754 bond_alb_deinit_slave(bond, slave); 1747 1755 } 1748 1756 1749 - if (oldcurrent == slave) 1757 + if (oldcurrent == slave) { 1758 + /* 1759 + * Note that we hold RTNL over this sequence, so there 1760 + * is no concern that another slave add/remove event 1761 + * will interfere. 1762 + */ 1763 + write_unlock_bh(&bond->lock); 1764 + read_lock(&bond->lock); 1765 + write_lock_bh(&bond->curr_slave_lock); 1766 + 1750 1767 bond_select_active_slave(bond); 1768 + 1769 + write_unlock_bh(&bond->curr_slave_lock); 1770 + read_unlock(&bond->lock); 1771 + write_lock_bh(&bond->lock); 1772 + } 1751 1773 1752 1774 if (bond->slave_cnt == 0) { 1753 1775 bond_set_carrier(bond); ··· 2018 2012 return -EINVAL; 2019 2013 } 2020 2014 2021 - write_lock_bh(&bond->lock); 2015 + read_lock(&bond->lock); 2022 2016 2017 + read_lock(&bond->curr_slave_lock); 2023 2018 old_active = bond->curr_active_slave; 2019 + read_unlock(&bond->curr_slave_lock); 2020 + 2024 2021 new_active = bond_get_slave_by_dev(bond, slave_dev); 2025 2022 2026 2023 /* 2027 2024 * Changing to the current active: do nothing; return success. 2028 2025 */ 2029 2026 if (new_active && (new_active == old_active)) { 2030 - write_unlock_bh(&bond->lock); 2027 + read_unlock(&bond->lock); 2031 2028 return 0; 2032 2029 } 2033 2030 ··· 2038 2029 (old_active) && 2039 2030 (new_active->link == BOND_LINK_UP) && 2040 2031 IS_UP(new_active->dev)) { 2032 + write_lock_bh(&bond->curr_slave_lock); 2041 2033 bond_change_active_slave(bond, new_active); 2034 + write_unlock_bh(&bond->curr_slave_lock); 2042 2035 } else { 2043 2036 res = -EINVAL; 2044 2037 } 2045 2038 2046 - write_unlock_bh(&bond->lock); 2039 + read_unlock(&bond->lock); 2047 2040 2048 2041 return res; 2049 2042 } ··· 2151 2140 switch (slave->link) { 2152 2141 case BOND_LINK_UP: /* the link was up */ 2153 2142 if (link_state == BMSR_LSTATUS) { 2154 - /* link stays up, nothing more to do */ 2143 + if (!oldcurrent) { 2144 + if (!have_locks) 2145 + return 1; 2146 + do_failover = 1; 2147 + } 2155 2148 break; 2156 2149 } else { /* link going down */ 2157 2150 slave->link = BOND_LINK_FAIL; ··· 2342 2327 } /* end of for */ 2343 2328 2344 2329 if (do_failover) { 2345 - write_lock(&bond->curr_slave_lock); 2330 + ASSERT_RTNL(); 2331 + 2332 + write_lock_bh(&bond->curr_slave_lock); 2346 2333 2347 2334 bond_select_active_slave(bond); 2348 2335 2349 - write_unlock(&bond->curr_slave_lock); 2336 + write_unlock_bh(&bond->curr_slave_lock); 2337 + 2350 2338 } else 2351 2339 bond_set_carrier(bond); 2352 2340 ··· 2788 2770 } 2789 2771 2790 2772 if (do_failover) { 2791 - write_lock(&bond->curr_slave_lock); 2773 + rtnl_lock(); 2774 + write_lock_bh(&bond->curr_slave_lock); 2792 2775 2793 2776 bond_select_active_slave(bond); 2794 2777 2795 - write_unlock(&bond->curr_slave_lock); 2778 + write_unlock_bh(&bond->curr_slave_lock); 2779 + rtnl_unlock(); 2780 + 2796 2781 } 2797 2782 2798 2783 re_arm: ··· 2852 2831 2853 2832 slave->link = BOND_LINK_UP; 2854 2833 2855 - write_lock(&bond->curr_slave_lock); 2834 + rtnl_lock(); 2835 + 2836 + write_lock_bh(&bond->curr_slave_lock); 2856 2837 2857 2838 if ((!bond->curr_active_slave) && 2858 2839 ((jiffies - slave->dev->trans_start) <= delta_in_ticks)) { ··· 2888 2865 slave->dev->name); 2889 2866 } 2890 2867 2891 - write_unlock(&bond->curr_slave_lock); 2868 + write_unlock_bh(&bond->curr_slave_lock); 2869 + rtnl_unlock(); 2892 2870 } 2893 2871 } else { 2894 2872 read_lock(&bond->curr_slave_lock); ··· 2959 2935 bond->dev->name, 2960 2936 slave->dev->name); 2961 2937 2962 - write_lock(&bond->curr_slave_lock); 2938 + rtnl_lock(); 2939 + write_lock_bh(&bond->curr_slave_lock); 2963 2940 2964 2941 bond_select_active_slave(bond); 2965 2942 slave = bond->curr_active_slave; 2966 2943 2967 - write_unlock(&bond->curr_slave_lock); 2944 + write_unlock_bh(&bond->curr_slave_lock); 2945 + 2946 + rtnl_unlock(); 2968 2947 2969 2948 bond->current_arp_slave = slave; 2970 2949 ··· 2986 2959 bond->primary_slave->dev->name); 2987 2960 2988 2961 /* primary is up so switch to it */ 2989 - write_lock(&bond->curr_slave_lock); 2962 + rtnl_lock(); 2963 + write_lock_bh(&bond->curr_slave_lock); 2990 2964 bond_change_active_slave(bond, bond->primary_slave); 2991 - write_unlock(&bond->curr_slave_lock); 2965 + write_unlock_bh(&bond->curr_slave_lock); 2966 + 2967 + rtnl_unlock(); 2992 2968 2993 2969 slave = bond->primary_slave; 2994 2970 slave->jiffies = jiffies;