diff options
author | Andrei Emeltchenko <andrei.emeltchenko@intel.com> | 2012-05-27 21:27:52 -0400 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2012-06-04 23:34:10 -0400 |
commit | c0df7f6e06e1aeccee39c801af7f78cadeb9f345 (patch) | |
tree | e5dbd0ee76df7d761c6315cc07ab5df4fa861cc4 /net/bluetooth | |
parent | 80b980279508edd1a92d8d77ec99b0ddad00c5fe (diff) |
Bluetooth: Move clean up code and set of SOCK_ZAPPED to l2cap_sock.c
This remove a bit more of socket code from l2cap core, this calls set the
SOCK_ZAPPED and do some clean up depending on the socket state.
Reported-by: Mat Martineau <mathewm@codeaurora.org>
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/l2cap_core.c | 55 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 61 |
2 files changed, 70 insertions, 46 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 7edc8146db26..1f4c72074154 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -493,9 +493,7 @@ static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |||
493 | 493 | ||
494 | static void l2cap_chan_del(struct l2cap_chan *chan, int err) | 494 | static void l2cap_chan_del(struct l2cap_chan *chan, int err) |
495 | { | 495 | { |
496 | struct sock *sk = chan->sk; | ||
497 | struct l2cap_conn *conn = chan->conn; | 496 | struct l2cap_conn *conn = chan->conn; |
498 | struct sock *parent = bt_sk(sk)->parent; | ||
499 | 497 | ||
500 | __clear_chan_timer(chan); | 498 | __clear_chan_timer(chan); |
501 | 499 | ||
@@ -511,21 +509,8 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
511 | hci_conn_put(conn->hcon); | 509 | hci_conn_put(conn->hcon); |
512 | } | 510 | } |
513 | 511 | ||
514 | lock_sock(sk); | 512 | if (chan->ops->teardown) |
515 | 513 | chan->ops->teardown(chan, err); | |
516 | __l2cap_state_change(chan, BT_CLOSED); | ||
517 | sock_set_flag(sk, SOCK_ZAPPED); | ||
518 | |||
519 | if (err) | ||
520 | __l2cap_chan_set_err(chan, err); | ||
521 | |||
522 | if (parent) { | ||
523 | bt_accept_unlink(sk); | ||
524 | parent->sk_data_ready(parent, 0); | ||
525 | } else | ||
526 | sk->sk_state_change(sk); | ||
527 | |||
528 | release_sock(sk); | ||
529 | 514 | ||
530 | if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) | 515 | if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) |
531 | return; | 516 | return; |
@@ -554,25 +539,6 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
554 | return; | 539 | return; |
555 | } | 540 | } |
556 | 541 | ||
557 | static void l2cap_chan_cleanup_listen(struct sock *parent) | ||
558 | { | ||
559 | struct sock *sk; | ||
560 | |||
561 | BT_DBG("parent %p", parent); | ||
562 | |||
563 | /* Close not yet accepted channels */ | ||
564 | while ((sk = bt_accept_dequeue(parent, NULL))) { | ||
565 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||
566 | |||
567 | l2cap_chan_lock(chan); | ||
568 | __clear_chan_timer(chan); | ||
569 | l2cap_chan_close(chan, ECONNRESET); | ||
570 | l2cap_chan_unlock(chan); | ||
571 | |||
572 | chan->ops->close(chan); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | void l2cap_chan_close(struct l2cap_chan *chan, int reason) | 542 | void l2cap_chan_close(struct l2cap_chan *chan, int reason) |
577 | { | 543 | { |
578 | struct l2cap_conn *conn = chan->conn; | 544 | struct l2cap_conn *conn = chan->conn; |
@@ -583,12 +549,8 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
583 | 549 | ||
584 | switch (chan->state) { | 550 | switch (chan->state) { |
585 | case BT_LISTEN: | 551 | case BT_LISTEN: |
586 | lock_sock(sk); | 552 | if (chan->ops->teardown) |
587 | l2cap_chan_cleanup_listen(sk); | 553 | chan->ops->teardown(chan, 0); |
588 | |||
589 | __l2cap_state_change(chan, BT_CLOSED); | ||
590 | sock_set_flag(sk, SOCK_ZAPPED); | ||
591 | release_sock(sk); | ||
592 | break; | 554 | break; |
593 | 555 | ||
594 | case BT_CONNECTED: | 556 | case BT_CONNECTED: |
@@ -630,9 +592,8 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
630 | break; | 592 | break; |
631 | 593 | ||
632 | default: | 594 | default: |
633 | lock_sock(sk); | 595 | if (chan->ops->teardown) |
634 | sock_set_flag(sk, SOCK_ZAPPED); | 596 | chan->ops->teardown(chan, 0); |
635 | release_sock(sk); | ||
636 | break; | 597 | break; |
637 | } | 598 | } |
638 | } | 599 | } |
@@ -3419,7 +3380,9 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
3419 | 3380 | ||
3420 | /* Check if we already have channel with that dcid */ | 3381 | /* Check if we already have channel with that dcid */ |
3421 | if (__l2cap_get_chan_by_dcid(conn, scid)) { | 3382 | if (__l2cap_get_chan_by_dcid(conn, scid)) { |
3422 | sock_set_flag(sk, SOCK_ZAPPED); | 3383 | if (chan->ops->teardown) |
3384 | chan->ops->teardown(chan, 0); | ||
3385 | |||
3423 | chan->ops->close(chan); | 3386 | chan->ops->close(chan); |
3424 | goto response; | 3387 | goto response; |
3425 | } | 3388 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index db787f67c52a..3f5946351fb9 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -872,6 +872,25 @@ static int l2cap_sock_release(struct socket *sock) | |||
872 | return err; | 872 | return err; |
873 | } | 873 | } |
874 | 874 | ||
875 | static void l2cap_sock_cleanup_listen(struct sock *parent) | ||
876 | { | ||
877 | struct sock *sk; | ||
878 | |||
879 | BT_DBG("parent %p", parent); | ||
880 | |||
881 | /* Close not yet accepted channels */ | ||
882 | while ((sk = bt_accept_dequeue(parent, NULL))) { | ||
883 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||
884 | |||
885 | l2cap_chan_lock(chan); | ||
886 | __clear_chan_timer(chan); | ||
887 | l2cap_chan_close(chan, ECONNRESET); | ||
888 | l2cap_chan_unlock(chan); | ||
889 | |||
890 | l2cap_sock_kill(sk); | ||
891 | } | ||
892 | } | ||
893 | |||
875 | static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) | 894 | static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) |
876 | { | 895 | { |
877 | struct sock *sk, *parent = chan->data; | 896 | struct sock *sk, *parent = chan->data; |
@@ -931,6 +950,47 @@ static void l2cap_sock_close_cb(struct l2cap_chan *chan) | |||
931 | l2cap_sock_kill(sk); | 950 | l2cap_sock_kill(sk); |
932 | } | 951 | } |
933 | 952 | ||
953 | static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err) | ||
954 | { | ||
955 | struct sock *sk = chan->data; | ||
956 | struct sock *parent; | ||
957 | |||
958 | lock_sock(sk); | ||
959 | |||
960 | parent = bt_sk(sk)->parent; | ||
961 | |||
962 | sock_set_flag(sk, SOCK_ZAPPED); | ||
963 | |||
964 | switch (chan->state) { | ||
965 | case BT_OPEN: | ||
966 | case BT_BOUND: | ||
967 | case BT_CLOSED: | ||
968 | break; | ||
969 | case BT_LISTEN: | ||
970 | l2cap_sock_cleanup_listen(sk); | ||
971 | sk->sk_state = BT_CLOSED; | ||
972 | chan->state = BT_CLOSED; | ||
973 | |||
974 | break; | ||
975 | default: | ||
976 | sk->sk_state = BT_CLOSED; | ||
977 | chan->state = BT_CLOSED; | ||
978 | |||
979 | sk->sk_err = err; | ||
980 | |||
981 | if (parent) { | ||
982 | bt_accept_unlink(sk); | ||
983 | parent->sk_data_ready(parent, 0); | ||
984 | } else { | ||
985 | sk->sk_state_change(sk); | ||
986 | } | ||
987 | |||
988 | break; | ||
989 | } | ||
990 | |||
991 | release_sock(sk); | ||
992 | } | ||
993 | |||
934 | static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state) | 994 | static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state) |
935 | { | 995 | { |
936 | struct sock *sk = chan->data; | 996 | struct sock *sk = chan->data; |
@@ -959,6 +1019,7 @@ static struct l2cap_ops l2cap_chan_ops = { | |||
959 | .new_connection = l2cap_sock_new_connection_cb, | 1019 | .new_connection = l2cap_sock_new_connection_cb, |
960 | .recv = l2cap_sock_recv_cb, | 1020 | .recv = l2cap_sock_recv_cb, |
961 | .close = l2cap_sock_close_cb, | 1021 | .close = l2cap_sock_close_cb, |
1022 | .teardown = l2cap_sock_teardown_cb, | ||
962 | .state_change = l2cap_sock_state_change_cb, | 1023 | .state_change = l2cap_sock_state_change_cb, |
963 | .alloc_skb = l2cap_sock_alloc_skb_cb, | 1024 | .alloc_skb = l2cap_sock_alloc_skb_cb, |
964 | }; | 1025 | }; |