All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
From: "Marc-André Lureau" <marcandre.lureau@gmail.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: qemu-devel@nongnu.org, Eric Blake <eblake@redhat.com>,
	 Cleber Rosa <crosa@redhat.com>,
	qemu-block@nongnu.org,  Paolo Bonzini <pbonzini@redhat.com>,
	Xie Yongji <xieyongji@bytedance.com>,
	 Kyle Evans <kevans@freebsd.org>,
	Peter Maydell <peter.maydell@linaro.org>,
	 John Snow <jsnow@redhat.com>,
	Michael Roth <michael.roth@amd.com>, Warner Losh <imp@bsdimp.com>,
	 Kevin Wolf <kwolf@redhat.com>,
	"Dr. David Alan Gilbert" <dgilbert@redhat.com>,
	 Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>,
	Laurent Vivier <laurent@vivier.eu>,  Fam Zheng <fam@euphon.net>,
	Hanna Reitz <hreitz@redhat.com>
Subject: Re: [PATCH v2 06/15] qapi: move QEMU-specific dispatch code in monitor
Date: Tue, 2 Aug 2022 15:19:57 +0400	[thread overview]
Message-ID: <CAJ+F1C+hqN0SpG6cLxGEi9xcpW+vha6NzZZDJXb1fEbn-UianA@mail.gmail.com> (raw)
In-Reply-To: <87les6ud1p.fsf@pond.sub.org>

