[CRIU] [PATCH 1/8] crtools: preload libraries (v2)
Andrey Vagin
avagin at openvz.org
Mon Dec 16 03:26:39 PST 2013
Libraries (plugins) is going to be used for dumping and restoring
external dependencies (e.g. dbus, systemd journal sockets, charecter
devices, etc)
A plugin can have the cr_plugin_init() and cr_plugin_fini functions for
initialization and deinialization.
criu-plugin.h contains all things, which can be used in plugins.
v2: rename lib to plugin
v3: add a default value for a plugin path.
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
Makefile | 4 +-
Makefile.crtools | 1 +
cr-dump.c | 6 +++
cr-restore.c | 27 ++++++----
crtools.c | 14 ++++-
include/cr_options.h | 1 +
include/criu-plugin.h | 26 ++++++++++
include/plugin.h | 10 ++++
plugin.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 216 insertions(+), 12 deletions(-)
create mode 100644 include/criu-plugin.h
create mode 100644 include/plugin.h
create mode 100644 plugin.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..1e1ccfe 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 += plugin.o
ifneq ($(MAKECMDGOALS),clean)
incdeps := y
diff --git a/cr-dump.c b/cr-dump.c
index ffae7ff..234fdee 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_plugin_init())
+ goto err;
+
if (kerndat_init())
goto err;
@@ -1753,6 +1757,8 @@ err:
close_cr_fdset(&glob_fdset);
+ cr_plugin_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..69c4696 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_plugin_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_plugin_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..b62e554 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"))
@@ -412,6 +423,7 @@ usage:
" --action-script FILE add an external action script\n"
" -j|--" OPT_SHELL_JOB " allow to dump and restore shell jobs\n"
" -l|--" OPT_FILE_LOCKS " handle file locks, for safety, only used for container\n"
+" -L|--libdir path to a plugin directory (by default " CR_PLUGIN_DEFAULT ")\n"
"\n"
"* Logging:\n"
" -o|--log-file FILE log file name\n"
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..87a38ec
--- /dev/null
+++ b/include/plugin.h
@@ -0,0 +1,10 @@
+#ifndef __CR_PLUGIN_H__
+#define __CR_PLUGIN_H__
+
+#include "criu-plugin.h"
+
+#define CR_PLUGIN_DEFAULT "/var/lib/criu/"
+
+void cr_plugin_fini(void);
+int cr_plugin_init(void);
+#endif
diff --git a/plugin.c b/plugin.c
new file mode 100644
index 0000000..373629a
--- /dev/null
+++ b/plugin.c
@@ -0,0 +1,139 @@
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <dlfcn.h>
+#include <unistd.h>
+
+#include "cr_options.h"
+#include "plugin.h"
+#include "log.h"
+#include "xmalloc.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;
+};
+
+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_plugin_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_plugin_init(void)
+{
+ int exit_code = -1;
+ char *path;
+ DIR *d;
+
+ memset(&cr_plugins, 0, sizeof(cr_plugins));
+
+ if (opts.libdir == NULL) {
+ path = getenv("CRIU_LIBS_DIR");
+ if (path) {
+ opts.libdir = strdup(path);
+ } else {
+ if (access(CR_PLUGIN_DEFAULT, F_OK))
+ return 0;
+ opts.libdir = strdup(CR_PLUGIN_DEFAULT);
+ }
+ if (opts.libdir == NULL) {
+ pr_perror("Can't allocate memory");
+ return -1;
+ }
+ }
+
+ d = opendir(opts.libdir);
+ if (d == NULL) {
+ 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_plugin_fini();
+
+ return exit_code;
+}
--
1.8.3.1
More information about the CRIU
mailing list