Commit-ID: ff960a731788a7408b6f66ec4fd772ff18833211 Gitweb: http://git.kernel.org/tip/ff960a731788a7408b6f66ec4fd772ff18833211 Author: Peter Zijlstra <peterz@xxxxxxxxxxxxx> AuthorDate: Wed, 29 Oct 2014 17:04:56 +0100 Committer: Ingo Molnar <mingo@xxxxxxxxxx> CommitDate: Tue, 4 Nov 2014 07:17:48 +0100 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@xxxxxxxxx> Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx> Acked-by: David S. Miller <davem@xxxxxxxxxxxxx> Cc: Oleg Nesterov <oleg@xxxxxxxxxx> Cc: Cong Wang <cwang@xxxxxxxxxxxxxxxx> Cc: David Gibson <david@xxxxxxxxxxxxxxxxxxxxx> Cc: Eric Biederman <ebiederm@xxxxxxxxxxxx> Cc: Eric Dumazet <edumazet@xxxxxxxxxx> Cc: Jamal Hadi Salim <jhs@xxxxxxxxxxxx> Cc: Jerry Chu <hkchu@xxxxxxxxxx> Cc: Jiri Pirko <jiri@xxxxxxxxxxx> Cc: John Fastabend <john.fastabend@xxxxxxxxx> Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> Cc: Nicolas Dichtel <nicolas.dichtel@xxxxxxxxx> Cc: sfeldma@xxxxxxxxxxxxxxxxxxx <sfeldma@xxxxxxxxxxxxxxxxxxx> Cc: stephen hemminger <stephen@xxxxxxxxxxxxxxxxxx> Cc: Tom Gundersen <teg@xxxxxxx> Cc: Tom Herbert <therbert@xxxxxxxxxx> Cc: Veaceslav Falico <vfalico@xxxxxxxxx> Cc: Vlad Yasevich <vyasevic@xxxxxxxxxx> Cc: netdev@xxxxxxxxxxxxxxx Link: http://lkml.kernel.org/r/20141029173110.GE15602@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Signed-off-by: Ingo Molnar <mingo@xxxxxxxxxx> --- net/core/dev.c | 10 +++++----- net/core/rtnetlink.c | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index b793e35..c5a9d73 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) */ struct net *net; bool unregistering; - DEFINE_WAIT(wait); + DEFINE_WAIT_FUNC(wait, woken_wake_function); + add_wait_queue(&netdev_unregistering_wq, &wait); for (;;) { - prepare_to_wait(&netdev_unregistering_wq, &wait, - TASK_UNINTERRUPTIBLE); unregistering = false; rtnl_lock(); 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) if (!unregistering) break; __rtnl_unlock(); - schedule(); + + wait_woken(&wait, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); } - finish_wait(&netdev_unregistering_wq, &wait); + remove_wait_queue(&netdev_unregistering_wq, &wait); } static 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 a688268..b095296 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -365,11 +365,10 @@ static void rtnl_lock_unregistering_all(void) { struct net *net; bool unregistering; - DEFINE_WAIT(wait); + DEFINE_WAIT_FUNC(wait, woken_wake_function); + add_wait_queue(&netdev_unregistering_wq, &wait); for (;;) { - prepare_to_wait(&netdev_unregistering_wq, &wait, - TASK_UNINTERRUPTIBLE); unregistering = false; rtnl_lock(); for_each_net(net) { @@ -381,9 +380,10 @@ static void rtnl_lock_unregistering_all(void) if (!unregistering) break; __rtnl_unlock(); - schedule(); + + wait_woken(&wait, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); } - finish_wait(&netdev_unregistering_wq, &wait); + remove_wait_queue(&netdev_unregistering_wq, &wait); } /** -- To unsubscribe from this list: send the line "unsubscribe linux-tip-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html
![]() |