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 */ 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 */ 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 */ 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 */ 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