Commit e2f736b7 authored by Eric Dumazet's avatar Eric Dumazet Committed by Jakub Kicinski

ip6mr: introduce ip6mr_net_exit_batch()

cleanup_net() is competing with other rtnl users.

Avoiding to acquire rtnl for each netns before calling
ip6mr_rules_exit() gives chance for cleanup_net()
to progress much faster, holding rtnl a bit longer.
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarDavid Ahern <dsahern@kernel.org>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent ea3e9166
...@@ -253,13 +253,12 @@ static void __net_exit ip6mr_rules_exit(struct net *net) ...@@ -253,13 +253,12 @@ static void __net_exit ip6mr_rules_exit(struct net *net)
{ {
struct mr_table *mrt, *next; struct mr_table *mrt, *next;
rtnl_lock(); ASSERT_RTNL();
list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) { list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
list_del(&mrt->list); list_del(&mrt->list);
ip6mr_free_table(mrt); ip6mr_free_table(mrt);
} }
fib_rules_unregister(net->ipv6.mr6_rules_ops); fib_rules_unregister(net->ipv6.mr6_rules_ops);
rtnl_unlock();
} }
static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb, static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb,
...@@ -316,10 +315,9 @@ static int __net_init ip6mr_rules_init(struct net *net) ...@@ -316,10 +315,9 @@ static int __net_init ip6mr_rules_init(struct net *net)
static void __net_exit ip6mr_rules_exit(struct net *net) static void __net_exit ip6mr_rules_exit(struct net *net)
{ {
rtnl_lock(); ASSERT_RTNL();
ip6mr_free_table(net->ipv6.mrt6); ip6mr_free_table(net->ipv6.mrt6);
net->ipv6.mrt6 = NULL; net->ipv6.mrt6 = NULL;
rtnl_unlock();
} }
static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb, static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb,
...@@ -1323,7 +1321,9 @@ static int __net_init ip6mr_net_init(struct net *net) ...@@ -1323,7 +1321,9 @@ static int __net_init ip6mr_net_init(struct net *net)
proc_cache_fail: proc_cache_fail:
remove_proc_entry("ip6_mr_vif", net->proc_net); remove_proc_entry("ip6_mr_vif", net->proc_net);
proc_vif_fail: proc_vif_fail:
rtnl_lock();
ip6mr_rules_exit(net); ip6mr_rules_exit(net);
rtnl_unlock();
#endif #endif
ip6mr_rules_fail: ip6mr_rules_fail:
ip6mr_notifier_exit(net); ip6mr_notifier_exit(net);
...@@ -1336,13 +1336,23 @@ static void __net_exit ip6mr_net_exit(struct net *net) ...@@ -1336,13 +1336,23 @@ static void __net_exit ip6mr_net_exit(struct net *net)
remove_proc_entry("ip6_mr_cache", net->proc_net); remove_proc_entry("ip6_mr_cache", net->proc_net);
remove_proc_entry("ip6_mr_vif", net->proc_net); remove_proc_entry("ip6_mr_vif", net->proc_net);
#endif #endif
ip6mr_rules_exit(net);
ip6mr_notifier_exit(net); ip6mr_notifier_exit(net);
} }
static void __net_exit ip6mr_net_exit_batch(struct list_head *net_list)
{
struct net *net;
rtnl_lock();
list_for_each_entry(net, net_list, exit_list)
ip6mr_rules_exit(net);
rtnl_unlock();
}
static struct pernet_operations ip6mr_net_ops = { static struct pernet_operations ip6mr_net_ops = {
.init = ip6mr_net_init, .init = ip6mr_net_init,
.exit = ip6mr_net_exit, .exit = ip6mr_net_exit,
.exit_batch = ip6mr_net_exit_batch,
}; };
int __init ip6_mr_init(void) int __init ip6_mr_init(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment