Change the pneigh_entry table to hlist from list.h
to allow for easier later conversion to RCU.

Signed-off-by: Stephen Hemminger <[EMAIL PROTECTED]>

---
 include/net/neighbour.h |    6 ++--
 net/core/neighbour.c    |   58 ++++++++++++++++++++++++------------------------
 2 files changed, 33 insertions(+), 31 deletions(-)

--- net-2.6.19.orig/include/net/neighbour.h
+++ net-2.6.19/include/net/neighbour.h
@@ -124,8 +124,8 @@ struct neigh_ops
 
 struct pneigh_entry
 {
-       struct pneigh_entry     *next;
-       struct net_device               *dev;
+       struct hlist_node       hlist;
+       struct net_device       *dev;
        u8                      key[0];
 };
 
@@ -165,7 +165,7 @@ struct neigh_table
        unsigned int            hash_mask;
        __u32                   hash_rnd;
        unsigned int            hash_chain_gc;
-       struct pneigh_entry     **phash_buckets;
+       struct hlist_head       *phash_buckets;
 #ifdef CONFIG_PROC_FS
        struct proc_dir_entry   *pde;
 #endif
--- net-2.6.19.orig/net/core/neighbour.c
+++ net-2.6.19/net/core/neighbour.c
@@ -455,6 +455,7 @@ struct pneigh_entry * pneigh_lookup(stru
                                    struct net_device *dev, int creat)
 {
        struct pneigh_entry *n;
+       struct hlist_node *tmp;
        int key_len = tbl->key_len;
        u32 hash_val = *(u32 *)(pkey + key_len - 4);
 
@@ -465,7 +466,7 @@ struct pneigh_entry * pneigh_lookup(stru
 
        read_lock_bh(&tbl->lock);
 
-       for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
+       hlist_for_each_entry(n, tmp, &tbl->phash_buckets[hash_val], hlist) {
                if (!memcmp(n->key, pkey, key_len) &&
                    (n->dev == dev || !n->dev)) {
                        read_unlock_bh(&tbl->lock);
@@ -495,8 +496,7 @@ struct pneigh_entry * pneigh_lookup(stru
        }
 
        write_lock_bh(&tbl->lock);
-       n->next = tbl->phash_buckets[hash_val];
-       tbl->phash_buckets[hash_val] = n;
+       hlist_add_head(&n->hlist, &tbl->phash_buckets[hash_val]);
        write_unlock_bh(&tbl->lock);
 out:
        return n;
@@ -506,7 +506,8 @@ out:
 int pneigh_delete(struct neigh_table *tbl, const void *pkey,
                  struct net_device *dev)
 {
-       struct pneigh_entry *n, **np;
+       struct pneigh_entry *n;
+       struct hlist_node *tmp;
        int key_len = tbl->key_len;
        u32 hash_val = *(u32 *)(pkey + key_len - 4);
 
@@ -516,10 +517,9 @@ int pneigh_delete(struct neigh_table *tb
        hash_val &= PNEIGH_HASHMASK;
 
        write_lock_bh(&tbl->lock);
-       for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
-            np = &n->next) {
+       hlist_for_each_entry(n, tmp, &tbl->phash_buckets[hash_val], hlist) {
                if (!memcmp(n->key, pkey, key_len) && n->dev == dev) {
-                       *np = n->next;
+                       hlist_del(&n->hlist);
                        write_unlock_bh(&tbl->lock);
                        if (tbl->pdestructor)
                                tbl->pdestructor(n);
@@ -535,22 +535,21 @@ int pneigh_delete(struct neigh_table *tb
 
 static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
 {
-       struct pneigh_entry *n, **np;
        u32 h;
 
        for (h = 0; h <= PNEIGH_HASHMASK; h++) {
-               np = &tbl->phash_buckets[h];
-               while ((n = *np) != NULL) {
+               struct pneigh_entry *n;
+               struct hlist_node *tmp, *nxt;
+
+               hlist_for_each_entry_safe(n, tmp, nxt, &tbl->phash_buckets[h], 
hlist) {
                        if (!dev || n->dev == dev) {
-                               *np = n->next;
+                               hlist_del(&n->hlist);
                                if (tbl->pdestructor)
                                        tbl->pdestructor(n);
                                if (n->dev)
                                        dev_put(n->dev);
                                kfree(n);
-                               continue;
                        }
-                       np = &n->next;
                }
        }
        return -ENOENT;
@@ -1332,7 +1331,6 @@ void neigh_parms_destroy(struct neigh_pa
 void neigh_table_init_no_netlink(struct neigh_table *tbl)
 {
        unsigned long now = jiffies;
-       unsigned long phsize;
 
        atomic_set(&tbl->parms.refcnt, 1);
        INIT_RCU_HEAD(&tbl->parms.rcu_head);
@@ -1359,8 +1357,8 @@ void neigh_table_init_no_netlink(struct 
        tbl->hash_mask = 1;
        tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
 
-       phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
-       tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
+       tbl->phash_buckets = kcalloc(PNEIGH_HASHMASK + 1, sizeof(struct 
hlist_head),
+                                    GFP_KERNEL);
 
        if (!tbl->hash_buckets || !tbl->phash_buckets)
                panic("cannot allocate neighbour cache hashes");
@@ -2188,18 +2186,18 @@ static struct pneigh_entry *pneigh_get_f
 {
        struct neigh_seq_state *state = seq->private;
        struct neigh_table *tbl = state->tbl;
-       struct pneigh_entry *pn = NULL;
+       struct hlist_node *pn = NULL;
        int bucket = state->bucket;
 
        state->flags |= NEIGH_SEQ_IS_PNEIGH;
        for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
-               pn = tbl->phash_buckets[bucket];
+               pn = tbl->phash_buckets[bucket].first;
                if (pn)
                        break;
        }
        state->bucket = bucket;
 
-       return pn;
+       return pn ? hlist_entry(pn, struct pneigh_entry, hlist) : NULL;
 }
 
 static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
@@ -2208,20 +2206,24 @@ static struct pneigh_entry *pneigh_get_n
 {
        struct neigh_seq_state *state = seq->private;
        struct neigh_table *tbl = state->tbl;
+       struct hlist_node *tmp = &pn->hlist;
 
-       pn = pn->next;
-       while (!pn) {
-               if (++state->bucket > PNEIGH_HASHMASK)
-                       break;
-               pn = tbl->phash_buckets[state->bucket];
-               if (pn)
-                       break;
+       tmp = tmp->next;
+       if (tmp)
+               goto found;
+
+       while (++state->bucket < PNEIGH_HASHMASK) {
+               tmp = tbl->phash_buckets[state->bucket].first;
+               if (tmp)
+                       goto found;
        }
+       return NULL;
 
-       if (pn && pos)
+found:
+       if (pos)
                --(*pos);
 
-       return pn;
+       return hlist_entry(tmp, struct pneigh_entry, hlist);
 }
 
 static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)

--
Stephen Hemminger <[EMAIL PROTECTED]>


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to