linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFCv0 0/5] Bluetooth: Change socket lock to l2cap_chan lock
@ 2012-01-30 15:09 Emeltchenko Andrei
  2012-01-30 15:09 ` [RFCv0 1/5] Bluetooth: Use locks in RCU updater code Emeltchenko Andrei
                   ` (4 more replies)
  0 siblings, 5 replies; 15+ messages in thread
From: Emeltchenko Andrei @ 2012-01-30 15:09 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

This is DRAFT RFC introducing l2cap channel lock. Please make suggestion how to
make it better.

Beside changing socket locks to l2cap_chan lock channel list lock is reverted.
It is now used to protect RCU updaters or RCU lists which might sleep and not
protected by rcu_read_lock.

Andrei Emeltchenko (5):
  Bluetooth: Use locks in RCU updater code
  Bluetooth: Add l2cap_chan_lock
  Bluetooth: Helper functions for locking change
  Bluetooth: Remove unneeded sk variable
  Bluetooth: Change sk lock to l2cap_chan lock

 include/net/bluetooth/l2cap.h |   11 ++
 net/bluetooth/l2cap_core.c    |  267 ++++++++++++++++++++++++++---------------
 net/bluetooth/l2cap_sock.c    |   13 ++-
 3 files changed, 193 insertions(+), 98 deletions(-)

-- 
1.7.4.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [RFCv0 1/5] Bluetooth: Use locks in RCU updater code
  2012-01-30 15:09 [RFCv0 0/5] Bluetooth: Change socket lock to l2cap_chan lock Emeltchenko Andrei
@ 2012-01-30 15:09 ` Emeltchenko Andrei
  2012-01-30 17:17   ` Ulisses Furquim
  2012-01-30 15:09 ` [RFCv0 2/5] Bluetooth: Add l2cap_chan_lock Emeltchenko Andrei
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Emeltchenko Andrei @ 2012-01-30 15:09 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Code which makes changes to RCU list shall be locked.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/l2cap_core.c |   13 +++++++++----
 1 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 6991821..f54768e 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -743,13 +743,13 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c
 /* ---- L2CAP connections ---- */
 static void l2cap_conn_start(struct l2cap_conn *conn)
 {
-	struct l2cap_chan *chan;
+	struct l2cap_chan *chan, *tmp;
 
 	BT_DBG("conn %p", conn);
 
-	rcu_read_lock();
+	mutex_lock(&conn->chan_lock);
 
-	list_for_each_entry_rcu(chan, &conn->chan_l, list) {
+	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
 		struct sock *sk = chan->sk;
 
 		bh_lock_sock(sk);
@@ -829,7 +829,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 		bh_unlock_sock(sk);
 	}
 
-	rcu_read_unlock();
+	mutex_unlock(&conn->chan_lock);
 }
 
 /* Find socket with cid and source bdaddr.
@@ -1009,6 +1009,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
 
 	kfree_skb(conn->rx_skb);
 
+	mutex_lock(&conn->chan_lock);
+
 	/* Kill channels */
 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
 		sk = chan->sk;
@@ -1018,6 +1020,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
 		chan->ops->close(chan->data);
 	}
 
+	mutex_unlock(&conn->chan_lock);
+
 	hci_chan_del(conn->hchan);
 
 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
@@ -1075,6 +1079,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
 	conn->feat_mask = 0;
 
 	spin_lock_init(&conn->lock);
+	mutex_init(&conn->chan_lock);
 
 	INIT_LIST_HEAD(&conn->chan_l);
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFCv0 2/5] Bluetooth: Add l2cap_chan_lock
  2012-01-30 15:09 [RFCv0 0/5] Bluetooth: Change socket lock to l2cap_chan lock Emeltchenko Andrei
  2012-01-30 15:09 ` [RFCv0 1/5] Bluetooth: Use locks in RCU updater code Emeltchenko Andrei
@ 2012-01-30 15:09 ` Emeltchenko Andrei
  2012-01-30 17:18   ` Ulisses Furquim
  2012-01-30 15:09 ` [RFCv0 3/5] Bluetooth: Helper functions for locking change Emeltchenko Andrei
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Emeltchenko Andrei @ 2012-01-30 15:09 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Channel lock will be used to lock L2CAP channels which are locked
currently by socket locks.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |   11 +++++++++++
 net/bluetooth/l2cap_core.c    |    2 ++
 2 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index e7a8cc7..e81f235 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -497,6 +497,7 @@ struct l2cap_chan {
 
 	void		*data;
 	struct l2cap_ops *ops;
+	struct mutex		lock;
 };
 
 struct l2cap_ops {
@@ -609,6 +610,16 @@ static inline void l2cap_chan_put(struct l2cap_chan *c)
 		kfree(c);
 }
 
+static inline void l2cap_chan_lock(struct l2cap_chan *chan)
+{
+	mutex_lock(&chan->lock);
+}
+
+static inline void l2cap_chan_unlock(struct l2cap_chan *chan)
+{
+	mutex_unlock(&chan->lock);
+}
+
 static inline void l2cap_set_timer(struct l2cap_chan *chan,
 					struct delayed_work *work, long timeout)
 {
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index f54768e..9a23b19 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -285,6 +285,8 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk)
 	if (!chan)
 		return NULL;
 
+	mutex_init(&chan->lock);
+
 	chan->sk = sk;
 
 	write_lock(&chan_list_lock);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFCv0 3/5] Bluetooth: Helper functions for locking change
  2012-01-30 15:09 [RFCv0 0/5] Bluetooth: Change socket lock to l2cap_chan lock Emeltchenko Andrei
  2012-01-30 15:09 ` [RFCv0 1/5] Bluetooth: Use locks in RCU updater code Emeltchenko Andrei
  2012-01-30 15:09 ` [RFCv0 2/5] Bluetooth: Add l2cap_chan_lock Emeltchenko Andrei
@ 2012-01-30 15:09 ` Emeltchenko Andrei
  2012-01-30 17:25   ` Ulisses Furquim
  2012-01-30 15:09 ` [RFCv0 4/5] Bluetooth: Remove unneeded sk variable Emeltchenko Andrei
  2012-01-30 15:09 ` [RFCv0 5/5] Bluetooth: Change sk lock to l2cap_chan lock Emeltchenko Andrei
  4 siblings, 1 reply; 15+ messages in thread
From: Emeltchenko Andrei @ 2012-01-30 15:09 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>


Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/l2cap_core.c |   23 ++++++++++++++++++++++-
 1 files changed, 22 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9a23b19..a7e5a55 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -241,7 +241,7 @@ static char *state_to_string(int state)
 	return "invalid state";
 }
 
-static void l2cap_state_change(struct l2cap_chan *chan, int state)
+static void __l2cap_state_change(struct l2cap_chan *chan, int state)
 {
 	BT_DBG("%p %s -> %s", chan, state_to_string(chan->state),
 						state_to_string(state));
@@ -250,6 +250,27 @@ static void l2cap_state_change(struct l2cap_chan *chan, int state)
 	chan->ops->state_change(chan->data, state);
 }
 
+static void l2cap_state_change(struct l2cap_chan *chan, int state)
+{
+	lock_sock(chan->sk);
+	__l2cap_state_change(chan, state);
+	release_sock(chan->sk);
+}
+
+static inline void __l2cap_set_sock_err(struct sock *sk, int err)
+{
+	sk->sk_err = err;
+}
+
+static inline void l2cap_set_sock_err(struct l2cap_chan *chan, int err)
+{
+	struct sock *sk = chan->sk;
+
+	lock_sock(sk);
+	__l2cap_set_sock_err(sk, err);
+	release_sock(sk);
+}
+
 static void l2cap_chan_timeout(struct work_struct *work)
 {
 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFCv0 4/5] Bluetooth: Remove unneeded sk variable
  2012-01-30 15:09 [RFCv0 0/5] Bluetooth: Change socket lock to l2cap_chan lock Emeltchenko Andrei
                   ` (2 preceding siblings ...)
  2012-01-30 15:09 ` [RFCv0 3/5] Bluetooth: Helper functions for locking change Emeltchenko Andrei
@ 2012-01-30 15:09 ` Emeltchenko Andrei
  2012-01-30 17:26   ` Ulisses Furquim
  2012-01-30 15:09 ` [RFCv0 5/5] Bluetooth: Change sk lock to l2cap_chan lock Emeltchenko Andrei
  4 siblings, 1 reply; 15+ messages in thread
