OSDN Git Service

net/sysctl: avoid two synchronize_rcu() calls
authorEric Dumazet <edumazet@google.com>
Fri, 25 Feb 2022 16:18:55 +0000 (08:18 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Feb 2022 11:40:47 +0000 (11:40 +0000)
Both rps_sock_flow_sysctl() and flow_limit_cpu_sysctl()
are using synchronize_rcu() right before freeing memory
either by vfree() or kfree()

They can switch to kvfree_rcu(ptr) and kfree_rcu(ptr) to benefit
from asynchronous mode, instead of blocking the current thread.

Note that kvfree_rcu(ptr) and kfree_rcu(ptr) eventually can
have to use synchronize_rcu() in some memory pressure cases.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/sysctl_net_core.c

index dbeb8ec..7123fe7 100644 (file)
@@ -103,8 +103,7 @@ static int rps_sock_flow_sysctl(struct ctl_table *table, int write,
                        if (orig_sock_table) {
                                static_branch_dec(&rps_needed);
                                static_branch_dec(&rfs_needed);
-                               synchronize_rcu();
-                               vfree(orig_sock_table);
+                               kvfree_rcu(orig_sock_table);
                        }
                }
        }
@@ -142,8 +141,7 @@ static int flow_limit_cpu_sysctl(struct ctl_table *table, int write,
                                     lockdep_is_held(&flow_limit_update_mutex));
                        if (cur && !cpumask_test_cpu(i, mask)) {
                                RCU_INIT_POINTER(sd->flow_limit, NULL);
-                               synchronize_rcu();
-                               kfree(cur);
+                               kfree_rcu(cur);
                        } else if (!cur && cpumask_test_cpu(i, mask)) {
                                cur = kzalloc_node(len, GFP_KERNEL,
                                                   cpu_to_node(i));