qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Peter Xu <peterx@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Marc-André Lureau" <marcandre.lureau@redhat.com>,
	"Daniel P . Berrange" <berrange@redhat.com>,
	peterx@redhat.com, "Eric Blake" <eblake@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Dr . David Alan Gilbert" <dgilbert@redhat.com>
Subject: [Qemu-devel] [PATCH 5/9] monitor: suspend monitor instead of send CMD_DROP
Date: Wed,  4 Jul 2018 16:45:03 +0800	[thread overview]
Message-ID: <20180704084507.14560-6-peterx@redhat.com> (raw)
In-Reply-To: <20180704084507.14560-1-peterx@redhat.com>

When we received too many qmp commands, previously we'll send
COMMAND_DROPPED events to monitors, then we'll drop the requests.  It
can only solve the flow control of the request queue, however it'll not
really work since we might queue unlimited events in the response queue
which is a potential risk.

Now instead of sending such an event, we stop consuming the client input
when we noticed that the queue is reaching its limitation before hand.
Then after we handled commands, we'll try to resume the monitor when
needed.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 monitor.c | 46 ++++++++++++++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 16 deletions(-)

diff --git a/monitor.c b/monitor.c
index 215029bc22..ebf862914f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -164,6 +164,8 @@ struct MonFdset {
     QLIST_ENTRY(MonFdset) next;
 };
 
+#define  QMP_REQ_QUEUE_LEN_MAX  (8)
+
 typedef struct {
     JSONMessageParser parser;
     /*
@@ -396,10 +398,21 @@ static void monitor_qmp_try_resume(Monitor *mon)
 {
     assert(monitor_is_qmp(mon));
     qemu_mutex_lock(&mon->qmp.qmp_lock);
+
+    if (mon->qmp.qmp_requests->length >= QMP_REQ_QUEUE_LEN_MAX) {
+        /*
+         * This should not happen, but in case if it happens, we
+         * should still keep the monitor in suspend state
+         */
+        qemu_mutex_unlock(&mon->qmp.qmp_lock);
+        return;
+    }
+
     if (mon->qmp.need_resume) {
         monitor_resume(mon);
         mon->qmp.need_resume = false;
     }
+
     qemu_mutex_unlock(&mon->qmp.qmp_lock);
 }
 
@@ -4213,7 +4226,14 @@ static void monitor_qmp_bh_dispatcher(void *data)
     qemu_bh_schedule(qmp_dispatcher_bh);
 }
 
-#define  QMP_REQ_QUEUE_LEN_MAX  (8)
+/* Called with Monitor.qmp.qmp_lock held. */
+static void monitor_qmp_suspend_locked(Monitor *mon)
+{
+    assert(monitor_is_qmp(mon));
+    assert(mon->qmp.need_resume == false);
+    monitor_suspend(mon);
+    mon->qmp.need_resume = true;
+}
 
 static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
 {
@@ -4266,22 +4286,16 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
      * OOB is not enabled, the server will never drop any command.
      */
     if (!qmp_oob_enabled(mon)) {
-        monitor_suspend(mon);
-        mon->qmp.need_resume = true;
+        monitor_qmp_suspend_locked(mon);
     } else {
-        /* Drop the request if queue is full. */
-        if (mon->qmp.qmp_requests->length >= QMP_REQ_QUEUE_LEN_MAX) {
-            qemu_mutex_unlock(&mon->qmp.qmp_lock);
-            /*
-             * FIXME @id's scope is just @mon, and broadcasting it is
-             * wrong.  If another monitor's client has a command with
-             * the same ID in flight, the event will incorrectly claim
-             * that command was dropped.
-             */
-            qapi_event_send_command_dropped(id,
-                                            COMMAND_DROP_REASON_QUEUE_FULL);
-            qmp_request_free(req_obj);
-            return;
+        /*
+         * If the queue is reaching the length limitation, we queue
+         * this command, meanwhile we suspend the monitor to block new
+         * commands.  We'll resume ourselves until the queue has more
+         * space.
+         */
+        if (mon->qmp.qmp_requests->length >= QMP_REQ_QUEUE_LEN_MAX - 1) {
+            monitor_qmp_suspend_locked(mon);
         }
     }
 
-- 
2.17.1

  parent reply	other threads:[~2018-07-04  8:45 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-04  8:44 [Qemu-devel] [PATCH 0/9] monitor: enable OOB by default Peter Xu
2018-07-04  8:44 ` [Qemu-devel] [PATCH 1/9] monitor: simplify monitor_qmp_setup_handlers_bh Peter Xu
2018-07-05  5:44   ` Markus Armbruster
2018-07-04  8:45 ` [Qemu-devel] [PATCH 2/9] qapi: allow build_params to return "void" Peter Xu
2018-07-05  6:02   ` Markus Armbruster
2018-07-05  6:18     ` Peter Xu
2018-07-04  8:45 ` [Qemu-devel] [PATCH 3/9] qapi: remove error checks for event emission Peter Xu
2018-07-05  8:43   ` Markus Armbruster
2018-07-05  9:17     ` Peter Xu
2018-07-04  8:45 ` [Qemu-devel] [PATCH 4/9] monitor: move need_resume flag into monitor struct Peter Xu
2018-07-05  8:51   ` Markus Armbruster
2018-07-05  9:49     ` Peter Xu
2018-07-05 11:09       ` Markus Armbruster
2018-07-05 11:32         ` Marc-André Lureau
2018-07-05 12:01           ` Peter Xu
2018-07-04  8:45 ` Peter Xu [this message]
2018-07-05 16:47   ` [Qemu-devel] [PATCH 5/9] monitor: suspend monitor instead of send CMD_DROP Eric Blake
2018-07-06  3:49     ` Peter Xu
2018-07-06  8:00       ` Markus Armbruster
2018-07-06  8:09   ` Markus Armbruster
2018-07-06  9:39     ` Peter Xu
2018-07-06 13:19       ` Markus Armbruster
2018-07-10  4:27         ` Peter Xu
2018-07-12  6:10           ` Markus Armbruster
2018-07-12 13:23             ` Markus Armbruster
2018-07-04  8:45 ` [Qemu-devel] [PATCH 6/9] qapi: remove COMMAND_DROPPED event Peter Xu
2018-07-04  8:45 ` [Qemu-devel] [PATCH 7/9] monitor: restrict response queue length too Peter Xu
2018-07-04  8:45 ` [Qemu-devel] [PATCH 8/9] monitor: remove "x-oob", turn oob on by default Peter Xu
2018-07-04  8:45 ` [Qemu-devel] [PATCH 9/9] Revert "tests: Add parameter to qtest_init_without_qmp_handshake" Peter Xu
2018-07-16 17:18 ` [Qemu-devel] [PATCH 0/9] monitor: enable OOB by default Markus Armbruster
2018-07-17 12:08   ` Peter Xu
2018-07-18  8:47     ` Peter Xu
2018-07-18 13:09       ` Markus Armbruster

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20180704084507.14560-6-peterx@redhat.com \
    --to=peterx@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=dgilbert@redhat.com \
    --cc=eblake@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).