[Devel] [PATCH VZ10 4/8] ve/net: thread owning ve through copy_net_ns
Vasileios Almpanis
vasileios.almpanis at virtuozzo.com
Thu Apr 30 11:19:21 MSK 2026
Reviewed-by: Vasileios Almpanis <vasileios.almpanis at virtuozzo.com>
On 4/29/26 3:41 PM, Pavel Tikhomirov wrote:
> Add new_ve parameter to copy_net_ns(). NULL preserves the existing
> behaviour of taking current ve via get_exec_env().
>
> This will be used to derive correct ownership of newly created net
> namespace in case of simultaneous creation of new ve namespace and net
> namespace, were we would like new net namespace having the new ve as an
> owner.
>
> While on it, move ve reference count handling from setup_net() to
> copy_net_ns(), since we already handle dec/inc_netns_avail() up there.
> This way we don't need to thread it also to setup_net(). That is
> also consistent with how user_ns is threaded.
>
> The init_net.owner_ve is now set explicitly to &ve0 in net_ns_init()
> since setup_net() no longer does it for the boot-time call.
>
> There is no change in behaviour yet: create_new_namespaces() still uses
> NULL.
>
> https://virtuozzo.atlassian.net/browse/VSTOR-129744
> Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
> Feature: ve: ve generic structures
> ---
> include/net/net_namespace.h | 7 +++++--
> kernel/nsproxy.c | 3 ++-
> net/core/net_namespace.c | 33 +++++++++++++++++++++++----------
> 3 files changed, 30 insertions(+), 13 deletions(-)
>
> diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
> index ed077747f710..dd0edb96f0ee 100644
> --- a/include/net/net_namespace.h
> +++ b/include/net/net_namespace.h
> @@ -203,9 +203,11 @@ struct net {
> /* Init's network namespace */
> extern struct net init_net;
>
> +struct ve_struct;
> +
> #ifdef CONFIG_NET_NS
> struct net *copy_net_ns(unsigned long flags, struct user_namespace *user_ns,
> - struct net *old_net);
> + struct net *old_net, struct ve_struct *new_ve);
>
> void net_ns_get_ownership(const struct net *net, kuid_t *uid, kgid_t *gid);
>
> @@ -218,7 +220,8 @@ struct net *get_net_ns_by_fd(int fd);
> #include <linux/sched.h>
> #include <linux/nsproxy.h>
> static inline struct net *copy_net_ns(unsigned long flags,
> - struct user_namespace *user_ns, struct net *old_net)
> + struct user_namespace *user_ns, struct net *old_net,
> + struct ve_struct *new_ve)
> {
> if (flags & CLONE_NEWNET)
> return ERR_PTR(-EINVAL);
> diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
> index 12de23ec80bf..1d0e8f9d98a3 100644
> --- a/kernel/nsproxy.c
> +++ b/kernel/nsproxy.c
> @@ -109,7 +109,8 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
> goto out_cgroup;
> }
>
> - new_nsp->net_ns = copy_net_ns(flags, user_ns, tsk->nsproxy->net_ns);
> + new_nsp->net_ns = copy_net_ns(flags, user_ns, tsk->nsproxy->net_ns,
> + NULL);
> if (IS_ERR(new_nsp->net_ns)) {
> err = PTR_ERR(new_nsp->net_ns);
> goto out_net;
> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
> index 40e74d956bc2..3738e5274cd9 100644
> --- a/net/core/net_namespace.c
> +++ b/net/core/net_namespace.c
> @@ -352,10 +352,6 @@ static __net_init int setup_net(struct net *net)
> LIST_HEAD(dev_kill_list);
> int error = 0;
>
> -#ifdef CONFIG_VE
> - net->owner_ve = get_ve(get_exec_env());
> -#endif
> -
> preempt_disable();
> net->net_cookie = gen_cookie_next(&net_cookie);
> preempt_enable();
> @@ -400,9 +396,6 @@ static __net_init int setup_net(struct net *net)
> ops_free_list(ops, &net_exit_list);
>
> rcu_barrier();
> -#ifdef CONFIG_VE
> - put_ve(net->owner_ve);
> -#endif
> goto out;
> }
>
> @@ -505,9 +498,10 @@ static void inc_netns_avail(struct ve_struct *ve)
> #endif
>
> struct net *copy_net_ns(unsigned long flags,
> - struct user_namespace *user_ns, struct net *old_net)
> + struct user_namespace *user_ns, struct net *old_net,
> + struct ve_struct *new_ve)
> {
> - struct ve_struct *ve = get_exec_env();
> + struct ve_struct *ve;
> struct ucounts *ucounts;
> struct net *net;
> int rv;
> @@ -515,6 +509,14 @@ struct net *copy_net_ns(unsigned long flags,
> if (!(flags & CLONE_NEWNET))
> return get_net(old_net);
>
> + /*
> + * The ve that should own the new netns. When called from
> + * copy_namespaces()/unshare_nsproxy_namespaces() with a freshly
> + * created CLONE_NEWVE in flight, @new_ve is supplied by the
> + * caller because get_exec_env() still resolves to the parent ve.
> + */
> + ve = new_ve ?: get_exec_env();
> +
> ucounts = inc_net_namespaces(user_ns);
> if (!ucounts)
> return ERR_PTR(-ENOSPC);
> @@ -538,16 +540,23 @@ struct net *copy_net_ns(unsigned long flags,
> preinit_net(net, user_ns);
> net->ucounts = ucounts;
> get_user_ns(user_ns);
> +#ifdef CONFIG_VE
> + net->owner_ve = get_ve(ve);
> +#endif
>
> rv = down_read_killable(&pernet_ops_rwsem);
> if (rv < 0)
> - goto put_userns;
> + goto put_owner_ve;
>
> rv = setup_net(net);
>
> up_read(&pernet_ops_rwsem);
>
> if (rv < 0) {
> +put_owner_ve:
> +#ifdef CONFIG_VE
> + put_ve(net->owner_ve);
> +#endif
> put_userns:
> #ifdef CONFIG_KEYS
> key_remove_domain(net->key_domain);
> @@ -1261,6 +1270,10 @@ void __init net_ns_init(void)
> #endif
> preinit_net(&init_net, &init_user_ns);
>
> +#ifdef CONFIG_VE
> + init_net.owner_ve = get_ve(&ve0);
> +#endif
> +
> down_write(&pernet_ops_rwsem);
> if (setup_net(&init_net))
> panic("Could not setup the initial network namespace");
--
Best regards, Vasileios Almpanis
Software Developer, Virtuozzo.
More information about the Devel
mailing list