Skip to content

Commit 45aad05

Browse files
committed
netfilter: nf_tables: split async and sync catchall in two functions
JIRA: https://issues.redhat.com/browse/RHEL-1720 JIRA: https://issues.redhat.com/browse/RHEL-1721 Upstream Status: nf commit 8837ba3 Conflicts: net/netfilter/nf_tables_api.c Series lacks commit 0e1ea65 ("netfilter: nf_tables: shrink memory consumption of set elements"), so we need to pass set_elem container struct instead of "elem_priv". commit 8837ba3 Author: Pablo Neira Ayuso <pablo@netfilter.org> Date: Mon Nov 13 21:13:31 2023 +0100 netfilter: nf_tables: split async and sync catchall in two functions list_for_each_entry_safe() does not work for the async case which runs under RCU, therefore, split GC logic for catchall in two functions instead, one for each of the sync and async GC variants. The catchall sync GC variant never sees a _DEAD bit set on ever, thus, this handling is removed in such case, moreover, allocate GC sync batch via GFP_KERNEL. Fixes: 93995bf ("netfilter: nf_tables: remove catchall element in GC sync path") Reported-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fwestpha@redhat.com>
1 parent 54e39cc commit 45aad05

File tree

1 file changed

+34
-28
lines changed

1 file changed

+34
-28
lines changed

net/netfilter/nf_tables_api.c

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9271,16 +9271,14 @@ void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)
92719271
call_rcu(&trans->rcu, nft_trans_gc_trans_free);
92729272
}
92739273

9274-
static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
9275-
unsigned int gc_seq,
9276-
bool sync)
9274+
struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
9275+
unsigned int gc_seq)
92779276
{
9278-
struct nft_set_elem_catchall *catchall, *next;
9277+
struct nft_set_elem_catchall *catchall;
92799278
const struct nft_set *set = gc->set;
9280-
struct nft_elem_priv *elem_priv;
92819279
struct nft_set_ext *ext;
92829280

9283-
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
9281+
list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
92849282
ext = nft_set_elem_ext(set, catchall->elem);
92859283

92869284
if (!nft_set_elem_expired(ext))
@@ -9290,41 +9288,49 @@ static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
92909288

92919289
nft_set_elem_dead(ext);
92929290
dead_elem:
9293-
if (sync)
9294-
gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
9295-
else
9296-
gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
9291+
gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
9292+
if (!gc)
9293+
return NULL;
9294+
9295+
nft_trans_gc_elem_add(gc, catchall->elem);
9296+
}
9297+
9298+
return gc;
9299+
}
92979300

9301+
struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc)
9302+
{
9303+
struct nft_set_elem_catchall *catchall, *next;
9304+
const struct nft_set *set = gc->set;
9305+
struct nft_elem_priv *elem_priv;
9306+
struct nft_set_elem elem;
9307+
struct nft_set_ext *ext;
9308+
9309+
WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net));
9310+
9311+
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
9312+
ext = nft_set_elem_ext(set, catchall->elem);
9313+
9314+
if (!nft_set_elem_expired(ext))
9315+
continue;
9316+
9317+
gc = nft_trans_gc_queue_sync(gc, GFP_KERNEL);
92989318
if (!gc)
92999319
return NULL;
93009320

93019321
elem_priv = catchall->elem;
9302-
if (sync) {
9303-
struct nft_set_elem elem = {
9304-
.priv = elem_priv,
9305-
};
93069322

9307-
nft_setelem_data_deactivate(gc->net, gc->set, &elem);
9308-
nft_setelem_catchall_destroy(catchall);
9309-
}
9323+
memset(&elem, 0, sizeof(elem));
9324+
elem.priv = catchall->elem;
93109325

9326+
nft_setelem_data_deactivate(gc->net, gc->set, &elem);
9327+
nft_setelem_catchall_destroy(catchall);
93119328
nft_trans_gc_elem_add(gc, elem_priv);
93129329
}
93139330

93149331
return gc;
93159332
}
93169333

9317-
struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
9318-
unsigned int gc_seq)
9319-
{
9320-
return nft_trans_gc_catchall(gc, gc_seq, false);
9321-
}
9322-
9323-
struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc)
9324-
{
9325-
return nft_trans_gc_catchall(gc, 0, true);
9326-
}
9327-
93289334
static void nf_tables_module_autoload_cleanup(struct net *net)
93299335
{
93309336
struct nftables_pernet *nft_net = nft_pernet(net);

0 commit comments

Comments
 (0)