[Devel] [PATCH VZ10 v6 3/9] ve/fs: Rework per-ve mount count

Vasileios Almpanis vasileios.almpanis at virtuozzo.com
Wed Aug 19 16:16:17 MSK 2026


> Previous approach with current mounts counter had an issue:
> there was a gap between ve_mount_allowed check and ve_mount_nr_inc,
> which could allow CT to have more mounts than expected.
> 
> Fix this by tracking the number of available mounts instead
> of current ones. This also makes resources accounting
> more consistent - we are using ***_avail_nr approach more.
> 
> One more issue with inconsistent ve value is fixed:
> ve_mount_allowed always used ve from get_exec_env, but
> ve_mount_nr_inc operated with owner_ve.
> Now actual ve value is calculated in the beginning of alloc_vfsmnt.
> 
> To avoid incorrect accounting when is_pseudosuper is changed,
> update avail_nr count without > 0 check if VE is ve0 or pseudosuper.
> This also simplifies ve_mount_put, since increment is
> now unconditional.
> 
> https://virtuozzo.atlassian.net/browse/VSTOR-135520
> 
> Feature: per-ve failcounters
> Signed-off-by: Vladimir Riabchun <vladimir.riabchun at virtuozzo.com>
>
> diff --git a/fs/namespace.c b/fs/namespace.c
> index 68e0efb73d7c..c9e2ab9b3b57 100644
> --- a/fs/namespace.c
> +++ b/fs/namespace.c
> @@ -317,18 +317,21 @@ int mnt_get_count(struct mount *mnt)
>  #endif
>  }
>  
> -static inline int ve_mount_allowed(void);
> -static inline void ve_mount_nr_inc(struct mount *mnt, struct ve_struct *ve);
> -static inline void ve_mount_nr_dec(struct mount *mnt);
> +static inline int ve_try_reserve_mount(struct ve_struct *ve);
> +static inline void ve_mount_put(struct mount *mnt, struct ve_struct *ve);
>  
>  static struct mount *alloc_vfsmnt(const char *name, struct ve_struct *owner_ve)
>  {
>  	struct mount *mnt;
> +	struct ve_struct *ve = owner_ve;
>  
> -	if (!ve_mount_allowed()) {
> +	if (!ve)
> +		ve = get_exec_env();
> +
> +	if (!ve_try_reserve_mount(ve)) {
>  		pr_warn_ratelimited(
>  			"CT#%s reached the limit on mounts.\n",
> -			ve_name(get_exec_env()));
> +			ve_name(ve));
>  		return NULL;
>  	}
>  
> @@ -336,6 +339,14 @@ static struct mount *alloc_vfsmnt(const char *name, struct ve_struct *owner_ve)
>  	if (mnt) {
>  		int err;
>  
> +#ifdef CONFIG_VE
> +		/*
> +		 * Got ve reference in ve_try_reserve_mount, set mnt ve data
> +		 * here, so in case of error ve_mount_put sees correct info.
> +		 */
> +		mnt->ve_owner = ve;
> +#endif
> +
>  		err = mnt_alloc_id(mnt);
>  		if (err)
>  			goto out_free_cache;
> @@ -370,7 +381,8 @@ static struct mount *alloc_vfsmnt(const char *name, struct ve_struct *owner_ve)
>  		INIT_LIST_HEAD(&mnt->mnt_umounting);
>  		INIT_HLIST_HEAD(&mnt->mnt_stuck_children);
>  		mnt->mnt.mnt_idmap = &nop_mnt_idmap;
> -		ve_mount_nr_inc(mnt, owner_ve);
> +	} else {
> +		ve_mount_put(mnt, ve);
>  	}
>  	return mnt;
>  
> @@ -381,6 +393,8 @@ static struct mount *alloc_vfsmnt(const char *name, struct ve_struct *owner_ve)
>  out_free_id:
>  	mnt_free_id(mnt);
>  out_free_cache:
> +	/* Got ve reference in ve_try_reserve_mount */
> +	ve_mount_put(mnt, ve);
>  	kmem_cache_free(mnt_cache, mnt);
>  	return NULL;
>  }
> @@ -750,7 +764,7 @@ int sb_prepare_remount_readonly(struct super_block *sb)
>  static void free_vfsmnt(struct mount *mnt)
>  {
>  	mnt_idmap_put(mnt_idmap(&mnt->mnt));
> -	ve_mount_nr_dec(mnt);
> +	ve_mount_put(mnt, mnt->ve_owner);
this breaks compilation with CONFIG_VE=n. ve_onwer doesn't exist there.
Easiest solution would be to just wrap it under ifdef since the getting
stub also does nothing incase CONFIG_VE=n

-- 
Vasileios Almpanis <vasileios.almpanis at virtuozzo.com>


More information about the Devel mailing list