summaryrefslogtreecommitdiff
path: root/net/batman-adv/hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/hash.c')
-rw-r--r--net/batman-adv/hash.c34
1 files changed, 25 insertions, 9 deletions
diff --git a/net/batman-adv/hash.c b/net/batman-adv/hash.c
index fa2693973ab8..02653666a26b 100644
--- a/net/batman-adv/hash.c
+++ b/net/batman-adv/hash.c
@@ -27,13 +27,16 @@ static void hash_init(struct hashtable_t *hash)
{
int i;
- for (i = 0 ; i < hash->size; i++)
+ for (i = 0 ; i < hash->size; i++) {
INIT_HLIST_HEAD(&hash->table[i]);
+ spin_lock_init(&hash->list_locks[i]);
+ }
}
/* free only the hashtable and the hash itself. */
void hash_destroy(struct hashtable_t *hash)
{
+ kfree(hash->list_locks);
kfree(hash->table);
kfree(hash);
}
@@ -43,20 +46,33 @@ struct hashtable_t *hash_new(int size)
{
struct hashtable_t *hash;
- hash = kmalloc(sizeof(struct hashtable_t) , GFP_ATOMIC);
-
+ hash = kmalloc(sizeof(struct hashtable_t), GFP_ATOMIC);
if (!hash)
return NULL;
- hash->size = size;
hash->table = kmalloc(sizeof(struct element_t *) * size, GFP_ATOMIC);
+ if (!hash->table)
+ goto free_hash;
- if (!hash->table) {
- kfree(hash);
- return NULL;
- }
+ hash->list_locks = kmalloc(sizeof(spinlock_t) * size, GFP_ATOMIC);
+ if (!hash->list_locks)
+ goto free_table;
+ hash->size = size;
hash_init(hash);
-
return hash;
+
+free_table:
+ kfree(hash->table);
+free_hash:
+ kfree(hash);
+ return NULL;
+}
+
+void bucket_free_rcu(struct rcu_head *rcu)
+{
+ struct element_t *bucket;
+
+ bucket = container_of(rcu, struct element_t, rcu);
+ kfree(bucket);
}