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

Andrey Vagin avagin at openvz.org
Wed Dec 11 03:49:10 PST 2013


v2: Callbacks are called for all files, which are not supported by CRIU.

The difference in compare with unix sockets is that dump callbacks
for character devices can be executed to test, which callback can be
used for a given fd.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 files-reg.c            | 16 ++++++++++++++++
 files.c                | 26 ++++++++++++++++++++------
 include/criu-plugin.h  |  3 +++
 include/files.h        |  2 ++
 include/plugin.h       |  4 ++++
 plugin.c               | 21 +++++++++++++++++++++
 protobuf/regfile.proto |  1 +
 7 files changed, 67 insertions(+), 6 deletions(-)

diff --git a/files-reg.c b/files-reg.c
index fb5d7ca..8d48bc0 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
@@ -484,6 +485,13 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
 
 	RegFileEntry rfe = REG_FILE_ENTRY__INIT;
 
+	if (p->cb) {
+		if (p->cb(lfd, id, false))
+			return -1;
+		rfe.has_need_callback = true;
+		rfe.need_callback = true;
+	}
+
 	if (!p->link) {
 		if (fill_fdlink(lfd, p, &_link))
 			return -1;
@@ -583,6 +591,14 @@ 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 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..ad7077f 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,8 +241,21 @@ 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)
+static int dump_unsupp_fd(struct fd_parms *p, int lfd,
+				const int fdinfo, char *more, char *info)
 {
+	cr_plugin_dump_file_t *cb;
+	int ret;
+
+	ret = cr_plugin_dump_file(lfd, 0, true, &cb);
+	if (ret < 0 && ret != CRIU_CB_SKIP)
+		return -1;
+
+	if (ret == 0) {
+		p->cb = cb;
+		return do_dump_gen_file(p, lfd, &regfile_dump_ops, fdinfo);
+	}
+
 	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 +292,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 +344,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 +363,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 +375,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..53efa41 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, bool test_only);
+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.h b/include/files.h
index d491cf1..85246dd 100644
--- a/include/files.h
+++ b/include/files.h
@@ -46,6 +46,8 @@ struct fd_parms {
 	struct fd_link	*link;
 
 	struct parasite_ctl *ctl;
+
+	cr_plugin_dump_file_t *cb;
 };
 
 #define FD_PARMS_INIT			\
diff --git a/include/plugin.h b/include/plugin.h
index a70dde3..b3d5f15 100644
--- a/include/plugin.h
+++ b/include/plugin.h
@@ -11,4 +11,8 @@ 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, bool test_only,
+				cr_plugin_dump_file_t **cb);
+int cr_plugin_restore_file(int fd, int id);
+
 #endif
diff --git a/plugin.c b/plugin.c
index 114a507..2dc947f 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;
@@ -77,6 +81,17 @@ int cr_plugin_restore_unix_sk(int ino)
 			(cr_plugin_restore_unix_sk_t **) NULL, ino);
 }
 
+int cr_plugin_dump_file(int fd, int id, bool test, cr_plugin_dump_file_t **cb)
+{
+	return run_plugin_funcs(cr_plugin_dump_file, cb, fd, id, test);
+}
+
+int cr_plugin_restore_file(int fd, int id)
+{
+	return run_plugin_funcs(cr_plugin_restore_file,
+				(cr_plugin_restore_file_t **) NULL, fd, id);
+}
+
 static int cr_lib_load(char *path)
 {
 	struct cr_plugin_entry *ce;
@@ -93,6 +108,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) {
@@ -131,6 +149,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