linux/net/batman-adv/hash.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (C) 2006-2018  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/gfp.h>
  23#include <linux/lockdep.h>
  24#include <linux/slab.h>
  25
  26/* clears the hash */
  27static 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/**
  38 * batadv_hash_destroy() - Free only the hashtable and the hash itself
  39 * @hash: hash object to destroy
  40 */
  41void batadv_hash_destroy(struct batadv_hashtable *hash)
  42{
  43        kfree(hash->list_locks);
  44        kfree(hash->table);
  45        kfree(hash);
  46}
  47
  48/**
  49 * batadv_hash_new() - Allocates and clears the hashtable
  50 * @size: number of hash buckets to allocate
  51 *
  52 * Return: newly allocated hashtable, NULL on errors
  53 */
  54struct batadv_hashtable *batadv_hash_new(u32 size)
  55{
  56        struct batadv_hashtable *hash;
  57
  58        hash = kmalloc(sizeof(*hash), GFP_ATOMIC);
  59        if (!hash)
  60                return NULL;
  61
  62        hash->table = kmalloc_array(size, sizeof(*hash->table), GFP_ATOMIC);
  63        if (!hash->table)
  64                goto free_hash;
  65
  66        hash->list_locks = kmalloc_array(size, sizeof(*hash->list_locks),
  67                                         GFP_ATOMIC);
  68        if (!hash->list_locks)
  69                goto free_table;
  70
  71        hash->size = size;
  72        batadv_hash_init(hash);
  73        return hash;
  74
  75free_table:
  76        kfree(hash->table);
  77free_hash:
  78        kfree(hash);
  79        return NULL;
  80}
  81
  82/**
  83 * batadv_hash_set_lock_class() - Set specific lockdep class for hash spinlocks
  84 * @hash: hash object to modify
  85 * @key: lockdep class key address
  86 */
  87void batadv_hash_set_lock_class(struct batadv_hashtable *hash,
  88                                struct lock_class_key *key)
  89{
  90        u32 i;
  91
  92        for (i = 0; i < hash->size; i++)
  93                lockdep_set_class(&hash->list_locks[i], key);
  94}
  95