All of lore.kernel.org
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: "Marc-André Lureau" <marcandre.lureau@redhat.com>
Cc: qemu-devel@nongnu.org, peterx@redhat.com,
	Michael Roth <mdroth@linux.vnet.ibm.com>
Subject: Re: [Qemu-devel] [PATCH 12/12] RFC: qmp: rework 'id' handling
Date: Tue, 17 Jul 2018 18:05:31 +0200	[thread overview]
Message-ID: <87a7qpc0fo.fsf@dusky.pond.sub.org> (raw)
In-Reply-To: <20180706121354.2021-13-marcandre.lureau@redhat.com> ("Marc-André Lureau"'s message of "Fri, 6 Jul 2018 14:13:54 +0200")

Copying the guest agent maintainer Michael Roth.

Patch needs a rebase.

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Let qmp_dispatch() copy the 'id' field. That way any qmp client will
> conform to the specification, including QGA.

Before this patch, users of the common core shared by QMP and QGA have
to do extra work to conform to qmp-spec.txt.  QMP does, QGA doesn't.
I'm inclined to consider that a bug.

Judging from your description, this patch moves that work into the
shared part.  The patch is therefore not just a rework of 'id' handling,
it's a QGA bug fix, if you're so inclined, else a QGA improvement.

Thus, 1. please rephrase the commit message accordingly, and 2. the
patch needs Michael's approval.

>                                              Furthermore, it
> simplifies the work for qemu monitor.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  monitor.c           | 31 ++++++++++++-------------------
>  qapi/qmp-dispatch.c | 10 ++++++++--
>  tests/test-qga.c    | 13 +++++--------
>  3 files changed, 25 insertions(+), 29 deletions(-)
>
> diff --git a/monitor.c b/monitor.c
> index a3efe96d1d..bf192697e4 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -249,8 +249,6 @@ QEMUBH *qmp_dispatcher_bh;
>  struct QMPRequest {
>      /* Owner of the request */
>      Monitor *mon;
> -    /* "id" field of the request */
> -    QObject *id;
>      /*
>       * Request object to be handled or Error to be reported
>       * (exactly one of them is non-null)
> @@ -351,7 +349,6 @@ int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
>  
>  static void qmp_request_free(QMPRequest *req)
>  {
> -    qobject_unref(req->id);
>      qobject_unref(req->req);
>      error_free(req->err);
>      g_free(req);
> @@ -3991,18 +3988,14 @@ static int monitor_can_read(void *opaque)
>   * Null @rsp can only happen for commands with QCO_NO_SUCCESS_RESP.
>   * Nothing is emitted then.
>   */
> -static void monitor_qmp_respond(Monitor *mon, QDict *rsp, QObject *id)
> +static void monitor_qmp_respond(Monitor *mon, QDict *rsp)
>  {
>      if (rsp) {
> -        if (id) {
> -            qdict_put_obj(rsp, "id", qobject_ref(id));
> -        }
> -
>          qmp_send_response(mon, rsp);
>      }
>  }
>  
> -static void monitor_qmp_dispatch(Monitor *mon, QObject *req, QObject *id)
> +static void monitor_qmp_dispatch(Monitor *mon, QObject *req)
>  {
>      Monitor *old_mon;
>      QDict *rsp;
> @@ -4027,7 +4020,7 @@ static void monitor_qmp_dispatch(Monitor *mon, QObject *req, QObject *id)
>          }
>      }
>  
> -    monitor_qmp_respond(mon, rsp, id);
> +    monitor_qmp_respond(mon, rsp);
>      qobject_unref(rsp);
>  }
>  
> @@ -4081,12 +4074,15 @@ static void monitor_qmp_bh_dispatcher(void *data)
>  
>      need_resume = !qmp_oob_enabled(req_obj->mon);
>      if (req_obj->req) {
> -        trace_monitor_qmp_cmd_in_band(qobject_get_try_str(req_obj->id) ?: "");
> -        monitor_qmp_dispatch(req_obj->mon, req_obj->req, req_obj->id);
> +        QDict *qdict = qobject_to(QDict, req_obj->req);
> +        QObject *id = qdict ? qdict_get(qdict, "id") : NULL;
> +        trace_monitor_qmp_cmd_in_band(qobject_get_try_str(id) ?: "");
> +        monitor_qmp_dispatch(req_obj->mon, req_obj->req);
>      } else {
>          assert(req_obj->err);
>          rsp = qmp_error_response(req_obj->err);
> -        monitor_qmp_respond(req_obj->mon, rsp, NULL);
> +        req_obj->err = NULL;
> +        monitor_qmp_respond(req_obj->mon, rsp);

Error response without ID before and after the patch.  Okay.

>          qobject_unref(rsp);
>      }
>  
> @@ -4115,8 +4111,7 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
>  
>      qdict = qobject_to(QDict, req);
>      if (qdict) {
> -        id = qobject_ref(qdict_get(qdict, "id"));
> -        qdict_del(qdict, "id");
> +        id = qdict_get(qdict, "id");
>      } /* else will fail qmp_dispatch() */

