mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-28 20:42:49 +00:00
mnt: Carry run-time device ID in mount_info
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 v2: - predefine MOUNT_INVALID_DEV - use fetch_rt_stat instead of assigning device in restore_shared_options - copy @s_dev_rt in propagate_siblings and propagate_mount Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
0b0f40ecf8
commit
6217a84ae3
3 changed files with 45 additions and 5 deletions
|
|
@ -29,10 +29,13 @@ struct ext_mount {
|
|||
char *val;
|
||||
};
|
||||
|
||||
#define MOUNT_INVALID_DEV (0)
|
||||
|
||||
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
|
||||
|
|
|
|||
45
mount.c
45
mount.c
|
|
@ -1031,10 +1031,23 @@ int __open_mountpoint(struct mount_info *pm, int mnt_fd)
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (pm->s_dev_rt == MOUNT_INVALID_DEV) {
|
||||
pr_err("Resolving over unvalid device for %#x %s %s\n",
|
||||
pm->s_dev, pm->fstype->name, pm->ns_mountpoint);
|
||||
goto err;
|
||||
}
|
||||
|
||||
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);
|
||||
/*
|
||||
* Always check for @s_dev_rt here, because the @s_dev
|
||||
* from the image (in case of restore) has all rights
|
||||
* to not match the device (say it's migrated and kernel
|
||||
* allocates new device ID).
|
||||
*/
|
||||
if (dev != pm->s_dev_rt) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -2102,6 +2115,7 @@ static int propagate_siblings(struct mount_info *mi)
|
|||
continue;
|
||||
pr_debug("\t\tBind share %s\n", t->mountpoint);
|
||||
t->bind = mi;
|
||||
t->s_dev_rt = mi->s_dev_rt;
|
||||
}
|
||||
|
||||
list_for_each_entry(t, &mi->mnt_slave_list, mnt_slave) {
|
||||
|
|
@ -2109,6 +2123,7 @@ static int propagate_siblings(struct mount_info *mi)
|
|||
continue;
|
||||
pr_debug("\t\tBind slave %s\n", t->mountpoint);
|
||||
t->bind = mi;
|
||||
t->s_dev_rt = mi->s_dev_rt;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -2154,12 +2169,26 @@ skip_parent:
|
|||
if (t->master_id)
|
||||
continue;
|
||||
t->bind = mi;
|
||||
t->s_dev_rt = mi->s_dev_rt;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fetch_rt_stat(struct mount_info *m, const char *where)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(where, &st)) {
|
||||
pr_perror("Can't stat on %s\n", where);
|
||||
return -1;
|
||||
}
|
||||
|
||||
m->s_dev_rt = MKKDEV(major(st.st_dev), minor(st.st_dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Here are a set of flags which we know how to handle for the one mount call.
|
||||
* All of them except MS_RDONLY are set only as mnt flags.
|
||||
|
|
@ -2383,7 +2412,7 @@ static int do_mount_root(struct mount_info *mi)
|
|||
mi->shared_id, mi->master_id))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
return fetch_rt_stat(mi, mi->mountpoint);
|
||||
}
|
||||
|
||||
static int do_mount_one(struct mount_info *mi)
|
||||
|
|
@ -2409,6 +2438,9 @@ static int do_mount_one(struct mount_info *mi)
|
|||
else
|
||||
ret = do_bind_mount(mi);
|
||||
|
||||
if (ret == 0 && fetch_rt_stat(mi, mi->mountpoint))
|
||||
return -1;
|
||||
|
||||
if (ret == 0 && propagate_mount(mi))
|
||||
return -1;
|
||||
|
||||
|
|
@ -2510,6 +2542,11 @@ struct mount_info *mnt_entry_alloc()
|
|||
{
|
||||
struct mount_info *new;
|
||||
|
||||
/*
|
||||
* We rely on xzalloc here for MOUNT_INVALID_DEV.
|
||||
*/
|
||||
BUILD_BUG_ON(MOUNT_INVALID_DEV);
|
||||
|
||||
new = xzalloc(sizeof(struct mount_info));
|
||||
if (new) {
|
||||
INIT_LIST_HEAD(&new->children);
|
||||
|
|
|
|||
|
|
@ -1093,7 +1093,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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue