[PATCH 2/3] plugin: Rework plugins API

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.

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>
---
 include/criu-plugin.h | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/plugin.h      | 32 ++++++++++++++++++++
 2 files changed, 115 insertions(+)

diff --git a/include/criu-plugin.h b/include/criu-plugin.h
index cda8c8eb98e6..c14b53b383c5 100644
--- a/include/criu-plugin.h
+++ b/include/criu-plugin.h
@@ -23,6 +23,89 @@
 #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.
+ */
+
+#define DECLARE_PLUGIN_HOOK_ARGS(__hook, ...)	\
+	typedef int (__hook ##_t)(__VA_ARGS__)
+
+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
+};
+
+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);
+
+typedef struct {
+	const char		*name;
+	int			(*init)(void);
+	void			(*exit)(void);
+	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(void) { return 0; }
+static inline void cr_plugin_dummy_exit(void) { }
+
+#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;					\
+}
+
+/*
+ * Obsolete, will be dropped off after a couple of releases.
+ */
 typedef int (cr_plugin_init_t)(void);
 typedef void (cr_plugin_fini_t)(void);
 
diff --git a/include/plugin.h b/include/plugin.h
index 3c53e3003de3..7f1de63701b1 100644
--- a/include/plugin.h
+++ b/include/plugin.h
@@ -2,6 +2,8 @@
 #define __CR_PLUGIN_H__
 
 #include "criu-plugin.h"
+#include "compiler.h"
+#include "list.h"
 
 #define CR_PLUGIN_DEFAULT "/var/lib/criu/"
 
@@ -19,4 +21,34 @@ int cr_plugin_restore_ext_mount(int id, char *mountpoint, char *old_root, int *i
 
 int cr_plugin_dump_ext_link(int index, int type, char *kind);
 
+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[__hook], link[__hook]) {		\
+		pr_debug("plugin: `%s' hook %u -> %p\n",					\
+			 this->d->name, __hook, this->d->hooks[__hook]);			\
+		__ret = ((__hook ##_t *)this->d->hooks[__hook])(__VA_ARGS__);			\
+		if (__ret == -ENOTSUP)								\
+			continue;								\
+		break;										\
+	}											\
+	__ret;											\
+})
+
 #endif
-- 
1.8.3.1


--3Gf/FFewwPeBMqCJ--


More information about the CRIU mailing list