You can import this changeset into BK by piping this whole message to:
'| bk receive [path to repository]' or apply the patch as usual.

===================================================================


ChangeSet@1.1422.1.19, 2003-11-14 21:52:30-02:00, acme@conectiva.com.br
  o LLC: use refcounting with struct llc_sap


 include/net/llc.h   |   16 +++++++++++++++-
 net/802/p8022.c     |    2 +-
 net/802/psnap.c     |    2 +-
 net/llc/af_llc.c    |   11 ++++++-----
 net/llc/llc_c_ac.c  |    1 +
 net/llc/llc_conn.c  |   28 ++--------------------------
 net/llc/llc_conn.h  |    1 -
 net/llc/llc_core.c  |   38 +++++++++++++++++++++++++-------------
 net/llc/llc_input.c |    9 +++++++--
 9 files changed, 58 insertions(+), 50 deletions(-)


diff -Nru a/include/net/llc.h b/include/net/llc.h
--- a/include/net/llc.h	Sat Nov 15 17:00:27 2003
+++ b/include/net/llc.h	Sat Nov 15 17:00:27 2003
@@ -17,6 +17,8 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 
+#include <asm/atomic.h>
+
 struct net_device;
 struct packet_type;
 struct sk_buff;
@@ -44,6 +46,7 @@
 	unsigned char	 state;
 	unsigned char	 p_bit;
 	unsigned char	 f_bit;
+	atomic_t         refcnt;
 	int		 (*rcv_func)(struct sk_buff *skb,
 				     struct net_device *dev,
 				     struct packet_type *pt);
@@ -79,7 +82,18 @@
 				    int (*rcv)(struct sk_buff *skb,
 					       struct net_device *dev,
 					       struct packet_type *pt));
-extern void llc_sap_close(struct llc_sap *sap);
+static inline void llc_sap_hold(struct llc_sap *sap)
+{
+	atomic_inc(&sap->refcnt);
+}
+
+static inline void llc_sap_put(struct llc_sap *sap)
+{
+	extern void llc_sap_close(struct llc_sap *sap);
+
+	if (atomic_dec_and_test(&sap->refcnt))
+		llc_sap_close(sap);
+}
 
 extern struct llc_sap *llc_sap_find(unsigned char sap_value);
 
diff -Nru a/net/802/p8022.c b/net/802/p8022.c
--- a/net/802/p8022.c	Sat Nov 15 17:00:27 2003
+++ b/net/802/p8022.c	Sat Nov 15 17:00:27 2003
@@ -55,7 +55,7 @@
 
 void unregister_8022_client(struct datalink_proto *proto)
 {
-	llc_sap_close(proto->sap);
+	llc_sap_put(proto->sap);
 	kfree(proto);
 }
 
diff -Nru a/net/802/psnap.c b/net/802/psnap.c
--- a/net/802/psnap.c	Sat Nov 15 17:00:27 2003
+++ b/net/802/psnap.c	Sat Nov 15 17:00:27 2003
@@ -106,7 +106,7 @@
 
 static void __exit snap_exit(void)
 {
-	llc_sap_close(snap_sap);
+	llc_sap_put(snap_sap);
 }
 
 module_exit(snap_exit);
diff -Nru a/net/llc/af_llc.c b/net/llc/af_llc.c
--- a/net/llc/af_llc.c	Sat Nov 15 17:00:27 2003
+++ b/net/llc/af_llc.c	Sat Nov 15 17:00:27 2003
@@ -21,6 +21,7 @@
  * See the GNU General Public License for more details.
  */
 #include <linux/config.h>
+#include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/tcp.h>
@@ -181,10 +182,6 @@
 	if (!sk->sk_zapped)
 		llc_sap_remove_socket(llc->sap, sk);
 	release_sock(sk);
-	if (llc->sap && hlist_empty(&llc->sap->sk_list.list)) {
-		llc_release_sockets(llc->sap);
-		llc_sap_close(llc->sap);
-	}
 	if (llc->dev)
 		dev_put(llc->dev);
 	sock_put(sk);
@@ -213,6 +210,7 @@
 				llc_ui_sap_last_autoport = i + 2;
 				goto out;
 			}
