* [PATCHv2 0/3] Bluetooth: Change socket lock to l2cap_chan lock
@ 2012-02-22 10:43 Andrei Emeltchenko
2012-02-22 10:43 ` [PATCHv2 1/3] Bluetooth: Add unlocked __l2cap_chan_add function Andrei Emeltchenko
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Andrei Emeltchenko @ 2012-02-22 10:43 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Changing socket lock to L2CAP chan lock in L2CAP code. Needed for implementing
protocols above L2CAP without creating sockets.
Changes:
* PATCHv2: Rebase remaining parts against latest tree and merge all
patches dealing with converting sk lock to chan lock together following
recommendation from Ulisses and Gustavo.
* PATCHv1: Added extra line (per Gustavo comment)
* RFCv6: Same code but patches 2,3 and 4 from RFCv5 are merged together
following recommendations from review.
* RFCv5: Fixed locking bug in l2cap_data_channel, added locks in
l2cap_sock_shutdown function, fixed several styles issues.
* RFCv4: Better split patches so they looks more clear and obvious,
taking coments about naming change and delete unused vars. See diff change
from the previous version below:
* RFCv3: Split the big patch to several small (I believe logical) chunks,
remove unneded locks from cleanup_listen, use the same arguments for
locked/unlocked socket error functions.
* RFCv2: Convert l2cap channel list back to mutex from RCU list.
Andrei Emeltchenko (3):
Bluetooth: Add unlocked __l2cap_chan_add function
Bluetooth: Change sk lock to chan lock in L2CAP core
Bluetooth: Remove socket lock check
net/bluetooth/l2cap_core.c | 173 +++++++++++++++++++++++++++-----------------
net/bluetooth/l2cap_sock.c | 28 +++++--
2 files changed, 125 insertions(+), 76 deletions(-)
--
1.7.9
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCHv2 1/3] Bluetooth: Add unlocked __l2cap_chan_add function 2012-02-22 10:43 [PATCHv2 0/3] Bluetooth: Change socket lock to l2cap_chan lock Andrei Emeltchenko @ 2012-02-22 10:43 ` Andrei Emeltchenko 2012-02-22 10:43 ` [PATCHv2 2/3] Bluetooth: Change sk lock to chan lock in L2CAP core Andrei Emeltchenko ` (2 subsequent siblings) 3 siblings, 0 replies; 7+ messages in thread From: Andrei Emeltchenko @ 2012-02-22 10:43 UTC (permalink / raw) To: linux-bluetooth From: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Add unlocked L2CAP channel add function. Unlocked version will be used in later patches. Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Reviewed-by: Ulisses Furquim <ulisses@profusion.mobi> Acked-by: Gustavo F. Padovan <padovan@profusion.mobi> --- net/bluetooth/l2cap_core.c | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c0640b7..0e4f4cb 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -300,7 +300,7 @@ void l2cap_chan_destroy(struct l2cap_chan *chan) l2cap_chan_put(chan); } -static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) +void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) { BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, chan->psm, chan->dcid); @@ -346,8 +346,13 @@ static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) l2cap_chan_hold(chan); - mutex_lock(&conn->chan_lock); list_add(&chan->list, &conn->chan_l); +} + +void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) +{ + mutex_lock(&conn->chan_lock); + __l2cap_chan_add(conn, chan); mutex_unlock(&conn->chan_lock); } -- 1.7.9 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCHv2 2/3] Bluetooth: Change sk lock to chan lock in L2CAP core 2012-02-22 10:43 [PATCHv2 0/3] Bluetooth: Change socket lock to l2cap_chan lock Andrei Emeltchenko 2012-02-22 10:43 ` [PATCHv2 1/3] Bluetooth: Add unlocked __l2cap_chan_add function Andrei Emeltchenko @ 2012-02-22 10:43 ` Andrei Emeltchenko 2012-02-22 10:43 ` [PATCHv2 3/3] Bluetooth: Remove socket lock check Andrei Emeltchenko 2012-02-22 12:30 ` [PATCHv2 0/3] Bluetooth: Change socket lock to l2cap_chan lock Ulisses Furquim 3 siblings, 0 replies; 7+ messages in thread From: Andrei Emeltchenko @ 2012-02-22 10:43 UTC (permalink / raw) To: linux-bluetooth From: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Change sk lock to chan lock in l2cap core and move sk locks to l2cap sock code. bh_locks were used because of being RCU critical section. When needed use explicit socket locks. Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> --- net/bluetooth/l2cap_core.c | 164 ++++++++++++++++++++++++++------------------ net/bluetooth/l2cap_sock.c | 20 ++++- 2 files changed, 114 insertions(+), 70 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 0e4f4cb..5f9ce44 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -238,13 +238,12 @@ static void l2cap_chan_timeout(struct work_struct *work) struct l2cap_chan *chan = container_of(work, struct l2cap_chan, chan_timer.work); struct l2cap_conn *conn = chan->conn; - struct sock *sk = chan->sk; int reason; BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); mutex_lock(&conn->chan_lock); - lock_sock(sk); + l2cap_chan_lock(chan); if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) reason = ECONNREFUSED; @@ -256,7 +255,7 @@ static void l2cap_chan_timeout(struct work_struct *work) l2cap_chan_close(chan, reason); - release_sock(sk); + l2cap_chan_unlock(chan); chan->ops->close(chan->data); mutex_unlock(&conn->chan_lock); @@ -378,6 +377,8 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err) hci_conn_put(conn->hcon); } + lock_sock(sk); + __l2cap_state_change(chan, BT_CLOSED); sock_set_flag(sk, SOCK_ZAPPED); @@ -390,6 +391,8 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err) } else sk->sk_state_change(sk); + release_sock(sk); + if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) && test_bit(CONF_INPUT_DONE, &chan->conf_state))) return; @@ -422,10 +425,10 @@ static void l2cap_chan_cleanup_listen(struct sock *parent) while ((sk = bt_accept_dequeue(parent, NULL))) { struct l2cap_chan *chan = l2cap_pi(sk)->chan; + l2cap_chan_lock(chan); __clear_chan_timer(chan); - lock_sock(sk); l2cap_chan_close(chan, ECONNRESET); - release_sock(sk); + l2cap_chan_unlock(chan); chan->ops->close(chan->data); } @@ -441,10 +444,12 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) switch (chan->state) { case BT_LISTEN: + lock_sock(sk); l2cap_chan_cleanup_listen(sk); __l2cap_state_change(chan, BT_CLOSED); sock_set_flag(sk, SOCK_ZAPPED); + release_sock(sk); break; case BT_CONNECTED: @@ -487,7 +492,9 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) break; default: + lock_sock(sk); sock_set_flag(sk, SOCK_ZAPPED); + release_sock(sk); break; } } @@ -715,6 +722,7 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) { + struct sock *sk = chan->sk; struct l2cap_disconn_req req; if (!conn) @@ -731,8 +739,10 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, sizeof(req), &req); + lock_sock(sk); __l2cap_state_change(chan, BT_DISCONN); __l2cap_chan_set_err(chan, err); + release_sock(sk); } /* ---- L2CAP connections ---- */ @@ -747,10 +757,10 @@ static void l2cap_conn_start(struct l2cap_conn *conn) list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { struct sock *sk = chan->sk; - bh_lock_sock(sk); + l2cap_chan_lock(chan); if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { - bh_unlock_sock(sk); + l2cap_chan_unlock(chan); continue; } @@ -759,17 +769,15 @@ static void l2cap_conn_start(struct l2cap_conn *conn) if (!l2cap_chan_check_security(chan) || !__l2cap_no_conn_pending(chan)) { - bh_unlock_sock(sk); + l2cap_chan_unlock(chan); continue; } if (!l2cap_mode_supported(chan->mode, conn->feat_mask) && test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { - /* l2cap_chan_close() calls list_del(chan) - * so release the lock */ l2cap_chan_close(chan, ECONNRESET); - bh_unlock_sock(sk); + l2cap_chan_unlock(chan); continue; } @@ -789,6 +797,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) rsp.dcid = cpu_to_le16(chan->scid); if (l2cap_chan_check_security(chan)) { + lock_sock(sk); if (bt_sk(sk)->defer_setup) { struct sock *parent = bt_sk(sk)->parent; rsp.result = cpu_to_le16(L2CAP_CR_PEND); @@ -801,6 +810,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); } + release_sock(sk); } else { rsp.result = cpu_to_le16(L2CAP_CR_PEND); rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); @@ -811,7 +821,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) if (test_bit(CONF_REQ_SENT, &chan->conf_state) || rsp.result != L2CAP_CR_SUCCESS) { - bh_unlock_sock(sk); + l2cap_chan_unlock(chan); continue; } @@ -821,7 +831,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) chan->num_conf_req++; } - bh_unlock_sock(sk); + l2cap_chan_unlock(chan); } mutex_unlock(&conn->chan_lock); @@ -910,7 +920,11 @@ clean: static void l2cap_chan_ready(struct l2cap_chan *chan) { struct sock *sk = chan->sk; - struct sock *parent = bt_sk(sk)->parent; + struct sock *parent; + + lock_sock(sk); + + parent = bt_sk(sk)->parent; BT_DBG("sk %p, parent %p", sk, parent); @@ -922,6 +936,8 @@ static void l2cap_chan_ready(struct l2cap_chan *chan) if (parent) parent->sk_data_ready(parent, 0); + + release_sock(sk); } static void l2cap_conn_ready(struct l2cap_conn *conn) @@ -939,23 +955,25 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) mutex_lock(&conn->chan_lock); list_for_each_entry(chan, &conn->chan_l, list) { - struct sock *sk = chan->sk; - bh_lock_sock(sk); + l2cap_chan_lock(chan); if (conn->hcon->type == LE_LINK) { if (smp_conn_security(conn, chan->sec_level)) l2cap_chan_ready(chan); } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { + struct sock *sk = chan->sk; __clear_chan_timer(chan); + lock_sock(sk); __l2cap_state_change(chan, BT_CONNECTED); sk->sk_state_change(sk); + release_sock(sk); } else if (chan->state == BT_CONNECT) l2cap_do_start(chan); - bh_unlock_sock(sk); + l2cap_chan_unlock(chan); } mutex_unlock(&conn->chan_lock); @@ -993,7 +1011,6 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) { struct l2cap_conn *conn = hcon->l2cap_data; struct l2cap_chan *chan, *l; - struct sock *sk; if (!conn) return; @@ -1006,10 +1023,12 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) /* Kill channels */ list_for_each_entry_safe(chan, l, &conn->chan_l, list) { - sk = chan->sk; - lock_sock(sk); + l2cap_chan_lock(chan); + l2cap_chan_del(chan, err); - release_sock(sk); + + l2cap_chan_unlock(chan); + chan->ops->close(chan->data); } @@ -1140,7 +1159,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *d hci_dev_lock(hdev); - lock_sock(sk); + l2cap_chan_lock(chan); /* PSM must be odd and lsb of upper byte must be 0 */ if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && @@ -1167,17 +1186,21 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *d goto done; } + lock_sock(sk); + switch (sk->sk_state) { case BT_CONNECT: case BT_CONNECT2: case BT_CONFIG: /* Already connecting */ err = 0; + release_sock(sk); goto done; case BT_CONNECTED: /* Already connected */ err = -EISCONN; + release_sock(sk); goto done; case BT_OPEN: @@ -1187,11 +1210,15 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *d default: err = -EBADFD; + release_sock(sk); goto done; } /* Set destination address and psm */ bacpy(&bt_sk(sk)->dst, dst); + + release_sock(sk); + chan->psm = psm; chan->dcid = cid; @@ -1219,16 +1246,18 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *d /* Update source addr of the socket */ bacpy(src, conn->src); + l2cap_chan_unlock(chan); l2cap_chan_add(conn, chan); + l2cap_chan_lock(chan); - __l2cap_state_change(chan, BT_CONNECT); + l2cap_state_change(chan, BT_CONNECT); __set_chan_timer(chan, sk->sk_sndtimeo); if (hcon->state == BT_CONNECTED) { if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { __clear_chan_timer(chan); if (l2cap_chan_check_security(chan)) - __l2cap_state_change(chan, BT_CONNECTED); + l2cap_state_change(chan, BT_CONNECTED); } else l2cap_do_start(chan); } @@ -1236,6 +1265,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *d err = 0; done: + l2cap_chan_unlock(chan); hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1277,14 +1307,14 @@ static void l2cap_monitor_timeout(struct work_struct *work) { struct l2cap_chan *chan = container_of(work, struct l2cap_chan, monitor_timer.work); - struct sock *sk = chan->sk; BT_DBG("chan %p", chan); - lock_sock(sk); + l2cap_chan_lock(chan); + if (chan->retry_count >= chan->remote_max_tx) { l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); - release_sock(sk); + l2cap_chan_unlock(chan); return; } @@ -1292,25 +1322,26 @@ static void l2cap_monitor_timeout(struct work_struct *work) __set_monitor_timer(chan); l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); - release_sock(sk); + l2cap_chan_unlock(chan); } static void l2cap_retrans_timeout(struct work_struct *work) { struct l2cap_chan *chan = container_of(work, struct l2cap_chan, retrans_timer.work); - struct sock *sk = chan->sk; BT_DBG("chan %p", chan); - lock_sock(sk); + l2cap_chan_lock(chan); + chan->retry_count = 1; __set_monitor_timer(chan); set_bit(CONN_WAIT_F, &chan->conn_state); l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); - release_sock(sk); + + l2cap_chan_unlock(chan); } static void l2cap_drop_acked_frames(struct l2cap_chan *chan) @@ -2001,9 +2032,11 @@ static void l2cap_ack_timeout(struct work_struct *work) BT_DBG("chan %p", chan); - lock_sock(chan->sk); + l2cap_chan_lock(chan); + __l2cap_send_ack(chan); - release_sock(chan->sk); + + l2cap_chan_unlock(chan); l2cap_chan_put(chan); } @@ -2664,7 +2697,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd bt_accept_enqueue(parent, sk); - l2cap_chan_add(conn, chan); + __l2cap_chan_add(conn, chan); dcid = chan->scid; @@ -2737,7 +2770,6 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; u16 scid, dcid, result, status; struct l2cap_chan *chan; - struct sock *sk; u8 req[128]; int err; @@ -2767,8 +2799,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd err = 0; - sk = chan->sk; - lock_sock(sk); + l2cap_chan_lock(chan); switch (result) { case L2CAP_CR_SUCCESS: @@ -2794,7 +2825,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd break; } - release_sock(sk); + l2cap_chan_unlock(chan); unlock: mutex_unlock(&conn->chan_lock); @@ -2819,7 +2850,6 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr u16 dcid, flags; u8 rsp[64]; struct l2cap_chan *chan; - struct sock *sk; int len; dcid = __le16_to_cpu(req->dcid); @@ -2831,8 +2861,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr if (!chan) return -ENOENT; - sk = chan->sk; - lock_sock(sk); + l2cap_chan_lock(chan); if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { struct l2cap_cmd_rej_cid rej; @@ -2921,7 +2950,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr } unlock: - release_sock(sk); + l2cap_chan_unlock(chan); return 0; } @@ -2930,7 +2959,6 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; u16 scid, flags, result; struct l2cap_chan *chan; - struct sock *sk; int len = cmd->len - sizeof(*rsp); scid = __le16_to_cpu(rsp->scid); @@ -2944,8 +2972,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr if (!chan) return 0; - sk = chan->sk; - lock_sock(sk); + l2cap_chan_lock(chan); switch (result) { case L2CAP_CONF_SUCCESS: @@ -3004,7 +3031,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr } default: - __l2cap_chan_set_err(chan, ECONNRESET); + l2cap_chan_set_err(chan, ECONNRESET); __set_chan_timer(chan, msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT)); @@ -3031,7 +3058,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr } done: - release_sock(sk); + l2cap_chan_unlock(chan); return 0; } @@ -3056,17 +3083,21 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd return 0; } + l2cap_chan_lock(chan); + sk = chan->sk; - lock_sock(sk); rsp.dcid = cpu_to_le16(chan->scid); rsp.scid = cpu_to_le16(chan->dcid); l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); + lock_sock(sk); sk->sk_shutdown = SHUTDOWN_MASK; + release_sock(sk); l2cap_chan_del(chan, ECONNRESET); - release_sock(sk); + + l2cap_chan_unlock(chan); chan->ops->close(chan->data); @@ -3080,7 +3111,6 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; u16 dcid, scid; struct l2cap_chan *chan; - struct sock *sk; scid = __le16_to_cpu(rsp->scid); dcid = __le16_to_cpu(rsp->dcid); @@ -3095,11 +3125,11 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd return 0; } - sk = chan->sk; - lock_sock(sk); + l2cap_chan_lock(chan); l2cap_chan_del(chan, 0); - release_sock(sk); + + l2cap_chan_unlock(chan); chan->ops->close(chan->data); @@ -4251,7 +4281,6 @@ drop: static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) { struct l2cap_chan *chan; - struct sock *sk = NULL; u32 control; u16 tx_seq; int len; @@ -4259,11 +4288,12 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk chan = l2cap_get_chan_by_scid(conn, cid); if (!chan) { BT_DBG("unknown cid 0x%4.4x", cid); - goto drop; + /* Drop packet and return */ + kfree(skb); + return 0; } - sk = chan->sk; - lock_sock(sk); + l2cap_chan_lock(chan); BT_DBG("chan %p, len %d", chan, skb->len); @@ -4334,8 +4364,7 @@ drop: kfree_skb(skb); done: - if (sk) - release_sock(sk); + l2cap_chan_unlock(chan); return 0; } @@ -4554,9 +4583,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) mutex_lock(&conn->chan_lock); list_for_each_entry(chan, &conn->chan_l, list) { - struct sock *sk = chan->sk; - - bh_lock_sock(sk); + l2cap_chan_lock(chan); BT_DBG("chan->scid %d", chan->scid); @@ -4566,19 +4593,19 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) l2cap_chan_ready(chan); } - bh_unlock_sock(sk); + l2cap_chan_unlock(chan); continue; } if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { - bh_unlock_sock(sk); + l2cap_chan_unlock(chan); continue; } if (!status && (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)) { l2cap_check_encryption(chan, encrypt); - bh_unlock_sock(sk); + l2cap_chan_unlock(chan); continue; } @@ -4599,9 +4626,12 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) msecs_to_jiffies(L2CAP_DISC_TIMEOUT)); } } else if (chan->state == BT_CONNECT2) { + struct sock *sk = chan->sk; struct l2cap_conn_rsp rsp; __u16 res, stat; + lock_sock(sk); + if (!status) { if (bt_sk(sk)->defer_setup) { struct sock *parent = bt_sk(sk)->parent; @@ -4622,6 +4652,8 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) stat = L2CAP_CS_NO_INFO; } + release_sock(sk); + rsp.scid = cpu_to_le16(chan->dcid); rsp.dcid = cpu_to_le16(chan->scid); rsp.result = cpu_to_le16(res); @@ -4630,7 +4662,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) sizeof(rsp), &rsp); } - bh_unlock_sock(sk); + l2cap_chan_unlock(chan); } mutex_unlock(&conn->chan_lock); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 1273fcb..bbc1747 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -127,6 +127,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al if (err) goto done; + lock_sock(sk); + err = bt_sock_wait_state(sk, BT_CONNECTED, sock_sndtimeo(sk, flags & O_NONBLOCK)); done: @@ -809,15 +811,18 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) if (conn) mutex_lock(&conn->chan_lock); - + l2cap_chan_lock(chan); lock_sock(sk); + if (!sk->sk_shutdown) { if (chan->mode == L2CAP_MODE_ERTM) err = __l2cap_wait_ack(sk); sk->sk_shutdown = SHUTDOWN_MASK; + release_sock(sk); l2cap_chan_close(chan, 0); + lock_sock(sk); if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) err = bt_sock_wait_state(sk, BT_CLOSED, @@ -828,7 +833,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) err = -sk->sk_err; release_sock(sk); - + l2cap_chan_unlock(chan); if (conn) mutex_unlock(&conn->chan_lock); @@ -874,8 +879,12 @@ static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb) struct sock *sk = data; struct l2cap_pinfo *pi = l2cap_pi(sk); - if (pi->rx_busy_skb) - return -ENOMEM; + lock_sock(sk); + + if (pi->rx_busy_skb) { + err = -ENOMEM; + goto done; + } err = sock_queue_rcv_skb(sk, skb); @@ -894,6 +903,9 @@ static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb) err = 0; } +done: + release_sock(sk); + return err; } -- 1.7.9 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCHv2 3/3] Bluetooth: Remove socket lock check 2012-02-22 10:43 [PATCHv2 0/3] Bluetooth: Change socket lock to l2cap_chan lock Andrei Emeltchenko 2012-02-22 10:43 ` [PATCHv2 1/3] Bluetooth: Add unlocked __l2cap_chan_add function Andrei Emeltchenko 2012-02-22 10:43 ` [PATCHv2 2/3] Bluetooth: Change sk lock to chan lock in L2CAP core Andrei Emeltchenko @ 2012-02-22 10:43 ` Andrei Emeltchenko 2012-02-22 12:30 ` [PATCHv2 0/3] Bluetooth: Change socket lock to l2cap_chan lock Ulisses Furquim 3 siblings, 0 replies; 7+ messages in thread From: Andrei Emeltchenko @ 2012-02-22 10:43 UTC (permalink / raw) To: linux-bluetooth From: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Simplify code so that we do not need to check whether socket is locked. Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Acked-by: Gustavo F. Padovan <padovan@profusion.mobi> --- net/bluetooth/l2cap_sock.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index bbc1747..e2fc24b 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -125,15 +125,15 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al err = l2cap_chan_connect(chan, la.l2_psm, la.l2_cid, &la.l2_bdaddr); if (err) - goto done; + return err; lock_sock(sk); err = bt_sock_wait_state(sk, BT_CONNECTED, sock_sndtimeo(sk, flags & O_NONBLOCK)); -done: - if (sock_owned_by_user(sk)) - release_sock(sk); + + release_sock(sk); + return err; } -- 1.7.9 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCHv2 0/3] Bluetooth: Change socket lock to l2cap_chan lock 2012-02-22 10:43 [PATCHv2 0/3] Bluetooth: Change socket lock to l2cap_chan lock Andrei Emeltchenko ` (2 preceding siblings ...) 2012-02-22 10:43 ` [PATCHv2 3/3] Bluetooth: Remove socket lock check Andrei Emeltchenko @ 2012-02-22 12:30 ` Ulisses Furquim 2012-02-22 13:21 ` Andrei Emeltchenko 3 siblings, 1 reply; 7+ messages in thread From: Ulisses Furquim @ 2012-02-22 12:30 UTC (permalink / raw) To: Andrei Emeltchenko; +Cc: linux-bluetooth Hi Andrei, On Wed, Feb 22, 2012 at 8:43 AM, Andrei Emeltchenko <Andrei.Emeltchenko.news@gmail.com> wrote: > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com> > > Changing socket lock to L2CAP chan lock in L2CAP code. Needed for implementing > protocols above L2CAP without creating sockets. > > Changes: > * PATCHv2: Rebase remaining parts against latest tree and merge all > patches dealing with converting sk lock to chan lock together following > recommendation from Ulisses and Gustavo. > * PATCHv1: Added extra line (per Gustavo comment) > * RFCv6: Same code but patches 2,3 and 4 from RFCv5 are merged together > following recommendations from review. > * RFCv5: Fixed locking bug in l2cap_data_channel, added locks in > l2cap_sock_shutdown function, fixed several styles issues. > * RFCv4: Better split patches so they looks more clear and obvious, > taking coments about naming change and delete unused vars. See diff change > from the previous version below: > * RFCv3: Split the big patch to several small (I believe logical) chunks, > remove unneded locks from cleanup_listen, use the same arguments for > locked/unlocked socket error functions. > * RFCv2: Convert l2cap channel list back to mutex from RCU list. > > Andrei Emeltchenko (3): > Bluetooth: Add unlocked __l2cap_chan_add function > Bluetooth: Change sk lock to chan lock in L2CAP core > Bluetooth: Remove socket lock check > > net/bluetooth/l2cap_core.c | 173 +++++++++++++++++++++++++++----------------- > net/bluetooth/l2cap_sock.c | 28 +++++-- > 2 files changed, 125 insertions(+), 76 deletions(-) I'm mostly ok with the patches. However, have you seen my questions on reply to PATCHv1 08/14? Please, check that. Thanks. Regards, -- Ulisses Furquim ProFUSION embedded systems http://profusion.mobi Mobile: +55 19 9250 0942 Skype: ulissesffs ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCHv2 0/3] Bluetooth: Change socket lock to l2cap_chan lock 2012-02-22 12:30 ` [PATCHv2 0/3] Bluetooth: Change socket lock to l2cap_chan lock Ulisses Furquim @ 2012-02-22 13:21 ` Andrei Emeltchenko 2012-02-22 13:53 ` Ulisses Furquim 0 siblings, 1 reply; 7+ messages in thread From: Andrei Emeltchenko @ 2012-02-22 13:21 UTC (permalink / raw) To: Ulisses Furquim; +Cc: linux-bluetooth Hi Ulisses, On Wed, Feb 22, 2012 at 10:30:40AM -0200, Ulisses Furquim wrote: > Hi Andrei, > > On Wed, Feb 22, 2012 at 8:43 AM, Andrei Emeltchenko > <Andrei.Emeltchenko.news@gmail.com> wrote: > > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com> > > > > Changing socket lock to L2CAP chan lock in L2CAP code. Needed for implementing > > protocols above L2CAP without creating sockets. > > > > Changes: > > * PATCHv2: Rebase remaining parts against latest tree and merge all > > patches dealing with converting sk lock to chan lock together following > > recommendation from Ulisses and Gustavo. > > * PATCHv1: Added extra line (per Gustavo comment) > > * RFCv6: Same code but patches 2,3 and 4 from RFCv5 are merged together > > following recommendations from review. > > * RFCv5: Fixed locking bug in l2cap_data_channel, added locks in > > l2cap_sock_shutdown function, fixed several styles issues. > > * RFCv4: Better split patches so they looks more clear and obvious, > > taking coments about naming change and delete unused vars. See diff change > > from the previous version below: > > * RFCv3: Split the big patch to several small (I believe logical) chunks, > > remove unneded locks from cleanup_listen, use the same arguments for > > locked/unlocked socket error functions. > > * RFCv2: Convert l2cap channel list back to mutex from RCU list. > > > > Andrei Emeltchenko (3): > > Bluetooth: Add unlocked __l2cap_chan_add function > > Bluetooth: Change sk lock to chan lock in L2CAP core > > Bluetooth: Remove socket lock check > > > > net/bluetooth/l2cap_core.c | 173 +++++++++++++++++++++++++++----------------- > > net/bluetooth/l2cap_sock.c | 28 +++++-- > > 2 files changed, 125 insertions(+), 76 deletions(-) > > I'm mostly ok with the patches. However, have you seen my questions on > reply to PATCHv1 08/14? Please, check that. Thanks. Sorry missed those comments. In a case of: <------8<--------------------------------------------------------------------- | > @@ -440,10 +444,12 @@ void l2cap_chan_close(struct l2cap_chan *chan, int | > reason) | > | > switch (chan->state) { | > case BT_LISTEN: | > + lock_sock(sk); | > l2cap_chan_cleanup_listen(sk); | > | > __l2cap_state_change(chan, BT_CLOSED); | > sock_set_flag(sk, SOCK_ZAPPED); | > + release_sock(sk); | > break; | > | > case BT_CONNECTED: | | Do we need to lock sock around l2cap_chan_cleanup_listen() as well? | l2cap_chan_close() will call l2cap_chan_del() which now does | lock_sock/release_sock, right? <------8<--------------------------------------------------------------------- Those are different socks. We take parent sk lock here. concerning: <------8<------------------------------------------------------------------ | > @@ -714,6 +722,7 @@ static inline int l2cap_mode_supported(__u8 mode, | > __u32 feat_mask) | > | > static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct | > l2cap_chan *chan, int err) | > { | > + struct sock *sk = chan->sk; | > struct l2cap_disconn_req req; | > | > if (!conn) | > @@ -730,8 +739,10 @@ static void l2cap_send_disconn_req(struct | > l2cap_conn *conn, struct l2cap_chan *c | > l2cap_send_cmd(conn, l2cap_get_ident(conn), | > L2CAP_DISCONN_REQ, sizeof(req), &req); | > | > + lock_sock(sk); | > __l2cap_state_change(chan, BT_DISCONN); | > __l2cap_chan_set_err(chan, err); | > + release_sock(sk); | > } | > | > /* ---- L2CAP connections ---- */ | | It seems we didn't have any locking around these before. Why? Do we | really need it now? <------8<------------------------------------------------------------------ The locks were in the functions invoking l2cap_send_disconn_req. Otherwise would following changes be OK? diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 60d3276..56a85c0 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -363,8 +363,6 @@ void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) mutex_unlock(&conn->chan_lock); } -/* Delete channel. - * Must be called on the locked socket. */ static void l2cap_chan_del(struct l2cap_chan *chan, int err) { struct sock *sk = chan->sk; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index ae15d7a..efe391e 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -812,6 +812,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) if (conn) mutex_lock(&conn->chan_lock); + l2cap_chan_lock(chan); lock_sock(sk); @@ -835,6 +836,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) release_sock(sk); l2cap_chan_unlock(chan); + if (conn) mutex_unlock(&conn->chan_lock); Best regards Andrei Emeltchenko ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCHv2 0/3] Bluetooth: Change socket lock to l2cap_chan lock 2012-02-22 13:21 ` Andrei Emeltchenko @ 2012-02-22 13:53 ` Ulisses Furquim 0 siblings, 0 replies; 7+ messages in thread From: Ulisses Furquim @ 2012-02-22 13:53 UTC (permalink / raw) To: Andrei Emeltchenko, Ulisses Furquim, linux-bluetooth Hi Andrei, On Wed, Feb 22, 2012 at 11:21 AM, Andrei Emeltchenko <Andrei.Emeltchenko.news@gmail.com> wrote: > Hi Ulisses, > > On Wed, Feb 22, 2012 at 10:30:40AM -0200, Ulisses Furquim wrote: >> Hi Andrei, >> >> On Wed, Feb 22, 2012 at 8:43 AM, Andrei Emeltchenko >> <Andrei.Emeltchenko.news@gmail.com> wrote: >> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com> >> > >> > Changing socket lock to L2CAP chan lock in L2CAP code. Needed for implementing >> > protocols above L2CAP without creating sockets. >> > >> > Changes: >> > * PATCHv2: Rebase remaining parts against latest tree and merge all >> > patches dealing with converting sk lock to chan lock together following >> > recommendation from Ulisses and Gustavo. >> > * PATCHv1: Added extra line (per Gustavo comment) >> > * RFCv6: Same code but patches 2,3 and 4 from RFCv5 are merged together >> > following recommendations from review. >> > * RFCv5: Fixed locking bug in l2cap_data_channel, added locks in >> > l2cap_sock_shutdown function, fixed several styles issues. >> > * RFCv4: Better split patches so they looks more clear and obvious, >> > taking coments about naming change and delete unused vars. See diff change >> > from the previous version below: >> > * RFCv3: Split the big patch to several small (I believe logical) chunks, >> > remove unneded locks from cleanup_listen, use the same arguments for >> > locked/unlocked socket error functions. >> > * RFCv2: Convert l2cap channel list back to mutex from RCU list. >> > >> > Andrei Emeltchenko (3): >> > Bluetooth: Add unlocked __l2cap_chan_add function >> > Bluetooth: Change sk lock to chan lock in L2CAP core >> > Bluetooth: Remove socket lock check >> > >> > net/bluetooth/l2cap_core.c | 173 +++++++++++++++++++++++++++----------------- >> > net/bluetooth/l2cap_sock.c | 28 +++++-- >> > 2 files changed, 125 insertions(+), 76 deletions(-) >> >> I'm mostly ok with the patches. However, have you seen my questions on >> reply to PATCHv1 08/14? Please, check that. Thanks. > > Sorry missed those comments. > > In a case of: > <------8<--------------------------------------------------------------------- > | > @@ -440,10 +444,12 @@ void l2cap_chan_close(struct l2cap_chan *chan, int > | > reason) > | > > | > switch (chan->state) { > | > case BT_LISTEN: > | > + lock_sock(sk); > | > l2cap_chan_cleanup_listen(sk); > | > > | > __l2cap_state_change(chan, BT_CLOSED); > | > sock_set_flag(sk, SOCK_ZAPPED); > | > + release_sock(sk); > | > break; > | > > | > case BT_CONNECTED: > | > | Do we need to lock sock around l2cap_chan_cleanup_listen() as well? > | l2cap_chan_close() will call l2cap_chan_del() which now does > | lock_sock/release_sock, right? > <------8<--------------------------------------------------------------------- > > Those are different socks. We take parent sk lock here. Hmm, ok, I missed that. > concerning: > > <------8<------------------------------------------------------------------ > | > @@ -714,6 +722,7 @@ static inline int l2cap_mode_supported(__u8 mode, > | > __u32 feat_mask) > | > > | > static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct > | > l2cap_chan *chan, int err) > | > { > | > + struct sock *sk = chan->sk; > | > struct l2cap_disconn_req req; > | > > | > if (!conn) > | > @@ -730,8 +739,10 @@ static void l2cap_send_disconn_req(struct > | > l2cap_conn *conn, struct l2cap_chan *c > | > l2cap_send_cmd(conn, l2cap_get_ident(conn), > | > L2CAP_DISCONN_REQ, sizeof(req), &req); > | > > | > + lock_sock(sk); > | > __l2cap_state_change(chan, BT_DISCONN); > | > __l2cap_chan_set_err(chan, err); > | > + release_sock(sk); > | > } > | > > | > /* ---- L2CAP connections ---- */ > | > | It seems we didn't have any locking around these before. Why? Do we > | really need it now? > <------8<------------------------------------------------------------------ > > The locks were in the functions invoking l2cap_send_disconn_req. Ok. > Otherwise would following changes be OK? Sure, I'm ok with them if you only squashed them and added these tiny changes below. Reviewed-by: Ulisses Furquim <ulisses@profusion.mobi> Regards, -- Ulisses > diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c > index 60d3276..56a85c0 100644 > --- a/net/bluetooth/l2cap_core.c > +++ b/net/bluetooth/l2cap_core.c > @@ -363,8 +363,6 @@ void l2cap_chan_add(struct l2cap_conn *conn, struct > l2cap_chan *chan) > mutex_unlock(&conn->chan_lock); > } > > -/* Delete channel. > - * Must be called on the locked socket. */ > static void l2cap_chan_del(struct l2cap_chan *chan, int err) > { > struct sock *sk = chan->sk; > diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c > index ae15d7a..efe391e 100644 > --- a/net/bluetooth/l2cap_sock.c > +++ b/net/bluetooth/l2cap_sock.c > @@ -812,6 +812,7 @@ static int l2cap_sock_shutdown(struct socket *sock, > int how) > > if (conn) > mutex_lock(&conn->chan_lock); > + > l2cap_chan_lock(chan); > lock_sock(sk); > > @@ -835,6 +836,7 @@ static int l2cap_sock_shutdown(struct socket *sock, > int how) > > release_sock(sk); > l2cap_chan_unlock(chan); > + > if (conn) > mutex_unlock(&conn->chan_lock); > > > Best regards > Andrei Emeltchenko -- Ulisses Furquim ProFUSION embedded systems http://profusion.mobi Mobile: +55 19 9250 0942 Skype: ulissesffs ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2012-02-22 13:53 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-02-22 10:43 [PATCHv2 0/3] Bluetooth: Change socket lock to l2cap_chan lock Andrei Emeltchenko 2012-02-22 10:43 ` [PATCHv2 1/3] Bluetooth: Add unlocked __l2cap_chan_add function Andrei Emeltchenko 2012-02-22 10:43 ` [PATCHv2 2/3] Bluetooth: Change sk lock to chan lock in L2CAP core Andrei Emeltchenko 2012-02-22 10:43 ` [PATCHv2 3/3] Bluetooth: Remove socket lock check Andrei Emeltchenko 2012-02-22 12:30 ` [PATCHv2 0/3] Bluetooth: Change socket lock to l2cap_chan lock Ulisses Furquim 2012-02-22 13:21 ` Andrei Emeltchenko 2012-02-22 13:53 ` Ulisses Furquim
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).