[CRIU] [PATCH 1/2] mount: create a mount point for the root mount namespace in the roots yard
Andrei Vagin
avagin at openvz.org
Thu Oct 20 12:06:59 PDT 2016
From: Andrei Vagin <avagin at virtuozzo.com>
These chnages allows us to:
* avoid difference between the root mount namespace and other mount namespaces
* support a read-only root mount
* don't create temporary directories in the root mount
Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
criu/include/path.h | 5 +-
criu/mount.c | 205 ++++++++++------------------------------------------
2 files changed, 42 insertions(+), 168 deletions(-)
diff --git a/criu/include/path.h b/criu/include/path.h
index 5fec3a9..b00c64a 100644
--- a/criu/include/path.h
+++ b/criu/include/path.h
@@ -1,6 +1,9 @@
#ifndef __CR_PATH_H__
#define __CR_PATH_H__
+#include "namespaces.h"
+#include "pstree.h"
+
/* Asolute paths are used on dump and relative paths are used on restore */
static inline int is_root(char *p)
{
@@ -10,7 +13,7 @@ static inline int is_root(char *p)
/* True for the root mount (the topmost one) */
static inline int is_root_mount(struct mount_info *mi)
{
- return is_root(mi->mountpoint + 1);
+ return mi->parent == NULL && mi->nsid->id == root_item->ids->mnt_ns_id;
}
/*
diff --git a/criu/mount.c b/criu/mount.c
index bb1378d..ba177f3 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -361,9 +361,10 @@ static struct mount_info *mnt_build_ids_tree(struct mount_info *list, struct mou
if (!parent) {
/* This should be / */
- if (root == NULL && is_root_mount(m)) {
+ if (root == NULL && (!tmp_root_mount || is_root_mount(m))) {
root = m;
- continue;
+ if (!tmp_root_mount)
+ continue;
}
pr_debug("Mountpoint %d (@%s) w/o parent %d\n",
@@ -395,7 +396,7 @@ static struct mount_info *mnt_build_ids_tree(struct mount_info *list, struct mou
pr_debug("Mountpoint %d (@%s) get parent %d (@%s)\n",
m->mnt_id, m->mountpoint,
parent->mnt_id, parent->mountpoint);
- } else {
+ } else if (root != m) {
pr_err("No root found for mountpoint %d (@%s)\n",
m->mnt_id, m->mountpoint);
return NULL;
@@ -411,10 +412,8 @@ static struct mount_info *mnt_build_ids_tree(struct mount_info *list, struct mou
return NULL;
}
- if (tmp_root_mount) {
- tmp_root_mount->parent = root;
- list_add_tail(&tmp_root_mount->siblings, &root->children);
- }
+ if (tmp_root_mount)
+ return tmp_root_mount;
return root;
}
@@ -634,7 +633,7 @@ static struct mount_info *find_fsroot_mount_for(struct mount_info *bm)
list_for_each_entry(sm, &bm->mnt_bind, mnt_bind)
if (fsroot_mounted(sm) ||
- (sm->parent == NULL &&
+ (sm->parent == root_yard_mp &&
strstartswith(bm->root, sm->root)))
return sm;
@@ -1642,7 +1641,7 @@ skip_parent:
* FIXME Currently non-root mounts can be restored
* only if a proper root mount exists
*/
- if (fsroot_mounted(mi) || mi->parent == NULL) {
+ if (fsroot_mounted(mi) || mi->parent == root_yard_mp) {
list_for_each_entry(t, &mi->mnt_bind, mnt_bind) {
if (t->mounted)
continue;
@@ -1984,10 +1983,14 @@ err:
return exit_code;
}
+static bool rst_mnt_is_root(struct mount_info *m)
+{
+ return (m->is_ns_root && m->nsid->id == root_item->ids->mnt_ns_id);
+}
+
static bool can_mount_now(struct mount_info *mi)
{
- /* The root mount */
- if (!mi->parent)
+ if (rst_mnt_is_root(mi))
return true;
if (mi->external)
@@ -2060,7 +2063,7 @@ static int do_mount_one(struct mount_info *mi)
return 1;
}
- if (mi->parent && !strcmp(mi->parent->mountpoint, mi->mountpoint)) {
+ if (!strcmp(mi->parent->mountpoint, mi->mountpoint)) {
mi->parent->fd = open(mi->parent->mountpoint, O_PATH);
if (mi->parent->fd < 0) {
pr_perror("Unable to open %s", mi->mountpoint);
@@ -2070,8 +2073,12 @@ static int do_mount_one(struct mount_info *mi)
pr_debug("\tMounting %s @%s (%d)\n", mi->fstype->name, mi->mountpoint, mi->need_plugin);
- if (!mi->parent) {
+ if (rst_mnt_is_root(mi)) {
/* do_mount_root() is called from populate_mnt_ns() */
+ if (mount(opts.root, mi->mountpoint, NULL, MS_BIND | MS_REC, NULL))
+ return -1;
+ if (do_mount_root(mi))
+ return -1;
mi->mounted = true;
ret = 0;
} else if (!mi->bind && !mi->need_plugin && !mi->external)
@@ -2144,33 +2151,10 @@ static int do_mnt_remap(struct mount_info *m)
{
int len;
- if (m->nsid->type == NS_OTHER) {
- /*
- * m->mountpoint already contains a roots_yard prefix and
- * it has a fixed size, so it can be just replaced.
- */
- len = print_ns_root(m->nsid, remap_id, m->mountpoint, PATH_MAX);
- m->mountpoint[len] = '/';
- } else if (m->nsid->type == NS_ROOT) {
- char root[PATH_MAX], *mp, *ns_mp;
- int len, ret;
+ /* A path in root_yard has a fixed size, so it can be replaced. */
+ len = print_ns_root(m->nsid, remap_id, m->mountpoint, PATH_MAX);
+ m->mountpoint[len] = '/';
- /*
- * Allocate a new path in the roots yard. m->mountpoint in the
- * root namespace doesn't have a roots_yard prefix, so its
- * size has to be changed and a new storage has to be
- * allocated.
- */
- mp = m->mountpoint; ns_mp = m->ns_mountpoint;
-
- len = print_ns_root(m->nsid, remap_id, root, PATH_MAX);
-
- ret = get_mp_mountpoint(ns_mp, m, root, len);
- if (ret < 0)
- return ret;
- xfree(mp);
- } else
- BUG();
return 0;
}
@@ -2231,14 +2215,9 @@ static int move_back_mnt_remaps()
char path[PATH_MAX];
int len;
- if (m->nsid->type == NS_ROOT) {
- path[0] = '.';
- strncpy(path + 1, m->ns_mountpoint, PATH_MAX - 1);
- } else {
- strncpy(path, m->mountpoint, PATH_MAX);
- len = print_ns_root(m->nsid, 0, path, PATH_MAX);
- path[len] = '/';
- }
+ strncpy(path, m->mountpoint, PATH_MAX);
+ len = print_ns_root(m->nsid, 0, path, PATH_MAX);
+ path[len] = '/';
pr_debug("Move mount %s -> %s\n", m->mountpoint, path);
if (mount(m->mountpoint, path, NULL, MS_MOVE, NULL)) {
@@ -2368,23 +2347,12 @@ static inline int print_ns_root(struct ns_id *ns, int remap_id, char *buf, int b
static int create_mnt_roots(void)
{
- int exit_code = -1, cwd_fd;
+ int exit_code = -1;
if (mnt_roots)
return 0;
- cwd_fd = open(".", O_DIRECTORY);
- if (cwd_fd < 0) {
- pr_perror("Unable to open cwd");
- return -1;
- }
-
- if (chdir(opts.root ? : "/")) {
- pr_perror("Unable to change working directory on %s", opts.root);
- goto out;
- }
-
- mnt_roots = strdup(".criu.mntns.XXXXXX");
+ mnt_roots = strdup("/tmp/.criu.mntns.XXXXXX");
if (mnt_roots == NULL) {
pr_perror("Can't allocate memory");
goto out;
@@ -2395,15 +2363,10 @@ static int create_mnt_roots(void)
mnt_roots = NULL;
goto out;
}
+ chmod(mnt_roots, 0777);
exit_code = 0;
out:
- if (fchdir(cwd_fd)) {
- pr_perror("Unable to restore cwd");
- exit_code = -1;
- }
- close(cwd_fd);
-
return exit_code;
}
@@ -2503,8 +2466,7 @@ static int collect_mnt_from_image(struct mount_info **pms, struct ns_id *nsid)
if (!img)
return -1;
- if (nsid->type == NS_OTHER)
- root_len = print_ns_root(nsid, 0, root, sizeof(root));
+ root_len = print_ns_root(nsid, 0, root, sizeof(root));
pr_debug("Reading mountpoint images (id %d pid %d)\n",
nsid->id, (int)nsid->ns_pid);
@@ -2624,8 +2586,7 @@ int rst_get_mnt_root(int mnt_id, char *path, int plen)
if (m == NULL)
return -1;
- if (m->nsid->type == NS_OTHER)
- return print_ns_root(m->nsid, 0, path, plen);
+ return print_ns_root(m->nsid, 0, path, plen);
rroot:
path[0] = '/';
@@ -2635,28 +2596,10 @@ rroot:
int mntns_maybe_create_roots(void)
{
- struct ns_id *ns;
-
if (!(root_ns_mask & CLONE_NEWNS))
return 0;
- for (ns = ns_ids; ns != NULL; ns = ns->next) {
- if (ns->nd != &mnt_ns_desc)
- continue;
-
- if (ns->type != NS_ROOT) {
- BUG_ON(ns->type == NS_CRIU);
-
- /*
- * If we have more than one (root) namespace,
- * then we'll need the roots yard.
- */
- return create_mnt_roots();
- }
- }
-
- /* No "other" mntns found, just go ahead, we don't need roots yard. */
- return 0;
+ return create_mnt_roots();
}
static int do_restore_task_mnt_ns(struct ns_id *nsid, struct pstree_item *current)
@@ -2679,6 +2622,9 @@ static int do_restore_task_mnt_ns(struct ns_id *nsid, struct pstree_item *curren
int restore_task_mnt_ns(struct pstree_item *current)
{
+ if ((root_ns_mask & CLONE_NEWNS) == 0)
+ return 0;
+
if (current->ids && current->ids->has_mnt_ns_id) {
unsigned int id = current->ids->mnt_ns_id;
struct ns_id *nsid;
@@ -2692,7 +2638,7 @@ int restore_task_mnt_ns(struct pstree_item *current)
* already there, otherwise it will have to do
* setns().
*/
- if (!current->parent || id == current->parent->ids->mnt_ns_id)
+ if (current->parent && id == current->parent->ids->mnt_ns_id)
return 0;
nsid = lookup_ns_by_id(id, &mnt_ns_desc);
@@ -2721,8 +2667,7 @@ void fini_restore_mntns(void)
if (nsid->nd != &mnt_ns_desc)
continue;
close_safe(&nsid->mnt.ns_fd);
- if (nsid->type != NS_ROOT)
- close_safe(&nsid->mnt.root_fd);
+ close_safe(&nsid->mnt.root_fd);
nsid->ns_populated = true;
}
}
@@ -2736,9 +2681,6 @@ static int populate_roots_yard(void)
char path[PATH_MAX];
struct ns_id *nsid;
- if (mnt_roots == NULL)
- return 0;
-
if (make_yard(mnt_roots))
return -1;
@@ -2811,14 +2753,6 @@ static int populate_mnt_ns(void)
if (handle_overmounts(pms))
return -1;
- /*
- * Set properties for the root before mounting a root yard,
- * otherwise the root yard can be propagated into the host
- * mntns and remain there.
- */
- if (do_mount_root(pms))
- return -1;
-
if (populate_roots_yard())
return -1;
@@ -2836,7 +2770,7 @@ static int populate_mnt_ns(void)
return ret;
}
-static int __depopulate_roots_yard(void)
+int __depopulate_roots_yard(void)
{
int ret = 0;
@@ -2961,64 +2895,11 @@ int prepare_mnt_ns(void)
pr_info("Cleaning mount namespace\n");
if (mnt_tree_for_each_reverse(ns.mnt.mntinfo_tree, do_umount_one))
return -1;
- } else {
- struct mount_info *mi;
- char *ret;
- char path[PATH_MAX];
-
- /*
- * The whole tree of mountpoints is to be moved into one
- * place with the pivot_root() call. Don't do manual
- * umount (as we do above), all this stuff will go away
- * with a single umount call later.
- */
-
- ret = realpath(opts.root, path);
- if (!ret) {
- pr_err("Unable to find real path for %s\n", opts.root);
- return -1;
- }
-
- /* moving a mount residing under a shared mount is invalid. */
- mi = mount_resolve_path(ns.mnt.mntinfo_tree, path);
- if (mi == NULL) {
- pr_err("Unable to find mount point for %s\n", opts.root);
- return -1;
- }
- if (mi->parent == NULL) {
- pr_err("New root and old root are the same\n");
- return -1;
- }
-
- /* Our root is mounted over the parent (in the same directory) */
- if (!strcmp(mi->parent->mountpoint, mi->mountpoint)) {
- pr_err("The parent of the new root is unreachable\n");
- return -1;
- }
-
- if (mount("none", mi->parent->mountpoint + 1, "none", MS_SLAVE, NULL)) {
- pr_perror("Can't remount the parent of the new root with MS_SLAVE");
- return -1;
- }
-
- /* Unprivileged users can't reveal what is under a mount */
- if (root_ns_mask & CLONE_NEWUSER) {
- if (mount(opts.root, opts.root, NULL, MS_BIND | MS_REC, NULL)) {
- pr_perror("Can't remount bind-mount %s into itself", opts.root);
- return -1;
- }
- }
- if (chdir(opts.root)) {
- pr_perror("chdir(%s) failed", opts.root ? : "/");
- return -1;
- }
}
free_mntinfo(old);
ret = populate_mnt_ns();
- if (!ret && opts.root)
- ret = cr_pivot_root(NULL);
if (ret)
return -1;
@@ -3032,16 +2913,6 @@ int prepare_mnt_ns(void)
if (nsid->nd != &mnt_ns_desc)
continue;
- if (nsid->type == NS_ROOT) {
- /* Pin one with a file descriptor */
- nsid->mnt.ns_fd = open_proc(PROC_SELF, "ns/mnt");
- if (nsid->mnt.ns_fd < 0)
- goto err;
- /* we set ns_populated so we don't need to open root_fd */
- nsid->ns_populated = true;
- continue;
- }
-
/* Create the new mount namespace */
if (unshare(CLONE_NEWNS)) {
pr_perror("Unable to create a new mntns");
--
2.7.4
More information about the CRIU
mailing list