# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/09/24 16:22:14-07:00 davem@nuts.davemloft.net # [NET]: Fix some neigh table locking errors. # # Also, make neigh_hash_alloc() use GFP_ATOMIC. # # Signed-off-by: David S. Miller # # net/core/neighbour.c # 2004/09/24 16:21:49-07:00 davem@nuts.davemloft.net +14 -9 # [NET]: Fix some neigh table locking errors. # # Also, make neigh_hash_alloc() use GFP_ATOMIC. # # Signed-off-by: David S. Miller # diff -Nru a/net/core/neighbour.c b/net/core/neighbour.c --- a/net/core/neighbour.c 2004-09-25 00:30:40 -07:00 +++ b/net/core/neighbour.c 2004-09-25 00:30:40 -07:00 @@ -116,11 +116,11 @@ int shrunk = 0; int i; + write_lock_bh(&tbl->lock); for (i = 0; i <= tbl->hash_mask; i++) { struct neighbour *n, **np; np = &tbl->hash_buckets[i]; - write_lock_bh(&tbl->lock); while ((n = *np) != NULL) { /* Neighbour record may be discarded if: - nobody refers to it. @@ -147,10 +147,12 @@ write_unlock(&n->lock); np = &n->next; } - write_unlock_bh(&tbl->lock); } tbl->last_flush = jiffies; + + write_unlock_bh(&tbl->lock); + return shrunk; } @@ -295,10 +297,10 @@ struct neighbour **ret; if (size <= PAGE_SIZE) { - ret = kmalloc(size, GFP_KERNEL); + ret = kmalloc(size, GFP_ATOMIC); } else { ret = (struct neighbour **) - __get_free_pages(GFP_KERNEL, get_order(size)); + __get_free_pages(GFP_ATOMIC, get_order(size)); } if (ret) memset(ret, 0, size); @@ -330,7 +332,6 @@ new_hash_mask = new_entries - 1; old_hash = tbl->hash_buckets; - write_lock_bh(&tbl->lock); get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd)); for (i = 0; i < old_entries; i++) { struct neighbour *n, *next; @@ -347,7 +348,6 @@ } tbl->hash_buckets = new_hash; tbl->hash_mask = new_hash_mask; - write_unlock_bh(&tbl->lock); neigh_hash_free(old_hash, old_entries); } @@ -400,8 +400,11 @@ goto out; } - if (tbl->entries > (tbl->hash_mask + 1)) + if (tbl->entries > (tbl->hash_mask + 1)) { + write_lock_bh(&tbl->lock); neigh_hash_grow(tbl, (tbl->hash_mask + 1) << 1); + write_unlock_bh(&tbl->lock); + } memcpy(n->primary_key, pkey, key_len); n->dev = dev; @@ -422,9 +425,10 @@ n->confirmed = jiffies - (n->parms->base_reachable_time << 1); + write_lock_bh(&tbl->lock); + hash_val = tbl->hash(pkey, dev) & tbl->hash_mask; - write_lock_bh(&tbl->lock); if (n->parms->dead) { rc = ERR_PTR(-EINVAL); goto out_tbl_unlock; @@ -514,10 +518,10 @@ hash_val ^= hash_val >> 4; hash_val &= PNEIGH_HASHMASK; + write_lock_bh(&tbl->lock); for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL; np = &n->next) { if (!memcmp(n->key, pkey, key_len) && n->dev == dev) { - write_lock_bh(&tbl->lock); *np = n->next; write_unlock_bh(&tbl->lock); if (tbl->pdestructor) @@ -526,6 +530,7 @@ return 0; } } + write_unlock_bh(&tbl->lock); return -ENOENT; }