From: Emeltchenko Andrei @ 2012-01-30 15:09 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

In debug use chan %p instead of sk.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/l2cap_core.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index a7e5a55..4a22602 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1589,13 +1589,12 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
 						struct msghdr *msg, size_t len,
 						u32 priority)
 {
-	struct sock *sk = chan->sk;
 	struct l2cap_conn *conn = chan->conn;
 	struct sk_buff *skb;
 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
 	struct l2cap_hdr *lh;
 
-	BT_DBG("sk %p len %d priority %u", sk, (int)len, priority);
+	BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
 
 	count = min_t(unsigned int, (conn->mtu - hlen), len);
 
@@ -1625,13 +1624,12 @@ static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
 						struct msghdr *msg, size_t len,
 						u32 priority)
 {
-	struct sock *sk = chan->sk;
 	struct l2cap_conn *conn = chan->conn;
 	struct sk_buff *skb;
 	int err, count, hlen = L2CAP_HDR_SIZE;
 	struct l2cap_hdr *lh;
 
-	BT_DBG("sk %p len %d", sk, (int)len);
+	BT_DBG("chan %p len %d", chan, (int)len);
 
 	count = min_t(unsigned int, (conn->mtu - hlen), len);
 
@@ -1660,13 +1658,12 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
 						struct msghdr *msg, size_t len,
 						u32 control, u16 sdulen)
 {
-	struct sock *sk = chan->sk;
 	struct l2cap_conn *conn = chan->conn;
 	struct sk_buff *skb;
 	int err, count, hlen;
 	struct l2cap_hdr *lh;
 
-	BT_DBG("sk %p len %d", sk, (int)len);
+	BT_DBG("chan %p len %d", chan, (int)len);
 
 	if (!conn)
 		return ERR_PTR(-ENOTCONN);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFCv0 5/5] Bluetooth: Change sk lock to l2cap_chan lock
  2012-01-30 15:09 [RFCv0 0/5] Bluetooth: Change socket lock to l2cap_chan lock Emeltchenko Andrei
                   ` (3 preceding siblings ...)
  2012-01-30 15:09 ` [RFCv0 4/5] Bluetooth: Remove unneeded sk variable Emeltchenko Andrei
@ 2012-01-30 15:09 ` Emeltchenko Andrei
  2012-01-30 17:46   ` Ulisses Furquim
  4 siblings, 1 reply; 15+ messages in thread
From: Emeltchenko Andrei @ 2012-01-30 15:09 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Change socket lock to l2cap_chan lock. This is needed for use l2cap
channels without opening kernel socket for locking.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/l2cap_core.c |  220 +++++++++++++++++++++++++++-----------------
 net/bluetooth/l2cap_sock.c |   13 ++-
 2 files changed, 146 insertions(+), 87 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 4a22602..85b4572 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -275,12 +275,12 @@ static void l2cap_chan_timeout(struct work_struct *work)
 {
 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
 							chan_timer.work);
-	struct sock *sk = chan->sk;
 	int reason;
 
 	BT_DBG("chan %p state %d", chan, chan->state);
 
-	lock_sock(sk);
+	mutex_lock(&chan->conn->chan_lock);
+	l2cap_chan_lock(chan);
 
 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
 		reason = ECONNREFUSED;
@@ -292,7 +292,8 @@ static void l2cap_chan_timeout(struct work_struct *work)
 
 	l2cap_chan_close(chan, reason);
 
-	release_sock(sk);
+	l2cap_chan_unlock(chan);
+	mutex_unlock(&chan->conn->chan_lock);
 
 	chan->ops->close(chan->data);
 	l2cap_chan_put(chan);
@@ -406,11 +407,13 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
 		hci_conn_put(conn->hcon);
 	}
 
-	l2cap_state_change(chan, BT_CLOSED);
+	lock_sock(sk);
+
+	__l2cap_state_change(chan, BT_CLOSED);
 	sock_set_flag(sk, SOCK_ZAPPED);
 
 	if (err)
-		sk->sk_err = err;
+		__l2cap_set_sock_err(sk, err);
 
 	if (parent) {
 		bt_accept_unlink(sk);
@@ -418,6 +421,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;
@@ -449,10 +454,14 @@ static void l2cap_chan_cleanup_listen(struct sock *parent)
 	/* Close not yet accepted channels */
 	while ((sk = bt_accept_dequeue(parent, NULL))) {
 		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+
+		mutex_lock(&chan->conn->chan_lock);
+		l2cap_chan_lock(chan);
 		__clear_chan_timer(chan);
-		lock_sock(sk);
 		l2cap_chan_close(chan, ECONNRESET);
-		release_sock(sk);
+		l2cap_chan_unlock(chan);
+		mutex_unlock(&chan->conn->chan_lock);
+
 		chan->ops->close(chan->data);
 	}
 }
