rhashtable.c (18093d1c0d1e032142ee24825678b0a8977d74ba) rhashtable.c (b824478b2145be78ac19e1cf44e2b9036c7a9608)
1/*
2 * Resizable, Scalable, Concurrent Hash Table
3 *
4 * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>
5 * Copyright (c) 2014-2015 Thomas Graf <tgraf@suug.ch>
6 * Copyright (c) 2008-2014 Patrick McHardy <kaber@trash.net>
7 *
8 * Code partially derived from nft_hash

--- 122 unchanged lines hidden (view full) ---

131 get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
132
133 for (i = 0; i < nbuckets; i++)
134 INIT_RHT_NULLS_HEAD(tbl->buckets[i], ht, i);
135
136 return tbl;
137}
138
1/*
2 * Resizable, Scalable, Concurrent Hash Table
3 *
4 * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>
5 * Copyright (c) 2014-2015 Thomas Graf <tgraf@suug.ch>
6 * Copyright (c) 2008-2014 Patrick McHardy <kaber@trash.net>
7 *
8 * Code partially derived from nft_hash

--- 122 unchanged lines hidden (view full) ---

131 get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
132
133 for (i = 0; i < nbuckets; i++)
134 INIT_RHT_NULLS_HEAD(tbl->buckets[i], ht, i);
135
136 return tbl;
137}
138
139static struct bucket_table *rhashtable_last_table(struct rhashtable *ht,
140 struct bucket_table *tbl)
141{
142 struct bucket_table *new_tbl;
143
144 do {
145 new_tbl = tbl;
146 tbl = rht_dereference_rcu(tbl->future_tbl, ht);
147 } while (tbl);
148
149 return new_tbl;
150}
151
139static int rhashtable_rehash_one(struct rhashtable *ht, unsigned old_hash)
140{
141 struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht);
152static int rhashtable_rehash_one(struct rhashtable *ht, unsigned old_hash)
153{
154 struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht);
142 struct bucket_table *new_tbl =
143 rht_dereference(old_tbl->future_tbl, ht) ?: old_tbl;
155 struct bucket_table *new_tbl = rhashtable_last_table(ht,
156 rht_dereference_rcu(old_tbl->future_tbl, ht));
144 struct rhash_head __rcu **pprev = &old_tbl->buckets[old_hash];
145 int err = -ENOENT;
146 struct rhash_head *head, *next, *entry;
147 spinlock_t *new_bucket_lock;
148 unsigned new_hash;
149
150 rht_for_each(entry, old_tbl, old_hash) {
151 err = 0;

--- 39 unchanged lines hidden (view full) ---

191
192 spin_lock_bh(old_bucket_lock);
193 while (!rhashtable_rehash_one(ht, old_hash))
194 ;
195 old_tbl->rehash++;
196 spin_unlock_bh(old_bucket_lock);
197}
198
157 struct rhash_head __rcu **pprev = &old_tbl->buckets[old_hash];
158 int err = -ENOENT;
159 struct rhash_head *head, *next, *entry;
160 spinlock_t *new_bucket_lock;
161 unsigned new_hash;
162
163 rht_for_each(entry, old_tbl, old_hash) {
164 err = 0;

--- 39 unchanged lines hidden (view full) ---

204
205 spin_lock_bh(old_bucket_lock);
206 while (!rhashtable_rehash_one(ht, old_hash))
207 ;
208 old_tbl->rehash++;
209 spin_unlock_bh(old_bucket_lock);
210}
211
199static void rhashtable_rehash(struct rhashtable *ht,
200 struct bucket_table *new_tbl)
212static int rhashtable_rehash_attach(struct rhashtable *ht,
213 struct bucket_table *old_tbl,
214 struct bucket_table *new_tbl)
201{
215{
202 struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht);
203 struct rhashtable_walker *walker;
204 unsigned old_hash;
216 /* Protect future_tbl using the first bucket lock. */
217 spin_lock_bh(old_tbl->locks);
205
218
219 /* Did somebody beat us to it? */
220 if (rcu_access_pointer(old_tbl->future_tbl)) {
221 spin_unlock_bh(old_tbl->locks);
222 return -EEXIST;
223 }
224
206 /* Make insertions go into the new, empty table right away. Deletions
207 * and lookups will be attempted in both tables until we synchronize.
208 */
209 rcu_assign_pointer(old_tbl->future_tbl, new_tbl);
210
211 /* Ensure the new table is visible to readers. */
212 smp_wmb();
213
225 /* Make insertions go into the new, empty table right away. Deletions
226 * and lookups will be attempted in both tables until we synchronize.
227 */
228 rcu_assign_pointer(old_tbl->future_tbl, new_tbl);
229
230 /* Ensure the new table is visible to readers. */
231 smp_wmb();
232
233 spin_unlock_bh(old_tbl->locks);
234
235 return 0;
236}
237
238static int rhashtable_rehash_table(struct rhashtable *ht)
239{
240 struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht);
241 struct bucket_table *new_tbl;
242 struct rhashtable_walker *walker;
243 unsigned old_hash;
244
245 new_tbl = rht_dereference(old_tbl->future_tbl, ht);
246 if (!new_tbl)
247 return 0;
248
214 for (old_hash = 0; old_hash < old_tbl->size; old_hash++)
215 rhashtable_rehash_chain(ht, old_hash);
216
217 /* Publish the new table pointer. */
218 rcu_assign_pointer(ht->tbl, new_tbl);
219
220 list_for_each_entry(walker, &old_tbl->walkers, list)
221 walker->tbl = NULL;
222
223 /* Wait for readers. All new readers will see the new
224 * table, and thus no references to the old table will
225 * remain.
226 */
227 call_rcu(&old_tbl->rcu, bucket_table_free_rcu);
249 for (old_hash = 0; old_hash < old_tbl->size; old_hash++)
250 rhashtable_rehash_chain(ht, old_hash);
251
252 /* Publish the new table pointer. */
253 rcu_assign_pointer(ht->tbl, new_tbl);
254
255 list_for_each_entry(walker, &old_tbl->walkers, list)
256 walker->tbl = NULL;
257
258 /* Wait for readers. All new readers will see the new
259 * table, and thus no references to the old table will
260 * remain.
261 */
262 call_rcu(&old_tbl->rcu, bucket_table_free_rcu);
263
264 return rht_dereference(new_tbl->future_tbl, ht) ? -EAGAIN : 0;
228}
229
230/**
231 * rhashtable_expand - Expand hash table while allowing concurrent lookups
232 * @ht: the hash table to expand
233 *
234 * A secondary bucket array is allocated and the hash entries are migrated.
235 *
236 * This function may only be called in a context where it is safe to call
237 * synchronize_rcu(), e.g. not within a rcu_read_lock() section.
238 *
239 * The caller must ensure that no concurrent resizing occurs by holding
240 * ht->mutex.
241 *
242 * It is valid to have concurrent insertions and deletions protected by per
243 * bucket locks or concurrent RCU protected lookups and traversals.
244 */
265}
266
267/**
268 * rhashtable_expand - Expand hash table while allowing concurrent lookups
269 * @ht: the hash table to expand
270 *
271 * A secondary bucket array is allocated and the hash entries are migrated.
272 *
273 * This function may only be called in a context where it is safe to call
274 * synchronize_rcu(), e.g. not within a rcu_read_lock() section.
275 *
276 * The caller must ensure that no concurrent resizing occurs by holding
277 * ht->mutex.
278 *
279 * It is valid to have concurrent insertions and deletions protected by per
280 * bucket locks or concurrent RCU protected lookups and traversals.
281 */
245int rhashtable_expand(struct rhashtable *ht)
282static int rhashtable_expand(struct rhashtable *ht)
246{
247 struct bucket_table *new_tbl, *old_tbl = rht_dereference(ht->tbl, ht);
283{
284 struct bucket_table *new_tbl, *old_tbl = rht_dereference(ht->tbl, ht);
285 int err;
248
249 ASSERT_RHT_MUTEX(ht);
250
286
287 ASSERT_RHT_MUTEX(ht);
288
289 old_tbl = rhashtable_last_table(ht, old_tbl);
290
251 new_tbl = bucket_table_alloc(ht, old_tbl->size * 2);
252 if (new_tbl == NULL)
253 return -ENOMEM;
254
291 new_tbl = bucket_table_alloc(ht, old_tbl->size * 2);
292 if (new_tbl == NULL)
293 return -ENOMEM;
294
255 rhashtable_rehash(ht, new_tbl);
256 return 0;
295 err = rhashtable_rehash_attach(ht, old_tbl, new_tbl);
296 if (err)
297 bucket_table_free(new_tbl);
298
299 return err;
257}
300}
258EXPORT_SYMBOL_GPL(rhashtable_expand);
259
260/**
261 * rhashtable_shrink - Shrink hash table while allowing concurrent lookups
262 * @ht: the hash table to shrink
263 *
264 * This function shrinks the hash table to fit, i.e., the smallest
265 * size would not cause it to expand right away automatically.
266 *
267 * The caller must ensure that no concurrent resizing occurs by holding
268 * ht->mutex.
269 *
270 * The caller must ensure that no concurrent table mutations take place.
271 * It is however valid to have concurrent lookups if they are RCU protected.
272 *
273 * It is valid to have concurrent insertions and deletions protected by per
274 * bucket locks or concurrent RCU protected lookups and traversals.
275 */
301
302/**
303 * rhashtable_shrink - Shrink hash table while allowing concurrent lookups
304 * @ht: the hash table to shrink
305 *
306 * This function shrinks the hash table to fit, i.e., the smallest
307 * size would not cause it to expand right away automatically.
308 *
309 * The caller must ensure that no concurrent resizing occurs by holding
310 * ht->mutex.
311 *
312 * The caller must ensure that no concurrent table mutations take place.
313 * It is however valid to have concurrent lookups if they are RCU protected.
314 *
315 * It is valid to have concurrent insertions and deletions protected by per
316 * bucket locks or concurrent RCU protected lookups and traversals.
317 */
276int rhashtable_shrink(struct rhashtable *ht)
318static int rhashtable_shrink(struct rhashtable *ht)
277{
278 struct bucket_table *new_tbl, *old_tbl = rht_dereference(ht->tbl, ht);
279 unsigned size = roundup_pow_of_two(atomic_read(&ht->nelems) * 3 / 2);
319{
320 struct bucket_table *new_tbl, *old_tbl = rht_dereference(ht->tbl, ht);
321 unsigned size = roundup_pow_of_two(atomic_read(&ht->nelems) * 3 / 2);
322 int err;
280
281 ASSERT_RHT_MUTEX(ht);
282
283 if (size < ht->p.min_size)
284 size = ht->p.min_size;
285
286 if (old_tbl->size <= size)
287 return 0;
288
323
324 ASSERT_RHT_MUTEX(ht);
325
326 if (size < ht->p.min_size)
327 size = ht->p.min_size;
328
329 if (old_tbl->size <= size)
330 return 0;
331
332 if (rht_dereference(old_tbl->future_tbl, ht))
333 return -EEXIST;
334
289 new_tbl = bucket_table_alloc(ht, size);
290 if (new_tbl == NULL)
291 return -ENOMEM;
292
335 new_tbl = bucket_table_alloc(ht, size);
336 if (new_tbl == NULL)
337 return -ENOMEM;
338
293 rhashtable_rehash(ht, new_tbl);
294 return 0;
339 err = rhashtable_rehash_attach(ht, old_tbl, new_tbl);
340 if (err)
341 bucket_table_free(new_tbl);
342
343 return err;
295}
344}
296EXPORT_SYMBOL_GPL(rhashtable_shrink);
297
298static void rht_deferred_worker(struct work_struct *work)
299{
300 struct rhashtable *ht;
301 struct bucket_table *tbl;
345
346static void rht_deferred_worker(struct work_struct *work)
347{
348 struct rhashtable *ht;
349 struct bucket_table *tbl;
350 int err = 0;
302
303 ht = container_of(work, struct rhashtable, run_work);
304 mutex_lock(&ht->mutex);
305 if (ht->being_destroyed)
306 goto unlock;
307
308 tbl = rht_dereference(ht->tbl, ht);
351
352 ht = container_of(work, struct rhashtable, run_work);
353 mutex_lock(&ht->mutex);
354 if (ht->being_destroyed)
355 goto unlock;
356
357 tbl = rht_dereference(ht->tbl, ht);
358 tbl = rhashtable_last_table(ht, tbl);
309
310 if (rht_grow_above_75(ht, tbl))
311 rhashtable_expand(ht);
312 else if (rht_shrink_below_30(ht, tbl))
313 rhashtable_shrink(ht);
359
360 if (rht_grow_above_75(ht, tbl))
361 rhashtable_expand(ht);
362 else if (rht_shrink_below_30(ht, tbl))
363 rhashtable_shrink(ht);
364
365 err = rhashtable_rehash_table(ht);
366
314unlock:
315 mutex_unlock(&ht->mutex);
367unlock:
368 mutex_unlock(&ht->mutex);
369
370 if (err)
371 schedule_work(&ht->run_work);
316}
317
318int rhashtable_insert_slow(struct rhashtable *ht, const void *key,
319 struct rhash_head *obj,
320 struct bucket_table *tbl)
321{
322 struct rhash_head *head;
323 unsigned hash;
324 int err = -EEXIST;
325
372}
373
374int rhashtable_insert_slow(struct rhashtable *ht, const void *key,
375 struct rhash_head *obj,
376 struct bucket_table *tbl)
377{
378 struct rhash_head *head;
379 unsigned hash;
380 int err = -EEXIST;
381
382 tbl = rhashtable_last_table(ht, tbl);
326 hash = head_hashfn(ht, tbl, obj);
327 spin_lock_nested(rht_bucket_lock(tbl, hash), SINGLE_DEPTH_NESTING);
328
329 if (key && rhashtable_lookup_fast(ht, key, ht->p))
330 goto exit;
331
332 err = 0;
333

--- 334 unchanged lines hidden ---
383 hash = head_hashfn(ht, tbl, obj);
384 spin_lock_nested(rht_bucket_lock(tbl, hash), SINGLE_DEPTH_NESTING);
385
386 if (key && rhashtable_lookup_fast(ht, key, ht->p))
387 goto exit;
388
389 err = 0;
390

--- 334 unchanged lines hidden ---