+			llc_sap_put(sap);
 		}
 		llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
 		tries++;
@@ -302,6 +300,7 @@
 		rc = -EBUSY; /* some other network layer is using the sap */
 		if (!sap)
 			goto out;
+		llc_sap_hold(sap);
 	} else {
 		struct llc_addr laddr, daddr;
 		struct sock *ask;
@@ -318,7 +317,7 @@
 		ask = llc_lookup_established(sap, &daddr, &laddr);
 		if (ask) {
 			sock_put(ask);
-			goto out;
+			goto out_put;
 		}
 	}
 	llc->laddr.lsap = addr->sllc_sap;
@@ -327,6 +326,8 @@
 	/* assign new connection to its SAP */
 	llc_sap_add_socket(sap, sk);
 	rc = sk->sk_zapped = 0;
+out_put:
+	llc_sap_put(sap);
 out:
 	return rc;
 }
diff -Nru a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c
--- a/net/llc/llc_c_ac.c	Sat Nov 15 17:00:27 2003
+++ b/net/llc/llc_c_ac.c	Sat Nov 15 17:00:27 2003
@@ -63,6 +63,7 @@
 		llc->dev = skb->dev;
 		ev->ind_prim = LLC_CONN_PRIM;
 		rc = 0;
+		llc_sap_put(sap);
 	}
 	return rc;
 }
diff -Nru a/net/llc/llc_conn.c b/net/llc/llc_conn.c
--- a/net/llc/llc_conn.c	Sat Nov 15 17:00:27 2003
+++ b/net/llc/llc_conn.c	Sat Nov 15 17:00:27 2003
@@ -628,6 +628,7 @@
  */
 void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk)
 {
+	llc_sap_hold(sap);
 	write_lock_bh(&sap->sk_list.lock);
 	llc_sk(sk)->sap = sap;
 	sk_add_node(sk, &sap->sk_list.list);
@@ -647,6 +648,7 @@
 	write_lock_bh(&sap->sk_list.lock);
 	sk_del_node_init(sk);
 	write_unlock_bh(&sap->sk_list.lock);
+	llc_sap_put(sap);
 }
 
 /**
@@ -724,32 +726,6 @@
 #ifdef LLC_REFCNT_DEBUG
 static atomic_t llc_sock_nr;
 #endif
-
-/**
- *	llc_release_sockets - releases all sockets in a sap
- *	@sap: sap to release its sockets
- *
- *	Releases all connections of a sap. Returns 0 if all actions complete
- *	successfully, nonzero otherwise
- */
-int llc_release_sockets(struct llc_sap *sap)
-{
-	int rc = 0;
-	struct sock *sk;
-	struct hlist_node *node;
-
-	write_lock_bh(&sap->sk_list.lock);
-
-	sk_for_each(sk, node, &sap->sk_list.list) {
-		llc_sk(sk)->state = LLC_CONN_STATE_TEMP;
-
-		if (llc_send_disc(sk))
-			rc = 1;
-	}
-
-	write_unlock_bh(&sap->sk_list.lock);
-	return rc;
-}
 
 /**
  *	llc_backlog_rcv - Processes rx frames and expired timers.
diff -Nru a/net/llc/llc_conn.h b/net/llc/llc_conn.h
--- a/net/llc/llc_conn.h	Sat Nov 15 17:00:27 2003
+++ b/net/llc/llc_conn.h	Sat Nov 15 17:00:27 2003
@@ -113,5 +113,4 @@
 
 extern u8 llc_data_accept_state(u8 state);
 extern void llc_build_offset_table(void);
-extern int llc_release_sockets(struct llc_sap *sap);
 #endif /* LLC_CONN_H */
diff -Nru a/net/llc/llc_core.c b/net/llc/llc_core.c
--- a/net/llc/llc_core.c	Sat Nov 15 17:00:27 2003
+++ b/net/llc/llc_core.c	Sat Nov 15 17:00:27 2003
@@ -31,7 +31,7 @@
  *
  *	Allocates and initializes sap.
  */