Two users of @id remain: trace_monitor_qmp_cmd_out_of_band(), visible
below, and qapi_event_send_command_dropped().  We currently plan to kill
the latter.  The former is guarded by if (qdict && qmp_is_oob(qdict)),
and could therefore safely use qdict_get(qdict, "id").  Together, this
will let us delete the whole conditional here.

>  
>      if (trace_event_get_state_backends(TRACE_HANDLE_QMP_COMMAND)) {
> @@ -4127,15 +4122,13 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
>  
>      if (qdict && qmp_is_oob(qdict)) {
>          /* OOB commands are executed immediately */
> -        trace_monitor_qmp_cmd_out_of_band(qobject_get_try_str(id)
> -                                          ?: "");
> -        monitor_qmp_dispatch(mon, req, id);
> +        trace_monitor_qmp_cmd_out_of_band(qobject_get_try_str(id) ?: "");
> +        monitor_qmp_dispatch(mon, req);
>          return;
>      }
>  
>      req_obj = g_new0(QMPRequest, 1);
>      req_obj->mon = mon;
> -    req_obj->id = id;
>      req_obj->req = req;
>      req_obj->err = err;
>  
> diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
> index 90ba5e3074..acea0fcfcd 100644
> --- a/qapi/qmp-dispatch.c
> +++ b/qapi/qmp-dispatch.c
> @@ -59,6 +59,8 @@ static QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oob,
>                             "QMP input member 'arguments' must be an object");
>                  return NULL;
>              }
> +        } else if (!strcmp(arg_name, "id")) {
> +            continue;
>          } else {
>              error_setg(errp, "QMP input member '%s' is unexpected",
>                         arg_name);
> @@ -166,8 +168,8 @@ QDict *qmp_dispatch(QmpCommandList *cmds, QObject *request,
>                      bool allow_oob)
>  {
>      Error *err = NULL;
> -    QObject *ret;
> -    QDict *rsp;
> +    QDict *rsp, *dict = qobject_to(QDict, request);
> +    QObject *ret, *id = dict ? qdict_get(dict, "id") : NULL;

I dislike mixing initialized and uninitialized variables in the same
declaration.

>  
>      ret = do_qmp_dispatch(cmds, request, allow_oob, &err);
>  
> @@ -181,5 +183,9 @@ QDict *qmp_dispatch(QmpCommandList *cmds, QObject *request,
>          rsp = NULL;
>      }
>  
> +    if (rsp && id) {
> +        qdict_put_obj(rsp, "id", qobject_ref(id));
> +    }
> +
>      return rsp;
>  }

This puts the ID (if any) into the response.  Good.

The monitor sends command responses only with monitor_qmp_respond().
It's called on two places:

* monitor_qmp_dispatch()

  Gets its response from qmp_dispatch(), which now puts the ID (if any).

* monitor_qmp_bh_dispatcher()

  Error response without ID before and after the patch (see above).

Good.

Not visible in the patch: QGA.  It sends command responses only with
send_response().  Called only in process_event().  Two cases:

* json_parser_parse_err() sets an error

  Error response without ID before and after the patch

* qmp_dispatch()

  Now puts the ID (if any).  This is the externally visible change.

Good.

> diff --git a/tests/test-qga.c b/tests/test-qga.c
> index d638b1571a..4ee8b405f4 100644
> --- a/tests/test-qga.c
> +++ b/tests/test-qga.c
> @@ -227,18 +227,15 @@ static void test_qga_ping(gconstpointer fix)
>      qobject_unref(ret);
>  }
>  
> -static void test_qga_invalid_id(gconstpointer fix)
> +static void test_qga_id(gconstpointer fix)
>  {
>      const TestFixture *fixture = fix;
> -    QDict *ret, *error;
> -    const char *class;
> +    QDict *ret;
>  
>      ret = qmp_fd(fixture->fd, "{'execute': 'guest-ping', 'id': 1}");
>      g_assert_nonnull(ret);
> -
> -    error = qdict_get_qdict(ret, "error");
> -    class = qdict_get_try_str(error, "class");
> -    g_assert_cmpstr(class, ==, "GenericError");
> +    qmp_assert_no_error(ret);
> +    g_assert_cmpint(qdict_get_int(ret, "id"), ==, 1);
>  
>      qobject_unref(ret);
>  }
> @@ -1014,7 +1011,7 @@ int main(int argc, char **argv)
>      g_test_add_data_func("/qga/file-ops", &fix, test_qga_file_ops);
>      g_test_add_data_func("/qga/file-write-read", &fix, test_qga_file_write_read);
>      g_test_add_data_func("/qga/get-time", &fix, test_qga_get_time);
> -    g_test_add_data_func("/qga/invalid-id", &fix, test_qga_invalid_id);
> +    g_test_add_data_func("/qga/id", &fix, test_qga_id);
>      g_test_add_data_func("/qga/invalid-oob", &fix, test_qga_invalid_oob);
>      g_test_add_data_func("/qga/invalid-cmd", &fix, test_qga_invalid_cmd);
>      g_test_add_data_func("/qga/invalid-args", &fix, test_qga_invalid_args);

  reply	other threads:[~2018-07-17 16:05 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-06 12:13 [Qemu-devel] [PATCH 00/12] RFC: monitor: various code simplification and fixes Marc-André Lureau
2018-07-06 12:13 ` [Qemu-devel] [PATCH 01/12] tests: change /0.15/* tests to /qmp/* Marc-André Lureau
2018-07-06 12:13 ` [Qemu-devel] [PATCH 02/12] monitor: consitify qmp_send_response() QDict argument Marc-André Lureau
2018-07-12 12:27   ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 03/12] qmp: constify qmp_is_oob() Marc-André Lureau
2018-07-12 12:27   ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 04/12] Revert "qmp: isolate responses into io thread" Marc-André Lureau
2018-07-12 13:14   ` Markus Armbruster
2018-07-12 13:32     ` Marc-André Lureau
2018-07-12 14:27       ` Peter Xu
2018-07-06 12:13 ` [Qemu-devel] [PATCH 05/12] monitor: no need to save need_resume Marc-André Lureau
2018-07-17  5:38   ` Markus Armbruster
2018-07-17  6:05     ` Peter Xu
2018-07-06 12:13 ` [Qemu-devel] [PATCH 06/12] qga: process_event() simplification and leak fix Marc-André Lureau
2018-07-17  5:53   ` Markus Armbruster
2018-07-17  9:27     ` Marc-André Lureau
2018-07-17 12:14       ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 07/12] json-parser: always set an error if return NULL Marc-André Lureau
2018-07-17  7:06   ` Markus Armbruster
2018-07-19 16:59     ` Marc-André Lureau
2018-07-20  6:03       ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 08/12] json-lexer: make it safe to call multiple times Marc-André Lureau
2018-07-17  7:22   ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 09/12] tests: add a few qemu-qmp tests Marc-André Lureau
2018-07-17  8:01   ` Markus Armbruster
2018-07-17  9:57     ` Marc-André Lureau
2018-07-17 13:15       ` Markus Armbruster
2018-07-19 17:20         ` Marc-André Lureau
2018-07-06 12:13 ` [Qemu-devel] [PATCH 10/12] tests: add a qmp success-response test Marc-André Lureau
2018-07-17 15:12   ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 11/12] qga: process_event() simplification Marc-André Lureau
2018-07-17 15:25   ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 12/12] RFC: qmp: rework 'id' handling Marc-André Lureau
2018-07-17 16:05   ` Markus Armbruster [this message]
2018-07-19 17:45     ` Marc-André 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=87a7qpc0fo.fsf@dusky.pond.sub.org \
    --to=armbru@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=peterx@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /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.