@@ -466,10 +475,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);
+		__l2cap_state_change(chan, BT_CLOSED);
 		sock_set_flag(sk, SOCK_ZAPPED);
+		release_sock(sk);
 		break;
 
 	case BT_CONNECTED:
@@ -512,7 +523,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;
 	}
 }
@@ -740,14 +753,12 @@ 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;
+	struct sock *sk = chan->sk;
 	struct l2cap_disconn_req req;
 
 	if (!conn)
 		return;
 
-	sk = chan->sk;
-
 	if (chan->mode == L2CAP_MODE_ERTM) {
 		__clear_retrans_timer(chan);
 		__clear_monitor_timer(chan);
@@ -759,8 +770,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);
 
-	l2cap_state_change(chan, BT_DISCONN);
-	sk->sk_err = err;
+	lock_sock(sk);
+	__l2cap_state_change(chan, BT_DISCONN);
+	__l2cap_set_sock_err(sk, err);
+	release_sock(sk);
 }
 
 /* ---- L2CAP connections ---- */
@@ -775,10 +788,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;
 		}
 
@@ -787,7 +800,7 @@ 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;
 			}
 
@@ -797,7 +810,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 				/* 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;
 			}
 
@@ -817,6 +830,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);
@@ -825,10 +839,11 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 						parent->sk_data_ready(parent, 0);
 
 				} else {
-					l2cap_state_change(chan, BT_CONFIG);
+					__l2cap_state_change(chan, BT_CONFIG);
 					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);
@@ -839,7 +854,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;
 			}
 
@@ -849,7 +864,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);
@@ -928,7 +943,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 
 	__set_chan_timer(chan, sk->sk_sndtimeo);
 
-	l2cap_state_change(chan, BT_CONNECTED);
+	__l2cap_state_change(chan, BT_CONNECTED);
 	parent->sk_data_ready(parent, 0);
 
 clean:
@@ -938,18 +953,24 @@ 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);
 
 	chan->conf_state = 0;
 	__clear_chan_timer(chan);
 
-	l2cap_state_change(chan, BT_CONNECTED);
+	__l2cap_state_change(chan, BT_CONNECTED);
 	sk->sk_state_change(sk);
 
 	if (parent)
 		parent->sk_data_ready(parent, 0);
+
+	release_sock(sk);
 }
 
 static void l2cap_conn_ready(struct l2cap_conn *conn)
@@ -964,29 +985,31 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
 	if (conn->hcon->out && conn->hcon->type == LE_LINK)
 		smp_conn_security(conn, conn->hcon->pending_sec_level);
 
-	rcu_read_lock();
+	mutex_lock(&conn->chan_lock);
 
-	list_for_each_entry_rcu(chan, &conn->chan_l, list) {
-		struct sock *sk = chan->sk;
+	list_for_each_entry(chan, &conn->chan_l, list) {
 
-		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);
-			l2cap_state_change(chan, BT_CONNECTED);
+			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);
 	}
 
-	rcu_read_unlock();
+	mutex_unlock(&conn->chan_lock);
 }
 
 /* Notify sockets that we cannot guaranty reliability anymore */
@@ -1001,8 +1024,12 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
 	list_for_each_entry_rcu(chan, &conn->chan_l, list) {
 		struct sock *sk = chan->sk;
 
+		lock_sock(sk);
+
 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
-			sk->sk_err = err;
+			__l2cap_set_sock_err(sk, err);
+
+		release_sock(sk);
 	}
 
 	rcu_read_unlock();
@@ -1023,7 +1050,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;
@@ -1036,10 +1062,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);
 	}
 
@@ -1251,14 +1279,14 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *d
 
 	l2cap_chan_add(conn, 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);
 	}
@@ -1307,40 +1335,39 @@ 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);
-		return;
+		goto done;
 	}
 
 	chan->retry_count++;
 	__set_monitor_timer(chan);
 
 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
-	release_sock(sk);
+done:
+	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)
@@ -2029,9 +2056,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);
 }
@@ -2702,22 +2731,22 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
 		if (l2cap_chan_check_security(chan)) {
 			if (bt_sk(sk)->defer_setup) {
-				l2cap_state_change(chan, BT_CONNECT2);
+				__l2cap_state_change(chan, BT_CONNECT2);
 				result = L2CAP_CR_PEND;
 				status = L2CAP_CS_AUTHOR_PEND;
 				parent->sk_data_ready(parent, 0);
 			} else {
-				l2cap_state_change(chan, BT_CONFIG);
+				__l2cap_state_change(chan, BT_CONFIG);
 				result = L2CAP_CR_SUCCESS;
 				status = L2CAP_CS_NO_INFO;
 			}
 		} else {
-			l2cap_state_change(chan, BT_CONNECT2);
+			__l2cap_state_change(chan, BT_CONNECT2);
 			result = L2CAP_CR_PEND;
 			status = L2CAP_CS_AUTHEN_PEND;
 		}
 	} else {
-		l2cap_state_change(chan, BT_CONNECT2);
+		__l2cap_state_change(chan, BT_CONNECT2);
 		result = L2CAP_CR_PEND;
 		status = L2CAP_CS_NO_INFO;
 	}
@@ -2774,15 +2803,18 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
 
 	if (scid) {
-		chan = l2cap_get_chan_by_scid(conn, scid);
+		chan = __l2cap_get_chan_by_scid(conn, scid);
 		if (!chan)
 			return -EFAULT;
 	} else {
-		chan = l2cap_get_chan_by_ident(conn, cmd->ident);
+		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
 		if (!chan)
 			return -EFAULT;
 	}
 
+	mutex_lock(&conn->chan_lock);
+	l2cap_chan_lock(chan);
+
 	sk = chan->sk;
 
 	switch (result) {
@@ -2809,7 +2841,9 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 		break;
 	}
 
-	release_sock(sk);
+	l2cap_chan_unlock(chan);
+	mutex_unlock(&conn->chan_lock);
+
 	return 0;
 }
 
@@ -2838,10 +2872,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
 
-	chan = l2cap_get_chan_by_scid(conn, dcid);
+	chan = __l2cap_get_chan_by_scid(conn, dcid);
 	if (!chan)
 		return -ENOENT;
 
+	l2cap_chan_lock(chan);
+
 	sk = chan->sk;
 
 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
@@ -2931,7 +2967,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;
 }
 
@@ -2950,10 +2986,12 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
 			scid, flags, result);
 
-	chan = l2cap_get_chan_by_scid(conn, scid);
+	chan = __l2cap_get_chan_by_scid(conn, scid);
 	if (!chan)
 		return 0;
 
