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

Andrey Vagin avagin at openvz.org
Fri Dec 20 03:10:59 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.
v4: A file descriptor is opened in a callback. It's required for
    restoring anon vmas.
v5: Add a separate type for unsupported files
v6: define FD_TYPES__UNSUPP

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 Makefile.crtools        |  1 +
 cr-restore.c            |  1 +
 cr-show.c               |  1 +
 files-reg.c             |  1 +
 files-unsupp.c          | 91 +++++++++++++++++++++++++++++++++++++++++++++++++
 files.c                 | 15 +++-----
 image-desc.c            |  1 +
 include/criu-plugin.h   |  4 +++
 include/files.h         |  4 +++
 include/image-desc.h    |  1 +
 include/magic.h         |  1 +
 include/plugin.h        |  3 ++
 include/protobuf-desc.h |  1 +
 plugin.c                | 20 +++++++++++
 protobuf-desc.c         |  1 +
 protobuf/Makefile       |  1 +
 protobuf/fdinfo.proto   |  1 +
 17 files changed, 138 insertions(+), 10 deletions(-)
 create mode 100644 files-unsupp.c

diff --git a/Makefile.crtools b/Makefile.crtools
index aecab0f..fd49d84 100644
--- a/Makefile.crtools
+++ b/Makefile.crtools
@@ -29,6 +29,7 @@ obj-y	+= sk-netlink.o
 obj-y	+= sk-queue.o
 obj-y	+= files.o
 obj-y	+= files-reg.o
+obj-y	+= files-unsupp.o
 obj-y	+= pipes.o
 obj-y	+= fifo.o
 obj-y	+= file-ids.o
diff --git a/cr-restore.c b/cr-restore.c
index e42f582..717e2a5 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -122,6 +122,7 @@ static int crtools_prepare_shared(void)
 }
 
 static struct collect_image_info *cinfos[] = {
+	&unsupp_file_cinfo,
 	&reg_file_cinfo,
 	&remap_cinfo,
 	&nsfile_cinfo,
diff --git a/cr-show.c b/cr-show.c
index df564a5..c7cd217 100644
--- a/cr-show.c
+++ b/cr-show.c
@@ -298,6 +298,7 @@ static struct show_image_info show_infos[] = {
 	SHOW_VERT(MM),
 
 	SHOW_PLAINS(REG_FILE),
+	SHOW_PLAINS(UNSUPP_FILE),
 	SHOW_PLAINS(NS_FILE),
 	SHOW_PLAIN(EVENTFD_FILE),
 	SHOW_PLAIN(EVENTPOLL_FILE),
diff --git a/files-reg.c b/files-reg.c
index 181f1f2..2b466bd 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
diff --git a/files-unsupp.c b/files-unsupp.c
new file mode 100644
index 0000000..ce371a2
--- /dev/null
+++ b/files-unsupp.c
@@ -0,0 +1,91 @@
+#include <unistd.h>
+
+#include "fdset.h"
+#include "files.h"
+#include "plugin.h"
+
+#include "protobuf.h"
+#include "protobuf/unsupp-file.pb-c.h"
+
+int dump_one_unsupp_file(int lfd, u32 id, const struct fd_parms *p)
+{
+	int rfd, ret;
+
+	UnsuppFileEntry ufe = UNSUPP_FILE_ENTRY__INIT;
+
+	ret = cr_plugin_dump_file(lfd, id);
+	if (ret < 0)
+		return ret;
+
+	ufe.id		= id;
+	ufe.fown	= (FownEntry *)&p->fown;
+
+	rfd = fdset_fd(glob_fdset, CR_FD_UNSUPP_FILES);
+
+	return pb_write_one(rfd, &ufe, PB_UNSUPP_FILE);
+}
+
+const struct fdtype_ops unsupp_dump_ops = {
+	.type		= FD_TYPES__UNSUPP,
+	.dump		= dump_one_unsupp_file,
+};
+
+struct unsupp_file_info {
+	struct file_desc	d;
+	UnsuppFileEntry		*ufe;
+};
+
+static int open_fd(struct file_desc *d)
+{
+	struct unsupp_file_info *ufi;
+	int fd;
+
+	ufi = container_of(d, struct unsupp_file_info, d);
+
+	fd = cr_plugin_restore_file(ufi->ufe->id);
+	if (fd < 0) {
+		pr_err("Unable to restore %#x\n", ufi->ufe->id);
+		return -1;
+	}
+
+	if (restore_fown(fd, ufi->ufe->fown))
+		return -1;
+
+	return fd;
+}
+
+static struct file_desc_ops unsupp_desc_ops = {
+	.type = FD_TYPES__UNSUPP,
+	.open = open_fd,
+};
+
+static int collect_one_unsupp(void *o, ProtobufCMessage *base)
+{
+	struct unsupp_file_info *ufi = o;
+
+	ufi->ufe = pb_msg(base, UnsuppFileEntry);
+
+	pr_info("Collected unsupported file with ID %#x\n", ufi->ufe->id);
+	return file_desc_add(&ufi->d, ufi->ufe->id, &unsupp_desc_ops);
+}
+
+struct collect_image_info unsupp_file_cinfo = {
+	.fd_type = CR_FD_UNSUPP_FILES,
+	.pb_type = PB_UNSUPP_FILE,
+	.priv_size = sizeof(struct unsupp_file_info),
+	.collect = collect_one_unsupp,
+};
+
+int dump_unsupp_fd(struct fd_parms *p, int lfd,
+			  const int fdinfo, char *more, char *info)
+{
+	int ret;
+
+	ret = do_dump_gen_file(p, lfd, &unsupp_dump_ops, fdinfo);
+	if (ret == 0)
+		return 0;
+	if (ret == -ENOTSUP)
+		pr_err("Can't dump file %d of that type [%o] (%s %s)\n",
+			p->fd, p->stat.st_mode, more, info);
+	return -1;
+}
diff --git a/files.c b/files.c
index a0a7ac6..af19146 100644
--- a/files.c
+++ b/files.c
@@ -32,12 +32,16 @@
 #include "signalfd.h"
 #include "namespaces.h"
 #include "tun.h"
+#include "fdset.h"
 
 #include "parasite.h"
 #include "parasite-syscall.h"
 
 #include "protobuf.h"
 #include "protobuf/fs.pb-c.h"
+#include "protobuf/unsupp-file.pb-c.h"
+
+#include "plugin.h"
 
 #define FDESC_HASH_SIZE	64
 static struct hlist_head file_desc_hash[FDESC_HASH_SIZE];
@@ -170,7 +174,7 @@ int do_dump_gen_file(struct fd_parms *p, int lfd,
 		ret = ops->dump(lfd, e.id, p);
 
 	if (ret < 0)
-		return -1;
+		return ret;
 
 	pr_info("fdinfo: type: 0x%2x flags: %#o/%#o pos: 0x%8"PRIx64" fd: %d\n",
 		ops->type, p->flags, (int)p->fd_flags, p->pos, p->fd);
@@ -239,14 +243,6 @@ 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, int lfd,
-			  const int fdinfo, char *more, char *info)
-{
-	pr_err("Can't dump file %d of that type [%o] (%s %s)\n",
-			p->fd, p->stat.st_mode, more, info);
-	return -1;
-}
-
 static const struct fdtype_ops *get_misc_dev_ops(int minor)
 {
 	switch (minor) {
@@ -278,7 +274,6 @@ 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, lfd, fdinfo, "chr", more);
 	}
diff --git a/image-desc.c b/image-desc.c
index 2361fe4..4f026d6 100644
--- a/image-desc.c
+++ b/image-desc.c
@@ -23,6 +23,7 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
 	FD_ENTRY(PAGEMAP,	"pagemap-%ld"),
 	FD_ENTRY(SHMEM_PAGEMAP,	"pagemap-shmem-%ld"),
 	FD_ENTRY(REG_FILES,	"reg-files"),
+	FD_ENTRY(UNSUPP_FILES,	"unsupp-files"),
 	FD_ENTRY(NS_FILES,	"ns-files"),
 	FD_ENTRY(EVENTFD_FILE,	"eventfd"),
 	FD_ENTRY(EVENTPOLL_FILE,"eventpoll"),
diff --git a/include/criu-plugin.h b/include/criu-plugin.h
index b205c10..cf6a2c5 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);
@@ -28,6 +29,9 @@ 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 id);
+
 /* Public API */
 extern int criu_get_image_dir(void);
 
