aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorYing Xue <ying.xue@windriver.com>2015-01-12 01:52:22 -0500
committerDavid S. Miller <davem@davemloft.net>2015-01-13 14:01:00 -0500
commit7a868d1e9ab3c534c5ad44e3e5dc46753a1e5636 (patch)
tree9b490c8b37180ba0ce56ffd9ff521b43218fd8c5 /lib
parentd2c60b1350c9a3eb7ed407c18f50306762365646 (diff)
rhashtable: involve rhashtable_lookup_compare_insert routine
Introduce a new function called rhashtable_lookup_compare_insert() which is very similar to rhashtable_lookup_insert(). But the former makes use of users' given compare function to look for an object, and then inserts it into hash table if found. As the entire process of search and insertion is under protection of per bucket lock, this can help users to avoid the involvement of extra lock. Signed-off-by: Ying Xue <ying.xue@windriver.com> Cc: Thomas Graf <tgraf@suug.ch> Acked-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'lib')
-rw-r--r--lib/rhashtable.c42
1 files changed, 40 insertions, 2 deletions
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 8023b554905c..ed6ae1ad304c 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -727,6 +727,43 @@ EXPORT_SYMBOL_GPL(rhashtable_lookup_compare);
727 */ 727 */
728bool rhashtable_lookup_insert(struct rhashtable *ht, struct rhash_head *obj) 728bool rhashtable_lookup_insert(struct rhashtable *ht, struct rhash_head *obj)
729{ 729{
730 struct rhashtable_compare_arg arg = {
731 .ht = ht,
732 .key = rht_obj(ht, obj) + ht->p.key_offset,
733 };
734
735 BUG_ON(!ht->p.key_len);
736
737 return rhashtable_lookup_compare_insert(ht, obj, &rhashtable_compare,
738 &arg);
739}
740EXPORT_SYMBOL_GPL(rhashtable_lookup_insert);
741
742/**
743 * rhashtable_lookup_compare_insert - search and insert object to hash table
744 * with compare function
745 * @ht: hash table
746 * @obj: pointer to hash head inside object
747 * @compare: compare function, must return true on match
748 * @arg: argument passed on to compare function
749 *
750 * Locks down the bucket chain in both the old and new table if a resize
751 * is in progress to ensure that writers can't remove from the old table
752 * and can't insert to the new table during the atomic operation of search
753 * and insertion. Searches for duplicates in both the old and new table if
754 * a resize is in progress.
755 *
756 * Lookups may occur in parallel with hashtable mutations and resizing.
757 *
758 * Will trigger an automatic deferred table resizing if the size grows
759 * beyond the watermark indicated by grow_decision() which can be passed
760 * to rhashtable_init().
761 */
762bool rhashtable_lookup_compare_insert(struct rhashtable *ht,
763 struct rhash_head *obj,
764 bool (*compare)(void *, void *),
765 void *arg)
766{
730 struct bucket_table *new_tbl, *old_tbl; 767 struct bucket_table *new_tbl, *old_tbl;
731 spinlock_t *new_bucket_lock, *old_bucket_lock; 768 spinlock_t *new_bucket_lock, *old_bucket_lock;
732 u32 new_hash, old_hash; 769 u32 new_hash, old_hash;
@@ -747,7 +784,8 @@ bool rhashtable_lookup_insert(struct rhashtable *ht, struct rhash_head *obj)
747 if (unlikely(old_tbl != new_tbl)) 784 if (unlikely(old_tbl != new_tbl))
748 spin_lock_bh_nested(new_bucket_lock, RHT_LOCK_NESTED); 785 spin_lock_bh_nested(new_bucket_lock, RHT_LOCK_NESTED);
749 786
750 if (rhashtable_lookup(ht, rht_obj(ht, obj) + ht->p.key_offset)) { 787 if (rhashtable_lookup_compare(ht, rht_obj(ht, obj) + ht->p.key_offset,
788 compare, arg)) {
751 success = false; 789 success = false;
752 goto exit; 790 goto exit;
753 } 791 }
@@ -763,7 +801,7 @@ exit:
763 801
764 return success; 802 return success;
765} 803}
766EXPORT_SYMBOL_GPL(rhashtable_lookup_insert); 804EXPORT_SYMBOL_GPL(rhashtable_lookup_compare_insert);
767 805
768static size_t rounded_hashtable_size(struct rhashtable_params *params) 806static size_t rounded_hashtable_size(struct rhashtable_params *params)
769{ 807{