mirror of
https://github.com/torvalds/linux.git
synced 2026-06-10 07:32:29 +02:00
netconsole: don't call __netpoll_cleanup() while atomic
[ Upstream commit 3f315bef23 ]
__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: Veaceslav Falico <vfalico@redhat.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
7436bcf615
commit
b52f06719c
|
|
@ -626,6 +626,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) {
|
||||
|
|
@ -637,21 +638,18 @@ static int netconsole_netdev_event(struct notifier_block *this,
|
|||
case NETDEV_JOIN:
|
||||
case NETDEV_UNREGISTER:
|
||||
/*
|
||||
* we might sleep in __netpoll_cleanup()
|
||||
* 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;
|
||||
}
|
||||
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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user