xref: /openbmc/linux/include/linux/rhashtable.h (revision e47877c7)
10eb71a9dSNeilBrown /* SPDX-License-Identifier: GPL-2.0 */
27e1e7763SThomas Graf /*
37e1e7763SThomas Graf  * Resizable, Scalable, Concurrent Hash Table
47e1e7763SThomas Graf  *
5ca26893fSHerbert Xu  * Copyright (c) 2015-2016 Herbert Xu <herbert@gondor.apana.org.au>
6b5e2c150SThomas Graf  * Copyright (c) 2014-2015 Thomas Graf <tgraf@suug.ch>
77e1e7763SThomas Graf  * Copyright (c) 2008-2014 Patrick McHardy <kaber@trash.net>
87e1e7763SThomas Graf  *
97e1e7763SThomas Graf  * Code partially derived from nft_hash
10dc0ee268SHerbert Xu  * Rewritten with rehash code from br_multicast plus single list
11dc0ee268SHerbert Xu  * pointer as suggested by Josh Triplett
127e1e7763SThomas Graf  *
137e1e7763SThomas Graf  * This program is free software; you can redistribute it and/or modify
147e1e7763SThomas Graf  * it under the terms of the GNU General Public License version 2 as
157e1e7763SThomas Graf  * published by the Free Software Foundation.
167e1e7763SThomas Graf  */
177e1e7763SThomas Graf 
187e1e7763SThomas Graf #ifndef _LINUX_RHASHTABLE_H
197e1e7763SThomas Graf #define _LINUX_RHASHTABLE_H
207e1e7763SThomas Graf 
213cf92222SHerbert Xu #include <linux/err.h>
226626af69SHerbert Xu #include <linux/errno.h>
2331ccde2dSHerbert Xu #include <linux/jhash.h>
24f89bd6f8SThomas Graf #include <linux/list_nulls.h>
2597defe1eSThomas Graf #include <linux/workqueue.h>
26b2d09103SIngo Molnar #include <linux/rculist.h>
278f0db018SNeilBrown #include <linux/bit_spinlock.h>
287e1e7763SThomas Graf 
290eb71a9dSNeilBrown #include <linux/rhashtable-types.h>
30f89bd6f8SThomas Graf /*
318f0db018SNeilBrown  * Objects in an rhashtable have an embedded struct rhash_head
328f0db018SNeilBrown  * which is linked into as hash chain from the hash table - or one
338f0db018SNeilBrown  * of two or more hash tables when the rhashtable is being resized.
34f89bd6f8SThomas Graf  * The end of the chain is marked with a special nulls marks which has
358f0db018SNeilBrown  * the least significant bit set but otherwise stores the address of
367f5f8140SRandy Dunlap  * the hash bucket.  This allows us to be sure we've found the end
378f0db018SNeilBrown  * of the right list.
38ca0b709dSNeilBrown  * The value stored in the hash bucket has BIT(0) used as a lock bit.
398f0db018SNeilBrown  * This bit must be atomically set before any changes are made to
408f0db018SNeilBrown  * the chain.  To avoid dereferencing this pointer without clearing
418f0db018SNeilBrown  * the bit first, we use an opaque 'struct rhash_lock_head *' for the
428f0db018SNeilBrown  * pointer stored in the bucket.  This struct needs to be defined so
43e4edbe3cSNeilBrown  * that rcu_dereference() works on it, but it has no content so a
448f0db018SNeilBrown  * cast is needed for it to be useful.  This ensures it isn't
458f0db018SNeilBrown  * used by mistake with clearing the lock bit first.
46f89bd6f8SThomas Graf  */
478f0db018SNeilBrown struct rhash_lock_head {};
4802fd97c3SHerbert Xu 
495f8ddeabSFlorian Westphal /* Maximum chain length before rehash
505f8ddeabSFlorian Westphal  *
515f8ddeabSFlorian Westphal  * The maximum (not average) chain length grows with the size of the hash
525f8ddeabSFlorian Westphal  * table, at a rate of (log N)/(log log N).
535f8ddeabSFlorian Westphal  *
545f8ddeabSFlorian Westphal  * The value of 16 is selected so that even if the hash table grew to
555f8ddeabSFlorian Westphal  * 2^32 you would not expect the maximum chain length to exceed it
565f8ddeabSFlorian Westphal  * unless we are under attack (or extremely unlucky).
575f8ddeabSFlorian Westphal  *
585f8ddeabSFlorian Westphal  * As this limit is only to detect attacks, we don't need to set it to a
595f8ddeabSFlorian Westphal  * lower value as you'd need the chain length to vastly exceed 16 to have
605f8ddeabSFlorian Westphal  * any real effect on the system.
615f8ddeabSFlorian Westphal  */
625f8ddeabSFlorian Westphal #define RHT_ELASTICITY	16u
635f8ddeabSFlorian Westphal 
6497defe1eSThomas Graf /**
6597defe1eSThomas Graf  * struct bucket_table - Table of hash buckets
6697defe1eSThomas Graf  * @size: Number of hash buckets
67da20420fSHerbert Xu  * @nest: Number of bits of first-level nested table.
6863d512d0SHerbert Xu  * @rehash: Current bucket being rehashed
69988dfbd7SHerbert Xu  * @hash_rnd: Random seed to fold into hash
70eddee5baSHerbert Xu  * @walkers: List of active walkers
719d901bc0SHerbert Xu  * @rcu: RCU structure for freeing the table
72c4db8848SHerbert Xu  * @future_tbl: Table under construction during rehashing
73da20420fSHerbert Xu  * @ntbl: Nested table used when out of memory.
7497defe1eSThomas Graf  * @buckets: size * hash buckets
7597defe1eSThomas Graf  */
767e1e7763SThomas Graf struct bucket_table {
7763d512d0SHerbert Xu 	unsigned int		size;
78da20420fSHerbert Xu 	unsigned int		nest;
79988dfbd7SHerbert Xu 	u32			hash_rnd;
80eddee5baSHerbert Xu 	struct list_head	walkers;
819d901bc0SHerbert Xu 	struct rcu_head		rcu;
82b9ebafbeSEric Dumazet 
83c4db8848SHerbert Xu 	struct bucket_table __rcu *future_tbl;
84c4db8848SHerbert Xu 
85149212f0SNeilBrown 	struct lockdep_map	dep_map;
86149212f0SNeilBrown 
87ce9b362bSHerbert Xu 	struct rhash_lock_head __rcu *buckets[] ____cacheline_aligned_in_smp;
887e1e7763SThomas Graf };
897e1e7763SThomas Graf 
9082208d0dSNeilBrown /*
9182208d0dSNeilBrown  * NULLS_MARKER() expects a hash value with the low
9282208d0dSNeilBrown  * bits mostly likely to be significant, and it discards
9382208d0dSNeilBrown  * the msb.
94ca0b709dSNeilBrown  * We give it an address, in which the bottom bit is
9582208d0dSNeilBrown  * always 0, and the msb might be significant.
9682208d0dSNeilBrown  * So we shift the address down one bit to align with
9782208d0dSNeilBrown  * expectations and avoid losing a significant bit.
98ca0b709dSNeilBrown  *
99ca0b709dSNeilBrown  * We never store the NULLS_MARKER in the hash table
100ca0b709dSNeilBrown  * itself as we need the lsb for locking.
101ca0b709dSNeilBrown  * Instead we store a NULL
10282208d0dSNeilBrown  */
10382208d0dSNeilBrown #define	RHT_NULLS_MARKER(ptr)	\
10482208d0dSNeilBrown 	((void *)NULLS_MARKER(((unsigned long) (ptr)) >> 1))
1059b4f64a2SNeilBrown #define INIT_RHT_NULLS_HEAD(ptr)	\
106ca0b709dSNeilBrown 	((ptr) = NULL)
107f89bd6f8SThomas Graf 
rht_is_a_nulls(const struct rhash_head * ptr)108f89bd6f8SThomas Graf static inline bool rht_is_a_nulls(const struct rhash_head *ptr)
109f89bd6f8SThomas Graf {
110f89bd6f8SThomas Graf 	return ((unsigned long) ptr & 1);
111f89bd6f8SThomas Graf }
112f89bd6f8SThomas Graf 
rht_obj(const struct rhashtable * ht,const struct rhash_head * he)11302fd97c3SHerbert Xu static inline void *rht_obj(const struct rhashtable *ht,
11402fd97c3SHerbert Xu 			    const struct rhash_head *he)
11502fd97c3SHerbert Xu {
11602fd97c3SHerbert Xu 	return (char *)he - ht->p.head_offset;
11702fd97c3SHerbert Xu }
11802fd97c3SHerbert Xu 
rht_bucket_index(const struct bucket_table * tbl,unsigned int hash)11902fd97c3SHerbert Xu static inline unsigned int rht_bucket_index(const struct bucket_table *tbl,
12002fd97c3SHerbert Xu 					    unsigned int hash)
12102fd97c3SHerbert Xu {
1229f9a7077SNeilBrown 	return hash & (tbl->size - 1);
12302fd97c3SHerbert Xu }
12402fd97c3SHerbert Xu 
rht_key_get_hash(struct rhashtable * ht,const void * key,const struct rhashtable_params params,unsigned int hash_rnd)1252b860931STom Herbert static inline unsigned int rht_key_get_hash(struct rhashtable *ht,
1262b860931STom Herbert 	const void *key, const struct rhashtable_params params,
1272b860931STom Herbert 	unsigned int hash_rnd)
12802fd97c3SHerbert Xu {
129299e5c32SThomas Graf 	unsigned int hash;
130de91b25cSHerbert Xu 
13131ccde2dSHerbert Xu 	/* params must be equal to ht->p if it isn't constant. */
13231ccde2dSHerbert Xu 	if (!__builtin_constant_p(params.key_len))
1332b860931STom Herbert 		hash = ht->p.hashfn(key, ht->key_len, hash_rnd);
13431ccde2dSHerbert Xu 	else if (params.key_len) {
135299e5c32SThomas Graf 		unsigned int key_len = params.key_len;
13631ccde2dSHerbert Xu 
13731ccde2dSHerbert Xu 		if (params.hashfn)
1382b860931STom Herbert 			hash = params.hashfn(key, key_len, hash_rnd);
13931ccde2dSHerbert Xu 		else if (key_len & (sizeof(u32) - 1))
1402b860931STom Herbert 			hash = jhash(key, key_len, hash_rnd);
14131ccde2dSHerbert Xu 		else
1422b860931STom Herbert 			hash = jhash2(key, key_len / sizeof(u32), hash_rnd);
14331ccde2dSHerbert Xu 	} else {
144299e5c32SThomas Graf 		unsigned int key_len = ht->p.key_len;
14531ccde2dSHerbert Xu 
14631ccde2dSHerbert Xu 		if (params.hashfn)
1472b860931STom Herbert 			hash = params.hashfn(key, key_len, hash_rnd);
14831ccde2dSHerbert Xu 		else
1492b860931STom Herbert 			hash = jhash(key, key_len, hash_rnd);
15031ccde2dSHerbert Xu 	}
15131ccde2dSHerbert Xu 
1522b860931STom Herbert 	return hash;
1532b860931STom Herbert }
1542b860931STom Herbert 
rht_key_hashfn(struct rhashtable * ht,const struct bucket_table * tbl,const void * key,const struct rhashtable_params params)1552b860931STom Herbert static inline unsigned int rht_key_hashfn(
1562b860931STom Herbert 	struct rhashtable *ht, const struct bucket_table *tbl,
1572b860931STom Herbert 	const void *key, const struct rhashtable_params params)
1582b860931STom Herbert {
1592b860931STom Herbert 	unsigned int hash = rht_key_get_hash(ht, key, params, tbl->hash_rnd);
1602b860931STom Herbert 
16131ccde2dSHerbert Xu 	return rht_bucket_index(tbl, hash);
16202fd97c3SHerbert Xu }
16302fd97c3SHerbert Xu 
rht_head_hashfn(struct rhashtable * ht,const struct bucket_table * tbl,const struct rhash_head * he,const struct rhashtable_params params)16402fd97c3SHerbert Xu static inline unsigned int rht_head_hashfn(
16502fd97c3SHerbert Xu 	struct rhashtable *ht, const struct bucket_table *tbl,
16602fd97c3SHerbert Xu 	const struct rhash_head *he, const struct rhashtable_params params)
16702fd97c3SHerbert Xu {
16802fd97c3SHerbert Xu 	const char *ptr = rht_obj(ht, he);
16902fd97c3SHerbert Xu 
17002fd97c3SHerbert Xu 	return likely(params.obj_hashfn) ?
17149f7b33eSPatrick McHardy 	       rht_bucket_index(tbl, params.obj_hashfn(ptr, params.key_len ?:
17249f7b33eSPatrick McHardy 							    ht->p.key_len,
17349f7b33eSPatrick McHardy 						       tbl->hash_rnd)) :
17402fd97c3SHerbert Xu 	       rht_key_hashfn(ht, tbl, ptr + params.key_offset, params);
17502fd97c3SHerbert Xu }
17602fd97c3SHerbert Xu 
17702fd97c3SHerbert Xu /**
17802fd97c3SHerbert Xu  * rht_grow_above_75 - returns true if nelems > 0.75 * table-size
17902fd97c3SHerbert Xu  * @ht:		hash table
18002fd97c3SHerbert Xu  * @tbl:	current table
18102fd97c3SHerbert Xu  */
rht_grow_above_75(const struct rhashtable * ht,const struct bucket_table * tbl)18202fd97c3SHerbert Xu static inline bool rht_grow_above_75(const struct rhashtable *ht,
18302fd97c3SHerbert Xu 				     const struct bucket_table *tbl)
18402fd97c3SHerbert Xu {
18502fd97c3SHerbert Xu 	/* Expand table when exceeding 75% load */
18602fd97c3SHerbert Xu 	return atomic_read(&ht->nelems) > (tbl->size / 4 * 3) &&
18702fd97c3SHerbert Xu 	       (!ht->p.max_size || tbl->size < ht->p.max_size);
18802fd97c3SHerbert Xu }
18902fd97c3SHerbert Xu 
19002fd97c3SHerbert Xu /**
19102fd97c3SHerbert Xu  * rht_shrink_below_30 - returns true if nelems < 0.3 * table-size
19202fd97c3SHerbert Xu  * @ht:		hash table
19302fd97c3SHerbert Xu  * @tbl:	current table
19402fd97c3SHerbert Xu  */
rht_shrink_below_30(const struct rhashtable * ht,const struct bucket_table * tbl)19502fd97c3SHerbert Xu static inline bool rht_shrink_below_30(const struct rhashtable *ht,
19602fd97c3SHerbert Xu 				       const struct bucket_table *tbl)
19702fd97c3SHerbert Xu {
19802fd97c3SHerbert Xu 	/* Shrink table beneath 30% load */
19902fd97c3SHerbert Xu 	return atomic_read(&ht->nelems) < (tbl->size * 3 / 10) &&
20002fd97c3SHerbert Xu 	       tbl->size > ht->p.min_size;
20102fd97c3SHerbert Xu }
20202fd97c3SHerbert Xu 
203ccd57b1bSHerbert Xu /**
204ccd57b1bSHerbert Xu  * rht_grow_above_100 - returns true if nelems > table-size
205ccd57b1bSHerbert Xu  * @ht:		hash table
206ccd57b1bSHerbert Xu  * @tbl:	current table
207ccd57b1bSHerbert Xu  */
rht_grow_above_100(const struct rhashtable * ht,const struct bucket_table * tbl)208ccd57b1bSHerbert Xu static inline bool rht_grow_above_100(const struct rhashtable *ht,
209ccd57b1bSHerbert Xu 				      const struct bucket_table *tbl)
210ccd57b1bSHerbert Xu {
2111d8dc3d3SJohannes Berg 	return atomic_read(&ht->nelems) > tbl->size &&
2121d8dc3d3SJohannes Berg 		(!ht->p.max_size || tbl->size < ht->p.max_size);
213ccd57b1bSHerbert Xu }
214ccd57b1bSHerbert Xu 
21507ee0722SHerbert Xu /**
21607ee0722SHerbert Xu  * rht_grow_above_max - returns true if table is above maximum
21707ee0722SHerbert Xu  * @ht:		hash table
21807ee0722SHerbert Xu  * @tbl:	current table
21907ee0722SHerbert Xu  */
rht_grow_above_max(const struct rhashtable * ht,const struct bucket_table * tbl)22007ee0722SHerbert Xu static inline bool rht_grow_above_max(const struct rhashtable *ht,
22107ee0722SHerbert Xu 				      const struct bucket_table *tbl)
22207ee0722SHerbert Xu {
2236d684e54SHerbert Xu 	return atomic_read(&ht->nelems) >= ht->max_elems;
22407ee0722SHerbert Xu }
22507ee0722SHerbert Xu 
2267e1e7763SThomas Graf #ifdef CONFIG_PROVE_LOCKING
22797defe1eSThomas Graf int lockdep_rht_mutex_is_held(struct rhashtable *ht);
22888d6ed15SThomas Graf int lockdep_rht_bucket_is_held(const struct bucket_table *tbl, u32 hash);
2297e1e7763SThomas Graf #else
lockdep_rht_mutex_is_held(struct rhashtable * ht)23097defe1eSThomas Graf static inline int lockdep_rht_mutex_is_held(struct rhashtable *ht)
2317e1e7763SThomas Graf {
2327e1e7763SThomas Graf 	return 1;
2337e1e7763SThomas Graf }
23488d6ed15SThomas Graf 
lockdep_rht_bucket_is_held(const struct bucket_table * tbl,u32 hash)23588d6ed15SThomas Graf static inline int lockdep_rht_bucket_is_held(const struct bucket_table *tbl,
23688d6ed15SThomas Graf 					     u32 hash)
23788d6ed15SThomas Graf {
23888d6ed15SThomas Graf 	return 1;
23988d6ed15SThomas Graf }
2407e1e7763SThomas Graf #endif /* CONFIG_PROVE_LOCKING */
2417e1e7763SThomas Graf 
242ca26893fSHerbert Xu void *rhashtable_insert_slow(struct rhashtable *ht, const void *key,
243ca26893fSHerbert Xu 			     struct rhash_head *obj);
2447e1e7763SThomas Graf 
245246779ddSHerbert Xu void rhashtable_walk_enter(struct rhashtable *ht,
246246779ddSHerbert Xu 			   struct rhashtable_iter *iter);
247f2dba9c6SHerbert Xu void rhashtable_walk_exit(struct rhashtable_iter *iter);
24897a6ec4aSTom Herbert int rhashtable_walk_start_check(struct rhashtable_iter *iter) __acquires(RCU);
24997a6ec4aSTom Herbert 
rhashtable_walk_start(struct rhashtable_iter * iter)25097a6ec4aSTom Herbert static inline void rhashtable_walk_start(struct rhashtable_iter *iter)
25197a6ec4aSTom Herbert {
25297a6ec4aSTom Herbert 	(void)rhashtable_walk_start_check(iter);
25397a6ec4aSTom Herbert }
25497a6ec4aSTom Herbert 
255f2dba9c6SHerbert Xu void *rhashtable_walk_next(struct rhashtable_iter *iter);
2562db54b47STom Herbert void *rhashtable_walk_peek(struct rhashtable_iter *iter);
257f2dba9c6SHerbert Xu void rhashtable_walk_stop(struct rhashtable_iter *iter) __releases(RCU);
258f2dba9c6SHerbert Xu 
2596b6f302cSThomas Graf void rhashtable_free_and_destroy(struct rhashtable *ht,
2606b6f302cSThomas Graf 				 void (*free_fn)(void *ptr, void *arg),
2616b6f302cSThomas Graf 				 void *arg);
26297defe1eSThomas Graf void rhashtable_destroy(struct rhashtable *ht);
2637e1e7763SThomas Graf 
264ce9b362bSHerbert Xu struct rhash_lock_head __rcu **rht_bucket_nested(
265ce9b362bSHerbert Xu 	const struct bucket_table *tbl, unsigned int hash);
266ce9b362bSHerbert Xu struct rhash_lock_head __rcu **__rht_bucket_nested(
267ce9b362bSHerbert Xu 	const struct bucket_table *tbl, unsigned int hash);
268ce9b362bSHerbert Xu struct rhash_lock_head __rcu **rht_bucket_nested_insert(
269ce9b362bSHerbert Xu 	struct rhashtable *ht, struct bucket_table *tbl, unsigned int hash);
270da20420fSHerbert Xu 
2717e1e7763SThomas Graf #define rht_dereference(p, ht) \
2727e1e7763SThomas Graf 	rcu_dereference_protected(p, lockdep_rht_mutex_is_held(ht))
2737e1e7763SThomas Graf 
2747e1e7763SThomas Graf #define rht_dereference_rcu(p, ht) \
2757e1e7763SThomas Graf 	rcu_dereference_check(p, lockdep_rht_mutex_is_held(ht))
2767e1e7763SThomas Graf 
27788d6ed15SThomas Graf #define rht_dereference_bucket(p, tbl, hash) \
27888d6ed15SThomas Graf 	rcu_dereference_protected(p, lockdep_rht_bucket_is_held(tbl, hash))
2797e1e7763SThomas Graf 
28088d6ed15SThomas Graf #define rht_dereference_bucket_rcu(p, tbl, hash) \
28188d6ed15SThomas Graf 	rcu_dereference_check(p, lockdep_rht_bucket_is_held(tbl, hash))
28288d6ed15SThomas Graf 
28388d6ed15SThomas Graf #define rht_entry(tpos, pos, member) \
28488d6ed15SThomas Graf 	({ tpos = container_of(pos, typeof(*tpos), member); 1; })
28588d6ed15SThomas Graf 
rht_bucket(const struct bucket_table * tbl,unsigned int hash)286ce9b362bSHerbert Xu static inline struct rhash_lock_head __rcu *const *rht_bucket(
287da20420fSHerbert Xu 	const struct bucket_table *tbl, unsigned int hash)
288da20420fSHerbert Xu {
289da20420fSHerbert Xu 	return unlikely(tbl->nest) ? rht_bucket_nested(tbl, hash) :
290da20420fSHerbert Xu 				     &tbl->buckets[hash];
291da20420fSHerbert Xu }
292da20420fSHerbert Xu 
rht_bucket_var(struct bucket_table * tbl,unsigned int hash)293ce9b362bSHerbert Xu static inline struct rhash_lock_head __rcu **rht_bucket_var(
294da20420fSHerbert Xu 	struct bucket_table *tbl, unsigned int hash)
295da20420fSHerbert Xu {
296ff302db9SNeilBrown 	return unlikely(tbl->nest) ? __rht_bucket_nested(tbl, hash) :
297da20420fSHerbert Xu 				     &tbl->buckets[hash];
298da20420fSHerbert Xu }
299da20420fSHerbert Xu 
rht_bucket_insert(struct rhashtable * ht,struct bucket_table * tbl,unsigned int hash)300ce9b362bSHerbert Xu static inline struct rhash_lock_head __rcu **rht_bucket_insert(
301da20420fSHerbert Xu 	struct rhashtable *ht, struct bucket_table *tbl, unsigned int hash)
302da20420fSHerbert Xu {
303da20420fSHerbert Xu 	return unlikely(tbl->nest) ? rht_bucket_nested_insert(ht, tbl, hash) :
304da20420fSHerbert Xu 				     &tbl->buckets[hash];
305da20420fSHerbert Xu }
306da20420fSHerbert Xu 
307c5783311SNeilBrown /*
308ca0b709dSNeilBrown  * We lock a bucket by setting BIT(0) in the pointer - this is always
309ca0b709dSNeilBrown  * zero in real pointers.  The NULLS mark is never stored in the bucket,
310ca0b709dSNeilBrown  * rather we store NULL if the bucket is empty.
311c5783311SNeilBrown  * bit_spin_locks do not handle contention well, but the whole point
312c5783311SNeilBrown  * of the hashtable design is to achieve minimum per-bucket contention.
313c5783311SNeilBrown  * A nested hash table might not have a bucket pointer.  In that case
314c5783311SNeilBrown  * we cannot get a lock.  For remove and replace the bucket cannot be
315c5783311SNeilBrown  * interesting and doesn't need locking.
316c5783311SNeilBrown  * For insert we allocate the bucket if this is the last bucket_table,
317c5783311SNeilBrown  * and then take the lock.
318c5783311SNeilBrown  * Sometimes we unlock a bucket by writing a new pointer there.  In that
319c5783311SNeilBrown  * case we don't need to unlock, but we do need to reset state such as
320c5783311SNeilBrown  * local_bh. For that we have rht_assign_unlock().  As rcu_assign_pointer()
321c5783311SNeilBrown  * provides the same release semantics that bit_spin_unlock() provides,
322c5783311SNeilBrown  * this is safe.
323f4712b46SNeilBrown  * When we write to a bucket without unlocking, we use rht_assign_locked().
324c5783311SNeilBrown  */
325c5783311SNeilBrown 
rht_lock(struct bucket_table * tbl,struct rhash_lock_head __rcu ** bkt)326*e47877c7STejun Heo static inline unsigned long rht_lock(struct bucket_table *tbl,
327ce9b362bSHerbert Xu 				     struct rhash_lock_head __rcu **bkt)
328c5783311SNeilBrown {
329*e47877c7STejun Heo 	unsigned long flags;
330*e47877c7STejun Heo 
331*e47877c7STejun Heo 	local_irq_save(flags);
332ca0b709dSNeilBrown 	bit_spin_lock(0, (unsigned long *)bkt);
333c5783311SNeilBrown 	lock_map_acquire(&tbl->dep_map);
334*e47877c7STejun Heo 	return flags;
335c5783311SNeilBrown }
336c5783311SNeilBrown 
rht_lock_nested(struct bucket_table * tbl,struct rhash_lock_head __rcu ** bucket,unsigned int subclass)337*e47877c7STejun Heo static inline unsigned long rht_lock_nested(struct bucket_table *tbl,
338ce9b362bSHerbert Xu 					struct rhash_lock_head __rcu **bucket,
339c5783311SNeilBrown 					unsigned int subclass)
340c5783311SNeilBrown {
341*e47877c7STejun Heo 	unsigned long flags;
342*e47877c7STejun Heo 
343*e47877c7STejun Heo 	local_irq_save(flags);
344ca0b709dSNeilBrown 	bit_spin_lock(0, (unsigned long *)bucket);
345c5783311SNeilBrown 	lock_acquire_exclusive(&tbl->dep_map, subclass, 0, NULL, _THIS_IP_);
346*e47877c7STejun Heo 	return flags;
347c5783311SNeilBrown }
348c5783311SNeilBrown 
rht_unlock(struct bucket_table * tbl,struct rhash_lock_head __rcu ** bkt,unsigned long flags)349c5783311SNeilBrown static inline void rht_unlock(struct bucket_table *tbl,
350*e47877c7STejun Heo 			      struct rhash_lock_head __rcu **bkt,
351*e47877c7STejun Heo 			      unsigned long flags)
352c5783311SNeilBrown {
353c5783311SNeilBrown 	lock_map_release(&tbl->dep_map);
354ca0b709dSNeilBrown 	bit_spin_unlock(0, (unsigned long *)bkt);
355*e47877c7STejun Heo 	local_irq_restore(flags);
356c5783311SNeilBrown }
357c5783311SNeilBrown 
__rht_ptr(struct rhash_lock_head * p,struct rhash_lock_head __rcu * const * bkt)3581748f6a2SHerbert Xu static inline struct rhash_head *__rht_ptr(
3591748f6a2SHerbert Xu 	struct rhash_lock_head *p, struct rhash_lock_head __rcu *const *bkt)
360ba6306e3SHerbert Xu {
3611748f6a2SHerbert Xu 	return (struct rhash_head *)
3621748f6a2SHerbert Xu 		((unsigned long)p & ~BIT(0) ?:
363279758f8SHerbert Xu 		 (unsigned long)RHT_NULLS_MARKER(bkt));
364ba6306e3SHerbert Xu }
365ba6306e3SHerbert Xu 
366c5783311SNeilBrown /*
367adc6a3abSNeilBrown  * Where 'bkt' is a bucket and might be locked:
368279758f8SHerbert Xu  *   rht_ptr_rcu() dereferences that pointer and clears the lock bit.
369279758f8SHerbert Xu  *   rht_ptr() dereferences in a context where the bucket is locked.
370adc6a3abSNeilBrown  *   rht_ptr_exclusive() dereferences in a context where exclusive
371adc6a3abSNeilBrown  *            access is guaranteed, such as when destroying the table.
372c5783311SNeilBrown  */
rht_ptr_rcu(struct rhash_lock_head __rcu * const * bkt)373279758f8SHerbert Xu static inline struct rhash_head *rht_ptr_rcu(
374ce9b362bSHerbert Xu 	struct rhash_lock_head __rcu *const *bkt)
375279758f8SHerbert Xu {
3761748f6a2SHerbert Xu 	return __rht_ptr(rcu_dereference(*bkt), bkt);
377279758f8SHerbert Xu }
378279758f8SHerbert Xu 
rht_ptr(struct rhash_lock_head __rcu * const * bkt,struct bucket_table * tbl,unsigned int hash)379adc6a3abSNeilBrown static inline struct rhash_head *rht_ptr(
380ce9b362bSHerbert Xu 	struct rhash_lock_head __rcu *const *bkt,
381adc6a3abSNeilBrown 	struct bucket_table *tbl,
382adc6a3abSNeilBrown 	unsigned int hash)
383c5783311SNeilBrown {
3841748f6a2SHerbert Xu 	return __rht_ptr(rht_dereference_bucket(*bkt, tbl, hash), bkt);
385c5783311SNeilBrown }
386c5783311SNeilBrown 
rht_ptr_exclusive(struct rhash_lock_head __rcu * const * bkt)387ba6306e3SHerbert Xu static inline struct rhash_head *rht_ptr_exclusive(
388ce9b362bSHerbert Xu 	struct rhash_lock_head __rcu *const *bkt)
389ba6306e3SHerbert Xu {
3901748f6a2SHerbert Xu 	return __rht_ptr(rcu_dereference_protected(*bkt, 1), bkt);
391ba6306e3SHerbert Xu }
392ba6306e3SHerbert Xu 
rht_assign_locked(struct rhash_lock_head __rcu ** bkt,struct rhash_head * obj)393ce9b362bSHerbert Xu static inline void rht_assign_locked(struct rhash_lock_head __rcu **bkt,
394f4712b46SNeilBrown 				     struct rhash_head *obj)
395c5783311SNeilBrown {
396ca0b709dSNeilBrown 	if (rht_is_a_nulls(obj))
397ca0b709dSNeilBrown 		obj = NULL;
398ce9b362bSHerbert Xu 	rcu_assign_pointer(*bkt, (void *)((unsigned long)obj | BIT(0)));
399c5783311SNeilBrown }
400c5783311SNeilBrown 
rht_assign_unlock(struct bucket_table * tbl,struct rhash_lock_head __rcu ** bkt,struct rhash_head * obj,unsigned long flags)401c5783311SNeilBrown static inline void rht_assign_unlock(struct bucket_table *tbl,
402ce9b362bSHerbert Xu 				     struct rhash_lock_head __rcu **bkt,
403*e47877c7STejun Heo 				     struct rhash_head *obj,
404*e47877c7STejun Heo 				     unsigned long flags)
405c5783311SNeilBrown {
406ca0b709dSNeilBrown 	if (rht_is_a_nulls(obj))
407ca0b709dSNeilBrown 		obj = NULL;
408c5783311SNeilBrown 	lock_map_release(&tbl->dep_map);
409ce9b362bSHerbert Xu 	rcu_assign_pointer(*bkt, (void *)obj);
410c5783311SNeilBrown 	preempt_enable();
411c5783311SNeilBrown 	__release(bitlock);
412*e47877c7STejun Heo 	local_irq_restore(flags);
413c5783311SNeilBrown }
414c5783311SNeilBrown 
41588d6ed15SThomas Graf /**
416f7ad68bfSNeilBrown  * rht_for_each_from - iterate over hash chain from given head
41788d6ed15SThomas Graf  * @pos:	the &struct rhash_head to use as a loop cursor.
418f7ad68bfSNeilBrown  * @head:	the &struct rhash_head to start from
41988d6ed15SThomas Graf  * @tbl:	the &struct bucket_table
42088d6ed15SThomas Graf  * @hash:	the hash value / bucket index
42188d6ed15SThomas Graf  */
422f7ad68bfSNeilBrown #define rht_for_each_from(pos, head, tbl, hash) \
423adc6a3abSNeilBrown 	for (pos = head;			\
424f89bd6f8SThomas Graf 	     !rht_is_a_nulls(pos);		\
42588d6ed15SThomas Graf 	     pos = rht_dereference_bucket((pos)->next, tbl, hash))
4267e1e7763SThomas Graf 
4277e1e7763SThomas Graf /**
4287e1e7763SThomas Graf  * rht_for_each - iterate over hash chain
42988d6ed15SThomas Graf  * @pos:	the &struct rhash_head to use as a loop cursor.
43088d6ed15SThomas Graf  * @tbl:	the &struct bucket_table
43188d6ed15SThomas Graf  * @hash:	the hash value / bucket index
4327e1e7763SThomas Graf  */
43388d6ed15SThomas Graf #define rht_for_each(pos, tbl, hash) \
434adc6a3abSNeilBrown 	rht_for_each_from(pos, rht_ptr(rht_bucket(tbl, hash), tbl, hash),  \
435adc6a3abSNeilBrown 			  tbl, hash)
43688d6ed15SThomas Graf 
43788d6ed15SThomas Graf /**
438f7ad68bfSNeilBrown  * rht_for_each_entry_from - iterate over hash chain from given head
43988d6ed15SThomas Graf  * @tpos:	the type * to use as a loop cursor.
44088d6ed15SThomas Graf  * @pos:	the &struct rhash_head to use as a loop cursor.
441f7ad68bfSNeilBrown  * @head:	the &struct rhash_head to start from
44288d6ed15SThomas Graf  * @tbl:	the &struct bucket_table
44388d6ed15SThomas Graf  * @hash:	the hash value / bucket index
44488d6ed15SThomas Graf  * @member:	name of the &struct rhash_head within the hashable struct.
44588d6ed15SThomas Graf  */
446f7ad68bfSNeilBrown #define rht_for_each_entry_from(tpos, pos, head, tbl, hash, member)	\
447adc6a3abSNeilBrown 	for (pos = head;						\
448f89bd6f8SThomas Graf 	     (!rht_is_a_nulls(pos)) && rht_entry(tpos, pos, member);	\
44988d6ed15SThomas Graf 	     pos = rht_dereference_bucket((pos)->next, tbl, hash))
4507e1e7763SThomas Graf 
4517e1e7763SThomas Graf /**
4527e1e7763SThomas Graf  * rht_for_each_entry - iterate over hash chain of given type
45388d6ed15SThomas Graf  * @tpos:	the type * to use as a loop cursor.
45488d6ed15SThomas Graf  * @pos:	the &struct rhash_head to use as a loop cursor.
45588d6ed15SThomas Graf  * @tbl:	the &struct bucket_table
45688d6ed15SThomas Graf  * @hash:	the hash value / bucket index
45788d6ed15SThomas Graf  * @member:	name of the &struct rhash_head within the hashable struct.
4587e1e7763SThomas Graf  */
45988d6ed15SThomas Graf #define rht_for_each_entry(tpos, pos, tbl, hash, member)		\
460adc6a3abSNeilBrown 	rht_for_each_entry_from(tpos, pos,				\
461adc6a3abSNeilBrown 				rht_ptr(rht_bucket(tbl, hash), tbl, hash), \
46288d6ed15SThomas Graf 				tbl, hash, member)
4637e1e7763SThomas Graf 
4647e1e7763SThomas Graf /**
4657e1e7763SThomas Graf  * rht_for_each_entry_safe - safely iterate over hash chain of given type
46688d6ed15SThomas Graf  * @tpos:	the type * to use as a loop cursor.
46788d6ed15SThomas Graf  * @pos:	the &struct rhash_head to use as a loop cursor.
46888d6ed15SThomas Graf  * @next:	the &struct rhash_head to use as next in loop cursor.
46988d6ed15SThomas Graf  * @tbl:	the &struct bucket_table
47088d6ed15SThomas Graf  * @hash:	the hash value / bucket index
47188d6ed15SThomas Graf  * @member:	name of the &struct rhash_head within the hashable struct.
4727e1e7763SThomas Graf  *
4737e1e7763SThomas Graf  * This hash chain list-traversal primitive allows for the looped code to
4747e1e7763SThomas Graf  * remove the loop cursor from the list.
4757e1e7763SThomas Graf  */
47688d6ed15SThomas Graf #define rht_for_each_entry_safe(tpos, pos, next, tbl, hash, member)	      \
477adc6a3abSNeilBrown 	for (pos = rht_ptr(rht_bucket(tbl, hash), tbl, hash),		      \
478f89bd6f8SThomas Graf 	     next = !rht_is_a_nulls(pos) ?				      \
479f89bd6f8SThomas Graf 		       rht_dereference_bucket(pos->next, tbl, hash) : NULL;   \
480f89bd6f8SThomas Graf 	     (!rht_is_a_nulls(pos)) && rht_entry(tpos, pos, member);	      \
481607954b0SPatrick McHardy 	     pos = next,						      \
482607954b0SPatrick McHardy 	     next = !rht_is_a_nulls(pos) ?				      \
483607954b0SPatrick McHardy 		       rht_dereference_bucket(pos->next, tbl, hash) : NULL)
48488d6ed15SThomas Graf 
48588d6ed15SThomas Graf /**
486f7ad68bfSNeilBrown  * rht_for_each_rcu_from - iterate over rcu hash chain from given head
48788d6ed15SThomas Graf  * @pos:	the &struct rhash_head to use as a loop cursor.
488f7ad68bfSNeilBrown  * @head:	the &struct rhash_head to start from
48988d6ed15SThomas Graf  * @tbl:	the &struct bucket_table
49088d6ed15SThomas Graf  * @hash:	the hash value / bucket index
49188d6ed15SThomas Graf  *
49288d6ed15SThomas Graf  * This hash chain list-traversal primitive may safely run concurrently with
49388d6ed15SThomas Graf  * the _rcu mutation primitives such as rhashtable_insert() as long as the
49488d6ed15SThomas Graf  * traversal is guarded by rcu_read_lock().
49588d6ed15SThomas Graf  */
496f7ad68bfSNeilBrown #define rht_for_each_rcu_from(pos, head, tbl, hash)			\
49788d6ed15SThomas Graf 	for (({barrier(); }),						\
498adc6a3abSNeilBrown 	     pos = head;						\
499f89bd6f8SThomas Graf 	     !rht_is_a_nulls(pos);					\
50088d6ed15SThomas Graf 	     pos = rcu_dereference_raw(pos->next))
5017e1e7763SThomas Graf 
5027e1e7763SThomas Graf /**
5037e1e7763SThomas Graf  * rht_for_each_rcu - iterate over rcu hash chain
50488d6ed15SThomas Graf  * @pos:	the &struct rhash_head to use as a loop cursor.
50588d6ed15SThomas Graf  * @tbl:	the &struct bucket_table
50688d6ed15SThomas Graf  * @hash:	the hash value / bucket index
5077e1e7763SThomas Graf  *
5087e1e7763SThomas Graf  * This hash chain list-traversal primitive may safely run concurrently with
50988d6ed15SThomas Graf  * the _rcu mutation primitives such as rhashtable_insert() as long as the
5107e1e7763SThomas Graf  * traversal is guarded by rcu_read_lock().
5117e1e7763SThomas Graf  */
51288d6ed15SThomas Graf #define rht_for_each_rcu(pos, tbl, hash)			\
5138f0db018SNeilBrown 	for (({barrier(); }),					\
514279758f8SHerbert Xu 	     pos = rht_ptr_rcu(rht_bucket(tbl, hash));		\
5158f0db018SNeilBrown 	     !rht_is_a_nulls(pos);				\
5168f0db018SNeilBrown 	     pos = rcu_dereference_raw(pos->next))
51788d6ed15SThomas Graf 
51888d6ed15SThomas Graf /**
519f7ad68bfSNeilBrown  * rht_for_each_entry_rcu_from - iterated over rcu hash chain from given head
52088d6ed15SThomas Graf  * @tpos:	the type * to use as a loop cursor.
52188d6ed15SThomas Graf  * @pos:	the &struct rhash_head to use as a loop cursor.
522f7ad68bfSNeilBrown  * @head:	the &struct rhash_head to start from
52388d6ed15SThomas Graf  * @tbl:	the &struct bucket_table
52488d6ed15SThomas Graf  * @hash:	the hash value / bucket index
52588d6ed15SThomas Graf  * @member:	name of the &struct rhash_head within the hashable struct.
52688d6ed15SThomas Graf  *
52788d6ed15SThomas Graf  * This hash chain list-traversal primitive may safely run concurrently with
52888d6ed15SThomas Graf  * the _rcu mutation primitives such as rhashtable_insert() as long as the
52988d6ed15SThomas Graf  * traversal is guarded by rcu_read_lock().
53088d6ed15SThomas Graf  */
531f7ad68bfSNeilBrown #define rht_for_each_entry_rcu_from(tpos, pos, head, tbl, hash, member) \
53288d6ed15SThomas Graf 	for (({barrier(); }),						    \
533adc6a3abSNeilBrown 	     pos = head;						    \
534f89bd6f8SThomas Graf 	     (!rht_is_a_nulls(pos)) && rht_entry(tpos, pos, member);	    \
53588d6ed15SThomas Graf 	     pos = rht_dereference_bucket_rcu(pos->next, tbl, hash))
5367e1e7763SThomas Graf 
5377e1e7763SThomas Graf /**
5387e1e7763SThomas Graf  * rht_for_each_entry_rcu - iterate over rcu hash chain of given type
53988d6ed15SThomas Graf  * @tpos:	the type * to use as a loop cursor.
54088d6ed15SThomas Graf  * @pos:	the &struct rhash_head to use as a loop cursor.
54188d6ed15SThomas Graf  * @tbl:	the &struct bucket_table
54288d6ed15SThomas Graf  * @hash:	the hash value / bucket index
54388d6ed15SThomas Graf  * @member:	name of the &struct rhash_head within the hashable struct.
5447e1e7763SThomas Graf  *
5457e1e7763SThomas Graf  * This hash chain list-traversal primitive may safely run concurrently with
54688d6ed15SThomas Graf  * the _rcu mutation primitives such as rhashtable_insert() as long as the
5477e1e7763SThomas Graf  * traversal is guarded by rcu_read_lock().
5487e1e7763SThomas Graf  */
54988d6ed15SThomas Graf #define rht_for_each_entry_rcu(tpos, pos, tbl, hash, member)		   \
5508f0db018SNeilBrown 	rht_for_each_entry_rcu_from(tpos, pos,				   \
551279758f8SHerbert Xu 				    rht_ptr_rcu(rht_bucket(tbl, hash)),	   \
55288d6ed15SThomas Graf 				    tbl, hash, member)
5537e1e7763SThomas Graf 
554ca26893fSHerbert Xu /**
555ca26893fSHerbert Xu  * rhl_for_each_rcu - iterate over rcu hash table list
556ca26893fSHerbert Xu  * @pos:	the &struct rlist_head to use as a loop cursor.
557ca26893fSHerbert Xu  * @list:	the head of the list
558ca26893fSHerbert Xu  *
559ca26893fSHerbert Xu  * This hash chain list-traversal primitive should be used on the
560ca26893fSHerbert Xu  * list returned by rhltable_lookup.
561ca26893fSHerbert Xu  */
562ca26893fSHerbert Xu #define rhl_for_each_rcu(pos, list)					\
563ca26893fSHerbert Xu 	for (pos = list; pos; pos = rcu_dereference_raw(pos->next))
564ca26893fSHerbert Xu 
565ca26893fSHerbert Xu /**
566ca26893fSHerbert Xu  * rhl_for_each_entry_rcu - iterate over rcu hash table list of given type
567ca26893fSHerbert Xu  * @tpos:	the type * to use as a loop cursor.
568ca26893fSHerbert Xu  * @pos:	the &struct rlist_head to use as a loop cursor.
569ca26893fSHerbert Xu  * @list:	the head of the list
570ca26893fSHerbert Xu  * @member:	name of the &struct rlist_head within the hashable struct.
571ca26893fSHerbert Xu  *
572ca26893fSHerbert Xu  * This hash chain list-traversal primitive should be used on the
573ca26893fSHerbert Xu  * list returned by rhltable_lookup.
574ca26893fSHerbert Xu  */
575ca26893fSHerbert Xu #define rhl_for_each_entry_rcu(tpos, pos, list, member)			\
576ca26893fSHerbert Xu 	for (pos = list; pos && rht_entry(tpos, pos, member);		\
577ca26893fSHerbert Xu 	     pos = rcu_dereference_raw(pos->next))
578ca26893fSHerbert Xu 
rhashtable_compare(struct rhashtable_compare_arg * arg,const void * obj)57902fd97c3SHerbert Xu static inline int rhashtable_compare(struct rhashtable_compare_arg *arg,
58002fd97c3SHerbert Xu 				     const void *obj)
58102fd97c3SHerbert Xu {
58202fd97c3SHerbert Xu 	struct rhashtable *ht = arg->ht;
58302fd97c3SHerbert Xu 	const char *ptr = obj;
58402fd97c3SHerbert Xu 
58502fd97c3SHerbert Xu 	return memcmp(ptr + ht->p.key_offset, arg->key, ht->p.key_len);
58602fd97c3SHerbert Xu }
58702fd97c3SHerbert Xu 
588ca26893fSHerbert Xu /* Internal function, do not use. */
__rhashtable_lookup(struct rhashtable * ht,const void * key,const struct rhashtable_params params)589ca26893fSHerbert Xu static inline struct rhash_head *__rhashtable_lookup(
59002fd97c3SHerbert Xu 	struct rhashtable *ht, const void *key,
59102fd97c3SHerbert Xu 	const struct rhashtable_params params)
59202fd97c3SHerbert Xu {
59302fd97c3SHerbert Xu 	struct rhashtable_compare_arg arg = {
59402fd97c3SHerbert Xu 		.ht = ht,
59502fd97c3SHerbert Xu 		.key = key,
59602fd97c3SHerbert Xu 	};
597ce9b362bSHerbert Xu 	struct rhash_lock_head __rcu *const *bkt;
598da20420fSHerbert Xu 	struct bucket_table *tbl;
59902fd97c3SHerbert Xu 	struct rhash_head *he;
600299e5c32SThomas Graf 	unsigned int hash;
60102fd97c3SHerbert Xu 
60202fd97c3SHerbert Xu 	tbl = rht_dereference_rcu(ht->tbl, ht);
60302fd97c3SHerbert Xu restart:
60402fd97c3SHerbert Xu 	hash = rht_key_hashfn(ht, tbl, key, params);
6058f0db018SNeilBrown 	bkt = rht_bucket(tbl, hash);
60682208d0dSNeilBrown 	do {
607279758f8SHerbert Xu 		rht_for_each_rcu_from(he, rht_ptr_rcu(bkt), tbl, hash) {
60802fd97c3SHerbert Xu 			if (params.obj_cmpfn ?
60902fd97c3SHerbert Xu 			    params.obj_cmpfn(&arg, rht_obj(ht, he)) :
61002fd97c3SHerbert Xu 			    rhashtable_compare(&arg, rht_obj(ht, he)))
61102fd97c3SHerbert Xu 				continue;
612ca26893fSHerbert Xu 			return he;
61302fd97c3SHerbert Xu 		}
61482208d0dSNeilBrown 		/* An object might have been moved to a different hash chain,
61582208d0dSNeilBrown 		 * while we walk along it - better check and retry.
61682208d0dSNeilBrown 		 */
6178f0db018SNeilBrown 	} while (he != RHT_NULLS_MARKER(bkt));
61802fd97c3SHerbert Xu 
61902fd97c3SHerbert Xu 	/* Ensure we see any new tables. */
62002fd97c3SHerbert Xu 	smp_rmb();
62102fd97c3SHerbert Xu 
62202fd97c3SHerbert Xu 	tbl = rht_dereference_rcu(tbl->future_tbl, ht);
62302fd97c3SHerbert Xu 	if (unlikely(tbl))
62402fd97c3SHerbert Xu 		goto restart;
62502fd97c3SHerbert Xu 
62602fd97c3SHerbert Xu 	return NULL;
62702fd97c3SHerbert Xu }
62802fd97c3SHerbert Xu 
629ca26893fSHerbert Xu /**
630ca26893fSHerbert Xu  * rhashtable_lookup - search hash table
631ca26893fSHerbert Xu  * @ht:		hash table
632ca26893fSHerbert Xu  * @key:	the pointer to the key
633ca26893fSHerbert Xu  * @params:	hash table parameters
634ca26893fSHerbert Xu  *
635ca26893fSHerbert Xu  * Computes the hash value for the key and traverses the bucket chain looking
636ca26893fSHerbert Xu  * for a entry with an identical key. The first matching entry is returned.
637ca26893fSHerbert Xu  *
638ca26893fSHerbert Xu  * This must only be called under the RCU read lock.
639ca26893fSHerbert Xu  *
640ca26893fSHerbert Xu  * Returns the first entry on which the compare function returned true.
641ca26893fSHerbert Xu  */
rhashtable_lookup(struct rhashtable * ht,const void * key,const struct rhashtable_params params)642ca26893fSHerbert Xu static inline void *rhashtable_lookup(
643ca26893fSHerbert Xu 	struct rhashtable *ht, const void *key,
644ca26893fSHerbert Xu 	const struct rhashtable_params params)
645ca26893fSHerbert Xu {
646ca26893fSHerbert Xu 	struct rhash_head *he = __rhashtable_lookup(ht, key, params);
647ca26893fSHerbert Xu 
648ca26893fSHerbert Xu 	return he ? rht_obj(ht, he) : NULL;
649ca26893fSHerbert Xu }
650ca26893fSHerbert Xu 
651ca26893fSHerbert Xu /**
652ca26893fSHerbert Xu  * rhashtable_lookup_fast - search hash table, without RCU read lock
653ca26893fSHerbert Xu  * @ht:		hash table
654ca26893fSHerbert Xu  * @key:	the pointer to the key
655ca26893fSHerbert Xu  * @params:	hash table parameters
656ca26893fSHerbert Xu  *
657ca26893fSHerbert Xu  * Computes the hash value for the key and traverses the bucket chain looking
658ca26893fSHerbert Xu  * for a entry with an identical key. The first matching entry is returned.
659ca26893fSHerbert Xu  *
660ca26893fSHerbert Xu  * Only use this function when you have other mechanisms guaranteeing
661ca26893fSHerbert Xu  * that the object won't go away after the RCU read lock is released.
662ca26893fSHerbert Xu  *
663ca26893fSHerbert Xu  * Returns the first entry on which the compare function returned true.
664ca26893fSHerbert Xu  */
rhashtable_lookup_fast(struct rhashtable * ht,const void * key,const struct rhashtable_params params)665ca26893fSHerbert Xu static inline void *rhashtable_lookup_fast(
666ca26893fSHerbert Xu 	struct rhashtable *ht, const void *key,
667ca26893fSHerbert Xu 	const struct rhashtable_params params)
668ca26893fSHerbert Xu {
669ca26893fSHerbert Xu 	void *obj;
670ca26893fSHerbert Xu 
671ca26893fSHerbert Xu 	rcu_read_lock();
672ca26893fSHerbert Xu 	obj = rhashtable_lookup(ht, key, params);
673ca26893fSHerbert Xu 	rcu_read_unlock();
674ca26893fSHerbert Xu 
675ca26893fSHerbert Xu 	return obj;
676ca26893fSHerbert Xu }
677ca26893fSHerbert Xu 
678ca26893fSHerbert Xu /**
679ca26893fSHerbert Xu  * rhltable_lookup - search hash list table
680ca26893fSHerbert Xu  * @hlt:	hash table
681ca26893fSHerbert Xu  * @key:	the pointer to the key
682ca26893fSHerbert Xu  * @params:	hash table parameters
683ca26893fSHerbert Xu  *
684ca26893fSHerbert Xu  * Computes the hash value for the key and traverses the bucket chain looking
685ca26893fSHerbert Xu  * for a entry with an identical key.  All matching entries are returned
686ca26893fSHerbert Xu  * in a list.
687ca26893fSHerbert Xu  *
688ca26893fSHerbert Xu  * This must only be called under the RCU read lock.
689ca26893fSHerbert Xu  *
690ca26893fSHerbert Xu  * Returns the list of entries that match the given key.
691ca26893fSHerbert Xu  */
rhltable_lookup(struct rhltable * hlt,const void * key,const struct rhashtable_params params)692ca26893fSHerbert Xu static inline struct rhlist_head *rhltable_lookup(
693ca26893fSHerbert Xu 	struct rhltable *hlt, const void *key,
694ca26893fSHerbert Xu 	const struct rhashtable_params params)
695ca26893fSHerbert Xu {
696ca26893fSHerbert Xu 	struct rhash_head *he = __rhashtable_lookup(&hlt->ht, key, params);
697ca26893fSHerbert Xu 
698ca26893fSHerbert Xu 	return he ? container_of(he, struct rhlist_head, rhead) : NULL;
699ca26893fSHerbert Xu }
700ca26893fSHerbert Xu 
7015ca8cc5bSPablo Neira Ayuso /* Internal function, please use rhashtable_insert_fast() instead. This
7025ca8cc5bSPablo Neira Ayuso  * function returns the existing element already in hashes in there is a clash,
7035ca8cc5bSPablo Neira Ayuso  * otherwise it returns an error via ERR_PTR().
7045ca8cc5bSPablo Neira Ayuso  */
__rhashtable_insert_fast(struct rhashtable * ht,const void * key,struct rhash_head * obj,const struct rhashtable_params params,bool rhlist)7055ca8cc5bSPablo Neira Ayuso static inline void *__rhashtable_insert_fast(
70602fd97c3SHerbert Xu 	struct rhashtable *ht, const void *key, struct rhash_head *obj,
707ca26893fSHerbert Xu 	const struct rhashtable_params params, bool rhlist)
70802fd97c3SHerbert Xu {
70902fd97c3SHerbert Xu 	struct rhashtable_compare_arg arg = {
71002fd97c3SHerbert Xu 		.ht = ht,
71102fd97c3SHerbert Xu 		.key = key,
71202fd97c3SHerbert Xu 	};
713ce9b362bSHerbert Xu 	struct rhash_lock_head __rcu **bkt;
714ca26893fSHerbert Xu 	struct rhash_head __rcu **pprev;
715ca26893fSHerbert Xu 	struct bucket_table *tbl;
71602fd97c3SHerbert Xu 	struct rhash_head *head;
717*e47877c7STejun Heo 	unsigned long flags;
718299e5c32SThomas Graf 	unsigned int hash;
719ca26893fSHerbert Xu 	int elasticity;
720ca26893fSHerbert Xu 	void *data;
72102fd97c3SHerbert Xu 
72202fd97c3SHerbert Xu 	rcu_read_lock();
72302fd97c3SHerbert Xu 
72402fd97c3SHerbert Xu 	tbl = rht_dereference_rcu(ht->tbl, ht);
72502fd97c3SHerbert Xu 	hash = rht_head_hashfn(ht, tbl, obj, params);
7268f0db018SNeilBrown 	elasticity = RHT_ELASTICITY;
7278f0db018SNeilBrown 	bkt = rht_bucket_insert(ht, tbl, hash);
7288f0db018SNeilBrown 	data = ERR_PTR(-ENOMEM);
7298f0db018SNeilBrown 	if (!bkt)
7308f0db018SNeilBrown 		goto out;
7318f0db018SNeilBrown 	pprev = NULL;
732*e47877c7STejun Heo 	flags = rht_lock(tbl, bkt);
73302fd97c3SHerbert Xu 
734c0690016SNeilBrown 	if (unlikely(rcu_access_pointer(tbl->future_tbl))) {
735ca26893fSHerbert Xu slow_path:
736*e47877c7STejun Heo 		rht_unlock(tbl, bkt, flags);
737ca26893fSHerbert Xu 		rcu_read_unlock();
738ca26893fSHerbert Xu 		return rhashtable_insert_slow(ht, key, obj);
739b824478bSHerbert Xu 	}
740b824478bSHerbert Xu 
741adc6a3abSNeilBrown 	rht_for_each_from(head, rht_ptr(bkt, tbl, hash), tbl, hash) {
742ca26893fSHerbert Xu 		struct rhlist_head *plist;
743ca26893fSHerbert Xu 		struct rhlist_head *list;
744ca26893fSHerbert Xu 
745ca26893fSHerbert Xu 		elasticity--;
746ca26893fSHerbert Xu 		if (!key ||
747ca26893fSHerbert Xu 		    (params.obj_cmpfn ?
748ca26893fSHerbert Xu 		     params.obj_cmpfn(&arg, rht_obj(ht, head)) :
749d3dcf8ebSPaul Blakey 		     rhashtable_compare(&arg, rht_obj(ht, head)))) {
750d3dcf8ebSPaul Blakey 			pprev = &head->next;
751ca26893fSHerbert Xu 			continue;
752d3dcf8ebSPaul Blakey 		}
753ca26893fSHerbert Xu 
754ca26893fSHerbert Xu 		data = rht_obj(ht, head);
755ca26893fSHerbert Xu 
756ca26893fSHerbert Xu 		if (!rhlist)
7578f0db018SNeilBrown 			goto out_unlock;
758ca26893fSHerbert Xu 
759ca26893fSHerbert Xu 
760ca26893fSHerbert Xu 		list = container_of(obj, struct rhlist_head, rhead);
761ca26893fSHerbert Xu 		plist = container_of(head, struct rhlist_head, rhead);
762ca26893fSHerbert Xu 
763ca26893fSHerbert Xu 		RCU_INIT_POINTER(list->next, plist);
764ca26893fSHerbert Xu 		head = rht_dereference_bucket(head->next, tbl, hash);
765ca26893fSHerbert Xu 		RCU_INIT_POINTER(list->rhead.next, head);
7668f0db018SNeilBrown 		if (pprev) {
767ca26893fSHerbert Xu 			rcu_assign_pointer(*pprev, obj);
768*e47877c7STejun Heo 			rht_unlock(tbl, bkt, flags);
7698f0db018SNeilBrown 		} else
770*e47877c7STejun Heo 			rht_assign_unlock(tbl, bkt, obj, flags);
7718f0db018SNeilBrown 		data = NULL;
7728f0db018SNeilBrown 		goto out;
773ca26893fSHerbert Xu 	}
774ca26893fSHerbert Xu 
775ca26893fSHerbert Xu 	if (elasticity <= 0)
776ccd57b1bSHerbert Xu 		goto slow_path;
7773cf92222SHerbert Xu 
778ca26893fSHerbert Xu 	data = ERR_PTR(-E2BIG);
77907ee0722SHerbert Xu 	if (unlikely(rht_grow_above_max(ht, tbl)))
7808f0db018SNeilBrown 		goto out_unlock;
78107ee0722SHerbert Xu 
782ca26893fSHerbert Xu 	if (unlikely(rht_grow_above_100(ht, tbl)))
783ccd57b1bSHerbert Xu 		goto slow_path;
78402fd97c3SHerbert Xu 
7858f0db018SNeilBrown 	/* Inserting at head of list makes unlocking free. */
786adc6a3abSNeilBrown 	head = rht_ptr(bkt, tbl, hash);
78702fd97c3SHerbert Xu 
78802fd97c3SHerbert Xu 	RCU_INIT_POINTER(obj->next, head);
789ca26893fSHerbert Xu 	if (rhlist) {
790ca26893fSHerbert Xu 		struct rhlist_head *list;
791ca26893fSHerbert Xu 
792ca26893fSHerbert Xu 		list = container_of(obj, struct rhlist_head, rhead);
793ca26893fSHerbert Xu 		RCU_INIT_POINTER(list->next, NULL);
794ca26893fSHerbert Xu 	}
79502fd97c3SHerbert Xu 
79602fd97c3SHerbert Xu 	atomic_inc(&ht->nelems);
797*e47877c7STejun Heo 	rht_assign_unlock(tbl, bkt, obj, flags);
7988f0db018SNeilBrown 
79902fd97c3SHerbert Xu 	if (rht_grow_above_75(ht, tbl))
80002fd97c3SHerbert Xu 		schedule_work(&ht->run_work);
80102fd97c3SHerbert Xu 
802ca26893fSHerbert Xu 	data = NULL;
80302fd97c3SHerbert Xu out:
80402fd97c3SHerbert Xu 	rcu_read_unlock();
80502fd97c3SHerbert Xu 
806ca26893fSHerbert Xu 	return data;
8078f0db018SNeilBrown 
8088f0db018SNeilBrown out_unlock:
809*e47877c7STejun Heo 	rht_unlock(tbl, bkt, flags);
8108f0db018SNeilBrown 	goto out;
81102fd97c3SHerbert Xu }
81202fd97c3SHerbert Xu 
81302fd97c3SHerbert Xu /**
81402fd97c3SHerbert Xu  * rhashtable_insert_fast - insert object into hash table
81502fd97c3SHerbert Xu  * @ht:		hash table
81602fd97c3SHerbert Xu  * @obj:	pointer to hash head inside object
81702fd97c3SHerbert Xu  * @params:	hash table parameters
81802fd97c3SHerbert Xu  *
8198f0db018SNeilBrown  * Will take the per bucket bitlock to protect against mutual mutations
82002fd97c3SHerbert Xu  * on the same bucket. Multiple insertions may occur in parallel unless
8218f0db018SNeilBrown  * they map to the same bucket.
82202fd97c3SHerbert Xu  *
82302fd97c3SHerbert Xu  * It is safe to call this function from atomic context.
82402fd97c3SHerbert Xu  *
8250c6f69a5SNeilBrown  * Will trigger an automatic deferred table resizing if residency in the
8260c6f69a5SNeilBrown  * table grows beyond 70%.
82702fd97c3SHerbert Xu  */
rhashtable_insert_fast(struct rhashtable * ht,struct rhash_head * obj,const struct rhashtable_params params)82802fd97c3SHerbert Xu static inline int rhashtable_insert_fast(
82902fd97c3SHerbert Xu 	struct rhashtable *ht, struct rhash_head *obj,
83002fd97c3SHerbert Xu 	const struct rhashtable_params params)
83102fd97c3SHerbert Xu {
8325ca8cc5bSPablo Neira Ayuso 	void *ret;
8335ca8cc5bSPablo Neira Ayuso 
834ca26893fSHerbert Xu 	ret = __rhashtable_insert_fast(ht, NULL, obj, params, false);
8355ca8cc5bSPablo Neira Ayuso 	if (IS_ERR(ret))
8365ca8cc5bSPablo Neira Ayuso 		return PTR_ERR(ret);
8375ca8cc5bSPablo Neira Ayuso 
8385ca8cc5bSPablo Neira Ayuso 	return ret == NULL ? 0 : -EEXIST;
83902fd97c3SHerbert Xu }
84002fd97c3SHerbert Xu 
84102fd97c3SHerbert Xu /**
842ca26893fSHerbert Xu  * rhltable_insert_key - insert object into hash list table
843ca26893fSHerbert Xu  * @hlt:	hash list table
844ca26893fSHerbert Xu  * @key:	the pointer to the key
845ca26893fSHerbert Xu  * @list:	pointer to hash list head inside object
846ca26893fSHerbert Xu  * @params:	hash table parameters
847ca26893fSHerbert Xu  *
8488f0db018SNeilBrown  * Will take the per bucket bitlock to protect against mutual mutations
849ca26893fSHerbert Xu  * on the same bucket. Multiple insertions may occur in parallel unless
8508f0db018SNeilBrown  * they map to the same bucket.
851ca26893fSHerbert Xu  *
852ca26893fSHerbert Xu  * It is safe to call this function from atomic context.
853ca26893fSHerbert Xu  *
8540c6f69a5SNeilBrown  * Will trigger an automatic deferred table resizing if residency in the
8550c6f69a5SNeilBrown  * table grows beyond 70%.
856ca26893fSHerbert Xu  */
rhltable_insert_key(struct rhltable * hlt,const void * key,struct rhlist_head * list,const struct rhashtable_params params)857ca26893fSHerbert Xu static inline int rhltable_insert_key(
858ca26893fSHerbert Xu 	struct rhltable *hlt, const void *key, struct rhlist_head *list,
859ca26893fSHerbert Xu 	const struct rhashtable_params params)
860ca26893fSHerbert Xu {
861ca26893fSHerbert Xu 	return PTR_ERR(__rhashtable_insert_fast(&hlt->ht, key, &list->rhead,
862ca26893fSHerbert Xu 						params, true));
863ca26893fSHerbert Xu }
864ca26893fSHerbert Xu 
865ca26893fSHerbert Xu /**
866ca26893fSHerbert Xu  * rhltable_insert - insert object into hash list table
867ca26893fSHerbert Xu  * @hlt:	hash list table
868ca26893fSHerbert Xu  * @list:	pointer to hash list head inside object
869ca26893fSHerbert Xu  * @params:	hash table parameters
870ca26893fSHerbert Xu  *
8718f0db018SNeilBrown  * Will take the per bucket bitlock to protect against mutual mutations
872ca26893fSHerbert Xu  * on the same bucket. Multiple insertions may occur in parallel unless
8738f0db018SNeilBrown  * they map to the same bucket.
874ca26893fSHerbert Xu  *
875ca26893fSHerbert Xu  * It is safe to call this function from atomic context.
876ca26893fSHerbert Xu  *
8770c6f69a5SNeilBrown  * Will trigger an automatic deferred table resizing if residency in the
8780c6f69a5SNeilBrown  * table grows beyond 70%.
879ca26893fSHerbert Xu  */
rhltable_insert(struct rhltable * hlt,struct rhlist_head * list,const struct rhashtable_params params)880ca26893fSHerbert Xu static inline int rhltable_insert(
881ca26893fSHerbert Xu 	struct rhltable *hlt, struct rhlist_head *list,
882ca26893fSHerbert Xu 	const struct rhashtable_params params)
883ca26893fSHerbert Xu {
884ca26893fSHerbert Xu 	const char *key = rht_obj(&hlt->ht, &list->rhead);
885ca26893fSHerbert Xu 
886ca26893fSHerbert Xu 	key += params.key_offset;
887ca26893fSHerbert Xu 
888ca26893fSHerbert Xu 	return rhltable_insert_key(hlt, key, list, params);
889ca26893fSHerbert Xu }
890ca26893fSHerbert Xu 
891ca26893fSHerbert Xu /**
89202fd97c3SHerbert Xu  * rhashtable_lookup_insert_fast - lookup and insert object into hash table
89302fd97c3SHerbert Xu  * @ht:		hash table
89402fd97c3SHerbert Xu  * @obj:	pointer to hash head inside object
89502fd97c3SHerbert Xu  * @params:	hash table parameters
89602fd97c3SHerbert Xu  *
89702fd97c3SHerbert Xu  * This lookup function may only be used for fixed key hash table (key_len
89802fd97c3SHerbert Xu  * parameter set). It will BUG() if used inappropriately.
89902fd97c3SHerbert Xu  *
90002fd97c3SHerbert Xu  * It is safe to call this function from atomic context.
90102fd97c3SHerbert Xu  *
9020c6f69a5SNeilBrown  * Will trigger an automatic deferred table resizing if residency in the
9030c6f69a5SNeilBrown  * table grows beyond 70%.
90402fd97c3SHerbert Xu  */
rhashtable_lookup_insert_fast(struct rhashtable * ht,struct rhash_head * obj,const struct rhashtable_params params)90502fd97c3SHerbert Xu static inline int rhashtable_lookup_insert_fast(
90602fd97c3SHerbert Xu 	struct rhashtable *ht, struct rhash_head *obj,
90702fd97c3SHerbert Xu 	const struct rhashtable_params params)
90802fd97c3SHerbert Xu {
90902fd97c3SHerbert Xu 	const char *key = rht_obj(ht, obj);
9105ca8cc5bSPablo Neira Ayuso 	void *ret;
91102fd97c3SHerbert Xu 
91202fd97c3SHerbert Xu 	BUG_ON(ht->p.obj_hashfn);
91302fd97c3SHerbert Xu 
914ca26893fSHerbert Xu 	ret = __rhashtable_insert_fast(ht, key + ht->p.key_offset, obj, params,
915ca26893fSHerbert Xu 				       false);
9165ca8cc5bSPablo Neira Ayuso 	if (IS_ERR(ret))
9175ca8cc5bSPablo Neira Ayuso 		return PTR_ERR(ret);
9185ca8cc5bSPablo Neira Ayuso 
9195ca8cc5bSPablo Neira Ayuso 	return ret == NULL ? 0 : -EEXIST;
92002fd97c3SHerbert Xu }
92102fd97c3SHerbert Xu 
92202fd97c3SHerbert Xu /**
923f9fe1c12SAndreas Gruenbacher  * rhashtable_lookup_get_insert_fast - lookup and insert object into hash table
924f9fe1c12SAndreas Gruenbacher  * @ht:		hash table
925f9fe1c12SAndreas Gruenbacher  * @obj:	pointer to hash head inside object
926f9fe1c12SAndreas Gruenbacher  * @params:	hash table parameters
927f9fe1c12SAndreas Gruenbacher  *
928f9fe1c12SAndreas Gruenbacher  * Just like rhashtable_lookup_insert_fast(), but this function returns the
929f9fe1c12SAndreas Gruenbacher  * object if it exists, NULL if it did not and the insertion was successful,
930f9fe1c12SAndreas Gruenbacher  * and an ERR_PTR otherwise.
931f9fe1c12SAndreas Gruenbacher  */
rhashtable_lookup_get_insert_fast(struct rhashtable * ht,struct rhash_head * obj,const struct rhashtable_params params)932f9fe1c12SAndreas Gruenbacher static inline void *rhashtable_lookup_get_insert_fast(
933f9fe1c12SAndreas Gruenbacher 	struct rhashtable *ht, struct rhash_head *obj,
934f9fe1c12SAndreas Gruenbacher 	const struct rhashtable_params params)
935f9fe1c12SAndreas Gruenbacher {
936f9fe1c12SAndreas Gruenbacher 	const char *key = rht_obj(ht, obj);
937f9fe1c12SAndreas Gruenbacher 
938f9fe1c12SAndreas Gruenbacher 	BUG_ON(ht->p.obj_hashfn);
939f9fe1c12SAndreas Gruenbacher 
940f9fe1c12SAndreas Gruenbacher 	return __rhashtable_insert_fast(ht, key + ht->p.key_offset, obj, params,
941f9fe1c12SAndreas Gruenbacher 					false);
942f9fe1c12SAndreas Gruenbacher }
943f9fe1c12SAndreas Gruenbacher 
944f9fe1c12SAndreas Gruenbacher /**
94502fd97c3SHerbert Xu  * rhashtable_lookup_insert_key - search and insert object to hash table
94602fd97c3SHerbert Xu  *				  with explicit key
94702fd97c3SHerbert Xu  * @ht:		hash table
94802fd97c3SHerbert Xu  * @key:	key
94902fd97c3SHerbert Xu  * @obj:	pointer to hash head inside object
95002fd97c3SHerbert Xu  * @params:	hash table parameters
95102fd97c3SHerbert Xu  *
95202fd97c3SHerbert Xu  * Lookups may occur in parallel with hashtable mutations and resizing.
95302fd97c3SHerbert Xu  *
9540c6f69a5SNeilBrown  * Will trigger an automatic deferred table resizing if residency in the
9550c6f69a5SNeilBrown  * table grows beyond 70%.
95602fd97c3SHerbert Xu  *
95702fd97c3SHerbert Xu  * Returns zero on success.
95802fd97c3SHerbert Xu  */
rhashtable_lookup_insert_key(struct rhashtable * ht,const void * key,struct rhash_head * obj,const struct rhashtable_params params)95902fd97c3SHerbert Xu static inline int rhashtable_lookup_insert_key(
96002fd97c3SHerbert Xu 	struct rhashtable *ht, const void *key, struct rhash_head *obj,
96102fd97c3SHerbert Xu 	const struct rhashtable_params params)
96202fd97c3SHerbert Xu {
9635ca8cc5bSPablo Neira Ayuso 	void *ret;
9645ca8cc5bSPablo Neira Ayuso 
9655ca8cc5bSPablo Neira Ayuso 	BUG_ON(!ht->p.obj_hashfn || !key);
9665ca8cc5bSPablo Neira Ayuso 
967ca26893fSHerbert Xu 	ret = __rhashtable_insert_fast(ht, key, obj, params, false);
9685ca8cc5bSPablo Neira Ayuso 	if (IS_ERR(ret))
9695ca8cc5bSPablo Neira Ayuso 		return PTR_ERR(ret);
9705ca8cc5bSPablo Neira Ayuso 
9715ca8cc5bSPablo Neira Ayuso 	return ret == NULL ? 0 : -EEXIST;
9725ca8cc5bSPablo Neira Ayuso }
9735ca8cc5bSPablo Neira Ayuso 
9745ca8cc5bSPablo Neira Ayuso /**
9755ca8cc5bSPablo Neira Ayuso  * rhashtable_lookup_get_insert_key - lookup and insert object into hash table
9765ca8cc5bSPablo Neira Ayuso  * @ht:		hash table
977aeaa925bSJonathan Neuschäfer  * @key:	key
9785ca8cc5bSPablo Neira Ayuso  * @obj:	pointer to hash head inside object
9795ca8cc5bSPablo Neira Ayuso  * @params:	hash table parameters
9805ca8cc5bSPablo Neira Ayuso  *
9815ca8cc5bSPablo Neira Ayuso  * Just like rhashtable_lookup_insert_key(), but this function returns the
9825ca8cc5bSPablo Neira Ayuso  * object if it exists, NULL if it does not and the insertion was successful,
9835ca8cc5bSPablo Neira Ayuso  * and an ERR_PTR otherwise.
9845ca8cc5bSPablo Neira Ayuso  */
rhashtable_lookup_get_insert_key(struct rhashtable * ht,const void * key,struct rhash_head * obj,const struct rhashtable_params params)9855ca8cc5bSPablo Neira Ayuso static inline void *rhashtable_lookup_get_insert_key(
9865ca8cc5bSPablo Neira Ayuso 	struct rhashtable *ht, const void *key, struct rhash_head *obj,
9875ca8cc5bSPablo Neira Ayuso 	const struct rhashtable_params params)
9885ca8cc5bSPablo Neira Ayuso {
98902fd97c3SHerbert Xu 	BUG_ON(!ht->p.obj_hashfn || !key);
99002fd97c3SHerbert Xu 
991ca26893fSHerbert Xu 	return __rhashtable_insert_fast(ht, key, obj, params, false);
99202fd97c3SHerbert Xu }
99302fd97c3SHerbert Xu 
994ac833bddSThomas Graf /* Internal function, please use rhashtable_remove_fast() instead */
__rhashtable_remove_fast_one(struct rhashtable * ht,struct bucket_table * tbl,struct rhash_head * obj,const struct rhashtable_params params,bool rhlist)995ca26893fSHerbert Xu static inline int __rhashtable_remove_fast_one(
99602fd97c3SHerbert Xu 	struct rhashtable *ht, struct bucket_table *tbl,
997ca26893fSHerbert Xu 	struct rhash_head *obj, const struct rhashtable_params params,
998ca26893fSHerbert Xu 	bool rhlist)
99902fd97c3SHerbert Xu {
1000ce9b362bSHerbert Xu 	struct rhash_lock_head __rcu **bkt;
100102fd97c3SHerbert Xu 	struct rhash_head __rcu **pprev;
100202fd97c3SHerbert Xu 	struct rhash_head *he;
1003*e47877c7STejun Heo 	unsigned long flags;
1004299e5c32SThomas Graf 	unsigned int hash;
100502fd97c3SHerbert Xu 	int err = -ENOENT;
100602fd97c3SHerbert Xu 
100702fd97c3SHerbert Xu 	hash = rht_head_hashfn(ht, tbl, obj, params);
10088f0db018SNeilBrown 	bkt = rht_bucket_var(tbl, hash);
10098f0db018SNeilBrown 	if (!bkt)
10108f0db018SNeilBrown 		return -ENOENT;
10118f0db018SNeilBrown 	pprev = NULL;
1012*e47877c7STejun Heo 	flags = rht_lock(tbl, bkt);
101302fd97c3SHerbert Xu 
1014adc6a3abSNeilBrown 	rht_for_each_from(he, rht_ptr(bkt, tbl, hash), tbl, hash) {
1015ca26893fSHerbert Xu 		struct rhlist_head *list;
101602fd97c3SHerbert Xu 
1017ca26893fSHerbert Xu 		list = container_of(he, struct rhlist_head, rhead);
1018ca26893fSHerbert Xu 
1019ca26893fSHerbert Xu 		if (he != obj) {
1020ca26893fSHerbert Xu 			struct rhlist_head __rcu **lpprev;
1021ca26893fSHerbert Xu 
1022ca26893fSHerbert Xu 			pprev = &he->next;
1023ca26893fSHerbert Xu 
1024ca26893fSHerbert Xu 			if (!rhlist)
1025ca26893fSHerbert Xu 				continue;
1026ca26893fSHerbert Xu 
1027ca26893fSHerbert Xu 			do {
1028ca26893fSHerbert Xu 				lpprev = &list->next;
1029ca26893fSHerbert Xu 				list = rht_dereference_bucket(list->next,
1030ca26893fSHerbert Xu 							      tbl, hash);
1031ca26893fSHerbert Xu 			} while (list && obj != &list->rhead);
1032ca26893fSHerbert Xu 
1033ca26893fSHerbert Xu 			if (!list)
1034ca26893fSHerbert Xu 				continue;
1035ca26893fSHerbert Xu 
1036ca26893fSHerbert Xu 			list = rht_dereference_bucket(list->next, tbl, hash);
1037ca26893fSHerbert Xu 			RCU_INIT_POINTER(*lpprev, list);
103802fd97c3SHerbert Xu 			err = 0;
103902fd97c3SHerbert Xu 			break;
104002fd97c3SHerbert Xu 		}
104102fd97c3SHerbert Xu 
1042ca26893fSHerbert Xu 		obj = rht_dereference_bucket(obj->next, tbl, hash);
1043ca26893fSHerbert Xu 		err = 1;
1044ca26893fSHerbert Xu 
1045ca26893fSHerbert Xu 		if (rhlist) {
1046ca26893fSHerbert Xu 			list = rht_dereference_bucket(list->next, tbl, hash);
1047ca26893fSHerbert Xu 			if (list) {
1048ca26893fSHerbert Xu 				RCU_INIT_POINTER(list->rhead.next, obj);
1049ca26893fSHerbert Xu 				obj = &list->rhead;
1050ca26893fSHerbert Xu 				err = 0;
1051ca26893fSHerbert Xu 			}
1052ca26893fSHerbert Xu 		}
1053ca26893fSHerbert Xu 
10548f0db018SNeilBrown 		if (pprev) {
1055ca26893fSHerbert Xu 			rcu_assign_pointer(*pprev, obj);
1056*e47877c7STejun Heo 			rht_unlock(tbl, bkt, flags);
10578f0db018SNeilBrown 		} else {
1058*e47877c7STejun Heo 			rht_assign_unlock(tbl, bkt, obj, flags);
10598f0db018SNeilBrown 		}
10608f0db018SNeilBrown 		goto unlocked;
1061ca26893fSHerbert Xu 	}
1062ca26893fSHerbert Xu 
1063*e47877c7STejun Heo 	rht_unlock(tbl, bkt, flags);
10648f0db018SNeilBrown unlocked:
1065ca26893fSHerbert Xu 	if (err > 0) {
1066ca26893fSHerbert Xu 		atomic_dec(&ht->nelems);
1067ca26893fSHerbert Xu 		if (unlikely(ht->p.automatic_shrinking &&
1068ca26893fSHerbert Xu 			     rht_shrink_below_30(ht, tbl)))
1069ca26893fSHerbert Xu 			schedule_work(&ht->run_work);
1070ca26893fSHerbert Xu 		err = 0;
1071ca26893fSHerbert Xu 	}
1072ca26893fSHerbert Xu 
1073ca26893fSHerbert Xu 	return err;
1074ca26893fSHerbert Xu }
1075ca26893fSHerbert Xu 
1076ca26893fSHerbert Xu /* Internal function, please use rhashtable_remove_fast() instead */
__rhashtable_remove_fast(struct rhashtable * ht,struct rhash_head * obj,const struct rhashtable_params params,bool rhlist)1077ca26893fSHerbert Xu static inline int __rhashtable_remove_fast(
1078ca26893fSHerbert Xu 	struct rhashtable *ht, struct rhash_head *obj,
1079ca26893fSHerbert Xu 	const struct rhashtable_params params, bool rhlist)
1080ca26893fSHerbert Xu {
1081ca26893fSHerbert Xu 	struct bucket_table *tbl;
1082ca26893fSHerbert Xu 	int err;
1083ca26893fSHerbert Xu 
1084ca26893fSHerbert Xu 	rcu_read_lock();
1085ca26893fSHerbert Xu 
1086ca26893fSHerbert Xu 	tbl = rht_dereference_rcu(ht->tbl, ht);
1087ca26893fSHerbert Xu 
1088ca26893fSHerbert Xu 	/* Because we have already taken (and released) the bucket
1089ca26893fSHerbert Xu 	 * lock in old_tbl, if we find that future_tbl is not yet
1090ca26893fSHerbert Xu 	 * visible then that guarantees the entry to still be in
1091ca26893fSHerbert Xu 	 * the old tbl if it exists.
1092ca26893fSHerbert Xu 	 */
1093ca26893fSHerbert Xu 	while ((err = __rhashtable_remove_fast_one(ht, tbl, obj, params,
1094ca26893fSHerbert Xu 						   rhlist)) &&
1095ca26893fSHerbert Xu 	       (tbl = rht_dereference_rcu(tbl->future_tbl, ht)))
1096ca26893fSHerbert Xu 		;
1097ca26893fSHerbert Xu 
1098ca26893fSHerbert Xu 	rcu_read_unlock();
1099ca26893fSHerbert Xu 
110002fd97c3SHerbert Xu 	return err;
110102fd97c3SHerbert Xu }
110202fd97c3SHerbert Xu 
110302fd97c3SHerbert Xu /**
110402fd97c3SHerbert Xu  * rhashtable_remove_fast - remove object from hash table
110502fd97c3SHerbert Xu  * @ht:		hash table
110602fd97c3SHerbert Xu  * @obj:	pointer to hash head inside object
110702fd97c3SHerbert Xu  * @params:	hash table parameters
110802fd97c3SHerbert Xu  *
110902fd97c3SHerbert Xu  * Since the hash chain is single linked, the removal operation needs to
111002fd97c3SHerbert Xu  * walk the bucket chain upon removal. The removal operation is thus
111102fd97c3SHerbert Xu  * considerable slow if the hash table is not correctly sized.
111202fd97c3SHerbert Xu  *
11130c6f69a5SNeilBrown  * Will automatically shrink the table if permitted when residency drops
11140c6f69a5SNeilBrown  * below 30%.
111502fd97c3SHerbert Xu  *
111602fd97c3SHerbert Xu  * Returns zero on success, -ENOENT if the entry could not be found.
111702fd97c3SHerbert Xu  */
rhashtable_remove_fast(struct rhashtable * ht,struct rhash_head * obj,const struct rhashtable_params params)111802fd97c3SHerbert Xu static inline int rhashtable_remove_fast(
111902fd97c3SHerbert Xu 	struct rhashtable *ht, struct rhash_head *obj,
112002fd97c3SHerbert Xu 	const struct rhashtable_params params)
112102fd97c3SHerbert Xu {
1122ca26893fSHerbert Xu 	return __rhashtable_remove_fast(ht, obj, params, false);
1123ca26893fSHerbert Xu }
112402fd97c3SHerbert Xu 
1125ca26893fSHerbert Xu /**
1126ca26893fSHerbert Xu  * rhltable_remove - remove object from hash list table
1127ca26893fSHerbert Xu  * @hlt:	hash list table
1128ca26893fSHerbert Xu  * @list:	pointer to hash list head inside object
1129ca26893fSHerbert Xu  * @params:	hash table parameters
1130ca26893fSHerbert Xu  *
1131ca26893fSHerbert Xu  * Since the hash chain is single linked, the removal operation needs to
1132ca26893fSHerbert Xu  * walk the bucket chain upon removal. The removal operation is thus
1133ca26893fSHerbert Xu  * considerable slow if the hash table is not correctly sized.
1134ca26893fSHerbert Xu  *
11350c6f69a5SNeilBrown  * Will automatically shrink the table if permitted when residency drops
11360c6f69a5SNeilBrown  * below 30%
1137ca26893fSHerbert Xu  *
1138ca26893fSHerbert Xu  * Returns zero on success, -ENOENT if the entry could not be found.
113902fd97c3SHerbert Xu  */
rhltable_remove(struct rhltable * hlt,struct rhlist_head * list,const struct rhashtable_params params)1140ca26893fSHerbert Xu static inline int rhltable_remove(
1141ca26893fSHerbert Xu 	struct rhltable *hlt, struct rhlist_head *list,
1142ca26893fSHerbert Xu 	const struct rhashtable_params params)
1143ca26893fSHerbert Xu {
1144ca26893fSHerbert Xu 	return __rhashtable_remove_fast(&hlt->ht, &list->rhead, params, true);
114502fd97c3SHerbert Xu }
114602fd97c3SHerbert Xu 
11473502cad7STom Herbert /* Internal function, please use rhashtable_replace_fast() instead */
__rhashtable_replace_fast(struct rhashtable * ht,struct bucket_table * tbl,struct rhash_head * obj_old,struct rhash_head * obj_new,const struct rhashtable_params params)11483502cad7STom Herbert static inline int __rhashtable_replace_fast(
11493502cad7STom Herbert 	struct rhashtable *ht, struct bucket_table *tbl,
11503502cad7STom Herbert 	struct rhash_head *obj_old, struct rhash_head *obj_new,
11513502cad7STom Herbert 	const struct rhashtable_params params)
11523502cad7STom Herbert {
1153ce9b362bSHerbert Xu 	struct rhash_lock_head __rcu **bkt;
11543502cad7STom Herbert 	struct rhash_head __rcu **pprev;
11553502cad7STom Herbert 	struct rhash_head *he;
1156*e47877c7STejun Heo 	unsigned long flags;
11573502cad7STom Herbert 	unsigned int hash;
11583502cad7STom Herbert 	int err = -ENOENT;
11593502cad7STom Herbert 
11603502cad7STom Herbert 	/* Minimally, the old and new objects must have same hash
11613502cad7STom Herbert 	 * (which should mean identifiers are the same).
11623502cad7STom Herbert 	 */
11633502cad7STom Herbert 	hash = rht_head_hashfn(ht, tbl, obj_old, params);
11643502cad7STom Herbert 	if (hash != rht_head_hashfn(ht, tbl, obj_new, params))
11653502cad7STom Herbert 		return -EINVAL;
11663502cad7STom Herbert 
11678f0db018SNeilBrown 	bkt = rht_bucket_var(tbl, hash);
11688f0db018SNeilBrown 	if (!bkt)
11698f0db018SNeilBrown 		return -ENOENT;
11703502cad7STom Herbert 
11718f0db018SNeilBrown 	pprev = NULL;
1172*e47877c7STejun Heo 	flags = rht_lock(tbl, bkt);
11733502cad7STom Herbert 
1174adc6a3abSNeilBrown 	rht_for_each_from(he, rht_ptr(bkt, tbl, hash), tbl, hash) {
11753502cad7STom Herbert 		if (he != obj_old) {
11763502cad7STom Herbert 			pprev = &he->next;
11773502cad7STom Herbert 			continue;
11783502cad7STom Herbert 		}
11793502cad7STom Herbert 
11803502cad7STom Herbert 		rcu_assign_pointer(obj_new->next, obj_old->next);
11818f0db018SNeilBrown 		if (pprev) {
11823502cad7STom Herbert 			rcu_assign_pointer(*pprev, obj_new);
1183*e47877c7STejun Heo 			rht_unlock(tbl, bkt, flags);
11848f0db018SNeilBrown 		} else {
1185*e47877c7STejun Heo 			rht_assign_unlock(tbl, bkt, obj_new, flags);
11863502cad7STom Herbert 		}
11878f0db018SNeilBrown 		err = 0;
11888f0db018SNeilBrown 		goto unlocked;
11898f0db018SNeilBrown 	}
11903502cad7STom Herbert 
1191*e47877c7STejun Heo 	rht_unlock(tbl, bkt, flags);
11928f0db018SNeilBrown 
11938f0db018SNeilBrown unlocked:
11943502cad7STom Herbert 	return err;
11953502cad7STom Herbert }
11963502cad7STom Herbert 
11973502cad7STom Herbert /**
11983502cad7STom Herbert  * rhashtable_replace_fast - replace an object in hash table
11993502cad7STom Herbert  * @ht:		hash table
12003502cad7STom Herbert  * @obj_old:	pointer to hash head inside object being replaced
12013502cad7STom Herbert  * @obj_new:	pointer to hash head inside object which is new
12023502cad7STom Herbert  * @params:	hash table parameters
12033502cad7STom Herbert  *
12043502cad7STom Herbert  * Replacing an object doesn't affect the number of elements in the hash table
12053502cad7STom Herbert  * or bucket, so we don't need to worry about shrinking or expanding the
12063502cad7STom Herbert  * table here.
12073502cad7STom Herbert  *
12083502cad7STom Herbert  * Returns zero on success, -ENOENT if the entry could not be found,
12093502cad7STom Herbert  * -EINVAL if hash is not the same for the old and new objects.
12103502cad7STom Herbert  */
rhashtable_replace_fast(struct rhashtable * ht,struct rhash_head * obj_old,struct rhash_head * obj_new,const struct rhashtable_params params)12113502cad7STom Herbert static inline int rhashtable_replace_fast(
12123502cad7STom Herbert 	struct rhashtable *ht, struct rhash_head *obj_old,
12133502cad7STom Herbert 	struct rhash_head *obj_new,
12143502cad7STom Herbert 	const struct rhashtable_params params)
12153502cad7STom Herbert {
12163502cad7STom Herbert 	struct bucket_table *tbl;
12173502cad7STom Herbert 	int err;
12183502cad7STom Herbert 
12193502cad7STom Herbert 	rcu_read_lock();
12203502cad7STom Herbert 
12213502cad7STom Herbert 	tbl = rht_dereference_rcu(ht->tbl, ht);
12223502cad7STom Herbert 
12233502cad7STom Herbert 	/* Because we have already taken (and released) the bucket
12243502cad7STom Herbert 	 * lock in old_tbl, if we find that future_tbl is not yet
12253502cad7STom Herbert 	 * visible then that guarantees the entry to still be in
12263502cad7STom Herbert 	 * the old tbl if it exists.
12273502cad7STom Herbert 	 */
12283502cad7STom Herbert 	while ((err = __rhashtable_replace_fast(ht, tbl, obj_old,
12293502cad7STom Herbert 						obj_new, params)) &&
12303502cad7STom Herbert 	       (tbl = rht_dereference_rcu(tbl->future_tbl, ht)))
12313502cad7STom Herbert 		;
12323502cad7STom Herbert 
12333502cad7STom Herbert 	rcu_read_unlock();
12343502cad7STom Herbert 
12353502cad7STom Herbert 	return err;
12363502cad7STom Herbert }
12373502cad7STom Herbert 
1238ca26893fSHerbert Xu /**
1239ca26893fSHerbert Xu  * rhltable_walk_enter - Initialise an iterator
1240ca26893fSHerbert Xu  * @hlt:	Table to walk over
1241ca26893fSHerbert Xu  * @iter:	Hash table Iterator
1242ca26893fSHerbert Xu  *
1243ca26893fSHerbert Xu  * This function prepares a hash table walk.
1244ca26893fSHerbert Xu  *
1245ca26893fSHerbert Xu  * Note that if you restart a walk after rhashtable_walk_stop you
1246ca26893fSHerbert Xu  * may see the same object twice.  Also, you may miss objects if
1247ca26893fSHerbert Xu  * there are removals in between rhashtable_walk_stop and the next
1248ca26893fSHerbert Xu  * call to rhashtable_walk_start.
1249ca26893fSHerbert Xu  *
1250ca26893fSHerbert Xu  * For a completely stable walk you should construct your own data
1251ca26893fSHerbert Xu  * structure outside the hash table.
1252ca26893fSHerbert Xu  *
125382266e98SNeilBrown  * This function may be called from any process context, including
125482266e98SNeilBrown  * non-preemptable context, but cannot be called from softirq or
125582266e98SNeilBrown  * hardirq context.
1256ca26893fSHerbert Xu  *
1257ca26893fSHerbert Xu  * You must call rhashtable_walk_exit after this function returns.
1258ca26893fSHerbert Xu  */
rhltable_walk_enter(struct rhltable * hlt,struct rhashtable_iter * iter)1259ca26893fSHerbert Xu static inline void rhltable_walk_enter(struct rhltable *hlt,
1260ca26893fSHerbert Xu 				       struct rhashtable_iter *iter)
1261ca26893fSHerbert Xu {
1262ca26893fSHerbert Xu 	return rhashtable_walk_enter(&hlt->ht, iter);
1263ca26893fSHerbert Xu }
1264ca26893fSHerbert Xu 
1265ca26893fSHerbert Xu /**
1266ca26893fSHerbert Xu  * rhltable_free_and_destroy - free elements and destroy hash list table
1267ca26893fSHerbert Xu  * @hlt:	the hash list table to destroy
1268ca26893fSHerbert Xu  * @free_fn:	callback to release resources of element
1269ca26893fSHerbert Xu  * @arg:	pointer passed to free_fn
1270ca26893fSHerbert Xu  *
1271ca26893fSHerbert Xu  * See documentation for rhashtable_free_and_destroy.
1272ca26893fSHerbert Xu  */
rhltable_free_and_destroy(struct rhltable * hlt,void (* free_fn)(void * ptr,void * arg),void * arg)1273ca26893fSHerbert Xu static inline void rhltable_free_and_destroy(struct rhltable *hlt,
1274ca26893fSHerbert Xu 					     void (*free_fn)(void *ptr,
1275ca26893fSHerbert Xu 							     void *arg),
1276ca26893fSHerbert Xu 					     void *arg)
1277ca26893fSHerbert Xu {
1278ca26893fSHerbert Xu 	return rhashtable_free_and_destroy(&hlt->ht, free_fn, arg);
1279ca26893fSHerbert Xu }
1280ca26893fSHerbert Xu 
rhltable_destroy(struct rhltable * hlt)1281ca26893fSHerbert Xu static inline void rhltable_destroy(struct rhltable *hlt)
1282ca26893fSHerbert Xu {
1283ca26893fSHerbert Xu 	return rhltable_free_and_destroy(hlt, NULL, NULL);
1284ca26893fSHerbert Xu }
1285ca26893fSHerbert Xu 
12867e1e7763SThomas Graf #endif /* _LINUX_RHASHTABLE_H */
1287