[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH 2/8] plugins: version 2, require unique plugin names
From: |
Alex Bennée |
Subject: |
Re: [PATCH 2/8] plugins: version 2, require unique plugin names |
Date: |
Thu, 09 Mar 2023 14:17:54 +0000 |
User-agent: |
mu4e 1.9.21; emacs 29.0.60 |
Andrew Fasano <fasano@mit.edu> writes:
> From: Elysia Witham <elysia.witham@ll.mit.edu>
>
> In order for the QPP API to resolve interactions between plugins,
> plugins must export their own names which cannot match any other
> loaded plugins.
>
> Signed-off-by: Elysia Witham <elysia.witham@ll.mit.edu>
> Signed-off-by: Andrew Fasano <fasano@mit.edu>
> ---
> include/qemu/qemu-plugin.h | 2 +-
> plugins/core.c | 12 +++++++++
> plugins/loader.c | 50 +++++++++++++++++++++++++++++++++-----
> plugins/plugin.h | 7 ++++++
> tests/plugin/bb.c | 1 +
> tests/plugin/empty.c | 1 +
> tests/plugin/insn.c | 1 +
> tests/plugin/mem.c | 1 +
> tests/plugin/syscall.c | 1 +
> 9 files changed, 69 insertions(+), 7 deletions(-)
>
> diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
> index d0e9d03adf..5326f33ce8 100644
> --- a/include/qemu/qemu-plugin.h
> +++ b/include/qemu/qemu-plugin.h
> @@ -51,7 +51,7 @@ typedef uint64_t qemu_plugin_id_t;
>
> extern QEMU_PLUGIN_EXPORT int qemu_plugin_version;
>
> -#define QEMU_PLUGIN_VERSION 1
> +#define QEMU_PLUGIN_VERSION 2
>
> /**
> * struct qemu_info_t - system information for plugins
> diff --git a/plugins/core.c b/plugins/core.c
> index ccb770a485..5fbdcb5768 100644
> --- a/plugins/core.c
> +++ b/plugins/core.c
> @@ -236,6 +236,18 @@ void qemu_plugin_vcpu_exit_hook(CPUState *cpu)
> qemu_rec_mutex_unlock(&plugin.lock);
> }
>
> +int name_to_plugin_version(const char *name)
> +{
> + struct qemu_plugin_ctx *ctx;
> + QTAILQ_FOREACH(ctx, &plugin.ctxs, entry) {
> + if (strcmp(ctx->name, name) == 0) {
> + return ctx->version;
> + }
> + }
> + warn_report("Could not find any plugin named %s.", name);
> + return -1;
> +}
> +
This function seems to be unused.
> struct plugin_for_each_args {
> struct qemu_plugin_ctx *ctx;
> qemu_plugin_vcpu_simple_cb_t cb;
> diff --git a/plugins/loader.c b/plugins/loader.c
> index 88c30bde2d..12c0680e03 100644
> --- a/plugins/loader.c
> +++ b/plugins/loader.c
> @@ -177,7 +177,7 @@ QEMU_DISABLE_CFI
> static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t
> *info, Error **errp)
> {
> qemu_plugin_install_func_t install;
> - struct qemu_plugin_ctx *ctx;
> + struct qemu_plugin_ctx *ctx, *ctx2;
> gpointer sym;
> int rc;
>
> @@ -208,17 +208,55 @@ static int plugin_load(struct qemu_plugin_desc *desc,
> const qemu_info_t *info, E
> desc->path, g_module_error());
> goto err_symbol;
> } else {
> - int version = *(int *)sym;
> - if (version < QEMU_PLUGIN_MIN_VERSION) {
> + ctx->version = *(int *)sym;
> + if (ctx->version < QEMU_PLUGIN_MIN_VERSION) {
> error_setg(errp, "Could not load plugin %s: plugin requires API
> version %d, but "
> "this QEMU supports only a minimum version of %d",
> - desc->path, version, QEMU_PLUGIN_MIN_VERSION);
> + desc->path, ctx->version, QEMU_PLUGIN_MIN_VERSION);
> goto err_symbol;
> - } else if (version > QEMU_PLUGIN_VERSION) {
> + } else if (ctx->version > QEMU_PLUGIN_VERSION) {
> error_setg(errp, "Could not load plugin %s: plugin requires API
> version %d, but "
> "this QEMU supports only up to version %d",
> - desc->path, version, QEMU_PLUGIN_VERSION);
> + desc->path, ctx->version, QEMU_PLUGIN_VERSION);
> goto err_symbol;
> + } else if (ctx->version < QPP_MINIMUM_VERSION) {
> + ctx->name = NULL;
A comment wouldn't go amiss here. Something like:
"Older plugins will not be available for QPP calls".
> + } else {
> + if (!g_module_symbol(ctx->handle, "qemu_plugin_name", &sym)) {
> + error_setg(errp, "Could not load plugin %s: plugin does not "
> + "declare plugin name %s",
> + desc->path, g_module_error());
> + goto err_symbol;
> + }
> + ctx->name = (const char *)strdup(*(const char **)sym);
> + QTAILQ_FOREACH(ctx2, &plugin.ctxs, entry) {
> + if (strcmp(ctx2->name, ctx->name) == 0) {
> + error_setg(errp, "Could not load plugin %s as the name
> %s "
> + "is already in use by plugin at %s",
> + desc->path, ctx->name, ctx2->desc->path);
> + goto err_symbol;
> + }
> + }
> + if (g_module_symbol(ctx->handle, "qemu_plugin_uses", &sym)) {
> + const char **dependencies = &(*(const char **)sym);
> + bool found = false;
> + while (*dependencies) {
> + found = false;
> + QTAILQ_FOREACH(ctx2, &plugin.ctxs, entry) {
> + if (strcmp(ctx2->name, *dependencies) == 0) {
Lets use glib where we can, in this case g_strcmp0().
> + dependencies++;
> + found = true;
> + break;
> + }
> + }
> + if (!found) {
> + error_setg(errp, "Could not load plugin %s as it is "
> + "dependent on %s which is not loaded",
> + ctx->name, *dependencies);
> + goto err_symbol;
> + }
We are implying a load order here which we should document. Ideally we
could avoid it but I suspect that requires too much hoop jumping.
> + }
> + }
> }
> }
>
> diff --git a/plugins/plugin.h b/plugins/plugin.h
> index 5eb2fdbc85..ce885bfa98 100644
> --- a/plugins/plugin.h
> +++ b/plugins/plugin.h
> @@ -16,6 +16,7 @@
> #include "qemu/qht.h"
>
> #define QEMU_PLUGIN_MIN_VERSION 0
> +#define QPP_MINIMUM_VERSION 2
>
> /* global state */
> struct qemu_plugin_state {
> @@ -50,6 +51,8 @@ struct qemu_plugin_state {
> struct qemu_plugin_ctx {
> GModule *handle;
> qemu_plugin_id_t id;
> + const char *name;
> + int version;
> struct qemu_plugin_cb *callbacks[QEMU_PLUGIN_EV_MAX];
> QTAILQ_ENTRY(qemu_plugin_ctx) entry;
> /*
> @@ -64,6 +67,8 @@ struct qemu_plugin_ctx {
>
> struct qemu_plugin_ctx *plugin_id_to_ctx_locked(qemu_plugin_id_t id);
>
> +struct qemu_plugin_ctx *plugin_name_to_ctx_locked(const char* name);
> +
> void plugin_register_inline_op(GArray **arr,
> enum qemu_plugin_mem_rw rw,
> enum qemu_plugin_op op, void *ptr,
> @@ -97,4 +102,6 @@ void plugin_register_vcpu_mem_cb(GArray **arr,
>
> void exec_inline_op(struct qemu_plugin_dyn_cb *cb);
>
> +int name_to_plugin_version(const char *name);
> +
> #endif /* PLUGIN_H */
> diff --git a/tests/plugin/bb.c b/tests/plugin/bb.c
> index 7d470a1011..c04e5aaf90 100644
> --- a/tests/plugin/bb.c
> +++ b/tests/plugin/bb.c
> @@ -15,6 +15,7 @@
> #include <qemu-plugin.h>
>
> QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> +QEMU_PLUGIN_EXPORT const char *qemu_plugin_name = "bb";
>
> typedef struct {
> GMutex lock;
> diff --git a/tests/plugin/empty.c b/tests/plugin/empty.c
> index 8fa6bacd93..0f3d2b92b9 100644
> --- a/tests/plugin/empty.c
> +++ b/tests/plugin/empty.c
> @@ -14,6 +14,7 @@
> #include <qemu-plugin.h>
>
> QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> +QEMU_PLUGIN_EXPORT const char *qemu_plugin_name = "empty";
>
> /*
> * Empty TB translation callback.
> diff --git a/tests/plugin/insn.c b/tests/plugin/insn.c
> index cd5ea5d4ae..3f71138139 100644
> --- a/tests/plugin/insn.c
> +++ b/tests/plugin/insn.c
> @@ -15,6 +15,7 @@
> #include <qemu-plugin.h>
>
> QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> +QEMU_PLUGIN_EXPORT const char *qemu_plugin_name = "insn";
>
> #define MAX_CPUS 8 /* lets not go nuts */
>
> diff --git a/tests/plugin/mem.c b/tests/plugin/mem.c
> index 4570f7d815..35e5d7fe2a 100644
> --- a/tests/plugin/mem.c
> +++ b/tests/plugin/mem.c
> @@ -15,6 +15,7 @@
> #include <qemu-plugin.h>
>
> QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> +QEMU_PLUGIN_EXPORT const char *qemu_plugin_name = "mem";
>
> static uint64_t inline_mem_count;
> static uint64_t cb_mem_count;
> diff --git a/tests/plugin/syscall.c b/tests/plugin/syscall.c
> index 96040c578f..922bdbd2e6 100644
> --- a/tests/plugin/syscall.c
> +++ b/tests/plugin/syscall.c
> @@ -15,6 +15,7 @@
> #include <qemu-plugin.h>
>
> QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> +QEMU_PLUGIN_EXPORT const char *qemu_plugin_name = "syscall";
>
> typedef struct {
> int64_t num;
You should update the plugins in contrib/plugins as well.
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [PATCH 2/8] plugins: version 2, require unique plugin names,
Alex Bennée <=