2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-31 06:15:24 +00:00

mount: put all mounts which propagate from each other to a list

These information will help improving the restore of tricky mounts
configurations.

Function same_propagation_group checks if two mounts were created
simultaneousely through shared mount propagation, and the main part of
these - they should be in exaclty the same place inside the share of
their parents.

Function root_path_from_parent prints the mountpoint path
relative to the root of the parent's share, by first substracting
parent's mountpoint from our mountpoint and second prepending parents
root path (relative to the root of it's file system), e.g:

id	parent_id	root	mountpoint
1	0		/	/
2	1		/	/parent_a
3	1		/dir	/parent_b
4	2		/	/parent_a/dir/a
5	3		/	/parent_b/a

(Let 2 and 3 be a shared group)

For mount 4 root_path_from_parent gives:
"/parent_a/dir/a" - "/parent_a" == "/dir/a"
"/" + "/dir/a" == "/dir/a"

For mount 5:
"/parent_b/a" - "/parent_b" == "/a"
"/dir" + "/a" == "/dir/a"

So mounts 4 and 5 are a propagation group.

Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This commit is contained in:
Pavel Tikhomirov
2018-07-10 19:02:27 +03:00
committed by Andrei Vagin
parent 24bd5fcfff
commit bc930d120e
2 changed files with 99 additions and 0 deletions

View File

@@ -65,6 +65,7 @@ struct mount_info {
struct list_head mnt_slave_list; /* list of slave mounts */
struct list_head mnt_slave; /* slave list entry */
struct mount_info *mnt_master; /* slave is on master->mnt_slave_list */
struct list_head mnt_propagate; /* circular list of mounts which propagate from each other */
struct list_head postpone;

View File

@@ -931,6 +931,74 @@ static int resolve_external_mounts(struct mount_info *info)
return 0;
}
static int root_path_from_parent(struct mount_info *m, char *buf, int size)
{
bool head_slash = false, tail_slash = false;
int p_len = strlen(m->parent->mountpoint),
m_len = strlen(m->mountpoint),
len;
if (!m->parent)
return -1;
len = snprintf(buf, size, "%s", m->parent->root);
if (len >= size)
return -1;
BUG_ON(len <= 0);
if (buf[len-1] == '/')
tail_slash = true;
size -= len;
buf += len;
len = m_len - p_len;
BUG_ON(len < 0);
if (len) {
if (m->mountpoint[p_len] == '/')
head_slash = true;
len = snprintf(buf, size, "%s%s",
(!tail_slash && !head_slash) ? "/" : "",
m->mountpoint + p_len + (tail_slash && head_slash));
if (len >= size)
return -1;
}
return 0;
}
static int same_propagation_group(struct mount_info *a, struct mount_info *b) {
char root_path_a[PATH_MAX], root_path_b[PATH_MAX];
/*
* If mounts are in same propagation group:
* 1) Their parents should be different
* 2) Their parents should be together in same shared group
*/
if (!a->parent || !b->parent || a->parent == b->parent ||
a->parent->shared_id != b->parent->shared_id)
return 0;
if (root_path_from_parent(a, root_path_a, PATH_MAX)) {
pr_err("Failed to get root path for mount %d\n", a->mnt_id);
return -1;
}
if (root_path_from_parent(b, root_path_b, PATH_MAX)) {
pr_err("Failed to get root path for mount %d\n", b->mnt_id);
return -1;
}
/*
* 3) Their mountpoints relative to the root of the superblock of their
* parent's share should be equal
*/
if (!strcmp(root_path_a, root_path_b))
return 1;
return 0;
}
static int resolve_shared_mounts(struct mount_info *info, int root_master_id)
{
struct mount_info *m, *t;
@@ -1003,6 +1071,35 @@ static int resolve_shared_mounts(struct mount_info *info, int root_master_id)
}
}
/* Search propagation groups */
for (m = info; m; m = m->next) {
struct mount_info *sparent;
if (!list_empty(&m->mnt_propagate))
continue;
if (!m->parent || !m->parent->shared_id)
continue;
list_for_each_entry(sparent, &m->parent->mnt_share, mnt_share) {
struct mount_info *schild;
list_for_each_entry(schild, &sparent->children, siblings) {
int ret;
ret = same_propagation_group(m, schild);
if (ret < 0)
return -1;
else if (ret) {
BUG_ON(!mounts_equal(m, schild));
pr_debug("\tMount %3d is in same propagation group with %3d (@%s ~ @%s)\n",
m->mnt_id, schild->mnt_id, m->mountpoint, schild->mountpoint);
list_add(&schild->mnt_propagate, &m->mnt_propagate);
}
}
}
}
return 0;
}
@@ -2700,6 +2797,7 @@ struct mount_info *mnt_entry_alloc()
INIT_LIST_HEAD(&new->mnt_slave_list);
INIT_LIST_HEAD(&new->mnt_share);
INIT_LIST_HEAD(&new->mnt_bind);
INIT_LIST_HEAD(&new->mnt_propagate);
INIT_LIST_HEAD(&new->postpone);
}
return new;