netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl().
@ 2025-04-11 20:52 Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 01/14] net: Factorise setup_net() and cleanup_net() Kuniyuki Iwashima
                   ` (15 more replies)
  0 siblings, 16 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

While converting nexthop to per-netns RTNL, there are two blockers
to using rtnl_net_dereference(), flush_all_nexthops() and
__unregister_nexthop_notifier(), both of which are called from
->exit_batch_rtnl().

Instead of spreading __rtnl_net_lock() over each ->exit_batch_rtnl(),
we should convert all ->exit_batch_rtnl() to per-net ->exit_rtnl() and
run it under __rtnl_net_lock() because all ->exit_batch_rtnl() functions
do not have anything to factor out for batching.

Patch 1 & 2 factorise the undo mechanism against ->init() into a single
function, and Patch 3 adds ->exit_batch_rtnl().

Patch 4 ~ 13 convert all ->exit_batch_rtnl() users.

Patch 14 removes ->exit_batch_rtnl().

Later, we can convert pfcp and ppp to use ->exit_rtnl().


v2:
  * Collect tags
  * Patch2
    * Convert free_exit_list() under CONFIG_NET_NS=n

v1: https://lore.kernel.org/all/20250410022004.8668-1-kuniyu@amazon.com/


Kuniyuki Iwashima (14):
  net: Factorise setup_net() and cleanup_net().
  net: Add ops_undo_single for module load/unload.
  net: Add ->exit_rtnl() hook to struct pernet_operations.
  nexthop: Convert nexthop_net_exit_batch_rtnl() to ->exit_rtnl().
  vxlan: Convert vxlan_exit_batch_rtnl() to ->exit_rtnl().
  ipv4: ip_tunnel: Convert ip_tunnel_delete_nets() callers to
    ->exit_rtnl().
  ipv6: Convert tunnel devices' ->exit_batch_rtnl() to ->exit_rtnl().
  xfrm: Convert xfrmi_exit_batch_rtnl() to ->exit_rtnl().
  bridge: Convert br_net_exit_batch_rtnl() to ->exit_rtnl().
  bonding: Convert bond_net_exit_batch_rtnl() to ->exit_rtnl().
  gtp: Convert gtp_net_exit_batch_rtnl() to ->exit_rtnl().
  bareudp: Convert bareudp_exit_batch_rtnl() to ->exit_rtnl().
  geneve: Convert geneve_exit_batch_rtnl() to ->exit_rtnl().
  net: Remove ->exit_batch_rtnl().

 drivers/net/bareudp.c           |  16 +--
 drivers/net/bonding/bond_main.c |  23 ++--
 drivers/net/geneve.c            |  16 +--
 drivers/net/gtp.c               |  18 ++--
 drivers/net/vxlan/vxlan_core.c  |  18 ++--
 include/net/ip_tunnels.h        |   7 +-
 include/net/net_namespace.h     |   4 +-
 net/bridge/br.c                 |  17 ++-
 net/core/net_namespace.c        | 181 +++++++++++++++++---------------
 net/ipv4/ip_gre.c               |  27 +++--
 net/ipv4/ip_tunnel.c            |  25 ++---
 net/ipv4/ip_vti.c               |   9 +-
 net/ipv4/ipip.c                 |   9 +-
 net/ipv4/nexthop.c              |  13 +--
 net/ipv6/ip6_gre.c              |  22 ++--
 net/ipv6/ip6_tunnel.c           |  24 ++---
 net/ipv6/ip6_vti.c              |  27 ++---
 net/ipv6/sit.c                  |  23 ++--
 net/xfrm/xfrm_interface_core.c  |  34 +++---
 19 files changed, 213 insertions(+), 300 deletions(-)

-- 
2.49.0


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 01/14] net: Factorise setup_net() and cleanup_net().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 02/14] net: Add ops_undo_single for module load/unload Kuniyuki Iwashima
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

When we roll back the changes made by struct pernet_operations.init(),
we execute mostly identical sequences in three places.

  * setup_net()
  * cleanup_net()
  * free_exit_list()

The only difference between the first two is which list and RCU helpers
to use.

In setup_net(), an ops could fail on the way, so we need to perform a
reverse walk from its previous ops in pernet_list.  OTOH, in cleanup_net(),
we iterate the full list from tail to head.

The former passes the failed ops to list_for_each_entry_continue_reverse().
It's tricky, but we can reuse it for the latter if we pass list_entry() of
the head node.

Also, synchronize_rcu() and synchronize_rcu_expedited() can be easily
switched by an argument.

Let's factorise the rollback part in setup_net() and cleanup_net().

In the next patch, ops_undo_list() will be reused for free_exit_list(),
and then two arguments (ops_list and hold_rtnl) will differ.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
 net/core/net_namespace.c | 106 +++++++++++++++++++--------------------
 1 file changed, 51 insertions(+), 55 deletions(-)

diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index b0dfdf791ece..2612339efd71 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -188,6 +188,53 @@ static void ops_free_list(const struct pernet_operations *ops,
 	}
 }
 
+static void ops_undo_list(const struct list_head *ops_list,
+			  const struct pernet_operations *ops,
+			  struct list_head *net_exit_list,
+			  bool expedite_rcu, bool hold_rtnl)
+{
+	const struct pernet_operations *saved_ops;
+
+	if (!ops)
+		ops = list_entry(ops_list, typeof(*ops), list);
+
+	saved_ops = ops;
+
+	list_for_each_entry_continue_reverse(ops, ops_list, list)
+		ops_pre_exit_list(ops, net_exit_list);
+
+	/* Another CPU might be rcu-iterating the list, wait for it.
+	 * This needs to be before calling the exit() notifiers, so the
+	 * rcu_barrier() after ops_undo_list() isn't sufficient alone.
+	 * Also the pre_exit() and exit() methods need this barrier.
+	 */
+	if (expedite_rcu)
+		synchronize_rcu_expedited();
+	else
+		synchronize_rcu();
+
+	if (hold_rtnl) {
+		LIST_HEAD(dev_kill_list);
+
+		ops = saved_ops;
+		rtnl_lock();
+		list_for_each_entry_continue_reverse(ops, ops_list, list) {
+			if (ops->exit_batch_rtnl)
+				ops->exit_batch_rtnl(net_exit_list, &dev_kill_list);
+		}
+		unregister_netdevice_many(&dev_kill_list);
+		rtnl_unlock();
+	}
+
+	ops = saved_ops;
+	list_for_each_entry_continue_reverse(ops, ops_list, list)
+		ops_exit_list(ops, net_exit_list);
+
+	ops = saved_ops;
+	list_for_each_entry_continue_reverse(ops, ops_list, list)
+		ops_free_list(ops, net_exit_list);
+}
+
 /* should be called with nsid_lock held */
 static int alloc_netid(struct net *net, struct net *peer, int reqid)
 {
@@ -351,9 +398,8 @@ static __net_init void preinit_net(struct net *net, struct user_namespace *user_
 static __net_init int setup_net(struct net *net)
 {
 	/* Must be called with pernet_ops_rwsem held */
-	const struct pernet_operations *ops, *saved_ops;
+	const struct pernet_operations *ops;
 	LIST_HEAD(net_exit_list);
-	LIST_HEAD(dev_kill_list);
 	int error = 0;
 
 	preempt_disable();
@@ -376,29 +422,7 @@ static __net_init int setup_net(struct net *net)
 	 * for the pernet modules whose init functions did not fail.
 	 */
 	list_add(&net->exit_list, &net_exit_list);
-	saved_ops = ops;
-	list_for_each_entry_continue_reverse(ops, &pernet_list, list)
-		ops_pre_exit_list(ops, &net_exit_list);
-
-	synchronize_rcu();
-
-	ops = saved_ops;
-	rtnl_lock();
-	list_for_each_entry_continue_reverse(ops, &pernet_list, list) {
-		if (ops->exit_batch_rtnl)
-			ops->exit_batch_rtnl(&net_exit_list, &dev_kill_list);
-	}
-	unregister_netdevice_many(&dev_kill_list);
-	rtnl_unlock();
-
-	ops = saved_ops;
-	list_for_each_entry_continue_reverse(ops, &pernet_list, list)
-		ops_exit_list(ops, &net_exit_list);
-
-	ops = saved_ops;
-	list_for_each_entry_continue_reverse(ops, &pernet_list, list)
-		ops_free_list(ops, &net_exit_list);
-
+	ops_undo_list(&pernet_list, ops, &net_exit_list, false, true);
 	rcu_barrier();
 	goto out;
 }
@@ -594,11 +618,9 @@ struct task_struct *cleanup_net_task;
 
 static void cleanup_net(struct work_struct *work)
 {
-	const struct pernet_operations *ops;
-	struct net *net, *tmp, *last;
 	struct llist_node *net_kill_list;
+	struct net *net, *tmp, *last;
 	LIST_HEAD(net_exit_list);
-	LIST_HEAD(dev_kill_list);
 
 	cleanup_net_task = current;
 
@@ -629,33 +651,7 @@ static void cleanup_net(struct work_struct *work)
 		list_add_tail(&net->exit_list, &net_exit_list);
 	}
 
-	/* Run all of the network namespace pre_exit methods */
-	list_for_each_entry_reverse(ops, &pernet_list, list)
-		ops_pre_exit_list(ops, &net_exit_list);
-
-	/*
-	 * Another CPU might be rcu-iterating the list, wait for it.
-	 * This needs to be before calling the exit() notifiers, so
-	 * the rcu_barrier() below isn't sufficient alone.
-	 * Also the pre_exit() and exit() methods need this barrier.
-	 */
-	synchronize_rcu_expedited();
-
-	rtnl_lock();
-	list_for_each_entry_reverse(ops, &pernet_list, list) {
-		if (ops->exit_batch_rtnl)
-			ops->exit_batch_rtnl(&net_exit_list, &dev_kill_list);
-	}
-	unregister_netdevice_many(&dev_kill_list);
-	rtnl_unlock();
-
-	/* Run all of the network namespace exit methods */
-	list_for_each_entry_reverse(ops, &pernet_list, list)
-		ops_exit_list(ops, &net_exit_list);
-
-	/* Free the net generic variables */
-	list_for_each_entry_reverse(ops, &pernet_list, list)
-		ops_free_list(ops, &net_exit_list);
+	ops_undo_list(&pernet_list, NULL, &net_exit_list, true, true);
 
 	up_read(&pernet_ops_rwsem);
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 02/14] net: Add ops_undo_single for module load/unload.
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 01/14] net: Factorise setup_net() and cleanup_net() Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-15  0:01   ` Jakub Kicinski
  2025-04-11 20:52 ` [PATCH v2 net-next 03/14] net: Add ->exit_rtnl() hook to struct pernet_operations Kuniyuki Iwashima
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

If ops_init() fails while loading a module or we unload the
module, free_exit_list() rolls back the changes.

The rollback sequence is the same as ops_undo_list().

The ops is already removed from pernet_list before calling
free_exit_list().  If we link the ops to a temporary list,
we can reuse ops_undo_list().

Let's add a wrapper of ops_undo_list() and use it instead
of free_exit_list().

Now, we have the central place to roll back ops_init().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
v2: Convert free_exit_list() under CONFIG_NET_NS=n
---
 net/core/net_namespace.c | 54 ++++++++++++++++++----------------------
 1 file changed, 24 insertions(+), 30 deletions(-)

diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 2612339efd71..37026776ae4e 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -235,6 +235,17 @@ static void ops_undo_list(const struct list_head *ops_list,
 		ops_free_list(ops, net_exit_list);
 }
 
+static void ops_undo_single(struct pernet_operations *ops,
+			    struct list_head *net_exit_list)
+{
+	bool hold_rtnl = !!ops->exit_batch_rtnl;
+	LIST_HEAD(ops_list);
+
+	list_add(&ops->list, &ops_list);
+	ops_undo_list(&ops_list, NULL, net_exit_list, false, hold_rtnl);
+	list_del(&ops->list);
+}
+
 /* should be called with nsid_lock held */
 static int alloc_netid(struct net *net, struct net *peer, int reqid)
 {
@@ -1235,31 +1246,13 @@ void __init net_ns_init(void)
 	rtnl_register_many(net_ns_rtnl_msg_handlers);
 }
 
-static void free_exit_list(struct pernet_operations *ops, struct list_head *net_exit_list)
-{
-	ops_pre_exit_list(ops, net_exit_list);
-	synchronize_rcu();
-
-	if (ops->exit_batch_rtnl) {
-		LIST_HEAD(dev_kill_list);
-
-		rtnl_lock();
-		ops->exit_batch_rtnl(net_exit_list, &dev_kill_list);
-		unregister_netdevice_many(&dev_kill_list);
-		rtnl_unlock();
-	}
-	ops_exit_list(ops, net_exit_list);
-
-	ops_free_list(ops, net_exit_list);
-}
-
 #ifdef CONFIG_NET_NS
 static int __register_pernet_operations(struct list_head *list,
 					struct pernet_operations *ops)
 {
+	LIST_HEAD(net_exit_list);
 	struct net *net;
 	int error;
-	LIST_HEAD(net_exit_list);
 
 	list_add_tail(&ops->list, list);
 	if (ops->init || ops->id) {
@@ -1278,21 +1271,21 @@ static int __register_pernet_operations(struct list_head *list,
 out_undo:
 	/* If I have an error cleanup all namespaces I initialized */
 	list_del(&ops->list);
-	free_exit_list(ops, &net_exit_list);
+	ops_undo_single(ops, &net_exit_list);
 	return error;
 }
 
 static void __unregister_pernet_operations(struct pernet_operations *ops)
 {
-	struct net *net;
 	LIST_HEAD(net_exit_list);
+	struct net *net;
 
-	list_del(&ops->list);
 	/* See comment in __register_pernet_operations() */
 	for_each_net(net)
 		list_add_tail(&net->exit_list, &net_exit_list);
 
-	free_exit_list(ops, &net_exit_list);
+	list_del(&ops->list);
+	ops_undo_single(ops, &net_exit_list);
 }
 
 #else
@@ -1300,22 +1293,23 @@ static void __unregister_pernet_operations(struct pernet_operations *ops)
 static int __register_pernet_operations(struct list_head *list,
 					struct pernet_operations *ops)
 {
-	if (!init_net_initialized) {
-		list_add_tail(&ops->list, list);
+	list_add_tail(&ops->list, list);
+
+	if (!init_net_initialized)
 		return 0;
-	}
 
 	return ops_init(ops, &init_net);
 }
 
 static void __unregister_pernet_operations(struct pernet_operations *ops)
 {
-	if (!init_net_initialized) {
-		list_del(&ops->list);
-	} else {
+	list_del(&ops->list);
+
+	if (init_net_initialized) {
 		LIST_HEAD(net_exit_list);
+
 		list_add(&init_net.exit_list, &net_exit_list);
-		free_exit_list(ops, &net_exit_list);
+		ops_undo_single(ops, &net_exit_list);
 	}
 }
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 03/14] net: Add ->exit_rtnl() hook to struct pernet_operations.
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 01/14] net: Factorise setup_net() and cleanup_net() Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 02/14] net: Add ops_undo_single for module load/unload Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 04/14] nexthop: Convert nexthop_net_exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

struct pernet_operations provides two batching hooks; ->exit_batch()
and ->exit_batch_rtnl().

The batching variant is beneficial if ->exit() meets any of the
following conditions:

  1) ->exit() repeatedly acquires a global lock for each netns

  2) ->exit() has a time-consuming operation that can be factored
     out (e.g. synchronize_rcu(), smp_mb(), etc)

  3) ->exit() does not need to repeat the same iterations for each
     netns (e.g. inet_twsk_purge())

Currently, none of the ->exit_batch_rtnl() functions satisfy any of
the above conditions because RTNL is factored out and held by the
caller and all of these functions iterate over the dying netns list.

Also, we want to hold per-netns RTNL there but avoid spreading
__rtnl_net_lock() across multiple locations.

Let's add ->exit_rtnl() hook and run it under __rtnl_net_lock().

The following patches will convert all ->exit_batch_rtnl() users
to ->exit_rtnl().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
 include/net/net_namespace.h |  2 ++
 net/core/net_namespace.c    | 53 +++++++++++++++++++++++++++----------
 2 files changed, 41 insertions(+), 14 deletions(-)

diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index bd57d8fb54f1..b071e6eed9d5 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -475,6 +475,8 @@ struct pernet_operations {
 	void (*exit)(struct net *net);
 	void (*exit_batch)(struct list_head *net_exit_list);
 	/* Following method is called with RTNL held. */
+	void (*exit_rtnl)(struct net *net,
+			  struct list_head *dev_kill_list);
 	void (*exit_batch_rtnl)(struct list_head *net_exit_list,
 				struct list_head *dev_kill_list);
 	unsigned int * const id;
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 37026776ae4e..afaa3d1bda8d 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -163,16 +163,51 @@ static void ops_pre_exit_list(const struct pernet_operations *ops,
 	}
 }
 
+static void ops_exit_rtnl_list(const struct list_head *ops_list,
+			       const struct pernet_operations *ops,
+			       struct list_head *net_exit_list)
+{
+	const struct pernet_operations *saved_ops = ops;
+	LIST_HEAD(dev_kill_list);
+	struct net *net;
+
+	rtnl_lock();
+
+	list_for_each_entry(net, net_exit_list, exit_list) {
+		__rtnl_net_lock(net);
+
+		ops = saved_ops;
+		list_for_each_entry_continue_reverse(ops, ops_list, list) {
+			if (ops->exit_rtnl)
+				ops->exit_rtnl(net, &dev_kill_list);
+		}
+
+		__rtnl_net_unlock(net);
+	}
+
+	ops = saved_ops;
+	list_for_each_entry_continue_reverse(ops, ops_list, list) {
+		if (ops->exit_batch_rtnl)
+			ops->exit_batch_rtnl(net_exit_list, &dev_kill_list);
+	}
+
+	unregister_netdevice_many(&dev_kill_list);
+
+	rtnl_unlock();
+}
+
 static void ops_exit_list(const struct pernet_operations *ops,
 			  struct list_head *net_exit_list)
 {
-	struct net *net;
 	if (ops->exit) {
+		struct net *net;
+
 		list_for_each_entry(net, net_exit_list, exit_list) {
 			ops->exit(net);
 			cond_resched();
 		}
 	}
+
 	if (ops->exit_batch)
 		ops->exit_batch(net_exit_list);
 }
@@ -213,18 +248,8 @@ static void ops_undo_list(const struct list_head *ops_list,
 	else
 		synchronize_rcu();
 
-	if (hold_rtnl) {
-		LIST_HEAD(dev_kill_list);
-
-		ops = saved_ops;
-		rtnl_lock();
-		list_for_each_entry_continue_reverse(ops, ops_list, list) {
-			if (ops->exit_batch_rtnl)
-				ops->exit_batch_rtnl(net_exit_list, &dev_kill_list);
-		}
-		unregister_netdevice_many(&dev_kill_list);
-		rtnl_unlock();
-	}
+	if (hold_rtnl)
+		ops_exit_rtnl_list(ops_list, saved_ops, net_exit_list);
 
 	ops = saved_ops;
 	list_for_each_entry_continue_reverse(ops, ops_list, list)
@@ -238,7 +263,7 @@ static void ops_undo_list(const struct list_head *ops_list,
 static void ops_undo_single(struct pernet_operations *ops,
 			    struct list_head *net_exit_list)
 {
-	bool hold_rtnl = !!ops->exit_batch_rtnl;
+	bool hold_rtnl = ops->exit_rtnl || ops->exit_batch_rtnl;
 	LIST_HEAD(ops_list);
 
 	list_add(&ops->list, &ops_list);
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 04/14] nexthop: Convert nexthop_net_exit_batch_rtnl() to ->exit_rtnl().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (2 preceding siblings ...)
  2025-04-11 20:52 ` [PATCH v2 net-next 03/14] net: Add ->exit_rtnl() hook to struct pernet_operations Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 05/14] vxlan: Convert vxlan_exit_batch_rtnl() " Kuniyuki Iwashima
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev,
	David Ahern