[-- Attachment #1: Type: text/plain, Size: 10956 bytes --]

Hi

On Tue, Aug 2, 2022 at 3:04 PM Markus Armbruster <armbru@redhat.com> wrote:

> marcandre.lureau@redhat.com writes:
>
> > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> >
> > Make QMP-dispatch code free from QEMU-specific OOB dispatch/async
> > coroutine handling. This will allow to move the base code to
> > qemu-common, and clear other users from potential mis-ususe (QGA doesn't
>

misuse :)

> have OOB or coroutine).
>
> I trust the utilty of such a move will become clear later in this
> series.
>
> >
> > To do that, introduce an optional callback QmpDispatchRun called when a
> > QMP command should be run, to allow QEMU to override the default
> > behaviour.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  include/qapi/qmp/dispatch.h |  7 ++--
> >  monitor/qmp.c               | 68 ++++++++++++++++++++++++++++++++++++-
> >  qapi/qmp-dispatch.c         | 64 +++-------------------------------
> >  qga/main.c                  |  2 +-
> >  tests/unit/test-qmp-cmds.c  |  6 ++--
> >  5 files changed, 81 insertions(+), 66 deletions(-)
> >
> > diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
> > index 1e4240fd0dbc..b659da613f2e 100644
> > --- a/include/qapi/qmp/dispatch.h
> > +++ b/include/qapi/qmp/dispatch.h
> > @@ -14,7 +14,6 @@
> >  #ifndef QAPI_QMP_DISPATCH_H
> >  #define QAPI_QMP_DISPATCH_H
> >
> > -#include "monitor/monitor.h"
> >  #include "qemu/queue.h"
> >
> >  typedef void (QmpCommandFunc)(QDict *, QObject **, Error **);
> > @@ -41,6 +40,10 @@ typedef struct QmpCommand
> >
> >  typedef QTAILQ_HEAD(QmpCommandList, QmpCommand) QmpCommandList;
> >
> > +typedef void (QmpDispatchRun)(bool oob, const QmpCommand *cmd,
> > +                              QDict *args, QObject **ret, Error **errp,
> > +                              void *run_data);
> > +
> >  void qmp_register_command(QmpCommandList *cmds, const char *name,
> >                            QmpCommandFunc *fn, QmpCommandOptions options,
> >                            unsigned special_features);
> > @@ -56,7 +59,7 @@ const char *qmp_command_name(const QmpCommand *cmd);
> >  bool qmp_has_success_response(const QmpCommand *cmd);
> >  QDict *qmp_error_response(Error *err);
> >  QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request,
> > -                    bool allow_oob, Monitor *cur_mon);
> > +                    bool allow_oob, QmpDispatchRun run_cb, void
> *run_data);
> >  bool qmp_is_oob(const QDict *dict);
> >
> >  typedef void (*qmp_cmd_callback_fn)(const QmpCommand *cmd, void
> *opaque);
> > diff --git a/monitor/qmp.c b/monitor/qmp.c
> > index 092c527b6fc9..f8dec97c96bb 100644
> > --- a/monitor/qmp.c
> > +++ b/monitor/qmp.c
> > @@ -132,6 +132,72 @@ static void monitor_qmp_respond(MonitorQMP *mon,
> QDict *rsp)
> >      }
> >  }
> >
> > +typedef struct QmpDispatchBH {
> > +    const QmpCommand *cmd;
> > +    Monitor *cur_mon;
> > +    QDict *args;
> > +    QObject **ret;
> > +    Error **errp;
> > +    Coroutine *co;
> > +} QmpDispatchBH;
> > +
> > +static void do_qmp_dispatch_bh(void *opaque)
> > +{
> > +    QmpDispatchBH *data = opaque;
> > +
> > +    assert(monitor_cur() == NULL);
> > +    monitor_set_cur(qemu_coroutine_self(), data->cur_mon);
> > +    data->cmd->fn(data->args, data->ret, data->errp);
> > +    monitor_set_cur(qemu_coroutine_self(), NULL);
> > +    aio_co_wake(data->co);
> > +}
> > +
> > +/*
> > + * Runs outside of coroutine context for OOB commands, but in coroutine
> > + * context for everything else.
> > + */
> > +static void qmp_dispatch_run(bool oob, const QmpCommand *cmd,
> > +                             QDict *args, QObject **ret, Error **errp,
> > +                             void *run_data)
> > +{
> > +    Monitor *cur_mon = run_data;
> > +
> > +    assert(!(oob && qemu_in_coroutine()));
> > +    assert(monitor_cur() == NULL);
> > +
> > +    if (!!(cmd->options & QCO_COROUTINE) == qemu_in_coroutine()) {
> > +        monitor_set_cur(qemu_coroutine_self(), cur_mon);
> > +        cmd->fn(args, ret, errp);
> > +        monitor_set_cur(qemu_coroutine_self(), NULL);
> > +    } else {
> > +       /*
> > +        * Actual context doesn't match the one the command needs.
> > +        *
> > +        * Case 1: we are in coroutine context, but command does not
> > +        * have QCO_COROUTINE.  We need to drop out of coroutine
> > +        * context for executing it.
> > +        *
> > +        * Case 2: we are outside coroutine context, but command has
> > +        * QCO_COROUTINE.  Can't actually happen, because we get here
> > +        * outside coroutine context only when executing a command
> > +        * out of band, and OOB commands never have QCO_COROUTINE.
> > +        */
> > +        assert(!oob && qemu_in_coroutine() && !(cmd->options &
> QCO_COROUTINE));
> > +
> > +        QmpDispatchBH data = {
> > +            .cur_mon    = cur_mon,
> > +            .cmd        = cmd,
> > +            .args       = args,
> > +            .ret        = ret,
> > +            .errp       = errp,
> > +            .co         = qemu_coroutine_self(),
> > +        };
> > +        aio_bh_schedule_oneshot(qemu_get_aio_context(),
> do_qmp_dispatch_bh,
> > +                                &data);
> > +        qemu_coroutine_yield();
> > +    }
> > +}
> > +
> >  /*
> >   * Runs outside of coroutine context for OOB commands, but in
> >   * coroutine context for everything else.
> > @@ -142,7 +208,7 @@ static void monitor_qmp_dispatch(MonitorQMP *mon,
> QObject *req)
> >      QDict *error;
> >
> >      rsp = qmp_dispatch(mon->commands, req, qmp_oob_enabled(mon),
> > -                       &mon->common);
> > +                       qmp_dispatch_run, &mon->common);
> >
> >      if (mon->commands == &qmp_cap_negotiation_commands) {
> >          error = qdict_get_qdict(rsp, "error");
> > diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
> > index 0990873ec8ec..342b13d7ebbd 100644
> > --- a/qapi/qmp-dispatch.c
> > +++ b/qapi/qmp-dispatch.c
> > @@ -13,7 +13,6 @@
> >
> >  #include "qemu/osdep.h"
> >
> > -#include "block/aio.h"
> >  #include "qapi/compat-policy.h"
> >  #include "qapi/error.h"
> >  #include "qapi/qmp/dispatch.h"
> > @@ -22,8 +21,6 @@
> >  #include "qapi/qobject-input-visitor.h"
> >  #include "qapi/qobject-output-visitor.h"
> >  #include "qapi/qmp/qbool.h"
> > -#include "qemu/coroutine.h"
> > -#include "qemu/main-loop.h"
> >
> >  Visitor *qobject_input_visitor_new_qmp(QObject *obj)
> >  {
> > @@ -110,32 +107,8 @@ bool qmp_is_oob(const QDict *dict)
> >          && !qdict_haskey(dict, "execute");
> >  }
> >
> > -typedef struct QmpDispatchBH {
> > -    const QmpCommand *cmd;
> > -    Monitor *cur_mon;
> > -    QDict *args;
> > -    QObject **ret;
> > -    Error **errp;
> > -    Coroutine *co;
> > -} QmpDispatchBH;
> > -
> > -static void do_qmp_dispatch_bh(void *opaque)
> > -{
> > -    QmpDispatchBH *data = opaque;
> > -
> > -    assert(monitor_cur() == NULL);
> > -    monitor_set_cur(qemu_coroutine_self(), data->cur_mon);
> > -    data->cmd->fn(data->args, data->ret, data->errp);
> > -    monitor_set_cur(qemu_coroutine_self(), NULL);
> > -    aio_co_wake(data->co);
> > -}
> > -
> > -/*
> > - * Runs outside of coroutine context for OOB commands, but in coroutine
> > - * context for everything else.
> > - */
> >  QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request,
> > -                    bool allow_oob, Monitor *cur_mon)
> > +                    bool allow_oob, QmpDispatchRun run_cb, void
> *run_data)
> >  {
> >      Error *err = NULL;
> >      bool oob;
> > @@ -203,39 +176,12 @@ QDict *qmp_dispatch(const QmpCommandList *cmds,
> QObject *request,
> >          qobject_ref(args);
> >      }
> >
> > -    assert(!(oob && qemu_in_coroutine()));
> > -    assert(monitor_cur() == NULL);
> > -    if (!!(cmd->options & QCO_COROUTINE) == qemu_in_coroutine()) {
> > -        monitor_set_cur(qemu_coroutine_self(), cur_mon);
> > -        cmd->fn(args, &ret, &err);
> > -        monitor_set_cur(qemu_coroutine_self(), NULL);
> > +    if (run_cb) {
> > +        run_cb(oob, cmd, args, &ret, &err, run_data);
> >      } else {
> > -       /*
> > -        * Actual context doesn't match the one the command needs.
> > -        *
> > -        * Case 1: we are in coroutine context, but command does not
> > -        * have QCO_COROUTINE.  We need to drop out of coroutine
> > -        * context for executing it.
> > -        *
> > -        * Case 2: we are outside coroutine context, but command has
> > -        * QCO_COROUTINE.  Can't actually happen, because we get here
> > -        * outside coroutine context only when executing a command
> > -        * out of band, and OOB commands never have QCO_COROUTINE.
> > -        */
> > -        assert(!oob && qemu_in_coroutine() && !(cmd->options &
> QCO_COROUTINE));
> > -
> > -        QmpDispatchBH data = {
> > -            .cur_mon    = cur_mon,
> > -            .cmd        = cmd,
> > -            .args       = args,
> > -            .ret        = &ret,
> > -            .errp       = &err,
> > -            .co         = qemu_coroutine_self(),
> > -        };
> > -        aio_bh_schedule_oneshot(qemu_get_aio_context(),
> do_qmp_dispatch_bh,
> > -                                &data);
> > -        qemu_coroutine_yield();
> > +        cmd->fn(args, &ret, &err);
> >      }
> > +
> >      qobject_unref(args);
> >      if (err) {
> >          /* or assert(!ret) after reviewing all handlers: */
>
> A callback works, but note that each program's function is fixed (the
> simple and common function is inlined, but that's just for convenience).
>
> We could use the linker instead.  We already do for
> qmp_command_available(), and the patch doesn't change that.
>

Tbh, using the linker override trick makes me a bit uncomfortable when
trying to make a "common" qemu library.

The "trick" is not well documented (I couldn't find a good reference for
the expected behaviour, and my experience with it isn't great when I
struggled with linking issues earlier). It also makes the library usage a
bit hidden. And it limits the full potential of the library to static
linking.

Callbacks are not always meant to be dynamically changeable.


> Perhaps a layering argument could be made for callbacks.  Before the
> series, monitor/qmp.c's monitor_qmp_dispatch() calls
> qapi/qmp-dispatch.c's qmp_dispatch(), which calls a few functions from
> monitor/.  However, consistency seems desirable.
>
> What do you think?
>

No strong opinion, as long as the qemu-common project is internal to qemu
projects. If we imagine the code can be made into a shared library, it will
need callbacks.


-- 
Marc-André Lureau

[-- Attachment #2: Type: text/html, Size: 14255 bytes --]

  reply	other threads:[~2022-08-02 11:21 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-12  9:35 [PATCH v2 00/15] Preliminary patches for subproject split marcandre.lureau
2022-07-12  9:35 ` [PATCH v2 01/15] error-report: misc comment fix marcandre.lureau
2022-07-12  9:35 ` [PATCH v2 02/15] error-report: introduce "detailed" variable marcandre.lureau
2022-07-12  9:35 ` [PATCH v2 03/15] error-report: simplify print_loc() marcandre.lureau
2022-07-12  9:35 ` [PATCH v2 04/15] error-report: introduce overridable error_is_detailed() marcandre.lureau
2022-07-12 15:02   ` Warner Losh
2022-07-19  7:24   ` Markus Armbruster
2022-07-12  9:35 ` [PATCH v2 05/15] stubs: remove needless error_vprintf_unless_qmp() marcandre.lureau
2022-07-19  7:24   ` Markus Armbruster
2022-07-12  9:35 ` [PATCH v2 06/15] qapi: move QEMU-specific dispatch code in monitor marcandre.lureau
2022-08-02 10:58   ` Markus Armbruster
2022-08-02 11:19     ` Marc-André Lureau [this message]
2022-08-02 12:21       ` Markus Armbruster
2022-07-12  9:35 ` [PATCH v2 07/15] scripts/qapi-gen: add -i option marcandre.lureau
2022-07-12  9:35 ` [PATCH v2 08/15] scripts/qapi: add required system includes to visitor marcandre.lureau
2022-07-12 15:08   ` Warner Losh
2022-07-12  9:35 ` [PATCH v2 09/15] util: move 256-by-128 division helpers to int128 marcandre.lureau
2022-08-04 16:17   ` Marc-André Lureau
2022-08-04 17:04   ` Lucas Mateus Martins Araujo e Castro
2022-07-12  9:35 ` [PATCH v2 10/15] qemu-common: introduce a common subproject marcandre.lureau
2022-07-12 14:57   ` Warner Losh
2022-07-15 11:55     ` Marc-André Lureau
2022-07-12  9:35 ` [PATCH v2 11/15] qemu-common: move scripts/qapi marcandre.lureau
2022-08-05  8:02   ` Markus Armbruster
2022-08-05  8:49     ` Marc-André Lureau
2022-08-11  6:52       ` Markus Armbruster
2022-08-11  7:11         ` Marc-André Lureau
2022-08-11  9:05           ` Markus Armbruster
2022-08-11 10:09             ` Marc-André Lureau
2022-08-11 10:22               ` Peter Maydell
2022-08-11 10:50                 ` Marc-André Lureau
2022-08-11 12:15                   ` Daniel P. Berrangé
2022-08-11 13:35                     ` Markus Armbruster
2022-08-22  8:16                       ` Marc-André Lureau
2022-09-02 11:15                         ` Markus Armbruster
2022-09-02 13:22                           ` Marc-André Lureau
2022-08-11 11:46                 ` Markus Armbruster
2022-07-12  9:35 ` [PATCH v2 12/15] qemu-common: move glib-compat.h marcandre.lureau
2022-07-12 15:00   ` Warner Losh
2022-07-12  9:35 ` [PATCH v2 13/15] qemu-common: move error-report marcandre.lureau
2022-07-12  9:35 ` [PATCH v2 14/15] mtest2make.py: teach suite name that are just "PROJECT" marcandre.lureau
2022-08-05 10:35   ` Paolo Bonzini
2022-08-05 11:22     ` Marc-André Lureau
2022-07-12  9:35 ` [PATCH v2 15/15] qemu-common: add error-report test marcandre.lureau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAJ+F1C+hqN0SpG6cLxGEi9xcpW+vha6NzZZDJXb1fEbn-UianA@mail.gmail.com \
    --to=marcandre.lureau@gmail.com \
    --cc=armbru@redhat.com \
    --cc=crosa@redhat.com \
    --cc=dgilbert@redhat.com \
    --cc=eblake@redhat.com \
    --cc=fam@euphon.net \
    --cc=hreitz@redhat.com \
    --cc=imp@bsdimp.com \
    --cc=jsnow@redhat.com \
    --cc=kevans@freebsd.org \
    --cc=kwolf@redhat.com \
    --cc=laurent@vivier.eu \
    --cc=michael.roth@amd.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=vsementsov@yandex-team.ru \
    --cc=xieyongji@bytedance.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.