[CRIU] [PATCH 7/8] files: add ability to set callbacks for files (v3)

Andrey Vagin avagin at openvz.org
Thu Dec 12 09:12:58 PST 2013


Here is nothing interecting. If a file can't be dumped by criu,
plugins are called. If one of plugins knows how to dump the file,
the file entry is marked as need_callback. On restore if we see
this mark, we execute plugins for restoring the file.

v2: Callbacks are called for all files, which are not supported by CRIU.
v3: Call plugins for a file instead of file descriptor. A few file
descriptors can be associated with one file.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 files-reg.c            | 17 ++++++++++++++++-
 files.c                | 38 +++++++++++++++++++++++++++++++-------
 include/criu-plugin.h  |  3 +++
 include/files-reg.h    |  7 ++++++-
 include/plugin.h       |  3 +++
 plugin.c               | 20 ++++++++++++++++++++
 protobuf/regfile.proto |  1 +
 7 files changed, 80 insertions(+), 9 deletions(-)

diff --git a/files-reg.c b/files-reg.c
index fb5d7ca..2e59ea7 100644
--- a/files-reg.c
+++ b/files-reg.c
@@ -20,6 +20,7 @@
 #include "protobuf/remap-file-path.pb-c.h"
 
 #include "files-reg.h"
+#include "plugin.h"
 
 /*
  * Ghost files are those not visible from the FS. Dumping them is
@@ -477,13 +478,18 @@ static int check_path_remap(char *rpath, int plen, const struct stat *ost, int l
 	return 0;
 }
 
-int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
+int __dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p, bool cb)
 {
 	struct fd_link _link, *link;
 	int rfd;
 
 	RegFileEntry rfe = REG_FILE_ENTRY__INIT;
 
+	if (cb) {
+		rfe.has_need_callback = true;
+		rfe.need_callback = true;
+	}
+
 	if (!p->link) {
 		if (fill_fdlink(lfd, p, &_link))
 			return -1;
@@ -583,6 +589,15 @@ static int do_open_reg(struct reg_file_info *rfi, void *arg)
 		return fd;
 	}
 
+	if (rfi->rfe->need_callback) {
+		if (cr_plugin_restore_file(fd, rfi->rfe->id)) {
+			pr_err("Unable to restore %#x\n", rfi->rfe->id);
+			close(fd);
+			return -1;
+		}
+		return fd;
+	}
+
 	if ((rfi->rfe->pos != -1ULL) &&
 			lseek(fd, rfi->rfe->pos, SEEK_SET) < 0) {
 		pr_perror("Can't restore file pos");
diff --git a/files.c b/files.c
index 6eb7282..7f7003a 100644
--- a/files.c
+++ b/files.c
@@ -39,6 +39,8 @@
 #include "protobuf.h"
 #include "protobuf/fs.pb-c.h"
 
+#include "plugin.h"
+
 #define FDESC_HASH_SIZE	64
 static struct hlist_head file_desc_hash[FDESC_HASH_SIZE];
 
@@ -239,9 +241,32 @@ static int fill_fd_params(struct parasite_ctl *ctl, int fd, int lfd,
 	return 0;
 }
 
-static int dump_unsupp_fd(const struct fd_parms *p, char *more, char *info)
+int dump_one_unsupp_file(int lfd, u32 id, const struct fd_parms *p)
+{
+	int ret;
+
+	ret = cr_plugin_dump_file(lfd, id);
+	if (ret < 0)
+		return ret;
+
+	return __dump_one_reg_file(lfd, id, p, true);
+}
+
+const struct fdtype_ops unsupp_dump_ops = {
+	.type		= FD_TYPES__REG,
+	.dump		= dump_one_unsupp_file,
+};
+
+static int dump_unsupp_fd(struct fd_parms *p, int lfd,
+				const int fdinfo, char *more, char *info)
 {
-	pr_err("Can't dump file %d of that type [%o] (%s %s)\n",
+	int ret;
+
+	ret = do_dump_gen_file(p, lfd, &unsupp_dump_ops, fdinfo);
+	if (ret == 0)
+		return 0;
+	if (ret == CRIU_CB_SKIP)
+		pr_err("Can't dump file %d of that type [%o] (%s %s)\n",
 			p->fd, p->stat.st_mode, more, info);
 	return -1;
 }
@@ -277,9 +302,8 @@ static int dump_chrdev(struct fd_parms *p, int lfd, const int fdinfo)
 		/* fallthrough */
 	default: {
 		char more[32];
-
 		sprintf(more, "%d:%d", maj, minor(p->stat.st_dev));
-		return dump_unsupp_fd(p, "chr", more);
+		return dump_unsupp_fd(p, lfd, fdinfo, "chr", more);
 	}
 	}
 
@@ -330,7 +354,7 @@ static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_op
 			if (read_fd_link(fd, more, sizeof(more)))
 				more[0] = '\0';
 
-			return dump_unsupp_fd(&p, "anon", more);
+			return dump_unsupp_fd(&p, lfd, fdinfo, "anon", more);
 		}
 
 		return do_dump_gen_file(&p, lfd, ops, fdinfo);
@@ -349,7 +373,7 @@ static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_op
 		if (check_ns_proc(&link))
 			return do_dump_gen_file(&p, lfd, &nsfile_dump_ops, fdinfo);
 
-		return dump_unsupp_fd(&p, "reg", link.name + 1);
+		return dump_unsupp_fd(&p, lfd, fdinfo, "reg", link.name + 1);
 	}
 
 	if (S_ISFIFO(p.stat.st_mode)) {
@@ -361,7 +385,7 @@ static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_op
 		return do_dump_gen_file(&p, lfd, ops, fdinfo);
 	}
 