nexthop_net_exit_batch_rtnl() iterates the dying netns list and
performs the same operation for each.

Let's use ->exit_rtnl().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
---
 net/ipv4/nexthop.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
index 467151517023..d9cf06b297d1 100644
--- a/net/ipv4/nexthop.c
+++ b/net/ipv4/nexthop.c
@@ -4040,14 +4040,11 @@ void nexthop_res_grp_activity_update(struct net *net, u32 id, u16 num_buckets,
 }
 EXPORT_SYMBOL(nexthop_res_grp_activity_update);
 
-static void __net_exit nexthop_net_exit_batch_rtnl(struct list_head *net_list,
-						   struct list_head *dev_to_kill)
+static void __net_exit nexthop_net_exit_rtnl(struct net *net,
+					     struct list_head *dev_to_kill)
 {
-	struct net *net;
-
-	ASSERT_RTNL();
-	list_for_each_entry(net, net_list, exit_list)
-		flush_all_nexthops(net);
+	ASSERT_RTNL_NET(net);
+	flush_all_nexthops(net);
 }
 
 static void __net_exit nexthop_net_exit(struct net *net)
@@ -4072,7 +4069,7 @@ static int __net_init nexthop_net_init(struct net *net)
 static struct pernet_operations nexthop_net_ops = {
 	.init = nexthop_net_init,
 	.exit = nexthop_net_exit,
-	.exit_batch_rtnl = nexthop_net_exit_batch_rtnl,
+	.exit_rtnl = nexthop_net_exit_rtnl,
 };
 
 static const struct rtnl_msg_handler nexthop_rtnl_msg_handlers[] __initconst = {
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 05/14] vxlan: Convert vxlan_exit_batch_rtnl() to ->exit_rtnl().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (3 preceding siblings ...)
  2025-04-11 20:52 ` [PATCH v2 net-next 04/14] nexthop: Convert nexthop_net_exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 06/14] ipv4: ip_tunnel: Convert ip_tunnel_delete_nets() callers " Kuniyuki Iwashima
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev,
	Nikolay Aleksandrov, Andrew Lunn

vxlan_exit_batch_rtnl() iterates the dying netns list and
performs the same operations for each.

Let's use ->exit_rtnl().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
---
Cc: Andrew Lunn <andrew+netdev@lunn.ch>
---
 drivers/net/vxlan/vxlan_core.c | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 9ccc3f09f71b..56aee539c235 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -4966,19 +4966,15 @@ static void __net_exit vxlan_destroy_tunnels(struct vxlan_net *vn,
 		vxlan_dellink(vxlan->dev, dev_to_kill);
 }
 
-static void __net_exit vxlan_exit_batch_rtnl(struct list_head *net_list,
-					     struct list_head *dev_to_kill)
+static void __net_exit vxlan_exit_rtnl(struct net *net,
+				       struct list_head *dev_to_kill)
 {
-	struct net *net;
-
-	ASSERT_RTNL();
-	list_for_each_entry(net, net_list, exit_list) {
-		struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+	struct vxlan_net *vn = net_generic(net, vxlan_net_id);
 
-		__unregister_nexthop_notifier(net, &vn->nexthop_notifier_block);
+	ASSERT_RTNL_NET(net);
 
-		vxlan_destroy_tunnels(vn, dev_to_kill);
-	}
+	__unregister_nexthop_notifier(net, &vn->nexthop_notifier_block);
+	vxlan_destroy_tunnels(vn, dev_to_kill);
 }
 
 static void __net_exit vxlan_exit_net(struct net *net)
@@ -4992,7 +4988,7 @@ static void __net_exit vxlan_exit_net(struct net *net)
 
 static struct pernet_operations vxlan_net_ops = {
 	.init = vxlan_init_net,
-	.exit_batch_rtnl = vxlan_exit_batch_rtnl,
+	.exit_rtnl = vxlan_exit_rtnl,
 	.exit = vxlan_exit_net,
 	.id   = &vxlan_net_id,
 	.size = sizeof(struct vxlan_net),
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 06/14] ipv4: ip_tunnel: Convert ip_tunnel_delete_nets() callers to ->exit_rtnl().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (4 preceding siblings ...)
  2025-04-11 20:52 ` [PATCH v2 net-next 05/14] vxlan: Convert vxlan_exit_batch_rtnl() " Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 07/14] ipv6: Convert tunnel devices' ->exit_batch_rtnl() " Kuniyuki Iwashima
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev,
	David Ahern, Steffen Klassert, Herbert Xu

