batman-adv: protect each hash row with rcu locks
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
diff --git a/net/batman-adv/hash.c b/net/batman-adv/hash.c
index fa26939..0265366 100644
--- a/net/batman-adv/hash.c
+++ b/net/batman-adv/hash.c
@@ -27,13 +27,16 @@
{
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;
- 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);
}