[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v3 24/31] libxl_qmp_ev: Respond to QMP greeting



Slight change in the infrastructure to allow to send a buffer before any
command that would already been prepared.

qmp_capabilities needs to be the first command sent.

Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>
---
 tools/libxl/libxl_qmp.c | 87 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 82 insertions(+), 5 deletions(-)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index db07c1822a..adf466e4c4 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -1387,6 +1387,8 @@ struct libxl__ev_qmp_state {
     unsigned int last_id_used;
     /* Indicate that QEMU is ready to respond to command. */
     bool ready;
+    /* Allow to commands while !ready, to respond to QMP greeting. */
+    int priority_send;
     LIBXL_TAILQ_HEAD(libxl__qmp_tx_bufs, libxl__qmp_tx_buf) tx_buf;
 
     LIBXL_TAILQ_HEAD(libxl__ev_qmps, libxl__ev_qmp) qmp_events;
@@ -1398,7 +1400,8 @@ static int ev_qmp_queue_command(libxl__gc *gc,
                                 libxl__ev_qmp_state *qmp,
                                 const char *cmd,
                                 const libxl__json_object *args,
-                                libxl__carefd *efd)
+                                libxl__carefd *efd,
+                                bool high_priority)
 {
     char *buf = NULL;
     size_t len;
@@ -1414,12 +1417,78 @@ static int ev_qmp_queue_command(libxl__gc *gc,
     out->buf = buf;
     out->len = len;
     out->efd = efd;
-    LIBXL_TAILQ_INSERT_TAIL(&qmp->tx_buf, out, entry);
+    if (high_priority) {
+        /* qmp_capabilities cmd need to be send out first */
+        LIBXL_TAILQ_INSERT_HEAD(&qmp->tx_buf, out, entry);
+        qmp->priority_send += 1;
+    } else {
+        LIBXL_TAILQ_INSERT_TAIL(&qmp->tx_buf, out, entry);
+    }
     libxl__ev_fd_modify(gc, &qmp->efd, qmp->efd.events | POLLOUT);
 
     return 0;
 }
 
+/* QMP greeting response */
+typedef struct {
+    libxl__ev_qmp ev;
+    libxl__ev_qmp_state *qmp;
+} ev_qmp_greeting_state;
+static void ev_qmp_callback_capabilities(libxl__egc *egc,
+                                        libxl__ev_qmp *ev,
+                                        const libxl__json_object *o,
+                                        libxl__qmp_error_class error)
+{
+    EGC_GC;
+    ev_qmp_greeting_state *qegs = CONTAINER_OF(ev, *qegs, ev);
+    libxl__ev_qmp_state *qmp = qegs->qmp;
+
+    CTX_LOCK;
+    qmp->ready = true;
+
+    /* Allow potential command to be sent */
+    libxl__ev_fd_modify(gc, &qmp->efd, qmp->efd.events | POLLOUT);
+
+    CTX_UNLOCK;
+
+    libxl__ev_qmp_deregister(gc, ev);
+
+    free(qegs);
+}
+
+static int ev_qmp_callback_greeting(libxl__egc *egc,
+                                    libxl__ev_qmp_state *qmp)
+{
+    EGC_GC;
+    ev_qmp_greeting_state *qegs;
+    int rc;
+
+    /* Will be freed in callback */
+    qegs = libxl__malloc(NOGC, sizeof(*qegs));
+
+    libxl__ev_qmp_init(&qegs->ev);
+
+    /* Do part of libxl__ev_qmp_register as this is the only time where the
+     * argument high_priority is true. */
+
+    qegs->qmp = qmp;
+    qegs->ev.domid = qmp->domid;
+    qegs->ev.callback = ev_qmp_callback_capabilities;
+    rc = ev_qmp_queue_command(gc, qmp, "qmp_capabilities", NULL, NULL, true);
+    if (rc)
+        goto out;
+    qegs->ev.id = qmp->last_id_used;
+
+    CTX_LOCK;
+    LIBXL_TAILQ_INSERT_TAIL(&qmp->qmp_events, &qegs->ev, entry);
+    CTX_UNLOCK;
+
+out:
+    if (rc)
+        free(qegs);
+    return rc;
+}
+
 /*
  * Handle messages received from QMP server
  */
@@ -1501,7 +1570,8 @@ static void ev_qmp_handle_message(libxl__egc *egc,
 
     switch (type) {
     case LIBXL__QMP_MESSAGE_TYPE_QMP:
-        /* greeting message */
+        /* On the greeting message from the server, call qmp_capabilities */
+        ev_qmp_callback_greeting(egc, qmp);
         return;
     case LIBXL__QMP_MESSAGE_TYPE_RETURN:
     case LIBXL__QMP_MESSAGE_TYPE_ERROR:
@@ -1673,7 +1743,9 @@ static int ev_qmp_callback_writable(libxl__egc *egc,
     libxl__qmp_tx_buf *buf;
     int rc;
 
-    if (!qmp->ready) {
+    /* Don't send anything until connected, unless there is the response to the
+     * greeting message */
+    if (!qmp->ready && !qmp->priority_send) {
         return 0;
     }
 
@@ -1701,6 +1773,9 @@ static int ev_qmp_callback_writable(libxl__egc *egc,
     free(buf->buf);
     free(buf);
 
+    if (!qmp->ready && qmp->priority_send)
+        qmp->priority_send -= 1;
+
 out:
     return 1;
 }
@@ -1771,6 +1846,7 @@ static void libxl__ev_qmp_state_init(libxl__ev_qmp_state 
*qmp)
     LIBXL_TAILQ_INIT(&qmp->bufs);
     qmp->last_id_used = 0;
     qmp->ready = false;
+    qmp->priority_send = 0;
     LIBXL_TAILQ_INIT(&qmp->tx_buf);
     LIBXL_TAILQ_INIT(&qmp->qmp_events);
 }
@@ -1878,6 +1954,7 @@ void libxl__ev_qmp_stop(libxl__gc *gc, 
libxl__ev_qmp_state *qmp)
     LIBXL_TAILQ_INIT(&qmp->qmp_events);
 
     qmp->ready = false;
+    qmp->priority_send = 0;
 
     libxl__ev_fd_deregister(gc, &qmp->efd);
     libxl__carefd_close(qmp->cfd);
@@ -1917,7 +1994,7 @@ int libxl__ev_qmp_register(libxl__gc *gc, libxl__ev_qmp 
*ev,
         goto out;
     }
 
-    rc = ev_qmp_queue_command(gc, qmp, cmd, args, ev->efd);
+    rc = ev_qmp_queue_command(gc, qmp, cmd, args, ev->efd, false);
     if (rc)
         goto out;
 
-- 
Anthony PERARD


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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.