ip_tunnel_delete_nets() iterates the dying netns list and performs the
same operations for each.

Let's export ip_tunnel_destroy() as ip_tunnel_delete_net() and call it
from ->exit_rtnl().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
---
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
---
 include/net/ip_tunnels.h |  7 +++----
 net/ipv4/ip_gre.c        | 27 ++++++++++++---------------
 net/ipv4/ip_tunnel.c     | 25 +++++++------------------
 net/ipv4/ip_vti.c        |  9 ++++-----
 net/ipv4/ipip.c          |  9 ++++-----
 5 files changed, 30 insertions(+), 47 deletions(-)

diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index a36a335cef9f..0c3d571a04a1 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -377,10 +377,9 @@ struct net *ip_tunnel_get_link_net(const struct net_device *dev);
 int ip_tunnel_get_iflink(const struct net_device *dev);
 int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id,
 		       struct rtnl_link_ops *ops, char *devname);
-
-void ip_tunnel_delete_nets(struct list_head *list_net, unsigned int id,
-			   struct rtnl_link_ops *ops,
-			   struct list_head *dev_to_kill);
+void ip_tunnel_delete_net(struct net *net, unsigned int id,
+			  struct rtnl_link_ops *ops,
+			  struct list_head *dev_to_kill);
 
 void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 		    const struct iphdr *tnl_params, const u8 protocol);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 26d15f907551..f5b9004d6938 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -1066,16 +1066,15 @@ static int __net_init ipgre_init_net(struct net *net)
 	return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
 }
 
-static void __net_exit ipgre_exit_batch_rtnl(struct list_head *list_net,
-					     struct list_head *dev_to_kill)
+static void __net_exit ipgre_exit_rtnl(struct net *net,
+				       struct list_head *dev_to_kill)
 {
-	ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops,
-			      dev_to_kill);
+	ip_tunnel_delete_net(net, ipgre_net_id, &ipgre_link_ops, dev_to_kill);
 }
 
 static struct pernet_operations ipgre_net_ops = {
 	.init = ipgre_init_net,
-	.exit_batch_rtnl = ipgre_exit_batch_rtnl,
+	.exit_rtnl = ipgre_exit_rtnl,
 	.id   = &ipgre_net_id,
 	.size = sizeof(struct ip_tunnel_net),
 };
