aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/rhashtable.c41
1 files changed, 18 insertions, 23 deletions
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index cbad192d3b3d..f2fdd7a7cb16 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -612,6 +612,19 @@ restart:
612} 612}
613EXPORT_SYMBOL_GPL(rhashtable_remove); 613EXPORT_SYMBOL_GPL(rhashtable_remove);
614 614
615struct rhashtable_compare_arg {
616 struct rhashtable *ht;
617 const void *key;
618};
619
620static bool rhashtable_compare(void *ptr, void *arg)
621{
622 struct rhashtable_compare_arg *x = arg;
623 struct rhashtable *ht = x->ht;
624
625 return !memcmp(ptr + ht->p.key_offset, x->key, ht->p.key_len);
626}
627
615/** 628/**
616 * rhashtable_lookup - lookup key in hash table 629 * rhashtable_lookup - lookup key in hash table
617 * @ht: hash table 630 * @ht: hash table
@@ -627,32 +640,14 @@ EXPORT_SYMBOL_GPL(rhashtable_remove);
627 */ 640 */
628void *rhashtable_lookup(struct rhashtable *ht, const void *key) 641void *rhashtable_lookup(struct rhashtable *ht, const void *key)
629{ 642{
630 const struct bucket_table *tbl, *old_tbl; 643 struct rhashtable_compare_arg arg = {
631 struct rhash_head *he; 644 .ht = ht,
632 u32 hash; 645 .key = key,
646 };
633 647
634 BUG_ON(!ht->p.key_len); 648 BUG_ON(!ht->p.key_len);
635 649
636 rcu_read_lock(); 650 return rhashtable_lookup_compare(ht, key, &rhashtable_compare, &arg);
637 old_tbl = rht_dereference_rcu(ht->tbl, ht);
638 tbl = rht_dereference_rcu(ht->future_tbl, ht);
639 hash = key_hashfn(ht, key, ht->p.key_len);
640restart:
641 rht_for_each_rcu(he, tbl, rht_bucket_index(tbl, hash)) {
642 if (memcmp(rht_obj(ht, he) + ht->p.key_offset, key,
643 ht->p.key_len))
644 continue;
645 rcu_read_unlock();
646 return rht_obj(ht, he);
647 }
648
649 if (unlikely(tbl != old_tbl)) {
650 tbl = old_tbl;
651 goto restart;
652 }
653
654 rcu_read_unlock();
655 return NULL;
656} 651}
657EXPORT_SYMBOL_GPL(rhashtable_lookup); 652EXPORT_SYMBOL_GPL(rhashtable_lookup);
658 653