qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/2] Misc QGA/monitor QMP improvements (resend)
@ 2019-02-20 15:42 Marc-André Lureau
  2019-02-20 15:42 ` [Qemu-devel] [PATCH 1/2] qga: process_event() simplification Marc-André Lureau
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Marc-André Lureau @ 2019-02-20 15:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Michael Roth, Markus Armbruster,
	Marc-André Lureau

Hi,

I have those 2 simplification patches left which were part of previous
series. They are still worthwhile imho.

Thanks

Marc-André Lureau (2):
  qga: process_event() simplification
  qmp: common 'id' handling & make QGA conform to QMP spec

 monitor.c           | 33 ++++++++++++-------------------
 qapi/qmp-dispatch.c | 10 ++++++++--
 qga/main.c          | 47 +++++++++------------------------------------
 tests/test-qga.c    | 13 +++++--------
 4 files changed, 34 insertions(+), 69 deletions(-)

-- 
2.21.0.rc1

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH 1/2] qga: process_event() simplification
  2019-02-20 15:42 [Qemu-devel] [PATCH 0/2] Misc QGA/monitor QMP improvements (resend) Marc-André Lureau
@ 2019-02-20 15:42 ` Marc-André Lureau
  2019-02-20 16:21   ` Eric Blake
  2019-02-20 15:42 ` [Qemu-devel] [PATCH 2/2] qmp: common 'id' handling & make QGA conform to QMP spec Marc-André Lureau
  2019-02-27  7:09 ` [Qemu-devel] [PATCH 0/2] Misc QGA/monitor QMP improvements (resend) Markus Armbruster
  2 siblings, 1 reply; 5+ messages in thread
From: Marc-André Lureau @ 2019-02-20 15:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Michael Roth, Markus Armbruster,
	Marc-André Lureau

Simplify the code around qmp_dispatch():
- rely on qmp_dispatch/check_obj() for message checking
- have a single send_response() point
- constify send_response() argument

It changes a couple of error messages:

* When @req isn't a dictionary, from
    Invalid JSON syntax
  to
    QMP input must be a JSON object

* When @req lacks member "execute", from
    this feature or command is not currently supported
  to
    QMP input lacks member 'execute'

CC: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qga/main.c | 47 +++++++++--------------------------------------
 1 file changed, 9 insertions(+), 38 deletions(-)

diff --git a/qga/main.c b/qga/main.c
index 87a0711c14..c0d77c79c4 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -523,15 +523,15 @@ fail:
 #endif
 }
 
-static int send_response(GAState *s, QDict *payload)
+static int send_response(GAState *s, const QDict *rsp)
 {
     const char *buf;
     QString *payload_qstr, *response_qstr;
     GIOStatus status;
 
-    g_assert(payload && s->channel);
+    g_assert(rsp && s->channel);
 
-    payload_qstr = qobject_to_json(QOBJECT(payload));
+    payload_qstr = qobject_to_json(QOBJECT(rsp));
     if (!payload_qstr) {
         return -EINVAL;
     }
@@ -557,53 +557,24 @@ static int send_response(GAState *s, QDict *payload)
     return 0;
 }
 
-static void process_command(GAState *s, QDict *req)
-{
-    QDict *rsp;
-    int ret;
-
-    g_assert(req);
-    g_debug("processing command");
-    rsp = qmp_dispatch(&ga_commands, QOBJECT(req), false);
-    if (rsp) {
-        ret = send_response(s, rsp);
-        if (ret < 0) {
-            g_warning("error sending response: %s", strerror(-ret));
-        }
-        qobject_unref(rsp);
-    }
-}
-
 /* handle requests/control events coming in over the channel */
 static void process_event(void *opaque, QObject *obj, Error *err)
 {
     GAState *s = opaque;
-    QDict *req, *rsp;
+    QDict *rsp;
     int ret;
 
     g_debug("process_event: called");
     assert(!obj != !err);
     if (err) {
-        goto err;
-    }
-    req = qobject_to(QDict, obj);
-    if (!req) {
-        error_setg(&err, "Input must be a JSON object");
-        goto err;
-    }
-    if (!qdict_haskey(req, "execute")) {
-        g_warning("unrecognized payload format");
-        error_setg(&err, QERR_UNSUPPORTED);
-        goto err;
+        rsp = qmp_error_response(err);
+        goto end;
     }
 
-    process_command(s, req);
-    qobject_unref(obj);
-    return;
+    g_debug("processing command");
+    rsp = qmp_dispatch(&ga_commands, obj, false);
 
-err:
-    g_warning("failed to parse event: %s", error_get_pretty(err));
-    rsp = qmp_error_response(err);
+end:
     ret = send_response(s, rsp);
     if (ret < 0) {
         g_warning("error sending error response: %s", strerror(-ret));
-- 
2.21.0.rc1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH 2/2] qmp: common 'id' handling & make QGA conform to QMP spec
  2019-02-20 15:42 [Qemu-devel] [PATCH 0/2] Misc QGA/monitor QMP improvements (resend) Marc-André Lureau
  2019-02-20 15:42 ` [Qemu-devel] [PATCH 1/2] qga: process_event() simplification Marc-André Lureau