@@ -1752,16 +1751,15 @@ static int __net_init ipgre_tap_init_net(struct net *net)
 	return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
 }
 
-static void __net_exit ipgre_tap_exit_batch_rtnl(struct list_head *list_net,
-						 struct list_head *dev_to_kill)
+static void __net_exit ipgre_tap_exit_rtnl(struct net *net,
+					   struct list_head *dev_to_kill)
 {
-	ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops,
-			      dev_to_kill);
+	ip_tunnel_delete_net(net, gre_tap_net_id, &ipgre_tap_ops, dev_to_kill);
 }
 
 static struct pernet_operations ipgre_tap_net_ops = {
 	.init = ipgre_tap_init_net,
-	.exit_batch_rtnl = ipgre_tap_exit_batch_rtnl,
+	.exit_rtnl = ipgre_tap_exit_rtnl,
 	.id   = &gre_tap_net_id,
 	.size = sizeof(struct ip_tunnel_net),
 };
@@ -1772,16 +1770,15 @@ static int __net_init erspan_init_net(struct net *net)
 				  &erspan_link_ops, "erspan0");
 }
 
-static void __net_exit erspan_exit_batch_rtnl(struct list_head *net_list,
-					      struct list_head *dev_to_kill)
+static void __net_exit erspan_exit_rtnl(struct net *net,
+					struct list_head *dev_to_kill)
 {
-	ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops,
-			      dev_to_kill);
+	ip_tunnel_delete_net(net, erspan_net_id, &erspan_link_ops, dev_to_kill);
 }
 
 static struct pernet_operations erspan_net_ops = {
 	.init = erspan_init_net,
-	.exit_batch_rtnl = erspan_exit_batch_rtnl,
+	.exit_rtnl = erspan_exit_rtnl,
 	.id   = &erspan_net_id,
 	.size = sizeof(struct ip_tunnel_net),
 };
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 1024f961ec9a..3913ec89ad20 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -1174,13 +1174,16 @@ int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id,
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_init_net);
 
-static void ip_tunnel_destroy(struct net *net, struct ip_tunnel_net *itn,
-			      struct list_head *head,
-			      struct rtnl_link_ops *ops)
+void ip_tunnel_delete_net(struct net *net, unsigned int id,
+			  struct rtnl_link_ops *ops,
+			  struct list_head *head)
 {
+	struct ip_tunnel_net *itn = net_generic(net, id);
 	struct net_device *dev, *aux;
 	int h;
 
+	ASSERT_RTNL_NET(net);
+
 	for_each_netdev_safe(net, dev, aux)
 		if (dev->rtnl_link_ops == ops)
 			unregister_netdevice_queue(dev, head);
@@ -1198,21 +1201,7 @@ static void ip_tunnel_destroy(struct net *net, struct ip_tunnel_net *itn,
 				unregister_netdevice_queue(t->dev, head);
 	}
 }
-
-void ip_tunnel_delete_nets(struct list_head *net_list, unsigned int id,
-			   struct rtnl_link_ops *ops,
-			   struct list_head *dev_to_kill)
-{
-	struct ip_tunnel_net *itn;
-	struct net *net;
-
-	ASSERT_RTNL();
-	list_for_each_entry(net, net_list, exit_list) {
-		itn = net_generic(net, id);
-		ip_tunnel_destroy(net, itn, dev_to_kill, ops);
-	}
-}
-EXPORT_SYMBOL_GPL(ip_tunnel_delete_nets);
+EXPORT_SYMBOL_GPL(ip_tunnel_delete_net);
 
 int ip_tunnel_newlink(struct net *net, struct net_device *dev,
 		      struct nlattr *tb[], struct ip_tunnel_parm_kern *p,
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 159b4473290e..686e4f3d83aa 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -523,16 +523,15 @@ static int __net_init vti_init_net(struct net *net)
 	return 0;
 }
 
-static void __net_exit vti_exit_batch_rtnl(struct list_head *list_net,
-					   struct list_head *dev_to_kill)
+static void __net_exit vti_exit_rtnl(struct net *net,
+				     struct list_head *dev_to_kill)
 {
-	ip_tunnel_delete_nets(list_net, vti_net_id, &vti_link_ops,
-			      dev_to_kill);
+	ip_tunnel_delete_net(net, vti_net_id, &vti_link_ops, dev_to_kill);
 }
 
 static struct pernet_operations vti_net_ops = {
 	.init = vti_init_net,
-	.exit_batch_rtnl = vti_exit_batch_rtnl,
+	.exit_rtnl = vti_exit_rtnl,
 	.id   = &vti_net_id,
 	.size = sizeof(struct ip_tunnel_net),
 };
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index bab0bf90c908..3e03af073a1c 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -604,16 +604,15 @@ static int __net_init ipip_init_net(struct net *net)
 	return ip_tunnel_init_net(net, ipip_net_id, &ipip_link_ops, "tunl0");
 }
 
-static void __net_exit ipip_exit_batch_rtnl(struct list_head *list_net,
-					    struct list_head *dev_to_kill)
+static void __net_exit ipip_exit_rtnl(struct net *net,
+				      struct list_head *dev_to_kill)
 {
-	ip_tunnel_delete_nets(list_net, ipip_net_id, &ipip_link_ops,
-			      dev_to_kill);
+	ip_tunnel_delete_net(net, ipip_net_id, &ipip_link_ops, dev_to_kill);
 }
 
 static struct pernet_operations ipip_net_ops = {
 	.init = ipip_init_net,
-	.exit_batch_rtnl = ipip_exit_batch_rtnl,
+	.exit_rtnl = ipip_exit_rtnl,
 	.id   = &ipip_net_id,
 	.size = sizeof(struct ip_tunnel_net),
 };
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 07/14] ipv6: Convert tunnel devices' ->exit_batch_rtnl() to ->exit_rtnl().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (5 preceding siblings ...)
  2025-04-11 20:52 ` [PATCH v2 net-next 06/14] ipv4: ip_tunnel: Convert ip_tunnel_delete_nets() callers " Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 08/14] xfrm: Convert xfrmi_exit_batch_rtnl() " Kuniyuki Iwashima
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev,
	David Ahern, Steffen Klassert, Herbert Xu

The following functions iterates the dying netns list and performs
the same operations for each netns.

  * ip6gre_exit_batch_rtnl()
  * ip6_tnl_exit_batch_rtnl()
  * vti6_exit_batch_rtnl()
  * sit_exit_batch_rtnl()

Let's use ->exit_rtnl().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
---
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
---
 net/ipv6/ip6_gre.c    | 22 ++++++----------------
 net/ipv6/ip6_tunnel.c | 24 ++++++++----------------
 net/ipv6/ip6_vti.c    | 27 +++++++--------------------
 net/ipv6/sit.c        | 23 ++++++-----------------
 4 files changed, 27 insertions(+), 69 deletions(-)

diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 957ca98fa70f..2dc9dcffe2ca 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1570,7 +1570,7 @@ static struct inet6_protocol ip6gre_protocol __read_mostly = {
 	.flags       = INET6_PROTO_FINAL,
 };
 
-static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head)
+static void __net_exit ip6gre_exit_rtnl_net(struct net *net, struct list_head *head)
 {
 	struct ip6gre_net *ign = net_generic(net, ip6gre_net_id);
 	struct net_device *dev, *aux;
@@ -1587,16 +1587,16 @@ static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head)
 		for (h = 0; h < IP6_GRE_HASH_SIZE; h++) {
 			struct ip6_tnl *t;
 
-			t = rtnl_dereference(ign->tunnels[prio][h]);
+			t = rtnl_net_dereference(net, ign->tunnels[prio][h]);
 
 			while (t) {
 				/* If dev is in the same netns, it has already
 				 * been added to the list by the previous loop.
 				 */
 				if (!net_eq(dev_net(t->dev), net))
-					unregister_netdevice_queue(t->dev,
-								   head);
-				t = rtnl_dereference(t->next);
+					unregister_netdevice_queue(t->dev, head);
+
+				t = rtnl_net_dereference(net, t->next);
 			}
 		}
 	}
@@ -1640,19 +1640,9 @@ static int __net_init ip6gre_init_net(struct net *net)
 	return err;
 }
 
-static void __net_exit ip6gre_exit_batch_rtnl(struct list_head *net_list,
-					      struct list_head *dev_to_kill)
-{
-	struct net *net;
-
-	ASSERT_RTNL();
-	list_for_each_entry(net, net_list, exit_list)
-		ip6gre_destroy_tunnels(net, dev_to_kill);
-}
-
 static struct pernet_operations ip6gre_net_ops = {
 	.init = ip6gre_init_net,
-	.exit_batch_rtnl = ip6gre_exit_batch_rtnl,
+	.exit_rtnl = ip6gre_exit_rtnl_net,
 	.id   = &ip6gre_net_id,
 	.size = sizeof(struct ip6gre_net),
 };
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index a04dd1bb4b19..894d3158a6f0 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -2210,7 +2210,7 @@ static struct xfrm6_tunnel mplsip6_handler __read_mostly = {
 	.priority	=	1,
 };
 
-static void __net_exit ip6_tnl_destroy_tunnels(struct net *net, struct list_head *list)
+static void __net_exit ip6_tnl_exit_rtnl_net(struct net *net, struct list_head *list)
 {
 	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
 	struct net_device *dev, *aux;
@@ -2222,25 +2222,27 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct net *net, struct list_head
 			unregister_netdevice_queue(dev, list);
 
 	for (h = 0; h < IP6_TUNNEL_HASH_SIZE; h++) {
-		t = rtnl_dereference(ip6n->tnls_r_l[h]);
+		t = rtnl_net_dereference(net, ip6n->tnls_r_l[h]);
 		while (t) {
 			/* If dev is in the same netns, it has already
 			 * been added to the list by the previous loop.
 			 */
 			if (!net_eq(dev_net(t->dev), net))
 				unregister_netdevice_queue(t->dev, list);
-			t = rtnl_dereference(t->next);
+
+			t = rtnl_net_dereference(net, t->next);
 		}
 	}
 
-	t = rtnl_dereference(ip6n->tnls_wc[0]);
+	t = rtnl_net_dereference(net, ip6n->tnls_wc[0]);
 	while (t) {
 		/* If dev is in the same netns, it has already
 		 * been added to the list by the previous loop.
 		 */
 		if (!net_eq(dev_net(t->dev), net))
 			unregister_netdevice_queue(t->dev, list);
-		t = rtnl_dereference(t->next);
+
+		t = rtnl_net_dereference(net, t->next);
 	}
 }
 
@@ -2287,19 +2289,9 @@ static int __net_init ip6_tnl_init_net(struct net *net)
 	return err;
 }
 
-static void __net_exit ip6_tnl_exit_batch_rtnl(struct list_head *net_list,
-					       struct list_head *dev_to_kill)
-{
-	struct net *net;
-
-	ASSERT_RTNL();
-	list_for_each_entry(net, net_list, exit_list)
-		ip6_tnl_destroy_tunnels(net, dev_to_kill);
-}
-
 static struct pernet_operations ip6_tnl_net_ops = {
 	.init = ip6_tnl_init_net,
-	.exit_batch_rtnl = ip6_tnl_exit_batch_rtnl,
+	.exit_rtnl = ip6_tnl_exit_rtnl_net,
 	.id   = &ip6_tnl_net_id,
 	.size = sizeof(struct ip6_tnl_net),
 };
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 09ec4b0ad7dc..40464a88bca6 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -1112,21 +1112,21 @@ static struct rtnl_link_ops vti6_link_ops __read_mostly = {
 	.get_link_net	= ip6_tnl_get_link_net,
 };
 
-static void __net_exit vti6_destroy_tunnels(struct vti6_net *ip6n,
-					    struct list_head *list)
+static void __net_exit vti6_exit_rtnl_net(struct net *net, struct list_head *list)
 {
-	int h;
+	struct vti6_net *ip6n = net_generic(net, vti6_net_id);
 	struct ip6_tnl *t;
+	int h;
 
 	for (h = 0; h < IP6_VTI_HASH_SIZE; h++) {
-		t = rtnl_dereference(ip6n->tnls_r_l[h]);
+		t = rtnl_net_dereference(net, ip6n->tnls_r_l[h]);
 		while (t) {
 			unregister_netdevice_queue(t->dev, list);
-			t = rtnl_dereference(t->next);
+			t = rtnl_net_dereference(net, t->next);
 		}
 	}
 
-	t = rtnl_dereference(ip6n->tnls_wc[0]);
+	t = rtnl_net_dereference(net, ip6n->tnls_wc[0]);
 	if (t)
 		unregister_netdevice_queue(t->dev, list);
 }
@@ -1170,22 +1170,9 @@ static int __net_init vti6_init_net(struct net *net)
 	return err;
 }
 
-static void __net_exit vti6_exit_batch_rtnl(struct list_head *net_list,
-					    struct list_head *dev_to_kill)
-{
-	struct vti6_net *ip6n;
-	struct net *net;
-
-	ASSERT_RTNL();
-	list_for_each_entry(net, net_list, exit_list) {
-		ip6n = net_generic(net, vti6_net_id);
-		vti6_destroy_tunnels(ip6n, dev_to_kill);
-	}
-}
-
 static struct pernet_operations vti6_net_ops = {
 	.init = vti6_init_net,
-	.exit_batch_rtnl = vti6_exit_batch_rtnl,
+	.exit_rtnl = vti6_exit_rtnl_net,
 	.id   = &vti6_net_id,
 	.size = sizeof(struct vti6_net),
 };
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 9a0f32acb750..a72dbca9e8fc 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -1804,8 +1804,7 @@ static struct xfrm_tunnel mplsip_handler __read_mostly = {
 };
 #endif
 
-static void __net_exit sit_destroy_tunnels(struct net *net,
-					   struct list_head *head)
+static void __net_exit sit_exit_rtnl_net(struct net *net, struct list_head *head)
 {
 	struct sit_net *sitn = net_generic(net, sit_net_id);
 	struct net_device *dev, *aux;
@@ -1820,15 +1819,15 @@ static void __net_exit sit_destroy_tunnels(struct net *net,
 		for (h = 0; h < (prio ? IP6_SIT_HASH_SIZE : 1); h++) {
 			struct ip_tunnel *t;
 
-			t = rtnl_dereference(sitn->tunnels[prio][h]);
+			t = rtnl_net_dereference(net, sitn->tunnels[prio][h]);
 			while (t) {
 				/* If dev is in the same netns, it has already
 				 * been added to the list by the previous loop.
 				 */
 				if (!net_eq(dev_net(t->dev), net))
-					unregister_netdevice_queue(t->dev,
-								   head);
-				t = rtnl_dereference(t->next);
+					unregister_netdevice_queue(t->dev, head);
+
+				t = rtnl_net_dereference(net, t->next);
 			}
 		}
 	}
@@ -1881,19 +1880,9 @@ static int __net_init sit_init_net(struct net *net)
 	return err;
 }
 
-static void __net_exit sit_exit_batch_rtnl(struct list_head *net_list,
-					   struct list_head *dev_to_kill)
-{
-	struct net *net;
-
-	ASSERT_RTNL();
-	list_for_each_entry(net, net_list, exit_list)
-		sit_destroy_tunnels(net, dev_to_kill);
-}
-
 static struct pernet_operations sit_net_ops = {
 	.init = sit_init_net,
-	.exit_batch_rtnl = sit_exit_batch_rtnl,
+	.exit_rtnl = sit_exit_rtnl_net,
 	.id   = &sit_net_id,
 	.size = sizeof(struct sit_net),
 };
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 08/14] xfrm: Convert xfrmi_exit_batch_rtnl() to ->exit_rtnl().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (6 preceding siblings ...)
  2025-04-11 20:52 ` [PATCH v2 net-next 07/14] ipv6: Convert tunnel devices' ->exit_batch_rtnl() " Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 09/14] bridge: Convert br_net_exit_batch_rtnl() " Kuniyuki Iwashima
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev,
	Steffen Klassert, Herbert Xu

xfrmi_exit_batch_rtnl() iterates the dying netns list and
performs the same operations for each.

Let's use ->exit_rtnl().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
---
 net/xfrm/xfrm_interface_core.c | 34 +++++++++++++++-------------------
 1 file changed, 15 insertions(+), 19 deletions(-)

diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c
index 622445f041d3..cb1e12740c87 100644
--- a/net/xfrm/xfrm_interface_core.c
+++ b/net/xfrm/xfrm_interface_core.c
@@ -952,32 +952,28 @@ static struct rtnl_link_ops xfrmi_link_ops __read_mostly = {
 	.get_link_net	= xfrmi_get_link_net,
 };
 
-static void __net_exit xfrmi_exit_batch_rtnl(struct list_head *net_exit_list,
-					     struct list_head *dev_to_kill)
+static void __net_exit xfrmi_exit_rtnl(struct net *net,
+				       struct list_head *dev_to_kill)
 {
-	struct net *net;
+	struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+	struct xfrm_if __rcu **xip;
+	struct xfrm_if *xi;
+	int i;
 
-	ASSERT_RTNL();
-	list_for_each_entry(net, net_exit_list, exit_list) {
-		struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
-		struct xfrm_if __rcu **xip;
-		struct xfrm_if *xi;
-		int i;
-
-		for (i = 0; i < XFRMI_HASH_SIZE; i++) {
-			for (xip = &xfrmn->xfrmi[i];
-			     (xi = rtnl_dereference(*xip)) != NULL;
-			     xip = &xi->next)
-				unregister_netdevice_queue(xi->dev, dev_to_kill);
-		}
-		xi = rtnl_dereference(xfrmn->collect_md_xfrmi);
-		if (xi)
+	for (i = 0; i < XFRMI_HASH_SIZE; i++) {
+		for (xip = &xfrmn->xfrmi[i];
+		     (xi = rtnl_net_dereference(net, *xip)) != NULL;
+		     xip = &xi->next)
 			unregister_netdevice_queue(xi->dev, dev_to_kill);
 	}
+
+	xi = rtnl_net_dereference(net, xfrmn->collect_md_xfrmi);
+	if (xi)
+		unregister_netdevice_queue(xi->dev, dev_to_kill);
 }
 
 static struct pernet_operations xfrmi_net_ops = {
-	.exit_batch_rtnl = xfrmi_exit_batch_rtnl,
+	.exit_rtnl = xfrmi_exit_rtnl,
 	.id   = &xfrmi_net_id,
 	.size = sizeof(struct xfrmi_net),
 };
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 09/14] bridge: Convert br_net_exit_batch_rtnl() to ->exit_rtnl().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (7 preceding siblings ...)
  2025-04-11 20:52 ` [PATCH v2 net-next 08/14] xfrm: Convert xfrmi_exit_batch_rtnl() " Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 10/14] bonding: Convert bond_net_exit_batch_rtnl() " Kuniyuki Iwashima
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev,
	Ido Schimmel, Nikolay Aleksandrov

br_net_exit_batch_rtnl() iterates the dying netns list and
performs the same operation for each.

Let's use ->exit_rtnl().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Acked-by: Nikolay Aleksandrov <razor@blackwall.org>
---
 net/bridge/br.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/net/bridge/br.c b/net/bridge/br.c
index 183fcb362f9e..c16913aac84c 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -363,21 +363,20 @@ void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on)
 		clear_bit(opt, &br->options);
 }
 
-static void __net_exit br_net_exit_batch_rtnl(struct list_head *net_list,
-					      struct list_head *dev_to_kill)
+static void __net_exit br_net_exit_rtnl(struct net *net,
+					struct list_head *dev_to_kill)
 {
 	struct net_device *dev;
-	struct net *net;
 
-	ASSERT_RTNL();
-	list_for_each_entry(net, net_list, exit_list)
-		for_each_netdev(net, dev)
-			if (netif_is_bridge_master(dev))
-				br_dev_delete(dev, dev_to_kill);
+	ASSERT_RTNL_NET(net);
+
+	for_each_netdev(net, dev)
+		if (netif_is_bridge_master(dev))
+			br_dev_delete(dev, dev_to_kill);
 }
 
 static struct pernet_operations br_net_ops = {
-	.exit_batch_rtnl = br_net_exit_batch_rtnl,
+	.exit_rtnl = br_net_exit_rtnl,
 };
 
 static const struct stp_proto br_stp_proto = {
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 10/14] bonding: Convert bond_net_exit_batch_rtnl() to ->exit_rtnl().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (8 preceding siblings ...)
  2025-04-11 20:52 ` [PATCH v2 net-next 09/14] bridge: Convert br_net_exit_batch_rtnl() " Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 11/14] gtp: Convert gtp_net_exit_batch_rtnl() " Kuniyuki Iwashima
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev,
	Nikolay Aleksandrov, Jay Vosburgh, Andrew Lunn

bond_net_exit_batch_rtnl() iterates the dying netns list and
performs the same operation for each.

Let's use ->exit_rtnl().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
---
Cc: Jay Vosburgh <jv@jvosburgh.net>
Cc: Andrew Lunn <andrew+netdev@lunn.ch>
---
 drivers/net/bonding/bond_main.c | 23 +++++++++--------------
 1 file changed, 9 insertions(+), 14 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 950d8e4d86f8..bdd36409dd9b 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -6558,7 +6558,7 @@ static int __net_init bond_net_init(struct net *net)
 
 /* According to commit 69b0216ac255 ("bonding: fix bonding_masters
  * race condition in bond unloading") we need to remove sysfs files
- * before we remove our devices (done later in bond_net_exit_batch_rtnl())
+ * before we remove our devices (done later in bond_net_exit_rtnl())
  */
 static void __net_exit bond_net_pre_exit(struct net *net)
 {
@@ -6567,25 +6567,20 @@ static void __net_exit bond_net_pre_exit(struct net *net)
 	bond_destroy_sysfs(bn);
 }
 
-static void __net_exit bond_net_exit_batch_rtnl(struct list_head *net_list,
-						struct list_head *dev_kill_list)
+static void __net_exit bond_net_exit_rtnl(struct net *net,
+					  struct list_head *dev_kill_list)
 {
-	struct bond_net *bn;
-	struct net *net;
+	struct bond_net *bn = net_generic(net, bond_net_id);
+	struct bonding *bond, *tmp_bond;
 
 	/* Kill off any bonds created after unregistering bond rtnl ops */
-	list_for_each_entry(net, net_list, exit_list) {
-		struct bonding *bond, *tmp_bond;
-
-		bn = net_generic(net, bond_net_id);
-		list_for_each_entry_safe(bond, tmp_bond, &bn->dev_list, bond_list)
-			unregister_netdevice_queue(bond->dev, dev_kill_list);
-	}
+	list_for_each_entry_safe(bond, tmp_bond, &bn->dev_list, bond_list)
+		unregister_netdevice_queue(bond->dev, dev_kill_list);
 }
 
 /* According to commit 23fa5c2caae0 ("bonding: destroy proc directory
  * only after all bonds are gone") bond_destroy_proc_dir() is called
- * after bond_net_exit_batch_rtnl() has completed.
+ * after bond_net_exit_rtnl() has completed.
  */
 static void __net_exit bond_net_exit_batch(struct list_head *net_list)
 {
@@ -6601,7 +6596,7 @@ static void __net_exit bond_net_exit_batch(struct list_head *net_list)
 static struct pernet_operations bond_net_ops = {
 	.init = bond_net_init,
 	.pre_exit = bond_net_pre_exit,
-	.exit_batch_rtnl = bond_net_exit_batch_rtnl,
+	.exit_rtnl = bond_net_exit_rtnl,
 	.exit_batch = bond_net_exit_batch,
 	.id   = &bond_net_id,
 	.size = sizeof(struct bond_net),
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 11/14] gtp: Convert gtp_net_exit_batch_rtnl() to ->exit_rtnl().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (9 preceding siblings ...)
  2025-04-11 20:52 ` [PATCH v2 net-next 10/14] bonding: Convert bond_net_exit_batch_rtnl() " Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 12/14] bareudp: Convert bareudp_exit_batch_rtnl() " Kuniyuki Iwashima
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev,
	Pablo Neira Ayuso, Harald Welte, Andrew Lunn

gtp_net_exit_batch_rtnl() iterates the dying netns list
and performs the same operations for each.

Let's use ->exit_rtnl().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
Cc: Pablo Neira Ayuso <pablo@netfilter.org>
Cc: Harald Welte <laforge@gnumonks.org>
Cc: Andrew Lunn <andrew+netdev@lunn.ch>
---
 drivers/net/gtp.c | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index ef793607890d..d4dec741c7f4 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -2475,23 +2475,19 @@ static int __net_init gtp_net_init(struct net *net)
 	return 0;
 }
 
-static void __net_exit gtp_net_exit_batch_rtnl(struct list_head *net_list,
-					       struct list_head *dev_to_kill)
+static void __net_exit gtp_net_exit_rtnl(struct net *net,
+					 struct list_head *dev_to_kill)
 {
-	struct net *net;
-
-	list_for_each_entry(net, net_list, exit_list) {
-		struct gtp_net *gn = net_generic(net, gtp_net_id);
-		struct gtp_dev *gtp, *gtp_next;
+	struct gtp_net *gn = net_generic(net, gtp_net_id);
+	struct gtp_dev *gtp, *gtp_next;
 
-		list_for_each_entry_safe(gtp, gtp_next, &gn->gtp_dev_list, list)
-			gtp_dellink(gtp->dev, dev_to_kill);
-	}
+	list_for_each_entry_safe(gtp, gtp_next, &gn->gtp_dev_list, list)
+		gtp_dellink(gtp->dev, dev_to_kill);
 }
 
 static struct pernet_operations gtp_net_ops = {
 	.init	= gtp_net_init,
-	.exit_batch_rtnl = gtp_net_exit_batch_rtnl,
+	.exit_rtnl = gtp_net_exit_rtnl,
 	.id	= &gtp_net_id,
 	.size	= sizeof(struct gtp_net),
 };
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 12/14] bareudp: Convert bareudp_exit_batch_rtnl() to ->exit_rtnl().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (10 preceding siblings ...)
  2025-04-11 20:52 ` [PATCH v2 net-next 11/14] gtp: Convert gtp_net_exit_batch_rtnl() " Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 13/14] geneve: Convert geneve_exit_batch_rtnl() " Kuniyuki Iwashima
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev,
	Andrew Lunn

bareudp_exit_batch_rtnl() iterates the dying netns list and performs the
same operation for each.

Let's use ->exit_rtnl().

While at it, we replace unregister_netdevice_queue() with
bareudp_dellink() for better cleanup.  It unlinks the device
from net_generic(net, bareudp_net_id)->bareudp_list, but there
is no real issue as both the dev and the list are freed later.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
Cc: Andrew Lunn <andrew+netdev@lunn.ch>
---
 drivers/net/bareudp.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c
index d1473c5f8eef..a9dffdcac805 100644
--- a/drivers/net/bareudp.c
+++ b/drivers/net/bareudp.c
@@ -777,27 +777,19 @@ static __net_init int bareudp_init_net(struct net *net)
 	return 0;
 }
 
