[CRIU] [PATCH 2/2] plugin: Rework plugins API, v2
Andrew Vagin
avagin at parallels.com
Thu Aug 14 01:42:22 PDT 2014
On Wed, Aug 13, 2014 at 11:52:24PM +0400, Cyrill Gorcunov wrote:
> On Thu, Aug 07, 2014 at 11:40:29PM +0400, Cyrill Gorcunov wrote:
> >
> > Here we define new api to be used in plugins.
>
> There were a small nit, so updated variant attached.
> From 936627ec8a04456ea3502bd760d6a05fa7833ac8 Mon Sep 17 00:00:00 2001
> From: Cyrill Gorcunov <gorcunov at openvz.org>
> Date: Thu, 27 Feb 2014 20:58:23 +0400
> Subject: [PATCH 1/2] plugin: Rework plugins API, v2
>
> 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>
Acked-by: Andrew Vagin <avagin 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
>
More information about the CRIU
mailing list