summaryrefslogtreecommitdiffstats
path: root/net/bluetooth/cmtp
diff options
context:
space:
mode:
authorJeffy Chen <jeffy.chen@rock-chips.com>2017-06-27 05:34:43 -0400
committerMarcel Holtmann <marcel@holtmann.org>2017-06-27 13:32:11 -0400
commitf06d977309d09253c744e54e75c5295ecc52b7b4 (patch)
tree530a02fc18a3983e4fd42641844ae7492fe9db5c /net/bluetooth/cmtp
parent25717382c1dd0ddced2059053e3ca5088665f7a5 (diff)
Bluetooth: cmtp: fix possible might sleep error in cmtp_session
It looks like cmtp_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>
Diffstat (limited to 'net/bluetooth/cmtp')
-rw-r--r--net/bluetooth/cmtp/core.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c
index f4c64ef01c24..7f26a5a19ff6 100644
--- a/net/bluetooth/cmtp/core.c
+++ b/net/bluetooth/cmtp/core.c
@@ -280,16 +280,16 @@ static int cmtp_session(void *arg)
280 struct cmtp_session *session = arg; 280 struct cmtp_session *session = arg;
281 struct sock *sk = session->sock->sk; 281 struct sock *sk = session->sock->sk;
282 struct sk_buff *skb; 282 struct sk_buff *skb;
283 wait_queue_t wait; 283 DEFINE_WAIT_FUNC(wait, woken_wake_function);
284 284
285 BT_DBG("session %p", session); 285 BT_DBG("session %p", session);
286 286
287 set_user_nice(current, -15); 287 set_user_nice(current, -15);
288 288
289 init_waitqueue_entry(&wait, current);
290 add_wait_queue(sk_sleep(sk), &wait); 289 add_wait_queue(sk_sleep(sk), &wait);
291 while (1) { 290 while (1) {
292 set_current_state(TASK_INTERRUPTIBLE); 291 /* Ensure session->terminate is updated */
292 smp_mb__before_atomic();
293 293
294 if (atomic_read(&session->terminate)) 294 if (atomic_read(&session->terminate))
295 break; 295 break;
@@ -306,9 +306,8 @@ static int cmtp_session(void *arg)
306 306
307 cmtp_process_transmit(session); 307 cmtp_process_transmit(session);
308 308
309 schedule(); 309 wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
310 } 310 }
311 __set_current_state(TASK_RUNNING);
312 remove_wait_queue(sk_sleep(sk), &wait); 311 remove_wait_queue(sk_sleep(sk), &wait);
313 312
314 down_write(&cmtp_session_sem); 313 down_write(&cmtp_session_sem);
@@ -393,7 +392,7 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
393 err = cmtp_attach_device(session); 392 err = cmtp_attach_device(session);
394 if (err < 0) { 393 if (err < 0) {
395 atomic_inc(&session->terminate); 394 atomic_inc(&session->terminate);
396 wake_up_process(session->task); 395 wake_up_interruptible(sk_sleep(session->sock->sk));
397 up_write(&cmtp_session_sem); 396 up_write(&cmtp_session_sem);
398 return err; 397 return err;
399 } 398 }
@@ -431,7 +430,11 @@ int cmtp_del_connection(struct cmtp_conndel_req *req)
431 430
432 /* Stop session thread */ 431 /* Stop session thread */
433 atomic_inc(&session->terminate); 432 atomic_inc(&session->terminate);
434 wake_up_process(session->task); 433
434 /* Ensure session->terminate is updated */
435 smp_mb__after_atomic();
436
437 wake_up_interruptible(sk_sleep(session->sock->sk));
435 } else 438 } else
436 err = -ENOENT; 439 err = -ENOENT;
437 440