+	l2cap_chan_lock(chan);
+
 	sk = chan->sk;
 
 	switch (result) {
@@ -3013,7 +3051,8 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 		}
 
 	default:
-		sk->sk_err = ECONNRESET;
+		l2cap_set_sock_err(chan, ECONNRESET);
+
 		__set_chan_timer(chan,
 				msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT));
 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
@@ -3039,7 +3078,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,20 +3095,27 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
 
 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
 
-	chan = l2cap_get_chan_by_scid(conn, dcid);
+	chan = __l2cap_get_chan_by_scid(conn, dcid);
 	if (!chan)
 		return 0;
 
+	mutex_lock(&conn->chan_lock);
+	l2cap_chan_lock(chan);
+
 	sk = chan->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);
+	mutex_unlock(&conn->chan_lock);
 
 	chan->ops->close(chan->data);
 	return 0;
@@ -3080,21 +3126,23 @@ 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);
 
 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
 
-	chan = l2cap_get_chan_by_scid(conn, scid);
+	chan = __l2cap_get_chan_by_scid(conn, scid);
 	if (!chan)
 		return 0;
 
-	sk = chan->sk;
+	mutex_lock(&conn->chan_lock);
+	l2cap_chan_lock(chan);
 
 	l2cap_chan_del(chan, 0);
-	release_sock(sk);
+
+	l2cap_chan_unlock(chan);
+	mutex_unlock(&conn->chan_lock);
 
 	chan->ops->close(chan->data);
 	return 0;
@@ -4243,18 +4291,17 @@ 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;
 
-	chan = l2cap_get_chan_by_scid(conn, cid);
+	chan = __l2cap_get_chan_by_scid(conn, cid);
 	if (!chan) {
 		BT_DBG("unknown cid 0x%4.4x", cid);
 		goto drop;
 	}
 
-	sk = chan->sk;
+	l2cap_chan_lock(chan);
 
 	BT_DBG("chan %p, len %d", chan, skb->len);
 
@@ -4325,8 +4372,7 @@ drop:
 	kfree_skb(skb);
 
 done:
-	if (sk)
-		release_sock(sk);
+	l2cap_chan_unlock(chan);
 
 	return 0;
 }
@@ -4542,12 +4588,10 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 		__cancel_delayed_work(&conn->security_timer);
 	}
 
-	rcu_read_lock();
-
-	list_for_each_entry_rcu(chan, &conn->chan_l, list) {
-		struct sock *sk = chan->sk;
+	mutex_lock(&conn->chan_lock);
 
-		bh_lock_sock(sk);
+	list_for_each_entry(chan, &conn->chan_l, list) {
+		l2cap_chan_lock(chan);
 
 		BT_DBG("chan->scid %d", chan->scid);
 
@@ -4557,19 +4601,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;
 		}
 
@@ -4590,9 +4634,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;
@@ -4601,18 +4648,20 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 					if (parent)
 						parent->sk_data_ready(parent, 0);
 				} else {
-					l2cap_state_change(chan, BT_CONFIG);
+					__l2cap_state_change(chan, BT_CONFIG);
 					res = L2CAP_CR_SUCCESS;
 					stat = L2CAP_CS_NO_INFO;
 				}
 			} else {
-				l2cap_state_change(chan, BT_DISCONN);
+				__l2cap_state_change(chan, BT_DISCONN);
 				__set_chan_timer(chan,
 					msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
 				res = L2CAP_CR_SEC_BLOCK;
 				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);
@@ -4621,10 +4670,10 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 							sizeof(rsp), &rsp);
 		}
 
-		bh_unlock_sock(sk);
+		l2cap_chan_unlock(chan);
 	}
 
-	rcu_read_unlock();
+	mutex_unlock(&conn->chan_lock);
 
 	return 0;
 }
@@ -4681,10 +4730,11 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 			goto drop;
 		}
 
-		chan = l2cap_get_chan_by_scid(conn, cid);
+		chan = __l2cap_get_chan_by_scid(conn, cid);
 
 		if (chan && chan->sk) {
 			struct sock *sk = chan->sk;
+			lock_sock(sk);
 
 			if (chan->imtu < len - L2CAP_HDR_SIZE) {
 				BT_ERR("Frame exceeding recv MTU (len %d, "
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 1636029..dea5418 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -809,7 +809,9 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
 			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,
@@ -862,8 +864,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);
 
@@ -882,6 +888,9 @@ static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb)
 		err = 0;
 	}
 
+done:
+	release_sock(sk);
+
 	return err;
 }
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [RFCv0 1/5] Bluetooth: Use locks in RCU updater code
  2012-01-30 15:09 ` [RFCv0 1/5] Bluetooth: Use locks in RCU updater code Emeltchenko Andrei
@ 2012-01-30 17:17   ` Ulisses Furquim
  2012-01-31  7:59     ` Emeltchenko Andrei
  0 siblings, 1 reply; 15+ messages in thread
From: Ulisses Furquim @ 2012-01-30 17:17 UTC (permalink / raw)
  To: Emeltchenko Andrei; +Cc: linux-bluetooth

Hi Andrei,

On Mon, Jan 30, 2012 at 1:09 PM, Emeltchenko Andrei
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> Code which makes changes to RCU list shall be locked.
>
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
>  net/bluetooth/l2cap_core.c |   13 +++++++++----
>  1 files changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 6991821..f54768e 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -743,13 +743,13 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c
>  /* ---- L2CAP connections ---- */
>  static void l2cap_conn_start(struct l2cap_conn *conn)
>  {
> -       struct l2cap_chan *chan;
> +       struct l2cap_chan *chan, *tmp;
>
>        BT_DBG("conn %p", conn);
>
> -       rcu_read_lock();
> +       mutex_lock(&conn->chan_lock);
>
> -       list_for_each_entry_rcu(chan, &conn->chan_l, list) {
> +       list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
>                struct sock *sk = chan->sk;
>
>                bh_lock_sock(sk);
> @@ -829,7 +829,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
>                bh_unlock_sock(sk);
>        }
>
> -       rcu_read_unlock();
> +       mutex_unlock(&conn->chan_lock);
>  }
>
>  /* Find socket with cid and source bdaddr.
> @@ -1009,6 +1009,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
>
>        kfree_skb(conn->rx_skb);
>
> +       mutex_lock(&conn->chan_lock);
> +
>        /* Kill channels */
>        list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
>                sk = chan->sk;
> @@ -1018,6 +1020,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
>                chan->ops->close(chan->data);
>        }
>
> +       mutex_unlock(&conn->chan_lock);
> +
>        hci_chan_del(conn->hchan);
>
>        if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
> @@ -1075,6 +1079,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
>        conn->feat_mask = 0;
>
>        spin_lock_init(&conn->lock);
> +       mutex_init(&conn->chan_lock);
>
>        INIT_LIST_HEAD(&conn->chan_l);
>

I was under the impression you'd remove RCU for conn->chan_l
completely. You're adding a lock only in the updaters? If so, please
take a look at commit 3d57dc680 which shows all changes from mutex to
RCU. I don't think just adding a lock/unlock in l2cap_conn_start and
l2cap_conn_del will be enough. l2cap_chan_add seems to be called from
other contexts and it does a list_add_rcu(). Have you thought of that?

Regards,

-- 
Ulisses Furquim
ProFUSION embedded systems
http://profusion.mobi
Mobile: +55 19 9250 0942
Skype: ulissesffs

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFCv0 2/5] Bluetooth: Add l2cap_chan_lock
  2012-01-30 15:09 ` [RFCv0 2/5] Bluetooth: Add l2cap_chan_lock Emeltchenko Andrei
