rhashtable: remove nulls_base and related code.
This "feature" is unused, undocumented, and untested and so doesn't really belong. A patch is under development to properly implement support for detecting when a search gets diverted down a different chain, which the common purpose of nulls markers. This patch actually fixes a bug too. The table resizing allows a table to grow to 2^31 buckets, but the hash is truncated to 27 bits - any growth beyond 2^27 is wasteful an ineffective. This patch results in NULLS_MARKER(0) being used for all chains, and leaves the use of rht_is_a_null() to test for it. Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: NeilBrown <neilb@suse.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0eb71a9da5
commit
9f9a707738
5 changed files with 6 additions and 46 deletions
|
@ -50,7 +50,6 @@ typedef int (*rht_obj_cmpfn_t)(struct rhashtable_compare_arg *arg,
|
||||||
* @min_size: Minimum size while shrinking
|
* @min_size: Minimum size while shrinking
|
||||||
* @locks_mul: Number of bucket locks to allocate per cpu (default: 32)
|
* @locks_mul: Number of bucket locks to allocate per cpu (default: 32)
|
||||||
* @automatic_shrinking: Enable automatic shrinking of tables
|
* @automatic_shrinking: Enable automatic shrinking of tables
|
||||||
* @nulls_base: Base value to generate nulls marker
|
|
||||||
* @hashfn: Hash function (default: jhash2 if !(key_len % 4), or jhash)
|
* @hashfn: Hash function (default: jhash2 if !(key_len % 4), or jhash)
|
||||||
* @obj_hashfn: Function to hash object
|
* @obj_hashfn: Function to hash object
|
||||||
* @obj_cmpfn: Function to compare key with object
|
* @obj_cmpfn: Function to compare key with object
|
||||||
|
@ -64,7 +63,6 @@ struct rhashtable_params {
|
||||||
u16 min_size;
|
u16 min_size;
|
||||||
bool automatic_shrinking;
|
bool automatic_shrinking;
|
||||||
u8 locks_mul;
|
u8 locks_mul;
|
||||||
u32 nulls_base;
|
|
||||||
rht_hashfn_t hashfn;
|
rht_hashfn_t hashfn;
|
||||||
rht_obj_hashfn_t obj_hashfn;
|
rht_obj_hashfn_t obj_hashfn;
|
||||||
rht_obj_cmpfn_t obj_cmpfn;
|
rht_obj_cmpfn_t obj_cmpfn;
|
||||||
|
|
|
@ -28,25 +28,8 @@
|
||||||
#include <linux/rhashtable-types.h>
|
#include <linux/rhashtable-types.h>
|
||||||
/*
|
/*
|
||||||
* The end of the chain is marked with a special nulls marks which has
|
* The end of the chain is marked with a special nulls marks which has
|
||||||
* the following format:
|
* the least significant bit set.
|
||||||
*
|
|
||||||
* +-------+-----------------------------------------------------+-+
|
|
||||||
* | Base | Hash |1|
|
|
||||||
* +-------+-----------------------------------------------------+-+
|
|
||||||
*
|
|
||||||
* Base (4 bits) : Reserved to distinguish between multiple tables.
|
|
||||||
* Specified via &struct rhashtable_params.nulls_base.
|
|
||||||
* Hash (27 bits): Full hash (unmasked) of first element added to bucket
|
|
||||||
* 1 (1 bit) : Nulls marker (always set)
|
|
||||||
*
|
|
||||||
* The remaining bits of the next pointer remain unused for now.
|
|
||||||
*/
|
*/
|
||||||
#define RHT_BASE_BITS 4
|
|
||||||
#define RHT_HASH_BITS 27
|
|
||||||
#define RHT_BASE_SHIFT RHT_HASH_BITS
|
|
||||||
|
|
||||||
/* Base bits plus 1 bit for nulls marker */
|
|
||||||
#define RHT_HASH_RESERVED_SPACE (RHT_BASE_BITS + 1)
|
|
||||||
|
|
||||||
/* Maximum chain length before rehash
|
/* Maximum chain length before rehash
|
||||||
*
|
*
|
||||||
|
@ -92,24 +75,14 @@ struct bucket_table {
|
||||||
struct rhash_head __rcu *buckets[] ____cacheline_aligned_in_smp;
|
struct rhash_head __rcu *buckets[] ____cacheline_aligned_in_smp;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline unsigned long rht_marker(const struct rhashtable *ht, u32 hash)
|
|
||||||
{
|
|
||||||
return NULLS_MARKER(ht->p.nulls_base + hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define INIT_RHT_NULLS_HEAD(ptr, ht, hash) \
|
#define INIT_RHT_NULLS_HEAD(ptr, ht, hash) \
|
||||||
((ptr) = (typeof(ptr)) rht_marker(ht, hash))
|
((ptr) = (typeof(ptr)) NULLS_MARKER(0))
|
||||||
|
|
||||||
static inline bool rht_is_a_nulls(const struct rhash_head *ptr)
|
static inline bool rht_is_a_nulls(const struct rhash_head *ptr)
|
||||||
{
|
{
|
||||||
return ((unsigned long) ptr & 1);
|
return ((unsigned long) ptr & 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long rht_get_nulls_value(const struct rhash_head *ptr)
|
|
||||||
{
|
|
||||||
return ((unsigned long) ptr) >> 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void *rht_obj(const struct rhashtable *ht,
|
static inline void *rht_obj(const struct rhashtable *ht,
|
||||||
const struct rhash_head *he)
|
const struct rhash_head *he)
|
||||||
{
|
{
|
||||||
|
@ -119,7 +92,7 @@ static inline void *rht_obj(const struct rhashtable *ht,
|
||||||
static inline unsigned int rht_bucket_index(const struct bucket_table *tbl,
|
static inline unsigned int rht_bucket_index(const struct bucket_table *tbl,
|
||||||
unsigned int hash)
|
unsigned int hash)
|
||||||
{
|
{
|
||||||
return (hash >> RHT_HASH_RESERVED_SPACE) & (tbl->size - 1);
|
return hash & (tbl->size - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int rht_key_get_hash(struct rhashtable *ht,
|
static inline unsigned int rht_key_get_hash(struct rhashtable *ht,
|
||||||
|
|
|
@ -995,7 +995,6 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
|
||||||
* .key_offset = offsetof(struct test_obj, key),
|
* .key_offset = offsetof(struct test_obj, key),
|
||||||
* .key_len = sizeof(int),
|
* .key_len = sizeof(int),
|
||||||
* .hashfn = jhash,
|
* .hashfn = jhash,
|
||||||
* .nulls_base = (1U << RHT_BASE_SHIFT),
|
|
||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
* Configuration Example 2: Variable length keys
|
* Configuration Example 2: Variable length keys
|
||||||
|
@ -1029,9 +1028,6 @@ int rhashtable_init(struct rhashtable *ht,
|
||||||
(params->obj_hashfn && !params->obj_cmpfn))
|
(params->obj_hashfn && !params->obj_cmpfn))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (params->nulls_base && params->nulls_base < (1U << RHT_BASE_SHIFT))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
memset(ht, 0, sizeof(*ht));
|
memset(ht, 0, sizeof(*ht));
|
||||||
mutex_init(&ht->mutex);
|
mutex_init(&ht->mutex);
|
||||||
spin_lock_init(&ht->lock);
|
spin_lock_init(&ht->lock);
|
||||||
|
@ -1096,10 +1092,6 @@ int rhltable_init(struct rhltable *hlt, const struct rhashtable_params *params)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* No rhlist NULLs marking for now. */
|
|
||||||
if (params->nulls_base)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
err = rhashtable_init(&hlt->ht, params);
|
err = rhashtable_init(&hlt->ht, params);
|
||||||
hlt->ht.rhlist = true;
|
hlt->ht.rhlist = true;
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -83,7 +83,7 @@ static u32 my_hashfn(const void *data, u32 len, u32 seed)
|
||||||
{
|
{
|
||||||
const struct test_obj_rhl *obj = data;
|
const struct test_obj_rhl *obj = data;
|
||||||
|
|
||||||
return (obj->value.id % 10) << RHT_HASH_RESERVED_SPACE;
|
return (obj->value.id % 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int my_cmpfn(struct rhashtable_compare_arg *arg, const void *obj)
|
static int my_cmpfn(struct rhashtable_compare_arg *arg, const void *obj)
|
||||||
|
@ -99,7 +99,6 @@ static struct rhashtable_params test_rht_params = {
|
||||||
.key_offset = offsetof(struct test_obj, value),
|
.key_offset = offsetof(struct test_obj, value),
|
||||||
.key_len = sizeof(struct test_obj_val),
|
.key_len = sizeof(struct test_obj_val),
|
||||||
.hashfn = jhash,
|
.hashfn = jhash,
|
||||||
.nulls_base = (3U << RHT_BASE_SHIFT),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct rhashtable_params test_rht_params_dup = {
|
static struct rhashtable_params test_rht_params_dup = {
|
||||||
|
@ -296,8 +295,6 @@ static int __init test_rhltable(unsigned int entries)
|
||||||
if (!obj_in_table)
|
if (!obj_in_table)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
/* nulls_base not supported in rhlist interface */
|
|
||||||
test_rht_params.nulls_base = 0;
|
|
||||||
err = rhltable_init(&rhlt, &test_rht_params);
|
err = rhltable_init(&rhlt, &test_rht_params);
|
||||||
if (WARN_ON(err))
|
if (WARN_ON(err))
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
|
@ -45,8 +45,8 @@ static u32 xdp_mem_id_hashfn(const void *data, u32 len, u32 seed)
|
||||||
BUILD_BUG_ON(FIELD_SIZEOF(struct xdp_mem_allocator, mem.id)
|
BUILD_BUG_ON(FIELD_SIZEOF(struct xdp_mem_allocator, mem.id)
|
||||||
!= sizeof(u32));
|
!= sizeof(u32));
|
||||||
|
|
||||||
/* Use cyclic increasing ID as direct hash key, see rht_bucket_index */
|
/* Use cyclic increasing ID as direct hash key */
|
||||||
return key << RHT_HASH_RESERVED_SPACE;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xdp_mem_id_cmp(struct rhashtable_compare_arg *arg,
|
static int xdp_mem_id_cmp(struct rhashtable_compare_arg *arg,
|
||||||
|
|
Loading…
Reference in a new issue