1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2006-2017 B.A.T.M.A.N. contributors: 3 * 4 * Simon Wunderlich, Marek Lindner 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of version 2 of the GNU General Public 8 * License as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include "hash.h" 20 #include "main.h" 21 22 #include <linux/fs.h> 23 #include <linux/lockdep.h> 24 #include <linux/slab.h> 25 26 /* clears the hash */ 27 static void batadv_hash_init(struct batadv_hashtable *hash) 28 { 29 u32 i; 30 31 for (i = 0; i < hash->size; i++) { 32 INIT_HLIST_HEAD(&hash->table[i]); 33 spin_lock_init(&hash->list_locks[i]); 34 } 35 } 36 37 /* free only the hashtable and the hash itself. */ 38 void batadv_hash_destroy(struct batadv_hashtable *hash) 39 { 40 kfree(hash->list_locks); 41 kfree(hash->table); 42 kfree(hash); 43 } 44 45 /* allocates and clears the hash */ 46 struct batadv_hashtable *batadv_hash_new(u32 size) 47 { 48 struct batadv_hashtable *hash; 49 50 hash = kmalloc(sizeof(*hash), GFP_ATOMIC); 51 if (!hash) 52 return NULL; 53 54 hash->table = kmalloc_array(size, sizeof(*hash->table), GFP_ATOMIC); 55 if (!hash->table) 56 goto free_hash; 57 58 hash->list_locks = kmalloc_array(size, sizeof(*hash->list_locks), 59 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 void batadv_hash_set_lock_class(struct batadv_hashtable *hash, 75 struct lock_class_key *key) 76 { 77 u32 i; 78 79 for (i = 0; i < hash->size; i++) 80 lockdep_set_class(&hash->list_locks[i], key); 81 } 82