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

ipmr: Move unregister_netdevice_many() out of mroute_clean_tables().



This is a prep commit to convert ipmr_net_exit_batch() to
->exit_rtnl().

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

As a bonus, mrtsock_destruct() can do batching for all tables.

Signed-off-by: default avatarKuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260228221800.1082070-8-kuniyu@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 2c698bab
Loading
Loading
Loading
Loading
+24 −10
Original line number Diff line number Diff line
@@ -112,7 +112,8 @@ static int ipmr_cache_report(const struct mr_table *mrt,
static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc,
				 int cmd);
static void igmpmsg_netlink_event(const struct mr_table *mrt, struct sk_buff *pkt);
static void mroute_clean_tables(struct mr_table *mrt, int flags);
static void mroute_clean_tables(struct mr_table *mrt, int flags,
				struct list_head *dev_kill_list);
static void ipmr_expire_process(struct timer_list *t);

#ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
@@ -427,12 +428,15 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
static void ipmr_free_table(struct mr_table *mrt)
{
	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);
			    MRT_FLUSH_MFC | MRT_FLUSH_MFC_STATIC,
			    &dev_kill_list);
	unregister_netdevice_many(&dev_kill_list);
	rhltable_destroy(&mrt->mfc_hash);
	kfree(mrt);
}
@@ -1293,12 +1297,12 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
}

/* Close the multicast socket, and clear the vif tables etc */
static void mroute_clean_tables(struct mr_table *mrt, int flags)
static void mroute_clean_tables(struct mr_table *mrt, int flags,
				struct list_head *dev_kill_list)
{
	struct net *net = read_pnet(&mrt->net);
	struct mr_mfc *c, *tmp;
	struct mfc_cache *cache;
	LIST_HEAD(list);
	struct mr_mfc *c, *tmp;
	int i;

	/* Shut down all active vif entries */
@@ -1308,9 +1312,8 @@ static void mroute_clean_tables(struct mr_table *mrt, int flags)
			     !(flags & MRT_FLUSH_VIFS_STATIC)) ||
			    (!(mrt->vif_table[i].flags & VIFF_STATIC) && !(flags & MRT_FLUSH_VIFS)))
				continue;
			vif_delete(mrt, i, 0, &list);
			vif_delete(mrt, i, 0, dev_kill_list);
		}
		unregister_netdevice_many(&list);
	}

	/* Wipe the cache */
@@ -1349,9 +1352,11 @@ static void mroute_clean_tables(struct mr_table *mrt, int flags)
static void mrtsock_destruct(struct sock *sk)
{
	struct net *net = sock_net(sk);
	LIST_HEAD(dev_kill_list);
	struct mr_table *mrt;

	rtnl_lock();

	ipmr_for_each_table(mrt, net) {
		if (sk == rtnl_dereference(mrt->mroute_sk)) {
			IPV4_DEVCONF_ALL(net, MC_FORWARDING)--;
@@ -1360,9 +1365,13 @@ static void mrtsock_destruct(struct sock *sk)
						    NETCONFA_IFINDEX_ALL,
						    net->ipv4.devconf_all);
			RCU_INIT_POINTER(mrt->mroute_sk, NULL);
			mroute_clean_tables(mrt, MRT_FLUSH_VIFS | MRT_FLUSH_MFC);
			mroute_clean_tables(mrt, MRT_FLUSH_VIFS | MRT_FLUSH_MFC,
					    &dev_kill_list);
		}
	}

	unregister_netdevice_many(&dev_kill_list);

	rtnl_unlock();
}

@@ -1485,7 +1494,9 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
					   sk == rtnl_dereference(mrt->mroute_sk),
					   parent);
		break;
	case MRT_FLUSH:
	case MRT_FLUSH: {
		LIST_HEAD(dev_kill_list);

		if (optlen != sizeof(val)) {
			ret = -EINVAL;
			break;
@@ -1494,8 +1505,11 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
			ret = -EFAULT;
			break;
		}
		mroute_clean_tables(mrt, val);

		mroute_clean_tables(mrt, val, &dev_kill_list);
		unregister_netdevice_many(&dev_kill_list);
		break;
	}
	/* Control PIM assert. */
	case MRT_ASSERT:
		if (optlen != sizeof(val)) {