]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ipmr: Move unregister_netdevice_many() out of ipmr_free_table().
authorKuniyuki Iwashima <kuniyu@google.com>
Sat, 28 Feb 2026 22:17:26 +0000 (22:17 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 3 Mar 2026 02:49:40 +0000 (18:49 -0800)
This is a prep commit to convert ipmr_net_exit_batch() to
->exit_rtnl().

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

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

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

Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260228221800.1082070-9-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv4/ipmr.c

index d15e05662b0905cef676d9dabad7c43c490c0556..7e2aa2026f01ed2f03b97505e2ed9cd0a59b2035 100644 (file)
@@ -102,7 +102,8 @@ static DEFINE_SPINLOCK(mfc_unres_lock);
 static struct kmem_cache *mrt_cachep __ro_after_init;
 
 static struct mr_table *ipmr_new_table(struct net *net, u32 id);
-static void ipmr_free_table(struct mr_table *mrt);
+static void ipmr_free_table(struct mr_table *mrt,
+                           struct list_head *dev_kill_list);
 
 static void ip_mr_forward(struct net *net, struct mr_table *mrt,
                          struct net_device *dev, struct sk_buff *skb,
@@ -251,6 +252,7 @@ static const struct fib_rules_ops __net_initconst ipmr_rules_ops_template = {
 static int __net_init ipmr_rules_init(struct net *net)
 {
        struct fib_rules_ops *ops;
+       LIST_HEAD(dev_kill_list);
        struct mr_table *mrt;
        int err;
 
@@ -275,7 +277,8 @@ static int __net_init ipmr_rules_init(struct net *net)
 
 err2:
        rtnl_lock();
-       ipmr_free_table(mrt);
+       ipmr_free_table(mrt, &dev_kill_list);
+       unregister_netdevice_many(&dev_kill_list);
        rtnl_unlock();
 err1:
        fib_rules_unregister(ops);
@@ -285,12 +288,15 @@ err1:
 static void __net_exit ipmr_rules_exit(struct net *net)
 {
        struct mr_table *mrt, *next;
+       LIST_HEAD(dev_kill_list);
 
        ASSERT_RTNL();
        list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) {
                list_del(&mrt->list);
-               ipmr_free_table(mrt);
+               ipmr_free_table(mrt, &dev_kill_list);
        }
+
+       unregister_netdevice_many(&dev_kill_list);
        fib_rules_unregister(net->ipv4.mr_rules_ops);
 }
 
@@ -349,8 +355,13 @@ static int __net_init ipmr_rules_init(struct net *net)
 
 static void __net_exit ipmr_rules_exit(struct net *net)
 {
+       LIST_HEAD(dev_kill_list);
+
        ASSERT_RTNL();
-       ipmr_free_table(net->ipv4.mrt);
+
+       ipmr_free_table(net->ipv4.mrt, &dev_kill_list);
+       unregister_netdevice_many(&dev_kill_list);
+
        net->ipv4.mrt = NULL;
 }
 
@@ -425,18 +436,16 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
                              ipmr_expire_process, ipmr_new_table_set);
 }
 
-static void ipmr_free_table(struct mr_table *mrt)
+static void ipmr_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, MRT_FLUSH_VIFS | MRT_FLUSH_VIFS_STATIC |
                            MRT_FLUSH_MFC | MRT_FLUSH_MFC_STATIC,
-                           &dev_kill_list);
-       unregister_netdevice_many(&dev_kill_list);
+                           dev_kill_list);
        rhltable_destroy(&mrt->mfc_hash);
        kfree(mrt);
 }