diff options
author | Thomas Graf <tgraf@suug.ch> | 2015-03-24 13:18:20 (GMT) |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-24 21:48:40 (GMT) |
commit | 6b6f302ceda7a052dab545d6c69abf5f0d4a6cab (patch) | |
tree | 8464850fd94dba0dfa34c75c46dfb3fcf4c3c381 /net | |
parent | b5e2c150ac914f28a28833b57397bec0b0a2bd5f (diff) | |
download | linux-6b6f302ceda7a052dab545d6c69abf5f0d4a6cab.tar.xz |
rhashtable: Add rhashtable_free_and_destroy()
rhashtable_destroy() variant which stops rehashes, iterates over
the table and calls a callback to release resources.
Avoids need for nft_hash to embed rhashtable internals and allows to
get rid of the being_destroyed flag. It also saves a 2nd mutex
lock upon destruction.
Also fixes an RCU lockdep splash on nft set destruction due to
calling rht_for_each_entry_safe() without holding bucket locks.
Open code this loop as we need know that no mutations may occur in
parallel.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nft_hash.c | 25 |
1 files changed, 7 insertions, 18 deletions
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index 8577a37..f9ce219 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c @@ -188,26 +188,15 @@ static int nft_hash_init(const struct nft_set *set, return rhashtable_init(priv, ¶ms); } -static void nft_hash_destroy(const struct nft_set *set) +static void nft_free_element(void *ptr, void *arg) { - struct rhashtable *priv = nft_set_priv(set); - const struct bucket_table *tbl; - struct nft_hash_elem *he; - struct rhash_head *pos, *next; - unsigned int i; - - /* Stop an eventual async resizing */ - priv->being_destroyed = true; - mutex_lock(&priv->mutex); - - tbl = rht_dereference(priv->tbl, priv); - for (i = 0; i < tbl->size; i++) { - rht_for_each_entry_safe(he, pos, next, tbl, i, node) - nft_hash_elem_destroy(set, he); - } - mutex_unlock(&priv->mutex); + nft_hash_elem_destroy((const struct nft_set *)arg, ptr); +} - rhashtable_destroy(priv); +static void nft_hash_destroy(const struct nft_set *set) +{ + rhashtable_free_and_destroy(nft_set_priv(set), nft_free_element, + (void *)set); } static bool nft_hash_estimate(const struct nft_set_desc *desc, u32 features, |