Skip to content

Commit ff960a7

Browse files
Peter ZijlstraIngo Molnar
Peter Zijlstra
authored and
Ingo Molnar
committed
netdev, sched/wait: Fix sleeping inside wait event
rtnl_lock_unregistering*() take rtnl_lock() -- a mutex -- inside a wait loop. The wait loop relies on current->state to function, but so does mutex_lock(), nesting them makes for the inner to destroy the outer state. Fix this using the new wait_woken() bits. Reported-by: Fengguang Wu <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Acked-by: David S. Miller <[email protected]> Cc: Oleg Nesterov <[email protected]> Cc: Cong Wang <[email protected]> Cc: David Gibson <[email protected]> Cc: Eric Biederman <[email protected]> Cc: Eric Dumazet <[email protected]> Cc: Jamal Hadi Salim <[email protected]> Cc: Jerry Chu <[email protected]> Cc: Jiri Pirko <[email protected]> Cc: John Fastabend <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Nicolas Dichtel <[email protected]> Cc: [email protected] <[email protected]> Cc: stephen hemminger <[email protected]> Cc: Tom Gundersen <[email protected]> Cc: Tom Herbert <[email protected]> Cc: Veaceslav Falico <[email protected]> Cc: Vlad Yasevich <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent eedf7e4 commit ff960a7

File tree

2 files changed

+10
-10
lines changed

2 files changed

+10
-10
lines changed

net/core/dev.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7196,11 +7196,10 @@ static void __net_exit rtnl_lock_unregistering(struct list_head *net_list)
71967196
*/
71977197
struct net *net;
71987198
bool unregistering;
7199-
DEFINE_WAIT(wait);
7199+
DEFINE_WAIT_FUNC(wait, woken_wake_function);
72007200

7201+
add_wait_queue(&netdev_unregistering_wq, &wait);
72017202
for (;;) {
7202-
prepare_to_wait(&netdev_unregistering_wq, &wait,
7203-
TASK_UNINTERRUPTIBLE);
72047203
unregistering = false;
72057204
rtnl_lock();
72067205
list_for_each_entry(net, net_list, exit_list) {
@@ -7212,9 +7211,10 @@ static void __net_exit rtnl_lock_unregistering(struct list_head *net_list)
72127211
if (!unregistering)
72137212
break;
72147213
__rtnl_unlock();
7215-
schedule();
7214+
7215+
wait_woken(&wait, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
72167216
}
7217-
finish_wait(&netdev_unregistering_wq, &wait);
7217+
remove_wait_queue(&netdev_unregistering_wq, &wait);
72187218
}
72197219

72207220
static void __net_exit default_device_exit_batch(struct list_head *net_list)

net/core/rtnetlink.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -365,11 +365,10 @@ static void rtnl_lock_unregistering_all(void)
365365
{
366366
struct net *net;
367367
bool unregistering;
368-
DEFINE_WAIT(wait);
368+
DEFINE_WAIT_FUNC(wait, woken_wake_function);
369369

370+
add_wait_queue(&netdev_unregistering_wq, &wait);
370371
for (;;) {
371-
prepare_to_wait(&netdev_unregistering_wq, &wait,
372-
TASK_UNINTERRUPTIBLE);
373372
unregistering = false;
374373
rtnl_lock();
375374
for_each_net(net) {
@@ -381,9 +380,10 @@ static void rtnl_lock_unregistering_all(void)
381380
if (!unregistering)
382381
break;
383382
__rtnl_unlock();
384-
schedule();
383+
384+
wait_woken(&wait, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
385385
}
386-
finish_wait(&netdev_unregistering_wq, &wait);
386+
remove_wait_queue(&netdev_unregistering_wq, &wait);
387387
}
388388

389389
/**

0 commit comments

Comments
 (0)