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

path: simplify mnt_get_sibling_path via get_relative_path

Previous code did:

1) get rpath: mount's mountpoint relative to it's parent mountpoint
2) get cut_root: parent's root relative to parent's slave root or vice
versa (will be "-" if parents root is wider of "+" if thicker)
3) return parent's slave mountpoint +/- cut_root + rpath

It can be done more robust with get_relative_path:

1) get rpath: mount's mountpoint relative to it's parent mountpoint
2) get fsrpath: add rpath to parent's root (path relative to fs root)
3) get rpath: fsrpath relative to parent's slave root
4) return parent's slave mountpoint + rpath

In the latter approach we do not need to open code workarounds for
consequent slashes in paths (get_relative_path would do this for us),
and we also do not need to have complex logic with +/-.

While on it let's also switch ->mountpoint to ->ns_mountpoint where
possible, as mountpoint can have unexpected prefixes.

Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/0fd09f8571

Changes: rework mnt_get_sibling_path more.

Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This commit is contained in:
Pavel Tikhomirov
2021-12-01 12:52:27 +03:00
committed by Andrei Vagin
parent abbc70adc9
commit f2bf6597ca
2 changed files with 19 additions and 50 deletions

View File

@@ -2040,6 +2040,8 @@ static int umount_from_slaves(struct mount_info *mi)
struct mount_info *t;
char *mpath, buf[PATH_MAX];
BUG_ON(mi->parent == root_yard_mp);
list_for_each_entry(t, &mi->parent->mnt_slave_list, mnt_slave) {
if (!t->mounted)
continue;
@@ -2107,7 +2109,7 @@ static int propagate_mount(struct mount_info *mi)
propagate_siblings(mi);
if (!mi->parent)
if (!mi->parent || mi->parent == root_yard_mp)
goto skip_parent;
umount_from_slaves(mi);

View File

@@ -6,6 +6,7 @@
#include "mount.h"
#include "path.h"
#include "log.h"
#include "util.h"
#include "common/bug.h"
char *cut_root_for_bind(char *target_root, char *source_root)
@@ -41,64 +42,30 @@ out:
char *mnt_get_sibling_path(struct mount_info *m, struct mount_info *p, char *buf, int len)
{
struct mount_info *pa = m->parent;
char *rpath, *cut_root, *path = buf;
int off = 0;
char *rpath, fsrpath[PATH_MAX];
if (pa == NULL)
return NULL;
rpath = m->mountpoint + strlen(pa->mountpoint);
if (rpath[0] == '/')
rpath++;
/*
* Get a path to a sibling of "m" with parent "p",
* return NULL is p can't have a sibling of m.
*
* Here are two cases:
* When a parent of "m" has longer root than "p":
* / pm->root / rpath
* | cut_root |
* / p->root /
* In this case, a sibling path is a sum of p->mountpoint,
* cut_root and rpath.
*
* When a parent of m has shorter root than "p":
* / pm->root / rpath
* | cut_root |
* / p->root / rpath +strlen(cut_root)
* In this case, a sibling path is a sum of p->mountpoint and
* rpath - strlen(cut_root).
*/
cut_root = cut_root_for_bind(pa->root, p->root);
if (cut_root == NULL)
rpath = get_relative_path(m->ns_mountpoint, pa->ns_mountpoint);
if (!rpath) {
pr_warn("child - parent mountpoint missmatch %s - %s\n", m->ns_mountpoint, pa->ns_mountpoint);
return NULL;
if (p->mountpoint[1] != 0) /* not "/" */ {
off = snprintf(path, len, "%s", p->mountpoint);
if (path[off - 1] == '/') /* p->mountpoint = "./" */
off--;
}
len -= off;
path += off;
if (strlen(pa->root) > strlen(p->root)) {
off = snprintf(path, len, "/%s", cut_root);
len -= off;
path += off;
} else {
int length = strlen(cut_root);
if (strncmp(rpath, cut_root, length))
return NULL;
rpath += strlen(cut_root);
if (length > 0 && (rpath[0] && rpath[0] != '/'))
return NULL;
if (snprintf(fsrpath, sizeof(fsrpath), "%s/%s", pa->root, rpath) >= sizeof(fsrpath)) {
pr_warn("snrptintf truncation \"%s / %s\"\n", pa->root, rpath);
return NULL;
}
if (rpath[0] == '/')
rpath++;
if (rpath[0] != '\0')
snprintf(path, len, "/%s", rpath);
rpath = get_relative_path(fsrpath, p->root);
if (!rpath)
return NULL;
if (snprintf(buf, len, "%s/%s", p->ns_mountpoint, rpath) >= sizeof(fsrpath)) {
pr_warn("snrptintf truncation \"%s / %s\"\n", p->ns_mountpoint, rpath);
return NULL;
}
return buf;
}