All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_*
@ 2018-07-27 14:05 Anthony PERARD
  2018-07-27 14:05 ` [PATCH v4 01/32] libxl_event: Fix DEBUG prints Anthony PERARD
                   ` (31 more replies)
  0 siblings, 32 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

In order for libxl to be able to manage QEMU while it is restricted, a few
changes are needed. We need a new way to get a startup notification from QEMU
as xenstore may not be accessible when QEMU is ready. We also need to a
different way to have QEMU save it's state and to insert cdrom as a restricted
QEMU doesn't have access to the file system.

For both, we can use QMP, we can use it to query QEMU's status, and we can use
it to send a file descriptor through which QEMU can save its state, or it can
be a cdrom.

We take this opportunity to rewrite the QMP client, and this time been
asynchronous, the result is libxl__ev_qmp_*.

The plat de résistance in this patch series start with patch
"libxl: Design of an async API to issue QMP commands to QEMU"
which implement libxl__ev_qmp_* functions to turn the QMP client into
asynchronous mode.

This comes with changes that uses the new interface.
* "libxl: QEMU startup sync based on QMP"
  which can use QMP to find out when QEMU as started.
  this requires: "libxl_dm: Pre-open QMP socket for QEMU"
  But that only works with dm_restrict=1 as explain in the patch.
* "libxl: Re-implement domain_suspend_device_model using libxl__ev_qmp"
  Which rewrite libxl__qmp_save(), and adds the ability to have QEMU save
  its state to a file descriptor which libxl will have openned.
* "libxl_disk: Have libxl_cdrom_insert use libxl__ev_qmp"
  Which rewrites libxl__qmp_insert_cdrom() and adds the ability for libxl
  to open the cdrom on behalf of QEMU.

The first few patches do some cleanup and fixes of the current qmp client
implementation, mostly because it bothered me as I think we should remove the
current implementation. They could be commited ahead of libxl__ev_qmp.

Changes in v4:
    Better API which meant a lot of other changes.

Patches series available in a git tag:
git fetch https://xenbits.xen.org/git-http/people/aperard/xen-unstable.git libxl-migration-fdset-v4
git checkout -b libxl-migration-fdset-v4 FETCH_HEAD

Cheers,

Anthony PERARD (32):
  libxl_event: Fix DEBUG prints
  libxl_qmp: Documentation of the logic of the QMP client
  libxl_qmp: Fix use of DEBUG_RECEIVED
  libxl_json: fix build with DEBUG_ANSWER
  libxl_qmp: Move the buffer realloc to the same scope level as read
  libxl_qmp: Add a warning to not trust QEMU
  libxl_qmp: Move struct sockaddr_un variable to qmp_open()
  libxl: Add libxl__prepare_sockaddr_un() helper
  libxl_qmp: Remove unused yajl_ctx from handler
  libxl_json: constify libxl__json_object_to_yajl_gen arguments
  libxl_dm: Add libxl__qemu_qmp_path()
  libxl: Design of an async API to issue QMP commands to QEMU
  libxl_qmp: Connect to QMP socket
  libxl_qmp: Implement fd callback and read data
  libxl_json: Enable yajl_allow_trailing_garbage
  libxl_json: libxl__json_object_to_json
  libxl_qmp: Parse JSON input from QMP
  libxl_qmp: Separate QMP message generation from qmp_send_prepare
  libxl_qmp: Prepare the command to be sent
  libxl_qmp: Handle write to QMP socket
  libxl_qmp: Simplify qmp_response_type() prototype
  libxl_qmp: Handle messages from QEMU
  libxl_qmp: Respond to QMP greeting
  libxl_qmp: Disable beautify for QMP generated cmd
  libxl_exec: Add libxl__spawn_initiate_failure
  libxl_dm: Pre-open QMP socket for QEMU
  libxl: QEMU startup sync based on QMP
  libxl_qmp: Store advertised QEMU version in libxl__ev_qmp
  libxl: Change libxl__domain_suspend_device_model() to be async.
  libxl: Re-implement domain_suspend_device_model using libxl__ev_qmp
  libxl_disk: Cut libxl_cdrom_insert into step
  libxl_disk: Have libxl_cdrom_insert use libxl__ev_qmp

 tools/libxl/libxl_create.c           |  30 +-
 tools/libxl/libxl_disk.c             | 214 +++++--
 tools/libxl/libxl_dm.c               | 143 ++++-
 tools/libxl/libxl_dom_suspend.c      |  22 +-
 tools/libxl/libxl_event.c            |   8 +-
 tools/libxl/libxl_exec.c             |   7 +
 tools/libxl/libxl_internal.h         | 166 ++++-
 tools/libxl/libxl_json.c             |  42 +-
 tools/libxl/libxl_json.h             |   5 +-
 tools/libxl/libxl_qmp.c              | 922 ++++++++++++++++++++++++---
 tools/libxl/libxl_types.idl          |   4 +
 tools/libxl/libxl_types_internal.idl |   8 +
 tools/libxl/libxl_utils.c            |  14 +
 13 files changed, 1385 insertions(+), 200 deletions(-)

-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 01/32] libxl_event: Fix DEBUG prints
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-07-27 14:05 ` [PATCH v4 02/32] libxl_qmp: Documentation of the logic of the QMP client Anthony PERARD
                   ` (30 subsequent siblings)
  31 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

The libxl__log() call was missing the domid.

The macro DBG is using LIBXL__LOG which rely on a "gc". Add a GC where
needed.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
---

Notes:
    v3:
    - Add a commit message.
    
    New in RFC v2

 tools/libxl/libxl_event.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/tools/libxl/libxl_event.c b/tools/libxl/libxl_event.c
