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