diff options
author | Jeffy Chen <jeffy.chen@rock-chips.com> | 2017-06-27 05:34:43 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2017-06-27 13:32:11 -0400 |
commit | f06d977309d09253c744e54e75c5295ecc52b7b4 (patch) | |
tree | 530a02fc18a3983e4fd42641844ae7492fe9db5c /net/bluetooth/cmtp | |
parent | 25717382c1dd0ddced2059053e3ca5088665f7a5 (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.c | 17 |
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 | ||