index 484f9bab4d..0370b6acdd 100644
--- a/tools/libxl/libxl_event.c
+++ b/tools/libxl/libxl_event.c
@@ -248,6 +248,7 @@ void libxl__ev_fd_deregister(libxl__gc *gc, libxl__ev_fd *ev)
 short libxl__fd_poll_recheck(libxl__egc *egc, int fd, short events) {
     struct pollfd check;
     int r;
+    EGC_GC;
 
     for (;;) {
         check.fd = fd;
@@ -336,7 +337,7 @@ static void time_done_debug(libxl__gc *gc, const char *func,
                             libxl__ev_time *ev, int rc)
 {
 #ifdef DEBUG
-    libxl__log(CTX, XTL_DEBUG, -1,__FILE__,0,func,
+    libxl__log(CTX, XTL_DEBUG, -1, __FILE__, 0, func, INVALID_DOMID,
                "ev_time=%p done rc=%d .func=%p infinite=%d abs=%lu.%06lu",
                ev, rc, ev->func, ev->infinite,
                (unsigned long)ev->abs.tv_sec, (unsigned long)ev->abs.tv_usec);
@@ -445,6 +446,8 @@ void libxl__ev_time_deregister(libxl__gc *gc, libxl__ev_time *ev)
 
 static void time_occurs(libxl__egc *egc, libxl__ev_time *etime, int rc)
 {
+    EGC_GC;
+
     DBG("ev_time=%p occurs abs=%lu.%06lu",
         etime, (unsigned long)etime->abs.tv_sec,
         (unsigned long)etime->abs.tv_usec);
@@ -1192,6 +1195,7 @@ static int afterpoll_check_fd(libxl__poller *poller,
 static void fd_occurs(libxl__egc *egc, libxl__ev_fd *efd, short revents_ign)
 {
     short revents_current = libxl__fd_poll_recheck(egc, efd->fd, efd->events);
+    EGC_GC;
 
     DBG("ev_fd=%p occurs fd=%d events=%x revents_ign=%x revents_current=%x",
         efd, efd->fd, efd->events, revents_ign, revents_current);
@@ -2117,6 +2121,8 @@ int libxl_ao_abort(libxl_ctx *ctx, const libxl_asyncop_how *how)
 int libxl__ao_aborting(libxl__ao *ao)
 {
     libxl__ao *root = ao_nested_root(ao);
+    AO_GC;
+
     if (root->aborting) {
         DBG("ao=%p: aborting at explicit check (root=%p)", ao, root);
         return ERROR_ABORTED;
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 02/32] libxl_qmp: Documentation of the logic of the QMP client
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
  2018-07-27 14:05 ` [PATCH v4 01/32] libxl_event: Fix DEBUG prints Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-07-27 14:05 ` [PATCH v4 03/32] libxl_qmp: Fix use of DEBUG_RECEIVED Anthony PERARD
                   ` (29 subsequent siblings)
  31 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
---

Notes:
    v3:
    - Add documentation of the qmp_callback_t type.
    
    New in RFC v2

 tools/libxl/libxl_qmp.c | 42 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 0fe42813bf..4555d6ae36 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -18,6 +18,42 @@
  * Specification, see in the QEMU repository.
  */
 
+/*
+ * Logic used to send command to QEMU
+ *
+ * qmp_open():
+ *  Will open a socket and connect to QEMU.
+ *
+ * qmp_next():
+ *  Will read data sent by QEMU and then call qmp_handle_response() once a
+ *  complete QMP message is received.
+ *  The function return on timeout/error or once every data received as been
+ *  processed.
+ *
+ * qmp_handle_response()
+ *  This process json messages received from QEMU and update different list and
+ *  may call callback function.
+ *  `libxl__qmp_handler.wait_for_id` is reset once a message with this ID is
+ *    processed.
+ *  `libxl__qmp_handler.callback_list`: list with ID of command sent and
+ *    optional assotiated callback function. The return value of a callback is
+ *    set in context.
+ *
+ * qmp_send():
+ *  Simply prepare a QMP command and send it to QEMU.
+ *  It also add a `struct callback_id_pair` on the
+ *  `libxl__qmp_handler.callback_list` via qmp_send_prepare().
+ *
+ * qmp_synchronous_send():
+ *  This function calls qmp_send(), then wait for QEMU to reply to the command.
+ *  The wait is done by calling qmp_next() over and over again until either
+ *  there is a response for the command or there is an error.
+ *
+ *  An ID can be set for each QMP command, this is set into
+ *  `libxl__qmp_handler.wait_for_id`. qmp_next will check every response's ID
+ *  again this field and change the value of the field once the ID is found.
+ */
+
 #include "libxl_osdeps.h" /* must come before any other headers */
 
 #include <sys/un.h>
@@ -43,6 +79,12 @@
 #define QMP_RECEIVE_BUFFER_SIZE 4096
 #define PCI_PT_QDEV_ID "pci-pt-%02x_%02x.%01x"
 
+/*
+ * qmp_callback_t is call whenever a message from QMP contain the "id"
+ * associated with the callback.
+ * "tree" contain the JSON tree that is in "return" of a QMP message. If QMP
+ * sent an error message, "tree" will be NULL.
+ */
 typedef int (*qmp_callback_t)(libxl__qmp_handler *qmp,
                               const libxl__json_object *tree,
                               void *opaque);
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 03/32] libxl_qmp: Fix use of DEBUG_RECEIVED
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
  2018-07-27 14:05 ` [PATCH v4 01/32] libxl_event: Fix DEBUG prints Anthony PERARD
  2018-07-27 14:05 ` [PATCH v4 02/32] libxl_qmp: Documentation of the logic of the QMP client Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-07-27 14:05 ` [PATCH v4 04/32] libxl_json: fix build with DEBUG_ANSWER Anthony PERARD
                   ` (28 subsequent siblings)
  31 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

This patch fix complilation error with #define DEBUG_RECEIVED of the
macro DEBUG_REPORT_RECEIVED.

  error: field precision specifier ‘.*’ expects argument of type ‘int’, but argument 9 has type ‘ssize_t {aka long int}’

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
---

Notes:
    New in RFC v2

 tools/libxl/libxl_qmp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 4555d6ae36..27227802e4 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -528,7 +528,7 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp)
         }
         qmp->buffer[rd] = '\0';
 
-        DEBUG_REPORT_RECEIVED(qmp->domid, qmp->buffer, rd);
+        DEBUG_REPORT_RECEIVED(qmp->domid, qmp->buffer, (int)rd);
 
         do {
             char *end = NULL;
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 04/32] libxl_json: fix build with DEBUG_ANSWER
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (2 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 03/32] libxl_qmp: Fix use of DEBUG_RECEIVED Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-07-27 14:05 ` [PATCH v4 05/32] libxl_qmp: Move the buffer realloc to the same scope level as read Anthony PERARD
                   ` (27 subsequent siblings)
  31 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

Also replace LIBXL__LOG_DEBUG by XTL_DEBUG, because it's shorter and
more often used in libxl.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
---

Notes:
    v4:
        explain s/LIBXL__LOG_DEBUG/XTL_DEBUG/.
        acked

 tools/libxl/libxl_json.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c
index 0823b8cfd2..dc93a88ef1 100644
--- a/tools/libxl/libxl_json.c
+++ b/tools/libxl/libxl_json.c
@@ -59,8 +59,8 @@ struct libxl__yajl_ctx {
         const unsigned char *buf = NULL; \
         size_t len = 0; \
         yajl_gen_get_buf((yajl_ctx)->g, &buf, &len); \
-        LIBXL__LOG(libxl__gc_owner((yajl_ctx)->gc), LIBXL__LOG_DEBUG,
-		   "response:\n", buf); \
+        LIBXL__LOG(libxl__gc_owner((yajl_ctx)->gc), XTL_DEBUG, \
+		   "response: %s\n", buf); \
         yajl_gen_free((yajl_ctx)->g); \
         (yajl_ctx)->g = NULL; \
     } while (0)
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 05/32] libxl_qmp: Move the buffer realloc to the same scope level as read
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (3 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 04/32] libxl_json: fix build with DEBUG_ANSWER Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-07-27 14:05 ` [PATCH v4 06/32] libxl_qmp: Add a warning to not trust QEMU Anthony PERARD
                   ` (26 subsequent siblings)
  31 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

In qmp_next(), the inner loop should only try to parse messages from
QMP, if there is more than one.

The handling of the receive buffer ('incomplete'), should be done at the
same scope level as read(). It doesn't need to be handle more that once
after a read.

Before this patch, when on message what handled, the inner loop would
restart by adding the 'buffer' into 'incomplete' (after reallocation).
Since 'rd' was not reset, the buffer would be strcat a second time.
After that, the stream from the QMP server would have syntax error, and
the parsor would throw errors.

This is unlikely to happen as the receive buffer is very large. And
receiving two messages in a row is unlikely. In the current case, this
could be an event and a response to a command.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
---

Notes:
    New in RFC v2

 tools/libxl/libxl_qmp.c | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 27227802e4..5b608f47e5 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -530,23 +530,24 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp)
 
         DEBUG_REPORT_RECEIVED(qmp->domid, qmp->buffer, (int)rd);
 
+        if (incomplete) {
+            size_t current_pos = s - incomplete;
+            incomplete = libxl__realloc(gc, incomplete,
+                                        incomplete_size + rd + 1);
+            strncat(incomplete + incomplete_size, qmp->buffer, rd);
+            s = incomplete + current_pos;
+            incomplete_size += rd;
+            s_end = incomplete + incomplete_size;
+        } else {
+            incomplete = libxl__strndup(gc, qmp->buffer, rd);
+            incomplete_size = rd;
+            s = incomplete;
+            s_end = s + rd;
+            rd = 0;
+        }
+
         do {
             char *end = NULL;
-            if (incomplete) {
-                size_t current_pos = s - incomplete;
-                incomplete = libxl__realloc(gc, incomplete,
-                                            incomplete_size + rd + 1);
-                strncat(incomplete + incomplete_size, qmp->buffer, rd);
-                s = incomplete + current_pos;
-                incomplete_size += rd;
-                s_end = incomplete + incomplete_size;
-            } else {
-                incomplete = libxl__strndup(gc, qmp->buffer, rd);
-                incomplete_size = rd;
-                s = incomplete;
-                s_end = s + rd;
-                rd = 0;
-            }
 
             end = strstr(s, "\r\n");
             if (end) {
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 06/32] libxl_qmp: Add a warning to not trust QEMU
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (4 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 05/32] libxl_qmp: Move the buffer realloc to the same scope level as read Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-07-27 14:05 ` [PATCH v4 07/32] libxl_qmp: Move struct sockaddr_un variable to qmp_open() Anthony PERARD
                   ` (25 subsequent siblings)
  31 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

... even if it is not the case for the current code.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
---
 tools/libxl/libxl_qmp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 5b608f47e5..987bf0232e 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -16,6 +16,9 @@
 /*
  * This file implement a client for QMP (QEMU Monitor Protocol). For the
  * Specification, see in the QEMU repository.
+ *
+ * WARNING - Do not trust QEMU when writing codes for new commands or when
+ *           improving the client code.
  */
 
 /*
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 07/32] libxl_qmp: Move struct sockaddr_un variable to qmp_open()
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (5 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 06/32] libxl_qmp: Add a warning to not trust QEMU Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-08-02  8:26   ` Roger Pau Monné
  2018-08-20 14:52   ` Wei Liu
  2018-07-27 14:05 ` [PATCH v4 08/32] libxl: Add libxl__prepare_sockaddr_un() helper Anthony PERARD
                   ` (24 subsequent siblings)
  31 siblings, 2 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

This variable is only used once, no need to keep it in the handler.

Also fix coding style (remove space after sizeof).
And allow strncpy to use all the space in sun_path.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---

Notes:
    v4:
        actually allow strncpy to use all the space in sun_path.

 tools/libxl/libxl_qmp.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 987bf0232e..1ffa17b632 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -105,7 +105,6 @@ typedef struct callback_id_pair {
 } callback_id_pair;
 
 struct libxl__qmp_handler {
-    struct sockaddr_un addr;
     int qmp_fd;
     bool connected;
     time_t timeout;
@@ -431,6 +430,7 @@ static int qmp_open(libxl__qmp_handler *qmp, const char *qmp_socket_path,
 {
     int ret = -1;
     int i = 0;
+    struct sockaddr_un addr;
 
     qmp->qmp_fd = socket(AF_UNIX, SOCK_STREAM, 0);
     if (qmp->qmp_fd < 0) {
@@ -447,18 +447,16 @@ static int qmp_open(libxl__qmp_handler *qmp, const char *qmp_socket_path,
         goto out;
     }
 
-    if (sizeof (qmp->addr.sun_path) <= strlen(qmp_socket_path)) {
+    if (sizeof(addr.sun_path) <= strlen(qmp_socket_path)) {
         ret = -1;
         goto out;
     }
-    memset(&qmp->addr, 0, sizeof (qmp->addr));
-    qmp->addr.sun_family = AF_UNIX;
-    strncpy(qmp->addr.sun_path, qmp_socket_path,
-            sizeof (qmp->addr.sun_path)-1);
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    strncpy(addr.sun_path, qmp_socket_path, sizeof(addr.sun_path));
 
     do {
-        ret = connect(qmp->qmp_fd, (struct sockaddr *) &qmp->addr,
-                      sizeof (qmp->addr));
+        ret = connect(qmp->qmp_fd, (struct sockaddr *) &addr, sizeof(addr));
         if (ret == 0)
             break;
         if (errno == ENOENT || errno == ECONNREFUSED) {
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 08/32] libxl: Add libxl__prepare_sockaddr_un() helper
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (6 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 07/32] libxl_qmp: Move struct sockaddr_un variable to qmp_open() Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-08-02  8:36   ` Roger Pau Monné
  2018-08-20 14:56   ` Wei Liu
  2018-07-27 14:05 ` [PATCH v4 09/32] libxl_qmp: Remove unused yajl_ctx from handler Anthony PERARD
                   ` (23 subsequent siblings)
  31 siblings, 2 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

There is going to be a few more users that want to use UNIX socket, this
helper is to prepare the `struct sockaddr_un` and check that the path
isn't too long.

Also start to use it in libxl_qmp.c.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---

Notes:
    New in v4.

 tools/libxl/libxl_internal.h |  4 ++++
 tools/libxl/libxl_qmp.c      | 10 ++++------
 tools/libxl/libxl_utils.c    | 14 ++++++++++++++
 3 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 843c625142..ab1de80522 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -47,6 +47,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <sys/file.h>
 #include <sys/ioctl.h>
 
@@ -4420,6 +4421,9 @@ static inline bool libxl__string_is_default(char **s)
 {
     return *s == NULL;
 }
+
+_hidden int libxl__prepare_sockaddr_un(libxl__gc *gc, struct sockaddr_un *un,
+                                       const char *path, const char *what);
 #endif
 
 /*
diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 1ffa17b632..7965ee37b9 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -428,6 +428,7 @@ static libxl__qmp_handler *qmp_init_handler(libxl__gc *gc, uint32_t domid)
 static int qmp_open(libxl__qmp_handler *qmp, const char *qmp_socket_path,
                     int timeout)
 {
+    GC_INIT(qmp->ctx);
     int ret = -1;
     int i = 0;
     struct sockaddr_un addr;
@@ -447,13 +448,9 @@ static int qmp_open(libxl__qmp_handler *qmp, const char *qmp_socket_path,
         goto out;
     }
 
-    if (sizeof(addr.sun_path) <= strlen(qmp_socket_path)) {
-        ret = -1;
+    ret = libxl__prepare_sockaddr_un(gc, &addr, qmp_socket_path, "QMP socket");
+    if (ret)
         goto out;
-    }
-    memset(&addr, 0, sizeof(addr));
-    addr.sun_family = AF_UNIX;
-    strncpy(addr.sun_path, qmp_socket_path, sizeof(addr.sun_path));
 
     do {
         ret = connect(qmp->qmp_fd, (struct sockaddr *) &addr, sizeof(addr));
@@ -471,6 +468,7 @@ static int qmp_open(libxl__qmp_handler *qmp, const char *qmp_socket_path,
 out:
     if (ret == -1 && qmp->qmp_fd > -1) close(qmp->qmp_fd);
 
+    GC_FREE;
     return ret;
 }
 
diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
index 507ee56c7c..7907e20672 100644
--- a/tools/libxl/libxl_utils.c
+++ b/tools/libxl/libxl_utils.c
@@ -1234,6 +1234,20 @@ int libxl__random_bytes(libxl__gc *gc, uint8_t *buf, size_t len)
     return ret;
 }
 
+int libxl__prepare_sockaddr_un(libxl__gc *gc,
+                               struct sockaddr_un *un, const char *path,
+                               const char *what) {
+    if (sizeof(un->sun_path) <= strlen(path)) {
+        LOG(ERROR, "UNIX socket path '%s' is too long for %s", path, what);
+        LOG(DEBUG, "Path must be less than %zu bytes", sizeof(un->sun_path));
+        return ERROR_INVAL;
+    }
+    memset(un, 0, sizeof(struct sockaddr_un));
+    un->sun_family = AF_UNIX;
+    strncpy(un->sun_path, path, sizeof(un->sun_path));
+    return 0;
+}
+
 /*
  * Local variables:
  * mode: C
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 09/32] libxl_qmp: Remove unused yajl_ctx from handler
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (7 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 08/32] libxl: Add libxl__prepare_sockaddr_un() helper Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-08-20 14:56   ` Wei Liu
  2018-07-27 14:05 ` [PATCH v4 10/32] libxl_json: constify libxl__json_object_to_yajl_gen arguments Anthony PERARD
                   ` (22 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
---

Notes:
    v4:
    - Acked
    - Fix subject s/form/from/

 tools/libxl/libxl_qmp.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 7965ee37b9..c5e05e5679 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -112,7 +112,6 @@ struct libxl__qmp_handler {
     int wait_for_id;
 
     char buffer[QMP_RECEIVE_BUFFER_SIZE + 1];
-    libxl__yajl_ctx *yajl_ctx;
 
     libxl_ctx *ctx;
     uint32_t domid;
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 10/32] libxl_json: constify libxl__json_object_to_yajl_gen arguments
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (8 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 09/32] libxl_qmp: Remove unused yajl_ctx from handler Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-07-27 14:05 ` [PATCH v4 11/32] libxl_dm: Add libxl__qemu_qmp_path() Anthony PERARD
                   ` (21 subsequent siblings)
  31 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
---
 tools/libxl/libxl_internal.h | 2 +-
 tools/libxl/libxl_json.c     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index ab1de80522..72ab177ce5 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2031,7 +2031,7 @@ _hidden const libxl__json_object *libxl__json_map_get(const char *key,
                                           libxl__json_node_type expected_type);
 _hidden yajl_status libxl__json_object_to_yajl_gen(libxl__gc *gc_opt,
                                                    yajl_gen hand,
-                                                   libxl__json_object *param);
+                                                   const libxl__json_object *param);
 _hidden void libxl__json_object_free(libxl__gc *gc_opt,
                                      libxl__json_object *obj);
 
diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c
index dc93a88ef1..b7f9077f0d 100644
--- a/tools/libxl/libxl_json.c
+++ b/tools/libxl/libxl_json.c
@@ -612,7 +612,7 @@ const libxl__json_object *libxl__json_map_get(const char *key,
 
 yajl_status libxl__json_object_to_yajl_gen(libxl__gc *gc,
                                            yajl_gen hand,
-                                           libxl__json_object *obj)
+                                           const libxl__json_object *obj)
 {
     int idx = 0;
     yajl_status rc;
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 11/32] libxl_dm: Add libxl__qemu_qmp_path()
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (9 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 10/32] libxl_json: constify libxl__json_object_to_yajl_gen arguments Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-08-02  8:41   ` Roger Pau Monné
  2018-08-20 14:57   ` Wei Liu
  2018-07-27 14:05 ` [PATCH v4 12/32] libxl: Design of an async API to issue QMP commands to QEMU Anthony PERARD
                   ` (20 subsequent siblings)
  31 siblings, 2 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

... which generate the path to a QMP socket that libxl uses.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---

Notes:
    New in v4.

 tools/libxl/libxl_dm.c       | 9 +++++++--
 tools/libxl/libxl_internal.h | 1 +
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index fdd7fa3ba4..5c28a0ced4 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -910,6 +910,11 @@ static char *qemu_disk_ide_drive_string(libxl__gc *gc, const char *target_path,
     return drive;
 }
 
+const char *libxl__qemu_qmp_path(libxl__gc *gc, int domid)
+{
+    return GCSPRINTF("%s/qmp-libxl-%d", libxl__run_dir_path(), domid);
+}
+
 static int libxl__build_device_model_args_new(libxl__gc *gc,
                                         const char *dm, int guest_domid,
                                         const libxl_domain_config *guest_config,
@@ -946,8 +951,8 @@ static int libxl__build_device_model_args_new(libxl__gc *gc,
     flexarray_append(dm_args, "-chardev");
     flexarray_append(dm_args,
                      GCSPRINTF("socket,id=libxl-cmd,"
-                                    "path=%s/qmp-libxl-%d,server,nowait",
-                                    libxl__run_dir_path(), guest_domid));
+                               "path=%s,server,nowait",
+                               libxl__qemu_qmp_path(gc, guest_domid)));
 
     flexarray_append(dm_args, "-no-shutdown");
     flexarray_append(dm_args, "-mon");
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 72ab177ce5..5b71a23d23 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -4424,6 +4424,7 @@ static inline bool libxl__string_is_default(char **s)
 
 _hidden int libxl__prepare_sockaddr_un(libxl__gc *gc, struct sockaddr_un *un,
                                        const char *path, const char *what);
+_hidden const char *libxl__qemu_qmp_path(libxl__gc *gc, int guest_domid);
 #endif
 
 /*
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 12/32] libxl: Design of an async API to issue QMP commands to QEMU
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (10 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 11/32] libxl_dm: Add libxl__qemu_qmp_path() Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-08-02  9:01   ` [PATCH v4 12/32] libxl: Design of an async API to issue QMP commands to QEMUç Roger Pau Monné
  2018-07-27 14:05 ` [PATCH v4 13/32] libxl_qmp: Connect to QMP socket Anthony PERARD
                   ` (19 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

All the functions will be implemented in later patches.

This patch includes the API that libxl can use to send QMP commands to
QEMU.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
 tools/libxl/libxl_internal.h | 76 +++++++++++++++++++++++++++++++++++-
 1 file changed, 74 insertions(+), 2 deletions(-)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 5b71a23d23..c453ac10a5 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -202,6 +202,8 @@ typedef struct libxl__ao libxl__ao;
 typedef struct libxl__aop_occurred libxl__aop_occurred;
 typedef struct libxl__osevent_hook_nexus libxl__osevent_hook_nexus;
 typedef struct libxl__osevent_hook_nexi libxl__osevent_hook_nexi;
+typedef struct libxl__json_object libxl__json_object;
+typedef struct libxl__carefd libxl__carefd;
 
 typedef struct libxl__domain_create_state libxl__domain_create_state;
 typedef void libxl__domain_create_cb(struct libxl__egc *egc,
@@ -357,6 +359,76 @@ struct libxl__ev_child {
     LIBXL_LIST_ENTRY(struct libxl__ev_child) entry;
 };
 
+/*
+ * QMP asynchronous calls
+ */
+
+/*
+ * This facility allows a command to be sent to QEMU, and the response to be
+ * handed to a callback function.  Each libxl__ev_qmp handles zero or one
+ * outstanding command.
+ *
+ * Commands can be chained, with a same connection. (e.g. "add-fd" will need to
+ * be chained to the next command). A libxl__ev_qmp can be reused when the
+ * callback is been called in order to use the same connection.
+ *
+ * Only one connection at a time can be made to one QEMU, so avoid keeping a
+ * libxl__ev_qmp Connected for to long and call libxl__ev_qmp_dispose as soon
+ * as it is not needed anymore.
+ *
+ * Possible states of a libxl__ev_qmp:
+ *  Undefined
+ *    Might contain anything.
+ *  Idle
+ *    Struct contents are defined enough to pass to any libxl__ev_qmp_*
+ *    functions.
+ *    The struct does not contain references to any allocated private resources
+ *    so can be thrown away.
+ *  Active
+ *    Currently waiting for the callback to be called.
+ *    _dispose must be called to reclaim resources.
+ *  Connected
+ *    Struct contain allocated ressources.
+ *    Calling _send() with this same ev will use the same QMP connection.
+ *    _dispose() must be called to reclaim resources.
+ *
+ * libxl__ev_qmp_init: Undefined/Idle -> Idle
+ *
+ * libxl__ev_qmp_send: Idle/Connected -> Active (on error: Idle)
+ *    Sends a command to QEMU.
+ *    callback will be called when a response is received or when an error
+ *    as occured.
+ *
+ * libxl__ev_qmp_dispose: Connected/Active/Idle -> Idle
+ *
+ * callback: When called: Active -> Connected
+ *    When called, ev is Connected and can be reused or disposed of.
+ *    When an error occured, it is called with response == NULL and the error
+ *    code in rc.
+ *    The callback is only called once.
+ */
+typedef struct libxl__ev_qmp libxl__ev_qmp;
+typedef void libxl__ev_qmp_callback(libxl__egc *egc, libxl__ev_qmp *ev,
+                                    const libxl__json_object *response,
+                                    int rc);
+
+_hidden void libxl__ev_qmp_init(libxl__ev_qmp *ev);
+_hidden int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
+                               const char *cmd, libxl__json_object *args);
+_hidden void libxl__ev_qmp_dispose(libxl__gc *gc, libxl__ev_qmp *ev);
+
+struct libxl__ev_qmp {
+    /* caller should include this in their own struct */
+    /* caller must fill these in, and they must all remain valid */
+    uint32_t domid;
+    libxl__ev_qmp_callback *callback;
+    libxl__carefd *cfd; /* set to send a fd with the command, NULL otherwise */
+
+    /* remaining fields are private to libxl_ev_qmp_* */
+
+    int id;
+};
+
 
 /*
  * evgen structures, which are the state we use for generating
@@ -1902,7 +1974,7 @@ typedef enum {
     JSON_ANY     = 255 /* this is a mask of all values above, adjust as needed */
 } libxl__json_node_type;
 
-typedef struct libxl__json_object {
+struct libxl__json_object {
     libxl__json_node_type type;
     union {
         bool b;
@@ -1915,7 +1987,7 @@ typedef struct libxl__json_object {
         flexarray_t *map;
     } u;
     struct libxl__json_object *parent;
-} libxl__json_object;
+};
 
 typedef int (*libxl__json_parse_callback)(libxl__gc *gc,
                                           libxl__json_object *o,
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 13/32] libxl_qmp: Connect to QMP socket
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (11 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 12/32] libxl: Design of an async API to issue QMP commands to QEMU Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-08-02  9:35   ` Roger Pau Monné
  2018-07-27 14:05 ` [PATCH v4 14/32] libxl_qmp: Implement fd callback and read data Anthony PERARD
                   ` (18 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

This is a first patch to implement libxl__ev_qmp, it only connect to the
QMP socket of QEMU and register a fd callback that does nothing.

Callback functions will be implemented in following patches.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
 tools/libxl/libxl_internal.h | 11 +++++
 tools/libxl/libxl_qmp.c      | 96 ++++++++++++++++++++++++++++++++++++
 2 files changed, 107 insertions(+)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index c453ac10a5..90ac48a659 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -417,6 +417,14 @@ _hidden int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
                                const char *cmd, libxl__json_object *args);
 _hidden void libxl__ev_qmp_dispose(libxl__gc *gc, libxl__ev_qmp *ev);
 
+typedef enum {
+    qmp_state_disconnected = 1,
+    qmp_state_connecting,
+    qmp_state_greeting,
+    qmp_state_capability_negociation,
+    qmp_state_connected,
+} libxl__qmp_state;
+
 struct libxl__ev_qmp {
     /* caller should include this in their own struct */
     /* caller must fill these in, and they must all remain valid */
@@ -427,6 +435,9 @@ struct libxl__ev_qmp {
     /* remaining fields are private to libxl_ev_qmp_* */
 
     int id;
+    libxl__carefd *qmp_cfd;
+    libxl__ev_fd qmp_efd;
+    libxl__qmp_state qmp_state;
 };
 
 
diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index c5e05e5679..96a347dd3b 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -1276,6 +1276,102 @@ int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
     return ret;
 }
 
+/* ------------ Implementation of libxl__ev_qmp ---------------- */
+
+static void qmp_ev_fd_callback(libxl__egc *egc, libxl__ev_fd *ev_fd,
+                               int fd, short events, short revents)
+{
+}
+
+static int qmp_ev_connect(libxl__gc *gc, libxl__ev_qmp *ev)
+{
+    int rc, r;
+    struct sockaddr_un un;
+    const char *qmp_socket_path;
+
+    if (ev->qmp_state != qmp_state_disconnected)
+        return 0;
+
+    qmp_socket_path = libxl__qemu_qmp_path(gc, ev->domid);
+
+    LOGD(DEBUG, ev->domid, "Connecting to %s", qmp_socket_path);
+
+    libxl__carefd_begin();
+    ev->qmp_cfd = libxl__carefd_opened(CTX, socket(AF_UNIX, SOCK_STREAM, 0));
+    if (!ev->qmp_cfd) {
+        LOGED(ERROR, ev->domid, "socket() failed");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    rc = libxl_fd_set_nonblock(CTX, libxl__carefd_fd(ev->qmp_cfd), 1);
+    if (rc)
+        goto out;
+
+    rc = libxl__prepare_sockaddr_un(gc, &un, qmp_socket_path, "QMP socket");
+    if (rc)
+        goto out;
+
+    r = connect(libxl__carefd_fd(ev->qmp_cfd),
+                (struct sockaddr *) &un, sizeof(un));
+    if (r) {
+        LOGED(ERROR, ev->domid, "Failed to connect to QMP socket %s",
+              qmp_socket_path);
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    rc = libxl__ev_fd_register(gc, &ev->qmp_efd, qmp_ev_fd_callback,
+                               libxl__carefd_fd(ev->qmp_cfd), POLLIN);
+    if (rc)
+        goto out;
+
+    ev->qmp_state = qmp_state_connecting;
+    return 0;
+
+out:
+    libxl__carefd_close(ev->qmp_cfd);
+    ev->qmp_cfd = NULL;
+    return rc;
+}
+
+
+/*
+ * libxl__ev_qmp_*
+ */
+
+void libxl__ev_qmp_init(libxl__ev_qmp *ev)
+{
+    ev->id = -1;
+
+    ev->qmp_cfd = NULL;
+    libxl__ev_fd_init(&ev->qmp_efd);
+    ev->qmp_state = qmp_state_disconnected;
+}
+
+int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
+                       const char *cmd, libxl__json_object *args)
+{
+    int rc;
+
+    LOGD(DEBUG, ev->domid, " ev %p, cmd '%s'", ev, cmd);
+
+    /* Connect to QEMU if not already connected */
+    rc = qmp_ev_connect(gc, ev);
+
+    return rc;
+}
+
+void libxl__ev_qmp_dispose(libxl__gc *gc, libxl__ev_qmp *ev)
+{
+    LOGD(DEBUG, ev->domid, " ev %p", ev);
+
+    libxl__ev_fd_deregister(gc, &ev->qmp_efd);
+    libxl__carefd_close(ev->qmp_cfd);
+    ev->qmp_cfd = NULL;
+
+    libxl__ev_qmp_init(ev);
+}
+
 /*
  * Local variables:
  * mode: C
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 14/32] libxl_qmp: Implement fd callback and read data
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (12 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 13/32] libxl_qmp: Connect to QMP socket Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-08-02  9:56   ` Roger Pau Monné
  2018-07-27 14:05 ` [PATCH v4 15/32] libxl_json: Enable yajl_allow_trailing_garbage Anthony PERARD
                   ` (17 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

First step into taking care of the input from QEMU's QMP socket. For
now, we read data and store them in a buffer.

Parsing of the data will be done in the following patches.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---

Notes:
    v4:
        remove use of a linked list of receive buffer, and use realloc instead.

 tools/libxl/libxl_internal.h |   9 ++++
 tools/libxl/libxl_qmp.c      | 101 +++++++++++++++++++++++++++++++++++
 2 files changed, 110 insertions(+)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 90ac48a659..8c3625a243 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -438,6 +438,15 @@ struct libxl__ev_qmp {
     libxl__carefd *qmp_cfd;
     libxl__ev_fd qmp_efd;
     libxl__qmp_state qmp_state;
+
+    /* receive buffer, with:
+     * buf_size: current allocated size,
+     * buf_used: actual data in the buffer,
+     * buf_consumed: data already parsed.  */
+    char *rx_buf;
+    size_t buf_size;
+    size_t buf_used;
+    size_t buf_consumed;
 };
 
 
diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 96a347dd3b..b0554df843 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -75,6 +75,12 @@
 #  define DEBUG_REPORT_RECEIVED(dom, buf, len) ((void)0)
 #endif
 
+#ifdef DEBUG_QMP_CLIENT
+#  define LOG_QMP(f, ...) LOGD(DEBUG, ev->domid, f, ##__VA_ARGS__)
+#else
+#  define LOG_QMP(f, ...)
+#endif
+
 /*
  * QMP types & constant
  */
@@ -1278,9 +1284,99 @@ int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
 
 /* ------------ Implementation of libxl__ev_qmp ---------------- */
 
+/*
+ * QMP FD callbacks
+ */
+
+static int qmp_ev_callback_readable(libxl__egc *egc, libxl__ev_qmp *ev, int fd)
+{
+    EGC_GC;
+    ssize_t r;
+
+    if (!ev->rx_buf) {
+        ev->rx_buf = libxl__malloc(NOGC, QMP_RECEIVE_BUFFER_SIZE);
+        ev->buf_size = QMP_RECEIVE_BUFFER_SIZE;
+        ev->buf_used = 0;
+        ev->buf_consumed = 0;
+    }
+
+    /* Check if last buffer still have space, or increase size */
+    /* The -1 is because there is always space for a NUL character */
+    if (ev->buf_used == ev->buf_size - 1) {
+        ev->buf_size += QMP_RECEIVE_BUFFER_SIZE;
+        ev->rx_buf = libxl__realloc(NOGC, ev->rx_buf, ev->buf_size);
+    }
+
+    for (;;) {
+        /* The -1 is because there is always space for a NUL character */
+        r = read(fd, ev->rx_buf + ev->buf_used,
+                 ev->buf_size - ev->buf_used - 1);
+        if (r < 0) {
+            if (errno == EINTR) continue;
+            assert(errno);
+            if (errno == EWOULDBLOCK) {
+                return 0;
+            }
+            LOGED(ERROR, ev->domid, "error reading QMP socket");
+            return ERROR_FAIL;
+        }
+        break;
+    }
+
+    if (r == 0) {
+        LOGD(ERROR, ev->domid, "No data read on QMP socket");
+        return 0;
+    }
+
+    LOG_QMP("received %ldB: '%.*s'", r, (int)r, ev->rx_buf + ev->buf_used);
+
+    ev->buf_used += r;
+    assert(ev->buf_used < ev->buf_size);
+
+    return 0;
+}
+
+static void qmp_ev_callback_error(libxl__egc *egc, libxl__ev_qmp *ev)
+{
+    EGC_GC;
+
+    LOGD(ERROR, ev->domid, "Error happend with the QMP connection to QEMU");
+
+    /* On error, deallocate all private ressources */
+    libxl__ev_qmp_dispose(gc, ev);
+}
+
 static void qmp_ev_fd_callback(libxl__egc *egc, libxl__ev_fd *ev_fd,
                                int fd, short events, short revents)
 {
+    EGC_GC;
+    int rc;
+
+    libxl__ev_qmp *ev = CONTAINER_OF(ev_fd, *ev, qmp_efd);
+
+    if (revents & (POLLHUP)) {
+        LOGD(DEBUG, ev->domid, "received POLLHUP from QMP socket");
+        qmp_ev_callback_error(egc, ev);
+        return;
+    }
+    if (revents & ~(POLLIN|POLLOUT)) {
+        LOGD(ERROR, ev->domid,
+             "unexpected poll event 0x%x on QMP socket (expected POLLIN "
+             "and/or POLLOUT)",
+            revents);
+        qmp_ev_callback_error(egc, ev);
+        return;
+    }
+
+    if (revents & POLLIN) {
+        rc = qmp_ev_callback_readable(egc, ev, fd);
+        if (rc)
+            goto out;
+    }
+out:
+    if (rc) {
+        qmp_ev_callback_error(egc, ev);
+    }
 }
 
 static int qmp_ev_connect(libxl__gc *gc, libxl__ev_qmp *ev)
@@ -1346,6 +1442,8 @@ void libxl__ev_qmp_init(libxl__ev_qmp *ev)
     ev->qmp_cfd = NULL;
     libxl__ev_fd_init(&ev->qmp_efd);
     ev->qmp_state = qmp_state_disconnected;
+
+    ev->rx_buf = NULL;
 }
 
 int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
@@ -1365,6 +1463,9 @@ void libxl__ev_qmp_dispose(libxl__gc *gc, libxl__ev_qmp *ev)
 {
     LOGD(DEBUG, ev->domid, " ev %p", ev);
 
+    free(ev->rx_buf);
+    ev->rx_buf = NULL;
+
     libxl__ev_fd_deregister(gc, &ev->qmp_efd);
     libxl__carefd_close(ev->qmp_cfd);
     ev->qmp_cfd = NULL;
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 15/32] libxl_json: Enable yajl_allow_trailing_garbage
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (13 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 14/32] libxl_qmp: Implement fd callback and read data Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-08-02 10:01   ` Roger Pau Monné
  2018-07-27 14:05 ` [PATCH v4 16/32] libxl_json: libxl__json_object_to_json Anthony PERARD
                   ` (16 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

This allow to parse a string that is not NUL-terminated. With that
options disabled, YAJL v2 would look ahead on completion to find out if
there is more to parse.

YAJL v1 doesn't have this behavior.

Any function function that allocate a yajl_handle via this function
either parse a NUL-terminated string, or do provide proper length. So
change the default and allow garbage (like a different JSON document)
after the end of the data to parse.

This is importand for the QMP client, as there could be more than one
message to parse, and YAJL would consider the next message to be
garbage and throw an error.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
 tools/libxl/libxl_json.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tools/libxl/libxl_json.h b/tools/libxl/libxl_json.h
index af26e7885d..260783bfde 100644
--- a/tools/libxl/libxl_json.h
+++ b/tools/libxl/libxl_json.h
@@ -50,7 +50,10 @@ static inline yajl_handle libxl__yajl_alloc(const yajl_callbacks *callbacks,
                                             yajl_alloc_funcs *allocFuncs,
                                             void *ctx)
 {
-    return yajl_alloc(callbacks, allocFuncs, ctx);
+    yajl_handle hand = yajl_alloc(callbacks, allocFuncs, ctx);
+    if (hand)
+        yajl_config(hand, yajl_allow_trailing_garbage, 1);
+    return hand;
 }
 
 static inline yajl_gen libxl_yajl_gen_alloc(const yajl_alloc_funcs *allocFuncs)
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 16/32] libxl_json: libxl__json_object_to_json
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (14 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 15/32] libxl_json: Enable yajl_allow_trailing_garbage Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-08-02 10:10   ` Roger Pau Monné
  2018-08-21  8:26   ` Wei Liu
  2018-07-27 14:05 ` [PATCH v4 17/32] libxl_qmp: Parse JSON input from QMP Anthony PERARD
                   ` (15 subsequent siblings)
  31 siblings, 2 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

Allow to generate a JSON string from a libxl__json_object,
usefull for debugging.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
---
 tools/libxl/libxl_internal.h |  3 +++
 tools/libxl/libxl_json.c     | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 8c3625a243..7f200e7a46 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2129,6 +2129,9 @@ _hidden void libxl__json_object_free(libxl__gc *gc_opt,
 
 _hidden libxl__json_object *libxl__json_parse(libxl__gc *gc_opt, const char *s);
 
+_hidden char *libxl__json_object_to_json(libxl__gc *gc,
+                                         const libxl__json_object *args);
+
   /* Based on /local/domain/$domid/dm-version xenstore key
    * default is qemu xen traditional */
 _hidden int libxl__device_model_version_running(libxl__gc *gc, uint32_t domid);
diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c
index b7f9077f0d..16cdd5bda3 100644
--- a/tools/libxl/libxl_json.c
+++ b/tools/libxl/libxl_json.c
@@ -1017,6 +1017,42 @@ out:
     return ret;
 }
 
+char *libxl__json_object_to_json(libxl__gc *gc,
+                                 const libxl__json_object *args)
+{
+    const unsigned char *buf;
+    libxl_yajl_length len;
+    yajl_gen_status s;
+    yajl_gen hand;
+    char *ret = NULL;
+    int rc;
+
+    if (!args)
+        return NULL;
+
+    hand = libxl_yajl_gen_alloc(NULL);
+
+    if (!hand) {
+        return NULL;
+    }
+
+    rc = libxl__json_object_to_yajl_gen(gc, hand, args);
+    if (rc)
+        goto out;
+
+    s = yajl_gen_get_buf(hand, &buf, &len);
+
+    if (s) {
+        goto out;
+    }
+
+    ret = libxl__strndup(gc, (const char *)buf, len);
+
+out:
+    yajl_gen_free(hand);
+    return ret;
+}
+
 yajl_gen_status libxl__uint64_gen_json(yajl_gen hand, uint64_t val)
 {
     char *num;
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 17/32] libxl_qmp: Parse JSON input from QMP
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (15 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 16/32] libxl_json: libxl__json_object_to_json Anthony PERARD
@ 2018-07-27 14:05 ` Anthony PERARD
  2018-08-02 10:25   ` Roger Pau Monné
  2018-07-27 14:06 ` [PATCH v4 18/32] libxl_qmp: Separate QMP message generation from qmp_send_prepare Anthony PERARD
                   ` (14 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:05 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---

Notes:
    v4:
        simplification of the patch due to use of a single allocated space for the
        receive buffer.

 tools/libxl/libxl_qmp.c | 54 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index b0554df843..665b6f5d05 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -1292,6 +1292,7 @@ static int qmp_ev_callback_readable(libxl__egc *egc, libxl__ev_qmp *ev, int fd)
 {
     EGC_GC;
     ssize_t r;
+    char *end = NULL;
 
     if (!ev->rx_buf) {
         ev->rx_buf = libxl__malloc(NOGC, QMP_RECEIVE_BUFFER_SIZE);
@@ -1333,6 +1334,59 @@ static int qmp_ev_callback_readable(libxl__egc *egc, libxl__ev_qmp *ev, int fd)
     ev->buf_used += r;
     assert(ev->buf_used < ev->buf_size);
 
+    /* workaround strstr limitation */
+    ev->rx_buf[ev->buf_used] = '\0';
+
+    /*
+     * Search for the end of a QMP message: "\r\n" in the newly received
+     * bytes + the last byte on the previous read() if any
+     *
+     * end: This will point to the byte right after \r\n
+     */
+    end = strstr(ev->rx_buf + ev->buf_used - r
+                 + (ev->buf_used - r == 0 ? 0 : -1),
+                 "\r\n");
+    if (end)
+        end += 2;
+
+    while (end) {
+        libxl__json_object *o;
+        size_t len;
+        char *s;
+
+        /* Start parsing from s */
+        s = ev->rx_buf + ev->buf_consumed;
+        /* Findout how much can be parsed */
+        len = end - s;
+
+        LOG_QMP("parsing %luB: '%.*s'", len, (int)len, s);
+
+        /* Replace \n by \0 so that libxl__json_parse can use strlen */
+        s[len - 1] = '\0';
+        o = libxl__json_parse(gc, s); //, len);
+
+        if (!o) {
+            LOGD(ERROR, ev->domid, "Parse error");
+            return ERROR_FAIL;
+        }
+
+        ev->buf_consumed += len;
+
+        if (ev->buf_consumed >= ev->buf_used) {
+            free(ev->rx_buf);
+            ev->rx_buf = NULL;
+        }
+
+        /* check if there is another message received at the same time */
+        if (ev->rx_buf) {
+            end = strstr(ev->rx_buf + ev->buf_consumed, "\r\n");
+            if (end)
+                end += 2;
+        } else
+            end = NULL;
+
+        LOG_QMP("JSON object received: %s", libxl__json_object_to_json(gc, o));
+    }
     return 0;
 }
 
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 18/32] libxl_qmp: Separate QMP message generation from qmp_send_prepare
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (16 preceding siblings ...)
  2018-07-27 14:05 ` [PATCH v4 17/32] libxl_qmp: Parse JSON input from QMP Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-02 10:34   ` Roger Pau Monné
  2018-07-27 14:06 ` [PATCH v4 19/32] libxl_qmp: Prepare the command to be sent Anthony PERARD
                   ` (13 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

To be able to re-use qmp_prepare_qmp_cmd with libxl__ev_qmp.

Also, add the QMP end of command '\r\n' into the generated string.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
 tools/libxl/libxl_qmp.c | 62 +++++++++++++++++++++++++++++------------
 1 file changed, 44 insertions(+), 18 deletions(-)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 665b6f5d05..38a4395266 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -578,17 +578,17 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp)
     return rc;
 }
 
-static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp,
-                              const char *cmd, libxl__json_object *args,
-                              qmp_callback_t callback, void *opaque,
-                              qmp_request_context *context)
-{
-    const unsigned char *buf = NULL;
-    char *ret = NULL;
-    libxl_yajl_length len = 0;
+static char *qmp_prepare_qmp_cmd(libxl__gc *gc,
+                                 const char *cmd,
+                                 const libxl__json_object *args,
+                                 int id,
+                                 size_t *len_r)
+{
+    const unsigned char *buf;
+    libxl_yajl_length len;
     yajl_gen_status s;
     yajl_gen hand;
-    callback_id_pair *elm = NULL;
+    char *ret = NULL;
 
     hand = libxl_yajl_gen_alloc(NULL);
 
@@ -600,7 +600,7 @@ static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp,
     libxl__yajl_gen_asciiz(hand, "execute");
     libxl__yajl_gen_asciiz(hand, cmd);
     libxl__yajl_gen_asciiz(hand, "id");
-    yajl_gen_integer(hand, ++qmp->last_id_used);
+    yajl_gen_integer(hand, id);
     if (args) {
         libxl__yajl_gen_asciiz(hand, "arguments");
         libxl__json_object_to_yajl_gen(gc, hand, args);
@@ -610,6 +610,36 @@ static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp,
     s = yajl_gen_get_buf(hand, &buf, &len);
 
     if (s) {
+        goto out;
+    }
+
+    ret = libxl__malloc(NOGC, len + 3);
+    strncpy(ret, (const char *)buf, len + 3);
+    strncpy(ret + len, "\r\n", 3);
+    len += 2;
+
+    if (len_r)
+        *len_r = len;
+
+out:
+    yajl_gen_free(hand);
+    return ret;
+}
+
+static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp,
+                              const char *cmd, libxl__json_object *args,
+                              qmp_callback_t callback, void *opaque,
+                              qmp_request_context *context,
+                              size_t *len_r)
+{
+    char *buf;
+    callback_id_pair *elm;
+
+    buf = qmp_prepare_qmp_cmd(gc,
+                              cmd, args, ++qmp->last_id_used,
+                              NULL);
+
+    if (!buf) {
         LOGD(ERROR, qmp->domid, "Failed to generate a qmp command");
         goto out;
     }
@@ -625,13 +655,10 @@ static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp,
     elm->context = context;
     LIBXL_STAILQ_INSERT_TAIL(&qmp->callback_list, elm, next);
 
-    ret = libxl__strndup(gc, (const char*)buf, len);
-
     LOGD(DEBUG, qmp->domid, "next qmp command: '%s'", buf);
 
 out:
-    yajl_gen_free(hand);
-    return ret;
+    return buf;
 }
 
 static int qmp_send(libxl__qmp_handler *qmp,
@@ -643,7 +670,8 @@ static int qmp_send(libxl__qmp_handler *qmp,
     int rc = -1;
     GC_INIT(qmp->ctx);
 
-    buf = qmp_send_prepare(gc, qmp, cmd, args, callback, opaque, context);
+    buf = qmp_send_prepare(gc, qmp, cmd, args, callback, opaque, context,
+                           NULL);
 
     if (buf == NULL) {
         goto out;
@@ -652,12 +680,10 @@ static int qmp_send(libxl__qmp_handler *qmp,
     if (libxl_write_exactly(qmp->ctx, qmp->qmp_fd, buf, strlen(buf),
                             "QMP command", "QMP socket"))
         goto out;
-    if (libxl_write_exactly(qmp->ctx, qmp->qmp_fd, "\r\n", 2,
-                            "CRLF", "QMP socket"))
-        goto out;
 
     rc = qmp->last_id_used;
 out:
+    free(buf);
     GC_FREE;
     return rc;
 }
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 19/32] libxl_qmp: Prepare the command to be sent
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (17 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 18/32] libxl_qmp: Separate QMP message generation from qmp_send_prepare Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-02 10:41   ` Roger Pau Monné
  2018-07-27 14:06 ` [PATCH v4 20/32] libxl_qmp: Handle write to QMP socket Anthony PERARD
                   ` (12 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

The actual sent will be done in a separate patch.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
 tools/libxl/libxl_internal.h |  4 ++++
 tools/libxl/libxl_qmp.c      | 37 ++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 7f200e7a46..110b951bbe 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -438,6 +438,7 @@ struct libxl__ev_qmp {
     libxl__carefd *qmp_cfd;
     libxl__ev_fd qmp_efd;
     libxl__qmp_state qmp_state;
+    unsigned int last_id_used;
 
     /* receive buffer, with:
      * buf_size: current allocated size,
@@ -447,6 +448,9 @@ struct libxl__ev_qmp {
     size_t buf_size;
     size_t buf_used;
     size_t buf_consumed;
+
+    char *tx_buf;
+    size_t tx_buf_len;
 };
 
 
diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 38a4395266..2792f35912 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -1310,6 +1310,25 @@ int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
 
 /* ------------ Implementation of libxl__ev_qmp ---------------- */
 
+static int qmp_ev_prepare_cmd(libxl__gc *gc,
+                              libxl__ev_qmp *ev,
+                              const char *cmd,
+                              const libxl__json_object *args)
+{
+    char *buf = NULL;
+    size_t len;
+
+    buf = qmp_prepare_qmp_cmd(gc, cmd, args, ++ev->last_id_used, &len);
+    if (!buf)
+        return ERROR_FAIL;
+
+    ev->id = ev->last_id_used;
+    ev->tx_buf = buf;
+    ev->tx_buf_len = len;
+
+    return 0;
+}
+
 /*
  * QMP FD callbacks
  */
@@ -1424,6 +1443,9 @@ static void qmp_ev_callback_error(libxl__egc *egc, libxl__ev_qmp *ev)
 
     /* On error, deallocate all private ressources */
     libxl__ev_qmp_dispose(gc, ev);
+
+    ev->id = -1;
+    ev->callback(egc, ev, NULL, ERROR_FAIL);
 }
 
 static void qmp_ev_fd_callback(libxl__egc *egc, libxl__ev_fd *ev_fd,
@@ -1522,8 +1544,10 @@ void libxl__ev_qmp_init(libxl__ev_qmp *ev)
     ev->qmp_cfd = NULL;
     libxl__ev_fd_init(&ev->qmp_efd);
     ev->qmp_state = qmp_state_disconnected;
+    ev->last_id_used = 0;
 
     ev->rx_buf = NULL;
+    ev->tx_buf = NULL;
 }
 
 int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
@@ -1535,7 +1559,17 @@ int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
 
     /* Connect to QEMU if not already connected */
     rc = qmp_ev_connect(gc, ev);
+    if (rc)
+        goto out;
+
+    rc = qmp_ev_prepare_cmd(gc, ev, cmd, args);
+    if (rc)
+        goto out;
+
 
+out:
+    if (rc)
+        libxl__ev_qmp_dispose(gc, ev);
     return rc;
 }
 
@@ -1546,6 +1580,9 @@ void libxl__ev_qmp_dispose(libxl__gc *gc, libxl__ev_qmp *ev)
     free(ev->rx_buf);
     ev->rx_buf = NULL;
 
+    free(ev->tx_buf);
+    ev->tx_buf = NULL;
+
     libxl__ev_fd_deregister(gc, &ev->qmp_efd);
     libxl__carefd_close(ev->qmp_cfd);
     ev->qmp_cfd = NULL;
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 20/32] libxl_qmp: Handle write to QMP socket
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (18 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 19/32] libxl_qmp: Prepare the command to be sent Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-02 11:02   ` Roger Pau Monné
  2018-07-27 14:06 ` [PATCH v4 21/32] libxl_qmp: Simplify qmp_response_type() prototype Anthony PERARD
                   ` (11 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

The libxl__ev_qmp_* will now send the command to QEMU when the socket is
ready for writes.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
 tools/libxl/libxl_qmp.c | 44 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 2792f35912..75f953d521 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -1326,6 +1326,8 @@ static int qmp_ev_prepare_cmd(libxl__gc *gc,
     ev->tx_buf = buf;
     ev->tx_buf_len = len;
 
+    libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events | POLLOUT);
+
     return 0;
 }
 
@@ -1435,6 +1437,43 @@ static int qmp_ev_callback_readable(libxl__egc *egc, libxl__ev_qmp *ev, int fd)
     return 0;
 }
 
+static int qmp_ev_callback_writable(libxl__gc *gc, libxl__ev_qmp *ev, int fd)
+{
+    int rc;
+    char *buf;
+    size_t len;
+    int buf_fd = -1;
+
+    /* No need to call qmp_ev_callback_writable again, everything that needs to
+     * be send for now will be in this call. */
+    libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events & ~POLLOUT);
+
+    if (ev->qmp_state == qmp_state_connected) {
+        if (!ev->tx_buf)
+            return 0;
+
+        buf = ev->tx_buf;
+        len = ev->tx_buf_len;
+        buf_fd = libxl__carefd_fd(ev->cfd);
+
+        ev->tx_buf = NULL;
+    } else {
+        return 0;
+    }
+
+    LOG_QMP("sending: '%.*s'", (int)len, buf);
+
+    if (buf_fd >= 0) {
+        rc = libxl__sendmsg_fds(gc, fd, buf, len, 1, &buf_fd, "QMP socket");
+    } else {
+        rc = libxl_write_exactly(CTX, fd, buf, len,
+                                 "QMP command", "QMP socket");
+    }
+
+    free(buf);
+    return rc;
+}
+
 static void qmp_ev_callback_error(libxl__egc *egc, libxl__ev_qmp *ev)
 {
     EGC_GC;
@@ -1470,6 +1509,11 @@ static void qmp_ev_fd_callback(libxl__egc *egc, libxl__ev_fd *ev_fd,
         return;
     }
 
+    if (revents & POLLOUT) {
+        rc = qmp_ev_callback_writable(gc, ev, fd);
+        if (rc)
+            goto out;
+    }
     if (revents & POLLIN) {
         rc = qmp_ev_callback_readable(egc, ev, fd);
         if (rc)
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 21/32] libxl_qmp: Simplify qmp_response_type() prototype
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (19 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 20/32] libxl_qmp: Handle write to QMP socket Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-02 11:03   ` Roger Pau Monné
  2018-08-21  8:53   ` Wei Liu
  2018-07-27 14:06 ` [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU Anthony PERARD
                   ` (10 subsequent siblings)
  31 siblings, 2 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

Remove the libxl__qmp_handler* argument so the function can be reused
later in a different context.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
---
 tools/libxl/libxl_qmp.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 75f953d521..aabf9ad5e7 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -279,8 +279,7 @@ static int enable_qmp_capabilities(libxl__qmp_handler *qmp)
  * Helpers
  */
 
-static libxl__qmp_message_type qmp_response_type(libxl__qmp_handler *qmp,
-                                                 const libxl__json_object *o)
+static libxl__qmp_message_type qmp_response_type(const libxl__json_object *o)
 {
     libxl__qmp_message_type type;
     libxl__json_map_node *node = NULL;
@@ -346,7 +345,7 @@ static int qmp_handle_response(libxl__gc *gc, libxl__qmp_handler *qmp,
 {
     libxl__qmp_message_type type = LIBXL__QMP_MESSAGE_TYPE_INVALID;
 
-    type = qmp_response_type(qmp, resp);
+    type = qmp_response_type(resp);
     LOGD(DEBUG, qmp->domid, "message type: %s", libxl__qmp_message_type_to_string(type));
 
     switch (type) {
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (20 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 21/32] libxl_qmp: Simplify qmp_response_type() prototype Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-02 11:17   ` Roger Pau Monné
  2018-07-27 14:06 ` [PATCH v4 23/32] libxl_qmp: Respond to QMP greeting Anthony PERARD
                   ` (9 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

This will handles messages received, and calls callbacks associated with
the libxl__ev_qmp when the expected response is received.

This also print error messages from QMP on behalf of the callback.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---

Notes:
    v4:
        Provide an libxl error code to callbacks on error instead of a
        qmp_error_class

 tools/libxl/libxl_qmp.c              | 116 +++++++++++++++++++++++++++
 tools/libxl/libxl_types.idl          |   4 +
 tools/libxl/libxl_types_internal.idl |   8 ++
 3 files changed, 128 insertions(+)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index aabf9ad5e7..e649b8054d 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -1330,6 +1330,118 @@ static int qmp_ev_prepare_cmd(libxl__gc *gc,
     return 0;
 }
 
+/*
+ * Handle messages received from QMP server
+ */
+
+static int qmp_error_class_to_libxl_error_code(const libxl__qmp_error_class c)
+{
+    switch (c) {
+    case LIBXL__QMP_ERROR_CLASS_GENERICERROR:
+        return ERROR_QMP_GENERIC_ERROR;
+    case LIBXL__QMP_ERROR_CLASS_COMMANDNOTFOUND:
+        return ERROR_QMP_COMMAND_NOT_FOUND;
+    case LIBXL__QMP_ERROR_CLASS_DEVICENOTACTIVE:
+        return ERROR_QMP_DEVICE_NOT_ACTIVE;
+    case LIBXL__QMP_ERROR_CLASS_DEVICENOTFOUND:
+        return ERROR_QMP_DEVICE_NOT_FOUND;
+    default:
+        abort();
+    }
+}
+
+/* return 1 when a user callback as been called */
+static int qmp_ev_handle_response(libxl__egc *egc,
+                                  libxl__ev_qmp *ev,
+                                  const libxl__json_object *resp,
+                                  libxl__qmp_message_type type)
+{
+    EGC_GC;
+    const libxl__json_object *response;
+    const libxl__json_object *o;
+    int rc;
+    int id;
+
+    o = libxl__json_map_get("id", resp, JSON_INTEGER);
+    if (!o) {
+        const char *error_desc;
+
+        /* unexpected message, attempt to find an error description */
+        o = libxl__json_map_get("error", resp, JSON_MAP);
+        o = libxl__json_map_get("desc", o, JSON_STRING);
+        error_desc = libxl__json_object_get_string(o);
+        if (error_desc)
+            LOGD(ERROR, ev->domid, "%s", error_desc);
+        else
+            LOGD(ERROR, ev->domid, "Received unexpected message: %s",
+                 libxl__json_object_to_json(gc, resp));
+        return 0;
+    }
+
+    id = libxl__json_object_get_integer(o);
+    if (id != ev->id)
+        return 0;
+
+    switch (type) {
+    case LIBXL__QMP_MESSAGE_TYPE_RETURN: {
+        response = libxl__json_map_get("return", resp, JSON_ANY);
+        rc = 0;
+        break;
+    }
+    case LIBXL__QMP_MESSAGE_TYPE_ERROR: {
+        const char *s;
+        const libxl__json_object *err;
+        libxl__qmp_error_class error_class;
+
+        rc = ERROR_FAIL;
+        response = NULL;
+
+        err = libxl__json_map_get("error", resp, JSON_MAP);
+        o = libxl__json_map_get("class", err, JSON_STRING);
+        s = libxl__json_object_get_string(o);
+        if (s && !libxl__qmp_error_class_from_string(s, &error_class))
+            rc = qmp_error_class_to_libxl_error_code(error_class);
+
+        o = libxl__json_map_get("desc", err, JSON_STRING);
+        s = libxl__json_object_get_string(o);
+        if (s)
+            LOGD(ERROR, ev->domid, "%s", s);
+
+        break;
+    }
+    default:
+        abort();
+    }
+
+    ev->id = -1;
+    ev->callback(egc, ev, response, rc); /* must be last */
+    return 1;
+}
+
+/* return 1 when a user callback as been called */
+static int qmp_ev_handle_message(libxl__egc *egc,
+                                 libxl__ev_qmp *ev,
+                                 const libxl__json_object *resp)
+{
+    EGC_GC;
+    libxl__qmp_message_type type = qmp_response_type(resp);
+
+    switch (type) {
+    case LIBXL__QMP_MESSAGE_TYPE_QMP:
+        /* greeting message */
+        return 0;
+    case LIBXL__QMP_MESSAGE_TYPE_RETURN:
+    case LIBXL__QMP_MESSAGE_TYPE_ERROR:
+        return qmp_ev_handle_response(egc, ev, resp, type);
+    case LIBXL__QMP_MESSAGE_TYPE_EVENT:
+        /* Event are ignored */
+        return 0;
+    case LIBXL__QMP_MESSAGE_TYPE_INVALID:
+        return 0;
+    }
+    return 0;
+}
+
 /*
  * QMP FD callbacks
  */
@@ -1432,6 +1544,10 @@ static int qmp_ev_callback_readable(libxl__egc *egc, libxl__ev_qmp *ev, int fd)
             end = NULL;
 
         LOG_QMP("JSON object received: %s", libxl__json_object_to_json(gc, o));
+
+        /* Must be last and return when the user callback is called */
+        if (qmp_ev_handle_message(egc, ev, o) == 1)
+            return 0;
     }
     return 0;
 }
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 4a385801ba..e104fea941 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -69,6 +69,10 @@ libxl_error = Enumeration("error", [
     (-23, "NOTFOUND"),
     (-24, "DOMAIN_DESTROYED"), # Target domain ceased to exist during op
     (-25, "FEATURE_REMOVED"), # For functionality that has been removed
+    (-26, "QMP_GENERIC_ERROR"), # unspecified qmp error
+    (-27, "QMP_COMMAND_NOT_FOUND"), # the requested command has not been found
+    (-28, "QMP_DEVICE_NOT_ACTIVE"), # a device has failed to be become active
+    (-29, "QMP_DEVICE_NOT_FOUND"), # the requested device has not been found
     ], value_namespace = "")
 
 libxl_domain_type = Enumeration("domain_type", [
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index 37402e49cb..1536d02215 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -13,6 +13,14 @@ libxl__qmp_message_type = Enumeration("qmp_message_type", [
     (5, "invalid"),
     ])
 
+libxl__qmp_error_class = Enumeration("qmp_error_class", [
+    # QMP error classes described in QEMU sources code (QapiErrorClass)
+    (1, "GenericError"),
+    (2, "CommandNotFound"),
+    (3, "DeviceNotActive"),
+    (4, "DeviceNotFound"),
+    ])
+
 libxl__device_kind = Enumeration("device_kind", [
     (0, "NONE"),
     (1, "VIF"),
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 23/32] libxl_qmp: Respond to QMP greeting
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (21 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-02 11:26   ` Roger Pau Monné
  2018-08-21  9:00   ` Wei Liu
  2018-07-27 14:06 ` [PATCH v4 24/32] libxl_qmp: Disable beautify for QMP generated cmd Anthony PERARD
                   ` (8 subsequent siblings)
  31 siblings, 2 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
 tools/libxl/libxl_qmp.c | 36 ++++++++++++++++++++++++++++++------
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index e649b8054d..83afce3192 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -1309,6 +1309,9 @@ int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
 
 /* ------------ Implementation of libxl__ev_qmp ---------------- */
 
+/* hard coded message ID used for capability negociation */
+static int qmp_capability_negociation_msgid = 1;
+
 static int qmp_ev_prepare_cmd(libxl__gc *gc,
                               libxl__ev_qmp *ev,
                               const char *cmd,
@@ -1379,7 +1382,7 @@ static int qmp_ev_handle_response(libxl__egc *egc,
     }
 
     id = libxl__json_object_get_integer(o);
-    if (id != ev->id)
+    if (id != ev->id && id != qmp_capability_negociation_msgid)
         return 0;
 
     switch (type) {
@@ -1413,9 +1416,21 @@ static int qmp_ev_handle_response(libxl__egc *egc,
         abort();
     }
 
-    ev->id = -1;
-    ev->callback(egc, ev, response, rc); /* must be last */
-    return 1;
+    /*
+     * Even if the current state is capability_negociation and the correct ID
+     * as been received, call the callback on error.
+     */
+    if (ev->qmp_state == qmp_state_capability_negociation &&
+        id == qmp_capability_negociation_msgid &&
+        rc == 0) {
+        ev->qmp_state = qmp_state_connected;
+        libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events | POLLOUT);
+        return 0;
+    } else {
+        ev->id = -1;
+        ev->callback(egc, ev, response, rc); /* must be last */
+        return 1;
+    }
 }
 
 /* return 1 when a user callback as been called */
@@ -1429,6 +1444,11 @@ static int qmp_ev_handle_message(libxl__egc *egc,
     switch (type) {
     case LIBXL__QMP_MESSAGE_TYPE_QMP:
         /* greeting message */
+        assert(ev->qmp_state == qmp_state_connecting);
+        ev->qmp_state = qmp_state_greeting;
+        /* Allow qmp_ev_callback_writable to be called in order to send
+         * qmp_capabilities */
+        libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events | POLLOUT);
         return 0;
     case LIBXL__QMP_MESSAGE_TYPE_RETURN:
     case LIBXL__QMP_MESSAGE_TYPE_ERROR:
@@ -1563,7 +1583,11 @@ static int qmp_ev_callback_writable(libxl__gc *gc, libxl__ev_qmp *ev, int fd)
      * be send for now will be in this call. */
     libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events & ~POLLOUT);
 
-    if (ev->qmp_state == qmp_state_connected) {
+    if (ev->qmp_state == qmp_state_greeting) {
+        buf = qmp_prepare_qmp_cmd(gc, "qmp_capabilities", NULL,
+                                  qmp_capability_negociation_msgid, &len);
+        ev->qmp_state = qmp_state_capability_negociation;
+    } else if (ev->qmp_state == qmp_state_connected) {
         if (!ev->tx_buf)
             return 0;
 
@@ -1703,7 +1727,7 @@ void libxl__ev_qmp_init(libxl__ev_qmp *ev)
     ev->qmp_cfd = NULL;
     libxl__ev_fd_init(&ev->qmp_efd);
     ev->qmp_state = qmp_state_disconnected;
-    ev->last_id_used = 0;
+    ev->last_id_used = qmp_capability_negociation_msgid + 1;
 
     ev->rx_buf = NULL;
     ev->tx_buf = NULL;
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 24/32] libxl_qmp: Disable beautify for QMP generated cmd
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (22 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 23/32] libxl_qmp: Respond to QMP greeting Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-21  9:00   ` Wei Liu
  2018-07-27 14:06 ` [PATCH v4 25/32] libxl_exec: Add libxl__spawn_initiate_failure Anthony PERARD
                   ` (7 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

There is no need for it.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
---
 tools/libxl/libxl_qmp.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 83afce3192..d7aedb56a8 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -595,6 +595,11 @@ static char *qmp_prepare_qmp_cmd(libxl__gc *gc,
         return NULL;
     }
 
+#if HAVE_YAJL_V2
+    /* Disable beautify for data sent to QEMU */
+    yajl_gen_config(hand, yajl_gen_beautify, 0);
+#endif
+
     yajl_gen_map_open(hand);
     libxl__yajl_gen_asciiz(hand, "execute");
     libxl__yajl_gen_asciiz(hand, cmd);
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 25/32] libxl_exec: Add libxl__spawn_initiate_failure
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (23 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 24/32] libxl_qmp: Disable beautify for QMP generated cmd Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-02 11:34   ` Roger Pau Monné
  2018-07-27 14:06 ` [PATCH v4 26/32] libxl_dm: Pre-open QMP socket for QEMU Anthony PERARD
                   ` (6 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

This function can be use by user libxl__spawn_* when they setup a
notification other than xenstore. The parent can already called success
via libxl__spawn_initiate_detach(), this new function can be used for
failure instead of waiting for the timeout.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
 tools/libxl/libxl_exec.c     |  7 +++++++
 tools/libxl/libxl_internal.h | 21 ++++++++++++++++++++-
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/tools/libxl/libxl_exec.c b/tools/libxl/libxl_exec.c
index 02e6c917f0..fb9621b10a 100644
--- a/tools/libxl/libxl_exec.c
+++ b/tools/libxl/libxl_exec.c
@@ -373,6 +373,13 @@ void libxl__spawn_initiate_detach(libxl__gc *gc, libxl__spawn_state *ss)
     spawn_detach(gc, ss);
 }
 
+void libxl__spawn_initiate_failure(libxl__gc *gc, libxl__spawn_state *ss, int rc)
+{
+    assert(rc);
+    ss->rc = rc;
+    spawn_detach(gc, ss);
+}
+
 static void spawn_fail(libxl__egc *egc, libxl__spawn_state *ss, int rc)
 /* Caller must have logged.  Must be last thing in calling function,
  * as it may make the callback.  Precondition: Attached or Detaching. */
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 110b951bbe..b94657a7f0 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1551,7 +1551,8 @@ _hidden void libxl__spawn_init(libxl__spawn_state*);
  *
  * The inner child must soon exit or exec.  It must also soon exit or
  * notify the parent of its successful startup by writing to the
- * xenstore path xspath.
+ * xenstore path xspath OR via other mean that the parent will have
+ * to setup.
  *
  * The user (in the parent) will be called back (confirm_cb) every
  * time that xenstore path is modified.
@@ -1607,6 +1608,24 @@ _hidden int libxl__spawn_spawn(libxl__egc *egc, libxl__spawn_state *spawn);
  */
 _hidden void libxl__spawn_initiate_detach(libxl__gc *gc, libxl__spawn_state*);
 
+/*
+ * libxl__spawn_initiate_failure - Propagate failure from the caller to the
+ * callee.
+ *
+ * Works by killing the intermediate process from spawn_spawn.
+ * After this function returns, failures will be reported via failure_cb.
+ *
+ * This is not synchronous: there will be a further callback when
+ * the detach is complete.
+ *
+ * Logs errors.
+ *
+ * The spawn state must be Attached entry and will be Attached Failed
+ * on return.
+ */
+_hidden void libxl__spawn_initiate_failure(libxl__gc *gc,
+                                           libxl__spawn_state *ss, int rc);
+
 /*
  * If successful, this should return 0.
  *
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 26/32] libxl_dm: Pre-open QMP socket for QEMU
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (24 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 25/32] libxl_exec: Add libxl__spawn_initiate_failure Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-02 15:00   ` Roger Pau Monné
  2018-07-27 14:06 ` [PATCH v4 27/32] libxl: QEMU startup sync based on QMP Anthony PERARD
                   ` (5 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

When starting QEMU with dm_restrict=1, pre-open the QMP socket before
exec QEMU. That socket will be usefull to findout if QEMU is ready, and
pre-opening it means that libxl can connect to it without waiting for
QEMU to create it.

The pre-openning is conditionnal, based on the use of dm_restrict
because it is using a new command line option of QEMU, and dm_restrict
support in QEMU is newer.

-chardev socket,fd=X is available with QEMU 2.12, since commit:
> char: allow passing pre-opened socket file descriptor at startup
> 0935700f8544033ebbd41e1f13cd528f8a58d24d

dm_restrict will be available in QEMU 3.0.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---

Notes:
    v4:
        separate the logic to open a socket into a function.
        Use libxl__prepare_sockaddr_un() to check path size

 tools/libxl/libxl_dm.c | 86 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 77 insertions(+), 9 deletions(-)

diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index 5c28a0ced4..9e3e501457 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -24,6 +24,8 @@
 #include <sys/types.h>
 #include <pwd.h>
 #include <grp.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 
 static const char *libxl_tapif_script(libxl__gc *gc)
 {
@@ -915,12 +917,58 @@ const char *libxl__qemu_qmp_path(libxl__gc *gc, int domid)
     return GCSPRINTF("%s/qmp-libxl-%d", libxl__run_dir_path(), domid);
 }
 
+static int libxl__pre_open_qmp_socket(libxl__gc *gc, int domid, int *fd_r)
+{
+    int rc;
+    int fd = -1;
+    struct sockaddr_un un;
+    const char *path;
+
+    path = libxl__qemu_qmp_path(gc, domid);
+
+    fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (fd < 0) {
+        LOGED(ERROR, domid, "socket() failed");
+        return ERROR_FAIL;
+    }
+
+    rc = libxl__prepare_sockaddr_un(gc, &un, path, "QEMU's QMP socket");
+    if (rc)
+        goto out;
+
+    if (unlink(path) < 0 && errno != ENOENT) {
+        LOGED(ERROR, domid, "unlink('%s') failed", path);
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    if (bind(fd, (struct sockaddr*) &un, sizeof(un)) < 0) {
+        LOGED(ERROR, domid, "bind('%s') failed", path);
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    if (listen(fd, 1) < 0) {
+        LOGED(ERROR, domid, "listen() failed");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    *fd_r = fd;
+    rc = 0;
+
+out:
+    if (rc && fd >= 0)
+        close(fd);
+    return rc;
+}
+
 static int libxl__build_device_model_args_new(libxl__gc *gc,
                                         const char *dm, int guest_domid,
                                         const libxl_domain_config *guest_config,
                                         char ***args, char ***envs,
                                         const libxl__domain_build_state *state,
-                                        int *dm_state_fd)
+                                        int *dm_state_fd, int *dm_monitor_fd)
 {
     const libxl_domain_create_info *c_info = &guest_config->c_info;
     const libxl_domain_build_info *b_info = &guest_config->b_info;
@@ -949,10 +997,25 @@ static int libxl__build_device_model_args_new(libxl__gc *gc,
                       GCSPRINTF("%d", guest_domid), NULL);
 
     flexarray_append(dm_args, "-chardev");
-    flexarray_append(dm_args,
-                     GCSPRINTF("socket,id=libxl-cmd,"
-                               "path=%s,server,nowait",
-                               libxl__qemu_qmp_path(gc, guest_domid)));
+    /* If we have to use dm_restrict, QEMU need to be new enough and will have
+     * the new interface where we can pre-open the QMP socket. */
+    if (libxl_defbool_val(b_info->dm_restrict))
+    {
+        int rc;
+
+        rc = libxl__pre_open_qmp_socket(gc, guest_domid, dm_monitor_fd);
+        if (rc)
+            return rc;
+
+        flexarray_append(dm_args,
+                         GCSPRINTF("socket,id=libxl-cmd,fd=%d,server,nowait",
+                                   *dm_monitor_fd));
+    } else {
+        flexarray_append(dm_args,
+                         GCSPRINTF("socket,id=libxl-cmd,"
+                                   "path=%s,server,nowait",
+                                   libxl__qemu_qmp_path(gc, guest_domid)));
+    }
 
     flexarray_append(dm_args, "-no-shutdown");
     flexarray_append(dm_args, "-mon");
@@ -1731,7 +1794,8 @@ static int libxl__build_device_model_args(libxl__gc *gc,
                                         const libxl_domain_config *guest_config,
                                         char ***args, char ***envs,
                                         const libxl__domain_build_state *state,
-                                        int *dm_state_fd)
+                                        int *dm_state_fd,
+                                        int *dm_monitor_fd)
 /* dm_state_fd may be NULL iff caller knows we are using old stubdom
  * and therefore will be passing a filename rather than a fd. */
 {
@@ -1744,10 +1808,11 @@ static int libxl__build_device_model_args(libxl__gc *gc,
     case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
         assert(dm_state_fd != NULL);
         assert(*dm_state_fd < 0);
+        assert(dm_monitor_fd != NULL);
         return libxl__build_device_model_args_new(gc, dm,
                                                   guest_domid, guest_config,
                                                   args, envs,
-                                                  state, dm_state_fd);
+                                                  state, dm_state_fd, dm_monitor_fd);
     default:
         LOGED(ERROR, guest_domid, "unknown device model version %d",
               guest_config->b_info.device_model_version);
@@ -1968,7 +2033,7 @@ void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state *sdss)
 
     ret = libxl__build_device_model_args(gc, "stubdom-dm", guest_domid,
                                          guest_config, &args, NULL,
-                                         d_state, NULL);
+                                         d_state, NULL, NULL);
     if (ret) {
         ret = ERROR_FAIL;
         goto out;
@@ -2254,6 +2319,7 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss)
     char **pass_stuff;
     const char *dm;
     int dm_state_fd = -1;
+    int dm_monitor_fd = -1;
 
     if (libxl_defbool_val(b_info->device_model_stubdomain)) {
         abort();
@@ -2271,7 +2337,8 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss)
     }
     rc = libxl__build_device_model_args(gc, dm, domid, guest_config,
                                           &args, &envs, state,
-                                          &dm_state_fd);
+                                          &dm_state_fd,
+                                          &dm_monitor_fd);
     if (rc)
         goto out;
 
@@ -2369,6 +2436,7 @@ out_close:
     if (logfile_w >= 0) close(logfile_w);
 out:
     if (dm_state_fd >= 0) close(dm_state_fd);
+    if (dm_monitor_fd >= 0) close(dm_monitor_fd);
     if (rc)
         device_model_spawn_outcome(egc, dmss, rc);
 }
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 27/32] libxl: QEMU startup sync based on QMP
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (25 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 26/32] libxl_dm: Pre-open QMP socket for QEMU Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-02 15:06   ` Roger Pau Monné
  2018-07-27 14:06 ` [PATCH v4 28/32] libxl_qmp: Store advertised QEMU version in libxl__ev_qmp Anthony PERARD
                   ` (4 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

This is only activated when dm_restrict=1, as explained in the previous
patch "libxl_dm: Pre-open QMP socket for QEMU"

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---

Notes:
    v4:
        moved to libxl__dm_spawn_* from libxl__spawn_*

 tools/libxl/libxl_dm.c       | 52 ++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_internal.h |  1 +
 2 files changed, 53 insertions(+)

diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index 9e3e501457..0c11e96a5d 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -2290,6 +2290,8 @@ static void device_model_startup_failed(libxl__egc *egc,
                                         int rc);
 static void device_model_detached(libxl__egc *egc,
                                   libxl__spawn_state *spawn);
+static void device_model_qmp_cb(libxl__egc *egc, libxl__ev_qmp *ev,
+                                const libxl__json_object *response, int rc);
 
 /* our "next step" function, called from those callbacks and elsewhere */
 static void device_model_spawn_outcome(libxl__egc *egc,
@@ -2421,6 +2423,17 @@ retry_transaction:
     spawn->failure_cb = device_model_startup_failed;
     spawn->detached_cb = device_model_detached;
 
+    libxl__ev_qmp_init(&dmss->qmp);
+    if (dm_monitor_fd >= 0) {
+        /* There is a valid QMP socket available now,
+         * use it to find out when QEMU is ready */
+        dmss->qmp.callback = device_model_qmp_cb;
+        dmss->qmp.domid = domid;
+        dmss->qmp.cfd = NULL;
+        rc = libxl__ev_qmp_send(gc, &dmss->qmp, "query-status", NULL);
+        if (rc) goto out_close;
+    }
+
     rc = libxl__spawn_spawn(egc, spawn);
     if (rc < 0)
         goto out_close;
@@ -2490,6 +2503,43 @@ static void device_model_detached(libxl__egc *egc,
     device_model_spawn_outcome(egc, dmss, 0);
 }
 
+static void device_model_qmp_cb(libxl__egc *egc, libxl__ev_qmp *ev,
+                                const libxl__json_object *response,
+                                int rc)
+{
+    EGC_GC;
+    libxl__dm_spawn_state *dmss = CONTAINER_OF(ev, *dmss, qmp);
+    const libxl__json_object *o;
+    const char *status;
+
+    libxl__ev_qmp_dispose(gc, ev);
+
+    if (rc)
+        goto failed;
+
+    o = libxl__json_map_get("status", response, JSON_STRING);
+    if (!o) {
+        LOGD(DEBUG, ev->domid, "QMP unexpected response");
+        rc = ERROR_FAIL;
+        goto failed;
+    }
+    status = libxl__json_object_get_string(o);
+    if (!strcmp(status, "running")) {
+        /* success */
+    } else {
+        LOGD(DEBUG, ev->domid, "Unexpected QEMU status: %s", status);
+        rc = ERROR_FAIL;
+        goto failed;
+    }
+
+    libxl__spawn_initiate_detach(gc, &dmss->spawn);
+    return;
+
+failed:
+    LOGD(ERROR, ev->domid, "QEMU did not start properly, rc=%d", rc);
+    libxl__spawn_initiate_failure(gc, &dmss->spawn, rc);
+}
+
 static void device_model_spawn_outcome(libxl__egc *egc,
                                        libxl__dm_spawn_state *dmss,
                                        int rc)
@@ -2513,6 +2563,8 @@ static void device_model_spawn_outcome(libxl__egc *egc,
         }
     }
 
+    libxl__ev_qmp_dispose(gc, &dmss->qmp);
+
  out:
     dmss->callback(egc, dmss, rc);
 }
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index b94657a7f0..01c3868748 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -3893,6 +3893,7 @@ struct libxl__dm_spawn_state {
     libxl_domain_config *guest_config;
     libxl__domain_build_state *build_state; /* relates to guest_domid */
     libxl__dm_spawn_cb *callback;
+    libxl__ev_qmp qmp;
 };
 
 _hidden void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state*);
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 28/32] libxl_qmp: Store advertised QEMU version in libxl__ev_qmp
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (26 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 27/32] libxl: QEMU startup sync based on QMP Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-02 15:08   ` Roger Pau Monné
  2018-07-27 14:06 ` [PATCH v4 29/32] libxl: Change libxl__domain_suspend_device_model() to be async Anthony PERARD
                   ` (3 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

This will be used in a later patch.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
 tools/libxl/libxl_internal.h |  7 +++++++
 tools/libxl/libxl_qmp.c      | 16 ++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 01c3868748..4fa54cdb6a 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -432,6 +432,13 @@ struct libxl__ev_qmp {
     libxl__ev_qmp_callback *callback;
     libxl__carefd *cfd; /* set to send a fd with the command, NULL otherwise */
 
+    /* read-only when Connected */
+    struct {
+        int major;
+        int minor;
+        int micro;
+    } qemu_version;
+
     /* remaining fields are private to libxl_ev_qmp_* */
 
     int id;
diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index d7aedb56a8..332dcf2069 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -1444,12 +1444,28 @@ static int qmp_ev_handle_message(libxl__egc *egc,
                                  const libxl__json_object *resp)
 {
     EGC_GC;
+    const libxl__json_object *o;
     libxl__qmp_message_type type = qmp_response_type(resp);
 
     switch (type) {
     case LIBXL__QMP_MESSAGE_TYPE_QMP:
         /* greeting message */
         assert(ev->qmp_state == qmp_state_connecting);
+
+        /* Store advertised QEMU version */
+        o = libxl__json_map_get("QMP", resp, JSON_MAP);
+        o = libxl__json_map_get("version", o, JSON_MAP);
+        o = libxl__json_map_get("qemu", o, JSON_MAP);
+        ev->qemu_version.major = libxl__json_object_get_integer(
+            libxl__json_map_get("major", o, JSON_INTEGER));
+        ev->qemu_version.minor = libxl__json_object_get_integer(
+            libxl__json_map_get("minor", o, JSON_INTEGER));
+        ev->qemu_version.micro = libxl__json_object_get_integer(
+            libxl__json_map_get("micro", o, JSON_INTEGER));
+        LOGD(DEBUG, ev->domid, "QEMU version: %d.%d.%d",
+             ev->qemu_version.major, ev->qemu_version.minor,
+             ev->qemu_version.micro);
+
         ev->qmp_state = qmp_state_greeting;
         /* Allow qmp_ev_callback_writable to be called in order to send
          * qmp_capabilities */
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 29/32] libxl: Change libxl__domain_suspend_device_model() to be async.
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (27 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 28/32] libxl_qmp: Store advertised QEMU version in libxl__ev_qmp Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-02 15:15   ` Roger Pau Monné
  2018-07-27 14:06 ` [PATCH v4 30/32] libxl: Re-implement domain_suspend_device_model using libxl__ev_qmp Anthony PERARD
                   ` (2 subsequent siblings)
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

This create an extra step for the two calls sites of the function.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

---
libxl_domain_soft_reset() haven't been tested, as it doesn't appear to
possible to call the function from xl.
---
 tools/libxl/libxl_create.c      | 30 ++++++++++++++++++++++--------
 tools/libxl/libxl_dom_suspend.c |  8 ++++++--
 tools/libxl/libxl_internal.h    |  4 +++-
 3 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 1ccb3e35d3..3181c57c30 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -1755,6 +1755,9 @@ error:
     domcreate_complete(egc, &cdcs->dcs, rc);
 }
 
+static void soft_reset_dm_suspended(libxl__egc *egc,
+                                    libxl__domain_suspend_state *dsps,
+                                    int rc);
 static int do_domain_soft_reset(libxl_ctx *ctx,
                                 libxl_domain_config *d_config,
                                 uint32_t domid_soft_reset,
@@ -1837,30 +1840,41 @@ static int do_domain_soft_reset(libxl_ctx *ctx,
         goto out;
     }
 
-    rc = libxl__domain_suspend_device_model(gc, &dss->dsps);
+    dss->dsps.ao = ao;
+    dss->dsps.callback_device_model_done = soft_reset_dm_suspended;
+    rc = libxl__domain_suspend_device_model(egc, &dss->dsps);
     if (rc) {
         LOGD(ERROR, domid_soft_reset, "failed to suspend device model.");
         goto out;
     }
 
+    return AO_INPROGRESS;
+
+ out:
+    return AO_CREATE_FAIL(rc);
+}
+
+static void soft_reset_dm_suspended(libxl__egc *egc,
+                                    libxl__domain_suspend_state *dsps,
+                                    int rc)
+{
+    STATE_AO_GC(dsps->ao);
+    libxl__domain_soft_reset_state *srs = CONTAINER_OF(dsps, *srs, dss.dsps);
+    libxl__app_domain_create_state *cdcs = &srs->cdcs;
+
     /*
      * Ask all backends to disconnect by removing the domain from
      * xenstore. On the creation path the domain will be introduced to
      * xenstore again with probably different store/console/...
      * channels.
      */
-    xs_release_domain(ctx->xsh, cdcs->dcs.domid_soft_reset);
+    xs_release_domain(CTX->xsh, cdcs->dcs.domid_soft_reset);
 
     srs->dds.ao = ao;
-    srs->dds.domid = domid_soft_reset;
+    srs->dds.domid = cdcs->dcs.domid_soft_reset;
     srs->dds.callback = domain_soft_reset_cb;
     srs->dds.soft_reset = true;
     libxl__domain_destroy(egc, &srs->dds);
-
-    return AO_INPROGRESS;
-
- out:
-    return AO_CREATE_FAIL(rc);
 }
 
 static void domain_create_cb(libxl__egc *egc,
diff --git a/tools/libxl/libxl_dom_suspend.c b/tools/libxl/libxl_dom_suspend.c
index 1e904bae8a..51c432a00a 100644
--- a/tools/libxl/libxl_dom_suspend.c
+++ b/tools/libxl/libxl_dom_suspend.c
@@ -68,9 +68,10 @@ out:
 
 /*----- callbacks, called by xc_domain_save -----*/
 
-int libxl__domain_suspend_device_model(libxl__gc *gc,
+int libxl__domain_suspend_device_model(libxl__egc *egc,
                                        libxl__domain_suspend_state *dsps)
 {
+    STATE_AO_GC(dsps->ao);
     int ret = 0;
     uint32_t const domid = dsps->domid;
     const char *const filename = dsps->dm_savefile;
@@ -94,6 +95,7 @@ int libxl__domain_suspend_device_model(libxl__gc *gc,
         return ERROR_INVAL;
     }
 
+    dsps->callback_device_model_done(egc, dsps, ret);
     return ret;
 }
 
@@ -378,13 +380,15 @@ static void domain_suspend_common_guest_suspended(libxl__egc *egc,
     libxl__ev_time_deregister(gc, &dsps->guest_timeout);
 
     if (dsps->type == LIBXL_DOMAIN_TYPE_HVM) {
-        rc = libxl__domain_suspend_device_model(gc, dsps);
+        dsps->callback_device_model_done = domain_suspend_common_done;
+        rc = libxl__domain_suspend_device_model(egc, dsps);
         if (rc) {
             LOGD(ERROR, dsps->domid,
                  "libxl__domain_suspend_device_model failed ret=%d", rc);
             domain_suspend_common_done(egc, dsps, rc);
             return;
         }
+        return;
     }
     domain_suspend_common_done(egc, dsps, 0);
 }
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 4fa54cdb6a..5b65cdbe40 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -3408,6 +3408,8 @@ struct libxl__domain_suspend_state {
     libxl__ev_time guest_timeout;
 
     const char *dm_savefile;
+    void (*callback_device_model_done)(libxl__egc*,
+                                 struct libxl__domain_suspend_state*, int ok);
     void (*callback_common_done)(libxl__egc*,
                                  struct libxl__domain_suspend_state*, int ok);
 };
@@ -4025,7 +4027,7 @@ static inline bool libxl__save_helper_inuse(const libxl__save_helper_state *shs)
 }
 
 /* Each time the dm needs to be saved, we must call suspend and then save */
-_hidden int libxl__domain_suspend_device_model(libxl__gc *gc,
+_hidden int libxl__domain_suspend_device_model(libxl__egc *egc,
                                            libxl__domain_suspend_state *dsps);
 
 _hidden const char *libxl__device_model_savefile(libxl__gc *gc, uint32_t domid);
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 30/32] libxl: Re-implement domain_suspend_device_model using libxl__ev_qmp
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (28 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 29/32] libxl: Change libxl__domain_suspend_device_model() to be async Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-02 15:38   ` Roger Pau Monné
  2018-07-27 14:06 ` [PATCH v4 31/32] libxl_disk: Cut libxl_cdrom_insert into step Anthony PERARD
  2018-07-27 14:06 ` [PATCH v4 32/32] libxl_disk: Have libxl_cdrom_insert use libxl__ev_qmp Anthony PERARD
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

The re-implementation is done because we want to be able to send the
file description that QEMU can use to save its state. When QEMU is
restricted, it would not be able to write to a path.

This replace both libxl__qmp_stop() and libxl__qmp_save().

qmp_qemu_check_version() was only used by libxl__qmp_save(), so it is
replace by a version using libxl__ev_qmp instead.

Coding style fixed in libxl__domain_suspend_device_model() for the
return value.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---

Notes:
    v4:
        This patch replace the patch "libxl_qmp: Have QEMU save its state to a file
        descriptor" from previous version of the serie.
        It uses libxl__ev_qmp instead.

 tools/libxl/libxl_dom_suspend.c |  16 ++--
 tools/libxl/libxl_internal.h    |   9 +-
 tools/libxl/libxl_qmp.c         | 152 +++++++++++++++++++++++++-------
 3 files changed, 129 insertions(+), 48 deletions(-)

diff --git a/tools/libxl/libxl_dom_suspend.c b/tools/libxl/libxl_dom_suspend.c
index 51c432a00a..0f4e1be115 100644
--- a/tools/libxl/libxl_dom_suspend.c
+++ b/tools/libxl/libxl_dom_suspend.c
@@ -34,6 +34,7 @@ int libxl__domain_suspend_init(libxl__egc *egc,
     libxl__ev_evtchn_init(&dsps->guest_evtchn);
     libxl__ev_xswatch_init(&dsps->guest_watch);
     libxl__ev_time_init(&dsps->guest_timeout);
+    libxl__ev_qmp_init(&dsps->qmp);
 
     if (type == LIBXL_DOMAIN_TYPE_INVALID) goto out;
     dsps->type = type;
@@ -72,7 +73,7 @@ int libxl__domain_suspend_device_model(libxl__egc *egc,
                                        libxl__domain_suspend_state *dsps)
 {
     STATE_AO_GC(dsps->ao);
-    int ret = 0;
+    int rc;
     uint32_t const domid = dsps->domid;
     const char *const filename = dsps->dm_savefile;
 
@@ -81,22 +82,18 @@ int libxl__domain_suspend_device_model(libxl__egc *egc,
         LOGD(DEBUG, domid, "Saving device model state to %s", filename);
         libxl__qemu_traditional_cmd(gc, domid, "save");
         libxl__wait_for_device_model_deprecated(gc, domid, "paused", NULL, NULL, NULL);
+        dsps->callback_device_model_done(egc, dsps, 0);
+        rc = 0;
         break;
     }
     case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
-        if (libxl__qmp_stop(gc, domid))
-            return ERROR_FAIL;
-        /* Save DM state into filename */
-        ret = libxl__qmp_save(gc, domid, filename, dsps->live);
-        if (ret)
-            unlink(filename);
+        rc = libxl__qmp_suspend_save(gc, dsps);
         break;
     default:
         return ERROR_INVAL;
     }
 
-    dsps->callback_device_model_done(egc, dsps, ret);
-    return ret;
+    return rc;
 }
 
 static void domain_suspend_common_wait_guest(libxl__egc *egc,
@@ -402,6 +399,7 @@ static void domain_suspend_common_done(libxl__egc *egc,
     libxl__ev_evtchn_cancel(gc, &dsps->guest_evtchn);
     libxl__ev_xswatch_deregister(gc, &dsps->guest_watch);
     libxl__ev_time_deregister(gc, &dsps->guest_timeout);
+    libxl__ev_qmp_dispose(gc, &dsps->qmp);
     dsps->callback_common_done(egc, dsps, rc);
 }
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 5b65cdbe40..cafe8b5733 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1942,13 +1942,8 @@ _hidden int libxl__qmp_pci_del(libxl__gc *gc, int domid,
                                libxl_device_pci *pcidev);
 /* Resume hvm domain */
 _hidden int libxl__qmp_system_wakeup(libxl__gc *gc, int domid);
-/* Suspend QEMU. */
-_hidden int libxl__qmp_stop(libxl__gc *gc, int domid);
 /* Resume QEMU. */
 _hidden int libxl__qmp_resume(libxl__gc *gc, int domid);
-/* Save current QEMU state into fd. */
-_hidden int libxl__qmp_save(libxl__gc *gc, int domid, const char *filename,
-                            bool live);
 /* Load current QEMU state from file. */
 _hidden int libxl__qmp_restore(libxl__gc *gc, int domid, const char *filename);
 /* Set dirty bitmap logging status */
@@ -3406,6 +3401,7 @@ struct libxl__domain_suspend_state {
     libxl__xswait_state pvcontrol;
     libxl__ev_xswatch guest_watch;
     libxl__ev_time guest_timeout;
+    libxl__ev_qmp qmp;
 
     const char *dm_savefile;
     void (*callback_device_model_done)(libxl__egc*,
@@ -3417,6 +3413,9 @@ int libxl__domain_suspend_init(libxl__egc *egc,
                                libxl__domain_suspend_state *dsps,
                                libxl_domain_type type);
 
+_hidden int libxl__qmp_suspend_save(libxl__gc *gc,
+                                    libxl__domain_suspend_state *dsps);
+
 struct libxl__domain_save_state {
     /* set by caller of libxl__domain_save */
     libxl__ao *ao;
diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 332dcf2069..07203a6fe6 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -398,13 +398,14 @@ static int qmp_handle_response(libxl__gc *gc, libxl__qmp_handler *qmp,
     return 0;
 }
 
-static bool qmp_qemu_check_version(libxl__qmp_handler *qmp, int major,
-                                   int minor, int micro)
+static bool qmp_ev_qemu_check_version(libxl__ev_qmp *ev, int major,
+                                      int minor, int micro)
 {
-    return qmp->version.major > major ||
-        (qmp->version.major == major &&
-            (qmp->version.minor > minor ||
-             (qmp->version.minor == minor && qmp->version.micro >= micro)));
+    return ev->qemu_version.major > major ||
+        (ev->qemu_version.major == major &&
+            (ev->qemu_version.minor > minor ||
+             (ev->qemu_version.minor == minor &&
+              ev->qemu_version.micro >= micro)));
 }
 
 /*
@@ -1017,29 +1018,6 @@ int libxl__qmp_system_wakeup(libxl__gc *gc, int domid)
     return qmp_run_command(gc, domid, "system_wakeup", NULL, NULL, NULL);
 }
 
-int libxl__qmp_save(libxl__gc *gc, int domid, const char *filename, bool live)
-{
-    libxl__json_object *args = NULL;
-    libxl__qmp_handler *qmp = NULL;
-    int rc;
-
-    qmp = libxl__qmp_initialize(gc, domid);
-    if (!qmp)
-        return ERROR_FAIL;
-
-    qmp_parameters_add_string(gc, &args, "filename", (char *)filename);
-
-    /* live parameter was added to QEMU 2.11. It signal QEMU that the save
-     * operation is for a live migration rather that for taking a snapshot. */
-    if (qmp_qemu_check_version(qmp, 2, 11, 0))
-        qmp_parameters_add_bool(gc, &args, "live", live);
-
-    rc = qmp_synchronous_send(qmp, "xen-save-devices-state", args,
-                              NULL, NULL, qmp->timeout);
-    libxl__qmp_close(qmp);
-    return rc;
-}
-
 int libxl__qmp_restore(libxl__gc *gc, int domid, const char *state_file)
 {
     libxl__json_object *args = NULL;
@@ -1068,11 +1046,6 @@ static int qmp_change(libxl__gc *gc, libxl__qmp_handler *qmp,
     return rc;
 }
 
-int libxl__qmp_stop(libxl__gc *gc, int domid)
-{
-    return qmp_run_command(gc, domid, "stop", NULL, NULL, NULL);
-}
-
 int libxl__qmp_resume(libxl__gc *gc, int domid)
 {
     return qmp_run_command(gc, domid, "cont", NULL, NULL, NULL);
@@ -1312,6 +1285,117 @@ int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
     return ret;
 }
 
+
+/*
+ * Function using libxl__ev_qmp
+ */
+
+static void dm_stopped(libxl__egc *egc, libxl__ev_qmp *ev,
+                       const libxl__json_object *response, int rc);
+static void dm_state_fd_ready(libxl__egc *egc, libxl__ev_qmp *ev,
+                              const libxl__json_object *response, int rc);
+static void dm_state_saved(libxl__egc *egc, libxl__ev_qmp *ev,
+                           const libxl__json_object *response, int rc);
+int libxl__qmp_suspend_save(libxl__gc *gc, libxl__domain_suspend_state *dsps)
+{
+    libxl__ev_qmp *ev = &dsps->qmp;
+    uint32_t const domid = dsps->domid;
+
+    ev->domid = domid;
+    ev->callback = dm_stopped;
+    ev->cfd = NULL;
+
+    return libxl__ev_qmp_send(gc, ev, "stop", NULL);
+}
+
+static void dm_stopped(libxl__egc *egc, libxl__ev_qmp *ev,
+                       const libxl__json_object *response, int rc)
+{
+    EGC_GC;
+    libxl__domain_suspend_state *dsps = CONTAINER_OF(ev, *dsps, qmp);
+    const char *const filename = dsps->dm_savefile;
+    uint32_t const domid = ev->domid;
+
+    if (rc)
+        goto out;
+
+    libxl__carefd_begin();
+    ev->cfd = libxl__carefd_opened(CTX,
+                                 open(filename, O_WRONLY | O_CREAT, 0600));
+    if (!ev->cfd) {
+        LOGED(ERROR, domid, "Failed to open file %s for QEMU", filename);
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    ev->callback = dm_state_fd_ready;
+    rc = libxl__ev_qmp_send(gc, ev, "add-fd", NULL);
+    if (rc)
+        goto out;
+
+    return;
+out:
+    if (ev->cfd) {
+        libxl__carefd_close(ev->cfd);
+        unlink(filename);
+        ev->cfd = NULL;
+    }
+    dsps->callback_device_model_done(egc, dsps, rc);
+}
+
+static void dm_state_fd_ready(libxl__egc *egc, libxl__ev_qmp *ev,
+                              const libxl__json_object *response, int rc)
+{
+    EGC_GC;
+    libxl__domain_suspend_state *dsps = CONTAINER_OF(ev, *dsps, qmp);
+    libxl__json_object *args = NULL;
+    const libxl__json_object *o;
+    int fdset;
+
+    libxl__carefd_close(ev->cfd);
+    ev->cfd = NULL;
+
+    if (rc)
+        goto out;
+
+    o = libxl__json_map_get("fdset-id", response, JSON_INTEGER);
+    if (!o) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    fdset = libxl__json_object_get_integer(o);
+
+    ev->callback = dm_state_saved;
+
+    if (qmp_ev_qemu_check_version(ev, 2, 11, 0))
+        qmp_parameters_add_bool(gc, &args, "live", dsps->live);
+    QMP_PARAMETERS_SPRINTF(&args, "filename", "/dev/fdset/%d", fdset);
+    rc = libxl__ev_qmp_send(gc, ev, "xen-save-devices-state", args);
+    if (rc)
+        goto out;
+
+    return;
+out:
+    if (rc)
+        unlink(dsps->dm_savefile);
+    dsps->callback_device_model_done(egc, dsps, rc);
+}
+
+static void dm_state_saved(libxl__egc *egc, libxl__ev_qmp *ev,
+                           const libxl__json_object *response, int rc)
+{
+    EGC_GC;
+    libxl__domain_suspend_state *dsps = CONTAINER_OF(ev, *dsps, qmp);
+
+    if (rc)
+        unlink(dsps->dm_savefile);
+
+    libxl__ev_qmp_dispose(gc, ev);
+    dsps->callback_device_model_done(egc, dsps, rc);
+}
+
+
+
 /* ------------ Implementation of libxl__ev_qmp ---------------- */
 
 /* hard coded message ID used for capability negociation */
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 31/32] libxl_disk: Cut libxl_cdrom_insert into step
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (29 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 30/32] libxl: Re-implement domain_suspend_device_model using libxl__ev_qmp Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  2018-08-02 15:50   ` Roger Pau Monné
  2018-07-27 14:06 ` [PATCH v4 32/32] libxl_disk: Have libxl_cdrom_insert use libxl__ev_qmp Anthony PERARD
  31 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

This is to prepare libxl_cdrom_insert to be able to send commands to
QEMU via the libxl__ev_qmp. The next patch is going to make use of it.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
 tools/libxl/libxl_disk.c | 194 +++++++++++++++++++++++++++------------
 1 file changed, 137 insertions(+), 57 deletions(-)

diff --git a/tools/libxl/libxl_disk.c b/tools/libxl/libxl_disk.c
index e9eceb65e3..c759179628 100644
--- a/tools/libxl/libxl_disk.c
+++ b/tools/libxl/libxl_disk.c
@@ -661,31 +661,55 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
     return rc;
 }
 
+typedef struct {
+    libxl__ao *ao;
+    libxl_domain_config d_config;
+    const char *be_path;
+    const char *libxl_path;
+    libxl_device_disk *disk;
+    libxl_device_disk disk_empty;
+    libxl_device_disk disk_saved;
+    int dm_ver;
+    int domid;
+    libxl__domain_userdata_lock *lock;
+} libxl__cdrom_insert_state;
+static void cdrom_insert_ejected(libxl__egc *egc,
+                                 libxl__cdrom_insert_state *cis);
+static void cdrom_insert_inserted(libxl__egc *egc,
+                                  libxl__cdrom_insert_state *cis);
+static void cdrom_insert_done(libxl__egc *egc,
+                              libxl__cdrom_insert_state *cis,
+                              int rc);
+
 int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
                        const libxl_asyncop_how *ao_how)
 {
     AO_CREATE(ctx, domid, ao_how);
     int num = 0, i;
-    libxl_device_disk *disks = NULL, disk_saved, disk_empty;
-    libxl_domain_config d_config;
-    int rc, dm_ver;
+    libxl_device_disk *disks = NULL, *disk_saved, *disk_empty;
+    int rc;
     libxl__device device;
-    const char *be_path, *libxl_path;
-    char * tmp;
-    libxl__domain_userdata_lock *lock = NULL;
-    xs_transaction_t t = XBT_NULL;
-    flexarray_t *insert = NULL, *empty = NULL;
+    libxl__cdrom_insert_state *cis;
 
-    libxl_domain_config_init(&d_config);
-    libxl_device_disk_init(&disk_empty);
-    libxl_device_disk_init(&disk_saved);
-    libxl_device_disk_copy(ctx, &disk_saved, disk);
+    GCNEW(cis);
+    cis->ao = ao;
+    cis->domid = domid;
+    cis->disk = disk;
 
-    disk_empty.format = LIBXL_DISK_FORMAT_EMPTY;
-    disk_empty.vdev = libxl__strdup(NOGC, disk->vdev);
-    disk_empty.pdev_path = libxl__strdup(NOGC, "");
-    disk_empty.is_cdrom = 1;
-    libxl__device_disk_setdefault(gc, domid, &disk_empty, false);
+    disk_empty = &cis->disk_empty;
+    disk_saved = &cis->disk_saved;
+
+
+    libxl_domain_config_init(&cis->d_config);
+    libxl_device_disk_init(disk_empty);
+    libxl_device_disk_init(disk_saved);
+    libxl_device_disk_copy(ctx, disk_saved, disk);
+
+    disk_empty->format = LIBXL_DISK_FORMAT_EMPTY;
+    disk_empty->vdev = libxl__strdup(NOGC, disk->vdev);
+    disk_empty->pdev_path = libxl__strdup(NOGC, "");
+    disk_empty->is_cdrom = 1;
+    libxl__device_disk_setdefault(gc, domid, disk_empty, false);
 
     libxl_domain_type type = libxl__domain_type(gc, domid);
     if (type == LIBXL_DOMAIN_TYPE_INVALID) {
@@ -704,8 +728,8 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
         goto out;
     }
 
-    dm_ver = libxl__device_model_version_running(gc, domid);
-    if (dm_ver == -1) {
+    cis->dm_ver = libxl__device_model_version_running(gc, domid);
+    if (cis->dm_ver == -1) {
         LOGD(ERROR, domid, "Cannot determine device model version");
         rc = ERROR_FAIL;
         goto out;
@@ -737,31 +761,14 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
     rc = libxl__device_from_disk(gc, domid, disk, &device);
     if (rc) goto out;
 
-    be_path = libxl__device_backend_path(gc, &device);
-    libxl_path = libxl__device_libxl_path(gc, &device);
-
-    insert = flexarray_make(gc, 4, 1);
-
-    flexarray_append_pair(insert, "type",
-                          libxl__device_disk_string_of_backend(disk->backend));
-    if (disk->format != LIBXL_DISK_FORMAT_EMPTY)
-        flexarray_append_pair(insert, "params",
-                        GCSPRINTF("%s:%s",
-                            libxl__device_disk_string_of_format(disk->format),
-                            disk->pdev_path));
-    else
-        flexarray_append_pair(insert, "params", "");
-
-    empty = flexarray_make(gc, 4, 1);
-    flexarray_append_pair(empty, "type",
-                          libxl__device_disk_string_of_backend(disk->backend));
-    flexarray_append_pair(empty, "params", "");
+    cis->be_path = libxl__device_backend_path(gc, &device);
+    cis->libxl_path = libxl__device_libxl_path(gc, &device);
 
     /* Note: CTX lock is already held at this point so lock hierarchy
      * is maintained.
      */
-    lock = libxl__lock_domain_userdata(gc, domid);
-    if (!lock) {
+    cis->lock = libxl__lock_domain_userdata(gc, domid);
+    if (!cis->lock) {
         rc = ERROR_LOCK_FAIL;
         goto out;
     }
@@ -769,11 +776,46 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
     /* We need to eject the original image first. This is implemented
      * by inserting empty media. JSON is not updated.
      */
-    if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
-        rc = libxl__qmp_insert_cdrom(gc, domid, &disk_empty);
+    if (cis->dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
+        rc = libxl__qmp_insert_cdrom(gc, domid, disk_empty);
         if (rc) goto out;
     }
 
+    cdrom_insert_ejected(egc, cis);
+
+    return AO_INPROGRESS;
+
+out:
+    libxl__device_list_free(&libxl__disk_devtype, disks, num);
+    cdrom_insert_done(egc, cis, rc);
+
+    if (rc) return AO_CREATE_FAIL(rc);
+    return AO_INPROGRESS;
+}
+
+static void cdrom_insert_ejected(libxl__egc *egc,
+                                 libxl__cdrom_insert_state *cis)
+{
+    STATE_AO_GC(cis->ao);
+    uint32_t domid = cis->domid;
+    int rc;
+    const char *be_path, *libxl_path;
+    char * tmp;
+    xs_transaction_t t = XBT_NULL;
+    flexarray_t *empty;
+
+    libxl_domain_config *d_config = &cis->d_config;
+    libxl_device_disk *disk = cis->disk;
+    libxl_device_disk *disk_saved = &cis->disk_saved;
+
+    be_path = cis->be_path;
+    libxl_path = cis->libxl_path;
+
+    empty = flexarray_make(gc, 4, 1);
+    flexarray_append_pair(empty, "type",
+                          libxl__device_disk_string_of_backend(disk->backend));
+    flexarray_append_pair(empty, "params", "");
+
     for (;;) {
         rc = libxl__xs_transaction_start(gc, &t);
         if (rc) goto out;
@@ -800,19 +842,55 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
         if (rc < 0) goto out;
     }
 
-    rc = libxl__get_domain_configuration(gc, domid, &d_config);
+    rc = libxl__get_domain_configuration(gc, domid, d_config);
     if (rc) goto out;
 
-    device_add_domain_config(gc, &d_config, &libxl__disk_devtype, &disk_saved);
+    device_add_domain_config(gc, d_config, &libxl__disk_devtype, disk_saved);
 
-    rc = libxl__dm_check_start(gc, &d_config, domid);
+    rc = libxl__dm_check_start(gc, d_config, domid);
     if (rc) goto out;
 
-    if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
+    if (cis->dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
         rc = libxl__qmp_insert_cdrom(gc, domid, disk);
         if (rc) goto out;
     }
 
+    cdrom_insert_inserted(egc, cis);
+
+    return;
+
+out:
+    libxl__xs_transaction_abort(gc, &t);
+    cdrom_insert_done(egc, cis, rc);
+}
+
+static void cdrom_insert_inserted(libxl__egc *egc,
+                                  libxl__cdrom_insert_state *cis)
+{
+    STATE_AO_GC(cis->ao);
+    uint32_t domid = cis->domid;
+    int rc;
+    const char *be_path, *libxl_path;
+    char * tmp;
+    xs_transaction_t t = XBT_NULL;
+    flexarray_t *insert;
+
+    libxl_device_disk *disk = cis->disk;
+    libxl_domain_config *d_config = &cis->d_config;
+    be_path = cis->be_path;
+    libxl_path = cis->libxl_path;
+
+    insert = flexarray_make(gc, 4, 1);
+    flexarray_append_pair(insert, "type",
+                          libxl__device_disk_string_of_backend(disk->backend));
+    if (disk->format != LIBXL_DISK_FORMAT_EMPTY)
+        flexarray_append_pair(insert, "params",
+                        GCSPRINTF("%s:%s",
+                            libxl__device_disk_string_of_format(disk->format),
+                            disk->pdev_path));
+    else
+        flexarray_append_pair(insert, "params", "");
+
     for (;;) {
         rc = libxl__xs_transaction_start(gc, &t);
         if (rc) goto out;
@@ -826,7 +904,7 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
             goto out;
         }
 
-        rc = libxl__set_domain_configuration(gc, domid, &d_config);
+        rc = libxl__set_domain_configuration(gc, domid, d_config);
         if (rc) goto out;
 
         char **kvs = libxl__xs_kvs_of_flexarray(gc, insert);
@@ -842,22 +920,24 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
         if (rc < 0) goto out;
     }
 
-    /* success, no actual async */
-    libxl__ao_complete(egc, ao, 0);
-
     rc = 0;
 
 out:
     libxl__xs_transaction_abort(gc, &t);
-    libxl__device_list_free(&libxl__disk_devtype, disks, num);
-    libxl_device_disk_dispose(&disk_empty);
-    libxl_device_disk_dispose(&disk_saved);
-    libxl_domain_config_dispose(&d_config);
+    cdrom_insert_done(egc, cis, rc);
+}
 
-    if (lock) libxl__unlock_domain_userdata(lock);
+static void cdrom_insert_done(libxl__egc *egc,
+                              libxl__cdrom_insert_state *cis,
+                              int rc)
+{
+    STATE_AO_GC(cis->ao);
 
-    if (rc) return AO_CREATE_FAIL(rc);
-    return AO_INPROGRESS;
+    libxl_domain_config_dispose(&cis->d_config);
+    libxl_device_disk_dispose(&cis->disk_empty);
+    libxl_device_disk_dispose(&cis->disk_saved);
+    if (cis->lock) libxl__unlock_domain_userdata(cis->lock);
+    libxl__ao_complete(egc, ao, rc);
 }
 
 /* libxl__alloc_vdev only works on the local domain, that is the domain
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v4 32/32] libxl_disk: Have libxl_cdrom_insert use libxl__ev_qmp
  2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
                   ` (30 preceding siblings ...)
  2018-07-27 14:06 ` [PATCH v4 31/32] libxl_disk: Cut libxl_cdrom_insert into step Anthony PERARD
@ 2018-07-27 14:06 ` Anthony PERARD
  31 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-07-27 14:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Anthony PERARD, Ian Jackson, Wei Liu

So when QEMU is involve, the operation will be asynchrone and will
finish later.

This path reimplement libxl__qmp_insert_cdrom to make use of the new
libxl__ev_qmp API.  It also open the cdrom in libxl and send the FD via
QMP, so QEMU doesn't need access permition on the cdrom file.

libxl__qmp_insert_cdrom() is now async, libxl_cdrom_insert() is updated
to make use of it.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---

Notes:
    v4:
        switch to the updated libxl__ev_qmp API

 tools/libxl/libxl_disk.c     |  42 +++++++++----
 tools/libxl/libxl_internal.h |  14 ++++-
 tools/libxl/libxl_qmp.c      | 117 +++++++++++++++++++++++++++++------
 3 files changed, 142 insertions(+), 31 deletions(-)

diff --git a/tools/libxl/libxl_disk.c b/tools/libxl/libxl_disk.c
index c759179628..eb086ed909 100644
--- a/tools/libxl/libxl_disk.c
+++ b/tools/libxl/libxl_disk.c
@@ -672,11 +672,14 @@ typedef struct {
     int dm_ver;
     int domid;
     libxl__domain_userdata_lock *lock;
+    libxl__qmp_insert_cdrom_state qics;
 } libxl__cdrom_insert_state;
 static void cdrom_insert_ejected(libxl__egc *egc,
-                                 libxl__cdrom_insert_state *cis);
+                                 libxl__qmp_insert_cdrom_state  *qics,
+                                 int rc);
 static void cdrom_insert_inserted(libxl__egc *egc,
-                                  libxl__cdrom_insert_state *cis);
+                                  libxl__qmp_insert_cdrom_state *qics,
+                                  int rc);
 static void cdrom_insert_done(libxl__egc *egc,
                               libxl__cdrom_insert_state *cis,
                               int rc);
@@ -777,12 +780,16 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
      * by inserting empty media. JSON is not updated.
      */
     if (cis->dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
-        rc = libxl__qmp_insert_cdrom(gc, domid, disk_empty);
+        libxl__qmp_insert_cdrom_state *qics = &cis->qics;
+        qics->domid = domid;
+        qics->disk = disk_empty;
+        qics->callback = cdrom_insert_ejected;
+        rc = libxl__qmp_insert_cdrom(gc, qics);
         if (rc) goto out;
+    } else {
+        cdrom_insert_ejected(egc, &cis->qics, 0);
     }
 
-    cdrom_insert_ejected(egc, cis);
-
     return AO_INPROGRESS;
 
 out:
@@ -794,11 +801,12 @@ out:
 }
 
 static void cdrom_insert_ejected(libxl__egc *egc,
-                                 libxl__cdrom_insert_state *cis)
+                                 libxl__qmp_insert_cdrom_state *qics,
+                                 int rc)
 {
+    libxl__cdrom_insert_state *cis = CONTAINER_OF(qics, *cis, qics);
     STATE_AO_GC(cis->ao);
     uint32_t domid = cis->domid;
-    int rc;
     const char *be_path, *libxl_path;
     char * tmp;
     xs_transaction_t t = XBT_NULL;
@@ -808,6 +816,9 @@ static void cdrom_insert_ejected(libxl__egc *egc,
     libxl_device_disk *disk = cis->disk;
     libxl_device_disk *disk_saved = &cis->disk_saved;
 
+    if (rc)
+        goto out;
+
     be_path = cis->be_path;
     libxl_path = cis->libxl_path;
 
@@ -851,12 +862,15 @@ static void cdrom_insert_ejected(libxl__egc *egc,
     if (rc) goto out;
 
     if (cis->dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
-        rc = libxl__qmp_insert_cdrom(gc, domid, disk);
+        qics->domid = domid;
+        qics->disk = disk;
+        qics->callback = cdrom_insert_inserted;
+        rc = libxl__qmp_insert_cdrom(gc, qics);
         if (rc) goto out;
+    } else {
+        cdrom_insert_inserted(egc, qics, 0);
     }
 
-    cdrom_insert_inserted(egc, cis);
-
     return;
 
 out:
@@ -865,11 +879,12 @@ out:
 }
 
 static void cdrom_insert_inserted(libxl__egc *egc,
-                                  libxl__cdrom_insert_state *cis)
+                                  libxl__qmp_insert_cdrom_state *qics,
+                                  int rc)
 {
+    libxl__cdrom_insert_state *cis = CONTAINER_OF(qics, *cis, qics);
     STATE_AO_GC(cis->ao);
     uint32_t domid = cis->domid;
-    int rc;
     const char *be_path, *libxl_path;
     char * tmp;
     xs_transaction_t t = XBT_NULL;
@@ -880,6 +895,9 @@ static void cdrom_insert_inserted(libxl__egc *egc,
     be_path = cis->be_path;
     libxl_path = cis->libxl_path;
 
+    if (rc)
+        goto out;
+
     insert = flexarray_make(gc, 4, 1);
     flexarray_append_pair(insert, "type",
                           libxl__device_disk_string_of_backend(disk->backend));
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index cafe8b5733..6b6ac65d00 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1948,7 +1948,19 @@ _hidden int libxl__qmp_resume(libxl__gc *gc, int domid);
 _hidden int libxl__qmp_restore(libxl__gc *gc, int domid, const char *filename);
 /* Set dirty bitmap logging status */
 _hidden int libxl__qmp_set_global_dirty_log(libxl__gc *gc, int domid, bool enable);
-_hidden int libxl__qmp_insert_cdrom(libxl__gc *gc, int domid, const libxl_device_disk *disk);
+
+typedef struct libxl__qmp_insert_cdrom_state libxl__qmp_insert_cdrom_state;
+struct libxl__qmp_insert_cdrom_state {
+    /* caller should include this in their own struct */
+    /* caller must fill these in, and they must all remain valid */
+    int domid;
+    const libxl_device_disk *disk;
+    void (*callback)(libxl__egc *egc, libxl__qmp_insert_cdrom_state *, int rc);
+    /* private to libxl__qmp_insert_cdrom() */
+    libxl__ev_qmp ev;
+};
+int libxl__qmp_insert_cdrom(libxl__gc *gc,
+                            libxl__qmp_insert_cdrom_state *qics);
 /* Add a virtual CPU */
 _hidden int libxl__qmp_cpu_add(libxl__gc *gc, int domid, int index);
 /* Query the bitmap of CPUs */
diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 07203a6fe6..08c8060095 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -1061,24 +1061,6 @@ int libxl__qmp_set_global_dirty_log(libxl__gc *gc, int domid, bool enable)
                            NULL, NULL);
 }
 
-int libxl__qmp_insert_cdrom(libxl__gc *gc, int domid,
-                            const libxl_device_disk *disk)
-{
-    libxl__json_object *args = NULL;
-    int dev_number = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
-
-    QMP_PARAMETERS_SPRINTF(&args, "device", "ide-%i", dev_number);
-
-    if (disk->format == LIBXL_DISK_FORMAT_EMPTY) {
-        return qmp_run_command(gc, domid, "eject", args, NULL, NULL);
-    } else {
-        qmp_parameters_add_string(gc, &args, "target", disk->pdev_path);
-        qmp_parameters_add_string(gc, &args, "arg",
-            libxl__qemu_disk_format_string(disk->format));
-        return qmp_run_command(gc, domid, "change", args, NULL, NULL);
-    }
-}
-
 int libxl__qmp_cpu_add(libxl__gc *gc, int domid, int idx)
 {
     libxl__json_object *args = NULL;
@@ -1395,6 +1377,105 @@ static void dm_state_saved(libxl__egc *egc, libxl__ev_qmp *ev,
 }
 
 
+static void qmp_insert_cdrom_addfd_cb(libxl__egc *egc, libxl__ev_qmp *ev,
+                                      const libxl__json_object *response,
+                                      int rc);
+static void qmp_insert_cdrom_done_cb(libxl__egc *egc, libxl__ev_qmp *ev,
+                                     const libxl__json_object *response,
+                                     int rc);
+int libxl__qmp_insert_cdrom(libxl__gc *gc,
+                            libxl__qmp_insert_cdrom_state *qics)
+{
+    int rc;
+    libxl__json_object *args = NULL;
+    int domid = qics->domid;
+    libxl__ev_qmp *ev =  &qics->ev;
+    const libxl_device_disk *disk = qics->disk;
+    int dev_number = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
+
+    libxl__ev_qmp_init(ev);
+    ev->domid = qics->domid;
+    ev->cfd = NULL;
+
+    if (disk->format == LIBXL_DISK_FORMAT_EMPTY) {
+        QMP_PARAMETERS_SPRINTF(&args, "device", "ide-%i", dev_number);
+        ev->callback = qmp_insert_cdrom_done_cb;
+        rc = libxl__ev_qmp_send(gc, ev, "eject", args);
+    } else {
+        libxl__carefd_begin();
+        ev->cfd = libxl__carefd_opened(CTX, open(disk->pdev_path, O_RDONLY));
+        if (!ev->cfd) {
+            LOGED(ERROR, domid,
+                  "Failed to open cdrom file %s", disk->pdev_path);
+            rc = ERROR_FAIL;
+            goto out;
+        }
+
+        /* This free form parameter is not use by QEMU or libxl. */
+        QMP_PARAMETERS_SPRINTF(&args, "opaque", "%s:%s",
+                               libxl_disk_format_to_string(disk->format),
+                               disk->pdev_path);
+        ev->callback = qmp_insert_cdrom_addfd_cb;
+        rc = libxl__ev_qmp_send(gc, ev, "add-fd", args);
+        if (rc)
+            goto out;
+    }
+out:
+    if (rc)
+        libxl__carefd_close(ev->cfd);
+    return rc;
+}
+
+static void qmp_insert_cdrom_addfd_cb(libxl__egc *egc, libxl__ev_qmp *ev,
+                                      const libxl__json_object *response,
+                                      int rc)
+{
+    EGC_GC;
+    libxl__qmp_insert_cdrom_state *qics = CONTAINER_OF(ev, *qics, ev);
+    libxl__json_object *args = NULL;
+    const libxl__json_object *o;
+    const libxl_device_disk *disk = qics->disk;
+    int dev_number = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
+    int fdset;
+
+    libxl__carefd_close(ev->cfd);
+    ev->cfd = NULL;
+
+    if (rc)
+        goto out;
+
+    o = libxl__json_map_get("fdset-id", response, JSON_INTEGER);
+    if (!o) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    fdset = libxl__json_object_get_integer(o);
+
+    ev->callback = qmp_insert_cdrom_done_cb;
+    QMP_PARAMETERS_SPRINTF(&args, "device", "ide-%i", dev_number);
+    QMP_PARAMETERS_SPRINTF(&args, "target", "/dev/fdset/%d", fdset);
+    qmp_parameters_add_string(gc, &args, "arg",
+                              libxl__qemu_disk_format_string(disk->format));
+    rc = libxl__ev_qmp_send(gc, ev, "change", args);
+    if (rc)
+        goto out;
+    return;
+out:
+    qmp_insert_cdrom_done_cb(egc, ev, NULL, rc);
+}
+
+static void qmp_insert_cdrom_done_cb(libxl__egc *egc, libxl__ev_qmp *ev,
+                                     const libxl__json_object *response,
+                                     int rc)
+{
+    EGC_GC;
+    libxl__qmp_insert_cdrom_state *qics = CONTAINER_OF(ev, *qics, ev);
+
+    libxl__ev_qmp_dispose(gc, ev);
+
+    qics->callback(egc, qics, rc);
+}
+
 
 /* ------------ Implementation of libxl__ev_qmp ---------------- */
 
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 07/32] libxl_qmp: Move struct sockaddr_un variable to qmp_open()
  2018-07-27 14:05 ` [PATCH v4 07/32] libxl_qmp: Move struct sockaddr_un variable to qmp_open() Anthony PERARD
@ 2018-08-02  8:26   ` Roger Pau Monné
  2018-08-20 14:52   ` Wei Liu
  1 sibling, 0 replies; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02  8:26 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:05:49PM +0100, Anthony PERARD wrote:
> This variable is only used once, no need to keep it in the handler.
> 
> Also fix coding style (remove space after sizeof).
> And allow strncpy to use all the space in sun_path.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

> ---
> 
> Notes:
>     v4:
>         actually allow strncpy to use all the space in sun_path.
> 
>  tools/libxl/libxl_qmp.c | 14 ++++++--------
>  1 file changed, 6 insertions(+), 8 deletions(-)
> 
> diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> index 987bf0232e..1ffa17b632 100644
> --- a/tools/libxl/libxl_qmp.c
> +++ b/tools/libxl/libxl_qmp.c
> @@ -105,7 +105,6 @@ typedef struct callback_id_pair {
>  } callback_id_pair;
>  
>  struct libxl__qmp_handler {
> -    struct sockaddr_un addr;
>      int qmp_fd;
>      bool connected;
>      time_t timeout;
> @@ -431,6 +430,7 @@ static int qmp_open(libxl__qmp_handler *qmp, const char *qmp_socket_path,
>  {
>      int ret = -1;
>      int i = 0;
> +    struct sockaddr_un addr;

You could do:

struct sockaddr_un addr = { };

And get rid of the memset below.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 08/32] libxl: Add libxl__prepare_sockaddr_un() helper
  2018-07-27 14:05 ` [PATCH v4 08/32] libxl: Add libxl__prepare_sockaddr_un() helper Anthony PERARD
@ 2018-08-02  8:36   ` Roger Pau Monné
  2018-08-20 14:56   ` Wei Liu
  1 sibling, 0 replies; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02  8:36 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:05:50PM +0100, Anthony PERARD wrote:
> There is going to be a few more users that want to use UNIX socket, this
> helper is to prepare the `struct sockaddr_un` and check that the path
> isn't too long.
> 
> Also start to use it in libxl_qmp.c.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

LGTM, just one style nit.

> diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
> index 507ee56c7c..7907e20672 100644
> --- a/tools/libxl/libxl_utils.c
> +++ b/tools/libxl/libxl_utils.c
> @@ -1234,6 +1234,20 @@ int libxl__random_bytes(libxl__gc *gc, uint8_t *buf, size_t len)
>      return ret;
>  }
>  
> +int libxl__prepare_sockaddr_un(libxl__gc *gc,
> +                               struct sockaddr_un *un, const char *path,
> +                               const char *what) {

The brace should be on a newline according to the coding style.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 11/32] libxl_dm: Add libxl__qemu_qmp_path()
  2018-07-27 14:05 ` [PATCH v4 11/32] libxl_dm: Add libxl__qemu_qmp_path() Anthony PERARD
@ 2018-08-02  8:41   ` Roger Pau Monné
  2018-08-20 14:57   ` Wei Liu
  1 sibling, 0 replies; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02  8:41 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:05:53PM +0100, Anthony PERARD wrote:
> ... which generate the path to a QMP socket that libxl uses.
            ^ generates
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

> ---
> 
> Notes:
>     New in v4.
> 
>  tools/libxl/libxl_dm.c       | 9 +++++++--
>  tools/libxl/libxl_internal.h | 1 +
>  2 files changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
> index fdd7fa3ba4..5c28a0ced4 100644
> --- a/tools/libxl/libxl_dm.c
> +++ b/tools/libxl/libxl_dm.c
> @@ -910,6 +910,11 @@ static char *qemu_disk_ide_drive_string(libxl__gc *gc, const char *target_path,
>      return drive;
>  }
>  
> +const char *libxl__qemu_qmp_path(libxl__gc *gc, int domid)
> +{
> +    return GCSPRINTF("%s/qmp-libxl-%d", libxl__run_dir_path(), domid);
> +}

You could place this as a static inline function in libxl_internal.h
directly IMO.

Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 12/32] libxl: Design of an async API to issue QMP commands to QEMUç
  2018-07-27 14:05 ` [PATCH v4 12/32] libxl: Design of an async API to issue QMP commands to QEMU Anthony PERARD
@ 2018-08-02  9:01   ` Roger Pau Monné
  2018-08-03 11:18     ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02  9:01 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:05:54PM +0100, Anthony PERARD wrote:
> All the functions will be implemented in later patches.
> 
> This patch includes the API that libxl can use to send QMP commands to
> QEMU.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
>  tools/libxl/libxl_internal.h | 76 +++++++++++++++++++++++++++++++++++-
>  1 file changed, 74 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 5b71a23d23..c453ac10a5 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -202,6 +202,8 @@ typedef struct libxl__ao libxl__ao;
>  typedef struct libxl__aop_occurred libxl__aop_occurred;
>  typedef struct libxl__osevent_hook_nexus libxl__osevent_hook_nexus;
>  typedef struct libxl__osevent_hook_nexi libxl__osevent_hook_nexi;
> +typedef struct libxl__json_object libxl__json_object;
> +typedef struct libxl__carefd libxl__carefd;
>  
>  typedef struct libxl__domain_create_state libxl__domain_create_state;
>  typedef void libxl__domain_create_cb(struct libxl__egc *egc,
> @@ -357,6 +359,76 @@ struct libxl__ev_child {
>      LIBXL_LIST_ENTRY(struct libxl__ev_child) entry;
>  };
>  
> +/*
> + * QMP asynchronous calls
> + */

Place the title in the same comment block?

> +/*
> + * This facility allows a command to be sent to QEMU, and the response to be
> + * handed to a callback function.  Each libxl__ev_qmp handles zero or one

Do you really mean 'zero or one' or 'zero or more'?

> + * outstanding command.
> + *
> + * Commands can be chained, with a same connection. (e.g. "add-fd" will need to
                                    ^ the
> + * be chained to the next command). A libxl__ev_qmp can be reused when the
                                                                     ^ after
> + * callback is been called in order to use the same connection.
               ^ has
> + *
> + * Only one connection at a time can be made to one QEMU, so avoid keeping a
                                                               ^ to
> + * libxl__ev_qmp Connected for to long and call libxl__ev_qmp_dispose as soon
                    ^ unneeded cap        ^ remove 'and'
> + * as it is not needed anymore.
> + *
> + * Possible states of a libxl__ev_qmp:
> + *  Undefined
> + *    Might contain anything.
> + *  Idle
> + *    Struct contents are defined enough to pass to any libxl__ev_qmp_*
> + *    functions.
         ^ function
> + *    The struct does not contain references to any allocated private resources
> + *    so can be thrown away.

I would add '... can be thrown away without any teardown.'

> + *  Active
> + *    Currently waiting for the callback to be called.
> + *    _dispose must be called to reclaim resources.
> + *  Connected
> + *    Struct contain allocated ressources.
> + *    Calling _send() with this same ev will use the same QMP connection.
> + *    _dispose() must be called to reclaim resources.
> + *
> + * libxl__ev_qmp_init: Undefined/Idle -> Idle
> + *
> + * libxl__ev_qmp_send: Idle/Connected -> Active (on error: Idle)
> + *    Sends a command to QEMU.
> + *    callback will be called when a response is received or when an error
> + *    as occured.
> + *
> + * libxl__ev_qmp_dispose: Connected/Active/Idle -> Idle
> + *
> + * callback: When called: Active -> Connected
> + *    When called, ev is Connected and can be reused or disposed of.
> + *    When an error occured, it is called with response == NULL and the error
         ^ If
> + *    code in rc.
> + *    The callback is only called once.
> + */
> +typedef struct libxl__ev_qmp libxl__ev_qmp;
> +typedef void libxl__ev_qmp_callback(libxl__egc *egc, libxl__ev_qmp *ev,
> +                                    const libxl__json_object *response,
> +                                    int rc);
> +
> +_hidden void libxl__ev_qmp_init(libxl__ev_qmp *ev);
> +_hidden int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
> +                               const char *cmd, libxl__json_object *args);
> +_hidden void libxl__ev_qmp_dispose(libxl__gc *gc, libxl__ev_qmp *ev);
> +
> +struct libxl__ev_qmp {
> +    /* caller should include this in their own struct */
> +    /* caller must fill these in, and they must all remain valid */
                                                   ^ no need for 'all'
> +    uint32_t domid;

Strictly speaking domid is an uint16_t.

> +    libxl__ev_qmp_callback *callback;
> +    libxl__carefd *cfd; /* set to send a fd with the command, NULL otherwise */
> +
> +    /* remaining fields are private to libxl_ev_qmp_* */
> +

Extra newline?

> +    int id;
> +};
> +

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 13/32] libxl_qmp: Connect to QMP socket
  2018-07-27 14:05 ` [PATCH v4 13/32] libxl_qmp: Connect to QMP socket Anthony PERARD
@ 2018-08-02  9:35   ` Roger Pau Monné
  2018-08-03 13:54     ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02  9:35 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:05:55PM +0100, Anthony PERARD wrote:
> This is a first patch to implement libxl__ev_qmp, it only connect to the
                                                            ^ connects
> QMP socket of QEMU and register a fd callback that does nothing.
                         ^ registers
> 
> Callback functions will be implemented in following patches.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
>  tools/libxl/libxl_internal.h | 11 +++++
>  tools/libxl/libxl_qmp.c      | 96 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 107 insertions(+)
> 
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index c453ac10a5..90ac48a659 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -417,6 +417,14 @@ _hidden int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
>                                 const char *cmd, libxl__json_object *args);
>  _hidden void libxl__ev_qmp_dispose(libxl__gc *gc, libxl__ev_qmp *ev);
>  
> +typedef enum {
> +    qmp_state_disconnected = 1,
> +    qmp_state_connecting,
> +    qmp_state_greeting,
> +    qmp_state_capability_negociation,
> +    qmp_state_connected,
> +} libxl__qmp_state;
> +

I think this should be declared in libxl_types_internal.idl?

And (maybe) a description of each state would be helpful for future
reference?

>  struct libxl__ev_qmp {
>      /* caller should include this in their own struct */
>      /* caller must fill these in, and they must all remain valid */
> @@ -427,6 +435,9 @@ struct libxl__ev_qmp {
>      /* remaining fields are private to libxl_ev_qmp_* */
>  
>      int id;
> +    libxl__carefd *qmp_cfd;
> +    libxl__ev_fd qmp_efd;
> +    libxl__qmp_state qmp_state;
>  };
>  
>  
> diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> index c5e05e5679..96a347dd3b 100644
> --- a/tools/libxl/libxl_qmp.c
> +++ b/tools/libxl/libxl_qmp.c
> @@ -1276,6 +1276,102 @@ int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
>      return ret;
>  }
>  
> +/* ------------ Implementation of libxl__ev_qmp ---------------- */
> +
> +static void qmp_ev_fd_callback(libxl__egc *egc, libxl__ev_fd *ev_fd,
> +                               int fd, short events, short revents)
> +{
> +}
> +
> +static int qmp_ev_connect(libxl__gc *gc, libxl__ev_qmp *ev)
> +{
> +    int rc, r;
> +    struct sockaddr_un un;
> +    const char *qmp_socket_path;
> +
> +    if (ev->qmp_state != qmp_state_disconnected)
> +        return 0;
> +
> +    qmp_socket_path = libxl__qemu_qmp_path(gc, ev->domid);
> +
> +    LOGD(DEBUG, ev->domid, "Connecting to %s", qmp_socket_path);
> +
> +    libxl__carefd_begin();
> +    ev->qmp_cfd = libxl__carefd_opened(CTX, socket(AF_UNIX, SOCK_STREAM, 0));
> +    if (!ev->qmp_cfd) {
> +        LOGED(ERROR, ev->domid, "socket() failed");
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }
> +    rc = libxl_fd_set_nonblock(CTX, libxl__carefd_fd(ev->qmp_cfd), 1);
> +    if (rc)
> +        goto out;
> +
> +    rc = libxl__prepare_sockaddr_un(gc, &un, qmp_socket_path, "QMP socket");
> +    if (rc)
> +        goto out;
> +
> +    r = connect(libxl__carefd_fd(ev->qmp_cfd),
> +                (struct sockaddr *) &un, sizeof(un));
> +    if (r) {
> +        LOGED(ERROR, ev->domid, "Failed to connect to QMP socket %s",
> +              qmp_socket_path);
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }
> +
> +    rc = libxl__ev_fd_register(gc, &ev->qmp_efd, qmp_ev_fd_callback,
> +                               libxl__carefd_fd(ev->qmp_cfd), POLLIN);
> +    if (rc)
> +        goto out;
> +
> +    ev->qmp_state = qmp_state_connecting;
> +    return 0;
> +
> +out:
> +    libxl__carefd_close(ev->qmp_cfd);
> +    ev->qmp_cfd = NULL;
> +    return rc;
> +}
> +
> +

Double newline.

> +/*
> + * libxl__ev_qmp_*
> + */
> +
> +void libxl__ev_qmp_init(libxl__ev_qmp *ev)
> +{
> +    ev->id = -1;
> +
> +    ev->qmp_cfd = NULL;
> +    libxl__ev_fd_init(&ev->qmp_efd);
> +    ev->qmp_state = qmp_state_disconnected;
> +}
> +
> +int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
> +                       const char *cmd, libxl__json_object *args)
> +{
> +    int rc;
> +
> +    LOGD(DEBUG, ev->domid, " ev %p, cmd '%s'", ev, cmd);
> +
> +    /* Connect to QEMU if not already connected */
> +    rc = qmp_ev_connect(gc, ev);
> +
> +    return rc;

You can get rid of rc and just use:

return qmp_ev_connect(gc, ev);

> +}
> +
> +void libxl__ev_qmp_dispose(libxl__gc *gc, libxl__ev_qmp *ev)
> +{
> +    LOGD(DEBUG, ev->domid, " ev %p", ev);
> +
> +    libxl__ev_fd_deregister(gc, &ev->qmp_efd);
> +    libxl__carefd_close(ev->qmp_cfd);
> +    ev->qmp_cfd = NULL;

No need to set qmp_cfd to NULL if you call _init afterwards.

> +
> +    libxl__ev_qmp_init(ev);

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 14/32] libxl_qmp: Implement fd callback and read data
  2018-07-27 14:05 ` [PATCH v4 14/32] libxl_qmp: Implement fd callback and read data Anthony PERARD
@ 2018-08-02  9:56   ` Roger Pau Monné
  2018-08-03 14:32     ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02  9:56 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:05:56PM +0100, Anthony PERARD wrote:
> First step into taking care of the input from QEMU's QMP socket. For
> now, we read data and store them in a buffer.
> 
> Parsing of the data will be done in the following patches.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
> 
> Notes:
>     v4:
>         remove use of a linked list of receive buffer, and use realloc instead.
> 
>  tools/libxl/libxl_internal.h |   9 ++++
>  tools/libxl/libxl_qmp.c      | 101 +++++++++++++++++++++++++++++++++++
>  2 files changed, 110 insertions(+)
> 
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 90ac48a659..8c3625a243 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -438,6 +438,15 @@ struct libxl__ev_qmp {
>      libxl__carefd *qmp_cfd;
>      libxl__ev_fd qmp_efd;
>      libxl__qmp_state qmp_state;
> +
> +    /* receive buffer, with:
> +     * buf_size: current allocated size,
> +     * buf_used: actual data in the buffer,
> +     * buf_consumed: data already parsed.  */
> +    char *rx_buf;
> +    size_t buf_size;
> +    size_t buf_used;
> +    size_t buf_consumed;
>  };
>  
>  
> diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> index 96a347dd3b..b0554df843 100644
> --- a/tools/libxl/libxl_qmp.c
> +++ b/tools/libxl/libxl_qmp.c
> @@ -75,6 +75,12 @@
>  #  define DEBUG_REPORT_RECEIVED(dom, buf, len) ((void)0)
>  #endif
>  
> +#ifdef DEBUG_QMP_CLIENT
> +#  define LOG_QMP(f, ...) LOGD(DEBUG, ev->domid, f, ##__VA_ARGS__)
> +#else
> +#  define LOG_QMP(f, ...)
> +#endif
> +
>  /*
>   * QMP types & constant
>   */
> @@ -1278,9 +1284,99 @@ int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
>  
>  /* ------------ Implementation of libxl__ev_qmp ---------------- */
>  
> +/*
> + * QMP FD callbacks
> + */
> +
> +static int qmp_ev_callback_readable(libxl__egc *egc, libxl__ev_qmp *ev, int fd)
> +{
> +    EGC_GC;
> +    ssize_t r;
> +
> +    if (!ev->rx_buf) {
> +        ev->rx_buf = libxl__malloc(NOGC, QMP_RECEIVE_BUFFER_SIZE);
> +        ev->buf_size = QMP_RECEIVE_BUFFER_SIZE;
> +        ev->buf_used = 0;
> +        ev->buf_consumed = 0;
> +    }
> +
> +    /* Check if last buffer still have space, or increase size */
> +    /* The -1 is because there is always space for a NUL character */
> +    if (ev->buf_used == ev->buf_size - 1) {
> +        ev->buf_size += QMP_RECEIVE_BUFFER_SIZE;
> +        ev->rx_buf = libxl__realloc(NOGC, ev->rx_buf, ev->buf_size);
> +    }
> +
> +    for (;;) {
> +        /* The -1 is because there is always space for a NUL character */
> +        r = read(fd, ev->rx_buf + ev->buf_used,
> +                 ev->buf_size - ev->buf_used - 1);
> +        if (r < 0) {
> +            if (errno == EINTR) continue;
> +            assert(errno);
> +            if (errno == EWOULDBLOCK) {
> +                return 0;
> +            }
> +            LOGED(ERROR, ev->domid, "error reading QMP socket");
> +            return ERROR_FAIL;

I think it would be clearer to use:

assert(errno);
switch (errno) {
case EINTR:
    continue;
case EWOULDBLOCK
    return 0;
default:
    LOGED(...)

> +        }
> +        break;
> +    }
> +
> +    if (r == 0) {
> +        LOGD(ERROR, ev->domid, "No data read on QMP socket");
> +        return 0;
> +    }
> +
> +    LOG_QMP("received %ldB: '%.*s'", r, (int)r, ev->rx_buf + ev->buf_used);
> +
> +    ev->buf_used += r;

Hm, don't you need to do this inside of a loop together with the
realloc, in case the data on the fd is bigger than the current space
on the buffer, and you need to keep growing it until you hit
EWOULDBLOCK?

I think with the current approach you can leave data pending in the fd
if the buffer happens to be smaller than the pending data in the fd?

I think the loop should be something like:

for (;;) {
    1. Check if there's space left in the buffer.
    2. Try to read from the fd.
    3. Parse error, exit loop if errno == EWOULDBLOCK.
    4. ev->buf_used += r;
    5. Restart loop.
}

> +    assert(ev->buf_used < ev->buf_size);
> +
> +    return 0;
> +}
> +
> +static void qmp_ev_callback_error(libxl__egc *egc, libxl__ev_qmp *ev)
> +{
> +    EGC_GC;
> +
> +    LOGD(ERROR, ev->domid, "Error happend with the QMP connection to QEMU");
> +
> +    /* On error, deallocate all private ressources */
> +    libxl__ev_qmp_dispose(gc, ev);
> +}
> +
>  static void qmp_ev_fd_callback(libxl__egc *egc, libxl__ev_fd *ev_fd,
>                                 int fd, short events, short revents)
>  {
> +    EGC_GC;
> +    int rc;
> +
> +    libxl__ev_qmp *ev = CONTAINER_OF(ev_fd, *ev, qmp_efd);
> +
> +    if (revents & (POLLHUP)) {
> +        LOGD(DEBUG, ev->domid, "received POLLHUP from QMP socket");
> +        qmp_ev_callback_error(egc, ev);
> +        return;
> +    }
> +    if (revents & ~(POLLIN|POLLOUT)) {
> +        LOGD(ERROR, ev->domid,
> +             "unexpected poll event 0x%x on QMP socket (expected POLLIN "
> +             "and/or POLLOUT)",
> +            revents);
> +        qmp_ev_callback_error(egc, ev);
> +        return;
> +    }
> +
> +    if (revents & POLLIN) {
> +        rc = qmp_ev_callback_readable(egc, ev, fd);
> +        if (rc)
> +            goto out;
> +    }
> +out:

Since you already have an out label that calls _error, why not use it
for the failure paths above by manually setting rc?

Or else get rid of it and just call _error directly.

    if (revents & POLLIN) {
        rc = qmp_ev_callback_readable(egc, ev, fd);
        if (rc) {
            qmp_ev_callback_error(egc, ev);
            return;
        }
    }

And then you can remove the label altogether.

> +    if (rc) {
> +        qmp_ev_callback_error(egc, ev);
> +    }
>  }
>  
>  static int qmp_ev_connect(libxl__gc *gc, libxl__ev_qmp *ev)
> @@ -1346,6 +1442,8 @@ void libxl__ev_qmp_init(libxl__ev_qmp *ev)
>      ev->qmp_cfd = NULL;
>      libxl__ev_fd_init(&ev->qmp_efd);
>      ev->qmp_state = qmp_state_disconnected;
> +
> +    ev->rx_buf = NULL;

Aren't you missing a

ev->buf_size = ev->buf_used = ev->buf_consumed = 0;

?

>  }
>  
>  int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
> @@ -1365,6 +1463,9 @@ void libxl__ev_qmp_dispose(libxl__gc *gc, libxl__ev_qmp *ev)
>  {
>      LOGD(DEBUG, ev->domid, " ev %p", ev);
>  
> +    free(ev->rx_buf);
> +    ev->rx_buf = NULL;

I don't think you need to set rx_buf to NULL if you call _init
afterwards.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 15/32] libxl_json: Enable yajl_allow_trailing_garbage
  2018-07-27 14:05 ` [PATCH v4 15/32] libxl_json: Enable yajl_allow_trailing_garbage Anthony PERARD
@ 2018-08-02 10:01   ` Roger Pau Monné
  2018-08-21  8:26     ` Wei Liu
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 10:01 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:05:57PM +0100, Anthony PERARD wrote:
> This allow to parse a string that is not NUL-terminated. With that
       ^ allows
> options disabled, YAJL v2 would look ahead on completion to find out if
  ^ option
> there is more to parse.
> 
> YAJL v1 doesn't have this behavior.
> 
> Any function function that allocate a yajl_handle via this function
      ^ duplicated           ^ allocates
> either parse a NUL-terminated string, or do provide proper length. So
> change the default and allow garbage (like a different JSON document)
> after the end of the data to parse.
> 
> This is importand for the QMP client, as there could be more than one
          ^ important
> message to parse, and YAJL would consider the next message to be
> garbage and throw an error.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 16/32] libxl_json: libxl__json_object_to_json
  2018-07-27 14:05 ` [PATCH v4 16/32] libxl_json: libxl__json_object_to_json Anthony PERARD
@ 2018-08-02 10:10   ` Roger Pau Monné
  2018-08-21  8:26   ` Wei Liu
  1 sibling, 0 replies; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 10:10 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:05:58PM +0100, Anthony PERARD wrote:
> Allow to generate a JSON string from a libxl__json_object,
> usefull for debugging.
  ^ useful
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

> ---
>  tools/libxl/libxl_internal.h |  3 +++
>  tools/libxl/libxl_json.c     | 36 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 39 insertions(+)
> 
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 8c3625a243..7f200e7a46 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -2129,6 +2129,9 @@ _hidden void libxl__json_object_free(libxl__gc *gc_opt,
>  
>  _hidden libxl__json_object *libxl__json_parse(libxl__gc *gc_opt, const char *s);
>  
> +_hidden char *libxl__json_object_to_json(libxl__gc *gc,
> +                                         const libxl__json_object *args);
> +
>    /* Based on /local/domain/$domid/dm-version xenstore key
>     * default is qemu xen traditional */
>  _hidden int libxl__device_model_version_running(libxl__gc *gc, uint32_t domid);
> diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c
> index b7f9077f0d..16cdd5bda3 100644
> --- a/tools/libxl/libxl_json.c
> +++ b/tools/libxl/libxl_json.c
> @@ -1017,6 +1017,42 @@ out:
>      return ret;
>  }
>  
> +char *libxl__json_object_to_json(libxl__gc *gc,
> +                                 const libxl__json_object *args)
> +{
> +    const unsigned char *buf;
> +    libxl_yajl_length len;
> +    yajl_gen_status s;
> +    yajl_gen hand;
> +    char *ret = NULL;
> +    int rc;
> +
> +    if (!args)
> +        return NULL;
> +
> +    hand = libxl_yajl_gen_alloc(NULL);
> +

I would remove this newline.

> +    if (!hand) {
> +        return NULL;
> +    }
> +
> +    rc = libxl__json_object_to_yajl_gen(gc, hand, args);
> +    if (rc)
> +        goto out;
> +
> +    s = yajl_gen_get_buf(hand, &buf, &len);
> +

And this one.

> +    if (s) {
> +        goto out;
> +    }

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 17/32] libxl_qmp: Parse JSON input from QMP
  2018-07-27 14:05 ` [PATCH v4 17/32] libxl_qmp: Parse JSON input from QMP Anthony PERARD
@ 2018-08-02 10:25   ` Roger Pau Monné
  2018-08-03 15:33     ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 10:25 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:05:59PM +0100, Anthony PERARD wrote:
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
> 
> Notes:
>     v4:
>         simplification of the patch due to use of a single allocated space for the
>         receive buffer.
> 
>  tools/libxl/libxl_qmp.c | 54 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 54 insertions(+)
> 
> diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> index b0554df843..665b6f5d05 100644
> --- a/tools/libxl/libxl_qmp.c
> +++ b/tools/libxl/libxl_qmp.c
> @@ -1292,6 +1292,7 @@ static int qmp_ev_callback_readable(libxl__egc *egc, libxl__ev_qmp *ev, int fd)
>  {
>      EGC_GC;
>      ssize_t r;
> +    char *end = NULL;
>  
>      if (!ev->rx_buf) {
>          ev->rx_buf = libxl__malloc(NOGC, QMP_RECEIVE_BUFFER_SIZE);
> @@ -1333,6 +1334,59 @@ static int qmp_ev_callback_readable(libxl__egc *egc, libxl__ev_qmp *ev, int fd)
>      ev->buf_used += r;
>      assert(ev->buf_used < ev->buf_size);
>  
> +    /* workaround strstr limitation */
> +    ev->rx_buf[ev->buf_used] = '\0';

Why not use strnstr to limit the size of the rx_buf that's searched? I
think that would allow you to get rid of the '-1' that you have to
take into account in several places?

> +
> +    /*
> +     * Search for the end of a QMP message: "\r\n" in the newly received
> +     * bytes + the last byte on the previous read() if any
> +     *
> +     * end: This will point to the byte right after \r\n
> +     */
> +    end = strstr(ev->rx_buf + ev->buf_used - r
> +                 + (ev->buf_used - r == 0 ? 0 : -1),
> +                 "\r\n");
> +    if (end)
> +        end += 2;
> +
> +    while (end) {
> +        libxl__json_object *o;
> +        size_t len;
> +        char *s;
> +
> +        /* Start parsing from s */
> +        s = ev->rx_buf + ev->buf_consumed;
> +        /* Findout how much can be parsed */
> +        len = end - s;

You can init both s and len above when defining them.

> +
> +        LOG_QMP("parsing %luB: '%.*s'", len, (int)len, s);
> +
> +        /* Replace \n by \0 so that libxl__json_parse can use strlen */
> +        s[len - 1] = '\0';
> +        o = libxl__json_parse(gc, s); //, len);

Doesn't look like the above line will compile.

> +
> +        if (!o) {
> +            LOGD(ERROR, ev->domid, "Parse error");
> +            return ERROR_FAIL;
> +        }
> +
> +        ev->buf_consumed += len;
> +
> +        if (ev->buf_consumed >= ev->buf_used) {

I'm not sure I see how the above check can ever be true, you search
the buffer up to buf_used, so 'end' can never be past buf_used?

> +            free(ev->rx_buf);
> +            ev->rx_buf = NULL;
> +        }
> +
> +        /* check if there is another message received at the same time */
> +        if (ev->rx_buf) {
> +            end = strstr(ev->rx_buf + ev->buf_consumed, "\r\n");
> +            if (end)
> +                end += 2;
> +        } else
> +            end = NULL;
> +
> +        LOG_QMP("JSON object received: %s", libxl__json_object_to_json(gc, o));
> +    }

Newline.

>      return 0;

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 18/32] libxl_qmp: Separate QMP message generation from qmp_send_prepare
  2018-07-27 14:06 ` [PATCH v4 18/32] libxl_qmp: Separate QMP message generation from qmp_send_prepare Anthony PERARD
@ 2018-08-02 10:34   ` Roger Pau Monné
  2018-08-03 15:43     ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 10:34 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:06:00PM +0100, Anthony PERARD wrote:
> To be able to re-use qmp_prepare_qmp_cmd with libxl__ev_qmp.
> 
> Also, add the QMP end of command '\r\n' into the generated string.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
>  tools/libxl/libxl_qmp.c | 62 +++++++++++++++++++++++++++++------------
>  1 file changed, 44 insertions(+), 18 deletions(-)
> 
> diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> index 665b6f5d05..38a4395266 100644
> --- a/tools/libxl/libxl_qmp.c
> +++ b/tools/libxl/libxl_qmp.c
> @@ -578,17 +578,17 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp)
>      return rc;
>  }
>  
> -static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp,
> -                              const char *cmd, libxl__json_object *args,
> -                              qmp_callback_t callback, void *opaque,
> -                              qmp_request_context *context)
> -{
> -    const unsigned char *buf = NULL;
> -    char *ret = NULL;
> -    libxl_yajl_length len = 0;
> +static char *qmp_prepare_qmp_cmd(libxl__gc *gc,

Is it really needed to have qmp twice in the function name?
qmp_prepare_cmd LGTM.

> +                                 const char *cmd,
> +                                 const libxl__json_object *args,
> +                                 int id,
> +                                 size_t *len_r)
> +{
> +    const unsigned char *buf;

While there I would drop the unsigned...

> +    libxl_yajl_length len;
>      yajl_gen_status s;
>      yajl_gen hand;
> -    callback_id_pair *elm = NULL;
> +    char *ret = NULL;
>  
>      hand = libxl_yajl_gen_alloc(NULL);
>  
> @@ -600,7 +600,7 @@ static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp,
>      libxl__yajl_gen_asciiz(hand, "execute");
>      libxl__yajl_gen_asciiz(hand, cmd);
>      libxl__yajl_gen_asciiz(hand, "id");
> -    yajl_gen_integer(hand, ++qmp->last_id_used);
> +    yajl_gen_integer(hand, id);
>      if (args) {
>          libxl__yajl_gen_asciiz(hand, "arguments");
>          libxl__json_object_to_yajl_gen(gc, hand, args);
> @@ -610,6 +610,36 @@ static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp,
>      s = yajl_gen_get_buf(hand, &buf, &len);
>  
>      if (s) {
> +        goto out;
> +    }
> +
> +    ret = libxl__malloc(NOGC, len + 3);
> +    strncpy(ret, (const char *)buf, len + 3);

... so that you can drop the cast from here.

> +    strncpy(ret + len, "\r\n", 3);
> +    len += 2;
> +
> +    if (len_r)
> +        *len_r = len;
> +
> +out:
> +    yajl_gen_free(hand);
> +    return ret;
> +}
> +
> +static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp,
> +                              const char *cmd, libxl__json_object *args,
> +                              qmp_callback_t callback, void *opaque,
> +                              qmp_request_context *context,
> +                              size_t *len_r)
> +{
> +    char *buf;
> +    callback_id_pair *elm;
> +
> +    buf = qmp_prepare_qmp_cmd(gc,
> +                              cmd, args, ++qmp->last_id_used,
> +                              NULL);

Indentation is very weird here. AFAICT it can fit in a single line?

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 19/32] libxl_qmp: Prepare the command to be sent
  2018-07-27 14:06 ` [PATCH v4 19/32] libxl_qmp: Prepare the command to be sent Anthony PERARD
@ 2018-08-02 10:41   ` Roger Pau Monné
  2018-08-03 16:35     ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 10:41 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:06:01PM +0100, Anthony PERARD wrote:
> The actual sent will be done in a separate patch.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
>  tools/libxl/libxl_internal.h |  4 ++++
>  tools/libxl/libxl_qmp.c      | 37 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 41 insertions(+)
> 
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 7f200e7a46..110b951bbe 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -438,6 +438,7 @@ struct libxl__ev_qmp {
>      libxl__carefd *qmp_cfd;
>      libxl__ev_fd qmp_efd;
>      libxl__qmp_state qmp_state;
> +    unsigned int last_id_used;

Now there are two last_id_used fields in different structures?
Shouldn't the previous one be removed when you introduce this new one?

>  
>      /* receive buffer, with:
>       * buf_size: current allocated size,
> @@ -447,6 +448,9 @@ struct libxl__ev_qmp {
>      size_t buf_size;
>      size_t buf_used;
>      size_t buf_consumed;
> +
> +    char *tx_buf;
> +    size_t tx_buf_len;
>  };
>  
>  
> diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> index 38a4395266..2792f35912 100644
> --- a/tools/libxl/libxl_qmp.c
> +++ b/tools/libxl/libxl_qmp.c
> @@ -1310,6 +1310,25 @@ int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
>  
>  /* ------------ Implementation of libxl__ev_qmp ---------------- */
>  
> +static int qmp_ev_prepare_cmd(libxl__gc *gc,
> +                              libxl__ev_qmp *ev,
> +                              const char *cmd,
> +                              const libxl__json_object *args)
> +{
> +    char *buf = NULL;
> +    size_t len;
> +
> +    buf = qmp_prepare_qmp_cmd(gc, cmd, args, ++ev->last_id_used, &len);
> +    if (!buf)
> +        return ERROR_FAIL;
> +
> +    ev->id = ev->last_id_used;
> +    ev->tx_buf = buf;
> +    ev->tx_buf_len = len;
> +
> +    return 0;
> +}
> +
>  /*
>   * QMP FD callbacks
>   */
> @@ -1424,6 +1443,9 @@ static void qmp_ev_callback_error(libxl__egc *egc, libxl__ev_qmp *ev)
>  
>      /* On error, deallocate all private ressources */
>      libxl__ev_qmp_dispose(gc, ev);
> +
> +    ev->id = -1;
> +    ev->callback(egc, ev, NULL, ERROR_FAIL);
>  }
>  
>  static void qmp_ev_fd_callback(libxl__egc *egc, libxl__ev_fd *ev_fd,
> @@ -1522,8 +1544,10 @@ void libxl__ev_qmp_init(libxl__ev_qmp *ev)
>      ev->qmp_cfd = NULL;
>      libxl__ev_fd_init(&ev->qmp_efd);
>      ev->qmp_state = qmp_state_disconnected;
> +    ev->last_id_used = 0;
>  
>      ev->rx_buf = NULL;
> +    ev->tx_buf = NULL;

ev->tx_buf_len = 0;

I think.

>  }
>  
>  int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
> @@ -1535,7 +1559,17 @@ int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
>  
>      /* Connect to QEMU if not already connected */
>      rc = qmp_ev_connect(gc, ev);
> +    if (rc)
> +        goto out;
> +
> +    rc = qmp_ev_prepare_cmd(gc, ev, cmd, args);
> +    if (rc)
> +        goto out;
> +
>  

Double newline?

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 20/32] libxl_qmp: Handle write to QMP socket
  2018-07-27 14:06 ` [PATCH v4 20/32] libxl_qmp: Handle write to QMP socket Anthony PERARD
@ 2018-08-02 11:02   ` Roger Pau Monné
  2018-08-03 16:50     ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 11:02 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:06:02PM +0100, Anthony PERARD wrote:
> The libxl__ev_qmp_* will now send the command to QEMU when the socket is
> ready for writes.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

> ---
>  tools/libxl/libxl_qmp.c | 44 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 44 insertions(+)
> 
> diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> index 2792f35912..75f953d521 100644
> --- a/tools/libxl/libxl_qmp.c
> +++ b/tools/libxl/libxl_qmp.c
> @@ -1326,6 +1326,8 @@ static int qmp_ev_prepare_cmd(libxl__gc *gc,
>      ev->tx_buf = buf;
>      ev->tx_buf_len = len;
>  
> +    libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events | POLLOUT);
> +
>      return 0;
>  }
>  
> @@ -1435,6 +1437,43 @@ static int qmp_ev_callback_readable(libxl__egc *egc, libxl__ev_qmp *ev, int fd)
>      return 0;
>  }
>  
> +static int qmp_ev_callback_writable(libxl__gc *gc, libxl__ev_qmp *ev, int fd)
> +{
> +    int rc;
> +    char *buf;
> +    size_t len;
> +    int buf_fd = -1;

I would name this send_fd.

> +
> +    /* No need to call qmp_ev_callback_writable again, everything that needs to
> +     * be send for now will be in this call. */
> +    libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events & ~POLLOUT);

I think you do this because you need to wait for this command to
complete before queuing another command?

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 21/32] libxl_qmp: Simplify qmp_response_type() prototype
  2018-07-27 14:06 ` [PATCH v4 21/32] libxl_qmp: Simplify qmp_response_type() prototype Anthony PERARD
@ 2018-08-02 11:03   ` Roger Pau Monné
  2018-08-21  8:53   ` Wei Liu
  1 sibling, 0 replies; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 11:03 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:06:03PM +0100, Anthony PERARD wrote:
> Remove the libxl__qmp_handler* argument so the function can be reused
> later in a different context.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU
  2018-07-27 14:06 ` [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU Anthony PERARD
@ 2018-08-02 11:17   ` Roger Pau Monné
  2018-08-03 17:25     ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 11:17 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:06:04PM +0100, Anthony PERARD wrote:
> This will handles messages received, and calls callbacks associated with
            ^ handle

I'm not sure I understand what's 'This' in the context. Would be good
if you could spell out what 'This' refers to IMO.

> the libxl__ev_qmp when the expected response is received.
> 
> This also print error messages from QMP on behalf of the callback.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
> 
> Notes:
>     v4:
>         Provide an libxl error code to callbacks on error instead of a
>         qmp_error_class
> 
>  tools/libxl/libxl_qmp.c              | 116 +++++++++++++++++++++++++++
>  tools/libxl/libxl_types.idl          |   4 +
>  tools/libxl/libxl_types_internal.idl |   8 ++
>  3 files changed, 128 insertions(+)
> 
> diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> index aabf9ad5e7..e649b8054d 100644
> --- a/tools/libxl/libxl_qmp.c
> +++ b/tools/libxl/libxl_qmp.c
> @@ -1330,6 +1330,118 @@ static int qmp_ev_prepare_cmd(libxl__gc *gc,
>      return 0;
>  }
>  
> +/*
> + * Handle messages received from QMP server
> + */
> +
> +static int qmp_error_class_to_libxl_error_code(const libxl__qmp_error_class c)
> +{
> +    switch (c) {
> +    case LIBXL__QMP_ERROR_CLASS_GENERICERROR:
> +        return ERROR_QMP_GENERIC_ERROR;
> +    case LIBXL__QMP_ERROR_CLASS_COMMANDNOTFOUND:
> +        return ERROR_QMP_COMMAND_NOT_FOUND;
> +    case LIBXL__QMP_ERROR_CLASS_DEVICENOTACTIVE:
> +        return ERROR_QMP_DEVICE_NOT_ACTIVE;
> +    case LIBXL__QMP_ERROR_CLASS_DEVICENOTFOUND:
> +        return ERROR_QMP_DEVICE_NOT_FOUND;
> +    default:
> +        abort();
> +    }
> +}
> +
> +/* return 1 when a user callback as been called */
> +static int qmp_ev_handle_response(libxl__egc *egc,
> +                                  libxl__ev_qmp *ev,
> +                                  const libxl__json_object *resp,
> +                                  libxl__qmp_message_type type)
> +{
> +    EGC_GC;
> +    const libxl__json_object *response;
> +    const libxl__json_object *o;
> +    int rc;
> +    int id;
> +
> +    o = libxl__json_map_get("id", resp, JSON_INTEGER);
> +    if (!o) {
> +        const char *error_desc;
> +
> +        /* unexpected message, attempt to find an error description */
> +        o = libxl__json_map_get("error", resp, JSON_MAP);
> +        o = libxl__json_map_get("desc", o, JSON_STRING);
> +        error_desc = libxl__json_object_get_string(o);
> +        if (error_desc)
> +            LOGD(ERROR, ev->domid, "%s", error_desc);
> +        else
> +            LOGD(ERROR, ev->domid, "Received unexpected message: %s",
> +                 libxl__json_object_to_json(gc, resp));
> +        return 0;
> +    }
> +
> +    id = libxl__json_object_get_integer(o);
> +    if (id != ev->id)
> +        return 0;
> +
> +    switch (type) {
> +    case LIBXL__QMP_MESSAGE_TYPE_RETURN: {
> +        response = libxl__json_map_get("return", resp, JSON_ANY);
> +        rc = 0;
> +        break;
> +    }
> +    case LIBXL__QMP_MESSAGE_TYPE_ERROR: {
> +        const char *s;
> +        const libxl__json_object *err;
> +        libxl__qmp_error_class error_class;
> +
> +        rc = ERROR_FAIL;
> +        response = NULL;
> +
> +        err = libxl__json_map_get("error", resp, JSON_MAP);
> +        o = libxl__json_map_get("class", err, JSON_STRING);
> +        s = libxl__json_object_get_string(o);

You could init err and s at definition time.

> +        if (s && !libxl__qmp_error_class_from_string(s, &error_class))
> +            rc = qmp_error_class_to_libxl_error_code(error_class);
> +
> +        o = libxl__json_map_get("desc", err, JSON_STRING);
> +        s = libxl__json_object_get_string(o);
> +        if (s)
> +            LOGD(ERROR, ev->domid, "%s", s);
> +
> +        break;
> +    }
> +    default:
> +        abort();
> +    }
> +
> +    ev->id = -1;
> +    ev->callback(egc, ev, response, rc); /* must be last */
> +    return 1;
> +}
> +
> +/* return 1 when a user callback as been called */
> +static int qmp_ev_handle_message(libxl__egc *egc,
> +                                 libxl__ev_qmp *ev,
> +                                 const libxl__json_object *resp)
> +{
> +    EGC_GC;
> +    libxl__qmp_message_type type = qmp_response_type(resp);
> +
> +    switch (type) {
> +    case LIBXL__QMP_MESSAGE_TYPE_QMP:
> +        /* greeting message */
> +        return 0;
> +    case LIBXL__QMP_MESSAGE_TYPE_RETURN:
> +    case LIBXL__QMP_MESSAGE_TYPE_ERROR:
> +        return qmp_ev_handle_response(egc, ev, resp, type);
> +    case LIBXL__QMP_MESSAGE_TYPE_EVENT:
> +        /* Event are ignored */
> +        return 0;
> +    case LIBXL__QMP_MESSAGE_TYPE_INVALID:
> +        return 0;

Might be good to have a 'default' lable here and print some debug
message about receiving an unknown QMP message type?

> +    }
> +    return 0;
> +}
> +
>  /*
>   * QMP FD callbacks
>   */
> @@ -1432,6 +1544,10 @@ static int qmp_ev_callback_readable(libxl__egc *egc, libxl__ev_qmp *ev, int fd)
>              end = NULL;
>  
>          LOG_QMP("JSON object received: %s", libxl__json_object_to_json(gc, o));
> +
> +        /* Must be last and return when the user callback is called */
> +        if (qmp_ev_handle_message(egc, ev, o) == 1)
> +            return 0;
>      }
>      return 0;
>  }
> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> index 4a385801ba..e104fea941 100644
> --- a/tools/libxl/libxl_types.idl
> +++ b/tools/libxl/libxl_types.idl
> @@ -69,6 +69,10 @@ libxl_error = Enumeration("error", [
>      (-23, "NOTFOUND"),
>      (-24, "DOMAIN_DESTROYED"), # Target domain ceased to exist during op
>      (-25, "FEATURE_REMOVED"), # For functionality that has been removed
> +    (-26, "QMP_GENERIC_ERROR"), # unspecified qmp error
> +    (-27, "QMP_COMMAND_NOT_FOUND"), # the requested command has not been found
> +    (-28, "QMP_DEVICE_NOT_ACTIVE"), # a device has failed to be become active
> +    (-29, "QMP_DEVICE_NOT_FOUND"), # the requested device has not been found

Do we really need such granularity for QMP errors? Isn't it enough to
have a single ERROR_QMP or similar?

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 23/32] libxl_qmp: Respond to QMP greeting
  2018-07-27 14:06 ` [PATCH v4 23/32] libxl_qmp: Respond to QMP greeting Anthony PERARD
@ 2018-08-02 11:26   ` Roger Pau Monné
  2018-08-06 17:41     ` Anthony PERARD
  2018-08-21  9:00   ` Wei Liu
  1 sibling, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 11:26 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:06:05PM +0100, Anthony PERARD wrote:
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
>  tools/libxl/libxl_qmp.c | 36 ++++++++++++++++++++++++++++++------
>  1 file changed, 30 insertions(+), 6 deletions(-)
> 
> diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> index e649b8054d..83afce3192 100644
> --- a/tools/libxl/libxl_qmp.c
> +++ b/tools/libxl/libxl_qmp.c
> @@ -1309,6 +1309,9 @@ int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
>  
>  /* ------------ Implementation of libxl__ev_qmp ---------------- */
>  
> +/* hard coded message ID used for capability negociation */
> +static int qmp_capability_negociation_msgid = 1;

Could this be a define instead? Or at least constify it because it
doesn't seem like it's modified (at least in this patch).

>  static int qmp_ev_prepare_cmd(libxl__gc *gc,
>                                libxl__ev_qmp *ev,
>                                const char *cmd,
> @@ -1379,7 +1382,7 @@ static int qmp_ev_handle_response(libxl__egc *egc,
>      }
>  
>      id = libxl__json_object_get_integer(o);
> -    if (id != ev->id)
> +    if (id != ev->id && id != qmp_capability_negociation_msgid)
>          return 0;
>  
>      switch (type) {
> @@ -1413,9 +1416,21 @@ static int qmp_ev_handle_response(libxl__egc *egc,
>          abort();
>      }
>  
> -    ev->id = -1;
> -    ev->callback(egc, ev, response, rc); /* must be last */
> -    return 1;
> +    /*
> +     * Even if the current state is capability_negociation and the correct ID
> +     * as been received, call the callback on error.
> +     */
> +    if (ev->qmp_state == qmp_state_capability_negociation &&
> +        id == qmp_capability_negociation_msgid &&
> +        rc == 0) {
> +        ev->qmp_state = qmp_state_connected;
> +        libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events | POLLOUT);
> +        return 0;
> +    } else {
> +        ev->id = -1;
> +        ev->callback(egc, ev, response, rc); /* must be last */
> +        return 1;
> +    }
>  }
>  
>  /* return 1 when a user callback as been called */
> @@ -1429,6 +1444,11 @@ static int qmp_ev_handle_message(libxl__egc *egc,
>      switch (type) {
>      case LIBXL__QMP_MESSAGE_TYPE_QMP:
>          /* greeting message */
> +        assert(ev->qmp_state == qmp_state_connecting);
> +        ev->qmp_state = qmp_state_greeting;
> +        /* Allow qmp_ev_callback_writable to be called in order to send
> +         * qmp_capabilities */
> +        libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events | POLLOUT);
>          return 0;
>      case LIBXL__QMP_MESSAGE_TYPE_RETURN:
>      case LIBXL__QMP_MESSAGE_TYPE_ERROR:
> @@ -1563,7 +1583,11 @@ static int qmp_ev_callback_writable(libxl__gc *gc, libxl__ev_qmp *ev, int fd)
>       * be send for now will be in this call. */
>      libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events & ~POLLOUT);
>  
> -    if (ev->qmp_state == qmp_state_connected) {
> +    if (ev->qmp_state == qmp_state_greeting) {
> +        buf = qmp_prepare_qmp_cmd(gc, "qmp_capabilities", NULL,
> +                                  qmp_capability_negociation_msgid, &len);
> +        ev->qmp_state = qmp_state_capability_negociation;
> +    } else if (ev->qmp_state == qmp_state_connected) {

A switch (ev->qmp_state) might be better.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 25/32] libxl_exec: Add libxl__spawn_initiate_failure
  2018-07-27 14:06 ` [PATCH v4 25/32] libxl_exec: Add libxl__spawn_initiate_failure Anthony PERARD
@ 2018-08-02 11:34   ` Roger Pau Monné
  2018-08-06 15:58     ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 11:34 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:06:07PM +0100, Anthony PERARD wrote:
> This function can be use by user libxl__spawn_* when they setup a
                       ^ used and remove user
> notification other than xenstore. The parent can already called success
                                                           ^ report
> via libxl__spawn_initiate_detach(), this new function can be used for
> failure instead of waiting for the timeout.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

> ---
>  tools/libxl/libxl_exec.c     |  7 +++++++
>  tools/libxl/libxl_internal.h | 21 ++++++++++++++++++++-
>  2 files changed, 27 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/libxl/libxl_exec.c b/tools/libxl/libxl_exec.c
> index 02e6c917f0..fb9621b10a 100644
> --- a/tools/libxl/libxl_exec.c
> +++ b/tools/libxl/libxl_exec.c
> @@ -373,6 +373,13 @@ void libxl__spawn_initiate_detach(libxl__gc *gc, libxl__spawn_state *ss)
>      spawn_detach(gc, ss);
>  }
>  
> +void libxl__spawn_initiate_failure(libxl__gc *gc, libxl__spawn_state *ss, int rc)
> +{
> +    assert(rc);
> +    ss->rc = rc;
> +    spawn_detach(gc, ss);
> +}
> +
>  static void spawn_fail(libxl__egc *egc, libxl__spawn_state *ss, int rc)
>  /* Caller must have logged.  Must be last thing in calling function,
>   * as it may make the callback.  Precondition: Attached or Detaching. */
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 110b951bbe..b94657a7f0 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -1551,7 +1551,8 @@ _hidden void libxl__spawn_init(libxl__spawn_state*);
>   *
>   * The inner child must soon exit or exec.  It must also soon exit or
>   * notify the parent of its successful startup by writing to the
> - * xenstore path xspath.
> + * xenstore path xspath OR via other mean that the parent will have
                                        ^ means
> + * to setup.
>   *
>   * The user (in the parent) will be called back (confirm_cb) every
>   * time that xenstore path is modified.
> @@ -1607,6 +1608,24 @@ _hidden int libxl__spawn_spawn(libxl__egc *egc, libxl__spawn_state *spawn);
>   */
>  _hidden void libxl__spawn_initiate_detach(libxl__gc *gc, libxl__spawn_state*);
>  
> +/*
> + * libxl__spawn_initiate_failure - Propagate failure from the caller to the
> + * callee.
> + *
> + * Works by killing the intermediate process from spawn_spawn.
> + * After this function returns, failures will be reported via failure_cb.
> + *
> + * This is not synchronous: there will be a further callback when
> + * the detach is complete.
> + *
> + * Logs errors.
> + *
> + * The spawn state must be Attached entry and will be Attached Failed
> + * on return.
> + */
> +_hidden void libxl__spawn_initiate_failure(libxl__gc *gc,
> +                                           libxl__spawn_state *ss, int rc);
> +
>  /*
>   * If successful, this should return 0.
>   *
> -- 
> Anthony PERARD
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xenproject.org
> https://lists.xenproject.org/mailman/listinfo/xen-devel

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 26/32] libxl_dm: Pre-open QMP socket for QEMU
  2018-07-27 14:06 ` [PATCH v4 26/32] libxl_dm: Pre-open QMP socket for QEMU Anthony PERARD
@ 2018-08-02 15:00   ` Roger Pau Monné
  0 siblings, 0 replies; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 15:00 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:06:08PM +0100, Anthony PERARD wrote:
> When starting QEMU with dm_restrict=1, pre-open the QMP socket before
> exec QEMU. That socket will be usefull to findout if QEMU is ready, and
> pre-opening it means that libxl can connect to it without waiting for
> QEMU to create it.
> 
> The pre-openning is conditionnal, based on the use of dm_restrict
> because it is using a new command line option of QEMU, and dm_restrict
> support in QEMU is newer.
> 
> -chardev socket,fd=X is available with QEMU 2.12, since commit:
> > char: allow passing pre-opened socket file descriptor at startup
> > 0935700f8544033ebbd41e1f13cd528f8a58d24d
> 
> dm_restrict will be available in QEMU 3.0.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
> 
> Notes:
>     v4:
>         separate the logic to open a socket into a function.
>         Use libxl__prepare_sockaddr_un() to check path size
> 
>  tools/libxl/libxl_dm.c | 86 +++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 77 insertions(+), 9 deletions(-)
> 
> diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
> index 5c28a0ced4..9e3e501457 100644
> --- a/tools/libxl/libxl_dm.c
> +++ b/tools/libxl/libxl_dm.c
> @@ -24,6 +24,8 @@
>  #include <sys/types.h>
>  #include <pwd.h>
>  #include <grp.h>
> +#include <sys/socket.h>

sys/socket.h should be already included by libxl_internal.h

> +#include <sys/un.h>

I would probably consider adding sys/un.h to libxl_internal.h unless
it's only required for this specific file.

>  
>  static const char *libxl_tapif_script(libxl__gc *gc)
>  {
> @@ -915,12 +917,58 @@ const char *libxl__qemu_qmp_path(libxl__gc *gc, int domid)
>      return GCSPRINTF("%s/qmp-libxl-%d", libxl__run_dir_path(), domid);
>  }
>  
> +static int libxl__pre_open_qmp_socket(libxl__gc *gc, int domid, int *fd_r)
> +{
> +    int rc;
> +    int fd = -1;

There's no need to init fd to -1.

> +    struct sockaddr_un un;
> +    const char *path;
> +
> +    path = libxl__qemu_qmp_path(gc, domid);

You can init it a definition time.

> +
> +    fd = socket(AF_UNIX, SOCK_STREAM, 0);
> +    if (fd < 0) {
> +        LOGED(ERROR, domid, "socket() failed");
> +        return ERROR_FAIL;
> +    }
> +
> +    rc = libxl__prepare_sockaddr_un(gc, &un, path, "QEMU's QMP socket");
> +    if (rc)
> +        goto out;
> +
> +    if (unlink(path) < 0 && errno != ENOENT) {
> +        LOGED(ERROR, domid, "unlink('%s') failed", path);
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }

You can use libxl__remove_file which also handles EINTR.

> +
> +    if (bind(fd, (struct sockaddr*) &un, sizeof(un)) < 0) {
> +        LOGED(ERROR, domid, "bind('%s') failed", path);
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }
> +
> +    if (listen(fd, 1) < 0) {
> +        LOGED(ERROR, domid, "listen() failed");
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }
> +
> +    *fd_r = fd;
> +    rc = 0;
> +
> +out:
> +    if (rc && fd >= 0)
> +        close(fd);
> +    return rc;
> +}
> +
>  static int libxl__build_device_model_args_new(libxl__gc *gc,
>                                          const char *dm, int guest_domid,
>                                          const libxl_domain_config *guest_config,
>                                          char ***args, char ***envs,
>                                          const libxl__domain_build_state *state,
> -                                        int *dm_state_fd)
> +                                        int *dm_state_fd, int *dm_monitor_fd)
>  {
>      const libxl_domain_create_info *c_info = &guest_config->c_info;
>      const libxl_domain_build_info *b_info = &guest_config->b_info;
> @@ -949,10 +997,25 @@ static int libxl__build_device_model_args_new(libxl__gc *gc,
>                        GCSPRINTF("%d", guest_domid), NULL);
>  
>      flexarray_append(dm_args, "-chardev");
> -    flexarray_append(dm_args,
> -                     GCSPRINTF("socket,id=libxl-cmd,"
> -                               "path=%s,server,nowait",
> -                               libxl__qemu_qmp_path(gc, guest_domid)));
> +    /* If we have to use dm_restrict, QEMU need to be new enough and will have
> +     * the new interface where we can pre-open the QMP socket. */
> +    if (libxl_defbool_val(b_info->dm_restrict))
> +    {
> +        int rc;
> +
> +        rc = libxl__pre_open_qmp_socket(gc, guest_domid, dm_monitor_fd);
> +        if (rc)
> +            return rc;
> +
> +        flexarray_append(dm_args,
> +                         GCSPRINTF("socket,id=libxl-cmd,fd=%d,server,nowait",
> +                                   *dm_monitor_fd));
> +    } else {
> +        flexarray_append(dm_args,
> +                         GCSPRINTF("socket,id=libxl-cmd,"
> +                                   "path=%s,server,nowait",
> +                                   libxl__qemu_qmp_path(gc, guest_domid)));
> +    }
>  
>      flexarray_append(dm_args, "-no-shutdown");
>      flexarray_append(dm_args, "-mon");
> @@ -1731,7 +1794,8 @@ static int libxl__build_device_model_args(libxl__gc *gc,
>                                          const libxl_domain_config *guest_config,
>                                          char ***args, char ***envs,
>                                          const libxl__domain_build_state *state,
> -                                        int *dm_state_fd)
> +                                        int *dm_state_fd,
> +                                        int *dm_monitor_fd)

You cna place dm_monitor_fd on the same line.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 27/32] libxl: QEMU startup sync based on QMP
  2018-07-27 14:06 ` [PATCH v4 27/32] libxl: QEMU startup sync based on QMP Anthony PERARD
@ 2018-08-02 15:06   ` Roger Pau Monné
  0 siblings, 0 replies; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 15:06 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:06:09PM +0100, Anthony PERARD wrote:
> This is only activated when dm_restrict=1, as explained in the previous
> patch "libxl_dm: Pre-open QMP socket for QEMU"
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

Just one nit...

> ---
> 
> Notes:
>     v4:
>         moved to libxl__dm_spawn_* from libxl__spawn_*
> 
>  tools/libxl/libxl_dm.c       | 52 ++++++++++++++++++++++++++++++++++++
>  tools/libxl/libxl_internal.h |  1 +
>  2 files changed, 53 insertions(+)
> 
> diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
> index 9e3e501457..0c11e96a5d 100644
> --- a/tools/libxl/libxl_dm.c
> +++ b/tools/libxl/libxl_dm.c
> @@ -2290,6 +2290,8 @@ static void device_model_startup_failed(libxl__egc *egc,
>                                          int rc);
>  static void device_model_detached(libxl__egc *egc,
>                                    libxl__spawn_state *spawn);
> +static void device_model_qmp_cb(libxl__egc *egc, libxl__ev_qmp *ev,
> +                                const libxl__json_object *response, int rc);
>  
>  /* our "next step" function, called from those callbacks and elsewhere */
>  static void device_model_spawn_outcome(libxl__egc *egc,
> @@ -2421,6 +2423,17 @@ retry_transaction:
>      spawn->failure_cb = device_model_startup_failed;
>      spawn->detached_cb = device_model_detached;
>  
> +    libxl__ev_qmp_init(&dmss->qmp);
> +    if (dm_monitor_fd >= 0) {
> +        /* There is a valid QMP socket available now,
> +         * use it to find out when QEMU is ready */
> +        dmss->qmp.callback = device_model_qmp_cb;
> +        dmss->qmp.domid = domid;
> +        dmss->qmp.cfd = NULL;
> +        rc = libxl__ev_qmp_send(gc, &dmss->qmp, "query-status", NULL);
> +        if (rc) goto out_close;
> +    }
> +
>      rc = libxl__spawn_spawn(egc, spawn);
>      if (rc < 0)
>          goto out_close;
> @@ -2490,6 +2503,43 @@ static void device_model_detached(libxl__egc *egc,
>      device_model_spawn_outcome(egc, dmss, 0);
>  }
>  
> +static void device_model_qmp_cb(libxl__egc *egc, libxl__ev_qmp *ev,
> +                                const libxl__json_object *response,
> +                                int rc)
> +{
> +    EGC_GC;
> +    libxl__dm_spawn_state *dmss = CONTAINER_OF(ev, *dmss, qmp);
> +    const libxl__json_object *o;
> +    const char *status;
> +
> +    libxl__ev_qmp_dispose(gc, ev);
> +
> +    if (rc)
> +        goto failed;
> +
> +    o = libxl__json_map_get("status", response, JSON_STRING);
> +    if (!o) {
> +        LOGD(DEBUG, ev->domid, "QMP unexpected response");
> +        rc = ERROR_FAIL;
> +        goto failed;
> +    }
> +    status = libxl__json_object_get_string(o);
> +    if (!strcmp(status, "running")) {
> +        /* success */
> +    } else {
> +        LOGD(DEBUG, ev->domid, "Unexpected QEMU status: %s", status);
> +        rc = ERROR_FAIL;
> +        goto failed;
> +    }

Isn't it clearer to just use:

if (strcmp(status, "running")) {
    /* Failure. */
}

The empty success branch doesn't look very useful.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 28/32] libxl_qmp: Store advertised QEMU version in libxl__ev_qmp
  2018-07-27 14:06 ` [PATCH v4 28/32] libxl_qmp: Store advertised QEMU version in libxl__ev_qmp Anthony PERARD
@ 2018-08-02 15:08   ` Roger Pau Monné
  2018-08-06 16:52     ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 15:08 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:06:10PM +0100, Anthony PERARD wrote:
> This will be used in a later patch.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
>  tools/libxl/libxl_internal.h |  7 +++++++
>  tools/libxl/libxl_qmp.c      | 16 ++++++++++++++++
>  2 files changed, 23 insertions(+)
> 
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 01c3868748..4fa54cdb6a 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -432,6 +432,13 @@ struct libxl__ev_qmp {
>      libxl__ev_qmp_callback *callback;
>      libxl__carefd *cfd; /* set to send a fd with the command, NULL otherwise */
>  
> +    /* read-only when Connected */
> +    struct {
> +        int major;
> +        int minor;
> +        int micro;
> +    } qemu_version;

I would init those field to some bogus value (-1) to make sure an use
before initialization will more likely cause a failure.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 29/32] libxl: Change libxl__domain_suspend_device_model() to be async.
  2018-07-27 14:06 ` [PATCH v4 29/32] libxl: Change libxl__domain_suspend_device_model() to be async Anthony PERARD
@ 2018-08-02 15:15   ` Roger Pau Monné
  0 siblings, 0 replies; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 15:15 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:06:11PM +0100, Anthony PERARD wrote:
> This create an extra step for the two calls sites of the function.
                                        ^ call
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 30/32] libxl: Re-implement domain_suspend_device_model using libxl__ev_qmp
  2018-07-27 14:06 ` [PATCH v4 30/32] libxl: Re-implement domain_suspend_device_model using libxl__ev_qmp Anthony PERARD
@ 2018-08-02 15:38   ` Roger Pau Monné
  2018-08-06 17:07     ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 15:38 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:06:12PM +0100, Anthony PERARD wrote:
> +static void dm_stopped(libxl__egc *egc, libxl__ev_qmp *ev,
> +                       const libxl__json_object *response, int rc)
> +{
> +    EGC_GC;
> +    libxl__domain_suspend_state *dsps = CONTAINER_OF(ev, *dsps, qmp);
> +    const char *const filename = dsps->dm_savefile;
> +    uint32_t const domid = ev->domid;
> +
> +    if (rc)
> +        goto out;
> +
> +    libxl__carefd_begin();
> +    ev->cfd = libxl__carefd_opened(CTX,
> +                                 open(filename, O_WRONLY | O_CREAT, 0600));
> +    if (!ev->cfd) {
> +        LOGED(ERROR, domid, "Failed to open file %s for QEMU", filename);
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }
> +
> +    ev->callback = dm_state_fd_ready;
> +    rc = libxl__ev_qmp_send(gc, ev, "add-fd", NULL);
> +    if (rc)
> +        goto out;
> +
> +    return;
> +out:

That label would be better named 'error', because it's only used for
the error paths.

> +    if (ev->cfd) {
> +        libxl__carefd_close(ev->cfd);
> +        unlink(filename);
> +        ev->cfd = NULL;
> +    }
> +    dsps->callback_device_model_done(egc, dsps, rc);
> +}
> +
> +static void dm_state_fd_ready(libxl__egc *egc, libxl__ev_qmp *ev,
> +                              const libxl__json_object *response, int rc)
> +{
> +    EGC_GC;
> +    libxl__domain_suspend_state *dsps = CONTAINER_OF(ev, *dsps, qmp);
> +    libxl__json_object *args = NULL;
> +    const libxl__json_object *o;
> +    int fdset;
> +
> +    libxl__carefd_close(ev->cfd);
> +    ev->cfd = NULL;
> +
> +    if (rc)
> +        goto out;
> +
> +    o = libxl__json_map_get("fdset-id", response, JSON_INTEGER);
> +    if (!o) {
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }
> +    fdset = libxl__json_object_get_integer(o);
> +
> +    ev->callback = dm_state_saved;
> +
> +    if (qmp_ev_qemu_check_version(ev, 2, 11, 0))
> +        qmp_parameters_add_bool(gc, &args, "live", dsps->live);
> +    QMP_PARAMETERS_SPRINTF(&args, "filename", "/dev/fdset/%d", fdset);
> +    rc = libxl__ev_qmp_send(gc, ev, "xen-save-devices-state", args);

I think some comments about the logic above would be helpful (at least
for me). Do you need to pass an extra argument to 2.11.0 and higher
versions in order to live-migrate?

> +    if (rc)
> +        goto out;
> +
> +    return;
> +out:

Same here regarding the naming of the label.

> +    if (rc)
> +        unlink(dsps->dm_savefile);
> +    dsps->callback_device_model_done(egc, dsps, rc);
> +}
> +
> +static void dm_state_saved(libxl__egc *egc, libxl__ev_qmp *ev,
> +                           const libxl__json_object *response, int rc)
> +{
> +    EGC_GC;
> +    libxl__domain_suspend_state *dsps = CONTAINER_OF(ev, *dsps, qmp);
> +
> +    if (rc)
> +        unlink(dsps->dm_savefile);

Use the libxl unlink helper.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 31/32] libxl_disk: Cut libxl_cdrom_insert into step
  2018-07-27 14:06 ` [PATCH v4 31/32] libxl_disk: Cut libxl_cdrom_insert into step Anthony PERARD
@ 2018-08-02 15:50   ` Roger Pau Monné
  2018-08-06 17:20     ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-02 15:50 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Jul 27, 2018 at 03:06:13PM +0100, Anthony PERARD wrote:
> This is to prepare libxl_cdrom_insert to be able to send commands to
> QEMU via the libxl__ev_qmp. The next patch is going to make use of it.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
>  tools/libxl/libxl_disk.c | 194 +++++++++++++++++++++++++++------------
>  1 file changed, 137 insertions(+), 57 deletions(-)
> 
> diff --git a/tools/libxl/libxl_disk.c b/tools/libxl/libxl_disk.c
> index e9eceb65e3..c759179628 100644
> --- a/tools/libxl/libxl_disk.c
> +++ b/tools/libxl/libxl_disk.c
> @@ -661,31 +661,55 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
>      return rc;
>  }
>  
> +typedef struct {
> +    libxl__ao *ao;
> +    libxl_domain_config d_config;
> +    const char *be_path;
> +    const char *libxl_path;
> +    libxl_device_disk *disk;
> +    libxl_device_disk disk_empty;
> +    libxl_device_disk disk_saved;
> +    int dm_ver;
> +    int domid;
> +    libxl__domain_userdata_lock *lock;
> +} libxl__cdrom_insert_state;
> +static void cdrom_insert_ejected(libxl__egc *egc,
> +                                 libxl__cdrom_insert_state *cis);
> +static void cdrom_insert_inserted(libxl__egc *egc,
> +                                  libxl__cdrom_insert_state *cis);
> +static void cdrom_insert_done(libxl__egc *egc,
> +                              libxl__cdrom_insert_state *cis,
> +                              int rc);

Can you provide a comment explaining how is this supposed to work? The
current code is already quite convoluted IMO (maybe because I'm not
familiar with it), so I think a comment would help reviewers.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 12/32] libxl: Design of an async API to issue QMP commands to QEMUç
  2018-08-02  9:01   ` [PATCH v4 12/32] libxl: Design of an async API to issue QMP commands to QEMUç Roger Pau Monné
@ 2018-08-03 11:18     ` Anthony PERARD
  2018-08-03 13:55       ` Roger Pau Monné
  0 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-08-03 11:18 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 11:01:43AM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:05:54PM +0100, Anthony PERARD wrote:
> > All the functions will be implemented in later patches.
> > 
> > This patch includes the API that libxl can use to send QMP commands to
> > QEMU.
> > 
> > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> > ---
> >  tools/libxl/libxl_internal.h | 76 +++++++++++++++++++++++++++++++++++-
> >  1 file changed, 74 insertions(+), 2 deletions(-)
> > 
> > diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> > index 5b71a23d23..c453ac10a5 100644
> > --- a/tools/libxl/libxl_internal.h
> > +++ b/tools/libxl/libxl_internal.h
> > @@ -202,6 +202,8 @@ typedef struct libxl__ao libxl__ao;
> >  typedef struct libxl__aop_occurred libxl__aop_occurred;
> >  typedef struct libxl__osevent_hook_nexus libxl__osevent_hook_nexus;
> >  typedef struct libxl__osevent_hook_nexi libxl__osevent_hook_nexi;
> > +typedef struct libxl__json_object libxl__json_object;
> > +typedef struct libxl__carefd libxl__carefd;
> >  
> >  typedef struct libxl__domain_create_state libxl__domain_create_state;
> >  typedef void libxl__domain_create_cb(struct libxl__egc *egc,
> > @@ -357,6 +359,76 @@ struct libxl__ev_child {
> >      LIBXL_LIST_ENTRY(struct libxl__ev_child) entry;
> >  };
> >  
> > +/*
> > + * QMP asynchronous calls
> > + */
> 
> Place the title in the same comment block?

Will do.

> > +/*
> > + * This facility allows a command to be sent to QEMU, and the response to be
> > + * handed to a callback function.  Each libxl__ev_qmp handles zero or one
> 
> Do you really mean 'zero or one' or 'zero or more'?

It is zero or one. But I'm not sur that extra sentence is usefull.
Initially, it was followed by "if multiple commands are to be sent
concurrently, multiple libxl__ev_qmp's must be used."

But concurency between multiple libxl__ev_qmp isn't possible, the second
libxl__ev_qmp created will have to wait until the first one is been
disposed of. But sending multiple command can be done, by waiting for
the first one to be done, then then the second one. This is why I have
the paragraph about "commands can be chained".

> > + * outstanding command.
> > + *
> > + * Commands can be chained, with a same connection. (e.g. "add-fd" will need to
>                                     ^ the
> > + * be chained to the next command). A libxl__ev_qmp can be reused when the
>                                                                      ^ after
> > + * callback is been called in order to use the same connection.
>                ^ has

Writing "after the callback has been called", would that mean that one
would need to wait that the callback returns before reusing the
libxl__ev_qmp?

That is what I meant, there is no need to wait for the callback to
return before reusing the same libxl__ev_qmp.

> > + *
> > + * Only one connection at a time can be made to one QEMU, so avoid keeping a
>                                                                ^ to

"To avoid" feels like a how-to, I intended to write what should be done
and that it is not an option.

> > + * libxl__ev_qmp Connected for to long and call libxl__ev_qmp_dispose as soon
>                     ^ unneeded cap        ^ remove 'and'

The use of the capital was an attempt to say that it is one of the
possible states in which libxl__ev_qmp can be.

> > + * as it is not needed anymore.
> > + *
> > + * Possible states of a libxl__ev_qmp:
> > + *  Undefined
> > + *    Might contain anything.
> > + *  Idle
> > + *    Struct contents are defined enough to pass to any libxl__ev_qmp_*
> > + *    functions.
>          ^ function
> > + *    The struct does not contain references to any allocated private resources
> > + *    so can be thrown away.
> 
> I would add '... can be thrown away without any teardown.'

I don't think that's usefull to point out. One would have to call the
teardown function (_dispose) in order to have an Idle state, anyway.

> > + *  Active
> > + *    Currently waiting for the callback to be called.
> > + *    _dispose must be called to reclaim resources.
> > + *  Connected
> > + *    Struct contain allocated ressources.
> > + *    Calling _send() with this same ev will use the same QMP connection.
> > + *    _dispose() must be called to reclaim resources.
> > + *
> > + * libxl__ev_qmp_init: Undefined/Idle -> Idle
> > + *
> > + * libxl__ev_qmp_send: Idle/Connected -> Active (on error: Idle)
> > + *    Sends a command to QEMU.
> > + *    callback will be called when a response is received or when an error
> > + *    as occured.
> > + *
> > + * libxl__ev_qmp_dispose: Connected/Active/Idle -> Idle
> > + *
> > + * callback: When called: Active -> Connected
> > + *    When called, ev is Connected and can be reused or disposed of.
> > + *    When an error occured, it is called with response == NULL and the error
>          ^ If
> > + *    code in rc.
> > + *    The callback is only called once.
> > + */
> > +typedef struct libxl__ev_qmp libxl__ev_qmp;
> > +typedef void libxl__ev_qmp_callback(libxl__egc *egc, libxl__ev_qmp *ev,
> > +                                    const libxl__json_object *response,
> > +                                    int rc);
> > +
> > +_hidden void libxl__ev_qmp_init(libxl__ev_qmp *ev);
> > +_hidden int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
> > +                               const char *cmd, libxl__json_object *args);
> > +_hidden void libxl__ev_qmp_dispose(libxl__gc *gc, libxl__ev_qmp *ev);
> > +
> > +struct libxl__ev_qmp {
> > +    /* caller should include this in their own struct */
> > +    /* caller must fill these in, and they must all remain valid */
>                                                    ^ no need for 'all'
> > +    uint32_t domid;
> 
> Strictly speaking domid is an uint16_t.

Nothing in libxl agrees with this statement. domid is almost always
stored in an uint32_t (sometime an int). There's event a libxl_domid
type (I just found out!) which is uint32_t.

Maybe I could try to use libxl_domid, and try to spread it's usage
inside libxl.

> > +    libxl__ev_qmp_callback *callback;
> > +    libxl__carefd *cfd; /* set to send a fd with the command, NULL otherwise */
> > +
> > +    /* remaining fields are private to libxl_ev_qmp_* */
> > +
> 
> Extra newline?
> 
> > +    int id;
> > +};
> > +
> 
> Thanks, Roger.

Thanks,

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 13/32] libxl_qmp: Connect to QMP socket
  2018-08-02  9:35   ` Roger Pau Monné
@ 2018-08-03 13:54     ` Anthony PERARD
  2018-08-03 14:03       ` Roger Pau Monné
  0 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-08-03 13:54 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 11:35:53AM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:05:55PM +0100, Anthony PERARD wrote:
> > +typedef enum {
> > +    qmp_state_disconnected = 1,
> > +    qmp_state_connecting,
> > +    qmp_state_greeting,
> > +    qmp_state_capability_negociation,
> > +    qmp_state_connected,
> > +} libxl__qmp_state;
> > +
> 
> I think this should be declared in libxl_types_internal.idl?

I don't know, I kind of wanted the enum to be contained in libxl_qmp.c,
but then I couldn't use the enum type in the struct here.

Also the idl provides more than needed (conversion to string) and make
the names more verbose, by adding libxl__ prefix.

> And (maybe) a description of each state would be helpful for future
> reference?

Yes, but not in libxl_internal.h, the description should be in
libxl_qmp.c as this qmp_state is not part of the API.

> >  struct libxl__ev_qmp {
> >      /* caller should include this in their own struct */
> >      /* caller must fill these in, and they must all remain valid */
> > @@ -427,6 +435,9 @@ struct libxl__ev_qmp {
> >      /* remaining fields are private to libxl_ev_qmp_* */
> >  
> >      int id;
> > +    libxl__carefd *qmp_cfd;
> > +    libxl__ev_fd qmp_efd;
> > +    libxl__qmp_state qmp_state;
> >  };
> >  
> >  
> > diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> > index c5e05e5679..96a347dd3b 100644
> > --- a/tools/libxl/libxl_qmp.c
> > +++ b/tools/libxl/libxl_qmp.c
> > +out:
> > +    libxl__carefd_close(ev->qmp_cfd);
> > +    ev->qmp_cfd = NULL;
> > +    return rc;
> > +}
> > +
> > +
> 
> Double newline.

I like space, it gives some separations before the next big chunk of
code.

> > +/*
> > + * libxl__ev_qmp_*
> > + */
> > +
> > +void libxl__ev_qmp_init(libxl__ev_qmp *ev)
> > +{
> > +    ev->id = -1;
> > +
> > +    ev->qmp_cfd = NULL;
> > +    libxl__ev_fd_init(&ev->qmp_efd);
> > +    ev->qmp_state = qmp_state_disconnected;
> > +}
> > +
> > +int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
> > +                       const char *cmd, libxl__json_object *args)
> > +{
> > +    int rc;
> > +
> > +    LOGD(DEBUG, ev->domid, " ev %p, cmd '%s'", ev, cmd);
> > +
> > +    /* Connect to QEMU if not already connected */
> > +    rc = qmp_ev_connect(gc, ev);
> > +
> > +    return rc;
> 
> You can get rid of rc and just use:
> 
> return qmp_ev_connect(gc, ev);

Will do. (And introduce the rc in the following patches.)

> > +}
> > +
> > +void libxl__ev_qmp_dispose(libxl__gc *gc, libxl__ev_qmp *ev)
> > +{
> > +    LOGD(DEBUG, ev->domid, " ev %p", ev);
> > +
> > +    libxl__ev_fd_deregister(gc, &ev->qmp_efd);
> > +    libxl__carefd_close(ev->qmp_cfd);
> > +    ev->qmp_cfd = NULL;
> 
> No need to set qmp_cfd to NULL if you call _init afterwards.

Will not do then.

> > +
> > +    libxl__ev_qmp_init(ev);
> 
> Thanks, Roger.

Thanks Roger,

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 12/32] libxl: Design of an async API to issue QMP commands to QEMUç
  2018-08-03 11:18     ` Anthony PERARD
@ 2018-08-03 13:55       ` Roger Pau Monné
  2018-08-03 14:45         ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-03 13:55 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Aug 03, 2018 at 12:18:02PM +0100, Anthony PERARD wrote:
> On Thu, Aug 02, 2018 at 11:01:43AM +0200, Roger Pau Monné wrote:
> > On Fri, Jul 27, 2018 at 03:05:54PM +0100, Anthony PERARD wrote:
> > > +/*
> > > + * This facility allows a command to be sent to QEMU, and the response to be
> > > + * handed to a callback function.  Each libxl__ev_qmp handles zero or one
> > 
> > Do you really mean 'zero or one' or 'zero or more'?
> 
> It is zero or one. But I'm not sur that extra sentence is usefull.
> Initially, it was followed by "if multiple commands are to be sent
> concurrently, multiple libxl__ev_qmp's must be used."
> 
> But concurency between multiple libxl__ev_qmp isn't possible, the second
> libxl__ev_qmp created will have to wait until the first one is been
> disposed of. But sending multiple command can be done, by waiting for
> the first one to be done, then then the second one. This is why I have
> the paragraph about "commands can be chained".

Then maybe you want to add something along the lines:

"Multiple QMP commands can be queued in a single libxl__ev_qmp
instance, however they will be dispatched in a serialized fashion.
Note also that there can only be a single libxl__ev_qmp instance
active at a time."

> > > + * outstanding command.
> > > + *
> > > + * Commands can be chained, with a same connection. (e.g. "add-fd" will need to
> >                                     ^ the
> > > + * be chained to the next command). A libxl__ev_qmp can be reused when the
> >                                                                      ^ after
> > > + * callback is been called in order to use the same connection.
> >                ^ has
> 
> Writing "after the callback has been called", would that mean that one
> would need to wait that the callback returns before reusing the
> libxl__ev_qmp?
> 
> That is what I meant, there is no need to wait for the callback to
> return before reusing the same libxl__ev_qmp.

You mean that the same ev_qmp can be reused from the callback itself
in order to send more QMP requests?

> > > + *
> > > + * Only one connection at a time can be made to one QEMU, so avoid keeping a
> >                                                                ^ to
> 
> "To avoid" feels like a how-to, I intended to write what should be done
> and that it is not an option.
> 
> > > + * libxl__ev_qmp Connected for to long and call libxl__ev_qmp_dispose as soon
> >                     ^ unneeded cap        ^ remove 'and'
> 
> The use of the capital was an attempt to say that it is one of the
> possible states in which libxl__ev_qmp can be.

Yes, I realized about that later.

> > > + * as it is not needed anymore.
> > > + *
> > > + * Possible states of a libxl__ev_qmp:
> > > + *  Undefined
> > > + *    Might contain anything.
> > > + *  Idle
> > > + *    Struct contents are defined enough to pass to any libxl__ev_qmp_*
> > > + *    functions.
> >          ^ function
> > > + *    The struct does not contain references to any allocated private resources
> > > + *    so can be thrown away.
> > 
> > I would add '... can be thrown away without any teardown.'
> 
> I don't think that's usefull to point out. One would have to call the
> teardown function (_dispose) in order to have an Idle state, anyway.

OK.

> > > +struct libxl__ev_qmp {
> > > +    /* caller should include this in their own struct */
> > > +    /* caller must fill these in, and they must all remain valid */
> >                                                    ^ no need for 'all'
> > > +    uint32_t domid;
> > 
> > Strictly speaking domid is an uint16_t.
> 
> Nothing in libxl agrees with this statement. domid is almost always
> stored in an uint32_t (sometime an int). There's event a libxl_domid
> type (I just found out!) which is uint32_t.
> 
> Maybe I could try to use libxl_domid, and try to spread it's usage
> inside libxl.

Yes, that would be my preference. I didn't know either that there was
a libxl_domid type.

Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 13/32] libxl_qmp: Connect to QMP socket
  2018-08-03 13:54     ` Anthony PERARD
@ 2018-08-03 14:03       ` Roger Pau Monné
  2018-08-21  8:22         ` Wei Liu
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-03 14:03 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Aug 03, 2018 at 02:54:20PM +0100, Anthony PERARD wrote:
> On Thu, Aug 02, 2018 at 11:35:53AM +0200, Roger Pau Monné wrote:
> > On Fri, Jul 27, 2018 at 03:05:55PM +0100, Anthony PERARD wrote:
> > > +typedef enum {
> > > +    qmp_state_disconnected = 1,
> > > +    qmp_state_connecting,
> > > +    qmp_state_greeting,
> > > +    qmp_state_capability_negociation,
> > > +    qmp_state_connected,
> > > +} libxl__qmp_state;
> > > +
> > 
> > I think this should be declared in libxl_types_internal.idl?
> 
> I don't know, I kind of wanted the enum to be contained in libxl_qmp.c,
> but then I couldn't use the enum type in the struct here.
> 
> Also the idl provides more than needed (conversion to string) and make
> the names more verbose, by adding libxl__ prefix.

Hm, yes. libxl_types_internal.idl doesn't seem to be used much. I will
leave this to the maintainers because it's not clear to me when a
declaration should live in the IDL or the private header directly.

> > And (maybe) a description of each state would be helpful for future
> > reference?
> 
> Yes, but not in libxl_internal.h, the description should be in
> libxl_qmp.c as this qmp_state is not part of the API.

I would place the description together with the declaration of the
type, or else it's very easy for things to get out of sync.

Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 14/32] libxl_qmp: Implement fd callback and read data
  2018-08-02  9:56   ` Roger Pau Monné
@ 2018-08-03 14:32     ` Anthony PERARD
  2018-08-03 15:24       ` Roger Pau Monné
  0 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-08-03 14:32 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 11:56:11AM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:05:56PM +0100, Anthony PERARD wrote:
> > +        /* The -1 is because there is always space for a NUL character */
> > +        r = read(fd, ev->rx_buf + ev->buf_used,
> > +                 ev->buf_size - ev->buf_used - 1);
> > +        if (r < 0) {
> > +            if (errno == EINTR) continue;
> > +            assert(errno);
> > +            if (errno == EWOULDBLOCK) {
> > +                return 0;
> > +            }
> > +            LOGED(ERROR, ev->domid, "error reading QMP socket");
> > +            return ERROR_FAIL;
> 
> I think it would be clearer to use:
> 
> assert(errno);
> switch (errno) {
> case EINTR:
>     continue;
> case EWOULDBLOCK
>     return 0;
> default:
>     LOGED(...)

That's not the same. In the patch, the only errno allowed is EINTR,
anything else is consider a programmer's mistake. For users (build with
NDEBUG), EWOULDBLOCK is also allowed and not considered an error and
other errno will attempt to let libxl generate a usefull error, instead
of an abort().

> > +        }
> > +        break;
> > +    }
> > +
> > +    if (r == 0) {
> > +        LOGD(ERROR, ev->domid, "No data read on QMP socket");
> > +        return 0;
> > +    }
> > +
> > +    LOG_QMP("received %ldB: '%.*s'", r, (int)r, ev->rx_buf + ev->buf_used);
> > +
> > +    ev->buf_used += r;
> 
> Hm, don't you need to do this inside of a loop together with the
> realloc, in case the data on the fd is bigger than the current space
> on the buffer, and you need to keep growing it until you hit
> EWOULDBLOCK?
> 
> I think with the current approach you can leave data pending in the fd
> if the buffer happens to be smaller than the pending data in the fd?

You would think that, but the read loop isn't in this file. The loop is
part of the libxl__ev_fd. As long as there is data to read from the fd,
the callback (initialized by libxl__ev_fd_register) is going to be
called. This callback, which ultimatly calls qmp_ev_callback_readable,
will attempt to read only once (unless interrupted, EINTR). EWOULDBLOCK
should never be seen.

There is a poll() somewhere in libxl which takes care of checking if
there's data left in the fd, and will call the callback associated with
that fd.

> >  static void qmp_ev_fd_callback(libxl__egc *egc, libxl__ev_fd *ev_fd,
> >                                 int fd, short events, short revents)
> >  {
> > +    EGC_GC;
> > +    int rc;
> > +
> > +    libxl__ev_qmp *ev = CONTAINER_OF(ev_fd, *ev, qmp_efd);
> > +
> > +    if (revents & (POLLHUP)) {
> > +        LOGD(DEBUG, ev->domid, "received POLLHUP from QMP socket");
> > +        qmp_ev_callback_error(egc, ev);
> > +        return;
> > +    }
> > +    if (revents & ~(POLLIN|POLLOUT)) {
> > +        LOGD(ERROR, ev->domid,
> > +             "unexpected poll event 0x%x on QMP socket (expected POLLIN "
> > +             "and/or POLLOUT)",
> > +            revents);
> > +        qmp_ev_callback_error(egc, ev);
> > +        return;
> > +    }
> > +
> > +    if (revents & POLLIN) {
> > +        rc = qmp_ev_callback_readable(egc, ev, fd);
> > +        if (rc)
> > +            goto out;
> > +    }
> > +out:
> 
> Since you already have an out label that calls _error, why not use it
> for the failure paths above by manually setting rc?

Right, I'll make better use of this out label.

> > +    if (rc) {
> > +        qmp_ev_callback_error(egc, ev);
> > +    }
> >  }
> >  
> >  static int qmp_ev_connect(libxl__gc *gc, libxl__ev_qmp *ev)
> > @@ -1346,6 +1442,8 @@ void libxl__ev_qmp_init(libxl__ev_qmp *ev)
> >      ev->qmp_cfd = NULL;
> >      libxl__ev_fd_init(&ev->qmp_efd);
> >      ev->qmp_state = qmp_state_disconnected;
> > +
> > +    ev->rx_buf = NULL;
> 
> Aren't you missing a
> 
> ev->buf_size = ev->buf_used = ev->buf_consumed = 0;

Not really, if there is no rx_buf, those variables can be undefined.

> >  }
> >  
> >  int libxl__ev_qmp_send(libxl__gc *gc, libxl__ev_qmp *ev,
> > @@ -1365,6 +1463,9 @@ void libxl__ev_qmp_dispose(libxl__gc *gc, libxl__ev_qmp *ev)
> >  {
> >      LOGD(DEBUG, ev->domid, " ev %p", ev);
> >  
> > +    free(ev->rx_buf);
> > +    ev->rx_buf = NULL;
> 
> I don't think you need to set rx_buf to NULL if you call _init
> afterwards.

Will remove it.

Thanks,

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 12/32] libxl: Design of an async API to issue QMP commands to QEMUç
  2018-08-03 13:55       ` Roger Pau Monné
@ 2018-08-03 14:45         ` Anthony PERARD
  2018-08-03 15:30           ` Roger Pau Monné
  0 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-08-03 14:45 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Aug 03, 2018 at 03:55:48PM +0200, Roger Pau Monné wrote:
> On Fri, Aug 03, 2018 at 12:18:02PM +0100, Anthony PERARD wrote:
> > On Thu, Aug 02, 2018 at 11:01:43AM +0200, Roger Pau Monné wrote:
> > > On Fri, Jul 27, 2018 at 03:05:54PM +0100, Anthony PERARD wrote:
> > > > +/*
> > > > + * This facility allows a command to be sent to QEMU, and the response to be
> > > > + * handed to a callback function.  Each libxl__ev_qmp handles zero or one
> > > 
> > > Do you really mean 'zero or one' or 'zero or more'?
> > 
> > It is zero or one. But I'm not sur that extra sentence is usefull.
> > Initially, it was followed by "if multiple commands are to be sent
> > concurrently, multiple libxl__ev_qmp's must be used."
> > 
> > But concurency between multiple libxl__ev_qmp isn't possible, the second
> > libxl__ev_qmp created will have to wait until the first one is been
> > disposed of. But sending multiple command can be done, by waiting for
> > the first one to be done, then then the second one. This is why I have
> > the paragraph about "commands can be chained".
> 
> Then maybe you want to add something along the lines:
> 
> "Multiple QMP commands can be queued in a single libxl__ev_qmp
> instance, however they will be dispatched in a serialized fashion.
> Note also that there can only be a single libxl__ev_qmp instance
> active at a time."

That's not true, I don't think adding facilities to queue commands will
be usefull, usually, one will need to wait for a response to the first
command in order to prepare a second one. It is rare in libxl that
several commands can be prepared and queued in advance. User of this API
can do the queuing themself.

As for the single active instance of libxl__ev_qmp, that isn't true
easier, several libxl__ev_qmp can be in the state "Active" at the same
time. But only one can be in the "Connected" state at the same time (in
relation to a single qemu) due to the way qemu handles QMP connections.

> > > > + * outstanding command.
> > > > + *
> > > > + * Commands can be chained, with a same connection. (e.g. "add-fd" will need to
> > >                                     ^ the
> > > > + * be chained to the next command). A libxl__ev_qmp can be reused when the
> > >                                                                      ^ after
> > > > + * callback is been called in order to use the same connection.
> > >                ^ has
> > 
> > Writing "after the callback has been called", would that mean that one
> > would need to wait that the callback returns before reusing the
> > libxl__ev_qmp?
> > 
> > That is what I meant, there is no need to wait for the callback to
> > return before reusing the same libxl__ev_qmp.
> 
> You mean that the same ev_qmp can be reused from the callback itself
> in order to send more QMP requests?

Yes, that's right.

> > > > + *
> > > > + * Only one connection at a time can be made to one QEMU, so avoid keeping a
> > >                                                                ^ to
> > 
> > "To avoid" feels like a how-to, I intended to write what should be done
> > and that it is not an option.
> > 
> > > > + * libxl__ev_qmp Connected for to long and call libxl__ev_qmp_dispose as soon
> > >                     ^ unneeded cap        ^ remove 'and'
> > 
> > The use of the capital was an attempt to say that it is one of the
> > possible states in which libxl__ev_qmp can be.
> 
> Yes, I realized about that later.

:-), good.

> > > > +struct libxl__ev_qmp {
> > > > +    /* caller should include this in their own struct */
> > > > +    /* caller must fill these in, and they must all remain valid */
> > >                                                    ^ no need for 'all'
> > > > +    uint32_t domid;
> > > 
> > > Strictly speaking domid is an uint16_t.
> > 
> > Nothing in libxl agrees with this statement. domid is almost always
> > stored in an uint32_t (sometime an int). There's event a libxl_domid
> > type (I just found out!) which is uint32_t.
> > 
> > Maybe I could try to use libxl_domid, and try to spread it's usage
> > inside libxl.
> 
> Yes, that would be my preference. I didn't know either that there was
> a libxl_domid type.

Well, beside the generated headers (libxl_types.idl), there is only 4
use of it (or 2 functions prototypes).

Thanks,

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 14/32] libxl_qmp: Implement fd callback and read data
  2018-08-03 14:32     ` Anthony PERARD
@ 2018-08-03 15:24       ` Roger Pau Monné
  2018-08-06 15:01         ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-03 15:24 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Aug 03, 2018 at 03:32:09PM +0100, Anthony PERARD wrote:
> On Thu, Aug 02, 2018 at 11:56:11AM +0200, Roger Pau Monné wrote:
> > On Fri, Jul 27, 2018 at 03:05:56PM +0100, Anthony PERARD wrote:
> > > +        /* The -1 is because there is always space for a NUL character */
> > > +        r = read(fd, ev->rx_buf + ev->buf_used,
> > > +                 ev->buf_size - ev->buf_used - 1);
> > > +        if (r < 0) {
> > > +            if (errno == EINTR) continue;
> > > +            assert(errno);
> > > +            if (errno == EWOULDBLOCK) {
> > > +                return 0;
> > > +            }
> > > +            LOGED(ERROR, ev->domid, "error reading QMP socket");
> > > +            return ERROR_FAIL;
> > 
> > I think it would be clearer to use:
> > 
> > assert(errno);
> > switch (errno) {
> > case EINTR:
> >     continue;
> > case EWOULDBLOCK
> >     return 0;
> > default:
> >     LOGED(...)
> 
> That's not the same. In the patch, the only errno allowed is EINTR,
> anything else is consider a programmer's mistake. For users (build with
> NDEBUG), EWOULDBLOCK is also allowed and not considered an error and
> other errno will attempt to let libxl generate a usefull error, instead
> of an abort().

I'm not sure I follow. According to the man page if read returns -1
errno will always be set to indicate the error, so I'm not sure of the
usefulness of the assert(errno), apart from checking that libc behaves
correctly.

> > > +        }
> > > +        break;
> > > +    }
> > > +
> > > +    if (r == 0) {
> > > +        LOGD(ERROR, ev->domid, "No data read on QMP socket");
> > > +        return 0;
> > > +    }
> > > +
> > > +    LOG_QMP("received %ldB: '%.*s'", r, (int)r, ev->rx_buf + ev->buf_used);
> > > +
> > > +    ev->buf_used += r;
> > 
> > Hm, don't you need to do this inside of a loop together with the
> > realloc, in case the data on the fd is bigger than the current space
> > on the buffer, and you need to keep growing it until you hit
> > EWOULDBLOCK?
> > 
> > I think with the current approach you can leave data pending in the fd
> > if the buffer happens to be smaller than the pending data in the fd?
> 
> You would think that, but the read loop isn't in this file. The loop is
> part of the libxl__ev_fd.

Then why do you have a loop here to handle EINTR?

If the loop is somewhere else isn't it capable of handling EINTR like
it handles partial reads? Adding the loop here just to handle EINTR
makes it look like this is the complete read loop.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 12/32] libxl: Design of an async API to issue QMP commands to QEMUç
  2018-08-03 14:45         ` Anthony PERARD
@ 2018-08-03 15:30           ` Roger Pau Monné
  0 siblings, 0 replies; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-03 15:30 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Aug 03, 2018 at 03:45:39PM +0100, Anthony PERARD wrote:
> On Fri, Aug 03, 2018 at 03:55:48PM +0200, Roger Pau Monné wrote:
> > On Fri, Aug 03, 2018 at 12:18:02PM +0100, Anthony PERARD wrote:
> > > On Thu, Aug 02, 2018 at 11:01:43AM +0200, Roger Pau Monné wrote:
> > > > On Fri, Jul 27, 2018 at 03:05:54PM +0100, Anthony PERARD wrote:
> > > > > +/*
> > > > > + * This facility allows a command to be sent to QEMU, and the response to be
> > > > > + * handed to a callback function.  Each libxl__ev_qmp handles zero or one
> > > > 
> > > > Do you really mean 'zero or one' or 'zero or more'?
> > > 
> > > It is zero or one. But I'm not sur that extra sentence is usefull.
> > > Initially, it was followed by "if multiple commands are to be sent
> > > concurrently, multiple libxl__ev_qmp's must be used."
> > > 
> > > But concurency between multiple libxl__ev_qmp isn't possible, the second
> > > libxl__ev_qmp created will have to wait until the first one is been
> > > disposed of. But sending multiple command can be done, by waiting for
> > > the first one to be done, then then the second one. This is why I have
> > > the paragraph about "commands can be chained".
> > 
> > Then maybe you want to add something along the lines:
> > 
> > "Multiple QMP commands can be queued in a single libxl__ev_qmp
> > instance, however they will be dispatched in a serialized fashion.
> > Note also that there can only be a single libxl__ev_qmp instance
> > active at a time."
> 
> That's not true, I don't think adding facilities to queue commands will
> be usefull, usually, one will need to wait for a response to the first
> command in order to prepare a second one. It is rare in libxl that
> several commands can be prepared and queued in advance. User of this API
> can do the queuing themself.
> 
> As for the single active instance of libxl__ev_qmp, that isn't true
> easier, several libxl__ev_qmp can be in the state "Active" at the same
> time. But only one can be in the "Connected" state at the same time (in
> relation to a single qemu) due to the way qemu handles QMP connections.

OK, I think you should remove that line (the zero or one...).
Hopefully the text in the "commands can be chained" part will already
make this clear.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 17/32] libxl_qmp: Parse JSON input from QMP
  2018-08-02 10:25   ` Roger Pau Monné
@ 2018-08-03 15:33     ` Anthony PERARD
  2018-08-06 11:17       ` Roger Pau Monné
  0 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-08-03 15:33 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 12:25:53PM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:05:59PM +0100, Anthony PERARD wrote:
> > +    /* workaround strstr limitation */
> > +    ev->rx_buf[ev->buf_used] = '\0';
> 
> Why not use strnstr to limit the size of the rx_buf that's searched? I
> think that would allow you to get rid of the '-1' that you have to
> take into account in several places?

Because that's a FreeBSD API, at least on my machine (Arch Linux), to
attempt to use it, I will need to install a new package, libbsd. So I
don't think strnstr was an option.

> > +
> > +    /*
> > +     * Search for the end of a QMP message: "\r\n" in the newly received
> > +     * bytes + the last byte on the previous read() if any
> > +     *
> > +     * end: This will point to the byte right after \r\n
> > +     */
> > +    end = strstr(ev->rx_buf + ev->buf_used - r
> > +                 + (ev->buf_used - r == 0 ? 0 : -1),
> > +                 "\r\n");
> > +    if (end)
> > +        end += 2;
> > +
> > +    while (end) {
> > +        libxl__json_object *o;
> > +        size_t len;
> > +        char *s;
> > +
> > +        /* Start parsing from s */
> > +        s = ev->rx_buf + ev->buf_consumed;
> > +        /* Findout how much can be parsed */
> > +        len = end - s;
> 
> You can init both s and len above when defining them.

Would not that looks a bit weird?

+    while (end) {
+        libxl__json_object *o;
+        /* Start parsing from s */
+        char *s = ev->rx_buf + ev->buf_consumed;
+        /* Findout how much can be parsed */
+        size_t len = end - s;

But that can be done.

> > +
> > +        LOG_QMP("parsing %luB: '%.*s'", len, (int)len, s);
> > +
> > +        /* Replace \n by \0 so that libxl__json_parse can use strlen */
> > +        s[len - 1] = '\0';
> > +        o = libxl__json_parse(gc, s); //, len);
> 
> Doesn't look like the above line will compile.

:-(, just left over from previous attempt.

> > +
> > +        if (!o) {
> > +            LOGD(ERROR, ev->domid, "Parse error");
> > +            return ERROR_FAIL;
> > +        }
> > +
> > +        ev->buf_consumed += len;
> > +
> > +        if (ev->buf_consumed >= ev->buf_used) {
> 
> I'm not sure I see how the above check can ever be true, you search
> the buffer up to buf_used, so 'end' can never be past buf_used?

We should have buf_consumed == buf_used when everything received has
been parsed.

Nevertheless, I'll do a debug run to find out, if that free ever happen.

Also, if for e.g., we receive:

nop\r\n
       ^ end should point here, right after the \n, or after the last
       byte received in this case, as per my comment abrove.

> > +            free(ev->rx_buf);
> > +            ev->rx_buf = NULL;
> > +        }
> > +

Thanks,

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 18/32] libxl_qmp: Separate QMP message generation from qmp_send_prepare
  2018-08-02 10:34   ` Roger Pau Monné
@ 2018-08-03 15:43     ` Anthony PERARD
  0 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-08-03 15:43 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 12:34:31PM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:06:00PM +0100, Anthony PERARD wrote:
> > To be able to re-use qmp_prepare_qmp_cmd with libxl__ev_qmp.
> > 
> > Also, add the QMP end of command '\r\n' into the generated string.
> > 
> > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> > ---
> >  tools/libxl/libxl_qmp.c | 62 +++++++++++++++++++++++++++++------------
> >  1 file changed, 44 insertions(+), 18 deletions(-)
> > 
> > diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> > index 665b6f5d05..38a4395266 100644
> > --- a/tools/libxl/libxl_qmp.c
> > +++ b/tools/libxl/libxl_qmp.c
> > @@ -578,17 +578,17 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp)
> >      return rc;
> >  }
> >  
> > -static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp,
> > -                              const char *cmd, libxl__json_object *args,
> > -                              qmp_callback_t callback, void *opaque,
> > -                              qmp_request_context *context)
> > -{
> > -    const unsigned char *buf = NULL;
> > -    char *ret = NULL;
> > -    libxl_yajl_length len = 0;
> > +static char *qmp_prepare_qmp_cmd(libxl__gc *gc,
> 
> Is it really needed to have qmp twice in the function name?
> qmp_prepare_cmd LGTM.

Will change.

> > +                                 const char *cmd,
> > +                                 const libxl__json_object *args,
> > +                                 int id,
> > +                                 size_t *len_r)
> > +{
> > +    const unsigned char *buf;
> 
> While there I would drop the unsigned...

I can't do that unfortunatly, this buffer will hold unsigned char. The
libyajl generated unsigned char strings.

> > +static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp,
> > +                              const char *cmd, libxl__json_object *args,
> > +                              qmp_callback_t callback, void *opaque,
> > +                              qmp_request_context *context,
> > +                              size_t *len_r)
> > +{
> > +    char *buf;
> > +    callback_id_pair *elm;
> > +
> > +    buf = qmp_prepare_qmp_cmd(gc,
> > +                              cmd, args, ++qmp->last_id_used,
> > +                              NULL);
> 
> Indentation is very weird here. AFAICT it can fit in a single line?

History, I guess, where these uses to not fit in a single line. I'll join
the lines.

Thanks,

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 19/32] libxl_qmp: Prepare the command to be sent
  2018-08-02 10:41   ` Roger Pau Monné
@ 2018-08-03 16:35     ` Anthony PERARD
  0 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-08-03 16:35 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 12:41:26PM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:06:01PM +0100, Anthony PERARD wrote:
> > The actual sent will be done in a separate patch.
> > 
> > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> > ---
> >  tools/libxl/libxl_internal.h |  4 ++++
> >  tools/libxl/libxl_qmp.c      | 37 ++++++++++++++++++++++++++++++++++++
> >  2 files changed, 41 insertions(+)
> > 
> > diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> > index 7f200e7a46..110b951bbe 100644
> > --- a/tools/libxl/libxl_internal.h
> > +++ b/tools/libxl/libxl_internal.h
> > @@ -438,6 +438,7 @@ struct libxl__ev_qmp {
> >      libxl__carefd *qmp_cfd;
> >      libxl__ev_fd qmp_efd;
> >      libxl__qmp_state qmp_state;
> > +    unsigned int last_id_used;
> 
> Now there are two last_id_used fields in different structures?
> Shouldn't the previous one be removed when you introduce this new one?

Sorry for the confusion, I'm making modification to the current qmp
engine in order to reuse part that can be reuse in the new, better one.
This is why there's two last_id_used, one for the current
implementation, and one for the new one, libxl__ev_qmp.

Thanks,

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 20/32] libxl_qmp: Handle write to QMP socket
  2018-08-02 11:02   ` Roger Pau Monné
@ 2018-08-03 16:50     ` Anthony PERARD
  0 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-08-03 16:50 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 01:02:13PM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:06:02PM +0100, Anthony PERARD wrote:
> > The libxl__ev_qmp_* will now send the command to QEMU when the socket is
> > ready for writes.
> > 
> > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> 
> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
> 
> > +static int qmp_ev_callback_writable(libxl__gc *gc, libxl__ev_qmp *ev, int fd)
> > +{
> > +    int rc;
> > +    char *buf;
> > +    size_t len;
> > +    int buf_fd = -1;
> 
> I would name this send_fd.

I wonder why I renamed it buf_fd ...
I'll change it to send_fd.

> > +
> > +    /* No need to call qmp_ev_callback_writable again, everything that needs to
> > +     * be send for now will be in this call. */
> > +    libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events & ~POLLOUT);
> 
> I think you do this because you need to wait for this command to
> complete before queuing another command?

It's actually because there is no queuing with this API. There is really
nothing else to send. A user of the API might want to send something
else, but in the meantime, there is nothing to send.

If (hypothetical) there were a queue, everything in the queue could be
sent, without waiting for qemu to respond, and I would turn of the
POLLOUT bit only when the queue was empty.

Thanks,

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU
  2018-08-02 11:17   ` Roger Pau Monné
@ 2018-08-03 17:25     ` Anthony PERARD
  2018-08-06 11:25       ` Roger Pau Monné
  2018-08-21  8:58       ` Wei Liu
  0 siblings, 2 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-08-03 17:25 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 01:17:37PM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:06:04PM +0100, Anthony PERARD wrote:
> > This will handles messages received, and calls callbacks associated with
>             ^ handle
> 
> I'm not sure I understand what's 'This' in the context. Would be good
> if you could spell out what 'This' refers to IMO.

I guess 'patch' will do.

> > the libxl__ev_qmp when the expected response is received.
> > 
> > This also print error messages from QMP on behalf of the callback.
> > +    case LIBXL__QMP_MESSAGE_TYPE_ERROR: {
> > +        const char *s;
> > +        const libxl__json_object *err;
> > +        libxl__qmp_error_class error_class;
> > +
> > +        rc = ERROR_FAIL;
> > +        response = NULL;
> > +
> > +        err = libxl__json_map_get("error", resp, JSON_MAP);
> > +        o = libxl__json_map_get("class", err, JSON_STRING);
> > +        s = libxl__json_object_get_string(o);
> 
> You could init err and s at definition time.

err maybe, but not s, as it's depends on o.

But then, I prefer it that way.

> > +/* return 1 when a user callback as been called */
> > +static int qmp_ev_handle_message(libxl__egc *egc,
> > +                                 libxl__ev_qmp *ev,
> > +                                 const libxl__json_object *resp)
> > +{
> > +    EGC_GC;
> > +    libxl__qmp_message_type type = qmp_response_type(resp);
> > +
> > +    switch (type) {
> > +    case LIBXL__QMP_MESSAGE_TYPE_QMP:
> > +        /* greeting message */
> > +        return 0;
> > +    case LIBXL__QMP_MESSAGE_TYPE_RETURN:
> > +    case LIBXL__QMP_MESSAGE_TYPE_ERROR:
> > +        return qmp_ev_handle_response(egc, ev, resp, type);
> > +    case LIBXL__QMP_MESSAGE_TYPE_EVENT:
> > +        /* Event are ignored */
> > +        return 0;
> > +    case LIBXL__QMP_MESSAGE_TYPE_INVALID:
> > +        return 0;
> 
> Might be good to have a 'default' lable here and print some debug
> message about receiving an unknown QMP message type?

INVALID is already for unknown message type. In this switch are listed
all the possible value that 'type' can get, as per the enum
libxl__qmp_message_type.

I'll add default: abort();

> > diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> > index 4a385801ba..e104fea941 100644
> > --- a/tools/libxl/libxl_types.idl
> > +++ b/tools/libxl/libxl_types.idl
> > @@ -69,6 +69,10 @@ libxl_error = Enumeration("error", [
> >      (-23, "NOTFOUND"),
> >      (-24, "DOMAIN_DESTROYED"), # Target domain ceased to exist during op
> >      (-25, "FEATURE_REMOVED"), # For functionality that has been removed
> > +    (-26, "QMP_GENERIC_ERROR"), # unspecified qmp error
> > +    (-27, "QMP_COMMAND_NOT_FOUND"), # the requested command has not been found
> > +    (-28, "QMP_DEVICE_NOT_ACTIVE"), # a device has failed to be become active
> > +    (-29, "QMP_DEVICE_NOT_FOUND"), # the requested device has not been found
> 
> Do we really need such granularity for QMP errors? Isn't it enough to
> have a single ERROR_QMP or similar?

No I don't think so. QMP_COMMAND_NOT_FOUND can be useful when a qmp
command is removed (there is already one that is deprecated and we use).

The last two could be useful to user of libxl as they could provide
better error messages. xl don't care because whatever error message is
attach to the error, it will be printed.

Thanks,

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 17/32] libxl_qmp: Parse JSON input from QMP
  2018-08-03 15:33     ` Anthony PERARD
@ 2018-08-06 11:17       ` Roger Pau Monné
  0 siblings, 0 replies; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-06 11:17 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Aug 03, 2018 at 04:33:31PM +0100, Anthony PERARD wrote:
> On Thu, Aug 02, 2018 at 12:25:53PM +0200, Roger Pau Monné wrote:
> > On Fri, Jul 27, 2018 at 03:05:59PM +0100, Anthony PERARD wrote:
> > > +    /* workaround strstr limitation */
> > > +    ev->rx_buf[ev->buf_used] = '\0';
> > 
> > Why not use strnstr to limit the size of the rx_buf that's searched? I
> > think that would allow you to get rid of the '-1' that you have to
> > take into account in several places?
> 
> Because that's a FreeBSD API, at least on my machine (Arch Linux), to
> attempt to use it, I will need to install a new package, libbsd. So I
> don't think strnstr was an option.

Oh, that's a shame. It would make the code easier IMO.

> > > +
> > > +    /*
> > > +     * Search for the end of a QMP message: "\r\n" in the newly received
> > > +     * bytes + the last byte on the previous read() if any
> > > +     *
> > > +     * end: This will point to the byte right after \r\n
> > > +     */
> > > +    end = strstr(ev->rx_buf + ev->buf_used - r
> > > +                 + (ev->buf_used - r == 0 ? 0 : -1),
> > > +                 "\r\n");
> > > +    if (end)
> > > +        end += 2;
> > > +
> > > +    while (end) {
> > > +        libxl__json_object *o;
> > > +        size_t len;
> > > +        char *s;
> > > +
> > > +        /* Start parsing from s */
> > > +        s = ev->rx_buf + ev->buf_consumed;
> > > +        /* Findout how much can be parsed */
> > > +        len = end - s;
> > 
> > You can init both s and len above when defining them.
> 
> Would not that looks a bit weird?
> 
> +    while (end) {
> +        libxl__json_object *o;
> +        /* Start parsing from s */
> +        char *s = ev->rx_buf + ev->buf_consumed;
> +        /* Findout how much can be parsed */
> +        size_t len = end - s;
> 
> But that can be done.

I have a tendency to try to init as much as possible at definition
time in order to make the code shorter, but that's my preference.
There's no rule in coding style that mandates that AFAIK.

Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU
  2018-08-03 17:25     ` Anthony PERARD
@ 2018-08-06 11:25       ` Roger Pau Monné
  2018-08-06 13:14         ` Anthony PERARD
  2018-08-21  8:58       ` Wei Liu
  1 sibling, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-06 11:25 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Aug 03, 2018 at 06:25:00PM +0100, Anthony PERARD wrote:
> On Thu, Aug 02, 2018 at 01:17:37PM +0200, Roger Pau Monné wrote:
> > On Fri, Jul 27, 2018 at 03:06:04PM +0100, Anthony PERARD wrote:
> > > diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> > > index 4a385801ba..e104fea941 100644
> > > --- a/tools/libxl/libxl_types.idl
> > > +++ b/tools/libxl/libxl_types.idl
> > > @@ -69,6 +69,10 @@ libxl_error = Enumeration("error", [
> > >      (-23, "NOTFOUND"),
> > >      (-24, "DOMAIN_DESTROYED"), # Target domain ceased to exist during op
> > >      (-25, "FEATURE_REMOVED"), # For functionality that has been removed
> > > +    (-26, "QMP_GENERIC_ERROR"), # unspecified qmp error
> > > +    (-27, "QMP_COMMAND_NOT_FOUND"), # the requested command has not been found
> > > +    (-28, "QMP_DEVICE_NOT_ACTIVE"), # a device has failed to be become active
> > > +    (-29, "QMP_DEVICE_NOT_FOUND"), # the requested device has not been found
> > 
> > Do we really need such granularity for QMP errors? Isn't it enough to
> > have a single ERROR_QMP or similar?
> 
> No I don't think so. QMP_COMMAND_NOT_FOUND can be useful when a qmp
> command is removed (there is already one that is deprecated and we use).
> 
> The last two could be useful to user of libxl as they could provide
> better error messages. xl don't care because whatever error message is
> attach to the error, it will be printed.

I wonder if this set of errors will change very often, at the end of
day it's not controlled by ourselves but QEMU, and then how much
chasing will libxl have to do in order to keep up with new types of
QMP errors.

IMO I don't see a lot of value in returning specific QMP error codes
from libxl, and I would even consider whether it's worth to have
something like ERROR_QMP, because I don't think there's much the
caller can do in case of QMP failure. It's an internal libxl QMP
error, and it's not like the caller is going to start it's own QMP
connection in order to speak with QEMU directly in order to solve
whatever QMP issue it got from libxl.

Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU
  2018-08-06 11:25       ` Roger Pau Monné
@ 2018-08-06 13:14         ` Anthony PERARD
  2018-08-06 15:03           ` Roger Pau Monné
  0 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-08-06 13:14 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Mon, Aug 06, 2018 at 01:25:22PM +0200, Roger Pau Monné wrote:
> On Fri, Aug 03, 2018 at 06:25:00PM +0100, Anthony PERARD wrote:
> > On Thu, Aug 02, 2018 at 01:17:37PM +0200, Roger Pau Monné wrote:
> > > On Fri, Jul 27, 2018 at 03:06:04PM +0100, Anthony PERARD wrote:
> > > > diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> > > > index 4a385801ba..e104fea941 100644
> > > > --- a/tools/libxl/libxl_types.idl
> > > > +++ b/tools/libxl/libxl_types.idl
> > > > @@ -69,6 +69,10 @@ libxl_error = Enumeration("error", [
> > > >      (-23, "NOTFOUND"),
> > > >      (-24, "DOMAIN_DESTROYED"), # Target domain ceased to exist during op
> > > >      (-25, "FEATURE_REMOVED"), # For functionality that has been removed
> > > > +    (-26, "QMP_GENERIC_ERROR"), # unspecified qmp error
> > > > +    (-27, "QMP_COMMAND_NOT_FOUND"), # the requested command has not been found
> > > > +    (-28, "QMP_DEVICE_NOT_ACTIVE"), # a device has failed to be become active
> > > > +    (-29, "QMP_DEVICE_NOT_FOUND"), # the requested device has not been found
> > > 
> > > Do we really need such granularity for QMP errors? Isn't it enough to
> > > have a single ERROR_QMP or similar?
> > 
> > No I don't think so. QMP_COMMAND_NOT_FOUND can be useful when a qmp
> > command is removed (there is already one that is deprecated and we use).
> > 
> > The last two could be useful to user of libxl as they could provide
> > better error messages. xl don't care because whatever error message is
> > attach to the error, it will be printed.
> 
> I wonder if this set of errors will change very often, at the end of
> day it's not controlled by ourselves but QEMU, and then how much
> chasing will libxl have to do in order to keep up with new types of
> QMP errors.

libxl doesn't have to know all the possible error code. Whenever there's
a code that is not known, I simple return ERROR_FAIL to the caller. So
it doesn't matter how often new error codes are added. (Also, I've
already left out one error code which is KVM specific.)

> IMO I don't see a lot of value in returning specific QMP error codes
> from libxl, and I would even consider whether it's worth to have
> something like ERROR_QMP, because I don't think there's much the
> caller can do in case of QMP failure. It's an internal libxl QMP
> error, and it's not like the caller is going to start it's own QMP
> connection in order to speak with QEMU directly in order to solve
> whatever QMP issue it got from libxl.

Those error codes aren't "internal libxl QMP error", the QMP connection
is working perfectly fine. All those error comes from QEMU.

All those error codes are part of possible responses to a command.

Here are the possible way that a caller can solve an issue with each
error code:

GenericError:
  The command failed, there's a description that a Human can read. Not
  much else can be done.

CommandNotFound:
  Will, the QMP command that the caller is trying to use is unknown to
  the current QEMU, it's maybe a command introduced in newer version of
  QEMU, or a deprecated command that is now removed.
  Maybe the caller try to use a newer command that replace a deprecated
  one, on error, it could call the older version. And vice versa.

DeviceNotActive:
  The device that libxl is trying to add via the command wasn't bring up
  properly, the caller could try again with different parameters or
  inverstigate with "query-*" commands to find out what's missing.

DeviceNotFound:
  The device that the caller is trying to modify (like a cdrom drive) is
  not found in QEMU, the caller could try to add it or let the user know
  that the device doesn't exist.


None of those error code are QMP issue.

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 14/32] libxl_qmp: Implement fd callback and read data
  2018-08-03 15:24       ` Roger Pau Monné
@ 2018-08-06 15:01         ` Anthony PERARD
  0 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-08-06 15:01 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Fri, Aug 03, 2018 at 05:24:52PM +0200, Roger Pau Monné wrote:
> On Fri, Aug 03, 2018 at 03:32:09PM +0100, Anthony PERARD wrote:
> > On Thu, Aug 02, 2018 at 11:56:11AM +0200, Roger Pau Monné wrote:
> > > On Fri, Jul 27, 2018 at 03:05:56PM +0100, Anthony PERARD wrote:
> > > > +        /* The -1 is because there is always space for a NUL character */
> > > > +        r = read(fd, ev->rx_buf + ev->buf_used,
> > > > +                 ev->buf_size - ev->buf_used - 1);
> > > > +        if (r < 0) {
> > > > +            if (errno == EINTR) continue;
> > > > +            assert(errno);
> > > > +            if (errno == EWOULDBLOCK) {
> > > > +                return 0;
> > > > +            }
> > > > +            LOGED(ERROR, ev->domid, "error reading QMP socket");
> > > > +            return ERROR_FAIL;
> > > 
> > > I think it would be clearer to use:
> > > 
> > > assert(errno);
> > > switch (errno) {
> > > case EINTR:
> > >     continue;
> > > case EWOULDBLOCK
> > >     return 0;
> > > default:
> > >     LOGED(...)
> > 
> > That's not the same. In the patch, the only errno allowed is EINTR,
> > anything else is consider a programmer's mistake. For users (build with
> > NDEBUG), EWOULDBLOCK is also allowed and not considered an error and
> > other errno will attempt to let libxl generate a usefull error, instead
> > of an abort().
> 
> I'm not sure I follow. According to the man page if read returns -1
> errno will always be set to indicate the error, so I'm not sure of the
> usefulness of the assert(errno), apart from checking that libc behaves
> correctly.
> 
> > > > +        }
> > > > +        break;
> > > > +    }
> > > > +
> > > > +    if (r == 0) {
> > > > +        LOGD(ERROR, ev->domid, "No data read on QMP socket");
> > > > +        return 0;
> > > > +    }
> > > > +
> > > > +    LOG_QMP("received %ldB: '%.*s'", r, (int)r, ev->rx_buf + ev->buf_used);
> > > > +
> > > > +    ev->buf_used += r;
> > > 
> > > Hm, don't you need to do this inside of a loop together with the
> > > realloc, in case the data on the fd is bigger than the current space
> > > on the buffer, and you need to keep growing it until you hit
> > > EWOULDBLOCK?
> > > 
> > > I think with the current approach you can leave data pending in the fd
> > > if the buffer happens to be smaller than the pending data in the fd?
> > 
> > You would think that, but the read loop isn't in this file. The loop is
> > part of the libxl__ev_fd.
> 
> Then why do you have a loop here to handle EINTR?
> 
> If the loop is somewhere else isn't it capable of handling EINTR like
> it handles partial reads? Adding the loop here just to handle EINTR
> makes it look like this is the complete read loop.

I thought I was following a pattern found elsewhere in libxl
(datacopier_readable), but apparently not. I'm not sure what would be
better to do. I think I'll just remove this loop and simply return on
EINTR.

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU
  2018-08-06 13:14         ` Anthony PERARD
@ 2018-08-06 15:03           ` Roger Pau Monné
  0 siblings, 0 replies; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-06 15:03 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Mon, Aug 06, 2018 at 02:14:51PM +0100, Anthony PERARD wrote:
> On Mon, Aug 06, 2018 at 01:25:22PM +0200, Roger Pau Monné wrote:
> > On Fri, Aug 03, 2018 at 06:25:00PM +0100, Anthony PERARD wrote:
> > > On Thu, Aug 02, 2018 at 01:17:37PM +0200, Roger Pau Monné wrote:
> > > > On Fri, Jul 27, 2018 at 03:06:04PM +0100, Anthony PERARD wrote:
> > > > > diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> > > > > index 4a385801ba..e104fea941 100644
> > > > > --- a/tools/libxl/libxl_types.idl
> > > > > +++ b/tools/libxl/libxl_types.idl
> > > > > @@ -69,6 +69,10 @@ libxl_error = Enumeration("error", [
> > > > >      (-23, "NOTFOUND"),
> > > > >      (-24, "DOMAIN_DESTROYED"), # Target domain ceased to exist during op
> > > > >      (-25, "FEATURE_REMOVED"), # For functionality that has been removed
> > > > > +    (-26, "QMP_GENERIC_ERROR"), # unspecified qmp error
> > > > > +    (-27, "QMP_COMMAND_NOT_FOUND"), # the requested command has not been found
> > > > > +    (-28, "QMP_DEVICE_NOT_ACTIVE"), # a device has failed to be become active
> > > > > +    (-29, "QMP_DEVICE_NOT_FOUND"), # the requested device has not been found
> > > > 
> > > > Do we really need such granularity for QMP errors? Isn't it enough to
> > > > have a single ERROR_QMP or similar?
> > > 
> > > No I don't think so. QMP_COMMAND_NOT_FOUND can be useful when a qmp
> > > command is removed (there is already one that is deprecated and we use).
> > > 
> > > The last two could be useful to user of libxl as they could provide
> > > better error messages. xl don't care because whatever error message is
> > > attach to the error, it will be printed.
> > 
> > I wonder if this set of errors will change very often, at the end of
> > day it's not controlled by ourselves but QEMU, and then how much
> > chasing will libxl have to do in order to keep up with new types of
> > QMP errors.
> 
> libxl doesn't have to know all the possible error code. Whenever there's
> a code that is not known, I simple return ERROR_FAIL to the caller. So
> it doesn't matter how often new error codes are added. (Also, I've
> already left out one error code which is KVM specific.)
> 
> > IMO I don't see a lot of value in returning specific QMP error codes
> > from libxl, and I would even consider whether it's worth to have
> > something like ERROR_QMP, because I don't think there's much the
> > caller can do in case of QMP failure. It's an internal libxl QMP
> > error, and it's not like the caller is going to start it's own QMP
> > connection in order to speak with QEMU directly in order to solve
> > whatever QMP issue it got from libxl.
> 
> Those error codes aren't "internal libxl QMP error", the QMP connection
> is working perfectly fine. All those error comes from QEMU.
> 
> All those error codes are part of possible responses to a command.
> 
> Here are the possible way that a caller can solve an issue with each
> error code:
> 
> GenericError:
>   The command failed, there's a description that a Human can read. Not
>   much else can be done.

That seems to me like ERROR_NONSPECIFIC, and you can pass that error
description to the caller.

> CommandNotFound:
>   Will, the QMP command that the caller is trying to use is unknown to
>   the current QEMU, it's maybe a command introduced in newer version of
>   QEMU, or a deprecated command that is now removed.
>   Maybe the caller try to use a newer command that replace a deprecated
>   one, on error, it could call the older version. And vice versa.

How would the caller do this? It's libxl the one that decides which
QMP commands to use, the caller of libxl has no idea about that.

This likely wants to be ERROR_FAIL.

> DeviceNotActive:
>   The device that libxl is trying to add via the command wasn't bring up
>   properly, the caller could try again with different parameters or
>   inverstigate with "query-*" commands to find out what's missing.

That one seems harder to match to any existing error code, the more
that I'm not sure of it's meaning. If a device isn't brought up
properly, isn't the device simply destroyed? Does QEMU keep around
zombie devices that failed to initialize?

In any case, how is the caller of libxl supposed to use this query-*
commands?

> DeviceNotFound:
>   The device that the caller is trying to modify (like a cdrom drive) is
>   not found in QEMU, the caller could try to add it or let the user know
>   that the device doesn't exist.

That one seems very similar to the current ERROR_NOTFOUND.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 25/32] libxl_exec: Add libxl__spawn_initiate_failure
  2018-08-02 11:34   ` Roger Pau Monné
@ 2018-08-06 15:58     ` Anthony PERARD
  0 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-08-06 15:58 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 01:34:52PM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:06:07PM +0100, Anthony PERARD wrote:
> > This function can be use by user libxl__spawn_* when they setup a
>                        ^ used and remove user

I meant user of libxl__spawn, so I'll s/user/user of/ instead.

> > notification other than xenstore. The parent can already called success
>                                                            ^ report
> > via libxl__spawn_initiate_detach(), this new function can be used for
> > failure instead of waiting for the timeout.
> > 
> > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> 
> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
> 

Thanks,

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 28/32] libxl_qmp: Store advertised QEMU version in libxl__ev_qmp
  2018-08-02 15:08   ` Roger Pau Monné
@ 2018-08-06 16:52     ` Anthony PERARD
  0 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-08-06 16:52 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 05:08:15PM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:06:10PM +0100, Anthony PERARD wrote:
> > This will be used in a later patch.
> > 
> > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> > ---
> >  tools/libxl/libxl_internal.h |  7 +++++++
> >  tools/libxl/libxl_qmp.c      | 16 ++++++++++++++++
> >  2 files changed, 23 insertions(+)
> > 
> > diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> > index 01c3868748..4fa54cdb6a 100644
> > --- a/tools/libxl/libxl_internal.h
> > +++ b/tools/libxl/libxl_internal.h
> > @@ -432,6 +432,13 @@ struct libxl__ev_qmp {
> >      libxl__ev_qmp_callback *callback;
> >      libxl__carefd *cfd; /* set to send a fd with the command, NULL otherwise */
> >  
> > +    /* read-only when Connected */
> > +    struct {
> > +        int major;
> > +        int minor;
> > +        int micro;
> > +    } qemu_version;
> 
> I would init those field to some bogus value (-1) to make sure an use
> before initialization will more likely cause a failure.

I don't think it matter, but I'll do it in libxl__ev_qmp_init.
(Those field should not be read before they have been written.)

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 30/32] libxl: Re-implement domain_suspend_device_model using libxl__ev_qmp
  2018-08-02 15:38   ` Roger Pau Monné
@ 2018-08-06 17:07     ` Anthony PERARD
  0 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-08-06 17:07 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 05:38:41PM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:06:12PM +0100, Anthony PERARD wrote:
> > +
> > +    if (qmp_ev_qemu_check_version(ev, 2, 11, 0))
> > +        qmp_parameters_add_bool(gc, &args, "live", dsps->live);
> > +    QMP_PARAMETERS_SPRINTF(&args, "filename", "/dev/fdset/%d", fdset);
> > +    rc = libxl__ev_qmp_send(gc, ev, "xen-save-devices-state", args);
> 
> I think some comments about the logic above would be helpful (at least
> for me). Do you need to pass an extra argument to 2.11.0 and higher
> versions in order to live-migrate?

I'll keep the comment that was there before:
 /* live parameter was added to QEMU 2.11. It signal QEMU that the save
  * operation is for a live migration rather that for taking a snapshot. */

And for more explanation about this parameter, I think I'll let future
archeologist find the commit that introduce its usage.
(db0c7dde021c29c2ae0d847d70fb7b59e02ea522)

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 31/32] libxl_disk: Cut libxl_cdrom_insert into step
  2018-08-02 15:50   ` Roger Pau Monné
@ 2018-08-06 17:20     ` Anthony PERARD
  2018-08-07 14:18       ` Roger Pau Monné
  0 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-08-06 17:20 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 05:50:52PM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:06:13PM +0100, Anthony PERARD wrote:
> Can you provide a comment explaining how is this supposed to work? The
> current code is already quite convoluted IMO (maybe because I'm not
> familiar with it), so I think a comment would help reviewers.

Have you read the CODING_STYLE file? I think you'll find that the
section "ASYNCHRONOUS/LONG-RUNNING OPERATIONS" will give you some answer
you are looking for. I'm not sure I'm following it perfectly, but at
least partially.

Thanks,

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 23/32] libxl_qmp: Respond to QMP greeting
  2018-08-02 11:26   ` Roger Pau Monné
@ 2018-08-06 17:41     ` Anthony PERARD
  0 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-08-06 17:41 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 01:26:35PM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:06:05PM +0100, Anthony PERARD wrote:
> > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> > ---
> >  tools/libxl/libxl_qmp.c | 36 ++++++++++++++++++++++++++++++------
> >  1 file changed, 30 insertions(+), 6 deletions(-)
> > 
> > diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> > index e649b8054d..83afce3192 100644
> > --- a/tools/libxl/libxl_qmp.c
> > +++ b/tools/libxl/libxl_qmp.c
> > @@ -1309,6 +1309,9 @@ int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
> >  
> >  /* ------------ Implementation of libxl__ev_qmp ---------------- */
> >  
> > +/* hard coded message ID used for capability negociation */
> > +static int qmp_capability_negociation_msgid = 1;
> 
> Could this be a define instead? Or at least constify it because it
> doesn't seem like it's modified (at least in this patch).

I guess a define will do.

> >  static int qmp_ev_prepare_cmd(libxl__gc *gc,
> >                                libxl__ev_qmp *ev,
> >                                const char *cmd,
> > @@ -1379,7 +1382,7 @@ static int qmp_ev_handle_response(libxl__egc *egc,
> >      }
> >  
> >      id = libxl__json_object_get_integer(o);
> > -    if (id != ev->id)
> > +    if (id != ev->id && id != qmp_capability_negociation_msgid)
> >          return 0;
> >  
> >      switch (type) {
> > @@ -1413,9 +1416,21 @@ static int qmp_ev_handle_response(libxl__egc *egc,
> >          abort();
> >      }
> >  
> > -    ev->id = -1;
> > -    ev->callback(egc, ev, response, rc); /* must be last */
> > -    return 1;
> > +    /*
> > +     * Even if the current state is capability_negociation and the correct ID
> > +     * as been received, call the callback on error.
> > +     */
> > +    if (ev->qmp_state == qmp_state_capability_negociation &&
> > +        id == qmp_capability_negociation_msgid &&
> > +        rc == 0) {
> > +        ev->qmp_state = qmp_state_connected;
> > +        libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events | POLLOUT);
> > +        return 0;
> > +    } else {
> > +        ev->id = -1;
> > +        ev->callback(egc, ev, response, rc); /* must be last */
> > +        return 1;
> > +    }
> >  }
> >  
> >  /* return 1 when a user callback as been called */
> > @@ -1429,6 +1444,11 @@ static int qmp_ev_handle_message(libxl__egc *egc,
> >      switch (type) {
> >      case LIBXL__QMP_MESSAGE_TYPE_QMP:
> >          /* greeting message */
> > +        assert(ev->qmp_state == qmp_state_connecting);
> > +        ev->qmp_state = qmp_state_greeting;
> > +        /* Allow qmp_ev_callback_writable to be called in order to send
> > +         * qmp_capabilities */
> > +        libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events | POLLOUT);
> >          return 0;
> >      case LIBXL__QMP_MESSAGE_TYPE_RETURN:
> >      case LIBXL__QMP_MESSAGE_TYPE_ERROR:
> > @@ -1563,7 +1583,11 @@ static int qmp_ev_callback_writable(libxl__gc *gc, libxl__ev_qmp *ev, int fd)
> >       * be send for now will be in this call. */
> >      libxl__ev_fd_modify(gc, &ev->qmp_efd, ev->qmp_efd.events & ~POLLOUT);
> >  
> > -    if (ev->qmp_state == qmp_state_connected) {
> > +    if (ev->qmp_state == qmp_state_greeting) {
> > +        buf = qmp_prepare_qmp_cmd(gc, "qmp_capabilities", NULL,
> > +                                  qmp_capability_negociation_msgid, &len);
> > +        ev->qmp_state = qmp_state_capability_negociation;
> > +    } else if (ev->qmp_state == qmp_state_connected) {
> 
> A switch (ev->qmp_state) might be better.

I guess, it's less repetition of ev->qmp_state. I'll switch.

Thanks,

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 31/32] libxl_disk: Cut libxl_cdrom_insert into step
  2018-08-06 17:20     ` Anthony PERARD
@ 2018-08-07 14:18       ` Roger Pau Monné
  2018-08-07 14:40         ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Roger Pau Monné @ 2018-08-07 14:18 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu

On Mon, Aug 06, 2018 at 06:20:50PM +0100, Anthony PERARD wrote:
> On Thu, Aug 02, 2018 at 05:50:52PM +0200, Roger Pau Monné wrote:
> > On Fri, Jul 27, 2018 at 03:06:13PM +0100, Anthony PERARD wrote:
> > Can you provide a comment explaining how is this supposed to work? The
> > current code is already quite convoluted IMO (maybe because I'm not
> > familiar with it), so I think a comment would help reviewers.
> 
> Have you read the CODING_STYLE file? I think you'll find that the
> section "ASYNCHRONOUS/LONG-RUNNING OPERATIONS" will give you some answer
> you are looking for. I'm not sure I'm following it perfectly, but at
> least partially.

Oh, I didn't mean comments about the async operations, but I would add
a note to clarify that you first empty the CDROM and then you attach
the specified image.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 31/32] libxl_disk: Cut libxl_cdrom_insert into step
  2018-08-07 14:18       ` Roger Pau Monné
@ 2018-08-07 14:40         ` Anthony PERARD
  2018-08-21  9:08           ` Wei Liu
  0 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-08-07 14:40 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Ian Jackson, Wei Liu

On Tue, Aug 07, 2018 at 04:18:21PM +0200, Roger Pau Monné wrote:
> On Mon, Aug 06, 2018 at 06:20:50PM +0100, Anthony PERARD wrote:
> > On Thu, Aug 02, 2018 at 05:50:52PM +0200, Roger Pau Monné wrote:
> > > On Fri, Jul 27, 2018 at 03:06:13PM +0100, Anthony PERARD wrote:
> > > Can you provide a comment explaining how is this supposed to work? The
> > > current code is already quite convoluted IMO (maybe because I'm not
> > > familiar with it), so I think a comment would help reviewers.
> > 
> > Have you read the CODING_STYLE file? I think you'll find that the
> > section "ASYNCHRONOUS/LONG-RUNNING OPERATIONS" will give you some answer
> > you are looking for. I'm not sure I'm following it perfectly, but at
> > least partially.
> 
> Oh, I didn't mean comments about the async operations, but I would add
> a note to clarify that you first empty the CDROM and then you attach
> the specified image.

I don't have better comments to provide than what's is already there. I
don't know what all the xenstore stuff is about, if it can be removed or
not. If the function was only to change media with qemu upstream almost
none of those stuff is usefull, only one qmp command is enough. There is
no need to insert an empty media before calling a command that would
simply swap medias.

The patch is awful, but the mechanic that create the patch isn't too
complicated, I simply cut the function after each qmp calls, use a
struct to store the variables instead of local variable, and sometime
initialise them later. There is also cdrom_insert_done() that can be
call at anytime to do the cleanup and stop the AO, but that just move
what was in out: before.

I don't think this patch can be review as a patch. I think one would
need to look at what was before, and what is after, side-by-side, in
order to have a good picture.

Something else to look after, can I keep a lock from
libxl__lock_domain_userdata() across the different step of an ao?

Thanks,

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 07/32] libxl_qmp: Move struct sockaddr_un variable to qmp_open()
  2018-07-27 14:05 ` [PATCH v4 07/32] libxl_qmp: Move struct sockaddr_un variable to qmp_open() Anthony PERARD
  2018-08-02  8:26   ` Roger Pau Monné
@ 2018-08-20 14:52   ` Wei Liu
  1 sibling, 0 replies; 96+ messages in thread
From: Wei Liu @ 2018-08-20 14:52 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Wei Liu, Ian Jackson

On Fri, Jul 27, 2018 at 03:05:49PM +0100, Anthony PERARD wrote:
> This variable is only used once, no need to keep it in the handler.
> 
> Also fix coding style (remove space after sizeof).
> And allow strncpy to use all the space in sun_path.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

Acked-by: Wei Liu <wei.liu2@citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 08/32] libxl: Add libxl__prepare_sockaddr_un() helper
  2018-07-27 14:05 ` [PATCH v4 08/32] libxl: Add libxl__prepare_sockaddr_un() helper Anthony PERARD
  2018-08-02  8:36   ` Roger Pau Monné
@ 2018-08-20 14:56   ` Wei Liu
  1 sibling, 0 replies; 96+ messages in thread
From: Wei Liu @ 2018-08-20 14:56 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Wei Liu, Ian Jackson

On Fri, Jul 27, 2018 at 03:05:50PM +0100, Anthony PERARD wrote:
> There is going to be a few more users that want to use UNIX socket, this
> helper is to prepare the `struct sockaddr_un` and check that the path
> isn't too long.
> 
> Also start to use it in libxl_qmp.c.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

With Roger's comment fixed:

Acked-by: Wei Liu <wei.liu2@citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 09/32] libxl_qmp: Remove unused yajl_ctx from handler
  2018-07-27 14:05 ` [PATCH v4 09/32] libxl_qmp: Remove unused yajl_ctx from handler Anthony PERARD
@ 2018-08-20 14:56   ` Wei Liu
  0 siblings, 0 replies; 96+ messages in thread
From: Wei Liu @ 2018-08-20 14:56 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Wei Liu, Ian Jackson

On Fri, Jul 27, 2018 at 03:05:51PM +0100, Anthony PERARD wrote:
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

Acked-by: Wei Liu <wei.liu2@citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 11/32] libxl_dm: Add libxl__qemu_qmp_path()
  2018-07-27 14:05 ` [PATCH v4 11/32] libxl_dm: Add libxl__qemu_qmp_path() Anthony PERARD
  2018-08-02  8:41   ` Roger Pau Monné
@ 2018-08-20 14:57   ` Wei Liu
  1 sibling, 0 replies; 96+ messages in thread
From: Wei Liu @ 2018-08-20 14:57 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Wei Liu, Ian Jackson

On Fri, Jul 27, 2018 at 03:05:53PM +0100, Anthony PERARD wrote:
> ... which generate the path to a QMP socket that libxl uses.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

Acked-by: Wei Liu <wei.liu2@citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 13/32] libxl_qmp: Connect to QMP socket
  2018-08-03 14:03       ` Roger Pau Monné
@ 2018-08-21  8:22         ` Wei Liu
  0 siblings, 0 replies; 96+ messages in thread
From: Wei Liu @ 2018-08-21  8:22 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: Anthony PERARD, xen-devel, Ian Jackson, Wei Liu

On Fri, Aug 03, 2018 at 04:03:54PM +0200, Roger Pau Monné wrote:
> On Fri, Aug 03, 2018 at 02:54:20PM +0100, Anthony PERARD wrote:
> > On Thu, Aug 02, 2018 at 11:35:53AM +0200, Roger Pau Monné wrote:
> > > On Fri, Jul 27, 2018 at 03:05:55PM +0100, Anthony PERARD wrote:
> > > > +typedef enum {
> > > > +    qmp_state_disconnected = 1,
> > > > +    qmp_state_connecting,
> > > > +    qmp_state_greeting,
> > > > +    qmp_state_capability_negociation,
> > > > +    qmp_state_connected,
> > > > +} libxl__qmp_state;
> > > > +
> > > 
> > > I think this should be declared in libxl_types_internal.idl?
> > 
> > I don't know, I kind of wanted the enum to be contained in libxl_qmp.c,
> > but then I couldn't use the enum type in the struct here.
> > 
> > Also the idl provides more than needed (conversion to string) and make
> > the names more verbose, by adding libxl__ prefix.
> 
> Hm, yes. libxl_types_internal.idl doesn't seem to be used much. I will
> leave this to the maintainers because it's not clear to me when a
> declaration should live in the IDL or the private header directly.

I think in this case it is better to use the internal header. The type
introduced here doesn't need all the fancy stuff generated by the IDL
infrastructure.

Wei.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 15/32] libxl_json: Enable yajl_allow_trailing_garbage
  2018-08-02 10:01   ` Roger Pau Monné
@ 2018-08-21  8:26     ` Wei Liu
  0 siblings, 0 replies; 96+ messages in thread
From: Wei Liu @ 2018-08-21  8:26 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: Anthony PERARD, xen-devel, Ian Jackson, Wei Liu

On Thu, Aug 02, 2018 at 12:01:23PM +0200, Roger Pau Monné wrote:
> On Fri, Jul 27, 2018 at 03:05:57PM +0100, Anthony PERARD wrote:
> > This allow to parse a string that is not NUL-terminated. With that
>        ^ allows
> > options disabled, YAJL v2 would look ahead on completion to find out if
>   ^ option
> > there is more to parse.
> > 
> > YAJL v1 doesn't have this behavior.
> > 
> > Any function function that allocate a yajl_handle via this function
>       ^ duplicated           ^ allocates
> > either parse a NUL-terminated string, or do provide proper length. So
> > change the default and allow garbage (like a different JSON document)
> > after the end of the data to parse.
> > 
> > This is importand for the QMP client, as there could be more than one
>           ^ important
> > message to parse, and YAJL would consider the next message to be
> > garbage and throw an error.
> > 
> > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> 
> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
> 

With commit message fixed:

Acked-by: Wei Liu <wei.liu2@citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 16/32] libxl_json: libxl__json_object_to_json
  2018-07-27 14:05 ` [PATCH v4 16/32] libxl_json: libxl__json_object_to_json Anthony PERARD
  2018-08-02 10:10   ` Roger Pau Monné
@ 2018-08-21  8:26   ` Wei Liu
  1 sibling, 0 replies; 96+ messages in thread
From: Wei Liu @ 2018-08-21  8:26 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Wei Liu, Ian Jackson

On Fri, Jul 27, 2018 at 03:05:58PM +0100, Anthony PERARD wrote:
> Allow to generate a JSON string from a libxl__json_object,
> usefull for debugging.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

Acked-by: Wei Liu <wei.liu2@citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 21/32] libxl_qmp: Simplify qmp_response_type() prototype
  2018-07-27 14:06 ` [PATCH v4 21/32] libxl_qmp: Simplify qmp_response_type() prototype Anthony PERARD
  2018-08-02 11:03   ` Roger Pau Monné
@ 2018-08-21  8:53   ` Wei Liu
  1 sibling, 0 replies; 96+ messages in thread
From: Wei Liu @ 2018-08-21  8:53 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Wei Liu, Ian Jackson

On Fri, Jul 27, 2018 at 03:06:03PM +0100, Anthony PERARD wrote:
> Remove the libxl__qmp_handler* argument so the function can be reused
> later in a different context.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

Acked-by: Wei Liu <wei.liu2@citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU
  2018-08-03 17:25     ` Anthony PERARD
  2018-08-06 11:25       ` Roger Pau Monné
@ 2018-08-21  8:58       ` Wei Liu
  2018-08-21 12:50         ` Anthony PERARD
  1 sibling, 1 reply; 96+ messages in thread
From: Wei Liu @ 2018-08-21  8:58 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu, Roger Pau Monné

On Fri, Aug 03, 2018 at 06:25:00PM +0100, Anthony PERARD wrote:
> > > diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> > > index 4a385801ba..e104fea941 100644
> > > --- a/tools/libxl/libxl_types.idl
> > > +++ b/tools/libxl/libxl_types.idl
> > > @@ -69,6 +69,10 @@ libxl_error = Enumeration("error", [
> > >      (-23, "NOTFOUND"),
> > >      (-24, "DOMAIN_DESTROYED"), # Target domain ceased to exist during op
> > >      (-25, "FEATURE_REMOVED"), # For functionality that has been removed
> > > +    (-26, "QMP_GENERIC_ERROR"), # unspecified qmp error
> > > +    (-27, "QMP_COMMAND_NOT_FOUND"), # the requested command has not been found
> > > +    (-28, "QMP_DEVICE_NOT_ACTIVE"), # a device has failed to be become active
> > > +    (-29, "QMP_DEVICE_NOT_FOUND"), # the requested device has not been found
> > 
> > Do we really need such granularity for QMP errors? Isn't it enough to
> > have a single ERROR_QMP or similar?
> 
> No I don't think so. QMP_COMMAND_NOT_FOUND can be useful when a qmp
> command is removed (there is already one that is deprecated and we use).
> 
> The last two could be useful to user of libxl as they could provide
> better error messages. xl don't care because whatever error message is
> attach to the error, it will be printed.

If the users of libxl aren't likely to care about the exact error
messages, we don't need to expose these at all. They are more suitable
to be put under libxl_internal_types.idl.

And then you translate the internal error numbers into external ones
where appropriate.

Wei.


> 
> Thanks,
> 
> -- 
> Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 23/32] libxl_qmp: Respond to QMP greeting
  2018-07-27 14:06 ` [PATCH v4 23/32] libxl_qmp: Respond to QMP greeting Anthony PERARD
  2018-08-02 11:26   ` Roger Pau Monné
@ 2018-08-21  9:00   ` Wei Liu
  2018-08-21 10:51     ` Anthony PERARD
  1 sibling, 1 reply; 96+ messages in thread
From: Wei Liu @ 2018-08-21  9:00 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Wei Liu, Ian Jackson

On Fri, Jul 27, 2018 at 03:06:05PM +0100, Anthony PERARD wrote:
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
>  tools/libxl/libxl_qmp.c | 36 ++++++++++++++++++++++++++++++------
>  1 file changed, 30 insertions(+), 6 deletions(-)
> 
> diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> index e649b8054d..83afce3192 100644
> --- a/tools/libxl/libxl_qmp.c
> +++ b/tools/libxl/libxl_qmp.c
> @@ -1309,6 +1309,9 @@ int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
>  
>  /* ------------ Implementation of libxl__ev_qmp ---------------- */
>  
> +/* hard coded message ID used for capability negociation */

s/negociation/negotiation/g.

I only make the same mistakes myself, too. :p

Wei.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 24/32] libxl_qmp: Disable beautify for QMP generated cmd
  2018-07-27 14:06 ` [PATCH v4 24/32] libxl_qmp: Disable beautify for QMP generated cmd Anthony PERARD
@ 2018-08-21  9:00   ` Wei Liu
  0 siblings, 0 replies; 96+ messages in thread
From: Wei Liu @ 2018-08-21  9:00 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Wei Liu, Ian Jackson

On Fri, Jul 27, 2018 at 03:06:06PM +0100, Anthony PERARD wrote:
> There is no need for it.
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

Acked-by: Wei Liu <wei.liu2@citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 31/32] libxl_disk: Cut libxl_cdrom_insert into step
  2018-08-07 14:40         ` Anthony PERARD
@ 2018-08-21  9:08           ` Wei Liu
  2018-08-21 12:58             ` Anthony PERARD
  0 siblings, 1 reply; 96+ messages in thread
From: Wei Liu @ 2018-08-21  9:08 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Ian Jackson, Wei Liu, Roger Pau Monné

On Tue, Aug 07, 2018 at 03:40:17PM +0100, Anthony PERARD wrote:
> On Tue, Aug 07, 2018 at 04:18:21PM +0200, Roger Pau Monné wrote:
> > On Mon, Aug 06, 2018 at 06:20:50PM +0100, Anthony PERARD wrote:
> > > On Thu, Aug 02, 2018 at 05:50:52PM +0200, Roger Pau Monné wrote:
> > > > On Fri, Jul 27, 2018 at 03:06:13PM +0100, Anthony PERARD wrote:
> > > > Can you provide a comment explaining how is this supposed to work? The
> > > > current code is already quite convoluted IMO (maybe because I'm not
> > > > familiar with it), so I think a comment would help reviewers.
> > > 
> > > Have you read the CODING_STYLE file? I think you'll find that the
> > > section "ASYNCHRONOUS/LONG-RUNNING OPERATIONS" will give you some answer
> > > you are looking for. I'm not sure I'm following it perfectly, but at
> > > least partially.
> > 
> > Oh, I didn't mean comments about the async operations, but I would add
> > a note to clarify that you first empty the CDROM and then you attach
> > the specified image.
> 
> I don't have better comments to provide than what's is already there. I
> don't know what all the xenstore stuff is about, if it can be removed or
> not. If the function was only to change media with qemu upstream almost
> none of those stuff is usefull, only one qmp command is enough. There is
> no need to insert an empty media before calling a command that would
> simply swap medias.
> 
> The patch is awful, but the mechanic that create the patch isn't too
> complicated, I simply cut the function after each qmp calls, use a
> struct to store the variables instead of local variable, and sometime
> initialise them later. There is also cdrom_insert_done() that can be
> call at anytime to do the cleanup and stop the AO, but that just move
> what was in out: before.
> 
> I don't think this patch can be review as a patch. I think one would
> need to look at what was before, and what is after, side-by-side, in
> order to have a good picture.
> 
> Something else to look after, can I keep a lock from
> libxl__lock_domain_userdata() across the different step of an ao?

Probably not.  AO_INPROGRESS and others unlock ctx.  The locking
hierarchy mandates you have to have ctx lock before you can have
userdata lock.

Wei.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 23/32] libxl_qmp: Respond to QMP greeting
  2018-08-21  9:00   ` Wei Liu
@ 2018-08-21 10:51     ` Anthony PERARD
  0 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-08-21 10:51 UTC (permalink / raw)
  To: Wei Liu; +Cc: xen-devel, Ian Jackson

On Tue, Aug 21, 2018 at 10:00:14AM +0100, Wei Liu wrote:
> On Fri, Jul 27, 2018 at 03:06:05PM +0100, Anthony PERARD wrote:
> > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> > ---
> >  tools/libxl/libxl_qmp.c | 36 ++++++++++++++++++++++++++++++------
> >  1 file changed, 30 insertions(+), 6 deletions(-)
> > 
> > diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
> > index e649b8054d..83afce3192 100644
> > --- a/tools/libxl/libxl_qmp.c
> > +++ b/tools/libxl/libxl_qmp.c
> > @@ -1309,6 +1309,9 @@ int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
> >  
> >  /* ------------ Implementation of libxl__ev_qmp ---------------- */
> >  
> > +/* hard coded message ID used for capability negociation */
> 
> s/negociation/negotiation/g.
> 
> I only make the same mistakes myself, too. :p

:-), and it's actually worse for me, because both "négociation" and
"negotiation" would be correct, depending on the context, the language
used :-(.

I'll try to fix all instances of this mistake.

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU
  2018-08-21  8:58       ` Wei Liu
@ 2018-08-21 12:50         ` Anthony PERARD
  2018-08-21 14:56           ` Ian Jackson
  0 siblings, 1 reply; 96+ messages in thread
From: Anthony PERARD @ 2018-08-21 12:50 UTC (permalink / raw)
  To: Wei Liu; +Cc: xen-devel, Ian Jackson, Roger Pau Monné

On Tue, Aug 21, 2018 at 09:58:57AM +0100, Wei Liu wrote:
> On Fri, Aug 03, 2018 at 06:25:00PM +0100, Anthony PERARD wrote:
> > > > diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> > > > index 4a385801ba..e104fea941 100644
> > > > --- a/tools/libxl/libxl_types.idl
> > > > +++ b/tools/libxl/libxl_types.idl
> > > > @@ -69,6 +69,10 @@ libxl_error = Enumeration("error", [
> > > >      (-23, "NOTFOUND"),
> > > >      (-24, "DOMAIN_DESTROYED"), # Target domain ceased to exist during op
> > > >      (-25, "FEATURE_REMOVED"), # For functionality that has been removed
> > > > +    (-26, "QMP_GENERIC_ERROR"), # unspecified qmp error
> > > > +    (-27, "QMP_COMMAND_NOT_FOUND"), # the requested command has not been found
> > > > +    (-28, "QMP_DEVICE_NOT_ACTIVE"), # a device has failed to be become active
> > > > +    (-29, "QMP_DEVICE_NOT_FOUND"), # the requested device has not been found
> > > 
> > > Do we really need such granularity for QMP errors? Isn't it enough to
> > > have a single ERROR_QMP or similar?
> > 
> > No I don't think so. QMP_COMMAND_NOT_FOUND can be useful when a qmp
> > command is removed (there is already one that is deprecated and we use).
> > 
> > The last two could be useful to user of libxl as they could provide
> > better error messages. xl don't care because whatever error message is
> > attach to the error, it will be printed.
> 
> If the users of libxl aren't likely to care about the exact error
> messages, we don't need to expose these at all. They are more suitable
> to be put under libxl_internal_types.idl.
> 
> And then you translate the internal error numbers into external ones
> where appropriate.

I've already tried to have qmp specific error number, I've been asked to
invent libxl error number instead:
https://lists.xenproject.org/archives/html/xen-devel/2018-07/msg01151.html

Also, libxl doesn't have internal error number, there is only one type
of error, it's `libxl_error`.

I'm quite certain that those error numbers needs to be exposed to users
of `libxl__ev_qmp` (so internal to libxl), and the only way to return
these error numbers, is via `rc`, which should at all time be
`libxl_error` (see coding style). An other way would be to add an extra
parameter to `libxl__ev_qmp_callback`, a second error number, this time
qmp specific. Now which one should we check? And that would be more
error-prone.

Maybe some of those error numbers could be match back to existing one,
but not all.

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 31/32] libxl_disk: Cut libxl_cdrom_insert into step
  2018-08-21  9:08           ` Wei Liu
@ 2018-08-21 12:58             ` Anthony PERARD
  0 siblings, 0 replies; 96+ messages in thread
From: Anthony PERARD @ 2018-08-21 12:58 UTC (permalink / raw)
  To: Wei Liu; +Cc: xen-devel, Ian Jackson, Roger Pau Monné

On Tue, Aug 21, 2018 at 10:08:49AM +0100, Wei Liu wrote:
> On Tue, Aug 07, 2018 at 03:40:17PM +0100, Anthony PERARD wrote:
> > On Tue, Aug 07, 2018 at 04:18:21PM +0200, Roger Pau Monné wrote:
> > > On Mon, Aug 06, 2018 at 06:20:50PM +0100, Anthony PERARD wrote:
> > > > On Thu, Aug 02, 2018 at 05:50:52PM +0200, Roger Pau Monné wrote:
> > > > > On Fri, Jul 27, 2018 at 03:06:13PM +0100, Anthony PERARD wrote:
> > > > > Can you provide a comment explaining how is this supposed to work? The
> > > > > current code is already quite convoluted IMO (maybe because I'm not
> > > > > familiar with it), so I think a comment would help reviewers.
> > > > 
> > > > Have you read the CODING_STYLE file? I think you'll find that the
> > > > section "ASYNCHRONOUS/LONG-RUNNING OPERATIONS" will give you some answer
> > > > you are looking for. I'm not sure I'm following it perfectly, but at
> > > > least partially.
> > > 
> > > Oh, I didn't mean comments about the async operations, but I would add
> > > a note to clarify that you first empty the CDROM and then you attach
> > > the specified image.
> > 
> > I don't have better comments to provide than what's is already there. I
> > don't know what all the xenstore stuff is about, if it can be removed or
> > not. If the function was only to change media with qemu upstream almost
> > none of those stuff is usefull, only one qmp command is enough. There is
> > no need to insert an empty media before calling a command that would
> > simply swap medias.
> > 
> > The patch is awful, but the mechanic that create the patch isn't too
> > complicated, I simply cut the function after each qmp calls, use a
> > struct to store the variables instead of local variable, and sometime
> > initialise them later. There is also cdrom_insert_done() that can be
> > call at anytime to do the cleanup and stop the AO, but that just move
> > what was in out: before.
> > 
> > I don't think this patch can be review as a patch. I think one would
> > need to look at what was before, and what is after, side-by-side, in
> > order to have a good picture.
> > 
> > Something else to look after, can I keep a lock from
> > libxl__lock_domain_userdata() across the different step of an ao?
> 
> Probably not.  AO_INPROGRESS and others unlock ctx.  The locking
> hierarchy mandates you have to have ctx lock before you can have
> userdata lock.

Ok, thanks. I'll attempt to fix that in v5.

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU
  2018-08-21 12:50         ` Anthony PERARD
@ 2018-08-21 14:56           ` Ian Jackson
  0 siblings, 0 replies; 96+ messages in thread
From: Ian Jackson @ 2018-08-21 14:56 UTC (permalink / raw)
  To: Anthony PERARD; +Cc: xen-devel, Wei Liu, Roger Pau Monné

Anthony PERARD writes ("Re: [Xen-devel] [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU"):
> I've already tried to have qmp specific error number, I've been asked to
> invent libxl error number instead:
> https://lists.xenproject.org/archives/html/xen-devel/2018-07/msg01151.html

I stand by that request and I disagree with Wei's suggestion to make a
new separate kind of internal error code.  We already have too many
different kinds of error number.  The last thing we need is to add
another.  Is there some difficulty with assigning a handful of
integers ?  Will we run out ?

IMO your (Anthony's) reply explains why this is needed and I have
nothing else to add to it...

Thanks,
Ian.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

end of thread, other threads:[~2018-08-21 14:57 UTC | newest]

Thread overview: 96+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-27 14:05 [PATCH v4 00/32] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
2018-07-27 14:05 ` [PATCH v4 01/32] libxl_event: Fix DEBUG prints Anthony PERARD
2018-07-27 14:05 ` [PATCH v4 02/32] libxl_qmp: Documentation of the logic of the QMP client Anthony PERARD
2018-07-27 14:05 ` [PATCH v4 03/32] libxl_qmp: Fix use of DEBUG_RECEIVED Anthony PERARD
2018-07-27 14:05 ` [PATCH v4 04/32] libxl_json: fix build with DEBUG_ANSWER Anthony PERARD
2018-07-27 14:05 ` [PATCH v4 05/32] libxl_qmp: Move the buffer realloc to the same scope level as read Anthony PERARD
2018-07-27 14:05 ` [PATCH v4 06/32] libxl_qmp: Add a warning to not trust QEMU Anthony PERARD
2018-07-27 14:05 ` [PATCH v4 07/32] libxl_qmp: Move struct sockaddr_un variable to qmp_open() Anthony PERARD
2018-08-02  8:26   ` Roger Pau Monné
2018-08-20 14:52   ` Wei Liu
2018-07-27 14:05 ` [PATCH v4 08/32] libxl: Add libxl__prepare_sockaddr_un() helper Anthony PERARD
2018-08-02  8:36   ` Roger Pau Monné
2018-08-20 14:56   ` Wei Liu
2018-07-27 14:05 ` [PATCH v4 09/32] libxl_qmp: Remove unused yajl_ctx from handler Anthony PERARD
2018-08-20 14:56   ` Wei Liu
2018-07-27 14:05 ` [PATCH v4 10/32] libxl_json: constify libxl__json_object_to_yajl_gen arguments Anthony PERARD
2018-07-27 14:05 ` [PATCH v4 11/32] libxl_dm: Add libxl__qemu_qmp_path() Anthony PERARD
2018-08-02  8:41   ` Roger Pau Monné
2018-08-20 14:57   ` Wei Liu
2018-07-27 14:05 ` [PATCH v4 12/32] libxl: Design of an async API to issue QMP commands to QEMU Anthony PERARD
2018-08-02  9:01   ` [PATCH v4 12/32] libxl: Design of an async API to issue QMP commands to QEMUç Roger Pau Monné
2018-08-03 11:18     ` Anthony PERARD
2018-08-03 13:55       ` Roger Pau Monné
2018-08-03 14:45         ` Anthony PERARD
2018-08-03 15:30           ` Roger Pau Monné
2018-07-27 14:05 ` [PATCH v4 13/32] libxl_qmp: Connect to QMP socket Anthony PERARD
2018-08-02  9:35   ` Roger Pau Monné
2018-08-03 13:54     ` Anthony PERARD
2018-08-03 14:03       ` Roger Pau Monné
2018-08-21  8:22         ` Wei Liu
2018-07-27 14:05 ` [PATCH v4 14/32] libxl_qmp: Implement fd callback and read data Anthony PERARD
2018-08-02  9:56   ` Roger Pau Monné
2018-08-03 14:32     ` Anthony PERARD
2018-08-03 15:24       ` Roger Pau Monné
2018-08-06 15:01         ` Anthony PERARD
2018-07-27 14:05 ` [PATCH v4 15/32] libxl_json: Enable yajl_allow_trailing_garbage Anthony PERARD
2018-08-02 10:01   ` Roger Pau Monné
2018-08-21  8:26     ` Wei Liu
2018-07-27 14:05 ` [PATCH v4 16/32] libxl_json: libxl__json_object_to_json Anthony PERARD
2018-08-02 10:10   ` Roger Pau Monné
2018-08-21  8:26   ` Wei Liu
2018-07-27 14:05 ` [PATCH v4 17/32] libxl_qmp: Parse JSON input from QMP Anthony PERARD
2018-08-02 10:25   ` Roger Pau Monné
2018-08-03 15:33     ` Anthony PERARD
2018-08-06 11:17       ` Roger Pau Monné
2018-07-27 14:06 ` [PATCH v4 18/32] libxl_qmp: Separate QMP message generation from qmp_send_prepare Anthony PERARD
2018-08-02 10:34   ` Roger Pau Monné
2018-08-03 15:43     ` Anthony PERARD
2018-07-27 14:06 ` [PATCH v4 19/32] libxl_qmp: Prepare the command to be sent Anthony PERARD
2018-08-02 10:41   ` Roger Pau Monné
2018-08-03 16:35     ` Anthony PERARD
2018-07-27 14:06 ` [PATCH v4 20/32] libxl_qmp: Handle write to QMP socket Anthony PERARD
2018-08-02 11:02   ` Roger Pau Monné
2018-08-03 16:50     ` Anthony PERARD
2018-07-27 14:06 ` [PATCH v4 21/32] libxl_qmp: Simplify qmp_response_type() prototype Anthony PERARD
2018-08-02 11:03   ` Roger Pau Monné
2018-08-21  8:53   ` Wei Liu
2018-07-27 14:06 ` [PATCH v4 22/32] libxl_qmp: Handle messages from QEMU Anthony PERARD
2018-08-02 11:17   ` Roger Pau Monné
2018-08-03 17:25     ` Anthony PERARD
2018-08-06 11:25       ` Roger Pau Monné
2018-08-06 13:14         ` Anthony PERARD
2018-08-06 15:03           ` Roger Pau Monné
2018-08-21  8:58       ` Wei Liu
2018-08-21 12:50         ` Anthony PERARD
2018-08-21 14:56           ` Ian Jackson
2018-07-27 14:06 ` [PATCH v4 23/32] libxl_qmp: Respond to QMP greeting Anthony PERARD
2018-08-02 11:26   ` Roger Pau Monné
2018-08-06 17:41     ` Anthony PERARD
2018-08-21  9:00   ` Wei Liu
2018-08-21 10:51     ` Anthony PERARD
2018-07-27 14:06 ` [PATCH v4 24/32] libxl_qmp: Disable beautify for QMP generated cmd Anthony PERARD
2018-08-21  9:00   ` Wei Liu
2018-07-27 14:06 ` [PATCH v4 25/32] libxl_exec: Add libxl__spawn_initiate_failure Anthony PERARD
2018-08-02 11:34   ` Roger Pau Monné
2018-08-06 15:58     ` Anthony PERARD
2018-07-27 14:06 ` [PATCH v4 26/32] libxl_dm: Pre-open QMP socket for QEMU Anthony PERARD
2018-08-02 15:00   ` Roger Pau Monné
2018-07-27 14:06 ` [PATCH v4 27/32] libxl: QEMU startup sync based on QMP Anthony PERARD
2018-08-02 15:06   ` Roger Pau Monné
2018-07-27 14:06 ` [PATCH v4 28/32] libxl_qmp: Store advertised QEMU version in libxl__ev_qmp Anthony PERARD
2018-08-02 15:08   ` Roger Pau Monné
2018-08-06 16:52     ` Anthony PERARD
2018-07-27 14:06 ` [PATCH v4 29/32] libxl: Change libxl__domain_suspend_device_model() to be async Anthony PERARD
2018-08-02 15:15   ` Roger Pau Monné
2018-07-27 14:06 ` [PATCH v4 30/32] libxl: Re-implement domain_suspend_device_model using libxl__ev_qmp Anthony PERARD
2018-08-02 15:38   ` Roger Pau Monné
2018-08-06 17:07     ` Anthony PERARD
2018-07-27 14:06 ` [PATCH v4 31/32] libxl_disk: Cut libxl_cdrom_insert into step Anthony PERARD
2018-08-02 15:50   ` Roger Pau Monné
2018-08-06 17:20     ` Anthony PERARD
2018-08-07 14:18       ` Roger Pau Monné
2018-08-07 14:40         ` Anthony PERARD
2018-08-21  9:08           ` Wei Liu
2018-08-21 12:58             ` Anthony PERARD
2018-07-27 14:06 ` [PATCH v4 32/32] libxl_disk: Have libxl_cdrom_insert use libxl__ev_qmp Anthony PERARD

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.