diff --git a/kernel.spec b/kernel.spec index bed7d28b1..d94c7e459 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 +- netconsole: fix deadlock in netdev notifier handler + * Sun Apr 24 2011 Kyle McMartin - 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 000000000..677ed760b --- /dev/null +++ b/linux-2.6-netconsole-deadlock.patch @@ -0,0 +1,56 @@ +commit 13f172ff26563995049abe73f6eeba828de3c09d +Author: Neil Horman +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 + CC: "David S. Miller" + Signed-off-by: David S. Miller + +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: