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

Pavel Emelyanov xemul at parallels.com
Mon Dec 16 03:55:47 PST 2013


On 12/16/2013 03:26 PM, Andrey Vagin wrote:
> 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.
> 
> Signed-off-by: Andrey Vagin <avagin at openvz.org>
> ---
>  files-reg.c            | 23 +++++++++++++++++++----
>  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, 83 insertions(+), 12 deletions(-)
> 
> diff --git a/files-reg.c b/files-reg.c
> index fb5d7ca..6ddfc35 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;
> @@ -577,10 +583,19 @@ static int do_open_reg(struct reg_file_info *rfi, void *arg)
>  {
>  	int fd;
>  
> -	fd = open(rfi->path, rfi->rfe->flags);
> -	if (fd < 0) {
> -		pr_perror("Can't open file %s on restore", rfi->path);
> +	if (rfi->rfe->need_callback) {
> +		fd = cr_plugin_restore_file(rfi->path, rfi->rfe->flags, rfi->rfe->id);
> +		if (fd < 0) {
> +			pr_err("Unable to restore %#x\n", rfi->rfe->id);
> +			return -1;
> +		}
>  		return fd;

After this the "} else {" is not required.

> +	} else {
> +		fd = open(rfi->path, rfi->rfe->flags);
> +		if (fd < 0) {
> +			pr_perror("Can't open file %s on restore", rfi->path);
> +			return fd;
> +		}
>  	}
>  
>  	if ((rfi->rfe->pos != -1ULL) &&
> diff --git a/files.c b/files.c
> index 6eb7282..a6e4977 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 == -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;
>  }
> @@ -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);

Split the patch -- lfd passing through the code is separate one.

>  	}
>  	}
>  
> @@ -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 14e1989..050cfdf 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,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)(const char *pathname, int flags, 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..77dd618 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(const char *pathname, int flags, int id);
> +
>  #endif
> diff --git a/plugin.c b/plugin.c
> index e65cd3f..4568f42 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(const char *pathname, int flags, int id)
> +{
> +	return run_plugin_funcs(cr_plugin_restore_file, pathname, flags, 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;
>  }
> 




More information about the CRIU mailing list