The commit is pushed to "branch-rh7-3.10.0-514.26.1.vz7.35.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git after rh7-3.10.0-514.26.1.vz7.35.3 ------> commit 049382b868b944f91c154bab238eb94c45ce476a Author: Konstantin Khorenko <khore...@virtuozzo.com> Date: Fri Aug 11 18:50:12 2017 +0400
ve/fs/mount: pin mnt to a VE for correct number of mounts accounting If a mount is done in one VE context and umount - in another, counters ve->mnt_nr became unbalanced and this can cause denial of new mounts due to per-VE numbre of mounts limit. Additionally move related functions to fs/namespace.c to avoid adding fs/mount.h into ve.h: ve_mount_nr_inc() ve_mount_nr_dec() ve_mount_allowed() Example: mount is done from inside a CT, umount - from host => ve->mnt_nr gets incorrectly increased for a CT. https://jira.sw.ru/browse/PSBM-69880 Signed-off-by: Konstantin Khorenko <khore...@virtuozzo.com> Reviewed-by: Kirill Tkhai <ktk...@virtuozzo.com> --- fs/mount.h | 3 +++ fs/namespace.c | 41 ++++++++++++++++++++++++++++++++++++++--- include/linux/ve.h | 27 +-------------------------- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/fs/mount.h b/fs/mount.h index 013152b..77f50cc 100644 --- a/fs/mount.h +++ b/fs/mount.h @@ -41,6 +41,9 @@ struct mount { struct mount *mnt_master; /* slave is on master->mnt_slave_list */ struct mnt_namespace *mnt_ns; /* containing namespace */ struct mountpoint *mnt_mp; /* where is it mounted */ +#ifdef CONFIG_VE + struct ve_struct *ve_owner; /* VE in which this mount was created */ +#endif /* CONFIG_VE */ #ifdef CONFIG_FSNOTIFY struct hlist_head mnt_fsnotify_marks; __u32 mnt_fsnotify_mask; diff --git a/fs/namespace.c b/fs/namespace.c index f2d1f84..2cf7f9a 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -163,6 +163,10 @@ unsigned 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); +static inline void ve_mount_nr_dec(struct mount *mnt); + static struct mount *alloc_vfsmnt(const char *name) { struct mount *mnt; @@ -211,7 +215,7 @@ static struct mount *alloc_vfsmnt(const char *name) INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks); #endif } - ve_mount_nr_inc(); + ve_mount_nr_inc(mnt); return mnt; #ifdef CONFIG_SMP @@ -552,7 +556,7 @@ int sb_prepare_remount_readonly(struct super_block *sb) static void free_vfsmnt(struct mount *mnt) { - ve_mount_nr_dec(); + ve_mount_nr_dec(mnt); kfree(mnt->mnt_devname); mnt_free_id(mnt); #ifdef CONFIG_SMP @@ -2012,7 +2016,38 @@ int ve_devmnt_process(struct ve_struct *ve, dev_t dev, void **data_pp, int remou return err; } -#endif + +static inline int ve_mount_allowed(void) +{ + struct ve_struct *ve = get_exec_env(); + + return ve_is_super(ve) || + atomic_read(&ve->mnt_nr) < (int)sysctl_ve_mount_nr; +} + +static inline void ve_mount_nr_inc(struct mount *mnt) +{ + struct ve_struct *ve = get_exec_env(); + + mnt->ve_owner = get_ve(ve); + atomic_inc(&ve->mnt_nr); +} + +static inline void ve_mount_nr_dec(struct mount *mnt) +{ + struct ve_struct *ve = mnt->ve_owner; + + atomic_dec(&ve->mnt_nr); + put_ve(ve); + mnt->ve_owner = NULL; +} + +#else /* CONFIG_VE */ + +static inline int ve_mount_allowed(void) { return 1; } +static inline void ve_mount_nr_inc(struct mount *mnt) { } +static inline void ve_mount_nr_dec(struct mount *mnt) { } +#endif /* CONFIG_VE */ static int do_check_and_remount_sb(struct super_block *sb, int flags, void *data) { diff --git a/include/linux/ve.h b/include/linux/ve.h index f430ccd..c9b0af4 100644 --- a/include/linux/ve.h +++ b/include/linux/ve.h @@ -119,10 +119,7 @@ struct ve_struct { int netns_max_nr; atomic_t netif_avail_nr; int netif_max_nr; - /* Number of mounts. May become unbalanced if VE0 mounts something - * and the VE unmounts it. This is acceptable. - */ - atomic_t mnt_nr; + atomic_t mnt_nr; /* number of present VE mounts */ #ifdef CONFIG_COREDUMP char core_pattern[CORENAME_MAX_SIZE]; #endif @@ -228,24 +225,6 @@ extern void vtty_release(struct tty_struct *tty, struct tty_struct *o_tty, extern bool vtty_is_master(struct tty_struct *tty); #endif /* CONFIG_TTY */ -static inline int ve_mount_allowed(void) -{ - struct ve_struct *ve = get_exec_env(); - - return ve_is_super(ve) || - atomic_read(&ve->mnt_nr) < (int)sysctl_ve_mount_nr; -} - -static inline void ve_mount_nr_inc(void) -{ - atomic_inc(&get_exec_env()->mnt_nr); -} - -static inline void ve_mount_nr_dec(void) -{ - atomic_dec(&get_exec_env()->mnt_nr); -} - #else /* CONFIG_VE */ #define ve_uevent_seqnum uevent_seqnum @@ -279,10 +258,6 @@ static inline void monotonic_abs_to_ve(clockid_t which_clock, struct timespec *tp) { } static inline void monotonic_ve_to_abs(clockid_t which_clock, struct timepsec *tp) { } - -static inline int ve_mount_allowed(void) { return 1; } -static inline void ve_mount_nr_inc(void) { } -static inline void ve_mount_nr_dec(void) { } #endif /* CONFIG_VE */ struct seq_file; _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel