[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