-static void bareudp_destroy_tunnels(struct net *net, struct list_head *head)
+static void __net_exit bareudp_exit_rtnl_net(struct net *net,
+					     struct list_head *dev_kill_list)
 {
 	struct bareudp_net *bn = net_generic(net, bareudp_net_id);
 	struct bareudp_dev *bareudp, *next;
 
 	list_for_each_entry_safe(bareudp, next, &bn->bareudp_list, next)
-		unregister_netdevice_queue(bareudp->dev, head);
-}
-
-static void __net_exit bareudp_exit_batch_rtnl(struct list_head *net_list,
-					       struct list_head *dev_kill_list)
-{
-	struct net *net;
-
-	list_for_each_entry(net, net_list, exit_list)
-		bareudp_destroy_tunnels(net, dev_kill_list);
+		bareudp_dellink(bareudp->dev, dev_kill_list);
 }
 
 static struct pernet_operations bareudp_net_ops = {
 	.init = bareudp_init_net,
-	.exit_batch_rtnl = bareudp_exit_batch_rtnl,
+	.exit_rtnl = bareudp_exit_rtnl_net,
 	.id   = &bareudp_net_id,
 	.size = sizeof(struct bareudp_net),
 };
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 13/14] geneve: Convert geneve_exit_batch_rtnl() to ->exit_rtnl().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (11 preceding siblings ...)
  2025-04-11 20:52 ` [PATCH v2 net-next 12/14] bareudp: Convert bareudp_exit_batch_rtnl() " Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-11 20:52 ` [PATCH v2 net-next 14/14] net: Remove ->exit_batch_rtnl() Kuniyuki Iwashima
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev,
	Andrew Lunn

geneve_exit_batch_rtnl() iterates the dying netns list and
performs the same operation for each.

Let's use ->exit_rtnl().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
Cc: Andrew Lunn <andrew+netdev@lunn.ch>
---
 drivers/net/geneve.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 66e38ce9cd1d..ffc15a432689 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -1946,22 +1946,14 @@ static __net_init int geneve_init_net(struct net *net)
 	return 0;
 }
 
-static void geneve_destroy_tunnels(struct net *net, struct list_head *head)
+static void __net_exit geneve_exit_rtnl_net(struct net *net,
+					    struct list_head *dev_to_kill)
 {
 	struct geneve_net *gn = net_generic(net, geneve_net_id);
 	struct geneve_dev *geneve, *next;
 
 	list_for_each_entry_safe(geneve, next, &gn->geneve_list, next)
-		geneve_dellink(geneve->dev, head);
-}
-
-static void __net_exit geneve_exit_batch_rtnl(struct list_head *net_list,
-					      struct list_head *dev_to_kill)
-{
-	struct net *net;
-
-	list_for_each_entry(net, net_list, exit_list)
-		geneve_destroy_tunnels(net, dev_to_kill);
+		geneve_dellink(geneve->dev, dev_to_kill);
 }
 
 static void __net_exit geneve_exit_net(struct net *net)
@@ -1973,7 +1965,7 @@ static void __net_exit geneve_exit_net(struct net *net)
 
 static struct pernet_operations geneve_net_ops = {
 	.init = geneve_init_net,
-	.exit_batch_rtnl = geneve_exit_batch_rtnl,
+	.exit_rtnl = geneve_exit_rtnl_net,
 	.exit = geneve_exit_net,
 	.id   = &geneve_net_id,
 	.size = sizeof(struct geneve_net),
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 net-next 14/14] net: Remove ->exit_batch_rtnl().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (12 preceding siblings ...)
  2025-04-11 20:52 ` [PATCH v2 net-next 13/14] geneve: Convert geneve_exit_batch_rtnl() " Kuniyuki Iwashima
@ 2025-04-11 20:52 ` Kuniyuki Iwashima
  2025-04-14 14:12 ` [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Sabrina Dubroca
  2025-04-15  0:30 ` patchwork-bot+netdevbpf
  15 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-11 20:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

There are no ->exit_batch_rtnl() users remaining.

Let's remove the hook.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
 include/net/net_namespace.h | 2 --
 net/core/net_namespace.c    | 8 +-------
 2 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index b071e6eed9d5..025a7574b275 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -477,8 +477,6 @@ struct pernet_operations {
 	/* Following method is called with RTNL held. */
 	void (*exit_rtnl)(struct net *net,
 			  struct list_head *dev_kill_list);
-	void (*exit_batch_rtnl)(struct list_head *net_exit_list,
-				struct list_head *dev_kill_list);
 	unsigned int * const id;
 	const size_t size;
 };
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index afaa3d1bda8d..0a2b24af4028 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -185,12 +185,6 @@ static void ops_exit_rtnl_list(const struct list_head *ops_list,
 		__rtnl_net_unlock(net);
 	}
 
-	ops = saved_ops;
-	list_for_each_entry_continue_reverse(ops, ops_list, list) {
-		if (ops->exit_batch_rtnl)
-			ops->exit_batch_rtnl(net_exit_list, &dev_kill_list);
-	}
-
 	unregister_netdevice_many(&dev_kill_list);
 
 	rtnl_unlock();
