@@ -2599,41 +2599,51 @@ static void bond_ab_arp_commit(struct bonding *bond)
2599
2599
2600
2600
/*
2601
2601
* Send ARP probes for active-backup mode ARP monitor.
2602
- *
2603
- * Called with rcu_read_lock hold.
2604
2602
*/
2605
- static void bond_ab_arp_probe (struct bonding * bond )
2603
+ static bool bond_ab_arp_probe (struct bonding * bond )
2606
2604
{
2607
2605
struct slave * slave , * before = NULL , * new_slave = NULL ,
2608
- * curr_arp_slave = rcu_dereference (bond -> current_arp_slave ),
2609
- * curr_active_slave = rcu_dereference (bond -> curr_active_slave );
2606
+ * curr_arp_slave , * curr_active_slave ;
2610
2607
struct list_head * iter ;
2611
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
2614
if (curr_arp_slave && curr_active_slave )
2614
2615
pr_info ("PROBE: c_arp %s && cas %s BAD\n" ,
2615
2616
curr_arp_slave -> dev -> name ,
2616
2617
curr_active_slave -> dev -> name );
2617
2618
2618
2619
if (curr_active_slave ) {
2619
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
2626
/* if we don't have a curr_active_slave, search for the next available
2624
2627
* backup slave from the current_arp_slave and make it the candidate
2625
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
2636
if (!curr_arp_slave ) {
2629
- curr_arp_slave = bond_first_slave_rcu (bond );
2630
- if (!curr_arp_slave )
2631
- return ;
2637
+ curr_arp_slave = bond_first_slave (bond );
2638
+ if (!curr_arp_slave ) {
2639
+ rtnl_unlock ();
2640
+ return true;
2641
+ }
2632
2642
}
2633
2643
2634
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
2647
if (!found && !before && IS_UP (slave -> dev ))
2638
2648
before = slave ;
2639
2649
@@ -2663,21 +2673,26 @@ static void bond_ab_arp_probe(struct bonding *bond)
2663
2673
if (!new_slave && before )
2664
2674
new_slave = before ;
2665
2675
2666
- if (!new_slave )
2667
- return ;
2676
+ if (!new_slave ) {
2677
+ rtnl_unlock ();
2678
+ return true;
2679
+ }
2668
2680
2669
2681
new_slave -> link = BOND_LINK_BACK ;
2670
2682
bond_set_slave_active_flags (new_slave );
2671
2683
bond_arp_send_all (bond , new_slave );
2672
2684
new_slave -> jiffies = jiffies ;
2673
2685
rcu_assign_pointer (bond -> current_arp_slave , new_slave );
2686
+ rtnl_unlock ();
2687
+
2688
+ return true;
2674
2689
}
2675
2690
2676
2691
static void bond_activebackup_arp_mon (struct work_struct * work )
2677
2692
{
2678
2693
struct bonding * bond = container_of (work , struct bonding ,
2679
2694
arp_work .work );
2680
- bool should_notify_peers = false;
2695
+ bool should_notify_peers = false, should_commit = false ;
2681
2696
int delta_in_ticks ;
2682
2697
2683
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
2701
goto re_arm ;
2687
2702
2688
2703
rcu_read_lock ();
2689
-
2690
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 )) {
2693
- rcu_read_unlock ();
2694
-
2708
+ if (should_commit ) {
2695
2709
/* Race avoidance with bond_close flush of workqueue */
2696
2710
if (!rtnl_trylock ()) {
2697
2711
delta_in_ticks = 1 ;
@@ -2700,13 +2714,14 @@ static void bond_activebackup_arp_mon(struct work_struct *work)
2700
2714
}
2701
2715
2702
2716
bond_ab_arp_commit (bond );
2703
-
2704
2717
rtnl_unlock ();
2705
- rcu_read_lock ();
2706
2718
}
2707
2719
2708
- bond_ab_arp_probe (bond );
2709
- rcu_read_unlock ();
2720
+ if (!bond_ab_arp_probe (bond )) {
2721
+ /* rtnl locking failed, re-arm */
2722
+ delta_in_ticks = 1 ;
2723
+ should_notify_peers = false;
2724
+ }
2710
2725
2711
2726
re_arm :
2712
2727
if (bond -> params .arp_interval )
0 commit comments