@@ -5261,6 +5261,10 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
static void nft_set_put(struct nft_set *set)
{
if (refcount_dec_and_test(&set->refs)) {
+ unsigned int nelems = atomic_read(&set->nelems);
+
+ WARN(nelems, "set %s (%ps) has element count of %u\n",
+ set->name, set->ops->lookup, nelems);
kfree(set->name);
kvfree(set);
}
@@ -9663,6 +9667,7 @@ static void nft_trans_gc_trans_free(struct rcu_head *rcu)
if (!nft_setelem_is_catchall(trans->set, elem_priv))
atomic_dec(&trans->set->nelems);
+ WARN_ON_ONCE(atomic_read(&trans->set->nelems) < 0);
nf_tables_set_elem_destroy(&ctx, trans->set, elem_priv);
}
@@ -275,9 +275,12 @@ static void nft_bitmap_destroy(const struct nft_ctx *ctx,
{
struct nft_bitmap *priv = nft_set_priv(set);
struct nft_bitmap_elem *be, *n;
+ struct nft_set *mset = (void *)set;
- list_for_each_entry_safe(be, n, &priv->list, head)
+ list_for_each_entry_safe(be, n, &priv->list, head) {
nf_tables_set_elem_destroy(ctx, set, &be->priv);
+ atomic_dec(&mset->nelems);
+ }
}
static bool nft_bitmap_estimate(const struct nft_set_desc *desc, u32 features,
@@ -438,8 +438,12 @@ static void nft_rhash_elem_destroy(void *ptr, void *arg)
{
struct nft_rhash_ctx *rhash_ctx = arg;
struct nft_rhash_elem *he = ptr;
+ struct nft_set *set;
nf_tables_set_elem_destroy(&rhash_ctx->ctx, rhash_ctx->set, &he->priv);
+
+ set = (struct nft_set *)rhash_ctx->set;
+ atomic_dec(&set->nelems);
}
static void nft_rhash_destroy(const struct nft_ctx *ctx,
@@ -688,6 +692,7 @@ static int nft_hash_init(const struct nft_set *set,
static void nft_hash_destroy(const struct nft_ctx *ctx,
const struct nft_set *set)
{
+ struct nft_set *mset = (struct nft_set *)set;
struct nft_hash *priv = nft_set_priv(set);
struct nft_hash_elem *he;
struct hlist_node *next;
@@ -697,6 +702,7 @@ static void nft_hash_destroy(const struct nft_ctx *ctx,
hlist_for_each_entry_safe(he, next, &priv->table[i], node) {
hlist_del_rcu(&he->node);
nf_tables_set_elem_destroy(ctx, set, &he->priv);
+ atomic_dec(&mset->nelems);
}
}
}
@@ -2295,6 +2295,7 @@ static void nft_set_pipapo_match_destroy(const struct nft_ctx *ctx,
const struct nft_set *set,
struct nft_pipapo_match *m)
{
+ struct nft_set *mset = (void *)set;
struct nft_pipapo_field *f;
unsigned int i, r;
@@ -2310,6 +2311,7 @@ static void nft_set_pipapo_match_destroy(const struct nft_ctx *ctx,
e = f->mt[r].e;
nf_tables_set_elem_destroy(ctx, set, &e->priv);
+ atomic_dec(&mset->nelems);
}
}
@@ -709,6 +709,7 @@ static void nft_rbtree_destroy(const struct nft_ctx *ctx,
const struct nft_set *set)
{
struct nft_rbtree *priv = nft_set_priv(set);
+ struct nft_set *mset = (void *)set;
struct nft_rbtree_elem *rbe;
struct rb_node *node;
@@ -716,6 +717,7 @@ static void nft_rbtree_destroy(const struct nft_ctx *ctx,
rb_erase(node, &priv->root);
rbe = rb_entry(node, struct nft_rbtree_elem, node);
nf_tables_set_elem_destroy(ctx, set, &rbe->priv);
+ atomic_dec(&mset->nelems);
}
}
Not a bug fix, idea is that this allows us to add runtime assertions, when set is free'd counter should be 0 as well. Signed-off-by: Florian Westphal <fw@strlen.de> --- net/netfilter/nf_tables_api.c | 5 +++++ net/netfilter/nft_set_bitmap.c | 5 ++++- net/netfilter/nft_set_hash.c | 6 ++++++ net/netfilter/nft_set_pipapo.c | 2 ++ net/netfilter/nft_set_rbtree.c | 2 ++ 5 files changed, 19 insertions(+), 1 deletion(-)