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_alb.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_alb.c')
-rw-r--r-- | drivers/net/bonding/bond_alb.c | 69 |
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 | |||
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 | ||