[PATCH 3/3] Bluetooth: Remove l2cap_sk_list

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



A new list was added to replace the socket based one. This new list
doesn't depent on sock and then fits better inside l2cap_core.c code.

It also rename l2cap_chan_alloc() to l2cap_chan_create() and
l2cap_chan_free() to l2cap_chan_destruct()

Signed-off-by: Gustavo F. Padovan <padovan@xxxxxxxxxxxxxx>
---
 include/net/bluetooth/l2cap.h |    6 +-
 net/bluetooth/l2cap_core.c    |  165 ++++++++++++++++++++++-------------------
 net/bluetooth/l2cap_sock.c    |    6 +-
 3 files changed, 95 insertions(+), 82 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index fb3f90e..2ba675c 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -350,6 +350,7 @@ struct l2cap_chan {
 	struct list_head	srej_l;
 
 	struct list_head list;
+	struct list_head global_l;
 };
 
 struct l2cap_conn {
@@ -441,7 +442,6 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
 #define __is_sar_start(ctrl)	(((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
 
 extern int disable_ertm;
-extern struct bt_sock_list l2cap_sk_list;
 
 int l2cap_init_sockets(void);
 void l2cap_cleanup_sockets(void);
@@ -469,9 +469,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent);
 struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 							int proto, gfp_t prio);
 void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err);
-struct l2cap_chan *l2cap_chan_alloc(struct sock *sk);
+struct l2cap_chan *l2cap_chan_create(struct sock *sk);
 void l2cap_chan_del(struct l2cap_chan *chan, int err);
-void l2cap_chan_free(struct l2cap_chan *chan);
+void l2cap_chan_destruct(struct l2cap_chan *chan);
 int l2cap_chan_connect(struct l2cap_chan *chan);
 
 #endif /* __L2CAP_H */
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9e3f64f..c1d08f1 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -62,9 +62,8 @@ static u8 l2cap_fixed_chan[8] = { 0x02, };
 
 static struct workqueue_struct *_busy_wq;
 
-struct bt_sock_list l2cap_sk_list = {
-	.lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
-};
+LIST_HEAD(chan_list);
+DEFINE_RWLOCK(chan_list_lock);
 
 static void l2cap_busy_work(struct work_struct *work);
 
@@ -135,29 +134,27 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn
 	return c;
 }
 
-static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
+static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
 {
-	struct sock *sk;
-	struct hlist_node *node;
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+	struct l2cap_chan *c;
 
-		if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src))
+	list_for_each_entry(c, &chan_list, global_l) {
+		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
 			goto found;
 	}
 
-	sk = NULL;
+	c = NULL;
 found:
-	return sk;
+	return c;
 }
 
 int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
 {
 	int err;
 
-	write_lock_bh(&l2cap_sk_list.lock);
+	write_lock_bh(&chan_list_lock);
 
-	if (psm && __l2cap_get_sock_by_addr(psm, src)) {
+	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
 		err = -EADDRINUSE;
 		goto done;
 	}
@@ -171,7 +168,7 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
 
 		err = -EINVAL;
 		for (p = 0x1001; p < 0x1100; p += 2)
-			if (!__l2cap_get_sock_by_addr(cpu_to_le16(p), src)) {
+			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
 				chan->psm   = cpu_to_le16(p);
 				chan->sport = cpu_to_le16(p);
 				err = 0;
@@ -180,17 +177,17 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
 	}
 
 done:
-	write_unlock_bh(&l2cap_sk_list.lock);
+	write_unlock_bh(&chan_list_lock);
 	return err;
 }
 
 int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
 {
-	write_lock_bh(&l2cap_sk_list.lock);
+	write_lock_bh(&chan_list_lock);
 
 	chan->scid = scid;
 
-	write_unlock_bh(&l2cap_sk_list.lock);
+	write_unlock_bh(&chan_list_lock);
 
 	return 0;
 }
@@ -207,7 +204,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
 	return 0;
 }
 
-struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
+struct l2cap_chan *l2cap_chan_create(struct sock *sk)
 {
 	struct l2cap_chan *chan;
 
@@ -217,11 +214,19 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
 
 	chan->sk = sk;
 
+	write_lock_bh(&chan_list_lock);
+	list_add(&chan->global_l, &chan_list);
+	write_unlock_bh(&chan_list_lock);
+
 	return chan;
 }
 
