summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeffy Chen <jeffy.chen@rock-chips.com>2017-06-27 05:34:42 -0400
committerMarcel Holtmann <marcel@holtmann.org>2017-06-27 13:32:11 -0400
commit25717382c1dd0ddced2059053e3ca5088665f7a5 (patch)
treeffe5af4a8f3d9b254f0575dd57eae84a78f46fb7
parentcdd24a200a8fa39e383890bbf862c0aa83ba83f5 (diff)
Bluetooth: bnep: fix possible might sleep error in bnep_session
It looks like bnep_session has same pattern as the issue reported in old rfcomm: while (1) { set_current_state(TASK_INTERRUPTIBLE); if (condition) break; // may call might_sleep here schedule(); } __set_current_state(TASK_RUNNING); Which fixed at: dfb2fae Bluetooth: Fix nested sleeps So let's fix it at the same way, also follow the suggestion of: https://lwn.net/Articles/628628/ Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> Reviewed-by: Brian Norris <briannorris@chromium.org> Reviewed-by: AL Yu-Chen Cho <acho@suse.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--net/bluetooth/bnep/core.c11
1 files changed, 5 insertions, 6 deletions
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 9a40013da915..7b3965861013 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -481,16 +481,16 @@ static int bnep_session(void *arg)
481 struct net_device *dev = s->dev; 481 struct net_device *dev = s->dev;
482 struct sock *sk = s->sock->sk; 482 struct sock *sk = s->sock->sk;
483 struct sk_buff *skb; 483 struct sk_buff *skb;
484 wait_queue_t wait; 484 DEFINE_WAIT_FUNC(wait, woken_wake_function);
485 485
486 BT_DBG(""); 486 BT_DBG("");
487 487
488 set_user_nice(current, -15); 488 set_user_nice(current, -15);
489 489
490 init_waitqueue_entry(&wait, current);
491 add_wait_queue(sk_sleep(sk), &wait); 490 add_wait_queue(sk_sleep(sk), &wait);
492 while (1) { 491 while (1) {
493 set_current_state(TASK_INTERRUPTIBLE); 492 /* Ensure session->terminate is updated */
493 smp_mb__before_atomic();
494 494
495 if (atomic_read(&s->terminate)) 495 if (atomic_read(&s->terminate))
496 break; 496 break;
@@ -512,9 +512,8 @@ static int bnep_session(void *arg)
512 break; 512 break;
513 netif_wake_queue(dev); 513 netif_wake_queue(dev);
514 514
515 schedule(); 515 wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
516 } 516 }
517 __set_current_state(TASK_RUNNING);
518 remove_wait_queue(sk_sleep(sk), &wait); 517 remove_wait_queue(sk_sleep(sk), &wait);
519 518
520 /* Cleanup session */ 519 /* Cleanup session */
@@ -663,7 +662,7 @@ int bnep_del_connection(struct bnep_conndel_req *req)
663 s = __bnep_get_session(req->dst); 662 s = __bnep_get_session(req->dst);
664 if (s) { 663 if (s) {
665 atomic_inc(&s->terminate); 664 atomic_inc(&s->terminate);
666 wake_up_process(s->task); 665 wake_up_interruptible(sk_sleep(s->sock->sk));
667 } else 666 } else
668 err = -ENOENT; 667 err = -ENOENT;
669 668