[kernel/f15/master] Fix deadlock in netconsoles netdev notifier handler function

Neil Horman nhorman at fedoraproject.org
Mon Apr 25 16:05:01 UTC 2011


commit cb4a4c8907f97b2a41d24ea81ee12303ee818fa3
Author: Neil Horman <nhorman at tuxdriver.com>
Date:   Mon Apr 25 12:04:09 2011 -0400

    Fix deadlock in netconsoles netdev notifier handler function
    
    Resolves: bz 668231

 kernel.spec                         |    9 +++++
 linux-2.6-netconsole-deadlock.patch |   56 +++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+), 0 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index bed7d28..d94c7e4 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -726,6 +726,9 @@ Patch12306: scsi-sd-downgrade-caching-printk-from-error-to-notice.patch
 
 Patch12307: iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch
 
+#netconsole fixes
+Patch12400: linux-2.6-netconsole-deadlock.patch
+
 %endif
 
 BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@@ -1348,6 +1351,9 @@ ApplyPatch printk-do-not-mangle-valid-userspace-syslog-prefixes.patch
 
 ApplyPatch scsi-sd-downgrade-caching-printk-from-error-to-notice.patch
 
+#rhbz 668231
+ApplyPatch linux-2.6-netconsole-deadlock.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -1956,6 +1962,9 @@ fi
 # and build.
 
 %changelog
+* Mon Apr 25 2011 Neil Horman <nhorman at redhat.com>
+- netconsole: fix deadlock in netdev notifier handler
+
 * Sun Apr 24 2011 Kyle McMartin <kmcmartin at redhat.com>
 - ppc64: disable TUNE_CELL, which causes problems with illegal instuctions
   being generated on non-Cell PPC machines. (#698256)
diff --git a/linux-2.6-netconsole-deadlock.patch b/linux-2.6-netconsole-deadlock.patch
new file mode 100644
index 0000000..677ed76
--- /dev/null
+++ b/linux-2.6-netconsole-deadlock.patch
@@ -0,0 +1,56 @@
+commit 13f172ff26563995049abe73f6eeba828de3c09d
+Author: Neil Horman <nhorman at tuxdriver.com>
+Date:   Fri Apr 22 08:10:59 2011 +0000
+
+    netconsole: fix deadlock when removing net driver that netconsole is using (v2)
+    
+    A deadlock was reported to me recently that occured when netconsole was being
+    used in a virtual guest.  If the virtio_net driver was removed while netconsole
+    was setup to use an interface that was driven by that driver, the guest
+    deadlocked.  No backtrace was provided because netconsole was the only console
+    configured, but it became clear pretty quickly what the problem was.  In
+    netconsole_netdev_event, if we get an unregister event, we call
+    __netpoll_cleanup with the target_list_lock held and irqs disabled.
+    __netpoll_cleanup can, if pending netpoll packets are waiting call
+    cancel_delayed_work_sync, which is a sleeping path.  the might_sleep call in
+    that path gets triggered, causing a console warning to be issued.  The
+    netconsole write handler of course tries to take the target_list_lock again,
+    which we already hold, causing deadlock.
+    
+    The fix is pretty striaghtforward.  Simply drop the target_list_lock and
+    re-enable irqs prior to calling __netpoll_cleanup, the re-acquire the lock, and
+    restart the loop.  Confirmed by myself to fix the problem reported.
+    
+    Signed-off-by: Neil Horman <nhorman at tuxdriver.com>
+    CC: "David S. Miller" <davem at davemloft.net>
+    Signed-off-by: David S. Miller <davem at davemloft.net>
+
+diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
+index dfb67eb..eb41e44 100644
+--- a/drivers/net/netconsole.c
++++ b/drivers/net/netconsole.c
+@@ -671,6 +671,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
+ 		goto done;
+ 
+ 	spin_lock_irqsave(&target_list_lock, flags);
++restart:
+ 	list_for_each_entry(nt, &target_list, list) {
+ 		netconsole_target_get(nt);
+ 		if (nt->np.dev == dev) {
+@@ -683,9 +684,16 @@ static int netconsole_netdev_event(struct notifier_block *this,
+ 				 * rtnl_lock already held
+ 				 */
+ 				if (nt->np.dev) {
++					spin_unlock_irqrestore(
++							      &target_list_lock,
++							      flags);
+ 					__netpoll_cleanup(&nt->np);
++					spin_lock_irqsave(&target_list_lock,
++							  flags);
+ 					dev_put(nt->np.dev);
+ 					nt->np.dev = NULL;
++					netconsole_target_put(nt);
++					goto restart;
+ 				}
+ 				/* Fall through */
+ 			case NETDEV_GOING_DOWN:


More information about the scm-commits mailing list