aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2014-10-29 12:04:56 -0400
committerIngo Molnar <mingo@kernel.org>2014-11-04 01:17:48 -0500
commitff960a731788a7408b6f66ec4fd772ff18833211 (patch)
tree081795cb185495198e5966ea171e7701241775f1 /net
parenteedf7e47daa0b8530246a8c9107c007fbf8231bf (diff)
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 <fengguang.wu@intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: David S. Miller <davem@davemloft.net> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Cong Wang <cwang@twopensource.com> Cc: David Gibson <david@gibson.dropbear.id.au> Cc: Eric Biederman <ebiederm@xmission.com> Cc: Eric Dumazet <edumazet@google.com> Cc: Jamal Hadi Salim <jhs@mojatatu.com> Cc: Jerry Chu <hkchu@google.com> Cc: Jiri Pirko <jiri@resnulli.us> Cc: John Fastabend <john.fastabend@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com> Cc: sfeldma@cumulusnetworks.com <sfeldma@cumulusnetworks.com> Cc: stephen hemminger <stephen@networkplumber.org> Cc: Tom Gundersen <teg@jklm.no> Cc: Tom Herbert <therbert@google.com> Cc: Veaceslav Falico <vfalico@gmail.com> Cc: Vlad Yasevich <vyasevic@redhat.com> Cc: netdev@vger.kernel.org Link: http://lkml.kernel.org/r/20141029173110.GE15602@worktop.programming.kicks-ass.net Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c10
-rw-r--r--net/core/rtnetlink.c10
2 files changed, 10 insertions, 10 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index b793e3521a36..c5a9d73147a6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -7196,11 +7196,10 @@ static void __net_exit rtnl_lock_unregistering(struct list_head *net_list)
7196 */ 7196 */
7197 struct net *net; 7197 struct net *net;
7198 bool unregistering; 7198 bool unregistering;
7199 DEFINE_WAIT(wait); 7199 DEFINE_WAIT_FUNC(wait, woken_wake_function);
7200 7200
7201 add_wait_queue(&netdev_unregistering_wq, &wait);
7201 for (;;) { 7202 for (;;) {
7202 prepare_to_wait(&netdev_unregistering_wq, &wait,
7203 TASK_UNINTERRUPTIBLE);
7204 unregistering = false; 7203 unregistering = false;
7205 rtnl_lock(); 7204 rtnl_lock();
7206 list_for_each_entry(net, net_list, exit_list) { 7205 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)
7212 if (!unregistering) 7211 if (!unregistering)
7213 break; 7212 break;
7214 __rtnl_unlock(); 7213 __rtnl_unlock();
7215 schedule(); 7214
7215 wait_woken(&wait, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
7216 } 7216 }
7217 finish_wait(&netdev_unregistering_wq, &wait); 7217 remove_wait_queue(&netdev_unregistering_wq, &wait);
7218} 7218}
7219 7219
7220static void __net_exit default_device_exit_batch(struct list_head *net_list) 7220static void __net_exit default_device_exit_batch(struct list_head *net_list)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index a6882686ca3a..b095296f711f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -365,11 +365,10 @@ static void rtnl_lock_unregistering_all(void)
365{ 365{
366 struct net *net; 366 struct net *net;
367 bool unregistering; 367 bool unregistering;
368 DEFINE_WAIT(wait); 368 DEFINE_WAIT_FUNC(wait, woken_wake_function);
369 369
370 add_wait_queue(&netdev_unregistering_wq, &wait);
370 for (;;) { 371 for (;;) {
371 prepare_to_wait(&netdev_unregistering_wq, &wait,
372 TASK_UNINTERRUPTIBLE);
373 unregistering = false; 372 unregistering = false;
374 rtnl_lock(); 373 rtnl_lock();
375 for_each_net(net) { 374 for_each_net(net) {
@@ -381,9 +380,10 @@ static void rtnl_lock_unregistering_all(void)
381 if (!unregistering) 380 if (!unregistering)
382 break; 381 break;
383 __rtnl_unlock(); 382 __rtnl_unlock();
384 schedule(); 383
384 wait_woken(&wait, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
385 } 385 }
386 finish_wait(&netdev_unregistering_wq, &wait); 386 remove_wait_queue(&netdev_unregistering_wq, &wait);
387} 387}
388 388
389/** 389/**