-void l2cap_chan_free(struct l2cap_chan *chan)
+void l2cap_chan_destruct(struct l2cap_chan *chan)
 {
+	write_lock_bh(&chan_list_lock);
+	list_del(&chan->global_l);
+	write_unlock_bh(&chan_list_lock);
+
 	kfree(chan);
 }
 
@@ -651,48 +656,51 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 /* Find socket with cid and source bdaddr.
  * Returns closest match, locked.
  */
-static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
+static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
 {
-	struct sock *sk = NULL, *sk1 = NULL;
-	struct hlist_node *node;
+	struct l2cap_chan *c, *c1 = NULL;
 
-	read_lock(&l2cap_sk_list.lock);
+	read_lock(&chan_list_lock);
 
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+	list_for_each_entry(c, &chan_list, global_l) {
+		struct sock *sk = c->sk;
 
 		if (state && sk->sk_state != state)
 			continue;
 
-		if (chan->scid == cid) {
+		if (c->scid == cid) {
 			/* Exact match. */
-			if (!bacmp(&bt_sk(sk)->src, src))
-				break;
+			if (!bacmp(&bt_sk(sk)->src, src)) {
+				read_unlock(&chan_list_lock);
+				return c;
+			}
 
 			/* Closest match */
 			if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
-				sk1 = sk;
+				c1 = c;
 		}
 	}
 
-	read_unlock(&l2cap_sk_list.lock);
+	read_unlock(&chan_list_lock);
 
-	return node ? sk : sk1;
+	return c1;
 }
 
 static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 {
 	struct sock *parent, *sk;
-	struct l2cap_chan *chan;
+	struct l2cap_chan *chan, *pchan;
 
 	BT_DBG("");
 
 	/* Check if we have socket listening on cid */
-	parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
+	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
 							conn->src);
-	if (!parent)
+	if (!pchan)
 		return;
 
+	parent = pchan->sk;
+
 	bh_lock_sock(parent);
 
 	/* Check for backlog size */
@@ -705,7 +713,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 	if (!sk)
 		goto clean;
 
-	chan = l2cap_chan_alloc(sk);
+	chan = l2cap_chan_create(sk);
 	if (!chan) {
 		l2cap_sock_kill(sk);
 		goto clean;
@@ -883,33 +891,34 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *ch
 /* Find socket with psm and source bdaddr.
  * Returns closest match.
  */
-static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
+static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
 {
-	struct sock *sk = NULL, *sk1 = NULL;
-	struct hlist_node *node;
+	struct l2cap_chan *c, *c1 = NULL;
 
-	read_lock(&l2cap_sk_list.lock);
+	read_lock(&chan_list_lock);
 
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+	list_for_each_entry(c, &chan_list, global_l) {
+		struct sock *sk = c->sk;
 
 		if (state && sk->sk_state != state)
 			continue;
 
-		if (chan->psm == psm) {
+		if (c->psm == psm) {
 			/* Exact match. */
-			if (!bacmp(&bt_sk(sk)->src, src))
-				break;
+			if (!bacmp(&bt_sk(sk)->src, src)) {
+				read_unlock_bh(&chan_list_lock);
+				return c;
+			}
 
 			/* Closest match */
 			if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
-				sk1 = sk;
+				c1 = c;
 		}
 	}
 
-	read_unlock(&l2cap_sk_list.lock);
+	read_unlock(&chan_list_lock);
 
-	return node ? sk : sk1;
+	return c1;
 }
 
 int l2cap_chan_connect(struct l2cap_chan *chan)
@@ -2079,22 +2088,26 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 {
 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
 	struct l2cap_conn_rsp rsp;
-	struct l2cap_chan *chan = NULL;
+	struct l2cap_chan *chan = NULL, *pchan;
 	struct sock *parent, *sk = NULL;
 	int result, status = L2CAP_CS_NO_INFO;
 
 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
 	__le16 psm = req->psm;
 
-	BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
+	BT_ERR("psm 0x%2.2x scid 0x%4.4x", psm, scid);
 
 	/* Check if we have socket listening on psm */
-	parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
-	if (!parent) {
+	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
+	if (!pchan) {
 		result = L2CAP_CR_BAD_PSM;
 		goto sendresp;
 	}
 
+	BT_ERR("%p 0x%2.2x", pchan, pchan->psm);
+
+	parent = pchan->sk;
+
 	bh_lock_sock(parent);
 
 	/* Check if the ACL is secure enough (if not SDP) */
@@ -2117,7 +2130,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 	if (!sk)
 		goto response;
 
-	chan = l2cap_chan_alloc(sk);
+	chan = l2cap_chan_create(sk);
 	if (!chan) {
 		l2cap_sock_kill(sk);
 		goto response;
@@ -3745,11 +3758,14 @@ done:
 static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
 {
 	struct sock *sk;
+	struct l2cap_chan *chan;
 
-	sk = l2cap_get_sock_by_psm(0, psm, conn->src);
-	if (!sk)
+	chan = l2cap_global_chan_by_psm(0, psm, conn->src);
+	if (!chan)
 		goto drop;
 
+	sk = chan->sk;
+
 	bh_lock_sock(sk);
 
 	BT_DBG("sk %p, len %d", sk, skb->len);
@@ -3775,11 +3791,14 @@ done:
 static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
 {
 	struct sock *sk;
+	struct l2cap_chan *chan;
 
-	sk = l2cap_get_sock_by_scid(0, cid, conn->src);
-	if (!sk)
+	chan = l2cap_global_chan_by_scid(0, cid, conn->src);
+	if (!chan)
 		goto drop;
 
+	sk = chan->sk;
+
 	bh_lock_sock(sk);
 
 	BT_DBG("sk %p, len %d", sk, skb->len);
@@ -3846,8 +3865,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
 {
 	int exact = 0, lm1 = 0, lm2 = 0;
-	register struct sock *sk;
-	struct hlist_node *node;
+	struct l2cap_chan *c;
 
 	if (type != ACL_LINK)
 		return -EINVAL;
@@ -3855,25 +3873,25 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
 	/* Find listening sockets and check their link_mode */
-	read_lock(&l2cap_sk_list.lock);
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+	read_lock(&chan_list_lock);
+	list_for_each_entry(c, &chan_list, global_l) {
+		struct sock *sk = c->sk;
 
 		if (sk->sk_state != BT_LISTEN)
 			continue;
 
 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
 			lm1 |= HCI_LM_ACCEPT;
-			if (chan->role_switch)
+			if (c->role_switch)
 				lm1 |= HCI_LM_MASTER;
 			exact++;
 		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
 			lm2 |= HCI_LM_ACCEPT;
-			if (chan->role_switch)
+			if (c->role_switch)
 				lm2 |= HCI_LM_MASTER;
 		}
 	}
-	read_unlock(&l2cap_sk_list.lock);
+	read_unlock(&chan_list_lock);
 
 	return exact ? lm1 : lm2;
 }
@@ -4126,25 +4144,22 @@ drop:
 
 static int l2cap_debugfs_show(struct seq_file *f, void *p)
 {
-	struct sock *sk;
-	struct hlist_node *node;
+	struct l2cap_chan *c;
 
-	read_lock_bh(&l2cap_sk_list.lock);
+	read_lock_bh(&chan_list_lock);
 
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		struct l2cap_pinfo *pi = l2cap_pi(sk);
-		struct l2cap_chan *chan = pi->chan;
+	list_for_each_entry(c, &chan_list, global_l) {
+		struct sock *sk = c->sk;
 
 		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
 					batostr(&bt_sk(sk)->src),
 					batostr(&bt_sk(sk)->dst),
-					sk->sk_state, __le16_to_cpu(chan->psm),
-					chan->scid, chan->dcid,
-					chan->imtu, chan->omtu, chan->sec_level,
-					chan->mode);
+					sk->sk_state, __le16_to_cpu(c->psm),
+					c->scid, c->dcid, c->imtu, c->omtu,
+					c->sec_level, c->mode);
 	}
 
-	read_unlock_bh(&l2cap_sk_list.lock);
+	read_unlock_bh(&chan_list_lock);
 
 	return 0;
 }
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index aca99cd..3a78e46 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -808,8 +808,7 @@ void l2cap_sock_kill(struct sock *sk)
 
 	/* Kill poor orphan */
 
-	l2cap_chan_free(l2cap_pi(sk)->chan);
-	bt_sock_unlink(&l2cap_sk_list, sk);
+	l2cap_chan_destruct(l2cap_pi(sk)->chan);
 	sock_set_flag(sk, SOCK_DEAD);
 	sock_put(sk);
 }
@@ -1025,7 +1024,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, g
 
 	setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
 
-	bt_sock_link(&l2cap_sk_list, sk);
 	return sk;
 }
 
@@ -1052,7 +1050,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
 	if (!sk)
 		return -ENOMEM;
 
-	chan = l2cap_chan_alloc(sk);
+	chan = l2cap_chan_create(sk);
 	if (!chan) {
 		l2cap_sock_kill(sk);
 		return -ENOMEM;
-- 
1.7.5.rc1

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux