From 65207c59d99f2260c5f1d3b9c491146616a522aa Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 5 Mar 2015 14:35:26 +0100 Subject: monitor: Drop broken, unused asynchronous command interface The asynchronous monitor command interface goes back to commit 940cc30 (Jan 2010). Added a third case to command execution. The hope back then according to the commit message was that all commands get converted to the asynchronous interface, killing off the other two cases. Didn't happen. The initial asynchronous commands balloon and info balloon were converted back to synchronous long ago (commit 96637bc and d72f32), with commit messages calling the asynchronous interface "not fully working" and "deprecated". The only other user went away in commit 3b5704b. New code generally uses synchronous commands and asynchronous events. What exactly is still "not fully working" with asynchronous commands? Well, here's a bug that defeats actual asynchronous use pretty reliably: the reply's ID is wrong (and has always been wrong) unless you use the command synchronously! To reproduce, we need an asynchronous command, so we have to go back before commit 3b5704b. Run QEMU with spice: $ qemu-system-x86_64 -nodefaults -S -spice port=5900,disable-ticketing -qmp stdio {"QMP": {"version": {"qemu": {"micro": 94, "minor": 2, "major": 2}, "package": ""}, "capabilities": []}} Connect a spice client in another terminal: $ remote-viewer spice://localhost:5900 Set up a migration destination dummy in a third terminal: $ socat TCP-LISTEN:12345 STDIO Now paste the following into the QMP monitor: { "execute": "qmp_capabilities", "id": "i0" } { "execute": "client_migrate_info", "id": "i1", "arguments": { "protocol": "spice", "hostname": "localhost", "port": 12345 } } { "execute": "query-kvm", "id": "i2" } Produces two replies immediately, one to qmp_capabilities, and one to query-kvm: {"return": {}, "id": "i0"} {"return": {"enabled": false, "present": true}, "id": "i2"} Both are correct. Two lines of debug output from libspice-server not shown. Now EOF socat's standard input to make it close the connection. This makes the asynchronous client_migrate_info complete. It replies: {"return": {}} Bug: "id": "i1" is missing. Two lines of debug output from libspice-server not shown. Cherry on top: storage for the missing ID is leaked. Get rid of this stuff before somebody hurts himself with it. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 70 ++------------------------------------------------------------- 1 file changed, 2 insertions(+), 68 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index b2561e1e2d..27efeb6804 100644 --- a/monitor.c +++ b/monitor.c @@ -118,12 +118,6 @@ * */ -typedef struct MonitorCompletionData MonitorCompletionData; -struct MonitorCompletionData { - Monitor *mon; - void (*user_print)(Monitor *mon, const QObject *data); -}; - typedef struct mon_cmd_t { const char *name; const char *args_type; @@ -133,10 +127,7 @@ typedef struct mon_cmd_t { union { void (*cmd)(Monitor *mon, const QDict *qdict); int (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data); - int (*cmd_async)(Monitor *mon, const QDict *params, - MonitorCompletion *cb, void *opaque); } mhandler; - int flags; /* @sub_table is a list of 2nd level of commands. If it do not exist, * mhandler should be used. If it exist, sub_table[?].mhandler should be * used, and mhandler of 1st level plays the role of help function. @@ -394,11 +385,6 @@ static inline int handler_is_qobject(const mon_cmd_t *cmd) return cmd->user_print != NULL; } -static inline bool handler_is_async(const mon_cmd_t *cmd) -{ - return cmd->flags & MONITOR_CMD_ASYNC; -} - static inline int monitor_has_error(const Monitor *mon) { return mon->error != NULL; @@ -917,45 +903,6 @@ static void hmp_trace_file(Monitor *mon, const QDict *qdict) } #endif -static void user_monitor_complete(void *opaque, QObject *ret_data) -{ - MonitorCompletionData *data = (MonitorCompletionData *)opaque; - - if (ret_data) { - data->user_print(data->mon, ret_data); - } - monitor_resume(data->mon); - g_free(data); -} - -static void qmp_monitor_complete(void *opaque, QObject *ret_data) -{ - monitor_protocol_emitter(opaque, ret_data); -} - -static int qmp_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd, - const QDict *params) -{ - return cmd->mhandler.cmd_async(mon, params, qmp_monitor_complete, mon); -} - -static void user_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd, - const QDict *params) -{ - int ret; - - MonitorCompletionData *cb_data = g_malloc(sizeof(*cb_data)); - cb_data->mon = mon; - cb_data->user_print = cmd->user_print; - monitor_suspend(mon); - ret = cmd->mhandler.cmd_async(mon, params, - user_monitor_complete, cb_data); - if (ret < 0) { - monitor_resume(mon); - g_free(cb_data); - } -} - static void hmp_info_help(Monitor *mon, const QDict *qdict) { help_cmd(mon, "info"); @@ -4121,9 +4068,7 @@ static void handle_user_command(Monitor *mon, const char *cmdline) if (!cmd) goto out; - if (handler_is_async(cmd)) { - user_async_cmd_handler(mon, cmd, qdict); - } else if (handler_is_qobject(cmd)) { + if (handler_is_qobject(cmd)) { QObject *data = NULL; /* XXX: ignores the error code */ @@ -5054,8 +4999,6 @@ static QDict *qmp_check_input_obj(QObject *input_obj) "object"); return NULL; } - } else if (!strcmp(arg_name, "id")) { - /* FIXME: check duplicated IDs for async commands */ } else { qerror_report(QERR_QMP_EXTRA_MEMBER, arg_name); return NULL; @@ -5134,16 +5077,7 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) goto err_out; } - if (handler_is_async(cmd)) { - err = qmp_async_cmd_handler(mon, cmd, args); - if (err) { - /* emit the error response */ - goto err_out; - } - } else { - qmp_call_cmd(mon, cmd, args); - } - + qmp_call_cmd(mon, cmd, args); goto out; err_out: -- cgit v1.2.3-55-g7522 From 84add864ebd2e6f3c645948ab595d8454165ebc5 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 5 Mar 2015 16:45:15 +0100 Subject: monitor: Clean up after previous commit Inline qmp_call_cmd() along with its helper handler_audit() into its only caller handle_qmp_command(), and simplify the result. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 40 +++++++++++----------------------------- 1 file changed, 11 insertions(+), 29 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index 27efeb6804..416ba10730 100644 --- a/monitor.c +++ b/monitor.c @@ -4045,18 +4045,6 @@ void monitor_set_error(Monitor *mon, QError *qerror) } } -static void handler_audit(Monitor *mon, const mon_cmd_t *cmd, int ret) -{ - if (ret && !monitor_has_error(mon)) { - /* - * If it returns failure, it must have passed on error. - * - * Action: Report an internal error to the client if in QMP. - */ - qerror_report(QERR_UNDEFINED_ERROR); - } -} - static void handle_user_command(Monitor *mon, const char *cmdline) { QDict *qdict; @@ -5013,28 +5001,17 @@ static QDict *qmp_check_input_obj(QObject *input_obj) return input_dict; } -static void qmp_call_cmd(Monitor *mon, const mon_cmd_t *cmd, - const QDict *params) -{ - int ret; - QObject *data = NULL; - - ret = cmd->mhandler.cmd_new(mon, params, &data); - handler_audit(mon, cmd, ret); - monitor_protocol_emitter(mon, data); - qobject_decref(data); -} - static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) { int err; - QObject *obj; + QObject *obj, *data; QDict *input, *args; const mon_cmd_t *cmd; const char *cmd_name; Monitor *mon = cur_mon; args = input = NULL; + data = NULL; obj = json_parser_parse(tokens, NULL); if (!obj) { @@ -5077,12 +5054,17 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) goto err_out; } - qmp_call_cmd(mon, cmd, args); - goto out; + if (cmd->mhandler.cmd_new(mon, args, &data)) { + /* Command failed... */ + if (!monitor_has_error(mon)) { + /* ... without setting an error, so make one up */ + qerror_report(QERR_UNDEFINED_ERROR); + } + } err_out: - monitor_protocol_emitter(mon, NULL); -out: + monitor_protocol_emitter(mon, data); + qobject_decref(data); QDECREF(input); QDECREF(args); } -- cgit v1.2.3-55-g7522 From 13cadefbda71e119db79fe0b7a4efd26a6d005bd Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 5 Mar 2015 19:16:58 +0100 Subject: monitor: Improve and document client_migrate_info protocol error Protocol must be spice, vnc isn't implemented. Fix up documentation. Attempts to use vnc or any other unknown protocol yield the misleading error message "Invalid parameter 'protocol'". Improve it to "Parameter 'protocol' expects spice". Cc: Gerd Hoffmann Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by. Gerd Hoffmann Reviewed-by: Luiz Capitulino --- hmp-commands.hx | 8 ++++---- monitor.c | 2 +- qmp-commands.hx | 14 +++++++------- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'monitor.c') diff --git a/hmp-commands.hx b/hmp-commands.hx index e864a6ca81..0cf592bcf8 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1011,7 +1011,7 @@ ETEXI .name = "client_migrate_info", .args_type = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?", .params = "protocol hostname port tls-port cert-subject", - .help = "send migration info to spice/vnc client", + .help = "set migration information for remote display", .user_print = monitor_user_noop, .mhandler.cmd_new = client_migrate_info, }, @@ -1019,9 +1019,9 @@ ETEXI STEXI @item client_migrate_info @var{protocol} @var{hostname} @var{port} @var{tls-port} @var{cert-subject} @findex client_migrate_info -Set the spice/vnc connection info for the migration target. The spice/vnc -server will ask the spice/vnc client to automatically reconnect using the -new parameters (if specified) once the vm migration finished successfully. +Set migration information for remote display. This makes the server +ask the client to automatically reconnect using the new parameters +once migration finished successfully. Only implemented for SPICE. ETEXI { diff --git a/monitor.c b/monitor.c index 416ba10730..81703093f9 100644 --- a/monitor.c +++ b/monitor.c @@ -1063,7 +1063,7 @@ static int client_migrate_info(Monitor *mon, const QDict *qdict, return 0; } - qerror_report(QERR_INVALID_PARAMETER, "protocol"); + qerror_report(QERR_INVALID_PARAMETER_VALUE, "protocol", "spice"); return -1; } diff --git a/qmp-commands.hx b/qmp-commands.hx index 14e109eb5c..a9768a25b6 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -784,23 +784,23 @@ EQMP .name = "client_migrate_info", .args_type = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?", .params = "protocol hostname port tls-port cert-subject", - .help = "send migration info to spice/vnc client", + .help = "set migration information for remote display", .mhandler.cmd_new = client_migrate_info, }, SQMP client_migrate_info ------------------- +------------------- -Set the spice/vnc connection info for the migration target. The spice/vnc -server will ask the spice/vnc client to automatically reconnect using the -new parameters (if specified) once the vm migration finished successfully. +Set migration information for remote display. This makes the server +ask the client to automatically reconnect using the new parameters +once migration finished successfully. Only implemented for SPICE. Arguments: -- "protocol": protocol: "spice" or "vnc" (json-string) +- "protocol": must be "spice" (json-string) - "hostname": migration target hostname (json-string) -- "port": spice/vnc tcp port for plaintext channels (json-int, optional) +- "port": spice tcp port for plaintext channels (json-int, optional) - "tls-port": spice tcp port for tls-secured channels (json-int, optional) - "cert-subject": server certificate subject (json-string, optional) -- cgit v1.2.3-55-g7522 From b8a185bc9a8ecbdc74fd64672e4abdd09a558e1c Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 5 Mar 2015 17:29:02 +0100 Subject: monitor: Convert client_migrate_info to QAPI Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- hmp-commands.hx | 3 +-- hmp.c | 17 +++++++++++++++++ hmp.h | 1 + monitor.c | 42 ++++++++++++++++++------------------------ qapi-schema.json | 19 +++++++++++++++++++ qmp-commands.hx | 2 +- 6 files changed, 57 insertions(+), 27 deletions(-) (limited to 'monitor.c') diff --git a/hmp-commands.hx b/hmp-commands.hx index 0cf592bcf8..af2de61066 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1012,8 +1012,7 @@ ETEXI .args_type = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?", .params = "protocol hostname port tls-port cert-subject", .help = "set migration information for remote display", - .user_print = monitor_user_noop, - .mhandler.cmd_new = client_migrate_info, + .mhandler.cmd = hmp_client_migrate_info, }, STEXI diff --git a/hmp.c b/hmp.c index e17852d1f9..5a43f9d2bd 100644 --- a/hmp.c +++ b/hmp.c @@ -1250,6 +1250,23 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) } } +void hmp_client_migrate_info(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + const char *protocol = qdict_get_str(qdict, "protocol"); + const char *hostname = qdict_get_str(qdict, "hostname"); + bool has_port = qdict_haskey(qdict, "port"); + int port = qdict_get_try_int(qdict, "port", -1); + bool has_tls_port = qdict_haskey(qdict, "tls-port"); + int tls_port = qdict_get_try_int(qdict, "tls-port", -1); + const char *cert_subject = qdict_get_try_str(qdict, "cert-subject"); + + qmp_client_migrate_info(protocol, hostname, + has_port, port, has_tls_port, tls_port, + !!cert_subject, cert_subject, &err); + hmp_handle_error(mon, &err); +} + void hmp_set_password(Monitor *mon, const QDict *qdict) { const char *protocol = qdict_get_str(qdict, "protocol"); diff --git a/hmp.h b/hmp.h index a158e3fda1..b81439cc3c 100644 --- a/hmp.h +++ b/hmp.h @@ -67,6 +67,7 @@ void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict); void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict); void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict); void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict); +void hmp_client_migrate_info(Monitor *mon, const QDict *qdict); void hmp_set_password(Monitor *mon, const QDict *qdict); void hmp_expire_password(Monitor *mon, const QDict *qdict); void hmp_eject(Monitor *mon, const QDict *qdict); diff --git a/monitor.c b/monitor.c index 81703093f9..38ff972755 100644 --- a/monitor.c +++ b/monitor.c @@ -1032,39 +1032,33 @@ static void hmp_info_trace_events(Monitor *mon, const QDict *qdict) qapi_free_TraceEventInfoList(events); } -static int client_migrate_info(Monitor *mon, const QDict *qdict, - QObject **ret_data) +void qmp_client_migrate_info(const char *protocol, const char *hostname, + bool has_port, int64_t port, + bool has_tls_port, int64_t tls_port, + bool has_cert_subject, const char *cert_subject, + Error **errp) { - const char *protocol = qdict_get_str(qdict, "protocol"); - const char *hostname = qdict_get_str(qdict, "hostname"); - const char *subject = qdict_get_try_str(qdict, "cert-subject"); - int port = qdict_get_try_int(qdict, "port", -1); - int tls_port = qdict_get_try_int(qdict, "tls-port", -1); - Error *err = NULL; - int ret; - if (strcmp(protocol, "spice") == 0) { - if (!qemu_using_spice(&err)) { - qerror_report_err(err); - error_free(err); - return -1; + if (!qemu_using_spice(errp)) { + return; } - if (port == -1 && tls_port == -1) { - qerror_report(QERR_MISSING_PARAMETER, "port/tls-port"); - return -1; + if (!has_port && !has_tls_port) { + error_set(errp, QERR_MISSING_PARAMETER, "port/tls-port"); + return; } - ret = qemu_spice_migrate_info(hostname, port, tls_port, subject); - if (ret != 0) { - qerror_report(QERR_UNDEFINED_ERROR); - return -1; + if (qemu_spice_migrate_info(hostname, + has_port ? port : -1, + has_tls_port ? tls_port : -1, + cert_subject)) { + error_set(errp, QERR_UNDEFINED_ERROR); + return; } - return 0; + return; } - qerror_report(QERR_INVALID_PARAMETER_VALUE, "protocol", "spice"); - return -1; + error_set(errp, QERR_INVALID_PARAMETER_VALUE, "protocol", "spice"); } static void hmp_logfile(Monitor *mon, const QDict *qdict) diff --git a/qapi-schema.json b/qapi-schema.json index 0662a9b445..6e17a5c36c 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -637,6 +637,25 @@ { 'command': 'query-migrate-parameters', 'returns': 'MigrationParameters' } +## +# @client_migrate_info +# +# Set migration information for remote display. This makes the server +# ask the client to automatically reconnect using the new parameters +# once migration finished successfully. Only implemented for SPICE. +# +# @protocol: must be "spice" +# @hostname: migration target hostname +# @port: #optional spice tcp port for plaintext channels +# @tls-port: #optional spice tcp port for tls-secured channels +# @cert-subject: #optional server certificate subject +# +# Since: 0.14.0 +## +{ 'command': 'client_migrate_info', + 'data': { 'protocol': 'str', 'hostname': 'str', '*port': 'int', + '*tls-port': 'int', '*cert-subject': 'str' } } + ## # @MouseInfo: # diff --git a/qmp-commands.hx b/qmp-commands.hx index a9768a25b6..867a21fab6 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -785,7 +785,7 @@ EQMP .args_type = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?", .params = "protocol hostname port tls-port cert-subject", .help = "set migration information for remote display", - .mhandler.cmd_new = client_migrate_info, + .mhandler.cmd_new = qmp_marshal_input_client_migrate_info, }, SQMP -- cgit v1.2.3-55-g7522 From 318660f84a0a26451750aee68ab7dcf88731637d Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 5 Mar 2015 17:24:48 +0100 Subject: monitor: Use traditional command interface for HMP device_add All QMP commands use the "new" handler interface (mhandler.cmd_new). Most HMP commands still use the traditional interface (mhandler.cmd), but a few use the "new" one. Complicates handle_user_command() for no gain, so I'm converting these to the traditional interface. For device_add, that's easy: just wrap the obvious hmp_device_add() around do_device_add(). monitor_user_noop() is now unused, drop it. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- hmp-commands.hx | 3 +-- hmp.c | 6 ++++++ hmp.h | 1 + monitor.c | 2 -- 4 files changed, 8 insertions(+), 4 deletions(-) (limited to 'monitor.c') diff --git a/hmp-commands.hx b/hmp-commands.hx index 52579698af..eff2f976d3 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -653,8 +653,7 @@ ETEXI .args_type = "device:O", .params = "driver[,prop=value][,...]", .help = "add device, like -device on the command line", - .user_print = monitor_user_noop, - .mhandler.cmd_new = do_device_add, + .mhandler.cmd = hmp_device_add, .command_completion = device_add_completion, }, diff --git a/hmp.c b/hmp.c index 5a43f9d2bd..514f22fbfa 100644 --- a/hmp.c +++ b/hmp.c @@ -22,6 +22,7 @@ #include "qmp-commands.h" #include "qemu/sockets.h" #include "monitor/monitor.h" +#include "monitor/qdev.h" #include "qapi/opts-visitor.h" #include "qapi/string-output-visitor.h" #include "qapi-visit.h" @@ -1499,6 +1500,11 @@ void hmp_migrate(Monitor *mon, const QDict *qdict) } } +void hmp_device_add(Monitor *mon, const QDict *qdict) +{ + do_device_add(mon, qdict, NULL); +} + void hmp_device_del(Monitor *mon, const QDict *qdict) { const char *id = qdict_get_str(qdict, "id"); diff --git a/hmp.h b/hmp.h index b81439cc3c..a70ac4fd0f 100644 --- a/hmp.h +++ b/hmp.h @@ -80,6 +80,7 @@ void hmp_block_job_pause(Monitor *mon, const QDict *qdict); void hmp_block_job_resume(Monitor *mon, const QDict *qdict); void hmp_block_job_complete(Monitor *mon, const QDict *qdict); void hmp_migrate(Monitor *mon, const QDict *qdict); +void hmp_device_add(Monitor *mon, const QDict *qdict); void hmp_device_del(Monitor *mon, const QDict *qdict); void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict); void hmp_netdev_add(Monitor *mon, const QDict *qdict); diff --git a/monitor.c b/monitor.c index 38ff972755..85bb71ed6f 100644 --- a/monitor.c +++ b/monitor.c @@ -378,8 +378,6 @@ static int GCC_FMT_ATTR(2, 3) monitor_fprintf(FILE *stream, return 0; } -static void monitor_user_noop(Monitor *mon, const QObject *data) { } - static inline int handler_is_qobject(const mon_cmd_t *cmd) { return cmd->user_print != NULL; -- cgit v1.2.3-55-g7522 From 8a4f501c09bcb8b5a220699e378aa8fb7ec178e4 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 5 Mar 2015 18:50:05 +0100 Subject: monitor: Drop unused "new" HMP command interface Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index 85bb71ed6f..9403c2c8e2 100644 --- a/monitor.c +++ b/monitor.c @@ -123,7 +123,6 @@ typedef struct mon_cmd_t { const char *args_type; const char *params; const char *help; - void (*user_print)(Monitor *mon, const QObject *data); union { void (*cmd)(Monitor *mon, const QDict *qdict); int (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data); @@ -378,11 +377,6 @@ static int GCC_FMT_ATTR(2, 3) monitor_fprintf(FILE *stream, return 0; } -static inline int handler_is_qobject(const mon_cmd_t *cmd) -{ - return cmd->user_print != NULL; -} - static inline int monitor_has_error(const Monitor *mon) { return mon->error != NULL; @@ -4045,24 +4039,10 @@ static void handle_user_command(Monitor *mon, const char *cmdline) qdict = qdict_new(); cmd = monitor_parse_command(mon, cmdline, 0, mon->cmd_table, qdict); - if (!cmd) - goto out; - - if (handler_is_qobject(cmd)) { - QObject *data = NULL; - - /* XXX: ignores the error code */ - cmd->mhandler.cmd_new(mon, qdict, &data); - assert(!monitor_has_error(mon)); - if (data) { - cmd->user_print(mon, data); - qobject_decref(data); - } - } else { + if (cmd) { cmd->mhandler.cmd(mon, qdict); } -out: QDECREF(qdict); } -- cgit v1.2.3-55-g7522 From 326283aa5d4d51d576185af4cbbdc29f648cd766 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 2 Mar 2015 18:39:09 +0100 Subject: monitor: Propagate errors through qmp_check_client_args() Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 65 ++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 33 insertions(+), 32 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index 9403c2c8e2..0afcf60ea8 100644 --- a/monitor.c +++ b/monitor.c @@ -4736,8 +4736,9 @@ static bool invalid_qmp_mode(const Monitor *mon, const mon_cmd_t *cmd) * the QMP_ACCEPT_UNKNOWNS flag is set, then the * checking is skipped for it. */ -static int check_client_args_type(const QDict *client_args, - const QDict *cmd_args, int flags) +static void check_client_args_type(const QDict *client_args, + const QDict *cmd_args, int flags, + Error **errp) { const QDictEntry *ent; @@ -4754,8 +4755,8 @@ static int check_client_args_type(const QDict *client_args, continue; } /* client arg doesn't exist */ - qerror_report(QERR_INVALID_PARAMETER, client_arg_name); - return -1; + error_set(errp, QERR_INVALID_PARAMETER, client_arg_name); + return; } arg_type = qobject_to_qstring(obj); @@ -4767,9 +4768,9 @@ static int check_client_args_type(const QDict *client_args, case 'B': case 's': if (qobject_type(client_arg) != QTYPE_QSTRING) { - qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name, - "string"); - return -1; + error_set(errp, QERR_INVALID_PARAMETER_TYPE, + client_arg_name, "string"); + return; } break; case 'i': @@ -4777,25 +4778,25 @@ static int check_client_args_type(const QDict *client_args, case 'M': case 'o': if (qobject_type(client_arg) != QTYPE_QINT) { - qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name, - "int"); - return -1; + error_set(errp, QERR_INVALID_PARAMETER_TYPE, + client_arg_name, "int"); + return; } break; case 'T': if (qobject_type(client_arg) != QTYPE_QINT && qobject_type(client_arg) != QTYPE_QFLOAT) { - qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name, - "number"); - return -1; + error_set(errp, QERR_INVALID_PARAMETER_TYPE, + client_arg_name, "number"); + return; } break; case 'b': case '-': if (qobject_type(client_arg) != QTYPE_QBOOL) { - qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name, - "bool"); - return -1; + error_set(errp, QERR_INVALID_PARAMETER_TYPE, + client_arg_name, "bool"); + return; } break; case 'O': @@ -4814,16 +4815,15 @@ static int check_client_args_type(const QDict *client_args, abort(); } } - - return 0; } /* * - Check if the client has passed all mandatory args * - Set special flags for argument validation */ -static int check_mandatory_args(const QDict *cmd_args, - const QDict *client_args, int *flags) +static void check_mandatory_args(const QDict *cmd_args, + const QDict *client_args, int *flags, + Error **errp) { const QDictEntry *ent; @@ -4838,12 +4838,10 @@ static int check_mandatory_args(const QDict *cmd_args, } else if (qstring_get_str(type)[0] != '-' && qstring_get_str(type)[1] != '?' && !qdict_haskey(client_args, cmd_arg_name)) { - qerror_report(QERR_MISSING_PARAMETER, cmd_arg_name); - return -1; + error_set(errp, QERR_MISSING_PARAMETER, cmd_arg_name); + return; } } - - return 0; } static QDict *qdict_from_args_type(const char *args_type) @@ -4899,24 +4897,26 @@ out: * 3. Each argument provided by the client must have the type expected * by the command */ -static int qmp_check_client_args(const mon_cmd_t *cmd, QDict *client_args) +static void qmp_check_client_args(const mon_cmd_t *cmd, QDict *client_args, + Error **errp) { - int flags, err; + Error *err = NULL; + int flags; QDict *cmd_args; cmd_args = qdict_from_args_type(cmd->args_type); flags = 0; - err = check_mandatory_args(cmd_args, client_args, &flags); + check_mandatory_args(cmd_args, client_args, &flags, &err); if (err) { goto out; } - err = check_client_args_type(client_args, cmd_args, flags); + check_client_args_type(client_args, cmd_args, flags, &err); out: + error_propagate(errp, err); QDECREF(cmd_args); - return err; } /* @@ -4975,7 +4975,7 @@ static QDict *qmp_check_input_obj(QObject *input_obj) static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) { - int err; + Error *local_err = NULL; QObject *obj, *data; QDict *input, *args; const mon_cmd_t *cmd; @@ -5021,8 +5021,9 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) QINCREF(args); } - err = qmp_check_client_args(cmd, args); - if (err < 0) { + qmp_check_client_args(cmd, args, &local_err); + if (local_err) { + qerror_report_err(local_err); goto err_out; } -- cgit v1.2.3-55-g7522 From ba0510aad43148e5284cb52fcc7a0103b5e0af4d Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 2 Mar 2015 18:41:43 +0100 Subject: monitor: Propagate errors through qmp_check_input_obj() Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index 0afcf60ea8..61ea3464e3 100644 --- a/monitor.c +++ b/monitor.c @@ -4929,14 +4929,14 @@ out: * 5. If the "id" key exists, it can be anything (ie. json-value) * 6. Any argument not listed above is considered invalid */ -static QDict *qmp_check_input_obj(QObject *input_obj) +static QDict *qmp_check_input_obj(QObject *input_obj, Error **errp) { const QDictEntry *ent; int has_exec_key = 0; QDict *input_dict; if (qobject_type(input_obj) != QTYPE_QDICT) { - qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "object"); + error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "object"); return NULL; } @@ -4948,25 +4948,25 @@ static QDict *qmp_check_input_obj(QObject *input_obj) if (!strcmp(arg_name, "execute")) { if (qobject_type(arg_obj) != QTYPE_QSTRING) { - qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute", - "string"); + error_set(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, + "execute", "string"); return NULL; } has_exec_key = 1; } else if (!strcmp(arg_name, "arguments")) { if (qobject_type(arg_obj) != QTYPE_QDICT) { - qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "arguments", - "object"); + error_set(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, + "arguments", "object"); return NULL; } } else { - qerror_report(QERR_QMP_EXTRA_MEMBER, arg_name); + error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name); return NULL; } } if (!has_exec_key) { - qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "execute"); + error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute"); return NULL; } @@ -4992,8 +4992,9 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) goto err_out; } - input = qmp_check_input_obj(obj); + input = qmp_check_input_obj(obj, &local_err); if (!input) { + qerror_report_err(local_err); qobject_decref(obj); goto err_out; } -- cgit v1.2.3-55-g7522 From 4086182fcd9b106345b5cc535d78bcc6d13a7683 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 29 May 2015 10:27:16 +0200 Subject: monitor: Propagate errors through invalid_qmp_mode() Signed-off-by: Markus Armbruster Reviewed-by: Luiz Capitulino --- monitor.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index 61ea3464e3..d336b8f94c 100644 --- a/monitor.c +++ b/monitor.c @@ -4708,19 +4708,20 @@ static int monitor_can_read(void *opaque) return (mon->suspend_cnt == 0) ? 1 : 0; } -static bool invalid_qmp_mode(const Monitor *mon, const mon_cmd_t *cmd) +static bool invalid_qmp_mode(const Monitor *mon, const mon_cmd_t *cmd, + Error **errp) { bool is_cap = cmd->mhandler.cmd_new == do_qmp_capabilities; if (is_cap && qmp_cmd_mode(mon)) { - qerror_report(ERROR_CLASS_COMMAND_NOT_FOUND, - "Capabilities negotiation is already complete, command " - "'%s' ignored", cmd->name); + error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, + "Capabilities negotiation is already complete, command " + "'%s' ignored", cmd->name); return true; } if (!is_cap && !qmp_cmd_mode(mon)) { - qerror_report(ERROR_CLASS_COMMAND_NOT_FOUND, - "Expecting capabilities negotiation with " - "'qmp_capabilities' before command '%s'", cmd->name); + error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, + "Expecting capabilities negotiation with " + "'qmp_capabilities' before command '%s'", cmd->name); return true; } return false; @@ -5010,7 +5011,8 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) "The command %s has not been found", cmd_name); goto err_out; } - if (invalid_qmp_mode(mon, cmd)) { + if (invalid_qmp_mode(mon, cmd, &local_err)) { + qerror_report_err(local_err); goto err_out; } -- cgit v1.2.3-55-g7522 From 70ea0c58991ae44b5a1e67d9c189d79029168cb1 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 6 Mar 2015 10:47:08 +0100 Subject: monitor: Wean monitor_protocol_emitter() off mon->error Move mon->error handling to its caller handle_qmp_command(). Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index d336b8f94c..56564d5bef 100644 --- a/monitor.c +++ b/monitor.c @@ -407,13 +407,14 @@ static QDict *build_qmp_error_dict(const QError *err) return qobject_to_qdict(obj); } -static void monitor_protocol_emitter(Monitor *mon, QObject *data) +static void monitor_protocol_emitter(Monitor *mon, QObject *data, + QError *err) { QDict *qmp; trace_monitor_protocol_emitter(mon); - if (!monitor_has_error(mon)) { + if (!err) { /* success response */ qmp = qdict_new(); if (data) { @@ -425,9 +426,7 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data) } } else { /* error response */ - qmp = build_qmp_error_dict(mon->error); - QDECREF(mon->error); - mon->error = NULL; + qmp = build_qmp_error_dict(err); } if (mon->mc->id) { @@ -5039,8 +5038,10 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) } err_out: - monitor_protocol_emitter(mon, data); + monitor_protocol_emitter(mon, data, mon->error); qobject_decref(data); + QDECREF(mon->error); + mon->error = NULL; QDECREF(input); QDECREF(args); } -- cgit v1.2.3-55-g7522 From 452e0300a3521f13b6c4ba0b99a8cea3a29209f1 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 6 Mar 2015 19:11:13 +0100 Subject: monitor: Inline monitor_has_error() into its only caller Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index 56564d5bef..91f8a4e5d7 100644 --- a/monitor.c +++ b/monitor.c @@ -377,11 +377,6 @@ static int GCC_FMT_ATTR(2, 3) monitor_fprintf(FILE *stream, return 0; } -static inline int monitor_has_error(const Monitor *mon) -{ - return mon->error != NULL; -} - static void monitor_json_emitter(Monitor *mon, const QObject *data) { QString *json; @@ -5031,7 +5026,7 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) if (cmd->mhandler.cmd_new(mon, args, &data)) { /* Command failed... */ - if (!monitor_has_error(mon)) { + if (!mon->error) { /* ... without setting an error, so make one up */ qerror_report(QERR_UNDEFINED_ERROR); } -- cgit v1.2.3-55-g7522 From 710aec915d208246891b68e2ba61b54951edc508 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 6 Mar 2015 11:28:00 +0100 Subject: monitor: Limit QError use to command handlers The previous commits narrowed use of QError to handle_qmp_command() and its helpers monitor_protocol_emitter(), build_qmp_error_dict(). Narrow it further to just the command handler call: instead of converting Error to QError throughout handle_qmp_command(), convert the QError gotten from the command handler to Error, and switch the helpers from QError to Error. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index 91f8a4e5d7..888d77153c 100644 --- a/monitor.c +++ b/monitor.c @@ -391,19 +391,19 @@ static void monitor_json_emitter(Monitor *mon, const QObject *data) QDECREF(json); } -static QDict *build_qmp_error_dict(const QError *err) +static QDict *build_qmp_error_dict(Error *err) { QObject *obj; - obj = qobject_from_jsonf("{ 'error': { 'class': %s, 'desc': %p } }", - ErrorClass_lookup[err->err_class], - qerror_human(err)); + obj = qobject_from_jsonf("{ 'error': { 'class': %s, 'desc': %s } }", + ErrorClass_lookup[error_get_class(err)], + error_get_pretty(err)); return qobject_to_qdict(obj); } static void monitor_protocol_emitter(Monitor *mon, QObject *data, - QError *err) + Error *err) { QDict *qmp; @@ -4983,13 +4983,12 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) obj = json_parser_parse(tokens, NULL); if (!obj) { // FIXME: should be triggered in json_parser_parse() - qerror_report(QERR_JSON_PARSING); + error_set(&local_err, QERR_JSON_PARSING); goto err_out; } input = qmp_check_input_obj(obj, &local_err); if (!input) { - qerror_report_err(local_err); qobject_decref(obj); goto err_out; } @@ -5001,12 +5000,11 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) trace_handle_qmp_command(mon, cmd_name); cmd = qmp_find_cmd(cmd_name); if (!cmd) { - qerror_report(ERROR_CLASS_COMMAND_NOT_FOUND, - "The command %s has not been found", cmd_name); + error_set(&local_err, ERROR_CLASS_COMMAND_NOT_FOUND, + "The command %s has not been found", cmd_name); goto err_out; } if (invalid_qmp_mode(mon, cmd, &local_err)) { - qerror_report_err(local_err); goto err_out; } @@ -5020,7 +5018,6 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) qmp_check_client_args(cmd, args, &local_err); if (local_err) { - qerror_report_err(local_err); goto err_out; } @@ -5028,12 +5025,16 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) /* Command failed... */ if (!mon->error) { /* ... without setting an error, so make one up */ - qerror_report(QERR_UNDEFINED_ERROR); + error_set(&local_err, QERR_UNDEFINED_ERROR); } } + if (mon->error) { + error_set(&local_err, mon->error->err_class, "%s", + mon->error->err_msg); + } err_out: - monitor_protocol_emitter(mon, data, mon->error); + monitor_protocol_emitter(mon, data, local_err); qobject_decref(data); QDECREF(mon->error); mon->error = NULL; -- cgit v1.2.3-55-g7522 From 7ef6cf6341c453021939c909adf2d62d9dc25fd5 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 6 Mar 2015 19:12:36 +0100 Subject: monitor: Rename handle_user_command() to handle_hmp_command() Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index 888d77153c..a39cd6cd98 100644 --- a/monitor.c +++ b/monitor.c @@ -574,7 +574,7 @@ static int do_qmp_capabilities(Monitor *mon, const QDict *params, return 0; } -static void handle_user_command(Monitor *mon, const char *cmdline); +static void handle_hmp_command(Monitor *mon, const char *cmdline); static void monitor_data_init(Monitor *mon) { @@ -613,7 +613,7 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index, } } - handle_user_command(&hmp, command_line); + handle_hmp_command(&hmp, command_line); cur_mon = old_mon; qemu_mutex_lock(&hmp.out_lock); @@ -4025,7 +4025,7 @@ void monitor_set_error(Monitor *mon, QError *qerror) } } -static void handle_user_command(Monitor *mon, const char *cmdline) +static void handle_hmp_command(Monitor *mon, const char *cmdline) { QDict *qdict; const mon_cmd_t *cmd; @@ -5070,7 +5070,7 @@ static void monitor_read(void *opaque, const uint8_t *buf, int size) if (size == 0 || buf[size - 1] != 0) monitor_printf(cur_mon, "corrupted command\n"); else - handle_user_command(cur_mon, (char *)buf); + handle_hmp_command(cur_mon, (char *)buf); } cur_mon = old_mon; @@ -5082,7 +5082,7 @@ static void monitor_command_cb(void *opaque, const char *cmdline, Monitor *mon = opaque; monitor_suspend(mon); - handle_user_command(mon, cmdline); + handle_hmp_command(mon, cmdline); monitor_resume(mon); } -- cgit v1.2.3-55-g7522 From c83fe23b58199a6d4a938305cb0fc45fe7729b61 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 6 Mar 2015 19:20:51 +0100 Subject: monitor: Rename monitor_control_read(), monitor_control_event() ... to monitor_qmp_read(), monitor_qmp_event(). Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index a39cd6cd98..5c2aa2789d 100644 --- a/monitor.c +++ b/monitor.c @@ -5042,10 +5042,7 @@ err_out: QDECREF(args); } -/** - * monitor_control_read(): Read and handle QMP input - */ -static void monitor_control_read(void *opaque, const uint8_t *buf, int size) +static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size) { Monitor *old_mon = cur_mon; @@ -5110,10 +5107,7 @@ static QObject *get_qmp_greeting(void) return qobject_from_jsonf("{'QMP':{'version': %p,'capabilities': []}}",ver); } -/** - * monitor_control_event(): Print QMP gretting - */ -static void monitor_control_event(void *opaque, int event) +static void monitor_qmp_event(void *opaque, int event) { QObject *data; Monitor *mon = opaque; @@ -5263,8 +5257,8 @@ void monitor_init(CharDriverState *chr, int flags) if (monitor_ctrl_mode(mon)) { mon->mc = g_malloc0(sizeof(MonitorControl)); /* Control mode requires special handlers */ - qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read, - monitor_control_event, mon); + qemu_chr_add_handlers(chr, monitor_can_read, monitor_qmp_read, + monitor_qmp_event, mon); qemu_chr_fe_set_echo(chr, true); json_message_parser_init(&mon->mc->parser, handle_qmp_command); -- cgit v1.2.3-55-g7522 From 74358f2a1647b239d87340ea0024f9d2efa266ca Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 6 Mar 2015 19:35:59 +0100 Subject: monitor: Unbox Monitor member mc and rename to qmp While there, rename its type as well, from MonitorControl to MonitorQMP. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index 5c2aa2789d..f20e918fe4 100644 --- a/monitor.c +++ b/monitor.c @@ -161,11 +161,11 @@ struct MonFdset { QLIST_ENTRY(MonFdset) next; }; -typedef struct MonitorControl { +typedef struct { QObject *id; JSONMessageParser parser; int command_mode; -} MonitorControl; +} MonitorQMP; /* * To prevent flooding clients, events can be throttled. The @@ -195,7 +195,7 @@ struct Monitor { int mux_out; ReadLineState *rs; - MonitorControl *mc; + MonitorQMP qmp; CPUState *mon_cpu; BlockCompletionFunc *password_completion_cb; void *password_opaque; @@ -228,7 +228,7 @@ static void monitor_command_cb(void *opaque, const char *cmdline, static inline int qmp_cmd_mode(const Monitor *mon) { - return (mon->mc ? mon->mc->command_mode : 0); + return mon->qmp.command_mode; } /* Return true if in control mode, false otherwise */ @@ -424,9 +424,9 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data, qmp = build_qmp_error_dict(err); } - if (mon->mc->id) { - qdict_put_obj(qmp, "id", mon->mc->id); - mon->mc->id = NULL; + if (mon->qmp.id) { + qdict_put_obj(qmp, "id", mon->qmp.id); + mon->qmp.id = NULL; } monitor_json_emitter(mon, QOBJECT(qmp)); @@ -568,7 +568,7 @@ static int do_qmp_capabilities(Monitor *mon, const QDict *params, { /* Will setup QMP capabilities in the future */ if (monitor_ctrl_mode(mon)) { - mon->mc->command_mode = 1; + mon->qmp.command_mode = 1; } return 0; @@ -4993,8 +4993,8 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) goto err_out; } - mon->mc->id = qdict_get(input, "id"); - qobject_incref(mon->mc->id); + mon->qmp.id = qdict_get(input, "id"); + qobject_incref(mon->qmp.id); cmd_name = qdict_get_str(input, "execute"); trace_handle_qmp_command(mon, cmd_name); @@ -5048,7 +5048,7 @@ static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size) cur_mon = opaque; - json_message_parser_feed(&cur_mon->mc->parser, (const char *) buf, size); + json_message_parser_feed(&cur_mon->qmp.parser, (const char *) buf, size); cur_mon = old_mon; } @@ -5114,15 +5114,15 @@ static void monitor_qmp_event(void *opaque, int event) switch (event) { case CHR_EVENT_OPENED: - mon->mc->command_mode = 0; + mon->qmp.command_mode = 0; data = get_qmp_greeting(); monitor_json_emitter(mon, data); qobject_decref(data); mon_refcount++; break; case CHR_EVENT_CLOSED: - json_message_parser_destroy(&mon->mc->parser); - json_message_parser_init(&mon->mc->parser, handle_qmp_command); + json_message_parser_destroy(&mon->qmp.parser); + json_message_parser_init(&mon->qmp.parser, handle_qmp_command); mon_refcount--; monitor_fdsets_cleanup(); break; @@ -5255,13 +5255,10 @@ void monitor_init(CharDriverState *chr, int flags) } if (monitor_ctrl_mode(mon)) { - mon->mc = g_malloc0(sizeof(MonitorControl)); - /* Control mode requires special handlers */ qemu_chr_add_handlers(chr, monitor_can_read, monitor_qmp_read, monitor_qmp_event, mon); qemu_chr_fe_set_echo(chr, true); - - json_message_parser_init(&mon->mc->parser, handle_qmp_command); + json_message_parser_init(&mon->qmp.parser, handle_qmp_command); } else { qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, monitor_event, mon); -- cgit v1.2.3-55-g7522 From 6a50636f35ba677c747f2f6127b0dba994b039ca Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 6 Mar 2015 19:49:41 +0100 Subject: monitor: Drop do_qmp_capabilities()'s superfluous QMP check Superfluous since commit 30f5041 removed it from HMP. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index f20e918fe4..daba98f372 100644 --- a/monitor.c +++ b/monitor.c @@ -566,11 +566,7 @@ static void monitor_qapi_event_init(void) static int do_qmp_capabilities(Monitor *mon, const QDict *params, QObject **ret_data) { - /* Will setup QMP capabilities in the future */ - if (monitor_ctrl_mode(mon)) { - mon->qmp.command_mode = 1; - } - + mon->qmp.command_mode = 1; return 0; } -- cgit v1.2.3-55-g7522 From f994b2587f081693b017ebd03b362d162d3108b3 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 6 Mar 2015 19:51:51 +0100 Subject: monitor: Turn int command_mode into bool in_command_mode While there, inline the pointless qmp_cmd_mode() wrapper. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index daba98f372..05502831f6 100644 --- a/monitor.c +++ b/monitor.c @@ -164,7 +164,12 @@ struct MonFdset { typedef struct { QObject *id; JSONMessageParser parser; - int command_mode; + /* + * When a client connects, we're in capabilities negotiation mode. + * When command qmp_capabilities succeeds, we go into command + * mode. + */ + bool in_command_mode; /* are we in command mode? */ } MonitorQMP; /* @@ -226,11 +231,6 @@ Monitor *default_mon; static void monitor_command_cb(void *opaque, const char *cmdline, void *readline_opaque); -static inline int qmp_cmd_mode(const Monitor *mon) -{ - return mon->qmp.command_mode; -} - /* Return true if in control mode, false otherwise */ static inline int monitor_ctrl_mode(const Monitor *mon) { @@ -446,7 +446,7 @@ static void monitor_qapi_event_emit(QAPIEvent event, QObject *data) trace_monitor_protocol_event_emit(event, data); QLIST_FOREACH(mon, &mon_list, entry) { - if (monitor_ctrl_mode(mon) && qmp_cmd_mode(mon)) { + if (monitor_ctrl_mode(mon) && mon->qmp.in_command_mode) { monitor_json_emitter(mon, data); } } @@ -566,7 +566,7 @@ static void monitor_qapi_event_init(void) static int do_qmp_capabilities(Monitor *mon, const QDict *params, QObject **ret_data) { - mon->qmp.command_mode = 1; + mon->qmp.in_command_mode = true; return 0; } @@ -4702,13 +4702,14 @@ static bool invalid_qmp_mode(const Monitor *mon, const mon_cmd_t *cmd, Error **errp) { bool is_cap = cmd->mhandler.cmd_new == do_qmp_capabilities; - if (is_cap && qmp_cmd_mode(mon)) { + + if (is_cap && mon->qmp.in_command_mode) { error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, "Capabilities negotiation is already complete, command " "'%s' ignored", cmd->name); return true; } - if (!is_cap && !qmp_cmd_mode(mon)) { + if (!is_cap && !mon->qmp.in_command_mode) { error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, "Expecting capabilities negotiation with " "'qmp_capabilities' before command '%s'", cmd->name); @@ -5110,7 +5111,7 @@ static void monitor_qmp_event(void *opaque, int event) switch (event) { case CHR_EVENT_OPENED: - mon->qmp.command_mode = 0; + mon->qmp.in_command_mode = false; data = get_qmp_greeting(); monitor_json_emitter(mon, data); qobject_decref(data); -- cgit v1.2.3-55-g7522 From 9f3982f2dcd96753d57d0ac64bd1ae3b37a90eb3 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 6 Mar 2015 19:56:38 +0100 Subject: monitor: Rename monitor_ctrl_mode() to monitor_is_qmp() ... and change return type to bool. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- monitor.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index 05502831f6..be18ac1e44 100644 --- a/monitor.c +++ b/monitor.c @@ -231,8 +231,10 @@ Monitor *default_mon; static void monitor_command_cb(void *opaque, const char *cmdline, void *readline_opaque); -/* Return true if in control mode, false otherwise */ -static inline int monitor_ctrl_mode(const Monitor *mon) +/** + * Is @mon a QMP monitor? + */ +static inline bool monitor_is_qmp(const Monitor *mon) { return (mon->flags & MONITOR_USE_CONTROL); } @@ -240,7 +242,7 @@ static inline int monitor_ctrl_mode(const Monitor *mon) /* Return non-zero iff we have a current monitor, and it is in QMP mode. */ int monitor_cur_is_qmp(void) { - return cur_mon && monitor_ctrl_mode(cur_mon); + return cur_mon && monitor_is_qmp(cur_mon); } void monitor_read_command(Monitor *mon, int show_prompt) @@ -350,7 +352,7 @@ void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) if (!mon) return; - if (monitor_ctrl_mode(mon)) { + if (monitor_is_qmp(mon)) { return; } @@ -446,7 +448,7 @@ static void monitor_qapi_event_emit(QAPIEvent event, QObject *data) trace_monitor_protocol_event_emit(event, data); QLIST_FOREACH(mon, &mon_list, entry) { - if (monitor_ctrl_mode(mon) && mon->qmp.in_command_mode) { + if (monitor_is_qmp(mon) && mon->qmp.in_command_mode) { monitor_json_emitter(mon, data); } } @@ -5251,7 +5253,7 @@ void monitor_init(CharDriverState *chr, int flags) monitor_read_command(mon, 0); } - if (monitor_ctrl_mode(mon)) { + if (monitor_is_qmp(mon)) { qemu_chr_add_handlers(chr, monitor_can_read, monitor_qmp_read, monitor_qmp_event, mon); qemu_chr_fe_set_echo(chr, true); -- cgit v1.2.3-55-g7522 From 489653b5db17679fd61b740dd289c798bb25d7b9 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 6 Mar 2015 20:01:05 +0100 Subject: monitor: Change return type of monitor_cur_is_qmp() to bool Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Luiz Capitulino --- include/monitor/monitor.h | 2 +- monitor.c | 6 ++++-- stubs/mon-is-qmp.c | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'monitor.c') diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index d409b6ac56..57f8394a94 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -16,7 +16,7 @@ extern Monitor *default_mon; #define MONITOR_USE_CONTROL 0x04 #define MONITOR_USE_PRETTY 0x08 -int monitor_cur_is_qmp(void); +bool monitor_cur_is_qmp(void); void monitor_init(CharDriverState *chr, int flags); diff --git a/monitor.c b/monitor.c index be18ac1e44..c7baa9198c 100644 --- a/monitor.c +++ b/monitor.c @@ -239,8 +239,10 @@ static inline bool monitor_is_qmp(const Monitor *mon) return (mon->flags & MONITOR_USE_CONTROL); } -/* Return non-zero iff we have a current monitor, and it is in QMP mode. */ -int monitor_cur_is_qmp(void) +/** + * Is the current monitor, if any, a QMP monitor? + */ +bool monitor_cur_is_qmp(void) { return cur_mon && monitor_is_qmp(cur_mon); } diff --git a/stubs/mon-is-qmp.c b/stubs/mon-is-qmp.c index 1f0a8fd98a..1ef136ab1d 100644 --- a/stubs/mon-is-qmp.c +++ b/stubs/mon-is-qmp.c @@ -1,7 +1,7 @@ #include "qemu-common.h" #include "monitor/monitor.h" -int monitor_cur_is_qmp(void) +bool monitor_cur_is_qmp(void) { - return 0; + return false; } -- cgit v1.2.3-55-g7522