[PATCH 1/2] plugin: Rework plugins API, v2

Cyrill Gorcunov gorcunov at openvz.org
Thu Feb 27 08:58:23 PST 2014


Here we define new api to be used in plugins.

 - Plugin should provide a descriptor with help of
   CR_PLUGIN_REGISTER macro, or in case if plugin require
   no init/exit functions -- with CR_PLUGIN_REGISTER_DUMMY.

 - Plugin should define a plugin hook with help of
   CR_PLUGIN_REGISTER_HOOK macro.

 - Now init/exit functions of plugins takes @stage
   argument which tells plugin which stage of criu
   it's been called on dump/restore. For exit it
   also takes @ret which allows plugin to know if
   something went wrong and it needs to cleanup
   own resources.

The idea behind is to not limit plugins authors with names
of functions they might need to use for particular hook.

Such new API deprecates olds plugins structure but to keep
backward compatibility we will provide a tiny layer of
additional code to support old plugins for at least a couple
of release cycles.

For example a trivial plugin might look like

 | #include <sys/types.h>
 | #include <sys/stat.h>
 | #include <fcntl.h>
 | #include <libgen.h>
 | #include <errno.h>
 |
 | #include <sys/socket.h>
 | #include <linux/un.h>
 |
 | #include <stdio.h>
 | #include <stdlib.h>
 | #include <string.h>
 | #include <unistd.h>
 |
 | #include "criu-plugin.h"
 | #include "criu-log.h"
 |
 | static int dump_ext_file(int fd, int id)
 | {
 |	pr_info("dump_ext_file: fd %d id %d\n", fd, id);
 |	return 0;
 | }
 |
 | CR_PLUGIN_REGISTER_DUMMY("trivial")
 | CR_PLUGIN_REGISTER_HOOK(CR_PLUGIN_HOOK__DUMP_EXT_FILE, dump_ext_file)

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 cr-dump.c             |   4 +-
 cr-restore.c          |   4 +-
 files-ext.c           |   4 +-
 include/criu-plugin.h | 102 +++++++++++++++++--
 include/plugin.h      |  50 +++++++---
 mount.c               |   4 +-
 net.c                 |   2 +-
 plugin.c              | 271 +++++++++++++++++++++++++-------------------------
 sk-unix.c             |   4 +-
 9 files changed, 279 insertions(+), 166 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index 1700d9dc071f..75f634a25a5a 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1761,7 +1761,7 @@ int cr_dump_tasks(pid_t pid)
 	if (init_stats(DUMP_STATS))
 		goto err;
 
-	if (cr_plugin_init())
+	if (cr_plugin_init(CR_PLUGIN_STAGE__DUMP))
 		goto err;
 
 	if (kerndat_init())
@@ -1858,7 +1858,7 @@ err:
 
 	close_cr_fdset(&glob_fdset);
 
