Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

bonding: properly stop queuing work when requested

During a test where a pair of bonding interfaces using ARP monitoring
were both brought up and torn down (with an rmmod) repeatedly, a panic
in the timer code was noticed. I tracked this down and determined that
any of the bonding functions that ran as workqueue handlers and requeued
more work might not properly exit when the module was removed.

There was a flag protected by the bond lock called kill_timers that is
set when the interface goes down or the module is removed, but many of
the functions that monitor link status now unlock the bond lock to take
rtnl first. There is a chance that another CPU running the rmmod could
get the lock and set kill_timers after the first check has passed.

This patch does not allow any function to queue work that will make
itself run unless kill_timers is not set. I also noticed while doing
this work that bond_resend_igmp_join_requests did not have a check for
kill_timers, so I added the needed call there as well.

Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
Reported-by: Liang Zheng <lzheng@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Andy Gospodarek and committed by
David S. Miller
a0db2dad 12d0d0d3

+12 -7
+2 -1
drivers/net/bonding/bond_3ad.c
··· 2168 2168 } 2169 2169 2170 2170 re_arm: 2171 - queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks); 2171 + if (!bond->kill_timers) 2172 + queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks); 2172 2173 out: 2173 2174 read_unlock(&bond->lock); 2174 2175 }
+2 -1
drivers/net/bonding/bond_alb.c
··· 1440 1440 } 1441 1441 1442 1442 re_arm: 1443 - queue_delayed_work(bond->wq, &bond->alb_work, alb_delta_in_ticks); 1443 + if (!bond->kill_timers) 1444 + queue_delayed_work(bond->wq, &bond->alb_work, alb_delta_in_ticks); 1444 1445 out: 1445 1446 read_unlock(&bond->lock); 1446 1447 }
+8 -5
drivers/net/bonding/bond_main.c
··· 777 777 778 778 read_lock(&bond->lock); 779 779 780 + if (bond->kill_timers) 781 + goto out; 782 + 780 783 /* rejoin all groups on bond device */ 781 784 __bond_resend_igmp_join_requests(bond->dev); 782 785 ··· 793 790 __bond_resend_igmp_join_requests(vlan_dev); 794 791 } 795 792 796 - if (--bond->igmp_retrans > 0) 793 + if ((--bond->igmp_retrans > 0) && !bond->kill_timers) 797 794 queue_delayed_work(bond->wq, &bond->mcast_work, HZ/5); 798 - 795 + out: 799 796 read_unlock(&bond->lock); 800 797 } 801 798 ··· 2541 2538 } 2542 2539 2543 2540 re_arm: 2544 - if (bond->params.miimon) 2541 + if (bond->params.miimon && !bond->kill_timers) 2545 2542 queue_delayed_work(bond->wq, &bond->mii_work, 2546 2543 msecs_to_jiffies(bond->params.miimon)); 2547 2544 out: ··· 2889 2886 } 2890 2887 2891 2888 re_arm: 2892 - if (bond->params.arp_interval) 2889 + if (bond->params.arp_interval && !bond->kill_timers) 2893 2890 queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); 2894 2891 out: 2895 2892 read_unlock(&bond->lock); ··· 3157 3154 bond_ab_arp_probe(bond); 3158 3155 3159 3156 re_arm: 3160 - if (bond->params.arp_interval) 3157 + if (bond->params.arp_interval && !bond->kill_timers) 3161 3158 queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); 3162 3159 out: 3163 3160 read_unlock(&bond->lock);