diff options
author | Andrei Vagin <avagin@virtuozzo.com> | 2017-02-22 09:39:45 +0300 |
---|---|---|
committer | Andrei Vagin <avagin@virtuozzo.com> | 2017-03-02 00:19:02 +0300 |
commit | b6f7577109d1e940f9f3dc64539803d1eb2ca411 (patch) | |
tree | 97b242b72cb2225b186452f8bfe1d10cd08aea7c | |
parent | f830e0ff3491c49dc6fc24c24e35cc7934e5fded (diff) |
mount: restore mounts in the root mount namespace
Currently all mounts are restored in a one mount namespace, then
this namespace is cloned to restore other mount namespaces and
we need another copy of this namespace to clean link remap files.
Let's define terms:
A - the root mount namespace
B - the mount namespace where link remap files are destroyed
Currently we restore all mounts in the B namespace and then
clone it into the A namespace.
But it doesn't work in a case, when we have to open file
descriptores to restore mounts (e g to restore bind-mount
pty slaves), because a file descriptor has to be opened from
a specified mount (which is one of restore mount namespaces).
This patch reworks code so, that all mounts is restored in the A mount
namespace and then the B mount namespace is created. In this case
we can open files from the root mount namespace (A).
$ ./zdtm.py run -t zdtm/static/pty-console --iter 5
====================== Run zdtm/static/pty-console in ns =======================
Start test
Test is SUID
./pty-console --pidfile=pty-console.pid --outfile=pty-console.out
Run criu dump
Run criu restore
Run criu dump
=[log]=> dump/zdtm/static/pty-console/36/2/dump.log
------------------------ grep Error ------------------------
(00.106521) Error (criu/files-reg.c:1132): Can't lookup mount=563 for fd=4 path=/ptmx
(00.106585) Error (criu/cr-dump.c:1325): Dump files (pid: 70) failed with -1
(00.129041) Error (criu/cr-dump.c:1674): Dumping FAILED.
------------------------ ERROR OVER ------------------------
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
-rw-r--r-- | criu/cr-restore.c | 21 | ||||
-rw-r--r-- | criu/include/restorer.h | 5 | ||||
-rw-r--r-- | criu/mount.c | 32 |
3 files changed, 49 insertions, 9 deletions
diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 0c216566c..0712b4695 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -1319,6 +1319,9 @@ static int restore_task_with_children(void *_arg) if (prepare_namespace(current, ca->clone_flags)) goto err; + if (restore_finish_stage(task_entries, CR_STATE_POST_RESTORE_NS) < 0) + goto err; + if (root_prepare_shared()) goto err; @@ -1382,6 +1385,7 @@ static inline int stage_participants(int next_stage) case CR_STATE_FAIL: return 0; case CR_STATE_RESTORE_NS: + case CR_STATE_POST_RESTORE_NS: case CR_STATE_RESTORE_SHARED: return 1; case CR_STATE_FORKING: @@ -1737,16 +1741,25 @@ static int restore_root_task(struct pstree_item *init) if (ret) goto out_kill; + ret = run_scripts(ACT_SETUP_NS); + if (ret) + goto out_kill; + + ret = restore_switch_stage(CR_STATE_POST_RESTORE_NS); + if (ret < 0) + goto out_kill; + + pr_info("Wait until namespaces are created\n"); + ret = restore_wait_inprogress_tasks(); + if (ret) + goto out_kill; + if (root_ns_mask & CLONE_NEWNS) { mnt_ns_fd = open_proc(init->pid->real, "ns/mnt"); if (mnt_ns_fd < 0) goto out_kill; } - ret = run_scripts(ACT_SETUP_NS); - if (ret) - goto out_kill; - if (opts.empty_ns & CLONE_NEWNET) { /* * Local TCP connections were locked by network_lock_internal() diff --git a/criu/include/restorer.h b/criu/include/restorer.h index cb2221671..60246eff1 100644 --- a/criu/include/restorer.h +++ b/criu/include/restorer.h @@ -198,6 +198,11 @@ static inline unsigned long restorer_stack(struct restore_mem_zone *mz) enum { CR_STATE_FAIL = -1, CR_STATE_RESTORE_NS = 0, /* is used for executing "setup-namespace" scripts */ + /* + * Need to wait a mount namespace which + * will be used to clean up remap files. + */ + CR_STATE_POST_RESTORE_NS, CR_STATE_RESTORE_SHARED, CR_STATE_FORKING, CR_STATE_RESTORE, diff --git a/criu/mount.c b/criu/mount.c index 8f66b4e09..013b17e2f 100644 --- a/criu/mount.c +++ b/criu/mount.c @@ -2948,17 +2948,39 @@ int prepare_mnt_ns(void) goto err; } + if (nsid->type == NS_ROOT) { + int fd; + + /* + * We need to create a mount namespace which will be + * used to clean up remap files + * (depopulate_roots_yard). The namespace where mounts + * was restored has to be restored as a root mount + * namespace, because there are file descriptors + * linked with it (e.g. to bind-mount slave pty-s). + */ + fd = open_proc(PROC_SELF, "ns/mnt"); + if (fd < 0) + goto err; + if (setns(rst, CLONE_NEWNS)) { + pr_perror("Can't restore mntns back"); + goto err; + } + nsid->mnt.ns_fd = rst; + rst = fd; + } else { + /* Pin one with a file descriptor */ + nsid->mnt.ns_fd = open_proc(PROC_SELF, "ns/mnt"); + if (nsid->mnt.ns_fd < 0) + goto err; + } + /* Set its root */ path[0] = '/'; print_ns_root(nsid, 0, path + 1, sizeof(path) - 1); if (cr_pivot_root(path)) goto err; - /* Pin one with a file descriptor */ - nsid->mnt.ns_fd = open_proc(PROC_SELF, "ns/mnt"); - if (nsid->mnt.ns_fd < 0) - goto err; - /* root_fd is used to restore file mappings */ nsid->mnt.root_fd = open_proc(PROC_SELF, "root"); if (nsid->mnt.root_fd < 0) |