summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2004-11-02 23:42:09 -0800
committerDavid S. Miller <davem@nuts.davemloft.net>2004-11-02 23:42:09 -0800
commitbfa840301c9c5cbe04a1a2556d3096c93c9bc9fd (patch)
tree9c197a1282ea758ee09a9f8a5797779caec60222
parentc888100b7ec188b20b05e8ab7f0f638999092e5d (diff)
[NET]: Neighbour table entries counter needs to be atomic_t
It is updated outside of locks, so... Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/neighbour.h2
-rw-r--r--net/core/neighbour.c25
2 files changed, 16 insertions, 11 deletions
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index f6c323a3e5b6..4c9ddae8c866 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -189,7 +189,7 @@ struct neigh_table
struct timer_list gc_timer;
struct timer_list proxy_timer;
struct sk_buff_head proxy_queue;
- int entries;
+ atomic_t entries;
rwlock_t lock;
unsigned long last_rand;
struct neigh_parms *parms_list;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index c9bd1b74fc2d..c722fa09459f 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -254,18 +254,20 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl)
{
struct neighbour *n = NULL;
unsigned long now = jiffies;
+ int entries;
- if (tbl->entries > tbl->gc_thresh3 ||
- (tbl->entries > tbl->gc_thresh2 &&
+ entries = atomic_inc_return(&tbl->entries) - 1;
+ if (entries >= tbl->gc_thresh3 ||
+ (entries >= tbl->gc_thresh2 &&
time_after(now, tbl->last_flush + 5 * HZ))) {
if (!neigh_forced_gc(tbl) &&
- tbl->entries > tbl->gc_thresh3)
- goto out;
+ entries >= tbl->gc_thresh3)
+ goto out_entries;
}
n = kmem_cache_alloc(tbl->kmem_cachep, SLAB_ATOMIC);
if (!n)
- goto out;
+ goto out_entries;
memset(n, 0, tbl->entry_size);
@@ -281,12 +283,15 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl)
NEIGH_CACHE_STAT_INC(tbl, allocs);
neigh_glbl_allocs++;
- tbl->entries++;
n->tbl = tbl;
atomic_set(&n->refcnt, 1);
n->dead = 1;
out:
return n;
+
+out_entries:
+ atomic_dec(&tbl->entries);
+ goto out;
}
static struct neighbour **neigh_hash_alloc(unsigned int entries)
@@ -427,7 +432,7 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
write_lock_bh(&tbl->lock);
- if (tbl->entries > (tbl->hash_mask + 1))
+ if (atomic_read(&tbl->entries) > (tbl->hash_mask + 1))
neigh_hash_grow(tbl, (tbl->hash_mask + 1) << 1);
hash_val = tbl->hash(pkey, dev) & tbl->hash_mask;
@@ -608,7 +613,7 @@ void neigh_destroy(struct neighbour *neigh)
NEIGH_PRINTK2("neigh %p is destroyed.\n", neigh);
neigh_glbl_allocs--;
- neigh->tbl->entries--;
+ atomic_dec(&neigh->tbl->entries);
kmem_cache_free(neigh->tbl->kmem_cachep, neigh);
}
@@ -1394,7 +1399,7 @@ int neigh_table_clear(struct neigh_table *tbl)
del_timer_sync(&tbl->proxy_timer);
pneigh_queue_purge(&tbl->proxy_queue);
neigh_ifdown(tbl, NULL);
- if (tbl->entries)
+ if (atomic_read(&tbl->entries))
printk(KERN_CRIT "neighbour leakage\n");
write_lock(&neigh_tbl_lock);
for (tp = &neigh_tables; *tp; tp = &(*tp)->next) {
@@ -1951,7 +1956,7 @@ static int neigh_stat_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
"%08lx %08lx %08lx %08lx\n",
- tbl->entries,
+ atomic_read(&tbl->entries),
st->allocs,
st->destroys,