Skip to content

Commit 8e51830

Browse files
author
Florian Westphal
committed
netfilter: nf_tables: defer gc run if previous batch is still pending
Don't queue more gc work, else we may queue the same elements multiple times. If an element is flagged as dead, this can mean that either the previous gc request was invalidated/discarded by a transaction or that the previous request is still pending in the system work queue. The latter will happen if the gc interval is set to a very low value, e.g. 1ms, and system work queue is backlogged. The sets refcount is 1 if no previous gc requeusts are queued, so add a helper for this and skip gc run if old requests are pending. Add a helper for this and skip the gc run in this case. Fixes: f6c383b ("netfilter: nf_tables: adapt set backend to use GC transaction API") Signed-off-by: Florian Westphal <fw@strlen.de> Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent 5e1be4c commit 8e51830

File tree

3 files changed

+11
-0
lines changed

3 files changed

+11
-0
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,11 @@ static inline void *nft_set_priv(const struct nft_set *set)
587587
return (void *)set->data;
588588
}
589589

590+
static inline bool nft_set_gc_is_pending(const struct nft_set *s)
591+
{
592+
return refcount_read(&s->refs) != 1;
593+
}
594+
590595
static inline struct nft_set *nft_set_container_of(const void *priv)
591596
{
592597
return (void *)priv - offsetof(struct nft_set, data);

net/netfilter/nft_set_hash.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,9 @@ static void nft_rhash_gc(struct work_struct *work)
326326
nft_net = nft_pernet(net);
327327
gc_seq = READ_ONCE(nft_net->gc_seq);
328328

329+
if (nft_set_gc_is_pending(set))
330+
goto done;
331+
329332
gc = nft_trans_gc_alloc(set, gc_seq, GFP_KERNEL);
330333
if (!gc)
331334
goto done;

net/netfilter/nft_set_rbtree.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,9 @@ static void nft_rbtree_gc(struct work_struct *work)
611611
nft_net = nft_pernet(net);
612612
gc_seq = READ_ONCE(nft_net->gc_seq);
613613

614+
if (nft_set_gc_is_pending(set))
615+
goto done;
616+
614617
gc = nft_trans_gc_alloc(set, gc_seq, GFP_KERNEL);
615618
if (!gc)
616619
goto done;

0 commit comments

Comments
 (0)