summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuniyuki Iwashima <kuniyu@google.com>2026-02-28 22:17:26 +0000
committerJakub Kicinski <kuba@kernel.org>2026-03-02 18:49:40 -0800
commitb7fdc3cfb60a4dd80bb71c818fe433d8b3449cf3 (patch)
tree12d513400605189f18a02d2e66017d61fb11fe7e
parent3810f9529dc7f784b5b958b2a018bb6996cf9077 (diff)
downloadlinux-b7fdc3cfb60a4dd80bb71c818fe433d8b3449cf3.tar.gz
linux-b7fdc3cfb60a4dd80bb71c818fe433d8b3449cf3.zip
ipmr: Move unregister_netdevice_many() out of ipmr_free_table().
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>
-rw-r--r--net/ipv4/ipmr.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index d15e05662b09..7e2aa2026f01 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -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);
}