[CRIU] [PATCH 1/2] file: add a general approach for inherited files

Andrey Vagin avagin at openvz.org
Sat Feb 13 09:55:24 PST 2016


From: Andrew Vagin <avagin at virtuozzo.com>

How to restore an external file? The problem is that a file
can be opened with different flags (O_APPNED, O_RDWR, O_RONLY,
etc). These flags can't be changed for a file descriptor, so
we can't just duplicate an inherit fd, when we meet an external
file.

A file is external, when we can't access them directly.
CRIU is able to restore a file descriptor, if it knows
how to open it, so we need to provide a way to open
an external file.

The idea of this patch is that we can open an external file
via /proc/self/fd/X where X is an inherit fd.

This approach works for files and fifo.

An example how it can be used:
criu -o dump.log -D dump/fifo.py/6/1 -v4 -t 6 --external file[72:a3e7]
criu -o restore.log -D dump/fifo.py/6/1 -v4 --restore-sibling --inherit-fd fd[4]:file[72:a3e7] --restore-detached

https://github.com/xemul/criu/issues/104

Cc: Saied Kazemi <saied at google.com>
Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
 crtools.c              |  2 ++
 files-reg.c            | 34 ++++++++++++++++++++++++++++++----
 protobuf/regfile.proto |  1 +
 3 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/crtools.c b/crtools.c
index 4406029..5024751 100644
--- a/crtools.c
+++ b/crtools.c
@@ -782,6 +782,7 @@ usage:
 "  --external RES        dump objects from this list as external resources:\n"
 "                        Formats of RES:\n"
 "                            tty[rdev:dev]\n"
+"                            file[mnt_id:inode]\n"
 "  --inherit-fd fd[<num>]:<existing>\n"
 "                        Inherit file descriptors. This allows to treat file descriptor\n"
 "                        <num> as being already opened via <existing> one and instead of\n"
@@ -789,6 +790,7 @@ usage:
 "                            tty[rdev:dev]\n"
 "                            pipe[inode]\n"
 "                            socket[inode]\n"
+"                            file[mnt_id:inode]\n"
 "\n"
 "* Logging:\n"
 "  -o|--log-file FILE    log file name\n"
diff --git a/files-reg.c b/files-reg.c
index 2e35853..14e4484 100644
--- a/files-reg.c
+++ b/files-reg.c
@@ -1084,6 +1084,7 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
 	struct fd_link _link, *link;
 	struct ns_id *nsid;
 	struct cr_img *rimg;
+	char ext_id[64];
 
 	RegFileEntry rfe = REG_FILE_ENTRY__INIT;
 
@@ -1094,6 +1095,17 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
 	} else
 		link = p->link;
 
+
+
+	snprintf(ext_id, sizeof(ext_id), "file[%x:%"PRIx64"]", p->mnt_id, p->stat.st_ino);
+	if (external_lookup_id(ext_id)) {
+		/* the first symbol will be cut on restore to get an relative path*/
+		rfe.name = xstrdup(ext_id);
+		rfe.ext = true;
+		rfe.has_ext = true;
+		goto ext;
+	}
+
 	nsid = lookup_nsid_by_mnt_id(p->mnt_id);
 	if (nsid == NULL) {
 		pr_err("Can't lookup mount=%d for fd=%d path=%s\n",
@@ -1119,12 +1131,12 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
 
 	if (check_path_remap(link, p, lfd, id, nsid))
 		return -1;
-
+	rfe.name	= &link->name[1];
+ext:
 	rfe.id		= id;
 	rfe.flags	= p->flags;
 	rfe.pos		= p->pos;
 	rfe.fown	= (FownEntry *)&p->fown;
-	rfe.name	= &link->name[1];
 
 	if (S_ISREG(p->stat.st_mode) && should_check_size(rfe.flags)) {
 		rfe.has_size = true;
@@ -1360,11 +1372,24 @@ int open_path(struct file_desc *d,
 	int tmp, mntns_root, level;
 	struct reg_file_info *rfi;
 	char *orig_path = NULL;
+	char path[PATH_MAX];
 
 	if (inherited_fd(d, &tmp))
 		return tmp;
 
 	rfi = container_of(d, struct reg_file_info, d);
+
+	if (rfi->rfe->ext) {
+		tmp = inherit_fd_lookup_id(rfi->rfe->name);
+		if (tmp >= 0) {
+			mntns_root = open_pid_proc(PROC_SELF);
+			snprintf(path, sizeof(path), "fd/%d", tmp);
+			orig_path = rfi->path;
+			rfi->path = path;
+			goto ext;
+		}
+	}
+
 	if (rfi->remap) {
 		mutex_lock(ghost_file_mutex);
 		if (rfi->remap->is_dir) {
@@ -1406,6 +1431,7 @@ int open_path(struct file_desc *d,
 	}
 
 	mntns_root = mntns_get_root_by_mnt_id(rfi->rfe->mnt_id);
+ext:
 	tmp = open_cb(mntns_root, rfi, arg);
 	if (tmp < 0) {
 		pr_perror("Can't open file %s", rfi->path);
@@ -1448,10 +1474,10 @@ int open_path(struct file_desc *d,
 			unlinkat(mntns_root, rfi->remap->rpath, rfi->remap->is_dir ? AT_REMOVEDIR : 0);
 		}
 
-		if (orig_path)
-			rfi->path = orig_path;
 		mutex_unlock(ghost_file_mutex);
 	}
+	if (orig_path)
+		rfi->path = orig_path;
 
 	if (restore_fown(tmp, rfi->rfe->fown))
 		return -1;
diff --git a/protobuf/regfile.proto b/protobuf/regfile.proto
index 3a9456f..e25d589 100644
--- a/protobuf/regfile.proto
+++ b/protobuf/regfile.proto
@@ -9,4 +9,5 @@ message reg_file_entry {
 	required string		name	= 6;
 	optional sint32		mnt_id	= 7 [default = -1];
 	optional uint64		size	= 8;
+	optional bool		ext	= 9;
 }
-- 
2.4.3



More information about the CRIU mailing list