[PATCH net-next] net: lwtunnel: use GFP_KERNEL in build_state paths
From: Max Boone
Date: Fri Nov 06 2026 - 06:59:31 EST
Since 3d25eabbbf67 ("ip_tunnel: Add dst_cache support in lwtunnel_state
of ip tunnel"), build_state runs outside RCU and all its callers can
sleep, but paths still use GFP_ATOMIC.
For dst caches, that limits allocation to populated percpu pages. A
large burst of SRv6 nexthops outruns the refill worker and will fail
with -ENOMEM despite there being free memory:
percpu: allocation failed, size=40 align=8 atomic=1, atomic alloc
failed, no space left
Batching 20000 RTM_NEWNEXTHOP under QEMU gave 10-109 failures per run
before, none after.
This commit converts the allocations reached through ops->build_state()
and are called after the rcu_read_unlock():
- ila_build_state(), ioam6_build_state(), rpl_build_state(),
seg6_build_state(): build_state ops
- bpf_parse_prog(): only called from bpf_build_state()
- lwtunnel_state_alloc(): only called from build_state ops (also
affects mpls, ip/ip6 tunnel, xfrmi and seg6_local)
Signed-off-by: Max Boone <mboone@xxxxxxxxxx>
Reviewed-by: Debabrata Banerjee <dbanerje@xxxxxxxxxx>
Reviewed-by: Nick Hudson <nhudson@xxxxxxxxxx>
---
net/core/lwt_bpf.c | 2 +-
net/core/lwtunnel.c | 2 +-
net/ipv6/ila/ila_lwt.c | 2 +-
net/ipv6/ioam6_iptunnel.c | 2 +-
net/ipv6/rpl_iptunnel.c | 2 +-
net/ipv6/seg6_iptunnel.c | 4 ++--
6 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c
index da49364ec63d..6d1059ff0c49 100644
--- a/net/core/lwt_bpf.c
+++ b/net/core/lwt_bpf.c
@@ -359,7 +359,7 @@ static int bpf_parse_prog(struct nlattr *attr, struct bpf_lwt_prog *prog,
if (!tb[LWT_BPF_PROG_FD] || !tb[LWT_BPF_PROG_NAME])
return -EINVAL;
- prog->name = nla_memdup(tb[LWT_BPF_PROG_NAME], GFP_ATOMIC);
+ prog->name = nla_memdup(tb[LWT_BPF_PROG_NAME], GFP_KERNEL);
if (!prog->name)
return -ENOMEM;
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index 8223c44f10c8..f2f4d1ace0e9 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -70,7 +70,7 @@ struct lwtunnel_state *lwtunnel_state_alloc(int encap_len)
{
struct lwtunnel_state *lws;
- lws = kzalloc(sizeof(*lws) + encap_len, GFP_ATOMIC);
+ lws = kzalloc(sizeof(*lws) + encap_len, GFP_KERNEL);
return lws;
}
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index 7bb9edc5c28c..01fd78a232e7 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -228,7 +228,7 @@ static int ila_build_state(struct net *net, struct nlattr *nla,
return -ENOMEM;
ilwt = ila_lwt_lwtunnel(newts);
- ret = dst_cache_init(&ilwt->dst_cache, GFP_ATOMIC);
+ ret = dst_cache_init(&ilwt->dst_cache, GFP_KERNEL);
if (ret) {
kfree(newts);
return ret;
diff --git a/net/ipv6/ioam6_iptunnel.c b/net/ipv6/ioam6_iptunnel.c
index cfb2c41634a0..3093446ad89a 100644
--- a/net/ipv6/ioam6_iptunnel.c
+++ b/net/ipv6/ioam6_iptunnel.c
@@ -166,7 +166,7 @@ static int ioam6_build_state(struct net *net, struct nlattr *nla,
return -ENOMEM;
ilwt = ioam6_lwt_state(lwt);
- err = dst_cache_init(&ilwt->cache, GFP_ATOMIC);
+ err = dst_cache_init(&ilwt->cache, GFP_KERNEL);
if (err)
goto free_lwt;
diff --git a/net/ipv6/rpl_iptunnel.c b/net/ipv6/rpl_iptunnel.c
index 4e10adcd70e8..838ede10a79d 100644
--- a/net/ipv6/rpl_iptunnel.c
+++ b/net/ipv6/rpl_iptunnel.c
@@ -102,7 +102,7 @@ static int rpl_build_state(struct net *net, struct nlattr *nla,
rlwt = rpl_lwt_lwtunnel(newts);
- err = dst_cache_init(&rlwt->cache, GFP_ATOMIC);
+ err = dst_cache_init(&rlwt->cache, GFP_KERNEL);
if (err) {
kfree(newts);
return err;
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index 0d39a38a5dd2..7c64680e4632 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -833,11 +833,11 @@ static int seg6_build_state(struct net *net, struct nlattr *nla,
slwt = seg6_lwt_lwtunnel(newts);
- err = dst_cache_init(&slwt->cache_input, GFP_ATOMIC);
+ err = dst_cache_init(&slwt->cache_input, GFP_KERNEL);
if (err)
goto err_free_newts;
- err = dst_cache_init(&slwt->cache_output, GFP_ATOMIC);
+ err = dst_cache_init(&slwt->cache_output, GFP_KERNEL);
if (err)
goto err_destroy_input;
---
base-commit: 0822d2fe38262e8b55c5ea55c970022bca8dd2a9
change-id: 20261105-build-state-use-gfp-kernel-c3598d190bfb
Best regards,
--
Max Boone <mboone@xxxxxxxxxx>