-struct llc_sap *llc_sap_alloc(void)
+static struct llc_sap *llc_sap_alloc(void)
 {
 	struct llc_sap *sap = kmalloc(sizeof(*sap), GFP_ATOMIC);
 
@@ -40,6 +40,7 @@
 		sap->state = LLC_SAP_STATE_ACTIVE;
 		memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN);
 		rwlock_init(&sap->sk_list.lock);
+		atomic_set(&sap->refcnt, 1);
 	}
 	return sap;
 }
@@ -52,9 +53,7 @@
  */
 void llc_add_sap(struct llc_sap *sap)
 {
-	write_lock_bh(&llc_sap_list_lock);
 	list_add_tail(&sap->node, &llc_sap_list);
-	write_unlock_bh(&llc_sap_list_lock);
 }
 
 /**
@@ -70,11 +69,25 @@
 	write_unlock_bh(&llc_sap_list_lock);
 }
 
+struct llc_sap *__llc_sap_find(unsigned char sap_value)
+{
+	struct llc_sap* sap;
+
+	list_for_each_entry(sap, &llc_sap_list, node)
+		if (sap->laddr.lsap == sap_value)
+			goto out;
+	sap = NULL;
+out:
+	return sap;
+}
+
 /**
  *	llc_sap_find - searchs a SAP in station
  *	@sap_value: sap to be found
  *
  *	Searchs for a sap in the sap list of the LLC's station upon the sap ID.
+ *	If the sap is found it will be refcounted and the user will have to do
+ *	a llc_sap_put after use.
  *	Returns the sap or %NULL if not found.
  */
 struct llc_sap *llc_sap_find(unsigned char sap_value)
@@ -82,11 +95,9 @@
 	struct llc_sap* sap;
 
 	read_lock_bh(&llc_sap_list_lock);
-	list_for_each_entry(sap, &llc_sap_list, node)
-		if (sap->laddr.lsap == sap_value)
-			goto out;
-	sap = NULL;
-out:
+	sap = __llc_sap_find(sap_value);
+	if (sap)
+		llc_sap_hold(sap);
 	read_unlock_bh(&llc_sap_list_lock);
 	return sap;
 }
@@ -105,19 +116,20 @@
 					 struct net_device *dev,
 					 struct packet_type *pt))
 {
-	struct llc_sap *sap = llc_sap_find(lsap);
-
-	if (sap) { /* SAP already exists */
-		sap = NULL;
+	struct llc_sap *sap = NULL;
+		
+	write_lock_bh(&llc_sap_list_lock);
+	if (__llc_sap_find(lsap)) /* SAP already exists */
 		goto out;
-	}
 	sap = llc_sap_alloc();
 	if (!sap)
 		goto out;
 	sap->laddr.lsap = lsap;
 	sap->rcv_func	= func;
+	llc_sap_hold(sap);
 	llc_add_sap(sap);
 out:
+	write_unlock_bh(&llc_sap_list_lock);
 	return sap;
 }
 
diff -Nru a/net/llc/llc_input.c b/net/llc/llc_input.c
--- a/net/llc/llc_input.c	Sat Nov 15 17:00:27 2003
+++ b/net/llc/llc_input.c	Sat Nov 15 17:00:27 2003
@@ -165,17 +165,22 @@
 	 */
 	if (sap->rcv_func) {
 		sap->rcv_func(skb, dev, pt);
-		goto out;
+		goto out_put;
 	}
 	dest = llc_pdu_type(skb);
 	if (unlikely(!dest || !llc_type_handlers[dest - 1]))
-		goto drop;
+		goto drop_put;
 	llc_type_handlers[dest - 1](sap, skb);
+out_put:
+	llc_sap_put(sap);
 out:
 	return 0;
 drop:
 	kfree_skb(skb);
 	goto out;
+drop_put:
+	kfree_skb(skb);
+	goto out_put;
 handle_station:
 	if (!llc_station_handler)
 		goto drop;

===================================================================


This BitKeeper patch contains the following changesets:
1.1422.1.19
## Wrapped with gzip_uu ##


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
CP;NG'I Y6<*[^F(QF*G@OEC,+R@GT@V$LO\#/ZY;9\T<    
 
