wl1251: fix a memory leak in probe
[safe/jmp/linux-2.6] / net / llc / llc_sap.c
index 94790e6..94e7fca 100644 (file)
@@ -23,6 +23,7 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <linux/llc.h>
+#include <linux/slab.h>
 
 static int llc_mac_header_len(unsigned short devtype)
 {
@@ -30,7 +31,7 @@ static int llc_mac_header_len(unsigned short devtype)
        case ARPHRD_ETHER:
        case ARPHRD_LOOPBACK:
                return sizeof(struct ethhdr);
-#ifdef CONFIG_TR
+#if defined(CONFIG_TR) || defined(CONFIG_TR_MODULE)
        case ARPHRD_IEEE802_TR:
                return sizeof(struct trh_hdr);
 #endif
@@ -321,10 +322,12 @@ static struct sock *llc_lookup_dgram(struct llc_sap *sap,
 {
        struct sock *rc;
        struct hlist_nulls_node *node;
+       int slot = llc_sk_laddr_hashfn(sap, laddr);
+       struct hlist_nulls_head *laddr_hb = &sap->sk_laddr_hash[slot];
 
        rcu_read_lock_bh();
 again:
-       sk_nulls_for_each_rcu(rc, node, &sap->sk_list) {
+       sk_nulls_for_each_rcu(rc, node, laddr_hb) {
                if (llc_dgram_match(sap, laddr, rc)) {
                        /* Extra checks required by SLAB_DESTROY_BY_RCU */
                        if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt)))
@@ -338,6 +341,13 @@ again:
                }
        }
        rc = NULL;
+       /*
+        * if the nulls value we got at the end of this lookup is
+        * not the expected one, we must restart lookup.
+        * We probably met an item that was moved to another chain.
+        */
+       if (unlikely(get_nulls_value(node) != slot))
+               goto again;
 found:
        rcu_read_unlock_bh();
        return rc;
@@ -387,10 +397,14 @@ static void llc_sap_mcast(struct llc_sap *sap,
 {
        int i = 0, count = 256 / sizeof(struct sock *);
        struct sock *sk, *stack[count];
-       struct hlist_nulls_node *node;
+       struct hlist_node *node;
+       struct llc_sock *llc;
+       struct hlist_head *dev_hb = llc_sk_dev_hash(sap, skb->dev->ifindex);
 
        spin_lock_bh(&sap->sk_lock);
-       sk_nulls_for_each_rcu(sk, node, &sap->sk_list) {
+       hlist_for_each_entry(llc, node, dev_hb, dev_hash_node) {
+
+               sk = &llc->sk;
 
                if (!llc_mcast_match(sap, laddr, skb, sk))
                        continue;