[CRIU] [PATCH] mnt: Carry run-time device ID in mount_info

Pavel Emelyanov xemul at parallels.com
Thu Dec 3 04:01:11 PST 2015


On 12/02/2015 06:57 PM, Cyrill Gorcunov wrote:
> When we're restoring fsnotify watchees we need to resolve
> path to a handle at some mountpoint referred by @s_dev
> member (device ID) which is saved inside image. This
> ID actually may be changed at the every mount (say
> one restores container after machine reboot) or in
> case of container's migration.
> 
> Thus the test for overmounting in __open_mountpoint
> will fail and we get an error.
> 
> Lets do a trick: introduce @s_dev_rt member which
> is supposed to carry run-time device ID. When dumping
> this member simply equal to traditional @s_dev fetched
> from the procfs, but when restoring we fetch it from
> stat call once mountpoint become alive.
> 
> https://jira.sw.ru/browse/PSBM-41610
> 
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
> 
> Guys, take a look please.
> 
>  include/mount.h |  1 +
>  mount.c         | 27 ++++++++++++++++++++++++---
>  proc_parse.c    |  2 +-
>  3 files changed, 26 insertions(+), 4 deletions(-)
> 
> diff --git a/include/mount.h b/include/mount.h
> index c3abc8479965..6831adf84910 100644
> --- a/include/mount.h
> +++ b/include/mount.h
> @@ -33,6 +33,7 @@ struct mount_info {
>  	int			mnt_id;
>  	int			parent_mnt_id;
>  	unsigned int		s_dev;
> +	unsigned int		s_dev_rt;
>  	char			*root;
>  	/*
>  	 * During dump mountpoint contains path with dot at the
> diff --git a/mount.c b/mount.c
> index 25fbc134ebe1..253025cb4971 100644
> --- a/mount.c
> +++ b/mount.c
> @@ -1009,9 +1009,18 @@ int __open_mountpoint(struct mount_info *pm, int mnt_fd)
>  	}
>  
>  	dev = phys_stat_resolve_dev(pm->nsid, st.st_dev, pm->ns_mountpoint + 1);
> -	if (dev != pm->s_dev) {
> -		pr_err("The file system %#x (%#x) %s %s is inaccessible\n",
> -		       pm->s_dev, (int)dev, pm->fstype->name, pm->ns_mountpoint);
> +	/*
> +	 * To prevent overmount clash we use two entries
> +	 * @s_dev and @s_dev_rt.  On dump @s_dev = @s_dev_rt
> +	 * obtained from procfs parsing but on restore @s_dev_rt
> +	 * may differ with one obtained from the image: the device
> +	 * ID may be new on provided by the kernel itself on new
> +	 * mount.
> +	 */
> +	if (dev != pm->s_dev && dev != pm->s_dev_rt) {

The first comparison is wrong, a "new" device can by chance coincide with
some "old" one and we'll have erroneous "open_mountpoint is OK".

Also here should go BUG_ON(pm->s_dev_rt == NON_INITIALIZED).

> +		pr_err("The file system %#x %#x (%#x) %s %s is inaccessible\n",
> +		       pm->s_dev, pm->s_dev_rt, (int)dev,
> +		       pm->fstype->name, pm->ns_mountpoint);
>  		goto err;
>  	}
>  
> @@ -1795,9 +1804,21 @@ static char *resolve_source(struct mount_info *mi)
>  
>  static int restore_shared_options(struct mount_info *mi, bool private, bool shared, bool slave)
>  {
> +	struct stat st;
> +
>  	pr_debug("%d:%s private %d shared %d slave %d\n",
>  			mi->mnt_id, mi->mountpoint, private, shared, slave);
>  
> +	/*
> +	 * Fetch runtime device once we're mounted for mount
> +	 * resolving when device has been migrated.
> +	 */
> +	if (stat(mi->mountpoint, &st)) {
> +		pr_perror("Can't stat on %s\n", mi->mountpoint);
> +		return -1;
> +	}
> +	mi->s_dev_rt = MKKDEV(major(st.st_dev), minor(st.st_dev));

This stat() should in in do_mount_one() after the 

        if (!mi->parent) {
                /* do_mount_root() is called from populate_mnt_ns() */
                mi->mounted = true;
                ret = 0;
        } else if (!mi->bind && !mi->need_plugin && !mi->external)
                ret = do_new_mount(mi);
        else
                ret = do_bind_mount(mi);

and also propagate_mount() should copy the s_dev_rt on all the auto-propagated
mountpoints.

> +
>  	if (mi->flags & MS_UNBINDABLE) {
>  		if (shared || slave)
>  			pr_warn("%s has both unbindable and sharing, ignoring unbindable\n", mi->mountpoint);
> diff --git a/proc_parse.c b/proc_parse.c
> index 3d924b2f68d5..4d67a13188bd 100644
> --- a/proc_parse.c
> +++ b/proc_parse.c
> @@ -1041,7 +1041,7 @@ static int parse_mountinfo_ent(char *str, struct mount_info *new, char **fsname)
>  	if (!new->mountpoint)
>  		goto err;
>  
> -	new->s_dev = MKKDEV(kmaj, kmin);
> +	new->s_dev = new->s_dev_rt = MKKDEV(kmaj, kmin);
>  	new->flags = 0;
>  	if (parse_mnt_flags(opt, &new->flags))
>  		goto err;
> 



More information about the CRIU mailing list