aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVeaceslav Falico <vfalico@redhat.com>2014-01-27 08:37:32 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-27 16:12:45 -0500
commitf2ebd477f141bc09b10fb8deb612a4d9b8999bba (patch)
tree097d2f21d367ae28eaa40fc5d1ee9519f8932687
parent98b90f26651f9d84cfbb0221c9a3d9863c5bea69 (diff)
bonding: restructure locking of bond_ab_arp_probe()
Currently we're calling it from under RCU context, however we're using some functions that require rtnl to be held. Fix this by restructuring the locking - don't call it under any locks, aquire rcu_read_lock() if we're sending _only_ (i.e. we have the active slave present), and use rtnl locking otherwise - if we need to modify (in)active flags of a slave. CC: Jay Vosburgh <fubar@us.ibm.com> CC: Andy Gospodarek <andy@greyhouse.net> Signed-off-by: Veaceslav Falico <vfalico@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/bonding/bond_main.c57
1 files changed, 36 insertions, 21 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 27e6fddb2206..dd75615d85f2 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2599,17 +2599,18 @@ do_failover:
2599 2599
2600/* 2600/*
2601 * Send ARP probes for active-backup mode ARP monitor. 2601 * Send ARP probes for active-backup mode ARP monitor.
2602 *
2603 * Called with rcu_read_lock hold.
2604 */ 2602 */
2605static void bond_ab_arp_probe(struct bonding *bond) 2603static bool bond_ab_arp_probe(struct bonding *bond)
2606{ 2604{
2607 struct slave *slave, *before = NULL, *new_slave = NULL, 2605 struct slave *slave, *before = NULL, *new_slave = NULL,
2608 *curr_arp_slave = rcu_dereference(bond->current_arp_slave), 2606 *curr_arp_slave, *curr_active_slave;
2609 *curr_active_slave = rcu_dereference(bond->curr_active_slave);
2610 struct list_head *iter; 2607 struct list_head *iter;
2611 bool found = false; 2608 bool found = false;
2612 2609
2610 rcu_read_lock();
2611 curr_arp_slave = rcu_dereference(bond->current_arp_slave);
2612 curr_active_slave = rcu_dereference(bond->curr_active_slave);
2613
2613 if (curr_arp_slave && curr_active_slave) 2614 if (curr_arp_slave && curr_active_slave)
2614 pr_info("PROBE: c_arp %s && cas %s BAD\n", 2615 pr_info("PROBE: c_arp %s && cas %s BAD\n",
2615 curr_arp_slave->dev->name, 2616 curr_arp_slave->dev->name,
@@ -2617,23 +2618,32 @@ static void bond_ab_arp_probe(struct bonding *bond)
2617 2618
2618 if (curr_active_slave) { 2619 if (curr_active_slave) {
2619 bond_arp_send_all(bond, curr_active_slave); 2620 bond_arp_send_all(bond, curr_active_slave);
2620 return; 2621 rcu_read_unlock();
2622 return true;
2621 } 2623 }
2624 rcu_read_unlock();
2622 2625
2623 /* if we don't have a curr_active_slave, search for the next available 2626 /* if we don't have a curr_active_slave, search for the next available
2624 * backup slave from the current_arp_slave and make it the candidate 2627 * backup slave from the current_arp_slave and make it the candidate
2625 * for becoming the curr_active_slave 2628 * for becoming the curr_active_slave
2626 */ 2629 */
2627 2630
2631 if (!rtnl_trylock())
2632 return false;
2633 /* curr_arp_slave might have gone away */
2634 curr_arp_slave = ACCESS_ONCE(bond->current_arp_slave);
2635
2628 if (!curr_arp_slave) { 2636 if (!curr_arp_slave) {
2629 curr_arp_slave = bond_first_slave_rcu(bond); 2637 curr_arp_slave = bond_first_slave(bond);
2630 if (!curr_arp_slave) 2638 if (!curr_arp_slave) {
2631 return; 2639 rtnl_unlock();
2640 return true;
2641 }
2632 } 2642 }
2633 2643
2634 bond_set_slave_inactive_flags(curr_arp_slave); 2644 bond_set_slave_inactive_flags(curr_arp_slave);
2635 2645
2636 bond_for_each_slave_rcu(bond, slave, iter) { 2646 bond_for_each_slave(bond, slave, iter) {
2637 if (!found && !before && IS_UP(slave->dev)) 2647 if (!found && !before && IS_UP(slave->dev))
2638 before = slave; 2648 before = slave;
2639 2649
@@ -2663,21 +2673,26 @@ static void bond_ab_arp_probe(struct bonding *bond)
2663 if (!new_slave && before) 2673 if (!new_slave && before)
2664 new_slave = before; 2674 new_slave = before;
2665 2675
2666 if (!new_slave) 2676 if (!new_slave) {
2667 return; 2677 rtnl_unlock();
2678 return true;
2679 }
2668 2680
2669 new_slave->link = BOND_LINK_BACK; 2681 new_slave->link = BOND_LINK_BACK;
2670 bond_set_slave_active_flags(new_slave); 2682 bond_set_slave_active_flags(new_slave);
2671 bond_arp_send_all(bond, new_slave); 2683 bond_arp_send_all(bond, new_slave);
2672 new_slave->jiffies = jiffies; 2684 new_slave->jiffies = jiffies;
2673 rcu_assign_pointer(bond->current_arp_slave, new_slave); 2685 rcu_assign_pointer(bond->current_arp_slave, new_slave);
2686 rtnl_unlock();
2687
2688 return true;
2674} 2689}
2675 2690
2676static void bond_activebackup_arp_mon(struct work_struct *work) 2691static void bond_activebackup_arp_mon(struct work_struct *work)
2677{ 2692{
2678 struct bonding *bond = container_of(work, struct bonding, 2693 struct bonding *bond = container_of(work, struct bonding,
2679 arp_work.work); 2694 arp_work.work);
2680 bool should_notify_peers = false; 2695 bool should_notify_peers = false, should_commit = false;
2681 int delta_in_ticks; 2696 int delta_in_ticks;
2682 2697
2683 delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval); 2698 delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
@@ -2686,12 +2701,11 @@ static void bond_activebackup_arp_mon(struct work_struct *work)
2686 goto re_arm; 2701 goto re_arm;
2687 2702
2688 rcu_read_lock(); 2703 rcu_read_lock();
2689
2690 should_notify_peers = bond_should_notify_peers(bond); 2704 should_notify_peers = bond_should_notify_peers(bond);
2705 should_commit = bond_ab_arp_inspect(bond);
2706 rcu_read_unlock();
2691 2707
2692 if (bond_ab_arp_inspect(bond)) { 2708 if (should_commit) {
2693 rcu_read_unlock();
2694
2695 /* Race avoidance with bond_close flush of workqueue */ 2709 /* Race avoidance with bond_close flush of workqueue */
2696 if (!rtnl_trylock()) { 2710 if (!rtnl_trylock()) {
2697 delta_in_ticks = 1; 2711 delta_in_ticks = 1;
@@ -2700,13 +2714,14 @@ static void bond_activebackup_arp_mon(struct work_struct *work)
2700 } 2714 }
2701 2715
2702 bond_ab_arp_commit(bond); 2716 bond_ab_arp_commit(bond);
2703
2704 rtnl_unlock(); 2717 rtnl_unlock();
2705 rcu_read_lock();
2706 } 2718 }
2707 2719
2708 bond_ab_arp_probe(bond); 2720 if (!bond_ab_arp_probe(bond)) {
2709 rcu_read_unlock(); 2721 /* rtnl locking failed, re-arm */
2722 delta_in_ticks = 1;
2723 should_notify_peers = false;
2724 }
2710 2725
2711re_arm: 2726re_arm:
2712 if (bond->params.arp_interval) 2727 if (bond->params.arp_interval)