1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) B.A.T.M.A.N. contributors:
3 *
4 * Simon Wunderlich, Marek Lindner
5 */
6
7 #include "hash.h"
8 #include "main.h"
9
10 #include <linux/gfp.h>
11 #include <linux/lockdep.h>
12 #include <linux/slab.h>
13
14 /**
15 * batadv_hash_init() - clear all buckets of a hashtable
16 * @hash: hashtable to clear
17 */
batadv_hash_init(struct batadv_hashtable * hash)18 static void batadv_hash_init(struct batadv_hashtable *hash)
19 {
20 u32 i;
21
22 for (i = 0; i < hash->size; i++) {
23 INIT_HLIST_HEAD(&hash->table[i]);
24 spin_lock_init(&hash->list_locks[i]);
25 }
26
27 atomic_set(&hash->generation, 0);
28 }
29
30 /**
31 * batadv_hash_destroy() - Free only the hashtable and the hash itself
32 * @hash: hash object to destroy
33 */
batadv_hash_destroy(struct batadv_hashtable * hash)34 void batadv_hash_destroy(struct batadv_hashtable *hash)
35 {
36 kfree(hash->list_locks);
37 kfree(hash->table);
38 kfree(hash);
39 }
40
41 /**
42 * batadv_hash_new() - Allocates and clears the hashtable
43 * @size: number of hash buckets to allocate
44 *
45 * Return: newly allocated hashtable, NULL on errors
46 */
batadv_hash_new(u32 size)47 struct batadv_hashtable *batadv_hash_new(u32 size)
48 {
49 struct batadv_hashtable *hash;
50
51 hash = kmalloc_obj(*hash, GFP_ATOMIC);
52 if (!hash)
53 return NULL;
54
55 hash->table = kmalloc_objs(*hash->table, size, GFP_ATOMIC);
56 if (!hash->table)
57 goto free_hash;
58
59 hash->list_locks = kmalloc_objs(*hash->list_locks, size, GFP_ATOMIC);
60 if (!hash->list_locks)
61 goto free_table;
62
63 hash->size = size;
64 batadv_hash_init(hash);
65 return hash;
66
67 free_table:
68 kfree(hash->table);
69 free_hash:
70 kfree(hash);
71 return NULL;
72 }
73
74 /**
75 * batadv_hash_set_lock_class() - Set specific lockdep class for hash spinlocks
76 * @hash: hash object to modify
77 * @key: lockdep class key address
78 */
batadv_hash_set_lock_class(struct batadv_hashtable * hash,struct lock_class_key * key)79 void batadv_hash_set_lock_class(struct batadv_hashtable *hash,
80 struct lock_class_key *key)
81 {
82 u32 i;
83
84 for (i = 0; i < hash->size; i++)
85 lockdep_set_class(&hash->list_locks[i], key);
86 }
87