aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/rhashtable.h
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2015-03-23 09:50:21 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-23 22:07:51 -0400
commit31ccde2dacea8375c3a7d6fffbf0060ee0d40214 (patch)
tree82c65efdd9369d9793996e568ada542ab54bc3c7 /include/linux/rhashtable.h
parentde91b25c8011089f5dd99b9d24743db1f550ca4b (diff)
rhashtable: Allow hashfn to be unset
Since every current rhashtable user uses jhash as their hash function, the fact that jhash is an inline function causes each user to generate a copy of its code. This function provides a solution to this problem by allowing hashfn to be unset. In which case rhashtable will automatically set it to jhash. Furthermore, if the key length is a multiple of 4, we will switch over to jhash2. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Acked-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/rhashtable.h')
-rw-r--r--include/linux/rhashtable.h33
1 files changed, 27 insertions, 6 deletions
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 3851952781d7..bc2488b98321 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -19,6 +19,7 @@
19 19
20#include <linux/compiler.h> 20#include <linux/compiler.h>
21#include <linux/errno.h> 21#include <linux/errno.h>
22#include <linux/jhash.h>
22#include <linux/list_nulls.h> 23#include <linux/list_nulls.h>
23#include <linux/workqueue.h> 24#include <linux/workqueue.h>
24#include <linux/mutex.h> 25#include <linux/mutex.h>
@@ -103,7 +104,7 @@ struct rhashtable;
103 * @min_size: Minimum size while shrinking 104 * @min_size: Minimum size while shrinking
104 * @nulls_base: Base value to generate nulls marker 105 * @nulls_base: Base value to generate nulls marker
105 * @locks_mul: Number of bucket locks to allocate per cpu (default: 128) 106 * @locks_mul: Number of bucket locks to allocate per cpu (default: 128)
106 * @hashfn: Function to hash key 107 * @hashfn: Hash function (default: jhash2 if !(key_len % 4), or jhash)
107 * @obj_hashfn: Function to hash object 108 * @obj_hashfn: Function to hash object
108 * @obj_cmpfn: Function to compare key with object 109 * @obj_cmpfn: Function to compare key with object
109 */ 110 */
@@ -125,6 +126,7 @@ struct rhashtable_params {
125 * struct rhashtable - Hash table handle 126 * struct rhashtable - Hash table handle
126 * @tbl: Bucket table 127 * @tbl: Bucket table
127 * @nelems: Number of elements in table 128 * @nelems: Number of elements in table
129 * @key_len: Key length for hashfn
128 * @p: Configuration parameters 130 * @p: Configuration parameters
129 * @run_work: Deferred worker to expand/shrink asynchronously 131 * @run_work: Deferred worker to expand/shrink asynchronously
130 * @mutex: Mutex to protect current/future table swapping 132 * @mutex: Mutex to protect current/future table swapping
@@ -134,6 +136,7 @@ struct rhashtable {
134 struct bucket_table __rcu *tbl; 136 struct bucket_table __rcu *tbl;
135 atomic_t nelems; 137 atomic_t nelems;
136 bool being_destroyed; 138 bool being_destroyed;
139 unsigned int key_len;
137 struct rhashtable_params p; 140 struct rhashtable_params p;
138 struct work_struct run_work; 141 struct work_struct run_work;
139 struct mutex mutex; 142 struct mutex mutex;
@@ -199,13 +202,31 @@ static inline unsigned int rht_key_hashfn(
199 struct rhashtable *ht, const struct bucket_table *tbl, 202 struct rhashtable *ht, const struct bucket_table *tbl,
200 const void *key, const struct rhashtable_params params) 203 const void *key, const struct rhashtable_params params)
201{ 204{
205 unsigned hash;
206
202 /* params must be equal to ht->p if it isn't constant. */ 207 /* params must be equal to ht->p if it isn't constant. */
203 unsigned key_len = __builtin_constant_p(params.key_len) ? 208 if (!__builtin_constant_p(params.key_len))
204 (params.key_len ?: ht->p.key_len) : 209 hash = ht->p.hashfn(key, ht->key_len, tbl->hash_rnd);
205 params.key_len; 210 else if (params.key_len) {
211 unsigned key_len = params.key_len;
212
213 if (params.hashfn)
214 hash = params.hashfn(key, key_len, tbl->hash_rnd);
215 else if (key_len & (sizeof(u32) - 1))
216 hash = jhash(key, key_len, tbl->hash_rnd);
217 else
218 hash = jhash2(key, key_len / sizeof(u32),
219 tbl->hash_rnd);
220 } else {
221 unsigned key_len = ht->p.key_len;
222
223 if (params.hashfn)
224 hash = params.hashfn(key, key_len, tbl->hash_rnd);
225 else
226 hash = jhash(key, key_len, tbl->hash_rnd);
227 }
206 228
207 return rht_bucket_index(tbl, params.hashfn(key, key_len, 229 return rht_bucket_index(tbl, hash);
208 tbl->hash_rnd));
209} 230}
210 231
211static inline unsigned int rht_head_hashfn( 232static inline unsigned int rht_head_hashfn(