From: Kuniyuki Iwashima Date: Thu, 4 Jun 2026 22:46:27 +0000 (+0000) Subject: ip6mr: Call fib_rules_unregister() without RTNL. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4becf012467511e9f3e21b641054f85711f4e187;p=thirdparty%2Flinux.git ip6mr: Call fib_rules_unregister() without RTNL. fib_rules_unregister() removes ops from net->rules_ops under spinlock, calls ops->delete() for each rule, and frees the ops. ip6mr_rules_ops_template does not have ->delete(), and any operation does not require RTNL there. Let's move fib_rules_unregister() from ip6mr_rules_exit() to ip6mr_net_exit(). Signed-off-by: Kuniyuki Iwashima Link: https://patch.msgid.link/20260604224712.3209821-10-kuniyu@google.com Signed-off-by: Jakub Kicinski --- diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index ddbe06397d9c5..bb613331ead27 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -259,6 +259,11 @@ err1: } static void __net_exit ip6mr_rules_exit(struct net *net) +{ + fib_rules_unregister(net->ipv6.mr6_rules_ops); +} + +static void __net_exit ip6mr_rules_exit_rtnl(struct net *net) { struct mr_table *mrt, *next; @@ -267,7 +272,6 @@ static void __net_exit ip6mr_rules_exit(struct net *net) list_del_rcu(&mrt->list); ip6mr_free_table(mrt); } - fib_rules_unregister(net->ipv6.mr6_rules_ops); } static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb, @@ -328,6 +332,10 @@ 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_rtnl(struct net *net) { struct mr_table *mrt = rcu_dereference_protected(net->ipv6.mrt6, 1); @@ -1366,8 +1374,9 @@ proc_cache_fail: remove_proc_entry("ip6_mr_vif", net->proc_net); proc_vif_fail: rtnl_lock(); - ip6mr_rules_exit(net); + ip6mr_rules_exit_rtnl(net); rtnl_unlock(); + ip6mr_rules_exit(net); #endif ip6mr_rules_fail: ip6mr_notifier_exit(net); @@ -1380,6 +1389,7 @@ static void __net_exit ip6mr_net_exit(struct net *net) remove_proc_entry("ip6_mr_cache", net->proc_net); remove_proc_entry("ip6_mr_vif", net->proc_net); #endif + ip6mr_rules_exit(net); ip6mr_notifier_exit(net); } @@ -1389,7 +1399,7 @@ static void __net_exit ip6mr_net_exit_batch(struct list_head *net_list) rtnl_lock(); list_for_each_entry(net, net_list, exit_list) - ip6mr_rules_exit(net); + ip6mr_rules_exit_rtnl(net); rtnl_unlock(); }