diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 124 |
1 files changed, 70 insertions, 54 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 1c6104d3501d..e5628fc725c3 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -829,21 +829,25 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) | |||
829 | if (bond_is_lb(bond)) { | 829 | if (bond_is_lb(bond)) { |
830 | bond_alb_handle_active_change(bond, new_active); | 830 | bond_alb_handle_active_change(bond, new_active); |
831 | if (old_active) | 831 | if (old_active) |
832 | bond_set_slave_inactive_flags(old_active); | 832 | bond_set_slave_inactive_flags(old_active, |
833 | BOND_SLAVE_NOTIFY_NOW); | ||
833 | if (new_active) | 834 | if (new_active) |
834 | bond_set_slave_active_flags(new_active); | 835 | bond_set_slave_active_flags(new_active, |
836 | BOND_SLAVE_NOTIFY_NOW); | ||
835 | } else { | 837 | } else { |
836 | rcu_assign_pointer(bond->curr_active_slave, new_active); | 838 | rcu_assign_pointer(bond->curr_active_slave, new_active); |
837 | } | 839 | } |
838 | 840 | ||
839 | if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { | 841 | if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { |
840 | if (old_active) | 842 | if (old_active) |
841 | bond_set_slave_inactive_flags(old_active); | 843 | bond_set_slave_inactive_flags(old_active, |
844 | BOND_SLAVE_NOTIFY_NOW); | ||
842 | 845 | ||
843 | if (new_active) { | 846 | if (new_active) { |
844 | bool should_notify_peers = false; | 847 | bool should_notify_peers = false; |
845 | 848 | ||
846 | bond_set_slave_active_flags(new_active); | 849 | bond_set_slave_active_flags(new_active, |
850 | BOND_SLAVE_NOTIFY_NOW); | ||
847 | 851 | ||
848 | if (bond->params.fail_over_mac) | 852 | if (bond->params.fail_over_mac) |
849 | bond_do_fail_over_mac(bond, new_active, | 853 | bond_do_fail_over_mac(bond, new_active, |
@@ -1193,6 +1197,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1193 | return -EBUSY; | 1197 | return -EBUSY; |
1194 | } | 1198 | } |
1195 | 1199 | ||
1200 | if (bond_dev == slave_dev) { | ||
1201 | pr_err("%s: cannot enslave bond to itself.\n", bond_dev->name); | ||
1202 | return -EPERM; | ||
1203 | } | ||
1204 | |||
1196 | /* vlan challenged mutual exclusion */ | 1205 | /* vlan challenged mutual exclusion */ |
1197 | /* no need to lock since we're protected by rtnl_lock */ | 1206 | /* no need to lock since we're protected by rtnl_lock */ |
1198 | if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { | 1207 | if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { |
@@ -1463,14 +1472,15 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1463 | 1472 | ||
1464 | switch (bond->params.mode) { | 1473 | switch (bond->params.mode) { |
1465 | case BOND_MODE_ACTIVEBACKUP: | 1474 | case BOND_MODE_ACTIVEBACKUP: |
1466 | bond_set_slave_inactive_flags(new_slave); | 1475 | bond_set_slave_inactive_flags(new_slave, |
1476 | BOND_SLAVE_NOTIFY_NOW); | ||
1467 | break; | 1477 | break; |
1468 | case BOND_MODE_8023AD: | 1478 | case BOND_MODE_8023AD: |
1469 | /* in 802.3ad mode, the internal mechanism | 1479 | /* in 802.3ad mode, the internal mechanism |
1470 | * will activate the slaves in the selected | 1480 | * will activate the slaves in the selected |
1471 | * aggregator | 1481 | * aggregator |
1472 | */ | 1482 | */ |
1473 | bond_set_slave_inactive_flags(new_slave); | 1483 | bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW); |
1474 | /* if this is the first slave */ | 1484 | /* if this is the first slave */ |
1475 | if (!prev_slave) { | 1485 | if (!prev_slave) { |
1476 | SLAVE_AD_INFO(new_slave).id = 1; | 1486 | SLAVE_AD_INFO(new_slave).id = 1; |
@@ -1488,7 +1498,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1488 | case BOND_MODE_TLB: | 1498 | case BOND_MODE_TLB: |
1489 | case BOND_MODE_ALB: | 1499 | case BOND_MODE_ALB: |
1490 | bond_set_active_slave(new_slave); | 1500 | bond_set_active_slave(new_slave); |
1491 | bond_set_slave_inactive_flags(new_slave); | 1501 | bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW); |
1492 | break; | 1502 | break; |
1493 | default: | 1503 | default: |
1494 | pr_debug("This slave is always active in trunk mode\n"); | 1504 | pr_debug("This slave is always active in trunk mode\n"); |
@@ -1654,9 +1664,6 @@ static int __bond_release_one(struct net_device *bond_dev, | |||
1654 | return -EINVAL; | 1664 | return -EINVAL; |
1655 | } | 1665 | } |
1656 | 1666 | ||
1657 | /* release the slave from its bond */ | ||
1658 | bond->slave_cnt--; | ||
1659 | |||
1660 | bond_sysfs_slave_del(slave); | 1667 | bond_sysfs_slave_del(slave); |
1661 | 1668 | ||
1662 | bond_upper_dev_unlink(bond_dev, slave_dev); | 1669 | bond_upper_dev_unlink(bond_dev, slave_dev); |
@@ -1738,6 +1745,7 @@ static int __bond_release_one(struct net_device *bond_dev, | |||
1738 | 1745 | ||
1739 | unblock_netpoll_tx(); | 1746 | unblock_netpoll_tx(); |
1740 | synchronize_rcu(); | 1747 | synchronize_rcu(); |
1748 | bond->slave_cnt--; | ||
1741 | 1749 | ||
1742 | if (!bond_has_slaves(bond)) { | 1750 | if (!bond_has_slaves(bond)) { |
1743 | call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev); | 1751 | call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev); |
@@ -2015,7 +2023,8 @@ static void bond_miimon_commit(struct bonding *bond) | |||
2015 | 2023 | ||
2016 | if (bond->params.mode == BOND_MODE_ACTIVEBACKUP || | 2024 | if (bond->params.mode == BOND_MODE_ACTIVEBACKUP || |
2017 | bond->params.mode == BOND_MODE_8023AD) | 2025 | bond->params.mode == BOND_MODE_8023AD) |
2018 | bond_set_slave_inactive_flags(slave); | 2026 | bond_set_slave_inactive_flags(slave, |
2027 | BOND_SLAVE_NOTIFY_NOW); | ||
2019 | 2028 | ||
2020 | pr_info("%s: link status definitely down for interface %s, disabling it\n", | 2029 | pr_info("%s: link status definitely down for interface %s, disabling it\n", |
2021 | bond->dev->name, slave->dev->name); | 2030 | bond->dev->name, slave->dev->name); |
@@ -2562,7 +2571,8 @@ static void bond_ab_arp_commit(struct bonding *bond) | |||
2562 | slave->link = BOND_LINK_UP; | 2571 | slave->link = BOND_LINK_UP; |
2563 | if (bond->current_arp_slave) { | 2572 | if (bond->current_arp_slave) { |
2564 | bond_set_slave_inactive_flags( | 2573 | bond_set_slave_inactive_flags( |
2565 | bond->current_arp_slave); | 2574 | bond->current_arp_slave, |
2575 | BOND_SLAVE_NOTIFY_NOW); | ||
2566 | bond->current_arp_slave = NULL; | 2576 | bond->current_arp_slave = NULL; |
2567 | } | 2577 | } |
2568 | 2578 | ||
@@ -2582,7 +2592,8 @@ static void bond_ab_arp_commit(struct bonding *bond) | |||
2582 | slave->link_failure_count++; | 2592 | slave->link_failure_count++; |
2583 | 2593 | ||
2584 | slave->link = BOND_LINK_DOWN; | 2594 | slave->link = BOND_LINK_DOWN; |
2585 | bond_set_slave_inactive_flags(slave); | 2595 | bond_set_slave_inactive_flags(slave, |
2596 | BOND_SLAVE_NOTIFY_NOW); | ||
2586 | 2597 | ||
2587 | pr_info("%s: link status definitely down for interface %s, disabling it\n", | 2598 | pr_info("%s: link status definitely down for interface %s, disabling it\n", |
2588 | bond->dev->name, slave->dev->name); | 2599 | bond->dev->name, slave->dev->name); |
@@ -2615,17 +2626,17 @@ do_failover: | |||
2615 | 2626 | ||
2616 | /* | 2627 | /* |
2617 | * Send ARP probes for active-backup mode ARP monitor. | 2628 | * Send ARP probes for active-backup mode ARP monitor. |
2629 | * | ||
2630 | * Called with rcu_read_lock hold. | ||
2618 | */ | 2631 | */ |
2619 | static bool bond_ab_arp_probe(struct bonding *bond) | 2632 | static bool bond_ab_arp_probe(struct bonding *bond) |
2620 | { | 2633 | { |
2621 | struct slave *slave, *before = NULL, *new_slave = NULL, | 2634 | struct slave *slave, *before = NULL, *new_slave = NULL, |
2622 | *curr_arp_slave, *curr_active_slave; | 2635 | *curr_arp_slave = rcu_dereference(bond->current_arp_slave), |
2636 | *curr_active_slave = rcu_dereference(bond->curr_active_slave); | ||
2623 | struct list_head *iter; | 2637 | struct list_head *iter; |
2624 | bool found = false; | 2638 | bool found = false; |
2625 | 2639 | bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER; | |
2626 | rcu_read_lock(); | ||
2627 | curr_arp_slave = rcu_dereference(bond->current_arp_slave); | ||
2628 | curr_active_slave = rcu_dereference(bond->curr_active_slave); | ||
2629 | 2640 | ||
2630 | if (curr_arp_slave && curr_active_slave) | 2641 | if (curr_arp_slave && curr_active_slave) |
2631 | pr_info("PROBE: c_arp %s && cas %s BAD\n", | 2642 | pr_info("PROBE: c_arp %s && cas %s BAD\n", |
@@ -2634,32 +2645,23 @@ static bool bond_ab_arp_probe(struct bonding *bond) | |||
2634 | 2645 | ||
2635 | if (curr_active_slave) { | 2646 | if (curr_active_slave) { |
2636 | bond_arp_send_all(bond, curr_active_slave); | 2647 | bond_arp_send_all(bond, curr_active_slave); |
2637 | rcu_read_unlock(); | 2648 | return should_notify_rtnl; |
2638 | return true; | ||
2639 | } | 2649 | } |
2640 | rcu_read_unlock(); | ||
2641 | 2650 | ||
2642 | /* if we don't have a curr_active_slave, search for the next available | 2651 | /* if we don't have a curr_active_slave, search for the next available |
2643 | * backup slave from the current_arp_slave and make it the candidate | 2652 | * backup slave from the current_arp_slave and make it the candidate |
2644 | * for becoming the curr_active_slave | 2653 | * for becoming the curr_active_slave |
2645 | */ | 2654 | */ |
2646 | 2655 | ||
2647 | if (!rtnl_trylock()) | ||
2648 | return false; | ||
2649 | /* curr_arp_slave might have gone away */ | ||
2650 | curr_arp_slave = ACCESS_ONCE(bond->current_arp_slave); | ||
2651 | |||
2652 | if (!curr_arp_slave) { | 2656 | if (!curr_arp_slave) { |
2653 | curr_arp_slave = bond_first_slave(bond); | 2657 | curr_arp_slave = bond_first_slave_rcu(bond); |
2654 | if (!curr_arp_slave) { | 2658 | if (!curr_arp_slave) |
2655 | rtnl_unlock(); | 2659 | return should_notify_rtnl; |
2656 | return true; | ||
2657 | } | ||
2658 | } | 2660 | } |
2659 | 2661 | ||
2660 | bond_set_slave_inactive_flags(curr_arp_slave); | 2662 | bond_set_slave_inactive_flags(curr_arp_slave, BOND_SLAVE_NOTIFY_LATER); |
2661 | 2663 | ||
2662 | bond_for_each_slave(bond, slave, iter) { | 2664 | bond_for_each_slave_rcu(bond, slave, iter) { |
2663 | if (!found && !before && IS_UP(slave->dev)) | 2665 | if (!found && !before && IS_UP(slave->dev)) |
2664 | before = slave; | 2666 | before = slave; |
2665 | 2667 | ||
@@ -2677,7 +2679,8 @@ static bool bond_ab_arp_probe(struct bonding *bond) | |||
2677 | if (slave->link_failure_count < UINT_MAX) | 2679 | if (slave->link_failure_count < UINT_MAX) |
2678 | slave->link_failure_count++; | 2680 | slave->link_failure_count++; |
2679 | 2681 | ||
2680 | bond_set_slave_inactive_flags(slave); | 2682 | bond_set_slave_inactive_flags(slave, |
2683 | BOND_SLAVE_NOTIFY_LATER); | ||
2681 | 2684 | ||
2682 | pr_info("%s: backup interface %s is now down.\n", | 2685 | pr_info("%s: backup interface %s is now down.\n", |
2683 | bond->dev->name, slave->dev->name); | 2686 | bond->dev->name, slave->dev->name); |
@@ -2689,26 +2692,31 @@ static bool bond_ab_arp_probe(struct bonding *bond) | |||
2689 | if (!new_slave && before) | 2692 | if (!new_slave && before) |
2690 | new_slave = before; | 2693 | new_slave = before; |
2691 | 2694 | ||
2692 | if (!new_slave) { | 2695 | if (!new_slave) |
2693 | rtnl_unlock(); | 2696 | goto check_state; |
2694 | return true; | ||
2695 | } | ||
2696 | 2697 | ||
2697 | new_slave->link = BOND_LINK_BACK; | 2698 | new_slave->link = BOND_LINK_BACK; |
2698 | bond_set_slave_active_flags(new_slave); | 2699 | bond_set_slave_active_flags(new_slave, BOND_SLAVE_NOTIFY_LATER); |
2699 | bond_arp_send_all(bond, new_slave); | 2700 | bond_arp_send_all(bond, new_slave); |
2700 | new_slave->jiffies = jiffies; | 2701 | new_slave->jiffies = jiffies; |
2701 | rcu_assign_pointer(bond->current_arp_slave, new_slave); | 2702 | rcu_assign_pointer(bond->current_arp_slave, new_slave); |
2702 | rtnl_unlock(); | ||
2703 | 2703 | ||
2704 | return true; | 2704 | check_state: |
2705 | bond_for_each_slave_rcu(bond, slave, iter) { | ||
2706 | if (slave->should_notify) { | ||
2707 | should_notify_rtnl = BOND_SLAVE_NOTIFY_NOW; | ||
2708 | break; | ||
2709 | } | ||
2710 | } | ||
2711 | return should_notify_rtnl; | ||
2705 | } | 2712 | } |
2706 | 2713 | ||
2707 | static void bond_activebackup_arp_mon(struct work_struct *work) | 2714 | static void bond_activebackup_arp_mon(struct work_struct *work) |
2708 | { | 2715 | { |
2709 | struct bonding *bond = container_of(work, struct bonding, | 2716 | struct bonding *bond = container_of(work, struct bonding, |
2710 | arp_work.work); | 2717 | arp_work.work); |
2711 | bool should_notify_peers = false, should_commit = false; | 2718 | bool should_notify_peers = false; |
2719 | bool should_notify_rtnl = false; | ||
2712 | int delta_in_ticks; | 2720 | int delta_in_ticks; |
2713 | 2721 | ||
2714 | delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval); | 2722 | delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval); |
@@ -2717,11 +2725,12 @@ static void bond_activebackup_arp_mon(struct work_struct *work) | |||
2717 | goto re_arm; | 2725 | goto re_arm; |
2718 | 2726 | ||
2719 | rcu_read_lock(); | 2727 | rcu_read_lock(); |
2728 | |||
2720 | should_notify_peers = bond_should_notify_peers(bond); | 2729 | should_notify_peers = bond_should_notify_peers(bond); |
2721 | should_commit = bond_ab_arp_inspect(bond); | ||
2722 | rcu_read_unlock(); | ||
2723 | 2730 | ||
2724 | if (should_commit) { | 2731 | if (bond_ab_arp_inspect(bond)) { |
2732 | rcu_read_unlock(); | ||
2733 | |||
2725 | /* Race avoidance with bond_close flush of workqueue */ | 2734 | /* Race avoidance with bond_close flush of workqueue */ |
2726 | if (!rtnl_trylock()) { | 2735 | if (!rtnl_trylock()) { |
2727 | delta_in_ticks = 1; | 2736 | delta_in_ticks = 1; |
@@ -2730,23 +2739,28 @@ static void bond_activebackup_arp_mon(struct work_struct *work) | |||
2730 | } | 2739 | } |
2731 | 2740 | ||
2732 | bond_ab_arp_commit(bond); | 2741 | bond_ab_arp_commit(bond); |
2742 | |||
2733 | rtnl_unlock(); | 2743 | rtnl_unlock(); |
2744 | rcu_read_lock(); | ||
2734 | } | 2745 | } |
2735 | 2746 | ||
2736 | if (!bond_ab_arp_probe(bond)) { | 2747 | should_notify_rtnl = bond_ab_arp_probe(bond); |
2737 | /* rtnl locking failed, re-arm */ | 2748 | rcu_read_unlock(); |
2738 | delta_in_ticks = 1; | ||
2739 | should_notify_peers = false; | ||
2740 | } | ||
2741 | 2749 | ||
2742 | re_arm: | 2750 | re_arm: |
2743 | if (bond->params.arp_interval) | 2751 | if (bond->params.arp_interval) |
2744 | queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); | 2752 | queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); |
2745 | 2753 | ||
2746 | if (should_notify_peers) { | 2754 | if (should_notify_peers || should_notify_rtnl) { |
2747 | if (!rtnl_trylock()) | 2755 | if (!rtnl_trylock()) |
2748 | return; | 2756 | return; |
2749 | call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev); | 2757 | |
2758 | if (should_notify_peers) | ||
2759 | call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, | ||
2760 | bond->dev); | ||
2761 | if (should_notify_rtnl) | ||
2762 | bond_slave_state_notify(bond); | ||
2763 | |||
2750 | rtnl_unlock(); | 2764 | rtnl_unlock(); |
2751 | } | 2765 | } |
2752 | } | 2766 | } |
@@ -3046,9 +3060,11 @@ static int bond_open(struct net_device *bond_dev) | |||
3046 | bond_for_each_slave(bond, slave, iter) { | 3060 | bond_for_each_slave(bond, slave, iter) { |
3047 | if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP) | 3061 | if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP) |
3048 | && (slave != bond->curr_active_slave)) { | 3062 | && (slave != bond->curr_active_slave)) { |
3049 | bond_set_slave_inactive_flags(slave); | 3063 | bond_set_slave_inactive_flags(slave, |
3064 | BOND_SLAVE_NOTIFY_NOW); | ||
3050 | } else { | 3065 | } else { |
3051 | bond_set_slave_active_flags(slave); | 3066 | bond_set_slave_active_flags(slave, |
3067 | BOND_SLAVE_NOTIFY_NOW); | ||
3052 | } | 3068 | } |
3053 | } | 3069 | } |
3054 | read_unlock(&bond->curr_slave_lock); | 3070 | read_unlock(&bond->curr_slave_lock); |