summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2016-08-24 06:31:31 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2016-08-26 11:29:41 -0400
commit5ca8cc5bf11faed257c762018aea9106d529232f (patch)
treefbde5c6f8c70195e649dbb0b0f69e6a808eb37e9 /lib
parent6133740d6e80d969ff7d41098a9db1091d0f9c94 (diff)
rhashtable: add rhashtable_lookup_get_insert_key()
This patch modifies __rhashtable_insert_fast() so it returns the existing object that clashes with the one that you want to insert. In case the object is successfully inserted, NULL is returned. Otherwise, you get an error via ERR_PTR(). This patch adapts the existing callers of __rhashtable_insert_fast() so they handle this new logic, and it adds a new rhashtable_lookup_get_insert_key() interface to fetch this existing object. nf_tables needs this change to improve handling of EEXIST cases via honoring the NLM_F_EXCL flag and by checking if the data part of the mapping matches what we have. Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: Thomas Graf <tgraf@suug.ch> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'lib')
-rw-r--r--lib/rhashtable.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 5d845ffd7982..7a940d92f17e 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -438,7 +438,8 @@ EXPORT_SYMBOL_GPL(rhashtable_insert_rehash);
438struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht, 438struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht,
439 const void *key, 439 const void *key,
440 struct rhash_head *obj, 440 struct rhash_head *obj,
441 struct bucket_table *tbl) 441 struct bucket_table *tbl,
442 void **data)
442{ 443{
443 struct rhash_head *head; 444 struct rhash_head *head;
444 unsigned int hash; 445 unsigned int hash;
@@ -449,8 +450,11 @@ struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht,
449 spin_lock_nested(rht_bucket_lock(tbl, hash), SINGLE_DEPTH_NESTING); 450 spin_lock_nested(rht_bucket_lock(tbl, hash), SINGLE_DEPTH_NESTING);
450 451
451 err = -EEXIST; 452 err = -EEXIST;
452 if (key && rhashtable_lookup_fast(ht, key, ht->p)) 453 if (key) {
453 goto exit; 454 *data = rhashtable_lookup_fast(ht, key, ht->p);
455 if (*data)
456 goto exit;
457 }
454 458
455 err = -E2BIG; 459 err = -E2BIG;
456 if (unlikely(rht_grow_above_max(ht, tbl))) 460 if (unlikely(rht_grow_above_max(ht, tbl)))