@@ -263,7 +257,7 @@ static void ops_undo_list(const struct list_head *ops_list,
 static void ops_undo_single(struct pernet_operations *ops,
 			    struct list_head *net_exit_list)
 {
-	bool hold_rtnl = ops->exit_rtnl || ops->exit_batch_rtnl;
+	bool hold_rtnl = !!ops->exit_rtnl;
 	LIST_HEAD(ops_list);
 
 	list_add(&ops->list, &ops_list);
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (13 preceding siblings ...)
  2025-04-11 20:52 ` [PATCH v2 net-next 14/14] net: Remove ->exit_batch_rtnl() Kuniyuki Iwashima
@ 2025-04-14 14:12 ` Sabrina Dubroca
  2025-04-15  0:30 ` patchwork-bot+netdevbpf
  15 siblings, 0 replies; 20+ messages in thread
From: Sabrina Dubroca @ 2025-04-14 14:12 UTC (permalink / raw)
  To: Kuniyuki Iwashima
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Kuniyuki Iwashima, netdev

2025-04-11, 13:52:29 -0700, Kuniyuki Iwashima wrote:
> Kuniyuki Iwashima (14):
>   net: Factorise setup_net() and cleanup_net().
>   net: Add ops_undo_single for module load/unload.
>   net: Add ->exit_rtnl() hook to struct pernet_operations.
>   nexthop: Convert nexthop_net_exit_batch_rtnl() to ->exit_rtnl().
>   vxlan: Convert vxlan_exit_batch_rtnl() to ->exit_rtnl().
>   ipv4: ip_tunnel: Convert ip_tunnel_delete_nets() callers to
>     ->exit_rtnl().
>   ipv6: Convert tunnel devices' ->exit_batch_rtnl() to ->exit_rtnl().
>   xfrm: Convert xfrmi_exit_batch_rtnl() to ->exit_rtnl().
>   bridge: Convert br_net_exit_batch_rtnl() to ->exit_rtnl().
>   bonding: Convert bond_net_exit_batch_rtnl() to ->exit_rtnl().
>   gtp: Convert gtp_net_exit_batch_rtnl() to ->exit_rtnl().
>   bareudp: Convert bareudp_exit_batch_rtnl() to ->exit_rtnl().
>   geneve: Convert geneve_exit_batch_rtnl() to ->exit_rtnl().
>   net: Remove ->exit_batch_rtnl().

Series:
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>

-- 
Sabrina

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 net-next 02/14] net: Add ops_undo_single for module load/unload.
  2025-04-11 20:52 ` [PATCH v2 net-next 02/14] net: Add ops_undo_single for module load/unload Kuniyuki Iwashima
@ 2025-04-15  0:01   ` Jakub Kicinski
  2025-04-15  0:12     ` Jakub Kicinski
  0 siblings, 1 reply; 20+ messages in thread
From: Jakub Kicinski @ 2025-04-15  0:01 UTC (permalink / raw)
  To: Kuniyuki Iwashima
  Cc: David S. Miller, Eric Dumazet, Paolo Abeni, Simon Horman,
	Kuniyuki Iwashima, netdev

On Fri, 11 Apr 2025 13:52:31 -0700 Kuniyuki Iwashima wrote:
> +	bool hold_rtnl = !!ops->exit_batch_rtnl;
> +
> +	list_add(&ops->list, &ops_list);
> +	ops_undo_list(&ops_list, NULL, net_exit_list, false, hold_rtnl);

Is this the only reason for the hold_rtnl argument to ops_undo_list() ?
We walk the ops once for pre-exit, before calling rtnl batch.
As we walk them we can |= their exit_batch_rtnl pointers, so
ops_undo_list() can figure out whether its worth taking rtnl all by itself ?

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 net-next 02/14] net: Add ops_undo_single for module load/unload.
  2025-04-15  0:01   ` Jakub Kicinski
@ 2025-04-15  0:12     ` Jakub Kicinski
  2025-04-15  0:17       ` Kuniyuki Iwashima
  0 siblings, 1 reply; 20+ messages in thread
From: Jakub Kicinski @ 2025-04-15  0:12 UTC (permalink / raw)
  To: Kuniyuki Iwashima
  Cc: David S. Miller, Eric Dumazet, Paolo Abeni, Simon Horman,
	Kuniyuki Iwashima, netdev

On Mon, 14 Apr 2025 17:01:48 -0700 Jakub Kicinski wrote:
> On Fri, 11 Apr 2025 13:52:31 -0700 Kuniyuki Iwashima wrote:
> > +	bool hold_rtnl = !!ops->exit_batch_rtnl;
> > +
> > +	list_add(&ops->list, &ops_list);
> > +	ops_undo_list(&ops_list, NULL, net_exit_list, false, hold_rtnl);  
> 
> Is this the only reason for the hold_rtnl argument to ops_undo_list() ?
> We walk the ops once for pre-exit, before calling rtnl batch.
> As we walk them we can |= their exit_batch_rtnl pointers, so
> ops_undo_list() can figure out whether its worth taking rtnl all by itself ?

Either way -- this would fit quite nicely as its own patch so please
follow up if you agree. I'll apply the series as is.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 net-next 02/14] net: Add ops_undo_single for module load/unload.
  2025-04-15  0:12     ` Jakub Kicinski
@ 2025-04-15  0:17       ` Kuniyuki Iwashima
  0 siblings, 0 replies; 20+ messages in thread
From: Kuniyuki Iwashima @ 2025-04-15  0:17 UTC (permalink / raw)
  To: kuba; +Cc: davem, edumazet, horms, kuni1840, kuniyu, netdev, pabeni

From: Jakub Kicinski <kuba@kernel.org>
Date: Mon, 14 Apr 2025 17:12:05 -0700
> On Mon, 14 Apr 2025 17:01:48 -0700 Jakub Kicinski wrote:
> > On Fri, 11 Apr 2025 13:52:31 -0700 Kuniyuki Iwashima wrote:
> > > +	bool hold_rtnl = !!ops->exit_batch_rtnl;
> > > +
> > > +	list_add(&ops->list, &ops_list);
> > > +	ops_undo_list(&ops_list, NULL, net_exit_list, false, hold_rtnl);  
> > 
> > Is this the only reason for the hold_rtnl argument to ops_undo_list() ?
> > We walk the ops once for pre-exit, before calling rtnl batch.
> > As we walk them we can |= their exit_batch_rtnl pointers, so
> > ops_undo_list() can figure out whether its worth taking rtnl all by itself ?

nexthop is the only built-in user of ->exit_rtnl(), so hold_rtnl
will be always true for setup/cleanup_net().


> 
> Either way -- this would fit quite nicely as its own patch so please
> follow up if you agree. I'll apply the series as is.

But I like that way so will post a follow up in case we can get
rid of ->exit_rtnl() from nexthop in the future.

Thanks!

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl().
  2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
                   ` (14 preceding siblings ...)
  2025-04-14 14:12 ` [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Sabrina Dubroca
@ 2025-04-15  0:30 ` patchwork-bot+netdevbpf
  15 siblings, 0 replies; 20+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-04-15  0:30 UTC (permalink / raw)
  To: Kuniyuki Iwashima; +Cc: davem, edumazet, kuba, pabeni, horms, kuni1840, netdev

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Fri, 11 Apr 2025 13:52:29 -0700 you wrote:
> While converting nexthop to per-netns RTNL, there are two blockers
> to using rtnl_net_dereference(), flush_all_nexthops() and
> __unregister_nexthop_notifier(), both of which are called from
> ->exit_batch_rtnl().
> 
> Instead of spreading __rtnl_net_lock() over each ->exit_batch_rtnl(),
> we should convert all ->exit_batch_rtnl() to per-net ->exit_rtnl() and
> run it under __rtnl_net_lock() because all ->exit_batch_rtnl() functions
> do not have anything to factor out for batching.
> 
> [...]

Here is the summary with links:
  - [v2,net-next,01/14] net: Factorise setup_net() and cleanup_net().
    https://git.kernel.org/netdev/net-next/c/e333b1c3cf25
  - [v2,net-next,02/14] net: Add ops_undo_single for module load/unload.
    https://git.kernel.org/netdev/net-next/c/fed176bf3143
  - [v2,net-next,03/14] net: Add ->exit_rtnl() hook to struct pernet_operations.
    https://git.kernel.org/netdev/net-next/c/7a60d91c690b
  - [v2,net-next,04/14] nexthop: Convert nexthop_net_exit_batch_rtnl() to ->exit_rtnl().
    https://git.kernel.org/netdev/net-next/c/cf701038d1c8
  - [v2,net-next,05/14] vxlan: Convert vxlan_exit_batch_rtnl() to ->exit_rtnl().
    https://git.kernel.org/netdev/net-next/c/6f2667b98ef2
  - [v2,net-next,06/14] ipv4: ip_tunnel: Convert ip_tunnel_delete_nets() callers to ->exit_rtnl().
    https://git.kernel.org/netdev/net-next/c/a967e01e2ad2
  - [v2,net-next,07/14] ipv6: Convert tunnel devices' ->exit_batch_rtnl() to ->exit_rtnl().
    https://git.kernel.org/netdev/net-next/c/f76758f18fb8
  - [v2,net-next,08/14] xfrm: Convert xfrmi_exit_batch_rtnl() to ->exit_rtnl().
    https://git.kernel.org/netdev/net-next/c/9571ab5a98fe
  - [v2,net-next,09/14] bridge: Convert br_net_exit_batch_rtnl() to ->exit_rtnl().
    https://git.kernel.org/netdev/net-next/c/b7924f50be15
  - [v2,net-next,10/14] bonding: Convert bond_net_exit_batch_rtnl() to ->exit_rtnl().
    https://git.kernel.org/netdev/net-next/c/baf720334c02
  - [v2,net-next,11/14] gtp: Convert gtp_net_exit_batch_rtnl() to ->exit_rtnl().
    https://git.kernel.org/netdev/net-next/c/bc7eaf7a40bb
  - [v2,net-next,12/14] bareudp: Convert bareudp_exit_batch_rtnl() to ->exit_rtnl().
    https://git.kernel.org/netdev/net-next/c/fc3dc33f668c
  - [v2,net-next,13/14] geneve: Convert geneve_exit_batch_rtnl() to ->exit_rtnl().
    https://git.kernel.org/netdev/net-next/c/4e53b32d74f0
  - [v2,net-next,14/14] net: Remove ->exit_batch_rtnl().
    https://git.kernel.org/netdev/net-next/c/c57a9c503543

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2025-04-15  0:30 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-11 20:52 [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 01/14] net: Factorise setup_net() and cleanup_net() Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 02/14] net: Add ops_undo_single for module load/unload Kuniyuki Iwashima
2025-04-15  0:01   ` Jakub Kicinski
2025-04-15  0:12     ` Jakub Kicinski
2025-04-15  0:17       ` Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 03/14] net: Add ->exit_rtnl() hook to struct pernet_operations Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 04/14] nexthop: Convert nexthop_net_exit_batch_rtnl() to ->exit_rtnl() Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 05/14] vxlan: Convert vxlan_exit_batch_rtnl() " Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 06/14] ipv4: ip_tunnel: Convert ip_tunnel_delete_nets() callers " Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 07/14] ipv6: Convert tunnel devices' ->exit_batch_rtnl() " Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 08/14] xfrm: Convert xfrmi_exit_batch_rtnl() " Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 09/14] bridge: Convert br_net_exit_batch_rtnl() " Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 10/14] bonding: Convert bond_net_exit_batch_rtnl() " Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 11/14] gtp: Convert gtp_net_exit_batch_rtnl() " Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 12/14] bareudp: Convert bareudp_exit_batch_rtnl() " Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 13/14] geneve: Convert geneve_exit_batch_rtnl() " Kuniyuki Iwashima
2025-04-11 20:52 ` [PATCH v2 net-next 14/14] net: Remove ->exit_batch_rtnl() Kuniyuki Iwashima
2025-04-14 14:12 ` [PATCH v2 net-next 00/14] net: Convert ->exit_batch_rtnl() to ->exit_rtnl() Sabrina Dubroca
2025-04-15  0:30 ` patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).