aboutsummaryrefslogtreecommitdiffstats
path: root/lib/rhashtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rhashtable.c')
-rw-r--r--lib/rhashtable.c300
1 files changed, 224 insertions, 76 deletions
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 56054e541a0f..32d0ad058380 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -378,22 +378,8 @@ static void rht_deferred_worker(struct work_struct *work)
378 schedule_work(&ht->run_work); 378 schedule_work(&ht->run_work);
379} 379}
380 380
381static bool rhashtable_check_elasticity(struct rhashtable *ht, 381static int rhashtable_insert_rehash(struct rhashtable *ht,
382 struct bucket_table *tbl, 382 struct bucket_table *tbl)
383 unsigned int hash)
384{
385 unsigned int elasticity = ht->elasticity;
386 struct rhash_head *head;
387
388 rht_for_each(head, tbl, hash)
389 if (!--elasticity)
390 return true;
391
392 return false;
393}
394
395int rhashtable_insert_rehash(struct rhashtable *ht,
396 struct bucket_table *tbl)
397{ 383{
398 struct bucket_table *old_tbl; 384 struct bucket_table *old_tbl;
399 struct bucket_table *new_tbl; 385 struct bucket_table *new_tbl;
@@ -439,61 +425,172 @@ fail:
439 425
440 return err; 426 return err;
441} 427}
442EXPORT_SYMBOL_GPL(rhashtable_insert_rehash);
443 428
444struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht, 429static void *rhashtable_lookup_one(struct rhashtable *ht,
445 const void *key, 430 struct bucket_table *tbl, unsigned int hash,
446 struct rhash_head *obj, 431 const void *key, struct rhash_head *obj)
447 struct bucket_table *tbl)
448{ 432{
433 struct rhashtable_compare_arg arg = {
434 .ht = ht,
435 .key = key,
436 };
437 struct rhash_head __rcu **pprev;
449 struct rhash_head *head; 438 struct rhash_head *head;
450 unsigned int hash; 439 int elasticity;
451 int err;
452 440
453 tbl = rhashtable_last_table(ht, tbl); 441 elasticity = ht->elasticity;
454 hash = head_hashfn(ht, tbl, obj); 442 pprev = &tbl->buckets[hash];
455 spin_lock_nested(rht_bucket_lock(tbl, hash), SINGLE_DEPTH_NESTING); 443 rht_for_each(head, tbl, hash) {
444 struct rhlist_head *list;
445 struct rhlist_head *plist;
456 446
457 err = -EEXIST; 447 elasticity--;
458 if (key && rhashtable_lookup_fast(ht, key, ht->p)) 448 if (!key ||
459 goto exit; 449 (ht->p.obj_cmpfn ?
450 ht->p.obj_cmpfn(&arg, rht_obj(ht, head)) :
451 rhashtable_compare(&arg, rht_obj(ht, head))))
452 continue;
460 453
461 err = -E2BIG; 454 if (!ht->rhlist)
462 if (unlikely(rht_grow_above_max(ht, tbl))) 455 return rht_obj(ht, head);
463 goto exit; 456
457 list = container_of(obj, struct rhlist_head, rhead);
458 plist = container_of(head, struct rhlist_head, rhead);
459
460 RCU_INIT_POINTER(list->next, plist);
461 head = rht_dereference_bucket(head->next, tbl, hash);
462 RCU_INIT_POINTER(list->rhead.next, head);
463 rcu_assign_pointer(*pprev, obj);
464
465 return NULL;
466 }
467
468 if (elasticity <= 0)
469 return ERR_PTR(-EAGAIN);
470
471 return ERR_PTR(-ENOENT);
472}
473
474static struct bucket_table *rhashtable_insert_one(struct rhashtable *ht,
475 struct bucket_table *tbl,
476 unsigned int hash,
477 struct rhash_head *obj,
478 void *data)
479{
480 struct bucket_table *new_tbl;
481 struct rhash_head *head;
482
483 if (!IS_ERR_OR_NULL(data))
484 return ERR_PTR(-EEXIST);
485
486 if (PTR_ERR(data) != -EAGAIN && PTR_ERR(data) != -ENOENT)
487 return ERR_CAST(data);
464 488
465 err = -EAGAIN; 489 new_tbl = rcu_dereference(tbl->future_tbl);
466 if (rhashtable_check_elasticity(ht, tbl, hash) || 490 if (new_tbl)
467 rht_grow_above_100(ht, tbl)) 491 return new_tbl;
468 goto exit;
469 492
470 err = 0; 493 if (PTR_ERR(data) != -ENOENT)
494 return ERR_CAST(data);
495
496 if (unlikely(rht_grow_above_max(ht, tbl)))
497 return ERR_PTR(-E2BIG);
498
499 if (unlikely(rht_grow_above_100(ht, tbl)))
500 return ERR_PTR(-EAGAIN);
471 501
472 head = rht_dereference_bucket(tbl->buckets[hash], tbl, hash); 502 head = rht_dereference_bucket(tbl->buckets[hash], tbl, hash);
473 503
474 RCU_INIT_POINTER(obj->next, head); 504 RCU_INIT_POINTER(obj->next, head);
505 if (ht->rhlist) {
506 struct rhlist_head *list;
507
508 list = container_of(obj, struct rhlist_head, rhead);
509 RCU_INIT_POINTER(list->next, NULL);
510 }
475 511
476 rcu_assign_pointer(tbl->buckets[hash], obj); 512 rcu_assign_pointer(tbl->buckets[hash], obj);
477 513
478 atomic_inc(&ht->nelems); 514 atomic_inc(&ht->nelems);
515 if (rht_grow_above_75(ht, tbl))
516 schedule_work(&ht->run_work);
479 517
480exit: 518 return NULL;
481 spin_unlock(rht_bucket_lock(tbl, hash)); 519}
482 520
483 if (err == 0) 521static void *rhashtable_try_insert(struct rhashtable *ht, const void *key,
484 return NULL; 522 struct rhash_head *obj)
485 else if (err == -EAGAIN) 523{
486 return tbl; 524 struct bucket_table *new_tbl;
487 else 525 struct bucket_table *tbl;
488 return ERR_PTR(err); 526 unsigned int hash;
527 spinlock_t *lock;
528 void *data;
529
530 tbl = rcu_dereference(ht->tbl);
531
532 /* All insertions must grab the oldest table containing
533 * the hashed bucket that is yet to be rehashed.
534 */
535 for (;;) {
536 hash = rht_head_hashfn(ht, tbl, obj, ht->p);
537 lock = rht_bucket_lock(tbl, hash);
538 spin_lock_bh(lock);
539
540 if (tbl->rehash <= hash)
541 break;
542
543 spin_unlock_bh(lock);
544 tbl = rcu_dereference(tbl->future_tbl);
545 }
546
547 data = rhashtable_lookup_one(ht, tbl, hash, key, obj);
548 new_tbl = rhashtable_insert_one(ht, tbl, hash, obj, data);
549 if (PTR_ERR(new_tbl) != -EEXIST)
550 data = ERR_CAST(new_tbl);
551
552 while (!IS_ERR_OR_NULL(new_tbl)) {
553 tbl = new_tbl;
554 hash = rht_head_hashfn(ht, tbl, obj, ht->p);
555 spin_lock_nested(rht_bucket_lock(tbl, hash),
556 SINGLE_DEPTH_NESTING);
557
558 data = rhashtable_lookup_one(ht, tbl, hash, key, obj);
559 new_tbl = rhashtable_insert_one(ht, tbl, hash, obj, data);
560 if (PTR_ERR(new_tbl) != -EEXIST)
561 data = ERR_CAST(new_tbl);
562
563 spin_unlock(rht_bucket_lock(tbl, hash));
564 }
565
566 spin_unlock_bh(lock);
567
568 if (PTR_ERR(data) == -EAGAIN)
569 data = ERR_PTR(rhashtable_insert_rehash(ht, tbl) ?:
570 -EAGAIN);
571
572 return data;
573}
574
575void *rhashtable_insert_slow(struct rhashtable *ht, const void *key,
576 struct rhash_head *obj)
577{
578 void *data;
579
580 do {
581 rcu_read_lock();
582 data = rhashtable_try_insert(ht, key, obj);
583 rcu_read_unlock();
584 } while (PTR_ERR(data) == -EAGAIN);
585
586 return data;
489} 587}
490EXPORT_SYMBOL_GPL(rhashtable_insert_slow); 588EXPORT_SYMBOL_GPL(rhashtable_insert_slow);
491 589
492/** 590/**
493 * rhashtable_walk_init - Initialise an iterator 591 * rhashtable_walk_enter - Initialise an iterator
494 * @ht: Table to walk over 592 * @ht: Table to walk over
495 * @iter: Hash table Iterator 593 * @iter: Hash table Iterator
496 * @gfp: GFP flags for allocations
497 * 594 *
498 * This function prepares a hash table walk. 595 * This function prepares a hash table walk.
499 * 596 *
@@ -508,30 +605,22 @@ EXPORT_SYMBOL_GPL(rhashtable_insert_slow);
508 * This function may sleep so you must not call it from interrupt 605 * This function may sleep so you must not call it from interrupt
509 * context or with spin locks held. 606 * context or with spin locks held.
510 * 607 *
511 * You must call rhashtable_walk_exit if this function returns 608 * You must call rhashtable_walk_exit after this function returns.
512 * successfully.
513 */ 609 */
514int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter, 610void rhashtable_walk_enter(struct rhashtable *ht, struct rhashtable_iter *iter)
515 gfp_t gfp)
516{ 611{
517 iter->ht = ht; 612 iter->ht = ht;
518 iter->p = NULL; 613 iter->p = NULL;
519 iter->slot = 0; 614 iter->slot = 0;
520 iter->skip = 0; 615 iter->skip = 0;
521 616
522 iter->walker = kmalloc(sizeof(*iter->walker), gfp);
523 if (!iter->walker)
524 return -ENOMEM;
525
526 spin_lock(&ht->lock); 617 spin_lock(&ht->lock);
527 iter->walker->tbl = 618 iter->walker.tbl =
528 rcu_dereference_protected(ht->tbl, lockdep_is_held(&ht->lock)); 619 rcu_dereference_protected(ht->tbl, lockdep_is_held(&ht->lock));
529 list_add(&iter->walker->list, &iter->walker->tbl->walkers); 620 list_add(&iter->walker.list, &iter->walker.tbl->walkers);
530 spin_unlock(&ht->lock); 621 spin_unlock(&ht->lock);
531
532 return 0;
533} 622}
534EXPORT_SYMBOL_GPL(rhashtable_walk_init); 623EXPORT_SYMBOL_GPL(rhashtable_walk_enter);
535 624
536/** 625/**
537 * rhashtable_walk_exit - Free an iterator 626 * rhashtable_walk_exit - Free an iterator
@@ -542,10 +631,9 @@ EXPORT_SYMBOL_GPL(rhashtable_walk_init);
542void rhashtable_walk_exit(struct rhashtable_iter *iter) 631void rhashtable_walk_exit(struct rhashtable_iter *iter)
543{ 632{
544 spin_lock(&iter->ht->lock); 633 spin_lock(&iter->ht->lock);
545 if (iter->walker->tbl) 634 if (iter->walker.tbl)
546 list_del(&iter->walker->list); 635 list_del(&iter->walker.list);
547 spin_unlock(&iter->ht->lock); 636 spin_unlock(&iter->ht->lock);
548 kfree(iter->walker);
549} 637}
550EXPORT_SYMBOL_GPL(rhashtable_walk_exit); 638EXPORT_SYMBOL_GPL(rhashtable_walk_exit);
551 639
@@ -571,12 +659,12 @@ int rhashtable_walk_start(struct rhashtable_iter *iter)
571 rcu_read_lock(); 659 rcu_read_lock();
572 660
573 spin_lock(&ht->lock); 661 spin_lock(&ht->lock);
574 if (iter->walker->tbl) 662 if (iter->walker.tbl)
575 list_del(&iter->walker->list); 663 list_del(&iter->walker.list);
576 spin_unlock(&ht->lock); 664 spin_unlock(&ht->lock);
577 665
578 if (!iter->walker->tbl) { 666 if (!iter->walker.tbl) {
579 iter->walker->tbl = rht_dereference_rcu(ht->tbl, ht); 667 iter->walker.tbl = rht_dereference_rcu(ht->tbl, ht);
580 return -EAGAIN; 668 return -EAGAIN;
581 } 669 }
582 670
@@ -598,12 +686,17 @@ EXPORT_SYMBOL_GPL(rhashtable_walk_start);
598 */ 686 */
599void *rhashtable_walk_next(struct rhashtable_iter *iter) 687void *rhashtable_walk_next(struct rhashtable_iter *iter)
600{ 688{
601 struct bucket_table *tbl = iter->walker->tbl; 689 struct bucket_table *tbl = iter->walker.tbl;
690 struct rhlist_head *list = iter->list;
602 struct rhashtable *ht = iter->ht; 691 struct rhashtable *ht = iter->ht;
603 struct rhash_head *p = iter->p; 692 struct rhash_head *p = iter->p;
693 bool rhlist = ht->rhlist;
604 694
605 if (p) { 695 if (p) {
606 p = rht_dereference_bucket_rcu(p->next, tbl, iter->slot); 696 if (!rhlist || !(list = rcu_dereference(list->next))) {
697 p = rcu_dereference(p->next);
698 list = container_of(p, struct rhlist_head, rhead);
699 }
607 goto next; 700 goto next;
608 } 701 }
609 702
@@ -611,6 +704,18 @@ void *rhashtable_walk_next(struct rhashtable_iter *iter)
611 int skip = iter->skip; 704 int skip = iter->skip;
612 705
613 rht_for_each_rcu(p, tbl, iter->slot) { 706 rht_for_each_rcu(p, tbl, iter->slot) {
707 if (rhlist) {
708 list = container_of(p, struct rhlist_head,
709 rhead);
710 do {
711 if (!skip)
712 goto next;
713 skip--;
714 list = rcu_dereference(list->next);
715 } while (list);
716
717 continue;
718 }
614 if (!skip) 719 if (!skip)
615 break; 720 break;
616 skip--; 721 skip--;
@@ -620,7 +725,8 @@ next:
620 if (!rht_is_a_nulls(p)) { 725 if (!rht_is_a_nulls(p)) {
621 iter->skip++; 726 iter->skip++;
622 iter->p = p; 727 iter->p = p;
623 return rht_obj(ht, p); 728 iter->list = list;
729 return rht_obj(ht, rhlist ? &list->rhead : p);
624 } 730 }
625 731
626 iter->skip = 0; 732 iter->skip = 0;
@@ -631,8 +737,8 @@ next:
631 /* Ensure we see any new tables. */ 737 /* Ensure we see any new tables. */
632 smp_rmb(); 738 smp_rmb();
633 739
634 iter->walker->tbl = rht_dereference_rcu(tbl->future_tbl, ht); 740 iter->walker.tbl = rht_dereference_rcu(tbl->future_tbl, ht);
635 if (iter->walker->tbl) { 741 if (iter->walker.tbl) {
636 iter->slot = 0; 742 iter->slot = 0;
637 iter->skip = 0; 743 iter->skip = 0;
638 return ERR_PTR(-EAGAIN); 744 return ERR_PTR(-EAGAIN);
@@ -652,7 +758,7 @@ void rhashtable_walk_stop(struct rhashtable_iter *iter)
652 __releases(RCU) 758 __releases(RCU)
653{ 759{
654 struct rhashtable *ht; 760 struct rhashtable *ht;
655 struct bucket_table *tbl = iter->walker->tbl; 761 struct bucket_table *tbl = iter->walker.tbl;
656 762
657 if (!tbl) 763 if (!tbl)
658 goto out; 764 goto out;
@@ -661,9 +767,9 @@ void rhashtable_walk_stop(struct rhashtable_iter *iter)
661 767
662 spin_lock(&ht->lock); 768 spin_lock(&ht->lock);
663 if (tbl->rehash < tbl->size) 769 if (tbl->rehash < tbl->size)
664 list_add(&iter->walker->list, &tbl->walkers); 770 list_add(&iter->walker.list, &tbl->walkers);
665 else 771 else
666 iter->walker->tbl = NULL; 772 iter->walker.tbl = NULL;
667 spin_unlock(&ht->lock); 773 spin_unlock(&ht->lock);
668 774
669 iter->p = NULL; 775 iter->p = NULL;
@@ -809,6 +915,48 @@ int rhashtable_init(struct rhashtable *ht,
809EXPORT_SYMBOL_GPL(rhashtable_init); 915EXPORT_SYMBOL_GPL(rhashtable_init);
810 916
811/** 917/**
918 * rhltable_init - initialize a new hash list table
919 * @hlt: hash list table to be initialized
920 * @params: configuration parameters
921 *
922 * Initializes a new hash list table.
923 *
924 * See documentation for rhashtable_init.
925 */
926int rhltable_init(struct rhltable *hlt, const struct rhashtable_params *params)
927{
928 int err;
929
930 /* No rhlist NULLs marking for now. */
931 if (params->nulls_base)
932 return -EINVAL;
933
934 err = rhashtable_init(&hlt->ht, params);
935 hlt->ht.rhlist = true;
936 return err;
937}
938EXPORT_SYMBOL_GPL(rhltable_init);
939
940static void rhashtable_free_one(struct rhashtable *ht, struct rhash_head *obj,
941 void (*free_fn)(void *ptr, void *arg),
942 void *arg)
943{
944 struct rhlist_head *list;
945
946 if (!ht->rhlist) {
947 free_fn(rht_obj(ht, obj), arg);
948 return;
949 }
950
951 list = container_of(obj, struct rhlist_head, rhead);
952 do {
953 obj = &list->rhead;
954 list = rht_dereference(list->next, ht);
955 free_fn(rht_obj(ht, obj), arg);
956 } while (list);
957}
958
959/**
812 * rhashtable_free_and_destroy - free elements and destroy hash table 960 * rhashtable_free_and_destroy - free elements and destroy hash table
813 * @ht: the hash table to destroy 961 * @ht: the hash table to destroy
814 * @free_fn: callback to release resources of element 962 * @free_fn: callback to release resources of element
@@ -845,7 +993,7 @@ void rhashtable_free_and_destroy(struct rhashtable *ht,
845 pos = next, 993 pos = next,
846 next = !rht_is_a_nulls(pos) ? 994 next = !rht_is_a_nulls(pos) ?
847 rht_dereference(pos->next, ht) : NULL) 995 rht_dereference(pos->next, ht) : NULL)
848 free_fn(rht_obj(ht, pos), arg); 996 rhashtable_free_one(ht, pos, free_fn, arg);
849 } 997 }
850 } 998 }
851 999