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 /drivers/net/bonding/bond_main.c | |
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>
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 78 |
1 files changed, 54 insertions, 24 deletions
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; |