[CRIU] [PATCH 1/5] crtools: preload libraries

Andrew Vagin avagin at parallels.com
Fri Dec 6 01:45:57 PST 2013


On Thu, Dec 05, 2013 at 09:58:55PM +0400, Andrey Vagin wrote:
> Libraries is going to be used for dumping and restoring
> external dependencies (e.g. dbus, systemd journal sockets)
> 
> A libary can have the cr_init() function for initialization.
> 
> The criu devel package should contain log.h, plugin.h. Probably
> this package should create the criu directory in /usr/include.
> 
> Signed-off-by: Andrey Vagin <avagin at openvz.org>
> ---
>  Makefile              |   4 +-
>  Makefile.crtools      |   1 +
>  cr-dump.c             |   6 +++
>  cr-restore.c          |  27 +++++++----
>  crtools.c             |  13 +++++-
>  include/cr_options.h  |   1 +
>  include/criu-plugin.h |  26 +++++++++++
>  include/plugin.h      |  22 +++++++++
>  lib.c                 | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  9 files changed, 211 insertions(+), 12 deletions(-)
>  create mode 100644 include/criu-plugin.h
>  create mode 100644 include/plugin.h
>  create mode 100644 lib.c
> 
> diff --git a/Makefile b/Makefile
> index cd312e7..1cdae52 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -82,7 +82,7 @@ cflags-y		+= -iquote $(ARCH_DIR) -iquote $(ARCH_DIR)/include
>  cflags-y		+= -fno-strict-aliasing
>  export cflags-y
>  
> -LIBS		:= -lrt -lpthread -lprotobuf-c
> +LIBS		:= -lrt -lpthread -lprotobuf-c -ldl
>  
>  DEFINES		+= -D_FILE_OFFSET_BITS=64
>  DEFINES		+= -D_GNU_SOURCE
> @@ -167,7 +167,7 @@ PROGRAM-BUILTINS	+= $(ARCH_DIR)/vdso-pie.o
>  
>  $(PROGRAM): $(SYSCALL-LIB) $(ARCH-LIB) $(PROGRAM-BUILTINS)
>  	$(E) "  LINK    " $@
> -	$(Q) $(CC) $(CFLAGS) $^ $(LIBS) $(LDFLAGS) -o $@
> +	$(Q) $(CC) $(CFLAGS) $^ $(LIBS) $(LDFLAGS) -rdynamic -o $@
>  
>  zdtm: all
>  	$(Q) $(MAKE) -C test/zdtm all
> diff --git a/Makefile.crtools b/Makefile.crtools
> index 3030ce9..227944c 100644
> --- a/Makefile.crtools
> +++ b/Makefile.crtools
> @@ -56,6 +56,7 @@ obj-y	+= string.o
>  obj-y	+= sigframe.o
>  obj-y	+= arch/$(ARCH)/vdso.o
>  obj-y	+= cr-service.o
> +obj-y	+= lib.o
>  
>  ifneq ($(MAKECMDGOALS),clean)
>  incdeps := y
> diff --git a/cr-dump.c b/cr-dump.c
> index ffae7ff..3c03ab6 100644
> --- a/cr-dump.c
> +++ b/cr-dump.c
> @@ -70,6 +70,7 @@
>  #include "vdso.h"
>  #include "vma.h"
>  #include "cr-service.h"
> +#include "plugin.h"
>  
>  #include "asm/dump.h"
>  
> @@ -1670,6 +1671,9 @@ int cr_dump_tasks(pid_t pid)
>  	if (init_stats(DUMP_STATS))
>  		goto err;
>  
> +	if (cr_lib_init())
> +		goto err;
> +
>  	if (kerndat_init())
>  		goto err;
>  
> @@ -1753,6 +1757,8 @@ err:
>  
>  	close_cr_fdset(&glob_fdset);
>  
> +	cr_lib_fini();
> +
>  	if (!ret) {
>  		/*
>  		 * It might be a migration case, where we're asked
> diff --git a/cr-restore.c b/cr-restore.c
> index 6a0637e..46dd262 100644
> --- a/cr-restore.c
> +++ b/cr-restore.c
> @@ -67,6 +67,7 @@
>  #include "vma.h"
>  #include "kerndat.h"
>  #include "rst-malloc.h"
> +#include "plugin.h"
>  
>  #include "parasite-syscall.h"
>  
> @@ -1616,33 +1617,41 @@ static int prepare_task_entries()
>  
>  int cr_restore_tasks(void)
>  {
> -	if (check_img_inventory() < 0)
> +	int ret = -1;
> +
> +	if (cr_lib_init())
>  		return -1;
>  
> +	if (check_img_inventory() < 0)
> +		goto err;
> +
>  	if (init_stats(RESTORE_STATS))
> -		return -1;
> +		goto err;
>  
>  	if (kerndat_init_rst())
> -		return -1;
> +		goto err;
>  
>  	timing_start(TIME_RESTORE);
>  
>  	if (cpu_init() < 0)
> -		return -1;
> +		goto err;
>  
>  	if (vdso_init())
> -		return -1;
> +		goto err;
>  
>  	if (prepare_task_entries() < 0)
> -		return -1;
> +		goto err;
>  
>  	if (prepare_pstree() < 0)
> -		return -1;
> +		goto err;
>  
>  	if (crtools_prepare_shared() < 0)
> -		return -1;
> +		goto err;
>  
> -	return restore_root_task(root_item);
> +	ret = restore_root_task(root_item);
> +err:
> +	cr_lib_fini();
> +	return ret;
>  }
>  
>  static long restorer_get_vma_hint(pid_t pid, struct list_head *tgt_vma_list,
> diff --git a/crtools.c b/crtools.c
> index ab885e6..53d67dd 100644
> --- a/crtools.c
> +++ b/crtools.c
> @@ -16,6 +16,8 @@
>  #include <netinet/in.h>
>  #include <arpa/inet.h>
>  
> +#include <dlfcn.h>
> +
>  #include "asm/types.h"
>  
>  #include "compiler.h"
> @@ -31,6 +33,7 @@
>  #include "tty.h"
>  #include "file-lock.h"
>  #include "cr-service.h"
> +#include "plugin.h"
>  
>  struct cr_options opts;
>  
> @@ -95,7 +98,7 @@ int main(int argc, char *argv[])
>  		return -1;
>  
>  	while (1) {
> -		static const char short_opts[] = "dsRf:t:p:hcD:o:n:v::xVr:jlW:";
> +		static const char short_opts[] = "dsRf:t:p:hcD:o:n:v::xVr:jlW:L:";
>  		static struct option long_opts[] = {
>  			{ "tree", required_argument, 0, 't' },
>  			{ "pid", required_argument, 0, 'p' },
> @@ -129,6 +132,7 @@ int main(int argc, char *argv[])
>  			{ "prev-images-dir", required_argument, 0, 53},
>  			{ "ms", no_argument, 0, 54},
>  			{ "track-mem", no_argument, 0, 55},
> +			{ "libdir", required_argument, 0, 'L'},
>  			{ },
>  		};
>  
> @@ -271,6 +275,13 @@ int main(int argc, char *argv[])
>  		case 54:
>  			opts.check_ms_kernel = true;
>  			break;
> +		case 'L':
> +			opts.libdir = strdup(optarg);
> +			if (opts.libdir == NULL) {
> +				pr_perror("Can't allocate memory");
> +				return -1;
> +			}
> +			break;
>  		case 'V':
>  			pr_msg("Version: %s\n", CRIU_VERSION);
>  			if (strcmp(CRIU_GITID, "0"))
> diff --git a/include/cr_options.h b/include/cr_options.h
> index b90b4e1..5a4676c 100644
> --- a/include/cr_options.h
> +++ b/include/cr_options.h
> @@ -29,6 +29,7 @@ struct cr_options {
>  	char			*pidfile;
>  	struct list_head	veth_pairs;
>  	struct list_head	scripts;
> +	char			*libdir;
>  	bool			use_page_server;
>  	unsigned short		ps_port;
>  	char			*addr;
> diff --git a/include/criu-plugin.h b/include/criu-plugin.h
> new file mode 100644
> index 0000000..44abb2a
> --- /dev/null
> +++ b/include/criu-plugin.h
> @@ -0,0 +1,26 @@
> +/*
> +    This file defines types and macros for CRIU plugins.
> +    Copyright (C) 2013 Parallels, Inc
> +
> +    This program is free software; you can redistribute it and/or modify
> +    it under the terms of the GNU General Public License as published by
> +    the Free Software Foundation; either version 2 of the License, or
> +    (at your option) any later version.
> +
> +    This program is distributed in the hope that it will be useful,
> +    but WITHOUT ANY WARRANTY; without even the implied warranty of
> +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +    GNU General Public License for more details.
> +
> +    You should have received a copy of the GNU General Public License
> +    along with this program; if not, write to the Free Software
> +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
> + */
> +
> +#ifndef __CRIU_PLUGIN_H__
> +#define __CRIU_PLUGIN_H__
> +
> +typedef int (cr_plugin_init_t)(void);
> +typedef void (cr_plugin_fini_t)(void);
> +
> +#endif
> diff --git a/include/plugin.h b/include/plugin.h
> new file mode 100644
> index 0000000..8653a5b
> --- /dev/null
> +++ b/include/plugin.h
> @@ -0,0 +1,22 @@
> +#ifndef __CR_PLUGIN_H__
> +#define __CR_PLUGIN_H__
> +
> +#include "criu-plugin.h"
> +
> +struct cr_plugin_entry {
> +	union {
> +		cr_plugin_fini_t *cr_fini;
> +	};
> +
> +	struct cr_plugin_entry *next;
> +};
> +
> +struct cr_plugins {
> +	struct cr_plugin_entry *cr_fini;
> +};
> +
> +extern struct cr_plugins cr_plugins;
> +
> +void cr_lib_fini(void);
> +int cr_lib_init(void);
> +#endif
> diff --git a/lib.c b/lib.c
> new file mode 100644
> index 0000000..387bb84
> --- /dev/null
> +++ b/lib.c
> @@ -0,0 +1,123 @@
> +#include <stdlib.h>
> +#include <string.h>
> +#include <dirent.h>
> +#include <errno.h>
> +#include <stdio.h>
> +#include <dlfcn.h>
> +
> +#include "cr_options.h"
> +#include "plugin.h"
> +#include "log.h"
> +#include "xmalloc.h"
> +
> +struct cr_plugins cr_plugins;
> +
> +static int cr_lib_load(char *path)
> +{
> +	struct cr_plugin_entry *ce;
> +	cr_plugin_init_t *f_init;
> +	cr_plugin_fini_t *f_fini;
> +	void *h;
> +
> +	h = dlopen(path, RTLD_LAZY);
> +	if (h == NULL) {
> +		pr_err("Unable to load %s: %s", path, dlerror());
> +		return -1;
> +	}
> +
> +	ce = NULL;
> +	f_fini = dlsym(h, "cr_plugin_fini");
> +	if (f_fini) {
> +		ce = xmalloc(sizeof(struct cr_plugin_entry));
> +		if (ce == NULL)
> +			return -1;
> +		ce->cr_fini = f_fini;
> +	}
> +
> +	f_init = dlsym(h, "cr_plugin_init");
> +	if (f_init && f_init()) {
> +		xfree(ce);
> +		return -1;
> +	}
> +
> +	if (ce) {
> +		ce->next = cr_plugins.cr_fini;
> +		cr_plugins.cr_fini = ce;
> +	}
> +
> +	return 0;
> +}
> +
> +void cr_lib_fini(void)
> +{
> +	struct cr_plugin_entry *ce;
> +
> +	while (cr_plugins.cr_fini) {
> +		ce = cr_plugins.cr_fini;
> +		cr_plugins.cr_fini = cr_plugins.cr_fini->next;
> +
> +		ce->cr_fini();
> +		xfree(ce);
> +	}
> +}
> +
> +int cr_lib_init(void)
> +{
> +	int exit_code = -1;
> +	DIR *d;
> +
> +	memset(&cr_plugins, 0, sizeof(cr_plugins));
> +
> +	if (opts.libdir == NULL) {
> +		char *path;
> +
> +		path = getenv("CRIU_LIBS_DIR");
> +		if (path == NULL)
> +			return 0;
> +
> +		opts.libdir = strdup(path);
> +		if (opts.libdir == NULL) {
> +			pr_perror("Can't allocate memory");
> +			return -1;
> +		}
> +	}
> +
> +	d = opendir(opts.libdir);
> +	if (d == 0) {
> +		pr_perror("Unable to open directory %s", opts.libdir);
> +		return -1;
> +	}
> +
> +	while (1) {
> +		char path[PATH_MAX];
> +		struct dirent *de;
> +		int len;
> +
> +		errno = 0;
> +		de = readdir(d);
> +		if (de == NULL) {
> +			if (errno == 0)
> +				break;
> +			pr_perror("Unable to read the libraries directory");
> +			goto err;
> +		}
> +
> +		len = strlen(de->d_name);
> +
> +		if (len < 3 || strncmp(de->d_name + len - 3, ".so", 3))
> +			continue;
> +
> +		snprintf(path, sizeof(path), "%s/%s", opts.libdir, de->d_name);
> +
> +		if (cr_lib_load(path))
> +			goto err;
> +	}
> +
> +	exit_code = 0;
> +err:
> +	closedir(d);
> +
	if (exit_code)
> +	cr_lib_fini();
> +
> +	return exit_code;
> +}
> -- 
> 1.8.3.1
> 


More information about the CRIU mailing list