From: Pavel Emelyanov Date: Sat, 3 May 2008 00:49:39 +0000 (-0700) Subject: bonding: Deadlock between bonding_store_bonds and bond_destroy_sysfs. X-Git-Tag: v2.6.26-rc2~23^2~2^2~17 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ae68c39819ddf30549652962768a50edae5eec6f;p=linux-2.6 bonding: Deadlock between bonding_store_bonds and bond_destroy_sysfs. The sysfs layer has an internal protection, that ensures, that all the process sitting inside ->sore/->show callback exits before the appropriate entry is unregistered (the calltraces are rather big, but I can provide them if required). On the other hand, bonding takes rtnl_lock in a) the bonding_store_bonds, i.e. in ->store callback, b) module exit before calling the sysfs unregister routines. Thus, the classical AB-BA deadlock may occur. To reproduce run # while :; do modprobe bonding; rmmod bonding; done and # while :; do echo '+bond%d' > /sys/class/net/bonding_masters ; done in parallel. The fix is to move the bond_destroy_sysfs out of the rtnl_lock, but _before_ bond_free_all to make sure no bonding devices exist after module unload. Signed-off-by: Pavel Emelyanov Acked-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 5509732d3f..e41b3e5726 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4992,9 +4992,10 @@ err: destroy_workqueue(bond->wq); } + bond_destroy_sysfs(); + rtnl_lock(); bond_free_all(); - bond_destroy_sysfs(); rtnl_unlock(); out: return res; @@ -5006,9 +5007,10 @@ static void __exit bonding_exit(void) unregister_netdevice_notifier(&bond_netdev_notifier); unregister_inetaddr_notifier(&bond_inetaddr_notifier); + bond_destroy_sysfs(); + rtnl_lock(); bond_free_all(); - bond_destroy_sysfs(); rtnl_unlock(); }