-	cr_plugin_fini();
+	cr_plugin_fini(CR_PLUGIN_STAGE__DUMP, ret);
 
 	if (!ret) {
 		/*
diff --git a/cr-restore.c b/cr-restore.c
index 2bc98e83fedd..c38526673d27 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1723,7 +1723,7 @@ int cr_restore_tasks(void)
 {
 	int ret = -1;
 
-	if (cr_plugin_init())
+	if (cr_plugin_init(CR_PLUGIN_STAGE__RESTORE))
 		return -1;
 
 	if (check_img_inventory() < 0)
@@ -1762,7 +1762,7 @@ int cr_restore_tasks(void)
 
 	fini_cgroup();
 err:
-	cr_plugin_fini();
+	cr_plugin_fini(CR_PLUGIN_STAGE__RESTORE, ret);
 	return ret;
 }
 
diff --git a/files-ext.c b/files-ext.c
index d9640c49ccb2..a5ca5945d4ac 100644
--- a/files-ext.c
+++ b/files-ext.c
@@ -15,7 +15,7 @@ static int dump_one_ext_file(int lfd, u32 id, const struct fd_parms *p)
 
 	ExtFileEntry xfe = EXT_FILE_ENTRY__INIT;
 
-	ret = cr_plugin_dump_file(lfd, id);
+	ret = run_plugins(DUMP_EXT_FILE, lfd, id);
 	if (ret < 0)
 		return ret;
 
@@ -44,7 +44,7 @@ static int open_fd(struct file_desc *d)
 
 	xfi = container_of(d, struct ext_file_info, d);
 
-	fd = cr_plugin_restore_file(xfi->xfe->id);
+	fd = run_plugins(RESTORE_EXT_FILE, xfi->xfe->id);
 	if (fd < 0) {
 		pr_err("Unable to restore %#x\n", xfi->xfe->id);
 		return -1;
diff --git a/include/criu-plugin.h b/include/criu-plugin.h
index cda8c8eb98e6..3f76b8fe6e54 100644
--- a/include/criu-plugin.h
+++ b/include/criu-plugin.h
@@ -23,21 +23,109 @@
 #include <limits.h>
 #include <stdbool.h>
 
+#define CRIU_PLUGIN_GEN_VERSION(a,b,c)	(((a) << 16) + ((b) << 8) + (c))
+#define CRIU_PLUGIN_VERSION_MAJOR	0
+#define CRIU_PLUGIN_VERSION_MINOR	2
+#define CRIU_PLUGIN_VERSION_SUBLEVEL	0
+
+#define CRIU_PLUGIN_VERSION_OLD		CRIU_PLUGIN_GEN_VERSION(0,1,0)
+
+#define CRIU_PLUGIN_VERSION					\
+	CRIU_PLUGIN_GEN_VERSION(CRIU_PLUGIN_VERSION_MAJOR,	\
+				CRIU_PLUGIN_VERSION_MINOR,	\
+				CRIU_PLUGIN_VERSION_SUBLEVEL)
+
+/*
+ * Plugin hook points and their arguments in hooks.
+ */
+enum {
+	CR_PLUGIN_HOOK__DUMP_UNIX_SK,
+	CR_PLUGIN_HOOK__RESTORE_UNIX_SK,
+
+	CR_PLUGIN_HOOK__DUMP_EXT_FILE,
+	CR_PLUGIN_HOOK__RESTORE_EXT_FILE,
+
+	CR_PLUGIN_HOOK__DUMP_EXT_MOUNT,
+	CR_PLUGIN_HOOK__RESTORE_EXT_MOUNT,
+
+	CR_PLUGIN_HOOK__DUMP_EXT_LINK,
+
+	CR_PLUGIN_HOOK__MAX
+};
+
+#define DECLARE_PLUGIN_HOOK_ARGS(__hook, ...)	\
+	typedef int (__hook ##_t)(__VA_ARGS__)
+
+DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__DUMP_UNIX_SK, int fd, int id);
+DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__RESTORE_UNIX_SK, int id);
+DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__DUMP_EXT_FILE, int fd, int id);
+DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__RESTORE_EXT_FILE, int id);
+DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__DUMP_EXT_MOUNT, char *mountpoint, int id);
+DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__RESTORE_EXT_MOUNT, int id, char *mountpoint, char *old_root, int *is_file);
+DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__DUMP_EXT_LINK, int index, int type, char *kind);
+
+enum {
+	CR_PLUGIN_STAGE__DUMP,
+	CR_PLUGIN_STAGE__RESTORE,
+
+	CR_PLUGIN_STAGE_MAX
+};
+
+/*
+ * Plugin descriptor.
+ */
+typedef struct {
+	const char		*name;
+	int			(*init)(int stage);
+	void			(*exit)(int stage, int ret);
+	unsigned int		version;
+	unsigned int		max_hooks;
+	void			*hooks[CR_PLUGIN_HOOK__MAX];
+} cr_plugin_desc_t;
+
+extern cr_plugin_desc_t CR_PLUGIN_DESC;
+
+#define CR_PLUGIN_REGISTER(___name, ___init, ___exit)					\
+	cr_plugin_desc_t CR_PLUGIN_DESC = {						\
+		.name		= ___name,						\
+		.init		= ___init,						\
+		.exit		= ___exit,						\
+		.version	= CRIU_PLUGIN_VERSION,					\
+		.max_hooks	= CR_PLUGIN_HOOK__MAX,					\
+	};
+
+static inline int cr_plugin_dummy_init(int stage) { return 0; }
+static inline void cr_plugin_dummy_exit(int stage, int ret) { }
+
+#define CR_PLUGIN_REGISTER_DUMMY(___name)						\
+	cr_plugin_desc_t CR_PLUGIN_DESC = {						\
+		.name		= ___name,						\
+		.init		= cr_plugin_dummy_init,					\
+		.exit		= cr_plugin_dummy_exit,					\
+		.version	= CRIU_PLUGIN_VERSION,					\
+		.max_hooks	= CR_PLUGIN_HOOK__MAX,					\
+	};
+
+#define CR_PLUGIN_REGISTER_HOOK(__hook, __func)						\
+static void __attribute__((constructor)) cr_plugin_register_hook_##__func (void)	\
+{											\
+	CR_PLUGIN_DESC.hooks[__hook] = (void *)__func;					\
+}
+
+/* Public API */
+extern int criu_get_image_dir(void);
+
+/*
+ * Deprecated, will be removed in next version.
+ */
 typedef int (cr_plugin_init_t)(void);
 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);
