Commit b7fdc3cf authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by Jakub Kicinski
Browse files

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: default avatarKuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260228221800.1082070-9-kuniyu@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 3810f952
Loading
Loading
Loading
Loading
+17 −8
Original line number Diff line number Diff line
@@ -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 @@ static int __net_init ipmr_rules_init(struct net *net)
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);
}