Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f315bef authored by Veaceslav Falico's avatar Veaceslav Falico Committed by David S. Miller
Browse files

netconsole: don't call __netpoll_cleanup() while atomic



__netpoll_cleanup() is called in netconsole_netdev_event() while holding a
spinlock. Release/acquire the spinlock before/after it and restart the
loop. Also, disable the netconsole completely, because we won't have chance
after the restart of the loop, and might end up in a situation where
nt->enabled == 1 and nt->np.dev == NULL.

Signed-off-by: default avatarVeaceslav Falico <vfalico@redhat.com>
Acked-by: default avatarNeil Horman <nhorman@tuxdriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3da889b6
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -666,6 +666,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) {
@@ -678,15 +679,17 @@ static int netconsole_netdev_event(struct notifier_block *this,
			case NETDEV_UNREGISTER:
				/*
				 * rtnl_lock already held
				 * we might sleep in __netpoll_cleanup()
				 */
				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;
				}
				nt->enabled = 0;
				stopped = true;
				break;
				netconsole_target_put(nt);
				goto restart;
			}
		}
		netconsole_target_put(nt);