diff --git a/include/files.h b/include/files.h
index d491cf1..e4d482f 100644
--- a/include/files.h
+++ b/include/files.h
@@ -147,4 +147,8 @@ extern int close_old_fds(struct pstree_item *me);
 
 extern int shared_fdt_prepare(struct pstree_item *item);
 
+extern struct collect_image_info unsupp_file_cinfo;
+extern int dump_unsupp_fd(struct fd_parms *p, int lfd,
+			  const int fdinfo, char *more, char *info);
+
 #endif /* __CR_FILES_H__ */
diff --git a/include/image-desc.h b/include/image-desc.h
index a38368b..3d1839c 100644
--- a/include/image-desc.h
+++ b/include/image-desc.h
@@ -56,6 +56,7 @@ enum {
 	_CR_FD_GLOB_FROM,
 	CR_FD_SK_QUEUES,
 	CR_FD_REG_FILES,
+	CR_FD_UNSUPP_FILES,
 	CR_FD_NS_FILES,
 	CR_FD_INETSK,
 	CR_FD_UNIXSK,
diff --git a/include/magic.h b/include/magic.h
index f17a191..cae56ee 100644
--- a/include/magic.h
+++ b/include/magic.h
@@ -47,6 +47,7 @@
 #define IPCNS_MSG_MAGIC		0x55453737 /* Moscow */
 #define IPCNS_SEM_MAGIC		0x59573019 /* St. Petersburg */
 #define REG_FILES_MAGIC		0x50363636 /* Belgorod */
+#define UNSUPP_FILES_MAGIC	0x59255641 /* Usolye */
 #define FS_MAGIC		0x51403912 /* Voronezh */
 #define MM_MAGIC		0x57492820 /* Pskov */
 #define REMAP_FPATH_MAGIC	0x59133954 /* Vologda */
diff --git a/include/plugin.h b/include/plugin.h
index a70dde3..6c8ab82 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 id);
+
 #endif
diff --git a/include/protobuf-desc.h b/include/protobuf-desc.h
index fd9ee43..787f0ac 100644
--- a/include/protobuf-desc.h
+++ b/include/protobuf-desc.h
@@ -25,6 +25,7 @@ enum {
 	PB_GHOST_FILE,
 	PB_TCP_STREAM,
 	PB_REG_FILE,
+	PB_UNSUPP_FILE,
 	PB_NS_FILE,
 	PB_INET_SK,
 	PB_UNIX_SK,
diff --git a/plugin.c b/plugin.c
index e65cd3f..222a2f5 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 id)
+{
+	return run_plugin_funcs(cr_plugin_restore_file, 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-desc.c b/protobuf-desc.c
index 1d0f7cd..9f3dff4 100644
--- a/protobuf-desc.c
+++ b/protobuf-desc.c
@@ -18,6 +18,7 @@
 #include "protobuf/inventory.pb-c.h"
 #include "protobuf/stats.pb-c.h"
 #include "protobuf/regfile.pb-c.h"
+#include "protobuf/unsupp-file.pb-c.h"
 #include "protobuf/ns.pb-c.h"
 #include "protobuf/eventfd.pb-c.h"
 #include "protobuf/eventpoll.pb-c.h"
diff --git a/protobuf/Makefile b/protobuf/Makefile
index 7ebe77a..f330af3 100644
--- a/protobuf/Makefile
+++ b/protobuf/Makefile
@@ -57,6 +57,7 @@ proto-obj-y	+= rlimit.o
 proto-obj-y	+= pagemap.o
 proto-obj-y	+= siginfo.o
 proto-obj-y	+= rpc.o
+proto-obj-y	+= unsupp-file.o
 
 proto		:= $(proto-obj-y:.o=)
 proto-c		:= $(proto-obj-y:.o=.pb-c.c)
diff --git a/protobuf/fdinfo.proto b/protobuf/fdinfo.proto
index 5850bd7..d6ca69a 100644
--- a/protobuf/fdinfo.proto
+++ b/protobuf/fdinfo.proto
@@ -15,6 +15,7 @@ enum fd_types {
 	NETLINKSK	= 13;
 	NS		= 14;
 	TUN		= 15;
+	UNSUPP		= 16;
 }
 
 message fdinfo_entry {
-- 
1.8.3.1



More information about the CRIU mailing list