@ 2012-01-30 17:18   ` Ulisses Furquim
  0 siblings, 0 replies; 15+ messages in thread
From: Ulisses Furquim @ 2012-01-30 17:18 UTC (permalink / raw)
  To: Emeltchenko Andrei; +Cc: linux-bluetooth

Hi Andrei,

On Mon, Jan 30, 2012 at 1:09 PM, Emeltchenko Andrei
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> Channel lock will be used to lock L2CAP channels which are locked
> currently by socket locks.
>
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
>  include/net/bluetooth/l2cap.h |   11 +++++++++++
>  net/bluetooth/l2cap_core.c    |    2 ++
>  2 files changed, 13 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index e7a8cc7..e81f235 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -497,6 +497,7 @@ struct l2cap_chan {
>
>        void            *data;
>        struct l2cap_ops *ops;
> +       struct mutex            lock;
>  };
>
>  struct l2cap_ops {
> @@ -609,6 +610,16 @@ static inline void l2cap_chan_put(struct l2cap_chan *c)
>                kfree(c);
>  }
>
> +static inline void l2cap_chan_lock(struct l2cap_chan *chan)
> +{
> +       mutex_lock(&chan->lock);
> +}
> +
> +static inline void l2cap_chan_unlock(struct l2cap_chan *chan)
> +{
> +       mutex_unlock(&chan->lock);
> +}
> +
>  static inline void l2cap_set_timer(struct l2cap_chan *chan,
>                                        struct delayed_work *work, long timeout)
>  {
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index f54768e..9a23b19 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -285,6 +285,8 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk)
>        if (!chan)
>                return NULL;
>
> +       mutex_init(&chan->lock);
> +
>        chan->sk = sk;
>
>        write_lock(&chan_list_lock);

This one looks good to me.

Regards,

-- 
Ulisses Furquim
ProFUSION embedded systems
http://profusion.mobi
Mobile: +55 19 9250 0942
Skype: ulissesffs

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFCv0 3/5] Bluetooth: Helper functions for locking change
  2012-01-30 15:09 ` [RFCv0 3/5] Bluetooth: Helper functions for locking change Emeltchenko Andrei
@ 2012-01-30 17:25   ` Ulisses Furquim
  0 siblings, 0 replies; 15+ messages in thread
From: Ulisses Furquim @ 2012-01-30 17:25 UTC (permalink / raw)
  To: Emeltchenko Andrei; +Cc: linux-bluetooth

Hi Andrei,

On Mon, Jan 30, 2012 at 1:09 PM, Emeltchenko Andrei
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

No commit message? In my opinion all commits should have a commit
message and even more in this patch set that deals with locking in
L2CAP core.

> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
>  net/bluetooth/l2cap_core.c |   23 ++++++++++++++++++++++-
>  1 files changed, 22 insertions(+), 1 deletions(-)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 9a23b19..a7e5a55 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -241,7 +241,7 @@ static char *state_to_string(int state)
>        return "invalid state";
>  }
>
> -static void l2cap_state_change(struct l2cap_chan *chan, int state)
> +static void __l2cap_state_change(struct l2cap_chan *chan, int state)
>  {
>        BT_DBG("%p %s -> %s", chan, state_to_string(chan->state),
>                                                state_to_string(state));
> @@ -250,6 +250,27 @@ static void l2cap_state_change(struct l2cap_chan *chan, int state)
>        chan->ops->state_change(chan->data, state);
>  }
>
> +static void l2cap_state_change(struct l2cap_chan *chan, int state)
> +{
> +       lock_sock(chan->sk);
> +       __l2cap_state_change(chan, state);
> +       release_sock(chan->sk);
> +}

Introducing this change now before the others in patch 5 will actually
change how l2cap_state_change works. Won't that cause any problems?

> +static inline void __l2cap_set_sock_err(struct sock *sk, int err)
> +{
> +       sk->sk_err = err;
> +}
> +
> +static inline void l2cap_set_sock_err(struct l2cap_chan *chan, int err)
> +{
> +       struct sock *sk = chan->sk;
> +
> +       lock_sock(sk);
> +       __l2cap_set_sock_err(sk, err);
> +       release_sock(sk);
> +}

This helper is different because it didn't exist before so I can say
we shall have no problems with it.

>  static void l2cap_chan_timeout(struct work_struct *work)
>  {
>        struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
> --
> 1.7.4.1

Regards,

-- 
Ulisses Furquim
ProFUSION embedded systems
http://profusion.mobi
Mobile: +55 19 9250 0942
Skype: ulissesffs

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFCv0 4/5] Bluetooth: Remove unneeded sk variable
  2012-01-30 15:09 ` [RFCv0 4/5] Bluetooth: Remove unneeded sk variable Emeltchenko Andrei
