aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2011-12-17 07:56:45 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-12-18 14:07:57 -0500
commit3d57dc6806599ca7d389fc9410eefbc1a7dc32bc (patch)
treebcb1efa2cec7f2e12aff5a5d40b2115c3b738d38
parent03a001948166d966d0d580cddb8ae3a23f8b795b (diff)
Bluetooth: Change l2cap chan_list to use RCU
This list has much more reads than writes, so RCU makes senses here, also it avoid deadlock against the socket lock. Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r--net/bluetooth/l2cap_core.c119
1 files changed, 58 insertions, 61 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index d6165199fc8b..a1766adee397 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -89,24 +89,36 @@ static inline void chan_put(struct l2cap_chan *c)
89 89
90static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) 90static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
91{ 91{
92 struct l2cap_chan *c; 92 struct l2cap_chan *c, *r = NULL;
93 93
94 list_for_each_entry(c, &conn->chan_l, list) { 94 rcu_read_lock();
95 if (c->dcid == cid) 95
96 return c; 96 list_for_each_entry_rcu(c, &conn->chan_l, list) {
97 if (c->dcid == cid) {
98 r = c;
99 break;
100 }
97 } 101 }
98 return NULL; 102
103 rcu_read_unlock();
104 return r;
99} 105}
100 106
101static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) 107static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
102{ 108{
103 struct l2cap_chan *c; 109 struct l2cap_chan *c, *r = NULL;
104 110
105 list_for_each_entry(c, &conn->chan_l, list) { 111 rcu_read_lock();
106 if (c->scid == cid) 112
107 return c; 113 list_for_each_entry_rcu(c, &conn->chan_l, list) {
114 if (c->scid == cid) {
115 r = c;
116 break;
117 }
108 } 118 }
109 return NULL; 119
120 rcu_read_unlock();
121 return r;
110} 122}
111 123
112/* Find channel with given SCID. 124/* Find channel with given SCID.
@@ -115,34 +127,36 @@ static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 ci
115{ 127{
116 struct l2cap_chan *c; 128 struct l2cap_chan *c;
117 129
118 mutex_lock(&conn->chan_lock);
119 c = __l2cap_get_chan_by_scid(conn, cid); 130 c = __l2cap_get_chan_by_scid(conn, cid);
120 if (c) 131 if (c)
121 lock_sock(c->sk); 132 lock_sock(c->sk);
122 mutex_unlock(&conn->chan_lock);
123 return c; 133 return c;
124} 134}
125 135
126static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) 136static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
127{ 137{
128 struct l2cap_chan *c; 138 struct l2cap_chan *c, *r = NULL;
129 139
130 list_for_each_entry(c, &conn->chan_l, list) { 140 rcu_read_lock();
131 if (c->ident == ident) 141
132 return c; 142 list_for_each_entry_rcu(c, &conn->chan_l, list) {
143 if (c->ident == ident) {
144 r = c;
145 break;
146 }
133 } 147 }
134 return NULL; 148
149 rcu_read_unlock();
150 return r;
135} 151}
136 152
137static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) 153static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
138{ 154{
139 struct l2cap_chan *c; 155 struct l2cap_chan *c;
140 156
141 mutex_lock(&conn->chan_lock);
142 c = __l2cap_get_chan_by_ident(conn, ident); 157 c = __l2cap_get_chan_by_ident(conn, ident);
143 if (c) 158 if (c)
144 lock_sock(c->sk); 159 lock_sock(c->sk);
145 mutex_unlock(&conn->chan_lock);
146 return c; 160 return c;
147} 161}
148 162
@@ -323,7 +337,7 @@ void l2cap_chan_destroy(struct l2cap_chan *chan)
323 chan_put(chan); 337 chan_put(chan);
324} 338}
325 339
326static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 340static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
327{ 341{
328 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 342 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
329 chan->psm, chan->dcid); 343 chan->psm, chan->dcid);
@@ -364,7 +378,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
364 378
365 chan_hold(chan); 379 chan_hold(chan);
366 380
367 list_add(&chan->list, &conn->chan_l); 381 list_add_rcu(&chan->list, &conn->chan_l);
368} 382}
369 383
370/* Delete channel. 384/* Delete channel.
@@ -381,9 +395,9 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
381 395
382 if (conn) { 396 if (conn) {
383 /* Delete from channel list */ 397 /* Delete from channel list */
384 mutex_lock(&conn->chan_lock); 398 list_del_rcu(&chan->list);
385 list_del(&chan->list); 399 synchronize_rcu();
386 mutex_unlock(&conn->chan_lock); 400
387 chan_put(chan); 401 chan_put(chan);
388 402
389 chan->conn = NULL; 403 chan->conn = NULL;
@@ -750,13 +764,13 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c
750/* ---- L2CAP connections ---- */ 764/* ---- L2CAP connections ---- */
751static void l2cap_conn_start(struct l2cap_conn *conn) 765static void l2cap_conn_start(struct l2cap_conn *conn)
752{ 766{
753 struct l2cap_chan *chan, *tmp; 767 struct l2cap_chan *chan;
754 768
755 BT_DBG("conn %p", conn); 769 BT_DBG("conn %p", conn);
756 770
757 mutex_lock(&conn->chan_lock); 771 rcu_read_lock();
758 772
759 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { 773 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
760 struct sock *sk = chan->sk; 774 struct sock *sk = chan->sk;
761 775
762 bh_lock_sock(sk); 776 bh_lock_sock(sk);
@@ -780,9 +794,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
780 &chan->conf_state)) { 794 &chan->conf_state)) {
781 /* l2cap_chan_close() calls list_del(chan) 795 /* l2cap_chan_close() calls list_del(chan)
782 * so release the lock */ 796 * so release the lock */
783 mutex_unlock(&conn->chan_lock);
784 l2cap_chan_close(chan, ECONNRESET); 797 l2cap_chan_close(chan, ECONNRESET);
785 utex_lock(&conn->chan_lock);
786 bh_unlock_sock(sk); 798 bh_unlock_sock(sk);
787 continue; 799 continue;
788 } 800 }
@@ -838,7 +850,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
838 bh_unlock_sock(sk); 850 bh_unlock_sock(sk);
839 } 851 }
840 852
841 mutex_unlock(&conn->chan_lock); 853 rcu_read_unlock();
842} 854}
843 855
844/* Find socket with cid and source bdaddr. 856/* Find socket with cid and source bdaddr.
@@ -903,8 +915,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
903 915
904 sk = chan->sk; 916 sk = chan->sk;
905 917
906 mutex_lock(&conn->chan_lock);
907
908 hci_conn_hold(conn->hcon); 918 hci_conn_hold(conn->hcon);
909 919
910 bacpy(&bt_sk(sk)->src, conn->src); 920 bacpy(&bt_sk(sk)->src, conn->src);
@@ -912,15 +922,13 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
912 922
913 bt_accept_enqueue(parent, sk); 923 bt_accept_enqueue(parent, sk);
914 924
915 __l2cap_chan_add(conn, chan); 925 l2cap_chan_add(conn, chan);
916 926
917 __set_chan_timer(chan, sk->sk_sndtimeo); 927 __set_chan_timer(chan, sk->sk_sndtimeo);
918 928
919 l2cap_state_change(chan, BT_CONNECTED); 929 l2cap_state_change(chan, BT_CONNECTED);
920 parent->sk_data_ready(parent, 0); 930 parent->sk_data_ready(parent, 0);
921 931
922 mutex_unlock(&conn->chan_lock);
923
924clean: 932clean:
925 release_sock(parent); 933 release_sock(parent);
926} 934}
@@ -954,9 +962,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
954 if (conn->hcon->out && conn->hcon->type == LE_LINK) 962 if (conn->hcon->out && conn->hcon->type == LE_LINK)
955 smp_conn_security(conn, conn->hcon->pending_sec_level); 963 smp_conn_security(conn, conn->hcon->pending_sec_level);
956 964
957 mutex_lock(&conn->chan_lock); 965 rcu_read_lock();
958 966
959 list_for_each_entry(chan, &conn->chan_l, list) { 967 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
960 struct sock *sk = chan->sk; 968 struct sock *sk = chan->sk;
961 969
962 bh_lock_sock(sk); 970 bh_lock_sock(sk);
@@ -976,7 +984,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
976 bh_unlock_sock(sk); 984 bh_unlock_sock(sk);
977 } 985 }
978 986
979 mutex_unlock(&conn->chan_lock); 987 rcu_read_unlock();
980} 988}
981 989
982/* Notify sockets that we cannot guaranty reliability anymore */ 990/* Notify sockets that we cannot guaranty reliability anymore */
@@ -986,16 +994,16 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
986 994
987 BT_DBG("conn %p", conn); 995 BT_DBG("conn %p", conn);
988 996
989 mutex_lock(&conn->chan_lock); 997 rcu_read_lock();
990 998
991 list_for_each_entry(chan, &conn->chan_l, list) { 999 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
992 struct sock *sk = chan->sk; 1000 struct sock *sk = chan->sk;
993 1001
994 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) 1002 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
995 sk->sk_err = err; 1003 sk->sk_err = err;
996 } 1004 }
997 1005
998 mutex_unlock(&conn->chan_lock); 1006 rcu_read_unlock();
999} 1007}
1000 1008
1001static void l2cap_info_timeout(struct work_struct *work) 1009static void l2cap_info_timeout(struct work_struct *work)
@@ -1087,7 +1095,6 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1087 conn->feat_mask = 0; 1095 conn->feat_mask = 0;
1088 1096
1089 spin_lock_init(&conn->lock); 1097 spin_lock_init(&conn->lock);
1090 mutex_init(&conn->chan_lock);
1091 1098
1092 INIT_LIST_HEAD(&conn->chan_l); 1099 INIT_LIST_HEAD(&conn->chan_l);
1093 1100
@@ -1102,13 +1109,6 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1102 return conn; 1109 return conn;
1103} 1110}
1104 1111
1105static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
1106{
1107 mutex_lock(&conn->chan_lock);
1108 __l2cap_chan_add(conn, chan);
1109 mutex_unlock(&conn->chan_lock);
1110}
1111
1112/* ---- Socket interface ---- */ 1112/* ---- Socket interface ---- */
1113 1113
1114/* Find socket with psm and source bdaddr. 1114/* Find socket with psm and source bdaddr.
@@ -1825,8 +1825,9 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1825 1825
1826 BT_DBG("conn %p", conn); 1826 BT_DBG("conn %p", conn);
1827 1827
1828 mutex_lock(&conn->chan_lock); 1828 rcu_read_lock();
1829 list_for_each_entry(chan, &conn->chan_l, list) { 1829
1830 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
1830 struct sock *sk = chan->sk; 1831 struct sock *sk = chan->sk;
1831 if (chan->chan_type != L2CAP_CHAN_RAW) 1832 if (chan->chan_type != L2CAP_CHAN_RAW)
1832 continue; 1833 continue;
@@ -1841,7 +1842,8 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1841 if (chan->ops->recv(chan->data, nskb)) 1842 if (chan->ops->recv(chan->data, nskb))
1842 kfree_skb(nskb); 1843 kfree_skb(nskb);
1843 } 1844 }
1844 mutex_unlock(&conn->chan_lock); 1845
1846 rcu_read_unlock();
1845} 1847}
1846 1848
1847/* ---- L2CAP signalling commands ---- */ 1849/* ---- L2CAP signalling commands ---- */
@@ -2641,11 +2643,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
2641 2643
2642 sk = chan->sk; 2644 sk = chan->sk;
2643 2645
2644 mutex_lock(&conn->chan_lock);
2645
2646 /* Check if we already have channel with that dcid */ 2646 /* Check if we already have channel with that dcid */
2647 if (__l2cap_get_chan_by_dcid(conn, scid)) { 2647 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2648 mutex_unlock(&conn->chan_lock);
2649 sock_set_flag(sk, SOCK_ZAPPED); 2648 sock_set_flag(sk, SOCK_ZAPPED);
2650 chan->ops->close(chan->data); 2649 chan->ops->close(chan->data);
2651 goto response; 2650 goto response;
@@ -2660,7 +2659,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
2660 2659
2661 bt_accept_enqueue(parent, sk); 2660 bt_accept_enqueue(parent, sk);
2662 2661
2663 __l2cap_chan_add(conn, chan); 2662 l2cap_chan_add(conn, chan);
2664 2663
2665 dcid = chan->scid; 2664 dcid = chan->scid;
2666 2665
@@ -2691,8 +2690,6 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
2691 status = L2CAP_CS_NO_INFO; 2690 status = L2CAP_CS_NO_INFO;
2692 } 2691 }
2693 2692
2694 mutex_unlock(&conn->chan_lock);
2695
2696response: 2693response:
2697 release_sock(parent); 2694 release_sock(parent);
2698 2695
@@ -4528,9 +4525,9 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
4528 del_timer(&conn->security_timer); 4525 del_timer(&conn->security_timer);
4529 } 4526 }
4530 4527
4531 mutex_lock(&conn->chan_lock); 4528 rcu_read_lock();
4532 4529
4533 list_for_each_entry(chan, &conn->chan_l, list) { 4530 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
4534 struct sock *sk = chan->sk; 4531 struct sock *sk = chan->sk;
4535 4532
4536 bh_lock_sock(sk); 4533 bh_lock_sock(sk);
@@ -4608,7 +4605,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
4608 bh_unlock_sock(sk); 4605 bh_unlock_sock(sk);
4609 } 4606 }
4610 4607
4611 mutex_unlock(&conn->chan_lock); 4608 rcu_read_unlock();
4612 4609
4613 return 0; 4610 return 0;
4614} 4611}