-
 typedef int (cr_plugin_dump_ext_mount_t)(char *mountpoint, int id);
 typedef int (cr_plugin_restore_ext_mount_t)(int id, char *mountpoint, char *old_root, int *is_file);
-
 typedef int (cr_plugin_dump_ext_link_t)(int index, int type, char *kind);
 
-/* Public API */
-extern int criu_get_image_dir(void);
-
 #endif /* __CRIU_PLUGIN_H__ */
diff --git a/include/plugin.h b/include/plugin.h
index 3c53e3003de3..2855836206d9 100644
--- a/include/plugin.h
+++ b/include/plugin.h
@@ -2,21 +2,45 @@
 #define __CR_PLUGIN_H__
 
 #include "criu-plugin.h"
+#include "compiler.h"
+#include "list.h"
 
 #define CR_PLUGIN_DEFAULT "/var/lib/criu/"
 
-void cr_plugin_fini(void);
-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);
-
-int cr_plugin_dump_ext_mount(char *mountpoint, int id);
-int cr_plugin_restore_ext_mount(int id, char *mountpoint, char *old_root, int *is_file);
-
-int cr_plugin_dump_ext_link(int index, int type, char *kind);
+void cr_plugin_fini(int stage, int err);
+int cr_plugin_init(int stage);
+
+typedef struct {
+	struct list_head	head;
+	struct list_head	hook_chain[CR_PLUGIN_HOOK__MAX];
+} cr_plugin_ctl_t;
+
+extern cr_plugin_ctl_t cr_plugin_ctl;
+
+typedef struct {
+	cr_plugin_desc_t	*d;
+	struct list_head	list;
+	void			*dlhandle;
+	struct list_head	link[CR_PLUGIN_HOOK__MAX];
+} plugin_desc_t;
+
+#define run_plugins(__hook, ...)								\
+({												\
+	plugin_desc_t *this;									\
+	int __ret = -ENOTSUP;									\
+												\
+	list_for_each_entry(this, &cr_plugin_ctl.hook_chain[CR_PLUGIN_HOOK__ ##__hook],		\
+			    link[CR_PLUGIN_HOOK__ ##__hook]) {					\
+		pr_debug("plugin: `%s' hook %u -> %p\n",					\
+			 this->d->name, CR_PLUGIN_HOOK__ ##__hook,				\
+			 this->d->hooks[CR_PLUGIN_HOOK__ ##__hook]);				\
+		__ret = ((CR_PLUGIN_HOOK__ ##__hook ##_t *)					\
+			 this->d->hooks[CR_PLUGIN_HOOK__ ##__hook])(__VA_ARGS__);		\
+		if (__ret == -ENOTSUP)								\
+			continue;								\
+		break;										\
+	}											\
+	__ret;											\
+})
 
 #endif
diff --git a/mount.c b/mount.c
index 9a147abe4ddd..81f358399c90 100644
--- a/mount.c
+++ b/mount.c
@@ -425,7 +425,7 @@ static int validate_mounts(struct mount_info *info, bool for_dump)
 				int ret;
 
 				if (for_dump) {
-					ret = cr_plugin_dump_ext_mount(m->mountpoint + 1, m->mnt_id);
+					ret = run_plugins(DUMP_EXT_MOUNT, m->mountpoint, m->mnt_id);
 					if (ret == 0)
 						m->need_plugin = true;
 					else if (ret == -ENOTSUP)
@@ -1297,7 +1297,7 @@ static int restore_ext_mount(struct mount_info *mi)
 	int ret;
 
 	pr_debug("Restoring external bind mount %s\n", mi->mountpoint);
-	ret = cr_plugin_restore_ext_mount(mi->mnt_id, mi->mountpoint, "/", NULL);
+	ret = run_plugins(RESTORE_EXT_MOUNT, mi->mnt_id, mi->mountpoint, "/", NULL);
 	if (ret)
 		pr_perror("Can't restore ext mount (%d)\n", ret);
 	return ret;
diff --git a/net.c b/net.c
index 206736ad764b..177b7592f6a4 100644
--- a/net.c
+++ b/net.c
@@ -106,7 +106,7 @@ static int dump_unknown_device(struct ifinfomsg *ifi, char *kind,
 {
 	int ret;
 
-	ret = cr_plugin_dump_ext_link(ifi->ifi_index, ifi->ifi_type, kind);
+	ret = run_plugins(DUMP_EXT_LINK, ifi->ifi_index, ifi->ifi_type, kind);
 	if (ret == 0)
 		return dump_one_netdev(ND_TYPE__EXTLINK, ifi, tb, fds, NULL);
 
diff --git a/plugin.c b/plugin.c
index 367f9fda39eb..c4584657f2e0 100644
--- a/plugin.c
+++ b/plugin.c
@@ -1,117 +1,97 @@
+#include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
 #include <dirent.h>
-#include <errno.h>
 #include <stdio.h>
+#include <errno.h>
 #include <dlfcn.h>
-#include <unistd.h>
 
 #include "cr_options.h"
+#include "compiler.h"
+#include "xmalloc.h"
 #include "plugin.h"
+#include "list.h"
 #include "log.h"
-#include "xmalloc.h"
 
-struct cr_plugin_entry {
-	union {
-		cr_plugin_fini_t		*cr_fini;
-
-		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;
-		cr_plugin_dump_ext_mount_t	*cr_plugin_dump_ext_mount;
-		cr_plugin_restore_ext_mount_t	*cr_plugin_restore_ext_mount;
-		cr_plugin_dump_ext_link_t	*cr_plugin_dump_ext_link;
-	};
-
-	struct cr_plugin_entry *next;
-};
-
-struct cr_plugins {
-	struct cr_plugin_entry *cr_fini;
-
-	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_plugin_entry *cr_plugin_dump_ext_mount;
-	struct cr_plugin_entry *cr_plugin_restore_ext_mount;
-	struct cr_plugin_entry *cr_plugin_dump_ext_link;
-};
-
-struct cr_plugins cr_plugins;
-
-#define add_plugin_func(name)						\
+cr_plugin_ctl_t cr_plugin_ctl;
+
+/*
+ * If we met old version of a plugin, selfgenerate a plugin descriptor for it.
+ */
+static cr_plugin_desc_t *cr_gen_plugin_desc(void *h, char *path)
+{
+	cr_plugin_desc_t *d;
+
+	d = xzalloc(sizeof(*d));
+	if (!d)
+		return NULL;
+
+	d->name		= strdup(path);
+	d->max_hooks	= CR_PLUGIN_HOOK__MAX;
+	d->version	= CRIU_PLUGIN_VERSION_OLD;
+
+	pr_warn("Generating dynamic descriptor for plugin `%s'."
+		"Won't work in next version of the program."
+		"Please update your plugin.\n", path);
+
+#define __assign_hook(__hook, __name)					\
 	do {								\
-		name ## _t *name;					\
-		name = dlsym(h, #name);					\
-		if (name) {						\
-			struct cr_plugin_entry *__ce;			\
-			__ce = xmalloc(sizeof(*__ce));			\
-			if (__ce == NULL)				\
-				goto nomem;				\
-			__ce->name = name;				\
-			__ce->next = cr_plugins.name;			\
-			cr_plugins.name = __ce;				\
-		}							\
+		void *name;						\
+		name = dlsym(h, __name);				\
+		if (name)						\
+			d->hooks[CR_PLUGIN_HOOK__ ##__hook] = name;	\
 	} while (0)
 
-#define run_plugin_funcs(name, ...) ({					\
-		struct cr_plugin_entry *__ce = cr_plugins.name;		\
-		int __ret = -ENOTSUP;					\
-									\
-		while (__ce) {						\
-			__ret = __ce->name(__VA_ARGS__);		\
-			if (__ret == -ENOTSUP) {			\
-				__ce = __ce->next;			\
-				continue;				\
-			}						\
-			break;						\
-		}							\
-									\
-		__ret;							\
-	})								\
-
-int cr_plugin_dump_unix_sk(int fd, int id)
-{
-	return run_plugin_funcs(cr_plugin_dump_unix_sk, fd, id);
-}
+	__assign_hook(DUMP_UNIX_SK,		"cr_plugin_dump_unix_sk");
+	__assign_hook(RESTORE_UNIX_SK,		"cr_plugin_restore_unix_sk");
+	__assign_hook(DUMP_EXT_FILE,		"cr_plugin_dump_file");
+	__assign_hook(RESTORE_EXT_FILE,		"cr_plugin_restore_file");
+	__assign_hook(DUMP_EXT_MOUNT,		"cr_plugin_dump_ext_mount");
+	__assign_hook(RESTORE_EXT_MOUNT,	"cr_plugin_restore_ext_mount");
+	__assign_hook(DUMP_EXT_LINK,		"cr_plugin_dump_ext_link");
 
-int cr_plugin_restore_unix_sk(int id)
-{
-	return run_plugin_funcs(cr_plugin_restore_unix_sk, id);
-}
+#undef __assign_hook
 
-int cr_plugin_dump_file(int fd, int id)
-{
-	return run_plugin_funcs(cr_plugin_dump_file, fd, id);
-}
+	d->init = dlsym(h, "cr_plugin_init");
+	d->exit = dlsym(h, "cr_plugin_fini");
 
-int cr_plugin_restore_file(int id)
-{
-	return run_plugin_funcs(cr_plugin_restore_file, id);
+	return d;
 }
 
-int cr_plugin_dump_ext_mount(char *mountpoint, int id)
+static void show_plugin_desc(cr_plugin_desc_t *d)
 {
-	return run_plugin_funcs(cr_plugin_dump_ext_mount, mountpoint, id);
-}
+	size_t i;
 
-int cr_plugin_restore_ext_mount(int id, char *mountpoint, char *old_root, int *is_file)
-{
-	return run_plugin_funcs(cr_plugin_restore_ext_mount, id, mountpoint, old_root, is_file);
+	pr_debug("Plugin \"%s\" (version %u hooks %u)\n",
+		 d->name, d->version, d->max_hooks);
+	for (i = 0; i < d->max_hooks; i++) {
+		if (d->hooks[i])
+			pr_debug("\t%4zu -> %p\n", i, d->hooks[i]);
+	}
 }
 
-int cr_plugin_dump_ext_link(int index, int type, char *kind)
+static int verify_plugin(cr_plugin_desc_t *d)
 {
-	return run_plugin_funcs(cr_plugin_dump_ext_link, index, type, kind);
+	if (d->version > CRIU_PLUGIN_VERSION) {
+		pr_debug("Plugin %s has version %x while max %x supported\n",
+			 d->name, d->version, CRIU_PLUGIN_VERSION);
+		return -1;
+	}
+
+	if (d->max_hooks > CR_PLUGIN_HOOK__MAX) {
+		pr_debug("Plugin %s has %u assigned while max %u supported\n",
+			 d->name, d->max_hooks, CR_PLUGIN_HOOK__MAX);
+		return -1;
+	}
+
+	return 0;
 }
 
-static int cr_lib_load(char *path)
+static int cr_lib_load(int stage, char *path)
 {
-	struct cr_plugin_entry *ce;
-	cr_plugin_init_t *f_init;
-	cr_plugin_fini_t *f_fini;
+	cr_plugin_desc_t *d;
+	plugin_desc_t *this;
+	size_t i;
 	void *h;
 
 	h = dlopen(path, RTLD_LAZY);
@@ -120,77 +100,98 @@ static int cr_lib_load(char *path)
 		return -1;
 	}
 
-	add_plugin_func(cr_plugin_dump_unix_sk);
-	add_plugin_func(cr_plugin_restore_unix_sk);
+	/*
+	 * Load plugin descriptor. If plugin is too old -- create
+	 * dynamic plugin descriptor. In most cases this won't
+	 * be a common operation and plugins are not supposed to
+	 * be changing own format frequently.
+	 */
+	d = dlsym(h, "CR_PLUGIN_DESC");
+	if (!d)
+		d = cr_gen_plugin_desc(h, path);
+	if (!d) {
+		pr_err("Can't load plugin %s\n", path);
+		dlclose(h);
+		return -1;
+	}
+
+	this = xzalloc(sizeof(*this));
+	if (!this) {
+		dlclose(h);
+		return -1;
+	}
 
-	add_plugin_func(cr_plugin_dump_file);
-	add_plugin_func(cr_plugin_restore_file);
+	if (verify_plugin(d)) {
+		pr_err("Corrupted plugin %s\n", path);
+		xfree(this);
+		dlclose(h);
+		return -1;
+	}
 
-	add_plugin_func(cr_plugin_dump_ext_mount);
-	add_plugin_func(cr_plugin_restore_ext_mount);
+	this->d = d;
+	this->dlhandle = h;
+	INIT_LIST_HEAD(&this->list);
 
-	add_plugin_func(cr_plugin_dump_ext_link);
+	for (i = 0; i < d->max_hooks; i++)
+		INIT_LIST_HEAD(&this->link[i]);
 
-	ce = NULL;
-	f_fini = dlsym(h, "cr_plugin_fini");
-	if (f_fini) {
-		ce = xmalloc(sizeof(*ce));
-		if (ce == NULL)
-			goto nomem;
-		ce->cr_fini = f_fini;
-	}
+	list_add_tail(&this->list, &cr_plugin_ctl.head);
+	show_plugin_desc(d);
 
-	f_init = dlsym(h, "cr_plugin_init");
-	if (f_init && f_init()) {
-		xfree(ce);
+	if (d->init && d->init(stage)) {
+		pr_err("Failed in init(%d) of \"%s\"\n", stage, d->name);
+		list_del(&this->list);
+		xfree(this);
+		dlclose(h);
 		return -1;
 	}
 
-	if (ce) {
-		ce->next = cr_plugins.cr_fini;
-		cr_plugins.cr_fini = ce;
+	/*
+	 * Chain hooks into appropriate places for
+	 * fast handler access.
+	 */
+	for (i = 0; i < d->max_hooks; i++) {
+		if (!d->hooks[i])
+			continue;
+		list_add_tail(&this->link[i], &cr_plugin_ctl.hook_chain[i]);
 	}
 
 	return 0;
-
-nomem:
-	return -1;
 }
 
-#define cr_plugin_free(name) do {				\
-	while (cr_plugins.name) {				\
-		ce = cr_plugins.name;				\
-		cr_plugins.name = cr_plugins.name->next;	\
-		xfree(ce);					\
-	}							\
-} while (0)							\
-
-void cr_plugin_fini(void)
+void cr_plugin_fini(int stage, int ret)
 {
-	struct cr_plugin_entry *ce;
+	plugin_desc_t *this, *tmp;
 
-	cr_plugin_free(cr_plugin_dump_unix_sk);
-	cr_plugin_free(cr_plugin_restore_unix_sk);
+	list_for_each_entry_safe(this, tmp, &cr_plugin_ctl.head, list) {
+		void *h = this->dlhandle;
+		size_t i;
 
-	cr_plugin_free(cr_plugin_dump_file);
-	cr_plugin_free(cr_plugin_restore_file);
+		list_del(&this->list);
+		if (this->d->exit)
+			this->d->exit(stage, ret);
 
-	while (cr_plugins.cr_fini) {
-		ce = cr_plugins.cr_fini;
-		cr_plugins.cr_fini = cr_plugins.cr_fini->next;
+		for (i = 0; i < this->d->max_hooks; i++) {
+			if (!list_empty(&this->link[i]))
+				list_del(&this->link[i]);
+		}
 
-		ce->cr_fini();
-		xfree(ce);
+		if (this->d->version == CRIU_PLUGIN_VERSION_OLD)
+			xfree(this->d);
+		dlclose(h);
 	}
 }
 
-int cr_plugin_init(void)
+int cr_plugin_init(int stage)
 {
 	int exit_code = -1;
 	char *path;
+	size_t i;
 	DIR *d;
 
-	memset(&cr_plugins, 0, sizeof(cr_plugins));
+	INIT_LIST_HEAD(&cr_plugin_ctl.head);
+	for (i = 0; i < ARRAY_SIZE(cr_plugin_ctl.hook_chain); i++)
+		INIT_LIST_HEAD(&cr_plugin_ctl.hook_chain[i]);
 
 	if (opts.libdir == NULL) {
 		path = getenv("CRIU_LIBS_DIR");
@@ -231,7 +232,7 @@ int cr_plugin_init(void)
 
 		snprintf(path, sizeof(path), "%s/%s", opts.libdir, de->d_name);
 
-		if (cr_lib_load(path))
+		if (cr_lib_load(stage, path))
 			goto err;
 	}
 
@@ -240,7 +241,7 @@ err:
 	closedir(d);
 
 	if (exit_code)
-		cr_plugin_fini();
+		cr_plugin_fini(stage, exit_code);
 
 	return exit_code;
 }
diff --git a/sk-unix.c b/sk-unix.c
index f205d8f46cdc..dad07505f98e 100644
--- a/sk-unix.c
+++ b/sk-unix.c
@@ -550,7 +550,7 @@ static int dump_external_sockets(struct unix_sk_desc *peer)
 	while (!list_empty(&peer->peer_list)) {
 		sk = list_first_entry(&peer->peer_list, struct unix_sk_desc, peer_node);
 
-		ret = cr_plugin_dump_unix_sk(sk->fd, sk->sd.ino);
+		ret = run_plugins(DUMP_UNIX_SK, sk->fd, sk->sd.ino);
 		if (ret == -ENOTSUP) {
 			if (!opts.ext_unix_sk) {
 				show_one_unix("Runaway socket", peer);
@@ -917,7 +917,7 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
 		sk = sks[0];
 	} else {
 		if (ui->ue->uflags & USK_CALLBACK) {
-			sk = cr_plugin_restore_unix_sk(ui->ue->ino);
+			sk = run_plugins(RESTORE_UNIX_SK, ui->ue->ino);
 			if (sk >= 0)
 				goto out;
 		}
-- 
1.9.3


--2/5bycvrmDh4d1IB--


More information about the CRIU mailing list