@ 2012-01-30 17:26   ` Ulisses Furquim
  0 siblings, 0 replies; 15+ messages in thread
From: Ulisses Furquim @ 2012-01-30 17:26 UTC (permalink / raw)
  To: Emeltchenko Andrei; +Cc: linux-bluetooth

Hi Andrei,

On Mon, Jan 30, 2012 at 1:09 PM, Emeltchenko Andrei
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> In debug use chan %p instead of sk.
>
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
>  net/bluetooth/l2cap_core.c |    9 +++------
>  1 files changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index a7e5a55..4a22602 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -1589,13 +1589,12 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
>                                                struct msghdr *msg, size_t len,
>                                                u32 priority)
>  {
> -       struct sock *sk = chan->sk;
>        struct l2cap_conn *conn = chan->conn;
>        struct sk_buff *skb;
>        int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
>        struct l2cap_hdr *lh;
>
> -       BT_DBG("sk %p len %d priority %u", sk, (int)len, priority);
> +       BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
>
>        count = min_t(unsigned int, (conn->mtu - hlen), len);
>
> @@ -1625,13 +1624,12 @@ static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
>                                                struct msghdr *msg, size_t len,
>                                                u32 priority)
>  {
> -       struct sock *sk = chan->sk;
>        struct l2cap_conn *conn = chan->conn;
>        struct sk_buff *skb;
>        int err, count, hlen = L2CAP_HDR_SIZE;
>        struct l2cap_hdr *lh;
>
> -       BT_DBG("sk %p len %d", sk, (int)len);
> +       BT_DBG("chan %p len %d", chan, (int)len);
>
>        count = min_t(unsigned int, (conn->mtu - hlen), len);
>
> @@ -1660,13 +1658,12 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
>                                                struct msghdr *msg, size_t len,
>                                                u32 control, u16 sdulen)
>  {
> -       struct sock *sk = chan->sk;
>        struct l2cap_conn *conn = chan->conn;
>        struct sk_buff *skb;
>        int err, count, hlen;
>        struct l2cap_hdr *lh;
>
> -       BT_DBG("sk %p len %d", sk, (int)len);
> +       BT_DBG("chan %p len %d", chan, (int)len);
>
>        if (!conn)
>                return ERR_PTR(-ENOTCONN);

This one looks good to me.

Regards,

-- 
Ulisses Furquim
ProFUSION embedded systems
http://profusion.mobi
Mobile: +55 19 9250 0942
Skype: ulissesffs

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFCv0 5/5] Bluetooth: Change sk lock to l2cap_chan lock
  2012-01-30 15:09 ` [RFCv0 5/5] Bluetooth: Change sk lock to l2cap_chan lock Emeltchenko Andrei
@ 2012-01-30 17:46   ` Ulisses Furquim
  2012-01-31  8:11     ` Emeltchenko Andrei
  0 siblings, 1 reply; 15+ messages in thread
From: Ulisses Furquim @ 2012-01-30 17:46 UTC (permalink / raw)
  To: Emeltchenko Andrei; +Cc: linux-bluetooth

Hi Andrei,

On Mon, Jan 30, 2012 at 1:09 PM, Emeltchenko Andrei
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> Change socket lock to l2cap_chan lock. This is needed for use l2cap
> channels without opening kernel socket for locking.
>
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
>  net/bluetooth/l2cap_core.c |  220 +++++++++++++++++++++++++++-----------------
>  net/bluetooth/l2cap_sock.c |   13 ++-
>  2 files changed, 146 insertions(+), 87 deletions(-)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 4a22602..85b4572 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -275,12 +275,12 @@ static void l2cap_chan_timeout(struct work_struct *work)
>  {
>        struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
>                                                        chan_timer.work);
> -       struct sock *sk = chan->sk;
>        int reason;
>
>        BT_DBG("chan %p state %d", chan, chan->state);
>
> -       lock_sock(sk);
> +       mutex_lock(&chan->conn->chan_lock);
> +       l2cap_chan_lock(chan);

Ugh, this doesn't look right or even pretty. Why do we need it this way?

>        if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
>                reason = ECONNREFUSED;
> @@ -292,7 +292,8 @@ static void l2cap_chan_timeout(struct work_struct *work)
>
>        l2cap_chan_close(chan, reason);
>
> -       release_sock(sk);
> +       l2cap_chan_unlock(chan);
> +       mutex_unlock(&chan->conn->chan_lock);
>
>        chan->ops->close(chan->data);
>        l2cap_chan_put(chan);
> @@ -406,11 +407,13 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
>                hci_conn_put(conn->hcon);
>        }
>
> -       l2cap_state_change(chan, BT_CLOSED);
> +       lock_sock(sk);
> +
> +       __l2cap_state_change(chan, BT_CLOSED);
>        sock_set_flag(sk, SOCK_ZAPPED);
>
>        if (err)
> -               sk->sk_err = err;
> +               __l2cap_set_sock_err(sk, err);
>
>        if (parent) {
>                bt_accept_unlink(sk);
> @@ -418,6 +421,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;
> @@ -449,10 +454,14 @@ static void l2cap_chan_cleanup_listen(struct sock *parent)
>        /* Close not yet accepted channels */
>        while ((sk = bt_accept_dequeue(parent, NULL))) {
>                struct l2cap_chan *chan = l2cap_pi(sk)->chan;
> +
> +               mutex_lock(&chan->conn->chan_lock);
> +               l2cap_chan_lock(chan);

Again.

>                __clear_chan_timer(chan);
> -               lock_sock(sk);
>                l2cap_chan_close(chan, ECONNRESET);
> -               release_sock(sk);
> +               l2cap_chan_unlock(chan);
> +               mutex_unlock(&chan->conn->chan_lock);
> +
>                chan->ops->close(chan->data);
>        }
>  }

<snip>

> @@ -964,29 +985,31 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
>        if (conn->hcon->out && conn->hcon->type == LE_LINK)
>                smp_conn_security(conn, conn->hcon->pending_sec_level);
>
> -       rcu_read_lock();
> +       mutex_lock(&conn->chan_lock);
>
> -       list_for_each_entry_rcu(chan, &conn->chan_l, list) {
> -               struct sock *sk = chan->sk;
> +       list_for_each_entry(chan, &conn->chan_l, list) {

Why are you removing RCU read locks here?

> -               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);
> -                       l2cap_state_change(chan, BT_CONNECTED);
> +                       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);
>        }
>
> -       rcu_read_unlock();
> +       mutex_unlock(&conn->chan_lock);
>  }

<snip>

This patch still mixes the return of using conn->chan_lock with
locking of l2cap_chan. It should be possible and better to have these
changes in different patches. Another question is will you remove RCU
usage for conn->chan_l completely or not?

Thanks,
Regards,

