]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ip6mr: Call fib_rules_unregister() without RTNL.
authorKuniyuki Iwashima <kuniyu@google.com>
Thu, 4 Jun 2026 22:46:27 +0000 (22:46 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 9 Jun 2026 00:06:23 +0000 (17:06 -0700)
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 <kuniyu@google.com>
Link: https://patch.msgid.link/20260604224712.3209821-10-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv6/ip6mr.c

index ddbe06397d9c5c7799c8573fc00d78daaca3a99a..bb613331ead27faa7c030069c5e3a0568261411f 100644 (file)
@@ -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();
 }