@ 2019-02-20 15:42 ` Marc-André Lureau
  2019-02-27  7:09 ` [Qemu-devel] [PATCH 0/2] Misc QGA/monitor QMP improvements (resend) Markus Armbruster
  2 siblings, 0 replies; 5+ messages in thread
From: Marc-André Lureau @ 2019-02-20 15:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Michael Roth, Markus Armbruster,
	Marc-André Lureau

Let qmp_dispatch() copy the 'id' field. That way any qmp client will
conform to the specification, including QGA. Furthermore, it
simplifies the work for qemu monitor.

CC: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
---
 monitor.c           | 33 ++++++++++++---------------------
 qapi/qmp-dispatch.c | 10 ++++++++--
 tests/test-qga.c    | 13 +++++--------
 3 files changed, 25 insertions(+), 31 deletions(-)

diff --git a/monitor.c b/monitor.c
index 33ccbf3957..c0bc089645 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)
@@ -352,7 +350,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);
@@ -4026,18 +4023,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;
@@ -4062,7 +4055,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);
 }
 
@@ -4126,13 +4119,15 @@ static void monitor_qmp_bh_dispatcher(void *data)
         mon->qmp.qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1;
     qemu_mutex_unlock(&mon->qmp.qmp_queue_lock);
     if (req_obj->req) {
-        trace_monitor_qmp_cmd_in_band(qobject_get_try_str(req_obj->id) ?: "");
-        monitor_qmp_dispatch(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(mon, req_obj->req);
     } else {
         assert(req_obj->err);
         rsp = qmp_error_response(req_obj->err);
         req_obj->err = NULL;
-        monitor_qmp_respond(mon, rsp, NULL);
+        monitor_qmp_respond(mon, rsp);
         qobject_unref(rsp);
     }
 
@@ -4157,8 +4152,7 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err)
 
     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() */
 
     if (req && trace_event_get_state_backends(TRACE_HANDLE_QMP_COMMAND)) {
@@ -4169,17 +4163,14 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err)
 
     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);
         qobject_unref(req);
-        qobject_unref(id);
         return;
     }
 
     req_obj = g_new0(QMPRequest, 1);
     req_obj->mon = mon;
-    req_obj->id = id;
     req_obj->req = req;
     req_obj->err = err;
 
