aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2015-01-23 12:16:53 -0500
committerJohan Hedberg <johan.hedberg@intel.com>2015-01-23 13:29:42 -0500
commitdfb2fae7cd0a1aa13610b11d54203bcd3893da07 (patch)
tree3aa293285c349233441ae31661c72773992e603e /net/bluetooth
parenta1443f5a273713d4bfda360e45aa6e1d14fe7324 (diff)
Bluetooth: Fix nested sleeps
l2cap/rfcomm/sco_sock_accept() are wait loops which may acquire sleeping locks. Since both wait loops and sleeping locks use task_struct.state to sleep and wake, the nested sleeping locks destroy the wait loop state. Use the newly-minted wait_woken() and DEFINE_WAIT_FUNC() for the wait loop. DEFINE_WAIT_FUNC() allows an alternate wake function to be specified; in this case, the predefined scheduler function, woken_wake_function(). This wait construct ensures wakeups will not be missed without requiring the wait loop to set the task state before condition evaluation. How this works: CPU 0 | CPU 1 | | is <condition> set? | no set <condition> | | wake_up_interruptible | woken_wake_function | set WQ_FLAG_WOKEN | try_to_wake_up | | wait_woken | set TASK_INTERRUPTIBLE | WQ_FLAG_WOKEN? yes | set TASK_RUNNING | | - loop - | | is <condition> set? | yes - exit wait loop Fixes "do not call blocking ops when !TASK_RUNNING" warnings in l2cap_sock_accept(), rfcomm_sock_accept() and sco_sock_accept(). Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/l2cap_sock.c9
-rw-r--r--net/bluetooth/rfcomm/sock.c9
-rw-r--r--net/bluetooth/sco.c8
3 files changed, 11 insertions, 15 deletions
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 20206cd3acbc..60694f0f4c73 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -302,7 +302,7 @@ done:
302static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, 302static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
303 int flags) 303 int flags)
304{ 304{
305 DECLARE_WAITQUEUE(wait, current); 305 DEFINE_WAIT_FUNC(wait, woken_wake_function);
306 struct sock *sk = sock->sk, *nsk; 306 struct sock *sk = sock->sk, *nsk;
307 long timeo; 307 long timeo;
308 int err = 0; 308 int err = 0;
@@ -316,8 +316,6 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
316 /* Wait for an incoming connection. (wake-one). */ 316 /* Wait for an incoming connection. (wake-one). */
317 add_wait_queue_exclusive(sk_sleep(sk), &wait); 317 add_wait_queue_exclusive(sk_sleep(sk), &wait);
318 while (1) { 318 while (1) {
319 set_current_state(TASK_INTERRUPTIBLE);
320
321 if (sk->sk_state != BT_LISTEN) { 319 if (sk->sk_state != BT_LISTEN) {
322 err = -EBADFD; 320 err = -EBADFD;
323 break; 321 break;
@@ -338,10 +336,11 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
338 } 336 }
339 337
340 release_sock(sk); 338 release_sock(sk);
341 timeo = schedule_timeout(timeo); 339
340 timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
341
342 lock_sock_nested(sk, L2CAP_NESTING_PARENT); 342 lock_sock_nested(sk, L2CAP_NESTING_PARENT);
343 } 343 }
344 __set_current_state(TASK_RUNNING);
345 remove_wait_queue(sk_sleep(sk), &wait); 344 remove_wait_queue(sk_sleep(sk), &wait);
346 345
347 if (err) 346 if (err)
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index d8a95755a8a8..3c6d2c8ac1a4 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -468,7 +468,7 @@ done:
468 468
469static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags) 469static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags)
470{ 470{
471 DECLARE_WAITQUEUE(wait, current); 471 DEFINE_WAIT_FUNC(wait, woken_wake_function);
472 struct sock *sk = sock->sk, *nsk; 472 struct sock *sk = sock->sk, *nsk;
473 long timeo; 473 long timeo;
474 int err = 0; 474 int err = 0;
@@ -487,8 +487,6 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
487 /* Wait for an incoming connection. (wake-one). */ 487 /* Wait for an incoming connection. (wake-one). */
488 add_wait_queue_exclusive(sk_sleep(sk), &wait); 488 add_wait_queue_exclusive(sk_sleep(sk), &wait);
489 while (1) { 489 while (1) {
490 set_current_state(TASK_INTERRUPTIBLE);
491
492 if (sk->sk_state != BT_LISTEN) { 490 if (sk->sk_state != BT_LISTEN) {
493 err = -EBADFD; 491 err = -EBADFD;
494 break; 492 break;
@@ -509,10 +507,11 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
509 } 507 }
510 508
511 release_sock(sk); 509 release_sock(sk);
512 timeo = schedule_timeout(timeo); 510
511 timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
512
513 lock_sock_nested(sk, SINGLE_DEPTH_NESTING); 513 lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
514 } 514 }
515 __set_current_state(TASK_RUNNING);
516 remove_wait_queue(sk_sleep(sk), &wait); 515 remove_wait_queue(sk_sleep(sk), &wait);
517 516
518 if (err) 517 if (err)
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 07ec7d23b843..76321b546e84 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -618,7 +618,7 @@ done:
618 618
619static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flags) 619static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flags)
620{ 620{
621 DECLARE_WAITQUEUE(wait, current); 621 DEFINE_WAIT_FUNC(wait, woken_wake_function);
622 struct sock *sk = sock->sk, *ch; 622 struct sock *sk = sock->sk, *ch;
623 long timeo; 623 long timeo;
624 int err = 0; 624 int err = 0;
@@ -632,8 +632,6 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag
632 /* Wait for an incoming connection. (wake-one). */ 632 /* Wait for an incoming connection. (wake-one). */
633 add_wait_queue_exclusive(sk_sleep(sk), &wait); 633 add_wait_queue_exclusive(sk_sleep(sk), &wait);
634 while (1) { 634 while (1) {
635 set_current_state(TASK_INTERRUPTIBLE);
636
637 if (sk->sk_state != BT_LISTEN) { 635 if (sk->sk_state != BT_LISTEN) {
638 err = -EBADFD; 636 err = -EBADFD;
639 break; 637 break;
@@ -654,10 +652,10 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag
654 } 652 }
655 653
656 release_sock(sk); 654 release_sock(sk);
657 timeo = schedule_timeout(timeo); 655
656 timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
658 lock_sock(sk); 657 lock_sock(sk);
659 } 658 }
660 __set_current_state(TASK_RUNNING);
661 remove_wait_queue(sk_sleep(sk), &wait); 659 remove_wait_queue(sk_sleep(sk), &wait);
662 660
663 if (err) 661 if (err)