/** @file hashtable_compat.h @brief Support hashtable for kernel <= 3.6 @details Copyright (c) 2023 Acronis International GmbH @author Bruce Wang ([email protected]) @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)