@@ -4199,7 +4190,7 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err)
 
     /*
      * Put the request to the end of queue so that requests will be
-     * handled in time order.  Ownership for req_obj, req, id,
+     * handled in time order.  Ownership for req_obj, req,
      * etc. will be delivered to the handler side.
      */
     assert(mon->qmp.qmp_requests->length < QMP_REQ_QUEUE_LEN_MAX);
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 1d922e04f7..5f812bb9f2 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -58,6 +58,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);
@@ -165,11 +167,11 @@ QDict *qmp_dispatch(QmpCommandList *cmds, QObject *request,
                     bool allow_oob)
 {
     Error *err = NULL;
-    QObject *ret;
+    QDict *dict = qobject_to(QDict, request);
+    QObject *ret, *id = dict ? qdict_get(dict, "id") : NULL;
     QDict *rsp;
 
     ret = do_qmp_dispatch(cmds, request, allow_oob, &err);
-
     if (err) {
         rsp = qmp_error_response(err);
     } else if (ret) {
@@ -180,5 +182,9 @@ QDict *qmp_dispatch(QmpCommandList *cmds, QObject *request,
         rsp = NULL;
     }
 
+    if (rsp && id) {
+        qdict_put_obj(rsp, "id", qobject_ref(id));
+    }
+
     return rsp;
 }
diff --git a/tests/test-qga.c b/tests/test-qga.c
index 3d6377436a..891aa3d322 100644
--- a/tests/test-qga.c
+++ b/tests/test-qga.c
@@ -225,18 +225,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);
 }
@@ -992,7 +989,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);
-- 
2.21.0.rc1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH 1/2] qga: process_event() simplification
  2019-02-20 15:42 ` [Qemu-devel] [PATCH 1/2] qga: process_event() simplification Marc-André Lureau
@ 2019-02-20 16:21   ` Eric Blake
  0 siblings, 0 replies; 5+ messages in thread
From: Eric Blake @ 2019-02-20 16:21 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel
  Cc: Markus Armbruster, Dr. David Alan Gilbert, Michael Roth

On 2/20/19 9:42 AM, Marc-André Lureau wrote:
> Simplify the code around qmp_dispatch():
> - rely on qmp_dispatch/check_obj() for message checking
> - have a single send_response() point
> - constify send_response() argument
> 
> It changes a couple of error messages:
> 
> * When @req isn't a dictionary, from
>     Invalid JSON syntax
>   to
>     QMP input must be a JSON object
> 
> * When @req lacks member "execute", from
>     this feature or command is not currently supported
>   to
>     QMP input lacks member 'execute'
> 
> CC: Michael Roth <mdroth@linux.vnet.ibm.com>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  qga/main.c | 47 +++++++++--------------------------------------
>  1 file changed, 9 insertions(+), 38 deletions(-)

Nice simplification.

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH 0/2] Misc QGA/monitor QMP improvements (resend)
  2019-02-20 15:42 [Qemu-devel] [PATCH 0/2] Misc QGA/monitor QMP improvements (resend) Marc-André Lureau
  2019-02-20 15:42 ` [Qemu-devel] [PATCH 1/2] qga: process_event() simplification Marc-André Lureau
  2019-02-20 15:42 ` [Qemu-devel] [PATCH 2/2] qmp: common 'id' handling & make QGA conform to QMP spec Marc-André Lureau
@ 2019-02-27  7:09 ` Markus Armbruster
  2 siblings, 0 replies; 5+ messages in thread
From: Markus Armbruster @ 2019-02-27  7:09 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: qemu-devel, Dr. David Alan Gilbert, Michael Roth

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

> Hi,
>
> I have those 2 simplification patches left which were part of previous
> series. They are still worthwhile imho.

They are.

> Thanks
>
> Marc-André Lureau (2):
>   qga: process_event() simplification
>   qmp: common 'id' handling & make QGA conform to QMP spec

PATCH 1 is qga only.  PATCH 2 simplifies the common monitor core, but
observable change is again qga only.  Mike, care to take these patches
through your tree?

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-02-27  7:09 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-02-20 15:42 [Qemu-devel] [PATCH 0/2] Misc QGA/monitor QMP improvements (resend) Marc-André Lureau
2019-02-20 15:42 ` [Qemu-devel] [PATCH 1/2] qga: process_event() simplification Marc-André Lureau
2019-02-20 16:21   ` Eric Blake
2019-02-20 15:42 ` [Qemu-devel] [PATCH 2/2] qmp: common 'id' handling & make QGA conform to QMP spec Marc-André Lureau
2019-02-27  7:09 ` [Qemu-devel] [PATCH 0/2] Misc QGA/monitor QMP improvements (resend) Markus Armbruster

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).