diff options
author | Mat Martineau <mathewm@codeaurora.org> | 2012-05-04 17:20:31 -0400 |
---|---|---|
committer | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2012-05-16 15:14:02 -0400 |
commit | a6a5568c03c4805d4d250f6bd9d468eeeb4ea059 (patch) | |
tree | a85da07516e3c584056373fbad175a3757040b5c | |
parent | ef191aded58c5e6860b01f463818584a420a4d6b (diff) |
Bluetooth: Lock the L2CAP channel when sending
The ERTM and streaming mode transmit queue must only be accessed while
the L2CAP channel lock is held. Locking the channel before calling
l2cap_chan_send ensures that multiple threads cannot simultaneously
manipulate the queue when sending and receiving concurrently.
L2CAP channel locking had previously moved to the l2cap_chan struct
instead of the associated socket, so some of the old socket locking
can also be removed in this patch.
Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
Signed-off-by: Gustavo Padovan <gustavo@padovan.org>
-rw-r--r-- | include/net/bluetooth/bluetooth.h | 2 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 12 |
2 files changed, 6 insertions, 8 deletions
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index c34a9a6184a1..7981ca48b83a 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h | |||
@@ -257,12 +257,10 @@ static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk, | |||
257 | { | 257 | { |
258 | struct sk_buff *skb; | 258 | struct sk_buff *skb; |
259 | 259 | ||
260 | release_sock(sk); | ||
261 | if ((skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err))) { | 260 | if ((skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err))) { |
262 | skb_reserve(skb, BT_SKB_RESERVE); | 261 | skb_reserve(skb, BT_SKB_RESERVE); |
263 | bt_cb(skb)->incoming = 0; | 262 | bt_cb(skb)->incoming = 0; |
264 | } | 263 | } |
265 | lock_sock(sk); | ||
266 | 264 | ||
267 | if (!skb && *err) | 265 | if (!skb && *err) |
268 | return NULL; | 266 | return NULL; |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index b7bc7b981ee2..f6d8e13197d6 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -720,16 +720,13 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
720 | if (msg->msg_flags & MSG_OOB) | 720 | if (msg->msg_flags & MSG_OOB) |
721 | return -EOPNOTSUPP; | 721 | return -EOPNOTSUPP; |
722 | 722 | ||
723 | lock_sock(sk); | 723 | if (sk->sk_state != BT_CONNECTED) |
724 | |||
725 | if (sk->sk_state != BT_CONNECTED) { | ||
726 | release_sock(sk); | ||
727 | return -ENOTCONN; | 724 | return -ENOTCONN; |
728 | } | ||
729 | 725 | ||
726 | l2cap_chan_lock(chan); | ||
730 | err = l2cap_chan_send(chan, msg, len, sk->sk_priority); | 727 | err = l2cap_chan_send(chan, msg, len, sk->sk_priority); |
728 | l2cap_chan_unlock(chan); | ||
731 | 729 | ||
732 | release_sock(sk); | ||
733 | return err; | 730 | return err; |
734 | } | 731 | } |
735 | 732 | ||
@@ -940,7 +937,10 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, | |||
940 | struct sk_buff *skb; | 937 | struct sk_buff *skb; |
941 | int err; | 938 | int err; |
942 | 939 | ||
940 | l2cap_chan_unlock(chan); | ||
943 | skb = bt_skb_send_alloc(chan->sk, len, nb, &err); | 941 | skb = bt_skb_send_alloc(chan->sk, len, nb, &err); |
942 | l2cap_chan_lock(chan); | ||
943 | |||
944 | if (!skb) | 944 | if (!skb) |
945 | return ERR_PTR(err); | 945 | return ERR_PTR(err); |
946 | 946 | ||