xref: /linux/net/batman-adv/hash.c (revision d0034a7a4ac7fae708146ac0059b9c47a1543f0d)
17db7d9f3SSven Eckelmann // SPDX-License-Identifier: GPL-2.0
2*cfa55c6dSSven Eckelmann /* Copyright (C) B.A.T.M.A.N. contributors:
3c6c8fea2SSven Eckelmann  *
4c6c8fea2SSven Eckelmann  * Simon Wunderlich, Marek Lindner
5c6c8fea2SSven Eckelmann  */
6c6c8fea2SSven Eckelmann 
7c6c8fea2SSven Eckelmann #include "hash.h"
81e2c2a4fSSven Eckelmann #include "main.h"
91e2c2a4fSSven Eckelmann 
10b92b94acSSven Eckelmann #include <linux/gfp.h>
111e2c2a4fSSven Eckelmann #include <linux/lockdep.h>
121e2c2a4fSSven Eckelmann #include <linux/slab.h>
13c6c8fea2SSven Eckelmann 
14c6c8fea2SSven Eckelmann /* clears the hash */
batadv_hash_init(struct batadv_hashtable * hash)155bf74e9cSSven Eckelmann static void batadv_hash_init(struct batadv_hashtable *hash)
16c6c8fea2SSven Eckelmann {
176b5e971aSSven Eckelmann 	u32 i;
18c6c8fea2SSven Eckelmann 
19fb778ea1SMarek Lindner 	for (i = 0; i < hash->size; i++) {
20c6c8fea2SSven Eckelmann 		INIT_HLIST_HEAD(&hash->table[i]);
21fb778ea1SMarek Lindner 		spin_lock_init(&hash->list_locks[i]);
22fb778ea1SMarek Lindner 	}
2305abd7bcSSven Eckelmann 
2405abd7bcSSven Eckelmann 	atomic_set(&hash->generation, 0);
25c6c8fea2SSven Eckelmann }
26c6c8fea2SSven Eckelmann 
27ff15c27cSSven Eckelmann /**
28ff15c27cSSven Eckelmann  * batadv_hash_destroy() - Free only the hashtable and the hash itself
29ff15c27cSSven Eckelmann  * @hash: hash object to destroy
30ff15c27cSSven Eckelmann  */
batadv_hash_destroy(struct batadv_hashtable * hash)315bf74e9cSSven Eckelmann void batadv_hash_destroy(struct batadv_hashtable *hash)
32c6c8fea2SSven Eckelmann {
33fb778ea1SMarek Lindner 	kfree(hash->list_locks);
34c6c8fea2SSven Eckelmann 	kfree(hash->table);
35c6c8fea2SSven Eckelmann 	kfree(hash);
36c6c8fea2SSven Eckelmann }
37c6c8fea2SSven Eckelmann 
38ff15c27cSSven Eckelmann /**
39ff15c27cSSven Eckelmann  * batadv_hash_new() - Allocates and clears the hashtable
40ff15c27cSSven Eckelmann  * @size: number of hash buckets to allocate
41ff15c27cSSven Eckelmann  *
42ff15c27cSSven Eckelmann  * Return: newly allocated hashtable, NULL on errors
43ff15c27cSSven Eckelmann  */
batadv_hash_new(u32 size)446b5e971aSSven Eckelmann struct batadv_hashtable *batadv_hash_new(u32 size)
45c6c8fea2SSven Eckelmann {
465bf74e9cSSven Eckelmann 	struct batadv_hashtable *hash;
47c6c8fea2SSven Eckelmann 
48704509b8SSven Eckelmann 	hash = kmalloc(sizeof(*hash), GFP_ATOMIC);
49c6c8fea2SSven Eckelmann 	if (!hash)
50c6c8fea2SSven Eckelmann 		return NULL;
51c6c8fea2SSven Eckelmann 
520185dda6SAntonio Quartulli 	hash->table = kmalloc_array(size, sizeof(*hash->table), GFP_ATOMIC);
53fb778ea1SMarek Lindner 	if (!hash->table)
54fb778ea1SMarek Lindner 		goto free_hash;
55c6c8fea2SSven Eckelmann 
560185dda6SAntonio Quartulli 	hash->list_locks = kmalloc_array(size, sizeof(*hash->list_locks),
57704509b8SSven Eckelmann 					 GFP_ATOMIC);
58fb778ea1SMarek Lindner 	if (!hash->list_locks)
59fb778ea1SMarek Lindner 		goto free_table;
60fb778ea1SMarek Lindner 
61fb778ea1SMarek Lindner 	hash->size = size;
627f9f02cbSSven Eckelmann 	batadv_hash_init(hash);
63fb778ea1SMarek Lindner 	return hash;
64fb778ea1SMarek Lindner 
65fb778ea1SMarek Lindner free_table:
66fb778ea1SMarek Lindner 	kfree(hash->table);
67fb778ea1SMarek Lindner free_hash:
68c6c8fea2SSven Eckelmann 	kfree(hash);
69c6c8fea2SSven Eckelmann 	return NULL;
70c6c8fea2SSven Eckelmann }
715d52dad2SSven Eckelmann 
72ff15c27cSSven Eckelmann /**
73ff15c27cSSven Eckelmann  * batadv_hash_set_lock_class() - Set specific lockdep class for hash spinlocks
74ff15c27cSSven Eckelmann  * @hash: hash object to modify
75ff15c27cSSven Eckelmann  * @key: lockdep class key address
76ff15c27cSSven Eckelmann  */
batadv_hash_set_lock_class(struct batadv_hashtable * hash,struct lock_class_key * key)775bf74e9cSSven Eckelmann void batadv_hash_set_lock_class(struct batadv_hashtable *hash,
785d52dad2SSven Eckelmann 				struct lock_class_key *key)
795d52dad2SSven Eckelmann {
806b5e971aSSven Eckelmann 	u32 i;
815d52dad2SSven Eckelmann 
825d52dad2SSven Eckelmann 	for (i = 0; i < hash->size; i++)
835d52dad2SSven Eckelmann 		lockdep_set_class(&hash->list_locks[i], key);
845d52dad2SSven Eckelmann }
85