]> err.no Git - linux-2.6/blobdiff - net/core/neighbour.c
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / net / core / neighbour.c
index 7bb6a9a1256df6a082d0792feca42db7d18ec0f5..aef01533dfb6ca2ed6dbc636ba58dc4ca490492d 100644 (file)
@@ -358,11 +358,12 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
 {
        struct neighbour *n;
        int key_len = tbl->key_len;
-       u32 hash_val = tbl->hash(pkey, dev);
+       u32 hash_val;
 
        NEIGH_CACHE_STAT_INC(tbl, lookups);
 
        read_lock_bh(&tbl->lock);
+       hash_val = tbl->hash(pkey, dev);
        for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) {
                if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) {
                        neigh_hold(n);
@@ -379,11 +380,12 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
 {
        struct neighbour *n;
        int key_len = tbl->key_len;
-       u32 hash_val = tbl->hash(pkey, NULL);
+       u32 hash_val;
 
        NEIGH_CACHE_STAT_INC(tbl, lookups);
 
        read_lock_bh(&tbl->lock);
+       hash_val = tbl->hash(pkey, NULL);
        for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) {
                if (!memcmp(n->primary_key, pkey, key_len) &&
                    (net == n->dev->nd_net)) {
@@ -507,6 +509,7 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
        if (tbl->pconstructor && tbl->pconstructor(n)) {
                if (dev)
                        dev_put(dev);
+               release_net(net);
                kfree(n);
                n = NULL;
                goto out;
@@ -834,12 +837,18 @@ static void neigh_timer_handler(unsigned long arg)
        }
        if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
                struct sk_buff *skb = skb_peek(&neigh->arp_queue);
-
+               /* keep skb alive even if arp_queue overflows */
+               if (skb)
+                       skb_get(skb);
+               write_unlock(&neigh->lock);
                neigh->ops->solicit(neigh, skb);
                atomic_inc(&neigh->probes);
-       }
+               if (skb)
+                       kfree_skb(skb);
+       } else {
 out:
-       write_unlock(&neigh->lock);
+               write_unlock(&neigh->lock);
+       }
 
        if (notify)
                neigh_update_notify(neigh);
@@ -1380,10 +1389,10 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
                panic("cannot create neighbour cache statistics");
 
 #ifdef CONFIG_PROC_FS
-       tbl->pde = create_proc_entry(tbl->id, 0, init_net.proc_net_stat);
+       tbl->pde = proc_create(tbl->id, 0, init_net.proc_net_stat,
+                              &neigh_stat_seq_fops);
        if (!tbl->pde)
                panic("cannot create neighbour proc dir entry");
-       tbl->pde->proc_fops = &neigh_stat_seq_fops;
        tbl->pde->data = tbl;
 #endif