-	return dump_unsupp_fd(&p, "unknown", NULL);
+	return dump_unsupp_fd(&p, lfd, fdinfo, "unknown", NULL);
 }
 
 int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
diff --git a/include/criu-plugin.h b/include/criu-plugin.h
index d4ea30c..eb71362 100644
--- a/include/criu-plugin.h
+++ b/include/criu-plugin.h
@@ -21,6 +21,7 @@
 #define __CRIU_PLUGIN_H__
 
 #include <limits.h>
+#include <stdbool.h>
 
 typedef int (cr_plugin_init_t)(void);
 typedef void (cr_plugin_fini_t)(void);
@@ -31,6 +32,8 @@ typedef void (cr_plugin_fini_t)(void);
 typedef int (cr_plugin_dump_unix_sk_t)(int fd, int id);
 typedef int (cr_plugin_restore_unix_sk_t)(int id);
 
+typedef int (cr_plugin_dump_file_t)(int fd, int id);
+typedef int (cr_plugin_restore_file_t)(int fd, int id);
 
 extern void print_on_level(unsigned int loglevel, const char *format, ...)
 	__attribute__ ((__format__ (__printf__, 2, 3)));
diff --git a/include/files-reg.h b/include/files-reg.h
index d3bd4f0..087a2d8 100644
--- a/include/files-reg.h
+++ b/include/files-reg.h
@@ -30,7 +30,12 @@ extern void clear_ghost_files(void);
 extern int prepare_shared_reg_files(void);
 
 extern const struct fdtype_ops regfile_dump_ops;
-extern int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p);
+int __dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p, bool cb);
+static inline int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
+{
+	return __dump_one_reg_file(lfd, id, p, false);
+}
+
 
 extern struct file_remap *lookup_ghost_remap(u32 dev, u32 ino);
 extern void remap_put(struct file_remap *remap);
diff --git a/include/plugin.h b/include/plugin.h
index a70dde3..a8909be 100644
--- a/include/plugin.h
+++ b/include/plugin.h
@@ -11,4 +11,7 @@ int cr_plugin_init(void);
 int cr_plugin_dump_unix_sk(int fd, int id);
 int cr_plugin_restore_unix_sk(int id);
 
+int cr_plugin_dump_file(int fd, int id);
+int cr_plugin_restore_file(int fd, int id);
+
 #endif
diff --git a/plugin.c b/plugin.c
index ce5fb10..bd41639 100644
--- a/plugin.c
+++ b/plugin.c
@@ -17,6 +17,8 @@ struct cr_plugin_entry {
 
 		cr_plugin_dump_unix_sk_t *cr_plugin_dump_unix_sk;
 		cr_plugin_restore_unix_sk_t *cr_plugin_restore_unix_sk;
+		cr_plugin_dump_file_t *cr_plugin_dump_file;
+		cr_plugin_restore_file_t *cr_plugin_restore_file;
 	};
 
 	struct cr_plugin_entry *next;
@@ -27,6 +29,8 @@ struct cr_plugins {
 
 	struct cr_plugin_entry *cr_plugin_dump_unix_sk;
 	struct cr_plugin_entry *cr_plugin_restore_unix_sk;
+	struct cr_plugin_entry *cr_plugin_dump_file;
+	struct cr_plugin_entry *cr_plugin_restore_file;
 };
 
 struct cr_plugins cr_plugins;
@@ -73,6 +77,16 @@ int cr_plugin_restore_unix_sk(int id)
 	return run_plugin_funcs(cr_plugin_restore_unix_sk, id);
 }
 
+int cr_plugin_dump_file(int fd, int id)
+{
+	return run_plugin_funcs(cr_plugin_dump_file, fd, id);
+}
+
+int cr_plugin_restore_file(int fd, int id)
+{
+	return run_plugin_funcs(cr_plugin_restore_file, fd, id);
+}
+
 static int cr_lib_load(char *path)
 {
 	struct cr_plugin_entry *ce;
@@ -89,6 +103,9 @@ static int cr_lib_load(char *path)
 	add_plugin_func(cr_plugin_dump_unix_sk);
 	add_plugin_func(cr_plugin_restore_unix_sk);
 
+	add_plugin_func(cr_plugin_dump_file);
+	add_plugin_func(cr_plugin_restore_file);
+
 	ce = NULL;
 	f_fini = dlsym(h, "cr_plugin_fini");
 	if (f_fini) {
@@ -127,6 +144,9 @@ void cr_plugin_fini(void)
 	cr_plugin_free(cr_plugin_dump_unix_sk);
 	cr_plugin_free(cr_plugin_restore_unix_sk);
 
+	cr_plugin_free(cr_plugin_dump_file);
+	cr_plugin_free(cr_plugin_restore_file);
+
 	while (cr_plugins.cr_fini) {
 		ce = cr_plugins.cr_fini;
 		cr_plugins.cr_fini = cr_plugins.cr_fini->next;
diff --git a/protobuf/regfile.proto b/protobuf/regfile.proto
index d975ab0..925d39a 100644
--- a/protobuf/regfile.proto
+++ b/protobuf/regfile.proto
@@ -6,4 +6,5 @@ message reg_file_entry {
 	required uint64		pos	= 3;
 	required fown_entry	fown	= 5;
 	required string		name	= 6;
+	optional bool		need_callback = 7;
 }
-- 
1.8.3.1



More information about the CRIU mailing list