]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ipv6: Preallocate nhc_pcpu_rth_output in ip6_route_info_create().
authorKuniyuki Iwashima <kuniyu@amazon.com>
Fri, 18 Apr 2025 00:03:49 +0000 (17:03 -0700)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 24 Apr 2025 07:29:56 +0000 (09:29 +0200)
ip6_route_info_create_nh() will be called under RCU.

It calls fib_nh_common_init() and allocates nhc->nhc_pcpu_rth_output.

As with the reason for rt->fib6_nh->rt6i_pcpu, we want to avoid
GFP_ATOMIC allocation for nhc->nhc_pcpu_rth_output under RCU.

Let's preallocate it in ip6_route_info_create().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://patch.msgid.link/20250418000443.43734-9-kuniyu@amazon.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
net/ipv4/fib_semantics.c
net/ipv6/route.c

index f68bb9e34c34ce79c01a77a60de0940e8add07e2..5326f1501af020f976d9d4c1e99f45970ea1b2a7 100644 (file)
@@ -617,10 +617,12 @@ int fib_nh_common_init(struct net *net, struct fib_nh_common *nhc,
 {
        int err;
 
-       nhc->nhc_pcpu_rth_output = alloc_percpu_gfp(struct rtable __rcu *,
-                                                   gfp_flags);
-       if (!nhc->nhc_pcpu_rth_output)
-               return -ENOMEM;
+       if (!nhc->nhc_pcpu_rth_output) {
+               nhc->nhc_pcpu_rth_output = alloc_percpu_gfp(struct rtable __rcu *,
+                                                           gfp_flags);
+               if (!nhc->nhc_pcpu_rth_output)
+                       return -ENOMEM;
+       }
 
        if (encap) {
                struct lwtunnel_state *lwtstate;
index 1155cb0173430348fb6763ce1bdc4a985aa7bafb..3037d13043882aefe0251bd81c58976ee6f6d2cd 100644 (file)
@@ -3732,10 +3732,19 @@ void fib6_nh_release_dsts(struct fib6_nh *fib6_nh)
 
 static int fib6_nh_prealloc_percpu(struct fib6_nh *fib6_nh, gfp_t gfp_flags)
 {
+       struct fib_nh_common *nhc = &fib6_nh->nh_common;
+
        fib6_nh->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, gfp_flags);
        if (!fib6_nh->rt6i_pcpu)
                return -ENOMEM;
 
+       nhc->nhc_pcpu_rth_output = alloc_percpu_gfp(struct rtable __rcu *,
+                                                   gfp_flags);
+       if (!nhc->nhc_pcpu_rth_output) {
+               free_percpu(fib6_nh->rt6i_pcpu);
+               return -ENOMEM;
+       }
+
        return 0;
 }