diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2015-03-23 09:50:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-23 22:07:51 -0400 |
commit | 31ccde2dacea8375c3a7d6fffbf0060ee0d40214 (patch) | |
tree | 82c65efdd9369d9793996e568ada542ab54bc3c7 /include/linux/rhashtable.h | |
parent | de91b25c8011089f5dd99b9d24743db1f550ca4b (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.h | 33 |
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 | ||
211 | static inline unsigned int rht_head_hashfn( | 232 | static inline unsigned int rht_head_hashfn( |