-- 
Ulisses Furquim
ProFUSION embedded systems
http://profusion.mobi
Mobile: +55 19 9250 0942
Skype: ulissesffs

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFCv0 1/5] Bluetooth: Use locks in RCU updater code
  2012-01-30 17:17   ` Ulisses Furquim
@ 2012-01-31  7:59     ` Emeltchenko Andrei
  2012-01-31 12:37       ` Ulisses Furquim
  0 siblings, 1 reply; 15+ messages in thread
From: Emeltchenko Andrei @ 2012-01-31  7:59 UTC (permalink / raw)
  To: Ulisses Furquim; +Cc: linux-bluetooth

Hi Ulisses,

On Mon, Jan 30, 2012 at 03:17:15PM -0200, Ulisses Furquim wrote:
> Hi Andrei,
> 
> On Mon, Jan 30, 2012 at 1:09 PM, Emeltchenko Andrei
> <Andrei.Emeltchenko.news@gmail.com> wrote:
> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> >
> > Code which makes changes to RCU list shall be locked.
> >
> > Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > ---
> >  net/bluetooth/l2cap_core.c |   13 +++++++++----
> >  1 files changed, 9 insertions(+), 4 deletions(-)
> >
> > diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> > index 6991821..f54768e 100644
> > --- a/net/bluetooth/l2cap_core.c
> > +++ b/net/bluetooth/l2cap_core.c
> > @@ -743,13 +743,13 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c
> >  /* ---- L2CAP connections ---- */
> >  static void l2cap_conn_start(struct l2cap_conn *conn)
> >  {
> > -       struct l2cap_chan *chan;
> > +       struct l2cap_chan *chan, *tmp;
> >
> >        BT_DBG("conn %p", conn);
> >
> > -       rcu_read_lock();
> > +       mutex_lock(&conn->chan_lock);
> >
> > -       list_for_each_entry_rcu(chan, &conn->chan_l, list) {
> > +       list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
> >                struct sock *sk = chan->sk;
> >
> >                bh_lock_sock(sk);
> > @@ -829,7 +829,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
> >                bh_unlock_sock(sk);
> >        }
> >
> > -       rcu_read_unlock();
> > +       mutex_unlock(&conn->chan_lock);
> >  }
> >
> >  /* Find socket with cid and source bdaddr.
> > @@ -1009,6 +1009,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
> >
> >        kfree_skb(conn->rx_skb);
> >
> > +       mutex_lock(&conn->chan_lock);
> > +
> >        /* Kill channels */
> >        list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
> >                sk = chan->sk;
> > @@ -1018,6 +1020,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
> >                chan->ops->close(chan->data);
> >        }
> >
> > +       mutex_unlock(&conn->chan_lock);
> > +
> >        hci_chan_del(conn->hchan);
> >
> >        if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
> > @@ -1075,6 +1079,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
> >        conn->feat_mask = 0;
> >
> >        spin_lock_init(&conn->lock);
> > +       mutex_init(&conn->chan_lock);
> >
> >        INIT_LIST_HEAD(&conn->chan_l);
> >
> 
> I was under the impression you'd remove RCU for conn->chan_l
> completely. You're adding a lock only in the updaters? If so, please
> take a look at commit 3d57dc680 which shows all changes from mutex to
> RCU. I don't think just adding a lock/unlock in l2cap_conn_start and
> l2cap_conn_del will be enough. l2cap_chan_add seems to be called from
> other contexts and it does a list_add_rcu(). Have you thought of that?

I am adding lock to updaters and to the places we need to sleep and
rcu_read_lock cannot be used. This patch adds locks to updaters and
following patches cover other places. Maybe I need to split them better.

Best regards 
Andrei Emeltchenko 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFCv0 5/5] Bluetooth: Change sk lock to l2cap_chan lock
  2012-01-30 17:46   ` Ulisses Furquim
@ 2012-01-31  8:11     ` Emeltchenko Andrei
  0 siblings, 0 replies; 15+ messages in thread
From: Emeltchenko Andrei @ 2012-01-31  8:11 UTC (permalink / raw)
  To: Ulisses Furquim; +Cc: linux-bluetooth

Hi Ulisses,

On Mon, Jan 30, 2012 at 03:46:27PM -0200, Ulisses Furquim wrote:
> Hi Andrei,
> 
> On Mon, Jan 30, 2012 at 1:09 PM, Emeltchenko Andrei
> <Andrei.Emeltchenko.news@gmail.com> wrote:
> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> >
> > Change socket lock to l2cap_chan lock. This is needed for use l2cap
> > channels without opening kernel socket for locking.
> >
> > Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > ---
> >  net/bluetooth/l2cap_core.c |  220 +++++++++++++++++++++++++++-----------------
> >  net/bluetooth/l2cap_sock.c |   13 ++-
> >  2 files changed, 146 insertions(+), 87 deletions(-)
> >
> > diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> > index 4a22602..85b4572 100644
> > --- a/net/bluetooth/l2cap_core.c
> > +++ b/net/bluetooth/l2cap_core.c
> > @@ -275,12 +275,12 @@ static void l2cap_chan_timeout(struct work_struct *work)
> >  {
> >        struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
> >                                                        chan_timer.work);
> > -       struct sock *sk = chan->sk;
> >        int reason;
> >
> >        BT_DBG("chan %p state %d", chan, chan->state);
> >
> > -       lock_sock(sk);
> > +       mutex_lock(&chan->conn->chan_lock);
> > +       l2cap_chan_lock(chan);
> 
> Ugh, this doesn't look right or even pretty. Why do we need it this way?

I try to keep order of locking, first conn->chan_lock and then chan->lock
otherwise I get warnings from lockdep. I am open to suggestions how to
make it better.

> >        if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
> >                reason = ECONNREFUSED;
> > @@ -292,7 +292,8 @@ static void l2cap_chan_timeout(struct work_struct *work)
> >
> >        l2cap_chan_close(chan, reason);
> >
> > -       release_sock(sk);
> > +       l2cap_chan_unlock(chan);
> > +       mutex_unlock(&chan->conn->chan_lock);
> >
> >        chan->ops->close(chan->data);
> >        l2cap_chan_put(chan);
> > @@ -406,11 +407,13 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
> >                hci_conn_put(conn->hcon);
> >        }
> >
> > -       l2cap_state_change(chan, BT_CLOSED);
> > +       lock_sock(sk);
> > +
> > +       __l2cap_state_change(chan, BT_CLOSED);
> >        sock_set_flag(sk, SOCK_ZAPPED);
> >
> >        if (err)
> > -               sk->sk_err = err;
> > +               __l2cap_set_sock_err(sk, err);
> >
> >        if (parent) {
> >                bt_accept_unlink(sk);
> > @@ -418,6 +421,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;
> > @@ -449,10 +454,14 @@ static void l2cap_chan_cleanup_listen(struct sock *parent)
> >        /* Close not yet accepted channels */
> >        while ((sk = bt_accept_dequeue(parent, NULL))) {
> >                struct l2cap_chan *chan = l2cap_pi(sk)->chan;
> > +
> > +               mutex_lock(&chan->conn->chan_lock);
> > +               l2cap_chan_lock(chan);
> 
> Again.
> 
> >                __clear_chan_timer(chan);
> > -               lock_sock(sk);
> >                l2cap_chan_close(chan, ECONNRESET);
> > -               release_sock(sk);
> > +               l2cap_chan_unlock(chan);
> > +               mutex_unlock(&chan->conn->chan_lock);
> > +
> >                chan->ops->close(chan->data);
> >        }
> >  }
> 
> <snip>
> 
> > @@ -964,29 +985,31 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
> >        if (conn->hcon->out && conn->hcon->type == LE_LINK)
> >                smp_conn_security(conn, conn->hcon->pending_sec_level);
> >
> > -       rcu_read_lock();
> > +       mutex_lock(&conn->chan_lock);
> >
> > -       list_for_each_entry_rcu(chan, &conn->chan_l, list) {
> > -               struct sock *sk = chan->sk;
> > +       list_for_each_entry(chan, &conn->chan_l, list) {
> 
> Why are you removing RCU read locks here?

Because I use mutexes in l2cap_chan_lock. So I can sleep which is not
allowed inside rcu_read_lock/unlock.

> > -               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);
> > -                       l2cap_state_change(chan, BT_CONNECTED);
> > +                       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);
> >        }
> >
> > -       rcu_read_unlock();
> > +       mutex_unlock(&conn->chan_lock);
> >  }
> 
> <snip>
> 
> This patch still mixes the return of using conn->chan_lock with
> locking of l2cap_chan. It should be possible and better to have these
> changes in different patches. Another question is will you remove RCU
> usage for conn->chan_l completely or not?

As I said the change is only to updaters and to the places where I need to
sleep.

Best regards 
Andrei Emeltchenko 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFCv0 1/5] Bluetooth: Use locks in RCU updater code
  2012-01-31  7:59     ` Emeltchenko Andrei
