]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ip6mr: Move unregister_netdevice_many() out of ip6mr_free_table().
authorKuniyuki Iwashima <kuniyu@google.com>
Thu, 4 Jun 2026 22:46:29 +0000 (22:46 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 9 Jun 2026 00:06:24 +0000 (17:06 -0700)
This is a prep commit to convert ip6mr_net_exit_batch() to
->exit_rtnl().

Let's move unregister_netdevice_many() in ip6mr_free_table()
to its callers.

Now ip6mr_rules_exit() can do batching all tables per netns.

Note that later we will remove RTNL and unregister_netdevice_many()
in ip6mr_rules_init().

Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20260604224712.3209821-12-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv6/ip6mr.c

index b5da94c9f074e012fb17706959dfddc05b55c47f..f531c4a24ea13b36474575a58ed747187ad9ef48 100644 (file)
@@ -85,7 +85,8 @@ static DEFINE_SPINLOCK(mfc_unres_lock);
 static struct kmem_cache *mrt_cachep __read_mostly;
 
 static struct mr_table *ip6mr_new_table(struct net *net, u32 id);
-static void ip6mr_free_table(struct mr_table *mrt);
+static void ip6mr_free_table(struct mr_table *mrt,
+                            struct list_head *dev_kill_list);
 
 static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
                           struct net_device *dev, struct sk_buff *skb,
@@ -228,6 +229,7 @@ static const struct fib_rules_ops __net_initconst ip6mr_rules_ops_template = {
 static int __net_init ip6mr_rules_init(struct net *net)
 {
        struct fib_rules_ops *ops;
+       LIST_HEAD(dev_kill_list);
        struct mr_table *mrt;
        int err;
 
@@ -252,7 +254,8 @@ static int __net_init ip6mr_rules_init(struct net *net)
 
 err2:
        rtnl_lock();
-       ip6mr_free_table(mrt);
+       ip6mr_free_table(mrt, &dev_kill_list);
+       unregister_netdevice_many(&dev_kill_list);
        rtnl_unlock();
 err1:
        fib_rules_unregister(ops);
@@ -267,12 +270,15 @@ 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, *next;
+       LIST_HEAD(dev_kill_list);
 
        ASSERT_RTNL();
        list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
                list_del_rcu(&mrt->list);
-               ip6mr_free_table(mrt);
+               ip6mr_free_table(mrt, &dev_kill_list);
        }
+
+       unregister_netdevice_many(&dev_kill_list);
 }
 
 static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb,
@@ -339,11 +345,13 @@ 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);
+       LIST_HEAD(dev_kill_list);
 
        ASSERT_RTNL();
 
        RCU_INIT_POINTER(net->ipv6.mrt6, NULL);
-       ip6mr_free_table(mrt);
+       ip6mr_free_table(mrt, &dev_kill_list);
+       unregister_netdevice_many(&dev_kill_list);
 }
 
 static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb,
@@ -418,18 +426,17 @@ static struct mr_table *ip6mr_new_table(struct net *net, u32 id)
                              ipmr_expire_process, ip6mr_new_table_set);
 }
 
-static void ip6mr_free_table(struct mr_table *mrt)
+static void ip6mr_free_table(struct mr_table *mrt,
+                            struct list_head *dev_kill_list)
 {
        struct net *net = read_pnet(&mrt->net);
-       LIST_HEAD(dev_kill_list);
 
        WARN_ON_ONCE(!mr_can_free_table(net));
 
        timer_shutdown_sync(&mrt->ipmr_expire_timer);
        mroute_clean_tables(mrt, MRT6_FLUSH_MIFS | MRT6_FLUSH_MIFS_STATIC |
                            MRT6_FLUSH_MFC | MRT6_FLUSH_MFC_STATIC,
-                           &dev_kill_list);
-       unregister_netdevice_many(&dev_kill_list);
+                           dev_kill_list);
 
        mr_table_free(mrt);
 }