diff options
author | Eric Dumazet <edumazet@google.com> | 2022-02-07 20:50:32 -0800 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2022-02-08 20:41:33 -0800 |
commit | 1c69576461435521b020cf0e6475b7524c1394dd (patch) | |
tree | df3596479d0b4e22477c1899c9aa33274a9ec99b | |
parent | fea7b201320ca222d532398685d23db2b8d55558 (diff) | |
download | linux-next-1c69576461435521b020cf0e6475b7524c1394dd.tar.gz |
ipv4: add fib_net_exit_batch()
cleanup_net() is competing with other rtnl users.
Instead of acquiring rtnl at each fib_net_exit() invocation,
add fib_net_exit_batch() so that rtnl is acquired once.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r-- | net/ipv4/fib_frontend.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index c60e1d1ed2b0..54811728d906 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -1556,7 +1556,7 @@ static void ip_fib_net_exit(struct net *net) { int i; - rtnl_lock(); + ASSERT_RTNL(); #ifdef CONFIG_IP_MULTIPLE_TABLES RCU_INIT_POINTER(net->ipv4.fib_main, NULL); RCU_INIT_POINTER(net->ipv4.fib_default, NULL); @@ -1581,7 +1581,7 @@ static void ip_fib_net_exit(struct net *net) #ifdef CONFIG_IP_MULTIPLE_TABLES fib4_rules_exit(net); #endif - rtnl_unlock(); + kfree(net->ipv4.fib_table_hash); fib4_notifier_exit(net); } @@ -1608,7 +1608,9 @@ out: out_proc: nl_fib_lookup_exit(net); out_nlfl: + rtnl_lock(); ip_fib_net_exit(net); + rtnl_unlock(); goto out; } @@ -1616,12 +1618,23 @@ static void __net_exit fib_net_exit(struct net *net) { fib_proc_exit(net); nl_fib_lookup_exit(net); - ip_fib_net_exit(net); +} + +static void __net_exit fib_net_exit_batch(struct list_head *net_list) +{ + struct net *net; + + rtnl_lock(); + list_for_each_entry(net, net_list, exit_list) + ip_fib_net_exit(net); + + rtnl_unlock(); } static struct pernet_operations fib_net_ops = { .init = fib_net_init, .exit = fib_net_exit, + .exit_batch = fib_net_exit_batch, }; void __init ip_fib_init(void) |