xref: /kernel/linux/linux-5.10/net/batman-adv/hash.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright (C) 2006-2020  B.A.T.M.A.N. contributors:
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Simon Wunderlich, Marek Lindner
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include "hash.h"
88c2ecf20Sopenharmony_ci#include "main.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/gfp.h>
118c2ecf20Sopenharmony_ci#include <linux/lockdep.h>
128c2ecf20Sopenharmony_ci#include <linux/slab.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci/* clears the hash */
158c2ecf20Sopenharmony_cistatic void batadv_hash_init(struct batadv_hashtable *hash)
168c2ecf20Sopenharmony_ci{
178c2ecf20Sopenharmony_ci	u32 i;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	for (i = 0; i < hash->size; i++) {
208c2ecf20Sopenharmony_ci		INIT_HLIST_HEAD(&hash->table[i]);
218c2ecf20Sopenharmony_ci		spin_lock_init(&hash->list_locks[i]);
228c2ecf20Sopenharmony_ci	}
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	atomic_set(&hash->generation, 0);
258c2ecf20Sopenharmony_ci}
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/**
288c2ecf20Sopenharmony_ci * batadv_hash_destroy() - Free only the hashtable and the hash itself
298c2ecf20Sopenharmony_ci * @hash: hash object to destroy
308c2ecf20Sopenharmony_ci */
318c2ecf20Sopenharmony_civoid batadv_hash_destroy(struct batadv_hashtable *hash)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	kfree(hash->list_locks);
348c2ecf20Sopenharmony_ci	kfree(hash->table);
358c2ecf20Sopenharmony_ci	kfree(hash);
368c2ecf20Sopenharmony_ci}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/**
398c2ecf20Sopenharmony_ci * batadv_hash_new() - Allocates and clears the hashtable
408c2ecf20Sopenharmony_ci * @size: number of hash buckets to allocate
418c2ecf20Sopenharmony_ci *
428c2ecf20Sopenharmony_ci * Return: newly allocated hashtable, NULL on errors
438c2ecf20Sopenharmony_ci */
448c2ecf20Sopenharmony_cistruct batadv_hashtable *batadv_hash_new(u32 size)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	struct batadv_hashtable *hash;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	hash = kmalloc(sizeof(*hash), GFP_ATOMIC);
498c2ecf20Sopenharmony_ci	if (!hash)
508c2ecf20Sopenharmony_ci		return NULL;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	hash->table = kmalloc_array(size, sizeof(*hash->table), GFP_ATOMIC);
538c2ecf20Sopenharmony_ci	if (!hash->table)
548c2ecf20Sopenharmony_ci		goto free_hash;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	hash->list_locks = kmalloc_array(size, sizeof(*hash->list_locks),
578c2ecf20Sopenharmony_ci					 GFP_ATOMIC);
588c2ecf20Sopenharmony_ci	if (!hash->list_locks)
598c2ecf20Sopenharmony_ci		goto free_table;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	hash->size = size;
628c2ecf20Sopenharmony_ci	batadv_hash_init(hash);
638c2ecf20Sopenharmony_ci	return hash;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cifree_table:
668c2ecf20Sopenharmony_ci	kfree(hash->table);
678c2ecf20Sopenharmony_cifree_hash:
688c2ecf20Sopenharmony_ci	kfree(hash);
698c2ecf20Sopenharmony_ci	return NULL;
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci/**
738c2ecf20Sopenharmony_ci * batadv_hash_set_lock_class() - Set specific lockdep class for hash spinlocks
748c2ecf20Sopenharmony_ci * @hash: hash object to modify
758c2ecf20Sopenharmony_ci * @key: lockdep class key address
768c2ecf20Sopenharmony_ci */
778c2ecf20Sopenharmony_civoid batadv_hash_set_lock_class(struct batadv_hashtable *hash,
788c2ecf20Sopenharmony_ci				struct lock_class_key *key)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	u32 i;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	for (i = 0; i < hash->size; i++)
838c2ecf20Sopenharmony_ci		lockdep_set_class(&hash->list_locks[i], key);
848c2ecf20Sopenharmony_ci}
85