monitor: enable OOB by default
v8 cover monitor: enable OOB by default
Based-on: <[email protected]>
Based-on: <[email protected]>
(this series is based on Markus's monitor-next tree)
v8:
- remove patch 1 & 2 since already in the QAPI pull
- squash patch 3 & 4, use Markus's version of commit message (with some of my additions), make sure popping and reading queue length is in the same critical section [Markus]
- add one patch to cover test for queue full [Markus]
- add one patch to resume the monitor earlier when queue not full [Markus]
v7:
- use Markus's commit message for patch "qapi: Drop qapi_event_send_FOO()'s Error ** argument" [Markus]
- update commit message for "qapi: remove COMMAND_DROPPED event" since QEMU 3.0 is released [Eric/Dave]
- rebase to Markus's monitor-next tree:
http://repo.or.cz/qemu/armbru.git/shortlog/refs/heads/monitor-next
the patch "monitor: suspend monitor instead of send CMD_DROP" re-written since people prefer to drop need_resume flag so now I hand-made it. Dropped a few patches since not appliable any more.
Please review. Thanks,
Peter Xu (6):
monitor: Suspend monitor instead dropping commands
monitor: resume the monitor earlier if needed
monitor: remove "x-oob", turn oob on by default
Revert "tests: Add parameter to qtest_init_without_qmp_handshake"
tests: add oob functional test for test-qmp-cmds
tests: qmp-test: add queue full test
docs/interop/qmp-spec.txt | 5 ++- include/monitor/monitor.h | 3 +- monitor.c | 80 +++++++++++++++------------------------ qapi/misc.json | 40 -------------------- tests/libqtest.c | 10 ++--- tests/libqtest.h | 4 +- tests/qmp-test.c | 32 ++++++++++++++-- tests/test-qmp-cmds.c | 16 ++++++++ vl.c | 5 --- 9 files changed, 86 insertions(+), 109 deletions(-)
Signature · 1 line
2.17.1
PATCH v8 1/6 monitor: Suspend monitor instead dropping commands
When a QMP client sends in-band commands more quickly that we can process them, we can either queue them without limit (QUEUE), drop commands when the queue is full (DROP), or suspend receiving commands when the queue is full (SUSPEND). None of them is ideal:
* QUEUE lets a misbehaving client make QEMU eat memory without bounds. Not such a hot idea.
* With DROP, the client has to cope with dropped in-band commands. To inform the client, we send a COMMAND_DROPPED event then. The event is flawed by design in two ways: it's ambiguous (see commit d621cfe0a17), and it brings back the "eat memory without bounds" problem.
* With SUSPEND, the client has to manage the flow of in-band commands to keep the monitor available for out-of-band commands.
We currently DROP. Switch to SUSPEND.
Managing the flow of in-band commands to keep the monitor available for out-of-band commands isn't really hard: just count the number of "outstanding" in-band commands (commands sent minus replies received), and if it exceeds the limit, hold back additional ones until it drops below the limit again.
Note that we need to be careful pairing the suspend with a resume, or else the monitor will hang, possibly forever. And here since we need to make sure both:
(1) popping request from the req queue, and
(2) reading length of the req queue
will be in the same critical section, we let the pop function take the corresponding queue lock when there is a request, then we release the lock from the caller.
--- docs/interop/qmp-spec.txt | 5 ++-- include/monitor/monitor.h | 2 ++ monitor.c | 52 +++++++++++++++++---------------------- qapi/misc.json | 40 ------------------------------ 4 files changed, 28 insertions(+), 71 deletions(-)
docs/interop/qmp-spec.txt +3 -2
@@ -130,8 +130,9 @@ to pass "id" with out-of-band commands. Passing it with all commands is recommended for clients that accept capability "oob". If the client sends in-band commands faster than the server can -execute them, the server will eventually drop commands to limit the -queue length. The sever sends event COMMAND_DROPPED then. +execute them, the server will stop reading the requests from the QMP +channel until the request queue length is reduced to an acceptable +range. Only a few commands support out-of-band execution. The ones that do have "allow-oob": true in output of query-qmp-schema.
include/monitor/monitor.h +2 -0
@@ -15,6 +15,8 @@ extern __thread Monitor *cur_mon;#define MONITOR_USE_PRETTY 0x08#define MONITOR_USE_OOB 0x10 +#define QMP_REQ_QUEUE_LEN_MAX 8 +bool monitor_cur_is_qmp (void );void monitor_init_globals (void );
monitor.c +23 -29
113 lines not on this page · raw message
qapi/misc.json +0 -40
@@ -3432,46 +3432,6 @@ ## { 'command': 'query-sev-capabilities', 'returns': 'SevCapability' } -## -# @CommandDropReason: -# -# Reasons that caused one command to be dropped. -# -# @queue-full: the command queue is full. This can only occur when -# the client sends a new non-oob command before the -# response to the previous non-oob command has been -# received. -# -# Since: 2.12 -## -{ 'enum': 'CommandDropReason', - 'data': [ 'queue-full' ] } - -## -# @COMMAND_DROPPED: -# -# Emitted when a command is dropped due to some reason. Commands can -# only be dropped when the oob capability is enabled. -# -# @id: The dropped command's "id" field. -# FIXME Broken by design. Events are broadcast to all monitors. If -# another monitor's client has a command with the same ID in flight, -# the event will incorrectly claim that command was dropped. -# -# @reason: The reason why the command is dropped. -# -# Since: 2.12 -# -# Example: -# -# { "event": "COMMAND_DROPPED", -# "data": {"result": {"id": "libvirt-102", -# "reason": "queue-full" } } } -# -## -{ 'event': 'COMMAND_DROPPED' , - 'data': { 'id': 'any', 'reason': 'CommandDropReason' } } - ## # @set-numa-node: #
Signature · 1 line
2.17.1
PATCH v8 2/6 monitor: resume the monitor earlier if needed
In reply to Peter XuCurrently when QMP request queue full we won't resume the monitor until we have completely handled the current command. It's not necessary since even before it's handled the queue is already non-full. Moving the resume logic earlier before the command execution, hence drop the need_resume local variable.
--- monitor.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
monitor.c +5 -7
@@ -4130,7 +4130,6 @@ static void monitor_qmp_bh_dispatcher(void *data) {QMPRequest *req_obj =monitor_qmp_requests_pop_any_with_lock ();QDict *rsp; -bool need_resume;Monitor *mon;if (!req_obj) {
@@ -4139,8 +4138,11 @@ static void monitor_qmp_bh_dispatcher(void *data) mon = req_obj->mon;/* qmp_oob_enabled() might change after "qmp_capabilities" */ - need_resume = !qmp_oob_enabled (mon) || - mon->qmp.qmp_requests->length ==QMP_REQ_QUEUE_LEN_MAX -1 ; +if (!qmp_oob_enabled (mon) || + mon->qmp.qmp_requests->length ==QMP_REQ_QUEUE_LEN_MAX -1 ) { +/* Pairs with the monitor_suspend() in handle_qmp_command() */ +monitor_resume (mon); + }qemu_mutex_unlock (&mon->qmp.qmp_queue_lock);if (req_obj->req) {trace_monitor_qmp_cmd_in_band (qobject_get_try_str (req_obj->id) ?:"" );
@@ -4153,10 +4155,6 @@ static void monitor_qmp_bh_dispatcher(void *data)qobject_unref (rsp); } -if (need_resume) { -/* Pairs with the monitor_suspend() in handle_qmp_command() */ -monitor_resume (mon); - }qmp_request_free (req_obj);/* Reschedule instead of looping so the main loop stays responsive */
Signature · 1 line
2.17.1
A message that is not in the archive (sent off-list or not yet received): CAJ+F1CJJB2ZyTQ3OBJ+c49bqZMWSKqfp7UOoM7QBEhH6Exnsbg@mail.gmail.com
A message that is not in the archive (sent off-list or not yet received): 20180929040529.GQ9560@xz-x1
Re: [Qemu-devel] [PATCH v8 2/6] monitor: resume the monitor earlier if needed
Hi Peter
Quoted 49 lines · Peter Xu
Quoted 43 lines · Marc-André Lureau
Hi
Quoted 25 lines · Peter Xu
Currently when QMP request queue full we won't resume the monitor until we have completely handled the current command. It's not necessary since even before it's handled the queue is already non-full. Moving the resume logic earlier before the command execution, hence drop the
need_resumelocal variable.Signed-off-by Peter Xu <[email protected]>--- monitor.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)monitor.c +0
-1@@ -4130,7 +4130,6 @@ static void monitor_qmp_bh_dispatcher(void *data) {QMPRequest *req_obj =monitor_qmp_requests_pop_any_with_lock ();QDict *rsp; -bool need_resume;Monitor *mon;if (!req_obj) {monitor.c static void monitor_qmp_bh_dispatcher(void *data) · line 4145
Quoted 10 lines
monitor.c +5
-2@@ -4139,8 +4138,11 @@ static void monitor_qmp_bh_dispatcher(void *data) mon = req_obj->mon;/* qmp_oob_enabled() might change after "qmp_capabilities" */ - need_resume = !qmp_oob_enabled (mon) || - mon->qmp.qmp_requests->length ==QMP_REQ_QUEUE_LEN_MAX -1 ; +if (!qmp_oob_enabled (mon) || + mon->qmp.qmp_requests->length ==QMP_REQ_QUEUE_LEN_MAX -1 ) { +/* Pairs with the monitor_suspend() in handle_qmp_command() */ +monitor_resume (mon); + }With spice chardev, this may result in a synchronous write. If I read it right, this may re-enter
handle_qmp_commandand dead-lock onqemu_mutex_lock(&mon->qmp.qmp_queue_lock);Quoted 1 line
So at least I would release the lock before resuming :)
For sure this I can do. :) Though I'd like to know more context too.
Quoted 8 lines
I just noticed that we added the
qemu_chr_fe_accept_input()call intomonitor_resume()a month ago which I completely unaware of... then the resuming could be a heavy-weighted function now. I'm a bit worried on whether this would affect the oob thing since noting that we're still in the monitor iothread (which should not block for long). Especially if you mentioned that we'll handle commands again, then could we potentially run non-oob command handlers in oob context here simply due to the call tomonitor_resume()?
monitor_resume() is only called from main thread, afaict.
So I think the problem is rather that qemu_chr_fe_accept_input() is not thread safe (if the same charfe is used in a different thread, like mon_iothread).
So instead of simply kicking the mon_iothread, we should probably schedule a BH to call accept input.
Quoted 5 lines
I'm thinking whether we should use a QEMU bottom half or things alike to handle the
qemu_chr_fe_accept_input(), and keep the resume and the stack simple. As we seem to be facing more dead locks recently, I'm thinking simplifying the stack might be a nice thing to have.
Sure, if that can help :)
Signature · 1 line
Marc-André Lureau
Re: [Qemu-devel] [PATCH v8 2/6] monitor: resume the monitor earlier if needed
Quoted 61 lines · Marc-André Lureau
Hi Peter
Quoted 49 lines · Peter Xu
Quoted 43 lines · Marc-André Lureau
Hi
Quoted 25 lines · Peter Xu
Currently when QMP request queue full we won't resume the monitor until we have completely handled the current command. It's not necessary since even before it's handled the queue is already non-full. Moving the resume logic earlier before the command execution, hence drop the
need_resumelocal variable.Signed-off-by Peter Xu <[email protected]>--- monitor.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)monitor.c +0
-1@@ -4130,7 +4130,6 @@ static void monitor_qmp_bh_dispatcher(void *data) {QMPRequest *req_obj =monitor_qmp_requests_pop_any_with_lock ();QDict *rsp; -bool need_resume;Monitor *mon;if (!req_obj) {monitor.c static void monitor_qmp_bh_dispatcher(void *data) · line 4145
Quoted 10 lines
monitor.c +5
-2@@ -4139,8 +4138,11 @@ static void monitor_qmp_bh_dispatcher(void *data) mon = req_obj->mon;/* qmp_oob_enabled() might change after "qmp_capabilities" */ - need_resume = !qmp_oob_enabled (mon) || - mon->qmp.qmp_requests->length ==QMP_REQ_QUEUE_LEN_MAX -1 ; +if (!qmp_oob_enabled (mon) || + mon->qmp.qmp_requests->length ==QMP_REQ_QUEUE_LEN_MAX -1 ) { +/* Pairs with the monitor_suspend() in handle_qmp_command() */ +monitor_resume (mon); + }With spice chardev, this may result in a synchronous write. If I read it right, this may re-enter
handle_qmp_commandand dead-lock onqemu_mutex_lock(&mon->qmp.qmp_queue_lock);Quoted 1 line
So at least I would release the lock before resuming :)
For sure this I can do. :) Though I'd like to know more context too.
Quoted 8 lines
I just noticed that we added the
qemu_chr_fe_accept_input()call intomonitor_resume()a month ago which I completely unaware of... then the resuming could be a heavy-weighted function now. I'm a bit worried on whether this would affect the oob thing since noting that we're still in the monitor iothread (which should not block for long). Especially if you mentioned that we'll handle commands again, then could we potentially run non-oob command handlers in oob context here simply due to the call tomonitor_resume()?
Quoted 1 line
monitor_resume()is only called from main thread, afaict.
My fault on misreading on that; yes it's only called in main thread.
Quoted 7 lines
So I think the problem is rather that
qemu_chr_fe_accept_input()is not thread safe (if the same charfe is used in a different thread, likemon_iothread).So instead of simply kicking the
mon_iothread, we should probably schedule a BH to call accept input.
Hmm, could you help explain why we need to make qemu_chr_fe_accept_input() thread safe? I see that's only called in main thread as well (besides the call in monitor_resume, it's mostly in memory region ops), or did I misread again?
Regards,
Signature · 1 line
Peter Xu
Re: [Qemu-devel] [PATCH v8 2/6] monitor: resume the monitor earlier if needed
Hi
Quoted 72 lines · Peter Xu
Quoted 61 lines · Marc-André Lureau
Hi Peter
Quoted 49 lines · Peter Xu
Quoted 43 lines · Marc-André Lureau
Hi
Quoted 25 lines · Peter Xu
Currently when QMP request queue full we won't resume the monitor until we have completely handled the current command. It's not necessary since even before it's handled the queue is already non-full. Moving the resume logic earlier before the command execution, hence drop the
need_resumelocal variable.Signed-off-by Peter Xu <[email protected]>--- monitor.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)monitor.c +0
-1@@ -4130,7 +4130,6 @@ static void monitor_qmp_bh_dispatcher(void *data) {QMPRequest *req_obj =monitor_qmp_requests_pop_any_with_lock ();QDict *rsp; -bool need_resume;Monitor *mon;if (!req_obj) {monitor.c static void monitor_qmp_bh_dispatcher(void *data) · line 4145
Quoted 10 lines
monitor.c +5
-2@@ -4139,8 +4138,11 @@ static void monitor_qmp_bh_dispatcher(void *data) mon = req_obj->mon;/* qmp_oob_enabled() might change after "qmp_capabilities" */ - need_resume = !qmp_oob_enabled (mon) || - mon->qmp.qmp_requests->length ==QMP_REQ_QUEUE_LEN_MAX -1 ; +if (!qmp_oob_enabled (mon) || + mon->qmp.qmp_requests->length ==QMP_REQ_QUEUE_LEN_MAX -1 ) { +/* Pairs with the monitor_suspend() in handle_qmp_command() */ +monitor_resume (mon); + }With spice chardev, this may result in a synchronous write. If I read it right, this may re-enter
handle_qmp_commandand dead-lock onqemu_mutex_lock(&mon->qmp.qmp_queue_lock);Quoted 1 line
So at least I would release the lock before resuming :)
For sure this I can do. :) Though I'd like to know more context too.
Quoted 8 lines
I just noticed that we added the
qemu_chr_fe_accept_input()call intomonitor_resume()a month ago which I completely unaware of... then the resuming could be a heavy-weighted function now. I'm a bit worried on whether this would affect the oob thing since noting that we're still in the monitor iothread (which should not block for long). Especially if you mentioned that we'll handle commands again, then could we potentially run non-oob command handlers in oob context here simply due to the call tomonitor_resume()?Quoted 1 line
monitor_resume()is only called from main thread, afaict.My fault on misreading on that; yes it's only called in main thread.
Quoted 5 lines
So I think the problem is rather that
qemu_chr_fe_accept_input()is not thread safe (if the same charfe is used in a different thread, likemon_iothread).
Quoted 7 lines
Quoted 2 lines
So instead of simply kicking the
mon_iothread, we should probably schedule a BH to call accept input.Hmm, could you help explain why we need to make
qemu_chr_fe_accept_input()thread safe? I see that's only called in main thread as well (besides the call inmonitor_resume, it's mostly in memory region ops), or did I misread again?
Yes, it's called from main thread. And that's not very safe for chardev to be called from different threads. Let's try to keep the chardev-related calls in the in mon_iothread (if it is used). I'll send a patch along with some other cleanups.
Quoted 5 lines
Regards,
--
Peter Xu
Signature · 1 line
Marc-André Lureau
PATCH v8 3/6 monitor: remove "x-oob", turn oob on by default
In reply to Peter XuOOB commands were introduced in commit cf869d53172. Unfortunately, we ran into a regression, and had to disable them by default for 2.12 (commit be933ffc23).
http://lists.gnu.org/archive/html/qemu-devel/2018-03/msg06231.html
The regression has since been fixed (commit 951702f39c7 "monitor: bind dispatch bh to iohandler context"). Time to re-enable OOB.
This patch partly reverts be933ffc23 (monitor: new parameter "x-oob"), and turns it on again for non-MUX QMPs. Note that we can't enable Out-Of-Band for monitors with MUX-typed chardev backends, because not all the chardev frontends can run without main thread, or can run in multiple threads.
Some trivial touch-up in the test code is required to make sure qmp-test won't break.
--- include/monitor/monitor.h | 1 - monitor.c | 22 ++++++---------------- tests/libqtest.c | 2 +- tests/qmp-test.c | 2 +- vl.c | 5 ----- 5 files changed, 8 insertions(+), 24 deletions(-)
include/monitor/monitor.h +0 -1
@@ -13,7 +13,6 @@ extern __thread Monitor *cur_mon;#define MONITOR_USE_READLINE 0x02#define MONITOR_USE_CONTROL 0x04#define MONITOR_USE_PRETTY 0x08 -#define MONITOR_USE_OOB 0x10#define QMP_REQ_QUEUE_LEN_MAX 8
monitor.c +6 -16
@@ -4524,19 +4524,12 @@ void monitor_init(Chardev *chr, int flags) {Monitor *mon =g_malloc (sizeof (*mon));bool use_readline = flags &MONITOR_USE_READLINE ; -bool use_oob = flags &MONITOR_USE_OOB ; - -if (use_oob) { -if (CHARDEV_IS_MUX (chr)) { -error_report ("Monitor out-of-band is not supported with " -"MUX typed chardev backend" ); -exit (1 ); - } -if (use_readline) { -error_report ("Monitor out-of-band is only supported by QMP" ); -exit (1 ); - } - } +/* +* Note: we can't enable Out-Of-Band for monitors with MUX-typed +* chardev backends, because not all the chardev frontends can run +* without main thread, or can run in multiple threads. +*/ +bool use_oob = (flags &MONITOR_USE_CONTROL ) && !CHARDEV_IS_MUX (chr);monitor_data_init (mon, false, use_oob);
@@ -4626,9 +4619,6 @@ QemuOptsList qemu_mon_opts = { },{ .name = "pretty", .type = QEMU_OPT_BOOL, - },{ - .name = "x-oob", - .type = QEMU_OPT_BOOL, }, {/* end of list */ } },
tests/libqtest.c +1 -1
@@ -231,7 +231,7 @@ QTestState *qtest_init_without_qmp_handshake(bool use_oob,"-display none " "%s" , qemu_binary, socket_path,getenv ("QTEST_LOG" ) ?"/dev/fd/2" :"/dev/null" , - qmp_socket_path, use_oob ?",x-oob=on" :"" , + qmp_socket_path,"" , extra_args ?: "");execlp ("/bin/sh" ,"sh" ,"-c" , command,NULL );exit (1 );
tests/qmp-test.c +1 -1
@@ -143,7 +143,7 @@ static void test_qmp_protocol(void)g_assert (q);test_version (qdict_get (q,"version" )); capabilities =qdict_get_qlist (q,"capabilities" ); -g_assert (capabilities &&qlist_empty (capabilities)); +g_assert (capabilities);qobject_unref (resp);/* Test valid command before handshake */
vl.c +0 -5
@@ -2323,11 +2323,6 @@ static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp)if (qemu_opt_get_bool (opts,"pretty" ,0 )) flags |=MONITOR_USE_PRETTY ; -/* OOB is off by default */ -if (qemu_opt_get_bool (opts,"x-oob" ,0 )) { - flags |=MONITOR_USE_OOB ; - } - chardev =qemu_opt_get (opts,"chardev" ); chr =qemu_chr_find (chardev);if (chr ==NULL ) {
Signature · 1 line
2.17.1
PATCH v8 4/6 Revert "tests: Add parameter to qtest_init_without_qmp_handshake"
In reply to Peter XuThis reverts commit ddee57e0176f6ab53b13c6c97605b62737a8fd7a.
Meanwhile, revert one line from fa198ad9bdef to make sure qtest_init_without_qmp_handshake() will only pass in one parameter.
--- tests/libqtest.c | 10 ++++------ tests/libqtest.h | 4 +--- tests/qmp-test.c | 4 ++-- 3 files changed, 7 insertions(+), 11 deletions(-)
tests/libqtest.c +4 -6
@@ -191,8 +191,7 @@ static const char *qtest_qemu_binary(void)return qemu_bin; } -QTestState *qtest_init_without_qmp_handshake (bool use_oob, -const char *extra_args) +QTestState *qtest_init_without_qmp_handshake (const char *extra_args) {QTestState *s;int sock, qmpsock, i;
@@ -225,13 +224,12 @@ QTestState *qtest_init_without_qmp_handshake(bool use_oob, command =g_strdup_printf ("exec %s " "-qtest unix:%s,nowait " "-qtest-log %s " -"-chardev socket,path=%s,nowait,id=char0 " -"-mon chardev=char0,mode=control%s " +"-qmp unix:%s,nowait " "-machine accel=qtest " "-display none " "%s" , qemu_binary, socket_path,getenv ("QTEST_LOG" ) ?"/dev/fd/2" :"/dev/null" , - qmp_socket_path,"" , + qmp_socket_path, extra_args ?:"" );execlp ("/bin/sh" ,"sh" ,"-c" , command,NULL );exit (1 );
@@ -266,7 +264,7 @@ QTestState *qtest_init_without_qmp_handshake(bool use_oob,QTestState *qtest_init (const char *extra_args) { -QTestState *s =qtest_init_without_qmp_handshake (false, extra_args); +QTestState *s =qtest_init_without_qmp_handshake (extra_args);QDict *greeting;/* Read the QMP greeting and then do the handshake */
tests/libqtest.h +1 -3
@@ -55,14 +55,12 @@ QTestState *qtest_init(const char *extra_args);/** * qtest_init_without_qmp_handshake: -* @use_oob: true to have the server advertise OOB support * @extra_args: other arguments to pass to QEMU. CAUTION: these * arguments are subject to word splitting and shell evaluation. * * Returns: #QTestState instance. */ -QTestState *qtest_init_without_qmp_handshake (bool use_oob, -const char *extra_args); +QTestState *qtest_init_without_qmp_handshake (const char *extra_args);/** * qtest_quit:
tests/qmp-test.c +2 -2
@@ -135,7 +135,7 @@ static void test_qmp_protocol(void)QList *capabilities;QTestState *qts; - qts =qtest_init_without_qmp_handshake (false, common_args); + qts =qtest_init_without_qmp_handshake (common_args);/* Test greeting */ resp =qtest_qmp_receive (qts);
@@ -249,7 +249,7 @@ static void test_qmp_oob(void)QList *capabilities;QString *qstr; - qts =qtest_init_without_qmp_handshake (true, common_args); + qts =qtest_init_without_qmp_handshake (common_args);/* Check the greeting message. */ resp =qtest_qmp_receive (qts);
Signature · 1 line
2.17.1
PATCH v8 5/6 tests: add oob functional test for test-qmp-cmds
In reply to Peter XuStraightforward test just to let the test-qmp-cmds be complete.
--- tests/test-qmp-cmds.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
tests/test-qmp-cmds.c +16 -0
@@ -122,6 +122,21 @@ static void test_dispatch_cmd(void)qobject_unref (req); } +static void test_dispatch_cmd_oob (void ) +{ +QDict *req =qdict_new (); +QDict *resp; + +qdict_put_str (req,"exec-oob" ,"test-flags-command" ); + + resp =qmp_dispatch (&qmp_commands,QOBJECT (req), true); +assert (resp !=NULL ); +assert (!qdict_haskey (resp,"error" )); + +qobject_unref (resp); +qobject_unref (req); +} +/* test commands that return an error due to invalid parameters */ static void test_dispatch_cmd_failure (void ) {
@@ -287,6 +302,7 @@ int main(int argc, char **argv)g_test_init (&argc, &argv,NULL );g_test_add_func ("/qmp/dispatch_cmd" , test_dispatch_cmd); +g_test_add_func ("/qmp/dispatch_cmd_oob" , test_dispatch_cmd_oob);g_test_add_func ("/qmp/dispatch_cmd_failure" , test_dispatch_cmd_failure);g_test_add_func ("/qmp/dispatch_cmd_io" , test_dispatch_cmd_io);g_test_add_func ("/qmp/dealloc_types" , test_dealloc_types);
Signature · 1 line
2.17.1
PATCH v8 6/6 tests: qmp-test: add queue full test
In reply to Peter XuWe'll need to include "monitor/monitor.h" for the queue length macro, then we don't need to hard code it.
--- tests/qmp-test.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
tests/qmp-test.c +26 -0
@@ -18,6 +18,7 @@#include "qapi/qmp/qlist.h" #include "qapi/qobject-input-visitor.h" #include "qapi/qmp/qstring.h" +#include "monitor/monitor.h" const char common_args[] ="-nodefaults -machine none" ;
@@ -248,6 +249,8 @@ static void test_qmp_oob(void)const QListEntry *entry;QList *capabilities;QString *qstr; +gchar *id; +int i; qts =qtest_init_without_qmp_handshake (common_args);
@@ -302,6 +305,29 @@ static void test_qmp_oob(void)unblock_blocked_cmd ();recv_cmd_id (qts,"blocks-2" );recv_cmd_id (qts,"err-2" ); + +/* +* Test queue full. When that happens, the out-of-band command +* will only be able to be handled after the queue is shrinked, so +* it'll be processed only after one existing in-band command +* finishes. +*/ +for (i =1 ; i <=QMP_REQ_QUEUE_LEN_MAX ; i++) { + id =g_strdup_printf ("queue-blocks-%d" , i); +send_cmd_that_blocks (qts, id); +g_free (id); + } +send_oob_cmd_that_fails (qts,"oob-1" ); +unblock_blocked_cmd (); +recv_cmd_id (qts,"queue-blocks-1" ); +recv_cmd_id (qts,"oob-1" ); +for (i =2 ; i <=QMP_REQ_QUEUE_LEN_MAX ; i++) { +unblock_blocked_cmd (); + id =g_strdup_printf ("queue-blocks-%d" , i); +recv_cmd_id (qts, id); +g_free (id); + } +cleanup_blocking_cmd ();qtest_quit (qts);
Signature · 1 line
2.17.1