/**
@file hashtable_compat.h
@brief Support hashtable for kernel <= 3.6
@details Copyright (c) 2023 Acronis International GmbH
@author Bruce Wang (bruce.wang@acronis.com)
@since $Id: $
*/
#pragma once
#include <linux/list.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/hash.h>
#include <linux/rculist.h>
#ifdef HAVE_HASHTABLE_H
#include <linux/hashtable.h>
#else
#define DECLARE_HASHTABLE(name, bits) \
struct hlist_head name[1 << (bits)]
static inline void __hash_init(struct hlist_head *ht, unsigned int sz)
{
unsigned int i;
for (i = 0; i < sz; i++)
INIT_HLIST_HEAD(&ht[i]);
}
#define hash_init(hashtable) __hash_init(hashtable, ARRAY_SIZE(hashtable))
static inline void hash_del_rcu(struct hlist_node *node)
{
hlist_del_init_rcu(node);
}
#endif
#ifndef hlist_entry_safe
#define hlist_entry_safe(ptr, type, member) \
({ \
typeof(ptr) ____ptr = (ptr); \
____ptr ? hlist_entry(____ptr, type, member) : NULL; \
})
#endif
#ifndef hlist_first_rcu
#define hlist_first_rcu(head) (*((struct hlist_node __rcu **)(&(head)->first)))
#endif
#ifndef hlist_next_rcu
#define hlist_next_rcu(node) (*((struct hlist_node __rcu **)(&(node)->next)))
#endif
#undef hlist_for_each_entry
#define hlist_for_each_entry(pos, head, member) \
for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member); \
pos; \
pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
#undef hlist_for_each_entry_rcu
#define hlist_for_each_entry_rcu(pos, head, member) \
for (pos = hlist_entry_safe(rcu_dereference(hlist_first_rcu(head)), \
typeof(*(pos)), member); \
pos; \
pos = hlist_entry_safe(rcu_dereference(hlist_next_rcu( \
&(pos)->member)), \
typeof(*(pos)), member))
static inline uint64_t moremur(uint64_t x) {
x ^= x >> 27;
x *= 0x3C79AC492BA7B653UL;
x ^= x >> 33;
x *= 0x1C69B3F74AC4AE35UL;
x ^= x >> 27;
return x;
}
static inline uint64_t moremur_hash(uint64_t val, unsigned int bits)
{
return moremur(val) >> (64 - bits);
}
#define hash_add_rcu_hashbits(hashtable, node, key, hashbits) \
hlist_add_head_rcu(node, &hashtable[moremur_hash(key, hashbits)])
#define hash_for_each_possible_with_hashbits(name, obj, member, key, hashbits) \
hlist_for_each_entry(obj, &name[moremur_hash(key, hashbits)], member)
#define hash_for_each_possible_rcu_with_hashbits(name, obj, member, key, hashbits) \
hlist_for_each_entry_rcu(obj, &name[moremur_hash(key, hashbits)], member)
|