aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2015-03-10 18:43:48 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-11 16:36:21 -0400
commitaa34a6cb0478842452bac58edb50d3ef9e178c92 (patch)
treef975994728a196f38a260207fd81880b84f1409c /lib
parent988dfbd795cf08b00576c1ced4210281b2bccffc (diff)
rhashtable: Add arbitrary rehash function
This patch adds a rehash function that supports the use of any hash function for the new table. This is needed to support changing the random seed value during the lifetime of the hash table. However for now the random seed value is still constant and the rehash function is simply used to replace the existing expand/shrink functions. [ ASSERT_BUCKET_LOCK() and thus debug_dump_table() + debug_dump_buckets() are not longer used, so delete them entirely. -DaveM ] Signed-off-by: Herbert Xu <herbert.xu@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'lib')
-rw-r--r--lib/rhashtable.c506
1 files changed, 174 insertions, 332 deletions
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index ba15dceee27f..b1c19c5fb326 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -66,9 +66,9 @@ static u32 rht_bucket_index(const struct bucket_table *tbl, u32 hash)
66 return hash & (tbl->size - 1); 66 return hash & (tbl->size - 1);
67} 67}
68 68
69static u32 obj_raw_hashfn(struct rhashtable *ht, const void *ptr) 69static u32 obj_raw_hashfn(struct rhashtable *ht,
70 const struct bucket_table *tbl, const void *ptr)
70{ 71{
71 struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht);
72 u32 hash; 72 u32 hash;
73 73
74 if (unlikely(!ht->p.key_len)) 74 if (unlikely(!ht->p.key_len))
@@ -80,10 +80,9 @@ static u32 obj_raw_hashfn(struct rhashtable *ht, const void *ptr)
80 return hash >> HASH_RESERVED_SPACE; 80 return hash >> HASH_RESERVED_SPACE;
81} 81}
82 82
83static u32 key_hashfn(struct rhashtable *ht, const void *key, u32 len) 83static u32 key_hashfn(struct rhashtable *ht, const struct bucket_table *tbl,
84 const void *key, u32 len)
84{ 85{
85 struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht);
86
87 return ht->p.hashfn(key, len, tbl->hash_rnd) >> HASH_RESERVED_SPACE; 86 return ht->p.hashfn(key, len, tbl->hash_rnd) >> HASH_RESERVED_SPACE;
88} 87}
89 88
@@ -91,60 +90,11 @@ static u32 head_hashfn(struct rhashtable *ht,
91 const struct bucket_table *tbl, 90 const struct bucket_table *tbl,
92 const struct rhash_head *he) 91 const struct rhash_head *he)
93{ 92{
94 return rht_bucket_index(tbl, obj_raw_hashfn(ht, rht_obj(ht, he))); 93 return rht_bucket_index(tbl, obj_raw_hashfn(ht, tbl, rht_obj(ht, he)));
95} 94}
96 95
97#ifdef CONFIG_PROVE_LOCKING 96#ifdef CONFIG_PROVE_LOCKING
98static void debug_dump_buckets(struct rhashtable *ht,
99 const struct bucket_table *tbl)
100{
101 struct rhash_head *he;
102 unsigned int i, hash;
103
104 for (i = 0; i < tbl->size; i++) {
105 pr_warn(" [Bucket %d] ", i);
106 rht_for_each_rcu(he, tbl, i) {
107 hash = head_hashfn(ht, tbl, he);
108 pr_cont("[hash = %#x, lock = %p] ",
109 hash, bucket_lock(tbl, hash));
110 }
111 pr_cont("\n");
112 }
113
114}
115
116static void debug_dump_table(struct rhashtable *ht,
117 const struct bucket_table *tbl,
118 unsigned int hash)
119{
120 struct bucket_table *old_tbl, *future_tbl;
121
122 pr_emerg("BUG: lock for hash %#x in table %p not held\n",
123 hash, tbl);
124
125 rcu_read_lock();
126 future_tbl = rht_dereference_rcu(ht->future_tbl, ht);
127 old_tbl = rht_dereference_rcu(ht->tbl, ht);
128 if (future_tbl != old_tbl) {
129 pr_warn("Future table %p (size: %zd)\n",
130 future_tbl, future_tbl->size);
131 debug_dump_buckets(ht, future_tbl);
132 }
133
134 pr_warn("Table %p (size: %zd)\n", old_tbl, old_tbl->size);
135 debug_dump_buckets(ht, old_tbl);
136
137 rcu_read_unlock();
138}
139
140#define ASSERT_RHT_MUTEX(HT) BUG_ON(!lockdep_rht_mutex_is_held(HT)) 97#define ASSERT_RHT_MUTEX(HT) BUG_ON(!lockdep_rht_mutex_is_held(HT))
141#define ASSERT_BUCKET_LOCK(HT, TBL, HASH) \
142 do { \
143 if (unlikely(!lockdep_rht_bucket_is_held(TBL, HASH))) { \
144 debug_dump_table(HT, TBL, HASH); \
145 BUG(); \
146 } \
147 } while (0)
148 98
149int lockdep_rht_mutex_is_held(struct rhashtable *ht) 99int lockdep_rht_mutex_is_held(struct rhashtable *ht)
150{ 100{
@@ -161,22 +111,9 @@ int lockdep_rht_bucket_is_held(const struct bucket_table *tbl, u32 hash)
161EXPORT_SYMBOL_GPL(lockdep_rht_bucket_is_held); 111EXPORT_SYMBOL_GPL(lockdep_rht_bucket_is_held);
162#else 112#else
163#define ASSERT_RHT_MUTEX(HT) 113#define ASSERT_RHT_MUTEX(HT)
164#define ASSERT_BUCKET_LOCK(HT, TBL, HASH)
165#endif 114#endif
166 115
167 116
168static struct rhash_head __rcu **bucket_tail(struct bucket_table *tbl, u32 n)
169{
170 struct rhash_head __rcu **pprev;
171
172 for (pprev = &tbl->buckets[n];
173 !rht_is_a_nulls(rht_dereference_bucket(*pprev, tbl, n));
174 pprev = &rht_dereference_bucket(*pprev, tbl, n)->next)
175 ;
176
177 return pprev;
178}
179
180static int alloc_bucket_locks(struct rhashtable *ht, struct bucket_table *tbl) 117static int alloc_bucket_locks(struct rhashtable *ht, struct bucket_table *tbl)
181{ 118{
182 unsigned int i, size; 119 unsigned int i, size;
@@ -270,101 +207,99 @@ static bool rht_shrink_below_30(const struct rhashtable *ht, size_t new_size)
270 (atomic_read(&ht->shift) > ht->p.min_shift); 207 (atomic_read(&ht->shift) > ht->p.min_shift);
271} 208}
272 209
273static void lock_buckets(struct bucket_table *new_tbl, 210static int rhashtable_rehash_one(struct rhashtable *ht, unsigned old_hash)
274 struct bucket_table *old_tbl, unsigned int hash)
275 __acquires(old_bucket_lock)
276{ 211{
277 spin_lock_bh(bucket_lock(old_tbl, hash)); 212 struct bucket_table *new_tbl = rht_dereference(ht->future_tbl, ht);
278 if (new_tbl != old_tbl) 213 struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht);
279 spin_lock_bh_nested(bucket_lock(new_tbl, hash), 214 struct rhash_head __rcu **pprev = &old_tbl->buckets[old_hash];
280 RHT_LOCK_NESTED); 215 int err = -ENOENT;
281} 216 struct rhash_head *head, *next, *entry;
217 spinlock_t *new_bucket_lock;
218 unsigned new_hash;
282 219
283static void unlock_buckets(struct bucket_table *new_tbl, 220 rht_for_each(entry, old_tbl, old_hash) {
284 struct bucket_table *old_tbl, unsigned int hash) 221 err = 0;
285 __releases(old_bucket_lock) 222 next = rht_dereference_bucket(entry->next, old_tbl, old_hash);
286{
287 if (new_tbl != old_tbl)
288 spin_unlock_bh(bucket_lock(new_tbl, hash));
289 spin_unlock_bh(bucket_lock(old_tbl, hash));
290}
291 223
292/** 224 if (rht_is_a_nulls(next))
293 * Unlink entries on bucket which hash to different bucket. 225 break;
294 *
295 * Returns true if no more work needs to be performed on the bucket.
296 */
297static bool hashtable_chain_unzip(struct rhashtable *ht,
298 const struct bucket_table *new_tbl,
299 struct bucket_table *old_tbl,
300 size_t old_hash)
301{
302 struct rhash_head *he, *p, *next;
303 unsigned int new_hash, new_hash2;
304 226
305 ASSERT_BUCKET_LOCK(ht, old_tbl, old_hash); 227 pprev = &entry->next;
228 }
306 229
307 /* Old bucket empty, no work needed. */ 230 if (err)
308 p = rht_dereference_bucket(old_tbl->buckets[old_hash], old_tbl, 231 goto out;
309 old_hash);
310 if (rht_is_a_nulls(p))
311 return false;
312 232
313 new_hash = head_hashfn(ht, new_tbl, p); 233 new_hash = head_hashfn(ht, new_tbl, entry);
314 ASSERT_BUCKET_LOCK(ht, new_tbl, new_hash);
315 234
316 /* Advance the old bucket pointer one or more times until it 235 new_bucket_lock = bucket_lock(new_tbl, new_hash);
317 * reaches a node that doesn't hash to the same bucket as the
318 * previous node p. Call the previous node p;
319 */
320 rht_for_each_continue(he, p->next, old_tbl, old_hash) {
321 new_hash2 = head_hashfn(ht, new_tbl, he);
322 ASSERT_BUCKET_LOCK(ht, new_tbl, new_hash2);
323 236
324 if (new_hash != new_hash2) 237 spin_lock(new_bucket_lock);
325 break; 238 head = rht_dereference_bucket(new_tbl->buckets[new_hash],
326 p = he; 239 new_tbl, new_hash);
327 }
328 rcu_assign_pointer(old_tbl->buckets[old_hash], p->next);
329 240
330 /* Find the subsequent node which does hash to the same 241 if (rht_is_a_nulls(head))
331 * bucket as node P, or NULL if no such node exists. 242 INIT_RHT_NULLS_HEAD(entry->next, ht, new_hash);
332 */ 243 else
333 INIT_RHT_NULLS_HEAD(next, ht, old_hash); 244 RCU_INIT_POINTER(entry->next, head);
334 if (!rht_is_a_nulls(he)) {
335 rht_for_each_continue(he, he->next, old_tbl, old_hash) {
336 if (head_hashfn(ht, new_tbl, he) == new_hash) {
337 next = he;
338 break;
339 }
340 }
341 }
342 245
343 /* Set p's next pointer to that subsequent node pointer, 246 rcu_assign_pointer(new_tbl->buckets[new_hash], entry);
344 * bypassing the nodes which do not hash to p's bucket 247 spin_unlock(new_bucket_lock);
345 */
346 rcu_assign_pointer(p->next, next);
347 248
348 p = rht_dereference_bucket(old_tbl->buckets[old_hash], old_tbl, 249 rcu_assign_pointer(*pprev, next);
349 old_hash);
350 250
351 return !rht_is_a_nulls(p); 251out:
252 return err;
352} 253}
353 254
354static void link_old_to_new(struct rhashtable *ht, struct bucket_table *new_tbl, 255static void rhashtable_rehash_chain(struct rhashtable *ht, unsigned old_hash)
355 unsigned int new_hash, struct rhash_head *entry)
356{ 256{
357 ASSERT_BUCKET_LOCK(ht, new_tbl, new_hash); 257 struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht);
258 spinlock_t *old_bucket_lock;
259
260 old_bucket_lock = bucket_lock(old_tbl, old_hash);
358 261
359 rcu_assign_pointer(*bucket_tail(new_tbl, new_hash), entry); 262 spin_lock_bh(old_bucket_lock);
263 while (!rhashtable_rehash_one(ht, old_hash))
264 ;
265 spin_unlock_bh(old_bucket_lock);
266}
267
268static void rhashtable_rehash(struct rhashtable *ht,
269 struct bucket_table *new_tbl)
270{
271 struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht);
272 unsigned old_hash;
273
274 get_random_bytes(&new_tbl->hash_rnd, sizeof(new_tbl->hash_rnd));
275
276 /* Make insertions go into the new, empty table right away. Deletions
277 * and lookups will be attempted in both tables until we synchronize.
278 * The synchronize_rcu() guarantees for the new table to be picked up
279 * so no new additions go into the old table while we relink.
280 */
281 rcu_assign_pointer(ht->future_tbl, new_tbl);
282
283 for (old_hash = 0; old_hash < old_tbl->size; old_hash++)
284 rhashtable_rehash_chain(ht, old_hash);
285
286 /* Publish the new table pointer. */
287 rcu_assign_pointer(ht->tbl, new_tbl);
288
289 /* Wait for readers. All new readers will see the new
290 * table, and thus no references to the old table will
291 * remain.
292 */
293 synchronize_rcu();
294
295 bucket_table_free(old_tbl);
360} 296}
361 297
362/** 298/**
363 * rhashtable_expand - Expand hash table while allowing concurrent lookups 299 * rhashtable_expand - Expand hash table while allowing concurrent lookups
364 * @ht: the hash table to expand 300 * @ht: the hash table to expand
365 * 301 *
366 * A secondary bucket array is allocated and the hash entries are migrated 302 * A secondary bucket array is allocated and the hash entries are migrated.
367 * while keeping them on both lists until the end of the RCU grace period.
368 * 303 *
369 * This function may only be called in a context where it is safe to call 304 * This function may only be called in a context where it is safe to call
370 * synchronize_rcu(), e.g. not within a rcu_read_lock() section. 305 * synchronize_rcu(), e.g. not within a rcu_read_lock() section.
@@ -378,9 +313,6 @@ static void link_old_to_new(struct rhashtable *ht, struct bucket_table *new_tbl,
378int rhashtable_expand(struct rhashtable *ht) 313int rhashtable_expand(struct rhashtable *ht)
379{ 314{
380 struct bucket_table *new_tbl, *old_tbl = rht_dereference(ht->tbl, ht); 315 struct bucket_table *new_tbl, *old_tbl = rht_dereference(ht->tbl, ht);
381 struct rhash_head *he;
382 unsigned int new_hash, old_hash;
383 bool complete = false;
384 316
385 ASSERT_RHT_MUTEX(ht); 317 ASSERT_RHT_MUTEX(ht);
386 318
@@ -392,64 +324,8 @@ int rhashtable_expand(struct rhashtable *ht)
392 324
393 atomic_inc(&ht->shift); 325 atomic_inc(&ht->shift);
394 326
395 /* Make insertions go into the new, empty table right away. Deletions 327 rhashtable_rehash(ht, new_tbl);
396 * and lookups will be attempted in both tables until we synchronize.
397 * The synchronize_rcu() guarantees for the new table to be picked up
398 * so no new additions go into the old table while we relink.
399 */
400 rcu_assign_pointer(ht->future_tbl, new_tbl);
401 synchronize_rcu();
402 328
403 /* For each new bucket, search the corresponding old bucket for the
404 * first entry that hashes to the new bucket, and link the end of
405 * newly formed bucket chain (containing entries added to future
406 * table) to that entry. Since all the entries which will end up in
407 * the new bucket appear in the same old bucket, this constructs an
408 * entirely valid new hash table, but with multiple buckets
409 * "zipped" together into a single imprecise chain.
410 */
411 for (new_hash = 0; new_hash < new_tbl->size; new_hash++) {
412 old_hash = rht_bucket_index(old_tbl, new_hash);
413 lock_buckets(new_tbl, old_tbl, new_hash);
414 rht_for_each(he, old_tbl, old_hash) {
415 if (head_hashfn(ht, new_tbl, he) == new_hash) {
416 link_old_to_new(ht, new_tbl, new_hash, he);
417 break;
418 }
419 }
420 unlock_buckets(new_tbl, old_tbl, new_hash);
421 cond_resched();
422 }
423
424 /* Unzip interleaved hash chains */
425 while (!complete && !ht->being_destroyed) {
426 /* Wait for readers. All new readers will see the new
427 * table, and thus no references to the old table will
428 * remain.
429 */
430 synchronize_rcu();
431
432 /* For each bucket in the old table (each of which
433 * contains items from multiple buckets of the new
434 * table): ...
435 */
436 complete = true;
437 for (old_hash = 0; old_hash < old_tbl->size; old_hash++) {
438 lock_buckets(new_tbl, old_tbl, old_hash);
439
440 if (hashtable_chain_unzip(ht, new_tbl, old_tbl,
441 old_hash))
442 complete = false;
443
444 unlock_buckets(new_tbl, old_tbl, old_hash);
445 cond_resched();
446 }
447 }
448
449 rcu_assign_pointer(ht->tbl, new_tbl);
450 synchronize_rcu();
451
452 bucket_table_free(old_tbl);
453 return 0; 329 return 0;
454} 330}
455EXPORT_SYMBOL_GPL(rhashtable_expand); 331EXPORT_SYMBOL_GPL(rhashtable_expand);
@@ -473,7 +349,6 @@ EXPORT_SYMBOL_GPL(rhashtable_expand);
473int rhashtable_shrink(struct rhashtable *ht) 349int rhashtable_shrink(struct rhashtable *ht)
474{ 350{
475 struct bucket_table *new_tbl, *tbl = rht_dereference(ht->tbl, ht); 351 struct bucket_table *new_tbl, *tbl = rht_dereference(ht->tbl, ht);
476 unsigned int new_hash;
477 352
478 ASSERT_RHT_MUTEX(ht); 353 ASSERT_RHT_MUTEX(ht);
479 354
@@ -483,39 +358,9 @@ int rhashtable_shrink(struct rhashtable *ht)
483 358
484 new_tbl->hash_rnd = tbl->hash_rnd; 359 new_tbl->hash_rnd = tbl->hash_rnd;
485 360
486 rcu_assign_pointer(ht->future_tbl, new_tbl);
487 synchronize_rcu();
488
489 /* Link the first entry in the old bucket to the end of the
490 * bucket in the new table. As entries are concurrently being
491 * added to the new table, lock down the new bucket. As we
492 * always divide the size in half when shrinking, each bucket
493 * in the new table maps to exactly two buckets in the old
494 * table.
495 */
496 for (new_hash = 0; new_hash < new_tbl->size; new_hash++) {
497 lock_buckets(new_tbl, tbl, new_hash);
498
499 rcu_assign_pointer(*bucket_tail(new_tbl, new_hash),
500 tbl->buckets[new_hash]);
501 ASSERT_BUCKET_LOCK(ht, tbl, new_hash + new_tbl->size);
502 rcu_assign_pointer(*bucket_tail(new_tbl, new_hash),
503 tbl->buckets[new_hash + new_tbl->size]);
504
505 unlock_buckets(new_tbl, tbl, new_hash);
506 cond_resched();
507 }
508
509 /* Publish the new, valid hash table */
510 rcu_assign_pointer(ht->tbl, new_tbl);
511 atomic_dec(&ht->shift); 361 atomic_dec(&ht->shift);
512 362
513 /* Wait for readers. No new readers will have references to the 363 rhashtable_rehash(ht, new_tbl);
514 * old hash table.
515 */
516 synchronize_rcu();
517
518 bucket_table_free(tbl);
519 364
520 return 0; 365 return 0;
521} 366}
@@ -545,18 +390,46 @@ unlock:
545 mutex_unlock(&ht->mutex); 390 mutex_unlock(&ht->mutex);
546} 391}
547 392
548static void __rhashtable_insert(struct rhashtable *ht, struct rhash_head *obj, 393static bool __rhashtable_insert(struct rhashtable *ht, struct rhash_head *obj,
549 struct bucket_table *tbl, 394 bool (*compare)(void *, void *), void *arg)
550 const struct bucket_table *old_tbl, u32 hash)
551{ 395{
552 bool no_resize_running = tbl == old_tbl; 396 struct bucket_table *tbl, *old_tbl;
553 struct rhash_head *head; 397 struct rhash_head *head;
398 bool no_resize_running;
399 unsigned hash;
400 bool success = true;
401
402 rcu_read_lock();
403
404 old_tbl = rht_dereference_rcu(ht->tbl, ht);
405 hash = obj_raw_hashfn(ht, old_tbl, rht_obj(ht, obj));
406
407 spin_lock_bh(bucket_lock(old_tbl, hash));
408
409 /* Because we have already taken the bucket lock in old_tbl,
410 * if we find that future_tbl is not yet visible then that
411 * guarantees all other insertions of the same entry will
412 * also grab the bucket lock in old_tbl because until the
413 * rehash completes ht->tbl won't be changed.
414 */
415 tbl = rht_dereference_rcu(ht->future_tbl, ht);
416 if (tbl != old_tbl) {
417 hash = obj_raw_hashfn(ht, tbl, rht_obj(ht, obj));
418 spin_lock(bucket_lock(tbl, hash));
419 }
420
421 if (compare &&
422 rhashtable_lookup_compare(ht, rht_obj(ht, obj) + ht->p.key_offset,
423 compare, arg)) {
424 success = false;
425 goto exit;
426 }
427
428 no_resize_running = tbl == old_tbl;
554 429
555 hash = rht_bucket_index(tbl, hash); 430 hash = rht_bucket_index(tbl, hash);
556 head = rht_dereference_bucket(tbl->buckets[hash], tbl, hash); 431 head = rht_dereference_bucket(tbl->buckets[hash], tbl, hash);
557 432
558 ASSERT_BUCKET_LOCK(ht, tbl, hash);
559
560 if (rht_is_a_nulls(head)) 433 if (rht_is_a_nulls(head))
561 INIT_RHT_NULLS_HEAD(obj->next, ht, hash); 434 INIT_RHT_NULLS_HEAD(obj->next, ht, hash);
562 else 435 else
@@ -567,6 +440,19 @@ static void __rhashtable_insert(struct rhashtable *ht, struct rhash_head *obj,
567 atomic_inc(&ht->nelems); 440 atomic_inc(&ht->nelems);
568 if (no_resize_running && rht_grow_above_75(ht, tbl->size)) 441 if (no_resize_running && rht_grow_above_75(ht, tbl->size))
569 schedule_work(&ht->run_work); 442 schedule_work(&ht->run_work);
443
444exit:
445 if (tbl != old_tbl) {
446 hash = obj_raw_hashfn(ht, tbl, rht_obj(ht, obj));
447 spin_unlock(bucket_lock(tbl, hash));
448 }
449
450 hash = obj_raw_hashfn(ht, old_tbl, rht_obj(ht, obj));
451 spin_unlock_bh(bucket_lock(old_tbl, hash));
452
453 rcu_read_unlock();
454
455 return success;
570} 456}
571 457
572/** 458/**
@@ -586,22 +472,42 @@ static void __rhashtable_insert(struct rhashtable *ht, struct rhash_head *obj,
586 */ 472 */
587void rhashtable_insert(struct rhashtable *ht, struct rhash_head *obj) 473void rhashtable_insert(struct rhashtable *ht, struct rhash_head *obj)
588{ 474{
589 struct bucket_table *tbl, *old_tbl; 475 __rhashtable_insert(ht, obj, NULL, NULL);
476}
477EXPORT_SYMBOL_GPL(rhashtable_insert);
478
479static bool __rhashtable_remove(struct rhashtable *ht,
480 struct bucket_table *tbl,
481 struct rhash_head *obj)
482{
483 struct rhash_head __rcu **pprev;
484 struct rhash_head *he;
485 spinlock_t * lock;
590 unsigned hash; 486 unsigned hash;
487 bool ret = false;
591 488
592 rcu_read_lock(); 489 hash = obj_raw_hashfn(ht, tbl, rht_obj(ht, obj));
490 lock = bucket_lock(tbl, hash);
491 hash = rht_bucket_index(tbl, hash);
593 492
594 tbl = rht_dereference_rcu(ht->future_tbl, ht); 493 spin_lock_bh(lock);
595 old_tbl = rht_dereference_rcu(ht->tbl, ht);
596 hash = obj_raw_hashfn(ht, rht_obj(ht, obj));
597 494
598 lock_buckets(tbl, old_tbl, hash); 495 pprev = &tbl->buckets[hash];
599 __rhashtable_insert(ht, obj, tbl, old_tbl, hash); 496 rht_for_each(he, tbl, hash) {
600 unlock_buckets(tbl, old_tbl, hash); 497 if (he != obj) {
498 pprev = &he->next;
499 continue;
500 }
601 501
602 rcu_read_unlock(); 502 rcu_assign_pointer(*pprev, obj->next);
503 ret = true;
504 break;
505 }
506
507 spin_unlock_bh(lock);
508
509 return ret;
603} 510}
604EXPORT_SYMBOL_GPL(rhashtable_insert);
605 511
606/** 512/**
607 * rhashtable_remove - remove object from hash table 513 * rhashtable_remove - remove object from hash table
@@ -620,68 +526,28 @@ EXPORT_SYMBOL_GPL(rhashtable_insert);
620 */ 526 */
621bool rhashtable_remove(struct rhashtable *ht, struct rhash_head *obj) 527bool rhashtable_remove(struct rhashtable *ht, struct rhash_head *obj)
622{ 528{
623 struct bucket_table *tbl, *new_tbl, *old_tbl; 529 struct bucket_table *tbl, *old_tbl;
624 struct rhash_head __rcu **pprev; 530 bool ret;
625 struct rhash_head *he, *he2;
626 unsigned int hash, new_hash;
627 bool ret = false;
628 531
629 rcu_read_lock(); 532 rcu_read_lock();
630 old_tbl = rht_dereference_rcu(ht->tbl, ht);
631 tbl = new_tbl = rht_dereference_rcu(ht->future_tbl, ht);
632 new_hash = obj_raw_hashfn(ht, rht_obj(ht, obj));
633
634 lock_buckets(new_tbl, old_tbl, new_hash);
635restart:
636 hash = rht_bucket_index(tbl, new_hash);
637 pprev = &tbl->buckets[hash];
638 rht_for_each(he, tbl, hash) {
639 if (he != obj) {
640 pprev = &he->next;
641 continue;
642 }
643 533
644 ASSERT_BUCKET_LOCK(ht, tbl, hash); 534 old_tbl = rht_dereference_rcu(ht->tbl, ht);
645 535 ret = __rhashtable_remove(ht, old_tbl, obj);
646 if (old_tbl->size > new_tbl->size && tbl == old_tbl &&
647 !rht_is_a_nulls(obj->next) &&
648 head_hashfn(ht, tbl, obj->next) != hash) {
649 rcu_assign_pointer(*pprev, (struct rhash_head *) rht_marker(ht, hash));
650 } else if (unlikely(old_tbl->size < new_tbl->size && tbl == new_tbl)) {
651 rht_for_each_continue(he2, obj->next, tbl, hash) {
652 if (head_hashfn(ht, tbl, he2) == hash) {
653 rcu_assign_pointer(*pprev, he2);
654 goto found;
655 }
656 }
657
658 rcu_assign_pointer(*pprev, (struct rhash_head *) rht_marker(ht, hash));
659 } else {
660 rcu_assign_pointer(*pprev, obj->next);
661 }
662
663found:
664 ret = true;
665 break;
666 }
667 536
668 /* The entry may be linked in either 'tbl', 'future_tbl', or both. 537 /* Because we have already taken (and released) the bucket
669 * 'future_tbl' only exists for a short period of time during 538 * lock in old_tbl, if we find that future_tbl is not yet
670 * resizing. Thus traversing both is fine and the added cost is 539 * visible then that guarantees the entry to still be in
671 * very rare. 540 * old_tbl if it exists.
672 */ 541 */
673 if (tbl != old_tbl) { 542 tbl = rht_dereference_rcu(ht->future_tbl, ht);
674 tbl = old_tbl; 543 if (!ret && old_tbl != tbl)
675 goto restart; 544 ret = __rhashtable_remove(ht, tbl, obj);
676 }
677
678 unlock_buckets(new_tbl, old_tbl, new_hash);
679 545
680 if (ret) { 546 if (ret) {
681 bool no_resize_running = new_tbl == old_tbl; 547 bool no_resize_running = tbl == old_tbl;
682 548
683 atomic_dec(&ht->nelems); 549 atomic_dec(&ht->nelems);
684 if (no_resize_running && rht_shrink_below_30(ht, new_tbl->size)) 550 if (no_resize_running && rht_shrink_below_30(ht, tbl->size))
685 schedule_work(&ht->run_work); 551 schedule_work(&ht->run_work);
686 } 552 }
687 553
@@ -753,9 +619,8 @@ void *rhashtable_lookup_compare(struct rhashtable *ht, const void *key,
753 619
754 rcu_read_lock(); 620 rcu_read_lock();
755 621
756 old_tbl = rht_dereference_rcu(ht->tbl, ht); 622 tbl = rht_dereference_rcu(ht->tbl, ht);
757 tbl = rht_dereference_rcu(ht->future_tbl, ht); 623 hash = key_hashfn(ht, tbl, key, ht->p.key_len);
758 hash = key_hashfn(ht, key, ht->p.key_len);
759restart: 624restart:
760 rht_for_each_rcu(he, tbl, rht_bucket_index(tbl, hash)) { 625 rht_for_each_rcu(he, tbl, rht_bucket_index(tbl, hash)) {
761 if (!compare(rht_obj(ht, he), arg)) 626 if (!compare(rht_obj(ht, he), arg))
@@ -764,10 +629,10 @@ restart:
764 return rht_obj(ht, he); 629 return rht_obj(ht, he);
765 } 630 }
766 631
767 if (unlikely(tbl != old_tbl)) { 632 old_tbl = tbl;
768 tbl = old_tbl; 633 tbl = rht_dereference_rcu(ht->future_tbl, ht);
634 if (unlikely(tbl != old_tbl))
769 goto restart; 635 goto restart;
770 }
771 rcu_read_unlock(); 636 rcu_read_unlock();
772 637
773 return NULL; 638 return NULL;
@@ -833,32 +698,9 @@ bool rhashtable_lookup_compare_insert(struct rhashtable *ht,
833 bool (*compare)(void *, void *), 698 bool (*compare)(void *, void *),
834 void *arg) 699 void *arg)
835{ 700{
836 struct bucket_table *new_tbl, *old_tbl;
837 u32 new_hash;
838 bool success = true;
839
840 BUG_ON(!ht->p.key_len); 701 BUG_ON(!ht->p.key_len);
841 702
842 rcu_read_lock(); 703 return __rhashtable_insert(ht, obj, compare, arg);
843 old_tbl = rht_dereference_rcu(ht->tbl, ht);
844 new_tbl = rht_dereference_rcu(ht->future_tbl, ht);
845 new_hash = obj_raw_hashfn(ht, rht_obj(ht, obj));
846
847 lock_buckets(new_tbl, old_tbl, new_hash);
848
849 if (rhashtable_lookup_compare(ht, rht_obj(ht, obj) + ht->p.key_offset,
850 compare, arg)) {
851 success = false;
852 goto exit;
853 }
854
855 __rhashtable_insert(ht, obj, new_tbl, old_tbl, new_hash);
856
857exit:
858 unlock_buckets(new_tbl, old_tbl, new_hash);
859 rcu_read_unlock();
860
861 return success;
862} 704}
863EXPORT_SYMBOL_GPL(rhashtable_lookup_compare_insert); 705EXPORT_SYMBOL_GPL(rhashtable_lookup_compare_insert);
864 706