aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2015-01-02 17:00:14 -0500
committerDavid S. Miller <davem@davemloft.net>2015-01-03 14:32:56 -0500
commit8d24c0b43125ec26cc80e04588477a9a2afc025c (patch)
treed02e1b74bf49017dd4fecdeaf82a1e4f8f64a25d /lib
parentdd9553988879a3ff71a86323b88409e7631c4e5d (diff)
rhashtable: Do hashing inside of rhashtable_lookup_compare()
Hash the key inside of rhashtable_lookup_compare() like rhashtable_lookup() does. This allows to simplify the hashing functions and keep them private. Signed-off-by: Thomas Graf <tgraf@suug.ch> Cc: netfilter-devel@vger.kernel.org Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'lib')
-rw-r--r--lib/rhashtable.c91
1 files changed, 30 insertions, 61 deletions
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 6c3c723e902b..1ee0eb636ca3 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -42,69 +42,39 @@ static void *rht_obj(const struct rhashtable *ht, const struct rhash_head *he)
42 return (void *) he - ht->p.head_offset; 42 return (void *) he - ht->p.head_offset;
43} 43}
44 44
45static u32 __hashfn(const struct rhashtable *ht, const void *key, 45static u32 rht_bucket_index(const struct bucket_table *tbl, u32 hash)
46 u32 len, u32 hsize)
47{ 46{
48 u32 h; 47 return hash & (tbl->size - 1);
49
50 h = ht->p.hashfn(key, len, ht->p.hash_rnd);
51
52 return h & (hsize - 1);
53}
54
55/**
56 * rhashtable_hashfn - compute hash for key of given length
57 * @ht: hash table to compute for
58 * @key: pointer to key
59 * @len: length of key
60 *
61 * Computes the hash value using the hash function provided in the 'hashfn'
62 * of struct rhashtable_params. The returned value is guaranteed to be
63 * smaller than the number of buckets in the hash table.
64 */
65u32 rhashtable_hashfn(const struct rhashtable *ht, const void *key, u32 len)
66{
67 struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht);
68
69 return __hashfn(ht, key, len, tbl->size);
70} 48}
71EXPORT_SYMBOL_GPL(rhashtable_hashfn);
72 49
73static u32 obj_hashfn(const struct rhashtable *ht, const void *ptr, u32 hsize) 50static u32 obj_raw_hashfn(const struct rhashtable *ht, const void *ptr)
74{ 51{
75 if (unlikely(!ht->p.key_len)) { 52 u32 hash;
76 u32 h;
77
78 h = ht->p.obj_hashfn(ptr, ht->p.hash_rnd);
79 53
80 return h & (hsize - 1); 54 if (unlikely(!ht->p.key_len))
81 } 55 hash = ht->p.obj_hashfn(ptr, ht->p.hash_rnd);
56 else
57 hash = ht->p.hashfn(ptr + ht->p.key_offset, ht->p.key_len,
58 ht->p.hash_rnd);
82 59
83 return __hashfn(ht, ptr + ht->p.key_offset, ht->p.key_len, hsize); 60 return hash;
84} 61}
85 62
86/** 63static u32 key_hashfn(const struct rhashtable *ht, const void *key, u32 len)
87 * rhashtable_obj_hashfn - compute hash for hashed object
88 * @ht: hash table to compute for
89 * @ptr: pointer to hashed object
90 *
91 * Computes the hash value using the hash function `hashfn` respectively
92 * 'obj_hashfn' depending on whether the hash table is set up to work with
93 * a fixed length key. The returned value is guaranteed to be smaller than
94 * the number of buckets in the hash table.
95 */
96u32 rhashtable_obj_hashfn(const struct rhashtable *ht, void *ptr)
97{ 64{
98 struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht); 65 struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht);
66 u32 hash;
67
68 hash = ht->p.hashfn(key, len, ht->p.hash_rnd);
99 69
100 return obj_hashfn(ht, ptr, tbl->size); 70 return rht_bucket_index(tbl, hash);
101} 71}
102EXPORT_SYMBOL_GPL(rhashtable_obj_hashfn);
103 72
104static u32 head_hashfn(const struct rhashtable *ht, 73static u32 head_hashfn(const struct rhashtable *ht,
105 const struct rhash_head *he, u32 hsize) 74 const struct bucket_table *tbl,
75 const struct rhash_head *he)
106{ 76{
107 return obj_hashfn(ht, rht_obj(ht, he), hsize); 77 return rht_bucket_index(tbl, obj_raw_hashfn(ht, rht_obj(ht, he)));
108} 78}
109 79
110static struct bucket_table *bucket_table_alloc(size_t nbuckets) 80static struct bucket_table *bucket_table_alloc(size_t nbuckets)
@@ -170,9 +140,9 @@ static void hashtable_chain_unzip(const struct rhashtable *ht,
170 * reaches a node that doesn't hash to the same bucket as the 140 * reaches a node that doesn't hash to the same bucket as the
171 * previous node p. Call the previous node p; 141 * previous node p. Call the previous node p;
172 */ 142 */
173 h = head_hashfn(ht, p, new_tbl->size); 143 h = head_hashfn(ht, new_tbl, p);
174 rht_for_each(he, p->next, ht) { 144 rht_for_each(he, p->next, ht) {
175 if (head_hashfn(ht, he, new_tbl->size) != h) 145 if (head_hashfn(ht, new_tbl, he) != h)
176 break; 146 break;
177 p = he; 147 p = he;
178 } 148 }
@@ -184,7 +154,7 @@ static void hashtable_chain_unzip(const struct rhashtable *ht,
184 next = NULL; 154 next = NULL;
185 if (he) { 155 if (he) {
186 rht_for_each(he, he->next, ht) { 156 rht_for_each(he, he->next, ht) {
187 if (head_hashfn(ht, he, new_tbl->size) == h) { 157 if (head_hashfn(ht, new_tbl, he) == h) {
188 next = he; 158 next = he;
189 break; 159 break;
190 } 160 }
@@ -237,9 +207,9 @@ int rhashtable_expand(struct rhashtable *ht)
237 * single imprecise chain. 207 * single imprecise chain.
238 */ 208 */
239 for (i = 0; i < new_tbl->size; i++) { 209 for (i = 0; i < new_tbl->size; i++) {
240 h = i & (old_tbl->size - 1); 210 h = rht_bucket_index(old_tbl, i);
241 rht_for_each(he, old_tbl->buckets[h], ht) { 211 rht_for_each(he, old_tbl->buckets[h], ht) {
242 if (head_hashfn(ht, he, new_tbl->size) == i) { 212 if (head_hashfn(ht, new_tbl, he) == i) {
243 RCU_INIT_POINTER(new_tbl->buckets[i], he); 213 RCU_INIT_POINTER(new_tbl->buckets[i], he);
244 break; 214 break;
245 } 215 }
@@ -353,7 +323,7 @@ void rhashtable_insert(struct rhashtable *ht, struct rhash_head *obj)
353 323
354 ASSERT_RHT_MUTEX(ht); 324 ASSERT_RHT_MUTEX(ht);
355 325
356 hash = head_hashfn(ht, obj, tbl->size); 326 hash = head_hashfn(ht, tbl, obj);
357 RCU_INIT_POINTER(obj->next, tbl->buckets[hash]); 327 RCU_INIT_POINTER(obj->next, tbl->buckets[hash]);
358 rcu_assign_pointer(tbl->buckets[hash], obj); 328 rcu_assign_pointer(tbl->buckets[hash], obj);
359 ht->nelems++; 329 ht->nelems++;
@@ -413,7 +383,7 @@ bool rhashtable_remove(struct rhashtable *ht, struct rhash_head *obj)
413 383
414 ASSERT_RHT_MUTEX(ht); 384 ASSERT_RHT_MUTEX(ht);
415 385
416 h = head_hashfn(ht, obj, tbl->size); 386 h = head_hashfn(ht, tbl, obj);
417 387
418 pprev = &tbl->buckets[h]; 388 pprev = &tbl->buckets[h];
419 rht_for_each(he, tbl->buckets[h], ht) { 389 rht_for_each(he, tbl->buckets[h], ht) {
@@ -452,7 +422,7 @@ void *rhashtable_lookup(const struct rhashtable *ht, const void *key)
452 422
453 BUG_ON(!ht->p.key_len); 423 BUG_ON(!ht->p.key_len);
454 424
455 h = __hashfn(ht, key, ht->p.key_len, tbl->size); 425 h = key_hashfn(ht, key, ht->p.key_len);
456 rht_for_each_rcu(he, tbl->buckets[h], ht) { 426 rht_for_each_rcu(he, tbl->buckets[h], ht) {
457 if (memcmp(rht_obj(ht, he) + ht->p.key_offset, key, 427 if (memcmp(rht_obj(ht, he) + ht->p.key_offset, key,
458 ht->p.key_len)) 428 ht->p.key_len))
@@ -467,7 +437,7 @@ EXPORT_SYMBOL_GPL(rhashtable_lookup);
467/** 437/**
468 * rhashtable_lookup_compare - search hash table with compare function 438 * rhashtable_lookup_compare - search hash table with compare function
469 * @ht: hash table 439 * @ht: hash table
470 * @hash: hash value of desired entry 440 * @key: the pointer to the key
471 * @compare: compare function, must return true on match 441 * @compare: compare function, must return true on match
472 * @arg: argument passed on to compare function 442 * @arg: argument passed on to compare function
473 * 443 *
@@ -479,15 +449,14 @@ EXPORT_SYMBOL_GPL(rhashtable_lookup);
479 * 449 *
480 * Returns the first entry on which the compare function returned true. 450 * Returns the first entry on which the compare function returned true.
481 */ 451 */
482void *rhashtable_lookup_compare(const struct rhashtable *ht, u32 hash, 452void *rhashtable_lookup_compare(const struct rhashtable *ht, const void *key,
483 bool (*compare)(void *, void *), void *arg) 453 bool (*compare)(void *, void *), void *arg)
484{ 454{
485 const struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht); 455 const struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht);
486 struct rhash_head *he; 456 struct rhash_head *he;
457 u32 hash;
487 458
488 if (unlikely(hash >= tbl->size)) 459 hash = key_hashfn(ht, key, ht->p.key_len);
489 return NULL;
490
491 rht_for_each_rcu(he, tbl->buckets[hash], ht) { 460 rht_for_each_rcu(he, tbl->buckets[hash], ht) {
492 if (!compare(rht_obj(ht, he), arg)) 461 if (!compare(rht_obj(ht, he), arg))
493 continue; 462 continue;