@ 2012-01-31 12:37       ` Ulisses Furquim
  2012-01-31 12:58         ` Emeltchenko Andrei
  0 siblings, 1 reply; 15+ messages in thread
From: Ulisses Furquim @ 2012-01-31 12:37 UTC (permalink / raw)
  To: Emeltchenko Andrei, Ulisses Furquim, linux-bluetooth

Hi Andrei,

On Tue, Jan 31, 2012 at 5:59 AM, Emeltchenko Andrei
<Andrei.Emeltchenko.news@gmail.com> wrote:
> On Mon, Jan 30, 2012 at 03:17:15PM -0200, Ulisses Furquim wrote:

<snip>

>> I was under the impression you'd remove RCU for conn->chan_l
>> completely. You're adding a lock only in the updaters? If so, please
>> take a look at commit 3d57dc680 which shows all changes from mutex to
>> RCU. I don't think just adding a lock/unlock in l2cap_conn_start and
>> l2cap_conn_del will be enough. l2cap_chan_add seems to be called from
>> other contexts and it does a list_add_rcu(). Have you thought of that?
>
> I am adding lock to updaters and to the places we need to sleep and
> rcu_read_lock cannot be used. This patch adds locks to updaters and
> following patches cover other places. Maybe I need to split them better.

It needs to be split better, yes. And if you're adding a mutex also in
some readers of the list instead of using RCU I believe it'd be better
to just use a mutex and remove RCU usage altogether. That will be
possibly just a revert of 3d57dc6806, but you need to check that.

Regards,

-- 
Ulisses Furquim
ProFUSION embedded systems
http://profusion.mobi
Mobile: +55 19 9250 0942
Skype: ulissesffs

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFCv0 1/5] Bluetooth: Use locks in RCU updater code
  2012-01-31 12:37       ` Ulisses Furquim
@ 2012-01-31 12:58         ` Emeltchenko Andrei
  0 siblings, 0 replies; 15+ messages in thread
From: Emeltchenko Andrei @ 2012-01-31 12:58 UTC (permalink / raw)
  To: Ulisses Furquim; +Cc: linux-bluetooth

Hi Ulisses,

On Tue, Jan 31, 2012 at 10:37:38AM -0200, Ulisses Furquim wrote:
> On Tue, Jan 31, 2012 at 5:59 AM, Emeltchenko Andrei
> <Andrei.Emeltchenko.news@gmail.com> wrote:
> > On Mon, Jan 30, 2012 at 03:17:15PM -0200, Ulisses Furquim wrote:
> >> I was under the impression you'd remove RCU for conn->chan_l
> >> completely. You're adding a lock only in the updaters? If so, please
> >> take a look at commit 3d57dc680 which shows all changes from mutex to
> >> RCU. I don't think just adding a lock/unlock in l2cap_conn_start and
> >> l2cap_conn_del will be enough. l2cap_chan_add seems to be called from
> >> other contexts and it does a list_add_rcu(). Have you thought of that?
> >
> > I am adding lock to updaters and to the places we need to sleep and
> > rcu_read_lock cannot be used. This patch adds locks to updaters and
> > following patches cover other places. Maybe I need to split them better.
> 
> It needs to be split better, yes. And if you're adding a mutex also in
> some readers of the list instead of using RCU I believe it'd be better
> to just use a mutex and remove RCU usage altogether. That will be
> possibly just a revert of 3d57dc6806, but you need to check that.

I actually do think that this will be better, in next patches I will
revert the commit mentioned.

Best regards 
Andrei Emeltchenko 

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2012-01-31 12:58 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-30 15:09 [RFCv0 0/5] Bluetooth: Change socket lock to l2cap_chan lock Emeltchenko Andrei
2012-01-30 15:09 ` [RFCv0 1/5] Bluetooth: Use locks in RCU updater code Emeltchenko Andrei
2012-01-30 17:17   ` Ulisses Furquim
2012-01-31  7:59     ` Emeltchenko Andrei
2012-01-31 12:37       ` Ulisses Furquim
2012-01-31 12:58         ` Emeltchenko Andrei
2012-01-30 15:09 ` [RFCv0 2/5] Bluetooth: Add l2cap_chan_lock Emeltchenko Andrei
2012-01-30 17:18   ` Ulisses Furquim
2012-01-30 15:09 ` [RFCv0 3/5] Bluetooth: Helper functions for locking change Emeltchenko Andrei
2012-01-30 17:25   ` Ulisses Furquim
2012-01-30 15:09 ` [RFCv0 4/5] Bluetooth: Remove unneeded sk variable Emeltchenko Andrei
2012-01-30 17:26   ` Ulisses Furquim
2012-01-30 15:09 ` [RFCv0 5/5] Bluetooth: Change sk lock to l2cap_chan lock Emeltchenko Andrei
2012-01-30 17:46   ` Ulisses Furquim
2012-01-31  8:11     ` Emeltchenko Andrei

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).