diff options
| author | Ingo Molnar <mingo@kernel.org> | 2024-03-25 13:32:29 +0300 | 
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2024-03-25 13:32:29 +0300 | 
| commit | f4566a1e73957800df75a3dd2dccee8a4697f327 (patch) | |
| tree | b043b875228c0b25988af66c680d60cae69d761d /net/core/net_namespace.c | |
| parent | b9e6e28663928cab836a19abbdec3d036a07db3b (diff) | |
| parent | 4cece764965020c22cff7665b18a012006359095 (diff) | |
| download | linux-f4566a1e73957800df75a3dd2dccee8a4697f327.tar.xz | |
Merge tag 'v6.9-rc1' into sched/core, to pick up fixes and to refresh the branch
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'net/core/net_namespace.c')
| -rw-r--r-- | net/core/net_namespace.c | 33 | 
1 files changed, 31 insertions, 2 deletions
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 72799533426b..f0540c557515 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -318,8 +318,9 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)  {  	/* Must be called with pernet_ops_rwsem held */  	const struct pernet_operations *ops, *saved_ops; -	int error = 0;  	LIST_HEAD(net_exit_list); +	LIST_HEAD(dev_kill_list); +	int error = 0;  	refcount_set(&net->ns.count, 1);  	ref_tracker_dir_init(&net->refcnt_tracker, 128, "net refcnt"); @@ -358,6 +359,15 @@ out_undo:  	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); @@ -573,6 +583,7 @@ static void cleanup_net(struct work_struct *work)  	struct net *net, *tmp, *last;  	struct llist_node *net_kill_list;  	LIST_HEAD(net_exit_list); +	LIST_HEAD(dev_kill_list);  	/* Atomically snapshot the list of namespaces to cleanup */  	net_kill_list = llist_del_all(&cleanup_list); @@ -611,7 +622,15 @@ static void cleanup_net(struct work_struct *work)  	 * the rcu_barrier() below isn't sufficient alone.  	 * Also the pre_exit() and exit() methods need this barrier.  	 */ -	synchronize_rcu(); +	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) @@ -1193,7 +1212,17 @@ static void free_exit_list(struct pernet_operations *ops, struct list_head *net_  {  	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);  }  | 
