From 694a099a542563f40116743c963066ce142a7755 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 19 Oct 2011 14:51:14 -0200 Subject: qapi-commands.py: Don't call the output marshal on error Today we generate something like this: int qmp_marshal_input_query_foo(...) ... retval = qmp_query_foo(errp); qmp_marshal_output_query_foo(retval, ret, errp); ... However, if qmp_query_foo() fails 'retval' will probably be NULL, which can cause a segfault as not all visitors check if 'retval' is valid. This commit fixes that by changing the code generator to only call the output marshal if qmp_query_foo() succeeds, like this: retval = qmp_query_foo(errp); if (!error_is_set(errp)) { qmp_marshal_output_query_foo(retval, ret, errp); } Signed-off-by: Luiz Capitulino --- scripts/qapi-commands.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index c947ba4208..f7def16662 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -62,7 +62,9 @@ def gen_sync_call(name, args, ret_type, indent=0): name=c_var(name), args=arglist, retval=retval).rstrip() if ret_type: ret += "\n" + mcgen('''' -%(marshal_output_call)s +if (!error_is_set(errp)) { + %(marshal_output_call)s +} ''', marshal_output_call=gen_marshal_output_call(name, ret_type)).rstrip() pop_indent(indent) -- cgit v1.2.1 From e235cec3762d2aa20b548114ea7b172113690463 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 21 Sep 2011 15:29:55 -0300 Subject: qapi: Convert query-mice Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- hmp.c | 20 ++++++++++++++++++ hmp.h | 1 + input.c | 64 ++++++++++++++------------------------------------------ monitor.c | 11 +--------- qapi-schema.json | 30 ++++++++++++++++++++++++++ qmp-commands.hx | 6 ++++++ 6 files changed, 74 insertions(+), 58 deletions(-) diff --git a/hmp.c b/hmp.c index 34416fc3c7..9c6d8966bf 100644 --- a/hmp.c +++ b/hmp.c @@ -94,6 +94,26 @@ void hmp_info_chardev(Monitor *mon) qapi_free_ChardevInfoList(char_info); } +void hmp_info_mice(Monitor *mon) +{ + MouseInfoList *mice_list, *mouse; + + mice_list = qmp_query_mice(NULL); + if (!mice_list) { + monitor_printf(mon, "No mouse devices connected\n"); + return; + } + + for (mouse = mice_list; mouse; mouse = mouse->next) { + monitor_printf(mon, "%c Mouse #%" PRId64 ": %s%s\n", + mouse->value->current ? '*' : ' ', + mouse->value->index, mouse->value->name, + mouse->value->absolute ? " (absolute)" : ""); + } + + qapi_free_MouseInfoList(mice_list); +} + void hmp_quit(Monitor *mon, const QDict *qdict) { monitor_suspend(mon); diff --git a/hmp.h b/hmp.h index 92433cff97..4e6697da67 100644 --- a/hmp.h +++ b/hmp.h @@ -23,6 +23,7 @@ void hmp_info_kvm(Monitor *mon); void hmp_info_status(Monitor *mon); void hmp_info_uuid(Monitor *mon); void hmp_info_chardev(Monitor *mon); +void hmp_info_mice(Monitor *mon); void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); diff --git a/input.c b/input.c index e2f7c92a71..9ade63f648 100644 --- a/input.c +++ b/input.c @@ -26,7 +26,8 @@ #include "net.h" #include "monitor.h" #include "console.h" -#include "qjson.h" +#include "error.h" +#include "qmp-commands.h" static QEMUPutKBDEvent *qemu_put_kbd_event; static void *qemu_put_kbd_event_opaque; @@ -211,60 +212,27 @@ int kbd_mouse_has_absolute(void) return 0; } -static void info_mice_iter(QObject *data, void *opaque) -{ - QDict *mouse; - Monitor *mon = opaque; - - mouse = qobject_to_qdict(data); - monitor_printf(mon, "%c Mouse #%" PRId64 ": %s%s\n", - (qdict_get_bool(mouse, "current") ? '*' : ' '), - qdict_get_int(mouse, "index"), qdict_get_str(mouse, "name"), - qdict_get_bool(mouse, "absolute") ? " (absolute)" : ""); -} - -void do_info_mice_print(Monitor *mon, const QObject *data) -{ - QList *mice_list; - - mice_list = qobject_to_qlist(data); - if (qlist_empty(mice_list)) { - monitor_printf(mon, "No mouse devices connected\n"); - return; - } - - qlist_iter(mice_list, info_mice_iter, mon); -} - -void do_info_mice(Monitor *mon, QObject **ret_data) +MouseInfoList *qmp_query_mice(Error **errp) { + MouseInfoList *mice_list = NULL; QEMUPutMouseEntry *cursor; - QList *mice_list; - int current; - - mice_list = qlist_new(); + bool current = true; - if (QTAILQ_EMPTY(&mouse_handlers)) { - goto out; - } + QTAILQ_FOREACH(cursor, &mouse_handlers, node) { + MouseInfoList *info = g_malloc0(sizeof(*info)); + info->value = g_malloc0(sizeof(*info->value)); + info->value->name = g_strdup(cursor->qemu_put_mouse_event_name); + info->value->index = cursor->index; + info->value->absolute = !!cursor->qemu_put_mouse_event_absolute; + info->value->current = current; - current = QTAILQ_FIRST(&mouse_handlers)->index; + current = false; - QTAILQ_FOREACH(cursor, &mouse_handlers, node) { - QObject *obj; - obj = qobject_from_jsonf("{ 'name': %s," - " 'index': %d," - " 'current': %i," - " 'absolute': %i }", - cursor->qemu_put_mouse_event_name, - cursor->index, - cursor->index == current, - !!cursor->qemu_put_mouse_event_absolute); - qlist_append_obj(mice_list, obj); + info->next = mice_list; + mice_list = info; } -out: - *ret_data = QOBJECT(mice_list); + return mice_list; } void do_mouse_set(Monitor *mon, const QDict *qdict) diff --git a/monitor.c b/monitor.c index ffda0feb84..d95abce223 100644 --- a/monitor.c +++ b/monitor.c @@ -2942,8 +2942,7 @@ static const mon_cmd_t info_cmds[] = { .args_type = "", .params = "", .help = "show which guest mouse is receiving events", - .user_print = do_info_mice_print, - .mhandler.info_new = do_info_mice, + .mhandler.info = hmp_info_mice, }, { .name = "vnc", @@ -3092,14 +3091,6 @@ static const mon_cmd_t qmp_query_cmds[] = { .user_print = do_pci_info_print, .mhandler.info_new = do_pci_info, }, - { - .name = "mice", - .args_type = "", - .params = "", - .help = "show which guest mouse is receiving events", - .user_print = do_info_mice_print, - .mhandler.info_new = do_info_mice, - }, { .name = "vnc", .args_type = "", diff --git a/qapi-schema.json b/qapi-schema.json index 5922c4a920..3175c82135 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -225,6 +225,36 @@ ## { 'command': 'query-commands', 'returns': ['CommandInfo'] } +## +# @MouseInfo: +# +# Information about a mouse device. +# +# @name: the name of the mouse device +# +# @index: the index of the mouse device +# +# @current: true if this device is currently receiving mouse events +# +# @absolute: true if this device supports absolute coordinates as input +# +# Since: 0.14.0 +## +{ 'type': 'MouseInfo', + 'data': {'name': 'str', 'index': 'int', 'current': 'bool', + 'absolute': 'bool'} } + +## +# @query-mice: +# +# Returns information about each active mouse device +# +# Returns: a list of @MouseInfo for each device +# +# Since: 0.14.0 +## +{ 'command': 'query-mice', 'returns': ['MouseInfo'] } + ## # @quit: # diff --git a/qmp-commands.hx b/qmp-commands.hx index 4328e8b86c..c5355601cc 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1663,6 +1663,12 @@ Example: EQMP + { + .name = "query-mice", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_mice, + }, + SQMP query-vnc --------- -- cgit v1.2.1 From 791e7c820e969a69aa2568fb528dbe9f7e923f5a Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 13 Sep 2011 17:37:16 -0300 Subject: qapi: Convert query-migrate Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- hmp.c | 31 +++++++++++++++++++++ hmp.h | 1 + migration.c | 82 ++++++++++++++++---------------------------------------- monitor.c | 11 +------- qapi-schema.json | 50 ++++++++++++++++++++++++++++++++++ qmp-commands.hx | 6 +++++ 6 files changed, 112 insertions(+), 69 deletions(-) diff --git a/hmp.c b/hmp.c index 9c6d8966bf..619b8ba70e 100644 --- a/hmp.c +++ b/hmp.c @@ -114,6 +114,37 @@ void hmp_info_mice(Monitor *mon) qapi_free_MouseInfoList(mice_list); } +void hmp_info_migrate(Monitor *mon) +{ + MigrationInfo *info; + + info = qmp_query_migrate(NULL); + + if (info->has_status) { + monitor_printf(mon, "Migration status: %s\n", info->status); + } + + if (info->has_ram) { + monitor_printf(mon, "transferred ram: %" PRIu64 " kbytes\n", + info->ram->transferred >> 10); + monitor_printf(mon, "remaining ram: %" PRIu64 " kbytes\n", + info->ram->remaining >> 10); + monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n", + info->ram->total >> 10); + } + + if (info->has_disk) { + monitor_printf(mon, "transferred disk: %" PRIu64 " kbytes\n", + info->disk->transferred >> 10); + monitor_printf(mon, "remaining disk: %" PRIu64 " kbytes\n", + info->disk->remaining >> 10); + monitor_printf(mon, "total disk: %" PRIu64 " kbytes\n", + info->disk->total >> 10); + } + + qapi_free_MigrationInfo(info); +} + void hmp_quit(Monitor *mon, const QDict *qdict) { monitor_suspend(mon); diff --git a/hmp.h b/hmp.h index 4e6697da67..49d9662626 100644 --- a/hmp.h +++ b/hmp.h @@ -24,6 +24,7 @@ void hmp_info_status(Monitor *mon); void hmp_info_uuid(Monitor *mon); void hmp_info_chardev(Monitor *mon); void hmp_info_mice(Monitor *mon); +void hmp_info_migrate(Monitor *mon); void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); diff --git a/migration.c b/migration.c index bdca72e008..6c70f72ce3 100644 --- a/migration.c +++ b/migration.c @@ -19,7 +19,7 @@ #include "block.h" #include "qemu_socket.h" #include "block-migration.h" -#include "qemu-objects.h" +#include "qmp-commands.h" //#define DEBUG_MIGRATION @@ -107,53 +107,9 @@ uint64_t migrate_max_downtime(void) return max_downtime; } -static void migrate_print_status(Monitor *mon, const char *name, - const QDict *status_dict) +MigrationInfo *qmp_query_migrate(Error **errp) { - QDict *qdict; - - qdict = qobject_to_qdict(qdict_get(status_dict, name)); - - monitor_printf(mon, "transferred %s: %" PRIu64 " kbytes\n", name, - qdict_get_int(qdict, "transferred") >> 10); - monitor_printf(mon, "remaining %s: %" PRIu64 " kbytes\n", name, - qdict_get_int(qdict, "remaining") >> 10); - monitor_printf(mon, "total %s: %" PRIu64 " kbytes\n", name, - qdict_get_int(qdict, "total") >> 10); -} - -void do_info_migrate_print(Monitor *mon, const QObject *data) -{ - QDict *qdict; - - qdict = qobject_to_qdict(data); - - monitor_printf(mon, "Migration status: %s\n", - qdict_get_str(qdict, "status")); - - if (qdict_haskey(qdict, "ram")) { - migrate_print_status(mon, "ram", qdict); - } - - if (qdict_haskey(qdict, "disk")) { - migrate_print_status(mon, "disk", qdict); - } -} - -static void migrate_put_status(QDict *qdict, const char *name, - uint64_t trans, uint64_t rem, uint64_t total) -{ - QObject *obj; - - obj = qobject_from_jsonf("{ 'transferred': %" PRId64 ", " - "'remaining': %" PRId64 ", " - "'total': %" PRId64 " }", trans, rem, total); - qdict_put_obj(qdict, name, obj); -} - -void do_info_migrate(Monitor *mon, QObject **ret_data) -{ - QDict *qdict; + MigrationInfo *info = g_malloc0(sizeof(*info)); MigrationState *s = migrate_get_current(); switch (s->state) { @@ -161,30 +117,38 @@ void do_info_migrate(Monitor *mon, QObject **ret_data) /* no migration has happened ever */ break; case MIG_STATE_ACTIVE: - qdict = qdict_new(); - qdict_put(qdict, "status", qstring_from_str("active")); + info->has_status = true; + info->status = g_strdup("active"); - migrate_put_status(qdict, "ram", ram_bytes_transferred(), - ram_bytes_remaining(), ram_bytes_total()); + info->has_ram = true; + info->ram = g_malloc0(sizeof(*info->ram)); + info->ram->transferred = ram_bytes_transferred(); + info->ram->remaining = ram_bytes_remaining(); + info->ram->total = ram_bytes_total(); if (blk_mig_active()) { - migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(), - blk_mig_bytes_remaining(), - blk_mig_bytes_total()); + info->has_disk = true; + info->disk = g_malloc0(sizeof(*info->disk)); + info->disk->transferred = blk_mig_bytes_transferred(); + info->disk->remaining = blk_mig_bytes_remaining(); + info->disk->total = blk_mig_bytes_total(); } - - *ret_data = QOBJECT(qdict); break; case MIG_STATE_COMPLETED: - *ret_data = qobject_from_jsonf("{ 'status': 'completed' }"); + info->has_status = true; + info->status = g_strdup("completed"); break; case MIG_STATE_ERROR: - *ret_data = qobject_from_jsonf("{ 'status': 'failed' }"); + info->has_status = true; + info->status = g_strdup("failed"); break; case MIG_STATE_CANCELLED: - *ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }"); + info->has_status = true; + info->status = g_strdup("cancelled"); break; } + + return info; } /* shared migration helpers */ diff --git a/monitor.c b/monitor.c index d95abce223..ea5ccd8f3d 100644 --- a/monitor.c +++ b/monitor.c @@ -2999,8 +2999,7 @@ static const mon_cmd_t info_cmds[] = { .args_type = "", .params = "", .help = "show migration status", - .user_print = do_info_migrate_print, - .mhandler.info_new = do_info_migrate, + .mhandler.info = hmp_info_migrate, }, { .name = "balloon", @@ -3109,14 +3108,6 @@ static const mon_cmd_t qmp_query_cmds[] = { .mhandler.info_new = do_info_spice, }, #endif - { - .name = "migrate", - .args_type = "", - .params = "", - .help = "show migration status", - .user_print = do_info_migrate_print, - .mhandler.info_new = do_info_migrate, - }, { .name = "balloon", .args_type = "", diff --git a/qapi-schema.json b/qapi-schema.json index 3175c82135..eb155b4d54 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -225,6 +225,56 @@ ## { 'command': 'query-commands', 'returns': ['CommandInfo'] } +## +# @MigrationStats +# +# Detailed migration status. +# +# @transferred: amount of bytes already transferred to the target VM +# +# @remaining: amount of bytes remaining to be transferred to the target VM +# +# @total: total amount of bytes involved in the migration process +# +# Since: 0.14.0. +## +{ 'type': 'MigrationStats', + 'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' } } + +## +# @MigrationInfo +# +# Information about current migration process. +# +# @status: #optional string describing the current migration status. +# As of 0.14.0 this can be 'active', 'completed', 'failed' or +# 'cancelled'. If this field is not returned, no migration process +# has been initiated +# +# @ram: #optional @MigrationStats containing detailed migration status, +# only returned if status is 'active' +# +# @disk: #optional @MigrationStats containing detailed disk migration +# status, only returned if status is 'active' and it is a block +# migration +# +# Since: 0.14.0 +## +{ 'type': 'MigrationInfo', + 'data': {'*status': 'str', '*ram': 'MigrationStats', + '*disk': 'MigrationStats'} } + +## +# @query-migrate +# +# Returns information about current migration process. +# +# Returns: @MigrationInfo +# +# Since: 0.14.0 +## +{ 'command': 'query-migrate', 'returns': 'MigrationInfo' } + ## # @MouseInfo: # diff --git a/qmp-commands.hx b/qmp-commands.hx index c5355601cc..8efdb25d0a 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1919,6 +1919,12 @@ Examples: EQMP + { + .name = "query-migrate", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_migrate, + }, + SQMP query-balloon ------------- -- cgit v1.2.1 From b025c8b4ab108a5a4bb4ef1e2500fc63214e2193 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 6 Oct 2011 14:02:57 -0300 Subject: Monitor: Make mon_set_cpu() public Also rename it to monitor_set_cpu(). Signed-off-by: Luiz Capitulino --- monitor.c | 11 +++++------ monitor.h | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/monitor.c b/monitor.c index ea5ccd8f3d..3f99ea0b90 100644 --- a/monitor.c +++ b/monitor.c @@ -514,7 +514,6 @@ static int do_qmp_capabilities(Monitor *mon, const QDict *params, return 0; } -static int mon_set_cpu(int cpu_index); static void handle_user_command(Monitor *mon, const char *cmdline); static int do_hmp_passthrough(Monitor *mon, const QDict *params, @@ -532,7 +531,7 @@ static int do_hmp_passthrough(Monitor *mon, const QDict *params, cur_mon = &hmp; if (qdict_haskey(params, "cpu-index")) { - ret = mon_set_cpu(qdict_get_int(params, "cpu-index")); + ret = monitor_set_cpu(qdict_get_int(params, "cpu-index")); if (ret < 0) { cur_mon = old_mon; qerror_report(QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number"); @@ -772,8 +771,8 @@ CommandInfoList *qmp_query_commands(Error **errp) return cmd_list; } -/* get the current CPU defined by the user */ -static int mon_set_cpu(int cpu_index) +/* set the current CPU defined by the user */ +int monitor_set_cpu(int cpu_index) { CPUState *env; @@ -789,7 +788,7 @@ static int mon_set_cpu(int cpu_index) static CPUState *mon_get_cpu(void) { if (!cur_mon->mon_cpu) { - mon_set_cpu(0); + monitor_set_cpu(0); } cpu_synchronize_state(cur_mon->mon_cpu); return cur_mon->mon_cpu; @@ -901,7 +900,7 @@ static void do_info_cpus(Monitor *mon, QObject **ret_data) static int do_cpu_set(Monitor *mon, const QDict *qdict, QObject **ret_data) { int index = qdict_get_int(qdict, "index"); - if (mon_set_cpu(index) < 0) { + if (monitor_set_cpu(index) < 0) { qerror_report(QERR_INVALID_PARAMETER_VALUE, "index", "a CPU number"); return -1; diff --git a/monitor.h b/monitor.h index 4f2d328db5..9b723b2ddd 100644 --- a/monitor.h +++ b/monitor.h @@ -57,6 +57,7 @@ void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) void monitor_printf(Monitor *mon, const char *fmt, ...) GCC_FMT_ATTR(2, 3); void monitor_print_filename(Monitor *mon, const char *filename); void monitor_flush(Monitor *mon); +int monitor_set_cpu(int cpu_index); typedef void (MonitorCompletion)(void *opaque, QObject *ret_data); -- cgit v1.2.1 From 99b7796f601cd275b16b3e7122874953ed1a0b1f Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Mon, 24 Oct 2011 10:53:44 -0200 Subject: Monitor: Introduce monitor_get_cpu_index() Returns 'cur_mons's CPU index. A future commit will use it. Signed-off-by: Luiz Capitulino --- monitor.c | 5 +++++ monitor.h | 1 + 2 files changed, 6 insertions(+) diff --git a/monitor.c b/monitor.c index 3f99ea0b90..3e1cd33942 100644 --- a/monitor.c +++ b/monitor.c @@ -794,6 +794,11 @@ static CPUState *mon_get_cpu(void) return cur_mon->mon_cpu; } +int monitor_get_cpu_index(void) +{ + return mon_get_cpu()->cpu_index; +} + static void do_info_registers(Monitor *mon) { CPUState *env; diff --git a/monitor.h b/monitor.h index 9b723b2ddd..e76795f1f3 100644 --- a/monitor.h +++ b/monitor.h @@ -58,6 +58,7 @@ void monitor_printf(Monitor *mon, const char *fmt, ...) GCC_FMT_ATTR(2, 3); void monitor_print_filename(Monitor *mon, const char *filename); void monitor_flush(Monitor *mon); int monitor_set_cpu(int cpu_index); +int monitor_get_cpu_index(void); typedef void (MonitorCompletion)(void *opaque, QObject *ret_data); -- cgit v1.2.1 From 755f196898e75bf453957609d1dbe02f73e5b12a Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 6 Oct 2011 14:31:39 -0300 Subject: qapi: Convert the cpu command Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- hmp-commands.hx | 3 +-- hmp.c | 12 ++++++++++++ hmp.h | 1 + monitor.c | 11 ----------- qapi-schema.json | 11 +++++++++++ qmp-commands.hx | 5 +---- qmp.c | 5 +++++ 7 files changed, 31 insertions(+), 17 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index ab08d583df..969ccf5edd 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -587,8 +587,7 @@ ETEXI .args_type = "index:i", .params = "index", .help = "set the default CPU", - .user_print = monitor_user_noop, - .mhandler.cmd_new = do_cpu_set, + .mhandler.cmd = hmp_cpu, }, STEXI diff --git a/hmp.c b/hmp.c index 619b8ba70e..35b0ca0bea 100644 --- a/hmp.c +++ b/hmp.c @@ -165,3 +165,15 @@ void hmp_system_powerdown(Monitor *mon, const QDict *qdict) { qmp_system_powerdown(NULL); } + +void hmp_cpu(Monitor *mon, const QDict *qdict) +{ + int64_t cpu_index; + + /* XXX: drop the monitor_set_cpu() usage when all HMP commands that + use it are converted to the QAPI */ + cpu_index = qdict_get_int(qdict, "index"); + if (monitor_set_cpu(cpu_index) < 0) { + monitor_printf(mon, "invalid CPU index\n"); + } +} diff --git a/hmp.h b/hmp.h index 49d9662626..9322b7f7f3 100644 --- a/hmp.h +++ b/hmp.h @@ -29,5 +29,6 @@ void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); void hmp_system_powerdown(Monitor *mon, const QDict *qdict); +void hmp_cpu(Monitor *mon, const QDict *qdict); #endif diff --git a/monitor.c b/monitor.c index 3e1cd33942..1edb646b95 100644 --- a/monitor.c +++ b/monitor.c @@ -902,17 +902,6 @@ static void do_info_cpus(Monitor *mon, QObject **ret_data) *ret_data = QOBJECT(cpu_list); } -static int do_cpu_set(Monitor *mon, const QDict *qdict, QObject **ret_data) -{ - int index = qdict_get_int(qdict, "index"); - if (monitor_set_cpu(index) < 0) { - qerror_report(QERR_INVALID_PARAMETER_VALUE, "index", - "a CPU number"); - return -1; - } - return 0; -} - static void do_info_jit(Monitor *mon) { dump_exec_info((FILE *)mon, monitor_fprintf); diff --git a/qapi-schema.json b/qapi-schema.json index eb155b4d54..e4cf6da4fb 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -351,3 +351,14 @@ # prompting the user in some way. ## { 'command': 'system_powerdown' } + +## +# @cpu: +# +# This command is a nop that is only provided for the purposes of compatibility. +# +# Since: 0.14.0 +# +# Notes: Do not use this command. +## +{ 'command': 'cpu', 'data': {'index': 'int'} } diff --git a/qmp-commands.hx b/qmp-commands.hx index 8efdb25d0a..dcca53cb5a 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -331,10 +331,7 @@ EQMP { .name = "cpu", .args_type = "index:i", - .params = "index", - .help = "set the default CPU", - .user_print = monitor_user_noop, - .mhandler.cmd_new = do_cpu_set, + .mhandler.cmd_new = qmp_marshal_input_cpu, }, SQMP diff --git a/qmp.c b/qmp.c index bf58b05a9a..e84922bff0 100644 --- a/qmp.c +++ b/qmp.c @@ -90,3 +90,8 @@ void qmp_system_powerdown(Error **erp) { qemu_system_powerdown_request(); } + +void qmp_cpu(int64_t index, Error **errp) +{ + /* Just do nothing */ +} -- cgit v1.2.1 From de0b36b67ea3e1ab3aa1b6625c4fd5cb29fa0ada Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 21 Sep 2011 16:38:35 -0300 Subject: qapi: Convert query-cpus Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- cpus.c | 45 +++++++++++++++++++++++++ hmp.c | 39 +++++++++++++++++++++ hmp.h | 1 + monitor.c | 101 +------------------------------------------------------ qapi-schema.json | 46 +++++++++++++++++++++++++ qmp-commands.hx | 6 ++++ 6 files changed, 138 insertions(+), 100 deletions(-) diff --git a/cpus.c b/cpus.c index 79a76560cb..f768683ad6 100644 --- a/cpus.c +++ b/cpus.c @@ -30,6 +30,7 @@ #include "gdbstub.h" #include "dma.h" #include "kvm.h" +#include "qmp-commands.h" #include "qemu-thread.h" #include "cpus.h" @@ -1094,3 +1095,47 @@ void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg) cpu_list(f, cpu_fprintf); /* deprecated */ #endif } + +CpuInfoList *qmp_query_cpus(Error **errp) +{ + CpuInfoList *head = NULL, *cur_item = NULL; + CPUState *env; + + for(env = first_cpu; env != NULL; env = env->next_cpu) { + CpuInfoList *info; + + cpu_synchronize_state(env); + + info = g_malloc0(sizeof(*info)); + info->value = g_malloc0(sizeof(*info->value)); + info->value->CPU = env->cpu_index; + info->value->current = (env == first_cpu); + info->value->halted = env->halted; + info->value->thread_id = env->thread_id; +#if defined(TARGET_I386) + info->value->has_pc = true; + info->value->pc = env->eip + env->segs[R_CS].base; +#elif defined(TARGET_PPC) + info->value->has_nip = true; + info->value->nip = env->nip; +#elif defined(TARGET_SPARC) + info->value->has_pc = true; + info->value->pc = env->pc; + info->value->has_npc = true; + info->value->npc = env->npc; +#elif defined(TARGET_MIPS) + info->value->has_PC = true; + info->value->PC = env->active_tc.PC; +#endif + + /* XXX: waiting for the qapi to support GSList */ + if (!cur_item) { + head = cur_item = info; + } else { + cur_item->next = info; + cur_item = info; + } + } + + return head; +} diff --git a/hmp.c b/hmp.c index 35b0ca0bea..172fe9cc4b 100644 --- a/hmp.c +++ b/hmp.c @@ -145,6 +145,45 @@ void hmp_info_migrate(Monitor *mon) qapi_free_MigrationInfo(info); } +void hmp_info_cpus(Monitor *mon) +{ + CpuInfoList *cpu_list, *cpu; + + cpu_list = qmp_query_cpus(NULL); + + for (cpu = cpu_list; cpu; cpu = cpu->next) { + int active = ' '; + + if (cpu->value->CPU == monitor_get_cpu_index()) { + active = '*'; + } + + monitor_printf(mon, "%c CPU #%" PRId64 ": ", active, cpu->value->CPU); + + if (cpu->value->has_pc) { + monitor_printf(mon, "pc=0x%016" PRIx64, cpu->value->pc); + } + if (cpu->value->has_nip) { + monitor_printf(mon, "nip=0x%016" PRIx64, cpu->value->nip); + } + if (cpu->value->has_npc) { + monitor_printf(mon, "pc=0x%016" PRIx64, cpu->value->pc); + monitor_printf(mon, "npc=0x%016" PRIx64, cpu->value->npc); + } + if (cpu->value->has_PC) { + monitor_printf(mon, "PC=0x%016" PRIx64, cpu->value->PC); + } + + if (cpu->value->halted) { + monitor_printf(mon, " (halted)"); + } + + monitor_printf(mon, " thread_id=%" PRId64 "\n", cpu->value->thread_id); + } + + qapi_free_CpuInfoList(cpu_list); +} + void hmp_quit(Monitor *mon, const QDict *qdict) { monitor_suspend(mon); diff --git a/hmp.h b/hmp.h index 9322b7f7f3..d9a83eb160 100644 --- a/hmp.h +++ b/hmp.h @@ -25,6 +25,7 @@ void hmp_info_uuid(Monitor *mon); void hmp_info_chardev(Monitor *mon); void hmp_info_mice(Monitor *mon); void hmp_info_migrate(Monitor *mon); +void hmp_info_cpus(Monitor *mon); void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); diff --git a/monitor.c b/monitor.c index 1edb646b95..2f49c74793 100644 --- a/monitor.c +++ b/monitor.c @@ -812,96 +812,6 @@ static void do_info_registers(Monitor *mon) #endif } -static void print_cpu_iter(QObject *obj, void *opaque) -{ - QDict *cpu; - int active = ' '; - Monitor *mon = opaque; - - assert(qobject_type(obj) == QTYPE_QDICT); - cpu = qobject_to_qdict(obj); - - if (qdict_get_bool(cpu, "current")) { - active = '*'; - } - - monitor_printf(mon, "%c CPU #%d: ", active, (int)qdict_get_int(cpu, "CPU")); - -#if defined(TARGET_I386) - monitor_printf(mon, "pc=0x" TARGET_FMT_lx, - (target_ulong) qdict_get_int(cpu, "pc")); -#elif defined(TARGET_PPC) - monitor_printf(mon, "nip=0x" TARGET_FMT_lx, - (target_long) qdict_get_int(cpu, "nip")); -#elif defined(TARGET_SPARC) - monitor_printf(mon, "pc=0x" TARGET_FMT_lx, - (target_long) qdict_get_int(cpu, "pc")); - monitor_printf(mon, "npc=0x" TARGET_FMT_lx, - (target_long) qdict_get_int(cpu, "npc")); -#elif defined(TARGET_MIPS) - monitor_printf(mon, "PC=0x" TARGET_FMT_lx, - (target_long) qdict_get_int(cpu, "PC")); -#endif - - if (qdict_get_bool(cpu, "halted")) { - monitor_printf(mon, " (halted)"); - } - - monitor_printf(mon, " thread_id=%" PRId64 " ", - qdict_get_int(cpu, "thread_id")); - - monitor_printf(mon, "\n"); -} - -static void monitor_print_cpus(Monitor *mon, const QObject *data) -{ - QList *cpu_list; - - assert(qobject_type(data) == QTYPE_QLIST); - cpu_list = qobject_to_qlist(data); - qlist_iter(cpu_list, print_cpu_iter, mon); -} - -static void do_info_cpus(Monitor *mon, QObject **ret_data) -{ - CPUState *env; - QList *cpu_list; - - cpu_list = qlist_new(); - - /* just to set the default cpu if not already done */ - mon_get_cpu(); - - for(env = first_cpu; env != NULL; env = env->next_cpu) { - QDict *cpu; - QObject *obj; - - cpu_synchronize_state(env); - - obj = qobject_from_jsonf("{ 'CPU': %d, 'current': %i, 'halted': %i }", - env->cpu_index, env == mon->mon_cpu, - env->halted); - - cpu = qobject_to_qdict(obj); - -#if defined(TARGET_I386) - qdict_put(cpu, "pc", qint_from_int(env->eip + env->segs[R_CS].base)); -#elif defined(TARGET_PPC) - qdict_put(cpu, "nip", qint_from_int(env->nip)); -#elif defined(TARGET_SPARC) - qdict_put(cpu, "pc", qint_from_int(env->pc)); - qdict_put(cpu, "npc", qint_from_int(env->npc)); -#elif defined(TARGET_MIPS) - qdict_put(cpu, "PC", qint_from_int(env->active_tc.PC)); -#endif - qdict_put(cpu, "thread_id", qint_from_int(env->thread_id)); - - qlist_append(cpu_list, cpu); - } - - *ret_data = QOBJECT(cpu_list); -} - static void do_info_jit(Monitor *mon) { dump_exec_info((FILE *)mon, monitor_fprintf); @@ -2787,8 +2697,7 @@ static const mon_cmd_t info_cmds[] = { .args_type = "", .params = "", .help = "show infos for each CPU", - .user_print = monitor_print_cpus, - .mhandler.info_new = do_info_cpus, + .mhandler.info = hmp_info_cpus, }, { .name = "history", @@ -3067,14 +2976,6 @@ static const mon_cmd_t qmp_query_cmds[] = { .user_print = bdrv_stats_print, .mhandler.info_new = bdrv_info_stats, }, - { - .name = "cpus", - .args_type = "", - .params = "", - .help = "show infos for each CPU", - .user_print = monitor_print_cpus, - .mhandler.info_new = do_info_cpus, - }, { .name = "pci", .args_type = "", diff --git a/qapi-schema.json b/qapi-schema.json index e4cf6da4fb..a1bf90deea 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -305,6 +305,52 @@ ## { 'command': 'query-mice', 'returns': ['MouseInfo'] } +## +# @CpuInfo: +# +# Information about a virtual CPU +# +# @CPU: the index of the virtual CPU +# +# @current: this only exists for backwards compatible and should be ignored +# +# @halted: true if the virtual CPU is in the halt state. Halt usually refers +# to a processor specific low power mode. +# +# @pc: #optional If the target is i386 or x86_64, this is the 64-bit instruction +# pointer. +# If the target is Sparc, this is the PC component of the +# instruction pointer. +# +# @nip: #optional If the target is PPC, the instruction pointer +# +# @npc: #optional If the target is Sparc, the NPC component of the instruction +# pointer +# +# @PC: #optional If the target is MIPS, the instruction pointer +# +# @thread_id: ID of the underlying host thread +# +# Since: 0.14.0 +# +# Notes: @halted is a transient state that changes frequently. By the time the +# data is sent to the client, the guest may no longer be halted. +## +{ 'type': 'CpuInfo', + 'data': {'CPU': 'int', 'current': 'bool', 'halted': 'bool', '*pc': 'int', + '*nip': 'int', '*npc': 'int', '*PC': 'int', 'thread_id': 'int'} } + +## +# @query-cpus: +# +# Returns a list of information about each virtual CPU. +# +# Returns: a list of @CpuInfo for each virtual CPU +# +# Since: 0.14.0 +## +{ 'command': 'query-cpus', 'returns': ['CpuInfo'] } + ## # @quit: # diff --git a/qmp-commands.hx b/qmp-commands.hx index dcca53cb5a..434ce6cba6 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1347,6 +1347,12 @@ Example: EQMP + { + .name = "query-cpus", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_cpus, + }, + SQMP query-pci --------- -- cgit v1.2.1 From d6bf279e7a949ad49a48a215f9ec28cb6ceb28aa Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 14 Oct 2011 17:11:23 -0300 Subject: block: iostatus: Drop BDRV_IOS_INVAL A future commit will convert bdrv_info() to the QAPI and it won't provide IOS_INVAL. Luckily all we have to do is to add a new 'iostatus_enabled' member to BlockDriverState and use it instead. Signed-off-by: Luiz Capitulino --- block.c | 5 +++-- block.h | 3 +-- block_int.h | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/block.c b/block.c index 70aab63e4b..4dc2b85b86 100644 --- a/block.c +++ b/block.c @@ -3139,6 +3139,7 @@ int bdrv_in_use(BlockDriverState *bs) void bdrv_iostatus_enable(BlockDriverState *bs) { + bs->iostatus_enabled = true; bs->iostatus = BDRV_IOS_OK; } @@ -3146,7 +3147,7 @@ void bdrv_iostatus_enable(BlockDriverState *bs) * enables it _and_ the VM is configured to stop on errors */ bool bdrv_iostatus_is_enabled(const BlockDriverState *bs) { - return (bs->iostatus != BDRV_IOS_INVAL && + return (bs->iostatus_enabled && (bs->on_write_error == BLOCK_ERR_STOP_ENOSPC || bs->on_write_error == BLOCK_ERR_STOP_ANY || bs->on_read_error == BLOCK_ERR_STOP_ANY)); @@ -3154,7 +3155,7 @@ bool bdrv_iostatus_is_enabled(const BlockDriverState *bs) void bdrv_iostatus_disable(BlockDriverState *bs) { - bs->iostatus = BDRV_IOS_INVAL; + bs->iostatus_enabled = false; } void bdrv_iostatus_reset(BlockDriverState *bs) diff --git a/block.h b/block.h index 5a042c96e7..1823e93801 100644 --- a/block.h +++ b/block.h @@ -78,8 +78,7 @@ typedef enum { } BlockMonEventAction; typedef enum { - BDRV_IOS_INVAL, BDRV_IOS_OK, BDRV_IOS_FAILED, BDRV_IOS_ENOSPC, - BDRV_IOS_MAX + BDRV_IOS_OK, BDRV_IOS_FAILED, BDRV_IOS_ENOSPC, BDRV_IOS_MAX } BlockIOStatus; void bdrv_iostatus_enable(BlockDriverState *bs); diff --git a/block_int.h b/block_int.h index dac00f504f..3929ec90a5 100644 --- a/block_int.h +++ b/block_int.h @@ -202,6 +202,7 @@ struct BlockDriverState { drivers. They are not used by the block driver */ int cyls, heads, secs, translation; BlockErrorAction on_read_error, on_write_error; + bool iostatus_enabled; BlockIOStatus iostatus; char device_name[32]; unsigned long *dirty_bitmap; -- cgit v1.2.1 From 58e21ef5ab262fb91256435c31cc7bfeead59754 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 14 Oct 2011 17:22:24 -0300 Subject: block: Rename the BlockIOStatus enum values The biggest change is to rename its prefix from BDRV_IOS to BLOCK_DEVICE_IO_STATUS. Next commit will convert the query-block command to the QAPI and that's how the enumeration is going to be generated. Signed-off-by: Luiz Capitulino --- block.c | 18 ++++++++++-------- block.h | 3 ++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/block.c b/block.c index 4dc2b85b86..1a4625f64b 100644 --- a/block.c +++ b/block.c @@ -1870,10 +1870,10 @@ void bdrv_info_print(Monitor *mon, const QObject *data) qlist_iter(qobject_to_qlist(data), bdrv_print_dict, mon); } -static const char *const io_status_name[BDRV_IOS_MAX] = { - [BDRV_IOS_OK] = "ok", - [BDRV_IOS_FAILED] = "failed", - [BDRV_IOS_ENOSPC] = "nospace", +static const char *const io_status_name[BLOCK_DEVICE_IO_STATUS_MAX] = { + [BLOCK_DEVICE_IO_STATUS_OK] = "ok", + [BLOCK_DEVICE_IO_STATUS_FAILED] = "failed", + [BLOCK_DEVICE_IO_STATUS_NOSPACE] = "nospace", }; void bdrv_info(Monitor *mon, QObject **ret_data) @@ -3140,7 +3140,7 @@ int bdrv_in_use(BlockDriverState *bs) void bdrv_iostatus_enable(BlockDriverState *bs) { bs->iostatus_enabled = true; - bs->iostatus = BDRV_IOS_OK; + bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK; } /* The I/O status is only enabled if the drive explicitly @@ -3161,7 +3161,7 @@ void bdrv_iostatus_disable(BlockDriverState *bs) void bdrv_iostatus_reset(BlockDriverState *bs) { if (bdrv_iostatus_is_enabled(bs)) { - bs->iostatus = BDRV_IOS_OK; + bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK; } } @@ -3170,9 +3170,11 @@ void bdrv_iostatus_reset(BlockDriverState *bs) possible to implement this without device models being involved */ void bdrv_iostatus_set_err(BlockDriverState *bs, int error) { - if (bdrv_iostatus_is_enabled(bs) && bs->iostatus == BDRV_IOS_OK) { + if (bdrv_iostatus_is_enabled(bs) && + bs->iostatus == BLOCK_DEVICE_IO_STATUS_OK) { assert(error >= 0); - bs->iostatus = error == ENOSPC ? BDRV_IOS_ENOSPC : BDRV_IOS_FAILED; + bs->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE : + BLOCK_DEVICE_IO_STATUS_FAILED; } } diff --git a/block.h b/block.h index 1823e93801..c37b1bf1a6 100644 --- a/block.h +++ b/block.h @@ -78,7 +78,8 @@ typedef enum { } BlockMonEventAction; typedef enum { - BDRV_IOS_OK, BDRV_IOS_FAILED, BDRV_IOS_ENOSPC, BDRV_IOS_MAX + BLOCK_DEVICE_IO_STATUS_OK, BLOCK_DEVICE_IO_STATUS_FAILED, + BLOCK_DEVICE_IO_STATUS_NOSPACE, BLOCK_DEVICE_IO_STATUS_MAX } BlockIOStatus; void bdrv_iostatus_enable(BlockDriverState *bs); -- cgit v1.2.1 From b202381800d81fbff9978abbdea95760dd363bb6 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 21 Sep 2011 17:16:47 -0300 Subject: qapi: Convert query-block Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- block.c | 112 +++++++++++++++---------------------------------------- block.h | 5 --- block_int.h | 3 +- hmp.c | 42 +++++++++++++++++++++ hmp.h | 1 + monitor.c | 11 +----- qapi-schema.json | 85 +++++++++++++++++++++++++++++++++++++++++ qmp-commands.hx | 6 +++ 8 files changed, 167 insertions(+), 98 deletions(-) diff --git a/block.c b/block.c index 1a4625f64b..e648513fdd 100644 --- a/block.c +++ b/block.c @@ -29,6 +29,7 @@ #include "module.h" #include "qemu-objects.h" #include "qemu-coroutine.h" +#include "qmp-commands.h" #ifdef CONFIG_BSD #include @@ -1824,106 +1825,53 @@ void bdrv_mon_event(const BlockDriverState *bdrv, qobject_decref(data); } -static void bdrv_print_dict(QObject *obj, void *opaque) +BlockInfoList *qmp_query_block(Error **errp) { - QDict *bs_dict; - Monitor *mon = opaque; - - bs_dict = qobject_to_qdict(obj); - - monitor_printf(mon, "%s: removable=%d", - qdict_get_str(bs_dict, "device"), - qdict_get_bool(bs_dict, "removable")); - - if (qdict_get_bool(bs_dict, "removable")) { - monitor_printf(mon, " locked=%d", qdict_get_bool(bs_dict, "locked")); - monitor_printf(mon, " tray-open=%d", - qdict_get_bool(bs_dict, "tray-open")); - } - - if (qdict_haskey(bs_dict, "io-status")) { - monitor_printf(mon, " io-status=%s", qdict_get_str(bs_dict, "io-status")); - } - - if (qdict_haskey(bs_dict, "inserted")) { - QDict *qdict = qobject_to_qdict(qdict_get(bs_dict, "inserted")); - - monitor_printf(mon, " file="); - monitor_print_filename(mon, qdict_get_str(qdict, "file")); - if (qdict_haskey(qdict, "backing_file")) { - monitor_printf(mon, " backing_file="); - monitor_print_filename(mon, qdict_get_str(qdict, "backing_file")); - } - monitor_printf(mon, " ro=%d drv=%s encrypted=%d", - qdict_get_bool(qdict, "ro"), - qdict_get_str(qdict, "drv"), - qdict_get_bool(qdict, "encrypted")); - } else { - monitor_printf(mon, " [not inserted]"); - } - - monitor_printf(mon, "\n"); -} - -void bdrv_info_print(Monitor *mon, const QObject *data) -{ - qlist_iter(qobject_to_qlist(data), bdrv_print_dict, mon); -} - -static const char *const io_status_name[BLOCK_DEVICE_IO_STATUS_MAX] = { - [BLOCK_DEVICE_IO_STATUS_OK] = "ok", - [BLOCK_DEVICE_IO_STATUS_FAILED] = "failed", - [BLOCK_DEVICE_IO_STATUS_NOSPACE] = "nospace", -}; - -void bdrv_info(Monitor *mon, QObject **ret_data) -{ - QList *bs_list; + BlockInfoList *head = NULL, *cur_item = NULL; BlockDriverState *bs; - bs_list = qlist_new(); - QTAILQ_FOREACH(bs, &bdrv_states, list) { - QObject *bs_obj; - QDict *bs_dict; + BlockInfoList *info = g_malloc0(sizeof(*info)); - bs_obj = qobject_from_jsonf("{ 'device': %s, 'type': 'unknown', " - "'removable': %i, 'locked': %i }", - bs->device_name, - bdrv_dev_has_removable_media(bs), - bdrv_dev_is_medium_locked(bs)); - bs_dict = qobject_to_qdict(bs_obj); + info->value = g_malloc0(sizeof(*info->value)); + info->value->device = g_strdup(bs->device_name); + info->value->type = g_strdup("unknown"); + info->value->locked = bdrv_dev_is_medium_locked(bs); + info->value->removable = bdrv_dev_has_removable_media(bs); if (bdrv_dev_has_removable_media(bs)) { - qdict_put(bs_dict, "tray-open", - qbool_from_int(bdrv_dev_is_tray_open(bs))); + info->value->has_tray_open = true; + info->value->tray_open = bdrv_dev_is_tray_open(bs); } if (bdrv_iostatus_is_enabled(bs)) { - qdict_put(bs_dict, "io-status", - qstring_from_str(io_status_name[bs->iostatus])); + info->value->has_io_status = true; + info->value->io_status = bs->iostatus; } if (bs->drv) { - QObject *obj; - - obj = qobject_from_jsonf("{ 'file': %s, 'ro': %i, 'drv': %s, " - "'encrypted': %i }", - bs->filename, bs->read_only, - bs->drv->format_name, - bdrv_is_encrypted(bs)); - if (bs->backing_file[0] != '\0') { - QDict *qdict = qobject_to_qdict(obj); - qdict_put(qdict, "backing_file", - qstring_from_str(bs->backing_file)); + info->value->has_inserted = true; + info->value->inserted = g_malloc0(sizeof(*info->value->inserted)); + info->value->inserted->file = g_strdup(bs->filename); + info->value->inserted->ro = bs->read_only; + info->value->inserted->drv = g_strdup(bs->drv->format_name); + info->value->inserted->encrypted = bs->encrypted; + if (bs->backing_file[0]) { + info->value->inserted->has_backing_file = true; + info->value->inserted->backing_file = g_strdup(bs->backing_file); } + } - qdict_put_obj(bs_dict, "inserted", obj); + /* XXX: waiting for the qapi to support GSList */ + if (!cur_item) { + head = cur_item = info; + } else { + cur_item->next = info; + cur_item = info; } - qlist_append_obj(bs_list, bs_obj); } - *ret_data = QOBJECT(bs_list); + return head; } static void bdrv_stats_iter(QObject *data, void *opaque) diff --git a/block.h b/block.h index c37b1bf1a6..38cd748b60 100644 --- a/block.h +++ b/block.h @@ -77,11 +77,6 @@ typedef enum { BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP } BlockMonEventAction; -typedef enum { - BLOCK_DEVICE_IO_STATUS_OK, BLOCK_DEVICE_IO_STATUS_FAILED, - BLOCK_DEVICE_IO_STATUS_NOSPACE, BLOCK_DEVICE_IO_STATUS_MAX -} BlockIOStatus; - void bdrv_iostatus_enable(BlockDriverState *bs); void bdrv_iostatus_reset(BlockDriverState *bs); void bdrv_iostatus_disable(BlockDriverState *bs); diff --git a/block_int.h b/block_int.h index 3929ec90a5..f4547f6d93 100644 --- a/block_int.h +++ b/block_int.h @@ -29,6 +29,7 @@ #include "qemu-queue.h" #include "qemu-coroutine.h" #include "qemu-timer.h" +#include "qapi-types.h" #define BLOCK_FLAG_ENCRYPT 1 #define BLOCK_FLAG_COMPAT6 4 @@ -203,7 +204,7 @@ struct BlockDriverState { int cyls, heads, secs, translation; BlockErrorAction on_read_error, on_write_error; bool iostatus_enabled; - BlockIOStatus iostatus; + BlockDeviceIoStatus iostatus; char device_name[32]; unsigned long *dirty_bitmap; int64_t dirty_count; diff --git a/hmp.c b/hmp.c index 172fe9cc4b..5912250d04 100644 --- a/hmp.c +++ b/hmp.c @@ -184,6 +184,48 @@ void hmp_info_cpus(Monitor *mon) qapi_free_CpuInfoList(cpu_list); } +void hmp_info_block(Monitor *mon) +{ + BlockInfoList *block_list, *info; + + block_list = qmp_query_block(NULL); + + for (info = block_list; info; info = info->next) { + monitor_printf(mon, "%s: removable=%d", + info->value->device, info->value->removable); + + if (info->value->removable) { + monitor_printf(mon, " locked=%d", info->value->locked); + monitor_printf(mon, " tray-open=%d", info->value->tray_open); + } + + if (info->value->has_io_status) { + monitor_printf(mon, " io-status=%s", + BlockDeviceIoStatus_lookup[info->value->io_status]); + } + + if (info->value->has_inserted) { + monitor_printf(mon, " file="); + monitor_print_filename(mon, info->value->inserted->file); + + if (info->value->inserted->has_backing_file) { + monitor_printf(mon, " backing_file="); + monitor_print_filename(mon, info->value->inserted->backing_file); + } + monitor_printf(mon, " ro=%d drv=%s encrypted=%d", + info->value->inserted->ro, + info->value->inserted->drv, + info->value->inserted->encrypted); + } else { + monitor_printf(mon, " [not inserted]"); + } + + monitor_printf(mon, "\n"); + } + + qapi_free_BlockInfoList(block_list); +} + void hmp_quit(Monitor *mon, const QDict *qdict) { monitor_suspend(mon); diff --git a/hmp.h b/hmp.h index d9a83eb160..f5ec417156 100644 --- a/hmp.h +++ b/hmp.h @@ -26,6 +26,7 @@ void hmp_info_chardev(Monitor *mon); void hmp_info_mice(Monitor *mon); void hmp_info_migrate(Monitor *mon); void hmp_info_cpus(Monitor *mon); +void hmp_info_block(Monitor *mon); void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); diff --git a/monitor.c b/monitor.c index 2f49c74793..3e76f4c0b7 100644 --- a/monitor.c +++ b/monitor.c @@ -2674,8 +2674,7 @@ static const mon_cmd_t info_cmds[] = { .args_type = "", .params = "", .help = "show the block devices", - .user_print = bdrv_info_print, - .mhandler.info_new = bdrv_info, + .mhandler.info = hmp_info_block, }, { .name = "blockstats", @@ -2960,14 +2959,6 @@ static const mon_cmd_t qmp_cmds[] = { }; static const mon_cmd_t qmp_query_cmds[] = { - { - .name = "block", - .args_type = "", - .params = "", - .help = "show the block devices", - .user_print = bdrv_info_print, - .mhandler.info_new = bdrv_info, - }, { .name = "blockstats", .args_type = "", diff --git a/qapi-schema.json b/qapi-schema.json index a1bf90deea..5e3570e53d 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -351,6 +351,91 @@ ## { 'command': 'query-cpus', 'returns': ['CpuInfo'] } +## +# @BlockDeviceInfo: +# +# Information about the backing device for a block device. +# +# @file: the filename of the backing device +# +# @ro: true if the backing device was open read-only +# +# @drv: the name of the block format used to open the backing device. As of +# 0.14.0 this can be: 'blkdebug', 'bochs', 'cloop', 'cow', 'dmg', +# 'file', 'file', 'ftp', 'ftps', 'host_cdrom', 'host_device', +# 'host_floppy', 'http', 'https', 'nbd', 'parallels', 'qcow', +# 'qcow2', 'raw', 'tftp', 'vdi', 'vmdk', 'vpc', 'vvfat' +# +# @backing_file: #optional the name of the backing file (for copy-on-write) +# +# @encrypted: true if the backing device is encrypted +# +# Since: 0.14.0 +# +# Notes: This interface is only found in @BlockInfo. +## +{ 'type': 'BlockDeviceInfo', + 'data': { 'file': 'str', 'ro': 'bool', 'drv': 'str', + '*backing_file': 'str', 'encrypted': 'bool' } } + +## +# @BlockDeviceIoStatus: +# +# An enumeration of block device I/O status. +# +# @ok: The last I/O operation has succeeded +# +# @failed: The last I/O operation has failed +# +# @nospace: The last I/O operation has failed due to a no-space condition +# +# Since: 1.0 +## +{ 'enum': 'BlockDeviceIoStatus', 'data': [ 'ok', 'failed', 'nospace' ] } + +## +# @BlockInfo: +# +# Block device information. This structure describes a virtual device and +# the backing device associated with it. +# +# @device: The device name associated with the virtual device. +# +# @type: This field is returned only for compatibility reasons, it should +# not be used (always returns 'unknown') +# +# @removable: True if the device supports removable media. +# +# @locked: True if the guest has locked this device from having its media +# removed +# +# @tray_open: #optional True if the device has a tray and it is open +# (only present if removable is true) +# +# @io-status: #optional @BlockDeviceIoStatus. Only present if the device +# supports it and the VM is configured to stop on errors +# +# @inserted: #optional @BlockDeviceInfo describing the device if media is +# present +# +# Since: 0.14.0 +## +{ 'type': 'BlockInfo', + 'data': {'device': 'str', 'type': 'str', 'removable': 'bool', + 'locked': 'bool', '*inserted': 'BlockDeviceInfo', + '*tray_open': 'bool', '*io-status': 'BlockDeviceIoStatus'} } + +## +# @query-block: +# +# Get a list of BlockInfo for all virtual block devices. +# +# Returns: a list of @BlockInfo describing each virtual block device +# +# Since: 0.14.0 +## +{ 'command': 'query-block', 'returns': ['BlockInfo'] } + ## # @quit: # diff --git a/qmp-commands.hx b/qmp-commands.hx index 434ce6cba6..0cf0be7e0d 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1198,6 +1198,12 @@ Example: EQMP + { + .name = "query-block", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_block, + }, + SQMP query-blockstats ---------------- -- cgit v1.2.1 From f11f57e405a99732ed0f3294904c2dd258d77629 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 22 Sep 2011 15:56:36 -0300 Subject: qapi: Convert query-blockstats Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- block.c | 111 +++++++++++++++++++------------------------------------ hmp.c | 34 +++++++++++++++++ hmp.h | 1 + monitor.c | 11 +----- qapi-schema.json | 67 +++++++++++++++++++++++++++++++++ qmp-commands.hx | 6 +++ 6 files changed, 146 insertions(+), 84 deletions(-) diff --git a/block.c b/block.c index e648513fdd..551aa80af9 100644 --- a/block.c +++ b/block.c @@ -1874,93 +1874,56 @@ BlockInfoList *qmp_query_block(Error **errp) return head; } -static void bdrv_stats_iter(QObject *data, void *opaque) -{ - QDict *qdict; - Monitor *mon = opaque; - - qdict = qobject_to_qdict(data); - monitor_printf(mon, "%s:", qdict_get_str(qdict, "device")); - - qdict = qobject_to_qdict(qdict_get(qdict, "stats")); - monitor_printf(mon, " rd_bytes=%" PRId64 - " wr_bytes=%" PRId64 - " rd_operations=%" PRId64 - " wr_operations=%" PRId64 - " flush_operations=%" PRId64 - " wr_total_time_ns=%" PRId64 - " rd_total_time_ns=%" PRId64 - " flush_total_time_ns=%" PRId64 - "\n", - qdict_get_int(qdict, "rd_bytes"), - qdict_get_int(qdict, "wr_bytes"), - qdict_get_int(qdict, "rd_operations"), - qdict_get_int(qdict, "wr_operations"), - qdict_get_int(qdict, "flush_operations"), - qdict_get_int(qdict, "wr_total_time_ns"), - qdict_get_int(qdict, "rd_total_time_ns"), - qdict_get_int(qdict, "flush_total_time_ns")); -} - -void bdrv_stats_print(Monitor *mon, const QObject *data) -{ - qlist_iter(qobject_to_qlist(data), bdrv_stats_iter, mon); -} - -static QObject* bdrv_info_stats_bs(BlockDriverState *bs) -{ - QObject *res; - QDict *dict; - - res = qobject_from_jsonf("{ 'stats': {" - "'rd_bytes': %" PRId64 "," - "'wr_bytes': %" PRId64 "," - "'rd_operations': %" PRId64 "," - "'wr_operations': %" PRId64 "," - "'wr_highest_offset': %" PRId64 "," - "'flush_operations': %" PRId64 "," - "'wr_total_time_ns': %" PRId64 "," - "'rd_total_time_ns': %" PRId64 "," - "'flush_total_time_ns': %" PRId64 - "} }", - bs->nr_bytes[BDRV_ACCT_READ], - bs->nr_bytes[BDRV_ACCT_WRITE], - bs->nr_ops[BDRV_ACCT_READ], - bs->nr_ops[BDRV_ACCT_WRITE], - bs->wr_highest_sector * - (uint64_t)BDRV_SECTOR_SIZE, - bs->nr_ops[BDRV_ACCT_FLUSH], - bs->total_time_ns[BDRV_ACCT_WRITE], - bs->total_time_ns[BDRV_ACCT_READ], - bs->total_time_ns[BDRV_ACCT_FLUSH]); - dict = qobject_to_qdict(res); - - if (*bs->device_name) { - qdict_put(dict, "device", qstring_from_str(bs->device_name)); +/* Consider exposing this as a full fledged QMP command */ +static BlockStats *qmp_query_blockstat(const BlockDriverState *bs, Error **errp) +{ + BlockStats *s; + + s = g_malloc0(sizeof(*s)); + + if (bs->device_name[0]) { + s->has_device = true; + s->device = g_strdup(bs->device_name); } + s->stats = g_malloc0(sizeof(*s->stats)); + s->stats->rd_bytes = bs->nr_bytes[BDRV_ACCT_READ]; + s->stats->wr_bytes = bs->nr_bytes[BDRV_ACCT_WRITE]; + s->stats->rd_operations = bs->nr_ops[BDRV_ACCT_READ]; + s->stats->wr_operations = bs->nr_ops[BDRV_ACCT_WRITE]; + s->stats->wr_highest_offset = bs->wr_highest_sector * BDRV_SECTOR_SIZE; + s->stats->flush_operations = bs->nr_ops[BDRV_ACCT_FLUSH]; + s->stats->wr_total_time_ns = bs->total_time_ns[BDRV_ACCT_WRITE]; + s->stats->rd_total_time_ns = bs->total_time_ns[BDRV_ACCT_READ]; + s->stats->flush_total_time_ns = bs->total_time_ns[BDRV_ACCT_FLUSH]; + if (bs->file) { - QObject *parent = bdrv_info_stats_bs(bs->file); - qdict_put_obj(dict, "parent", parent); + s->has_parent = true; + s->parent = qmp_query_blockstat(bs->file, NULL); } - return res; + return s; } -void bdrv_info_stats(Monitor *mon, QObject **ret_data) +BlockStatsList *qmp_query_blockstats(Error **errp) { - QObject *obj; - QList *devices; + BlockStatsList *head = NULL, *cur_item = NULL; BlockDriverState *bs; - devices = qlist_new(); - QTAILQ_FOREACH(bs, &bdrv_states, list) { - obj = bdrv_info_stats_bs(bs); - qlist_append_obj(devices, obj); + BlockStatsList *info = g_malloc0(sizeof(*info)); + info->value = qmp_query_blockstat(bs, NULL); + + /* XXX: waiting for the qapi to support GSList */ + if (!cur_item) { + head = cur_item = info; + } else { + cur_item->next = info; + cur_item = info; + } } - *ret_data = QOBJECT(devices); + return head; } const char *bdrv_get_encrypted_filename(BlockDriverState *bs) diff --git a/hmp.c b/hmp.c index 5912250d04..eab2ddfce9 100644 --- a/hmp.c +++ b/hmp.c @@ -226,6 +226,40 @@ void hmp_info_block(Monitor *mon) qapi_free_BlockInfoList(block_list); } +void hmp_info_blockstats(Monitor *mon) +{ + BlockStatsList *stats_list, *stats; + + stats_list = qmp_query_blockstats(NULL); + + for (stats = stats_list; stats; stats = stats->next) { + if (!stats->value->has_device) { + continue; + } + + monitor_printf(mon, "%s:", stats->value->device); + monitor_printf(mon, " rd_bytes=%" PRId64 + " wr_bytes=%" PRId64 + " rd_operations=%" PRId64 + " wr_operations=%" PRId64 + " flush_operations=%" PRId64 + " wr_total_time_ns=%" PRId64 + " rd_total_time_ns=%" PRId64 + " flush_total_time_ns=%" PRId64 + "\n", + stats->value->stats->rd_bytes, + stats->value->stats->wr_bytes, + stats->value->stats->rd_operations, + stats->value->stats->wr_operations, + stats->value->stats->flush_operations, + stats->value->stats->wr_total_time_ns, + stats->value->stats->rd_total_time_ns, + stats->value->stats->flush_total_time_ns); + } + + qapi_free_BlockStatsList(stats_list); +} + void hmp_quit(Monitor *mon, const QDict *qdict) { monitor_suspend(mon); diff --git a/hmp.h b/hmp.h index f5ec417156..f8c50d438b 100644 --- a/hmp.h +++ b/hmp.h @@ -27,6 +27,7 @@ void hmp_info_mice(Monitor *mon); void hmp_info_migrate(Monitor *mon); void hmp_info_cpus(Monitor *mon); void hmp_info_block(Monitor *mon); +void hmp_info_blockstats(Monitor *mon); void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); diff --git a/monitor.c b/monitor.c index 3e76f4c0b7..70e54602a9 100644 --- a/monitor.c +++ b/monitor.c @@ -2681,8 +2681,7 @@ static const mon_cmd_t info_cmds[] = { .args_type = "", .params = "", .help = "show block device statistics", - .user_print = bdrv_stats_print, - .mhandler.info_new = bdrv_info_stats, + .mhandler.info = hmp_info_blockstats, }, { .name = "registers", @@ -2959,14 +2958,6 @@ static const mon_cmd_t qmp_cmds[] = { }; static const mon_cmd_t qmp_query_cmds[] = { - { - .name = "blockstats", - .args_type = "", - .params = "", - .help = "show block device statistics", - .user_print = bdrv_stats_print, - .mhandler.info_new = bdrv_info_stats, - }, { .name = "pci", .args_type = "", diff --git a/qapi-schema.json b/qapi-schema.json index 5e3570e53d..45494d8af8 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -436,6 +436,73 @@ ## { 'command': 'query-block', 'returns': ['BlockInfo'] } +## +# @BlockDeviceStats: +# +# Statistics of a virtual block device or a block backing device. +# +# @rd_bytes: The number of bytes read by the device. +# +# @wr_bytes: The number of bytes written by the device. +# +# @rd_operations: The number of read operations performed by the device. +# +# @wr_operations: The number of write operations performed by the device. +# +# @flush_operations: The number of cache flush operations performed by the +# device (since 0.15.0) +# +# @flush_total_time_ns: Total time spend on cache flushes in nano-seconds +# (since 0.15.0). +# +# @wr_total_time_ns: Total time spend on writes in nano-seconds (since 0.15.0). +# +# @rd_total_time_ns: Total_time_spend on reads in nano-seconds (since 0.15.0). +# +# @wr_highest_offset: The offset after the greatest byte written to the +# device. The intended use of this information is for +# growable sparse files (like qcow2) that are used on top +# of a physical device. +# +# Since: 0.14.0 +## +{ 'type': 'BlockDeviceStats', + 'data': {'rd_bytes': 'int', 'wr_bytes': 'int', 'rd_operations': 'int', + 'wr_operations': 'int', 'flush_operations': 'int', + 'flush_total_time_ns': 'int', 'wr_total_time_ns': 'int', + 'rd_total_time_ns': 'int', 'wr_highest_offset': 'int' } } + +## +# @BlockStats: +# +# Statistics of a virtual block device or a block backing device. +# +# @device: #optional If the stats are for a virtual block device, the name +# corresponding to the virtual block device. +# +# @stats: A @BlockDeviceStats for the device. +# +# @parent: #optional This may point to the backing block device if this is a +# a virtual block device. If it's a backing block, this will point +# to the backing file is one is present. +# +# Since: 0.14.0 +## +{ 'type': 'BlockStats', + 'data': {'*device': 'str', 'stats': 'BlockDeviceStats', + '*parent': 'BlockStats'} } + +## +# @query-blockstats: +# +# Query the @BlockStats for all virtual block devices. +# +# Returns: A list of @BlockStats for each virtual block devices. +# +# Since: 0.14.0 +## +{ 'command': 'query-blockstats', 'returns': ['BlockStats'] } + ## # @quit: # diff --git a/qmp-commands.hx b/qmp-commands.hx index 0cf0be7e0d..a250a7ada7 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1311,6 +1311,12 @@ Example: EQMP + { + .name = "query-blockstats", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_blockstats, + }, + SQMP query-cpus ---------- -- cgit v1.2.1 From bf82632841cd5cd9b4275913591efe4a2035b969 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 19 Oct 2011 15:15:57 -0200 Subject: qerror: Add a user string for QERR_FEATURE_DISABLED Missing from commit 821601ea5b. Signed-off-by: Luiz Capitulino --- qerror.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qerror.c b/qerror.c index 68998d4bab..4b48b39660 100644 --- a/qerror.c +++ b/qerror.c @@ -116,6 +116,10 @@ static const QErrorStringTable qerror_table[] = { .error_fmt = QERR_FD_NOT_SUPPLIED, .desc = "No file descriptor supplied via SCM_RIGHTS", }, + { + .error_fmt = QERR_FEATURE_DISABLED, + .desc = "The feature '%(name)' is not enabled", + }, { .error_fmt = QERR_INVALID_BLOCK_FORMAT, .desc = "Invalid block format '%(name)'", -- cgit v1.2.1 From 2b54aa879ea8490e25107dfc51a6ee268c84c273 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Mon, 17 Oct 2011 16:41:22 -0200 Subject: qapi: Convert query-vnc There are three important remarks in relation to the non-qapi command: 1. This commit also fixes the behavior of the 'query-vnc' and 'info vnc' commands to return an error when qemu is built without VNC support (ie. --disable-vnc). The non-qapi command would return the OK response in QMP and no response in HMP 2. The qapi version explicitly marks the fields 'host', 'family', 'service' and 'auth' as optional. Their are not documented as optional in the non-qapi command doc, but they would not be returned if vnc support is disabled. The qapi version maintains the same semantics, but documents those fields correctly 3. The 'clients' field, which is a list, is marked as optional but is always returned. If there are no clients connected an empty list is returned. This is not the Right Way to this in the qapi but it's how the non-qapi command used to work Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- console.h | 9 ---- hmp.c | 46 +++++++++++++++++++ hmp.h | 1 + monitor.c | 11 +---- qapi-schema.json | 81 +++++++++++++++++++++++++++++++++ qmp-commands.hx | 6 +++ qmp.c | 10 +++++ ui/vnc.c | 135 ++++++++++++++++++++++++++++++++++--------------------- 8 files changed, 228 insertions(+), 71 deletions(-) diff --git a/console.h b/console.h index 9c1487e041..6ac4ed31ec 100644 --- a/console.h +++ b/console.h @@ -383,8 +383,6 @@ char *vnc_display_local_addr(DisplayState *ds); #ifdef CONFIG_VNC int vnc_display_password(DisplayState *ds, const char *password); int vnc_display_pw_expire(DisplayState *ds, time_t expires); -void do_info_vnc_print(Monitor *mon, const QObject *data); -void do_info_vnc(Monitor *mon, QObject **ret_data); #else static inline int vnc_display_password(DisplayState *ds, const char *password) { @@ -396,13 +394,6 @@ static inline int vnc_display_pw_expire(DisplayState *ds, time_t expires) qerror_report(QERR_FEATURE_DISABLED, "vnc"); return -ENODEV; }; -static inline void do_info_vnc(Monitor *mon, QObject **ret_data) -{ -}; -static inline void do_info_vnc_print(Monitor *mon, const QObject *data) -{ - monitor_printf(mon, "VNC support disabled\n"); -}; #endif /* curses.c */ diff --git a/hmp.c b/hmp.c index eab2ddfce9..6d86fe3d1c 100644 --- a/hmp.c +++ b/hmp.c @@ -260,6 +260,52 @@ void hmp_info_blockstats(Monitor *mon) qapi_free_BlockStatsList(stats_list); } +void hmp_info_vnc(Monitor *mon) +{ + VncInfo *info; + Error *err = NULL; + VncClientInfoList *client; + + info = qmp_query_vnc(&err); + if (err) { + monitor_printf(mon, "%s\n", error_get_pretty(err)); + error_free(err); + return; + } + + if (!info->enabled) { + monitor_printf(mon, "Server: disabled\n"); + goto out; + } + + monitor_printf(mon, "Server:\n"); + if (info->has_host && info->has_service) { + monitor_printf(mon, " address: %s:%s\n", info->host, info->service); + } + if (info->has_auth) { + monitor_printf(mon, " auth: %s\n", info->auth); + } + + if (!info->has_clients || info->clients == NULL) { + monitor_printf(mon, "Client: none\n"); + } else { + for (client = info->clients; client; client = client->next) { + monitor_printf(mon, "Client:\n"); + monitor_printf(mon, " address: %s:%s\n", + client->value->host, client->value->service); + monitor_printf(mon, " x509_dname: %s\n", + client->value->x509_dname ? + client->value->x509_dname : "none"); + monitor_printf(mon, " username: %s\n", + client->value->has_sasl_username ? + client->value->sasl_username : "none"); + } + } + +out: + qapi_free_VncInfo(info); +} + void hmp_quit(Monitor *mon, const QDict *qdict) { monitor_suspend(mon); diff --git a/hmp.h b/hmp.h index f8c50d438b..7713348cfd 100644 --- a/hmp.h +++ b/hmp.h @@ -28,6 +28,7 @@ void hmp_info_migrate(Monitor *mon); void hmp_info_cpus(Monitor *mon); void hmp_info_block(Monitor *mon); void hmp_info_blockstats(Monitor *mon); +void hmp_info_vnc(Monitor *mon); void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); diff --git a/monitor.c b/monitor.c index 70e54602a9..d7c72bbe0d 100644 --- a/monitor.c +++ b/monitor.c @@ -2849,8 +2849,7 @@ static const mon_cmd_t info_cmds[] = { .args_type = "", .params = "", .help = "show the vnc server status", - .user_print = do_info_vnc_print, - .mhandler.info_new = do_info_vnc, + .mhandler.info = hmp_info_vnc, }, #if defined(CONFIG_SPICE) { @@ -2966,14 +2965,6 @@ static const mon_cmd_t qmp_query_cmds[] = { .user_print = do_pci_info_print, .mhandler.info_new = do_pci_info, }, - { - .name = "vnc", - .args_type = "", - .params = "", - .help = "show the vnc server status", - .user_print = do_info_vnc_print, - .mhandler.info_new = do_info_vnc, - }, #if defined(CONFIG_SPICE) { .name = "spice", diff --git a/qapi-schema.json b/qapi-schema.json index 45494d8af8..23be143a88 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -503,6 +503,87 @@ ## { 'command': 'query-blockstats', 'returns': ['BlockStats'] } +## +# @VncClientInfo: +# +# Information about a connected VNC client. +# +# @host: The host name of the client. QEMU tries to resolve this to a DNS name +# when possible. +# +# @family: 'ipv6' if the client is connected via IPv6 and TCP +# 'ipv4' if the client is connected via IPv4 and TCP +# 'unix' if the client is connected via a unix domain socket +# 'unknown' otherwise +# +# @service: The service name of the client's port. This may depends on the +# host system's service database so symbolic names should not be +# relied on. +# +# @x509_dname: #optional If x509 authentication is in use, the Distinguished +# Name of the client. +# +# @sasl_username: #optional If SASL authentication is in use, the SASL username +# used for authentication. +# +# Since: 0.14.0 +## +{ 'type': 'VncClientInfo', + 'data': {'host': 'str', 'family': 'str', 'service': 'str', + '*x509_dname': 'str', '*sasl_username': 'str'} } + +## +# @VncInfo: +# +# Information about the VNC session. +# +# @enabled: true if the VNC server is enabled, false otherwise +# +# @host: #optional The hostname the VNC server is bound to. This depends on +# the name resolution on the host and may be an IP address. +# +# @family: #optional 'ipv6' if the host is listening for IPv6 connections +# 'ipv4' if the host is listening for IPv4 connections +# 'unix' if the host is listening on a unix domain socket +# 'unknown' otherwise +# +# @service: #optional The service name of the server's port. This may depends +# on the host system's service database so symbolic names should not +# be relied on. +# +# @auth: #optional the current authentication type used by the server +# 'none' if no authentication is being used +# 'vnc' if VNC authentication is being used +# 'vencrypt+plain' if VEncrypt is used with plain text authentication +# 'vencrypt+tls+none' if VEncrypt is used with TLS and no authentication +# 'vencrypt+tls+vnc' if VEncrypt is used with TLS and VNC authentication +# 'vencrypt+tls+plain' if VEncrypt is used with TLS and plain text auth +# 'vencrypt+x509+none' if VEncrypt is used with x509 and no auth +# 'vencrypt+x509+vnc' if VEncrypt is used with x509 and VNC auth +# 'vencrypt+x509+plain' if VEncrypt is used with x509 and plain text auth +# 'vencrypt+tls+sasl' if VEncrypt is used with TLS and SASL auth +# 'vencrypt+x509+sasl' if VEncrypt is used with x509 and SASL auth +# +# @clients: a list of @VncClientInfo of all currently connected clients +# +# Since: 0.14.0 +## +{ 'type': 'VncInfo', + 'data': {'enabled': 'bool', '*host': 'str', '*family': 'str', + '*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']} } + +## +# @query-vnc: +# +# Returns information about the current VNC server +# +# Returns: @VncInfo +# If VNC support is not compiled in, FeatureDisabled +# +# Since: 0.14.0 +## +{ 'command': 'query-vnc', 'returns': 'VncInfo' } + ## # @quit: # diff --git a/qmp-commands.hx b/qmp-commands.hx index a250a7ada7..0953d3f6be 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1741,6 +1741,12 @@ Example: EQMP + { + .name = "query-vnc", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_vnc, + }, + SQMP query-spice ----------- diff --git a/qmp.c b/qmp.c index e84922bff0..3a58cfe35f 100644 --- a/qmp.c +++ b/qmp.c @@ -95,3 +95,13 @@ void qmp_cpu(int64_t index, Error **errp) { /* Just do nothing */ } + +#ifndef CONFIG_VNC +/* If VNC support is enabled, the "true" query-vnc command is + defined in the VNC subsystem */ +VncInfo *qmp_query_vnc(Error **errp) +{ + error_set(errp, QERR_FEATURE_DISABLED, "vnc"); + return NULL; +}; +#endif diff --git a/ui/vnc.c b/ui/vnc.c index fc3a612a35..32d4cb70cd 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -31,6 +31,7 @@ #include "qemu-timer.h" #include "acl.h" #include "qemu-objects.h" +#include "qmp-commands.h" #define VNC_REFRESH_INTERVAL_BASE 30 #define VNC_REFRESH_INTERVAL_INC 50 @@ -274,80 +275,110 @@ static void vnc_qmp_event(VncState *vs, MonitorEvent event) qobject_decref(data); } -static void info_vnc_iter(QObject *obj, void *opaque) +static VncClientInfo *qmp_query_vnc_client(const VncState *client) { - QDict *client; - Monitor *mon = opaque; + struct sockaddr_storage sa; + socklen_t salen = sizeof(sa); + char host[NI_MAXHOST]; + char serv[NI_MAXSERV]; + VncClientInfo *info; + + if (getpeername(client->csock, (struct sockaddr *)&sa, &salen) < 0) { + return NULL; + } + + if (getnameinfo((struct sockaddr *)&sa, salen, + host, sizeof(host), + serv, sizeof(serv), + NI_NUMERICHOST | NI_NUMERICSERV) < 0) { + return NULL; + } - client = qobject_to_qdict(obj); - monitor_printf(mon, "Client:\n"); - monitor_printf(mon, " address: %s:%s\n", - qdict_get_str(client, "host"), - qdict_get_str(client, "service")); + info = g_malloc0(sizeof(*info)); + info->host = g_strdup(host); + info->service = g_strdup(serv); + info->family = g_strdup(inet_strfamily(sa.ss_family)); #ifdef CONFIG_VNC_TLS - monitor_printf(mon, " x509_dname: %s\n", - qdict_haskey(client, "x509_dname") ? - qdict_get_str(client, "x509_dname") : "none"); + if (client->tls.session && client->tls.dname) { + info->has_x509_dname = true; + info->x509_dname = g_strdup(client->tls.dname); + } #endif #ifdef CONFIG_VNC_SASL - monitor_printf(mon, " username: %s\n", - qdict_haskey(client, "sasl_username") ? - qdict_get_str(client, "sasl_username") : "none"); -#endif -} - -void do_info_vnc_print(Monitor *mon, const QObject *data) -{ - QDict *server; - QList *clients; - - server = qobject_to_qdict(data); - if (qdict_get_bool(server, "enabled") == 0) { - monitor_printf(mon, "Server: disabled\n"); - return; + if (client->sasl.conn && client->sasl.username) { + info->has_sasl_username = true; + info->sasl_username = g_strdup(client->sasl.username); } +#endif - monitor_printf(mon, "Server:\n"); - monitor_printf(mon, " address: %s:%s\n", - qdict_get_str(server, "host"), - qdict_get_str(server, "service")); - monitor_printf(mon, " auth: %s\n", qdict_get_str(server, "auth")); - - clients = qdict_get_qlist(server, "clients"); - if (qlist_empty(clients)) { - monitor_printf(mon, "Client: none\n"); - } else { - qlist_iter(clients, info_vnc_iter, mon); - } + return info; } -void do_info_vnc(Monitor *mon, QObject **ret_data) +VncInfo *qmp_query_vnc(Error **errp) { + VncInfo *info = g_malloc0(sizeof(*info)); + if (vnc_display == NULL || vnc_display->display == NULL) { - *ret_data = qobject_from_jsonf("{ 'enabled': false }"); + info->enabled = false; } else { - QList *clist; + VncClientInfoList *cur_item = NULL; + struct sockaddr_storage sa; + socklen_t salen = sizeof(sa); + char host[NI_MAXHOST]; + char serv[NI_MAXSERV]; VncState *client; - clist = qlist_new(); + info->enabled = true; + + /* for compatibility with the original command */ + info->has_clients = true; + QTAILQ_FOREACH(client, &vnc_display->clients, next) { - if (client->info) { - /* incref so that it's not freed by upper layers */ - qobject_incref(client->info); - qlist_append_obj(clist, client->info); + VncClientInfoList *cinfo = g_malloc0(sizeof(*info)); + cinfo->value = qmp_query_vnc_client(client); + + /* XXX: waiting for the qapi to support GSList */ + if (!cur_item) { + info->clients = cur_item = cinfo; + } else { + cur_item->next = cinfo; + cur_item = cinfo; } } - *ret_data = qobject_from_jsonf("{ 'enabled': true, 'clients': %p }", - QOBJECT(clist)); - assert(*ret_data != NULL); + if (getsockname(vnc_display->lsock, (struct sockaddr *)&sa, + &salen) == -1) { + error_set(errp, QERR_UNDEFINED_ERROR); + goto out_error; + } - if (vnc_server_info_put(qobject_to_qdict(*ret_data)) < 0) { - qobject_decref(*ret_data); - *ret_data = NULL; + if (getnameinfo((struct sockaddr *)&sa, salen, + host, sizeof(host), + serv, sizeof(serv), + NI_NUMERICHOST | NI_NUMERICSERV) < 0) { + error_set(errp, QERR_UNDEFINED_ERROR); + goto out_error; } + + info->has_host = true; + info->host = g_strdup(host); + + info->has_service = true; + info->service = g_strdup(serv); + + info->has_family = true; + info->family = g_strdup(inet_strfamily(sa.ss_family)); + + info->has_auth = true; + info->auth = g_strdup(vnc_auth_name(vnc_display)); } + + return info; + +out_error: + qapi_free_VncInfo(info); + return NULL; } /* TODO -- cgit v1.2.1 From d1f29646f21321e60d1be4e72ac3b6caaa0239cc Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 20 Oct 2011 17:01:33 -0200 Subject: qapi: Convert query-spice Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- hmp.c | 43 +++++++++++++++++ hmp.h | 1 + monitor.c | 13 +----- qapi-schema.json | 74 +++++++++++++++++++++++++++++ qmp-commands.hx | 8 ++++ qmp.c | 12 +++++ ui/spice-core.c | 139 +++++++++++++++++++++++-------------------------------- 7 files changed, 197 insertions(+), 93 deletions(-) diff --git a/hmp.c b/hmp.c index 6d86fe3d1c..aae13c093b 100644 --- a/hmp.c +++ b/hmp.c @@ -306,6 +306,49 @@ out: qapi_free_VncInfo(info); } +void hmp_info_spice(Monitor *mon) +{ + SpiceChannelList *chan; + SpiceInfo *info; + + info = qmp_query_spice(NULL); + + if (!info->enabled) { + monitor_printf(mon, "Server: disabled\n"); + goto out; + } + + monitor_printf(mon, "Server:\n"); + if (info->has_port) { + monitor_printf(mon, " address: %s:%" PRId64 "\n", + info->host, info->port); + } + if (info->has_tls_port) { + monitor_printf(mon, " address: %s:%" PRId64 " [tls]\n", + info->host, info->tls_port); + } + monitor_printf(mon, " auth: %s\n", info->auth); + monitor_printf(mon, " compiled: %s\n", info->compiled_version); + + if (!info->has_channels || info->channels == NULL) { + monitor_printf(mon, "Channels: none\n"); + } else { + for (chan = info->channels; chan; chan = chan->next) { + monitor_printf(mon, "Channel:\n"); + monitor_printf(mon, " address: %s:%s%s\n", + chan->value->host, chan->value->port, + chan->value->tls ? " [tls]" : ""); + monitor_printf(mon, " session: %" PRId64 "\n", + chan->value->connection_id); + monitor_printf(mon, " channel: %" PRId64 ":%" PRId64 "\n", + chan->value->channel_type, chan->value->channel_id); + } + } + +out: + qapi_free_SpiceInfo(info); +} + void hmp_quit(Monitor *mon, const QDict *qdict) { monitor_suspend(mon); diff --git a/hmp.h b/hmp.h index 7713348cfd..09f3a01cee 100644 --- a/hmp.h +++ b/hmp.h @@ -29,6 +29,7 @@ void hmp_info_cpus(Monitor *mon); void hmp_info_block(Monitor *mon); void hmp_info_blockstats(Monitor *mon); void hmp_info_vnc(Monitor *mon); +void hmp_info_spice(Monitor *mon); void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); diff --git a/monitor.c b/monitor.c index d7c72bbe0d..fc3da382f0 100644 --- a/monitor.c +++ b/monitor.c @@ -2857,8 +2857,7 @@ static const mon_cmd_t info_cmds[] = { .args_type = "", .params = "", .help = "show the spice server status", - .user_print = do_info_spice_print, - .mhandler.info_new = do_info_spice, + .mhandler.info = hmp_info_spice, }, #endif { @@ -2965,16 +2964,6 @@ static const mon_cmd_t qmp_query_cmds[] = { .user_print = do_pci_info_print, .mhandler.info_new = do_pci_info, }, -#if defined(CONFIG_SPICE) - { - .name = "spice", - .args_type = "", - .params = "", - .help = "show the spice server status", - .user_print = do_info_spice_print, - .mhandler.info_new = do_info_spice, - }, -#endif { .name = "balloon", .args_type = "", diff --git a/qapi-schema.json b/qapi-schema.json index 23be143a88..087a46305e 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -584,6 +584,80 @@ ## { 'command': 'query-vnc', 'returns': 'VncInfo' } +## +# @SpiceChannel +# +# Information about a SPICE client channel. +# +# @host: The host name of the client. QEMU tries to resolve this to a DNS name +# when possible. +# +# @family: 'ipv6' if the client is connected via IPv6 and TCP +# 'ipv4' if the client is connected via IPv4 and TCP +# 'unix' if the client is connected via a unix domain socket +# 'unknown' otherwise +# +# @port: The client's port number. +# +# @connection-id: SPICE connection id number. All channels with the same id +# belong to the same SPICE session. +# +# @connection-type: SPICE channel type number. "1" is the main control channel, +# filter for this one if you want track spice sessions only +# +# @channel-id: SPICE channel ID number. Usually "0", might be different needed +# when multiple channels of the same type exist, such as multiple +# display channels in a multihead setup +# +# @tls: true if the channel is encrypted, false otherwise. +# +# Since: 0.14.0 +## +{ 'type': 'SpiceChannel', + 'data': {'host': 'str', 'family': 'str', 'port': 'str', + 'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int', + 'tls': 'bool'} } + +## +# @SpiceInfo +# +# Information about the SPICE session. +# +# @enabled: true if the SPICE server is enabled, false otherwise +# +# @host: #optional The hostname the SPICE server is bound to. This depends on +# the name resolution on the host and may be an IP address. +# +# @port: #optional The SPICE server's port number. +# +# @compiled-version: #optional SPICE server version. +# +# @tls-port: #optional The SPICE server's TLS port number. +# +# @auth: #optional the current authentication type used by the server +# 'none' if no authentication is being used +# 'spice' (TODO: describe) +# +# @channels: a list of @SpiceChannel for each active spice channel +# +# Since: 0.14.0 +## +{ 'type': 'SpiceInfo', + 'data': {'enabled': 'bool', '*host': 'str', '*port': 'int', + '*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str', + '*channels': ['SpiceChannel']} } + +## +# @query-spice +# +# Returns information about the current SPICE server +# +# Returns: @SpiceInfo +# +# Since: 0.14.0 +## +{ 'command': 'query-spice', 'returns': 'SpiceInfo' } + ## # @quit: # diff --git a/qmp-commands.hx b/qmp-commands.hx index 0953d3f6be..e99c240f1a 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1817,6 +1817,14 @@ Example: EQMP +#if defined(CONFIG_SPICE) + { + .name = "query-spice", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_spice, + }, +#endif + SQMP query-name ---------- diff --git a/qmp.c b/qmp.c index 3a58cfe35f..511dd624b5 100644 --- a/qmp.c +++ b/qmp.c @@ -105,3 +105,15 @@ VncInfo *qmp_query_vnc(Error **errp) return NULL; }; #endif + +#ifndef CONFIG_SPICE +/* If SPICE support is enabled, the "true" query-spice command is + defined in the SPICE subsystem. Also note that we use a small + trick to maintain query-spice's original behavior, which is not + to be available in the namespace if SPICE is not compiled in */ +SpiceInfo *qmp_query_spice(Error **errp) +{ + error_set(errp, QERR_COMMAND_NOT_FOUND, "query-spice"); + return NULL; +}; +#endif diff --git a/ui/spice-core.c b/ui/spice-core.c index b33366e5d7..f556849ef9 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -27,6 +27,7 @@ #include "qemu-queue.h" #include "qemu-x509.h" #include "qemu_socket.h" +#include "qmp-commands.h" #include "qint.h" #include "qbool.h" #include "qstring.h" @@ -194,22 +195,6 @@ static void add_channel_info(QDict *dict, SpiceChannelEventInfo *info) qdict_put(dict, "tls", qbool_from_int(tls)); } -static QList *channel_list_get(void) -{ - ChannelList *item; - QList *list; - QDict *dict; - - list = qlist_new(); - QTAILQ_FOREACH(item, &channel_list, link) { - dict = qdict_new(); - add_addr_info(dict, &item->info->paddr, item->info->plen); - add_channel_info(dict, item->info); - qlist_append(list, dict); - } - return list; -} - static void channel_event(int event, SpiceChannelEventInfo *info) { static const int qevent[] = { @@ -351,98 +336,90 @@ static const char *wan_compression_names[] = { /* functions for the rest of qemu */ -static void info_spice_iter(QObject *obj, void *opaque) +static SpiceChannelList *qmp_query_spice_channels(void) { - QDict *client; - Monitor *mon = opaque; - - client = qobject_to_qdict(obj); - monitor_printf(mon, "Channel:\n"); - monitor_printf(mon, " address: %s:%s%s\n", - qdict_get_str(client, "host"), - qdict_get_str(client, "port"), - qdict_get_bool(client, "tls") ? " [tls]" : ""); - monitor_printf(mon, " session: %" PRId64 "\n", - qdict_get_int(client, "connection-id")); - monitor_printf(mon, " channel: %d:%d\n", - (int)qdict_get_int(client, "channel-type"), - (int)qdict_get_int(client, "channel-id")); -} - -void do_info_spice_print(Monitor *mon, const QObject *data) -{ - QDict *server; - QList *channels; - const char *host; - int port; - - server = qobject_to_qdict(data); - if (qdict_get_bool(server, "enabled") == 0) { - monitor_printf(mon, "Server: disabled\n"); - return; - } + SpiceChannelList *cur_item = NULL, *head = NULL; + ChannelList *item; - monitor_printf(mon, "Server:\n"); - host = qdict_get_str(server, "host"); - port = qdict_get_try_int(server, "port", -1); - if (port != -1) { - monitor_printf(mon, " address: %s:%d\n", host, port); - } - port = qdict_get_try_int(server, "tls-port", -1); - if (port != -1) { - monitor_printf(mon, " address: %s:%d [tls]\n", host, port); + QTAILQ_FOREACH(item, &channel_list, link) { + SpiceChannelList *chan; + char host[NI_MAXHOST], port[NI_MAXSERV]; + + chan = g_malloc0(sizeof(*chan)); + chan->value = g_malloc0(sizeof(*chan->value)); + + getnameinfo(&item->info->paddr, item->info->plen, + host, sizeof(host), port, sizeof(port), + NI_NUMERICHOST | NI_NUMERICSERV); + chan->value->host = g_strdup(host); + chan->value->port = g_strdup(port); + chan->value->family = g_strdup(inet_strfamily(item->info->paddr.sa_family)); + + chan->value->connection_id = item->info->connection_id; + chan->value->channel_type = item->info->type; + chan->value->channel_id = item->info->id; + chan->value->tls = item->info->flags & SPICE_CHANNEL_EVENT_FLAG_TLS; + + /* XXX: waiting for the qapi to support GSList */ + if (!cur_item) { + head = cur_item = chan; + } else { + cur_item->next = chan; + cur_item = chan; + } } - monitor_printf(mon, " auth: %s\n", qdict_get_str(server, "auth")); - monitor_printf(mon, " compiled: %s\n", - qdict_get_str(server, "compiled-version")); - channels = qdict_get_qlist(server, "channels"); - if (qlist_empty(channels)) { - monitor_printf(mon, "Channels: none\n"); - } else { - qlist_iter(channels, info_spice_iter, mon); - } + return head; } -void do_info_spice(Monitor *mon, QObject **ret_data) +SpiceInfo *qmp_query_spice(Error **errp) { QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head); - QDict *server; - QList *clist; - const char *addr; int port, tls_port; + const char *addr; + SpiceInfo *info; char version_string[20]; /* 12 = |255.255.255\0| is the max */ + info = g_malloc0(sizeof(*info)); + if (!spice_server) { - *ret_data = qobject_from_jsonf("{ 'enabled': false }"); - return; + info->enabled = false; + return info; } + info->enabled = true; + addr = qemu_opt_get(opts, "addr"); port = qemu_opt_get_number(opts, "port", 0); tls_port = qemu_opt_get_number(opts, "tls-port", 0); - clist = channel_list_get(); - server = qdict_new(); - qdict_put(server, "enabled", qbool_from_int(true)); - qdict_put(server, "auth", qstring_from_str(auth)); - qdict_put(server, "host", qstring_from_str(addr ? addr : "0.0.0.0")); + info->has_auth = true; + info->auth = g_strdup(auth); + + info->has_host = true; + info->host = g_strdup(addr ? addr : "0.0.0.0"); + + info->has_compiled_version = true; snprintf(version_string, sizeof(version_string), "%d.%d.%d", (SPICE_SERVER_VERSION & 0xff0000) >> 16, (SPICE_SERVER_VERSION & 0xff00) >> 8, SPICE_SERVER_VERSION & 0xff); - qdict_put(server, "compiled-version", qstring_from_str(version_string)); + info->compiled_version = g_strdup(version_string); + if (port) { - qdict_put(server, "port", qint_from_int(port)); + info->has_port = true; + info->port = port; } if (tls_port) { - qdict_put(server, "tls-port", qint_from_int(tls_port)); - } - if (clist) { - qdict_put(server, "channels", clist); + info->has_tls_port = true; + info->tls_port = tls_port; } - *ret_data = QOBJECT(server); + /* for compatibility with the original command */ + info->has_channels = true; + info->channels = qmp_query_spice_channels(); + + return info; } static void migration_state_notifier(Notifier *notifier, void *data) -- cgit v1.2.1 From 96637bcdf9e00db77265229d3d30d952bdde74be Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 21 Oct 2011 11:41:37 -0200 Subject: qapi: Convert query-balloon Please, note that some of the code supporting memory statistics is still around (eg. virtio_balloon_receive_stats() and reset_stats()). Also, the qmp_query_balloon() function is synchronous and thus doesn't make any use of the (not fully working) monitor's asynchronous command support (the old non-qapi implementation did). Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- balloon.c | 72 ++++++++++--------------------------------------- balloon.h | 6 ++--- hmp.c | 39 +++++++++++++++++++++++++++ hmp.h | 1 + hw/virtio-balloon.c | 78 ++++++++++------------------------------------------- monitor.c | 13 +-------- qapi-schema.json | 44 ++++++++++++++++++++++++++++++ qmp-commands.hx | 5 ++++ 8 files changed, 120 insertions(+), 138 deletions(-) diff --git a/balloon.c b/balloon.c index a2133dba75..e1cd5fac4c 100644 --- a/balloon.c +++ b/balloon.c @@ -25,12 +25,11 @@ */ #include "monitor.h" -#include "qjson.h" -#include "qint.h" #include "cpu-common.h" #include "kvm.h" #include "balloon.h" #include "trace.h" +#include "qmp-commands.h" static QEMUBalloonEvent *balloon_event_fn; static QEMUBalloonStatus *balloon_stat_fn; @@ -72,76 +71,33 @@ static int qemu_balloon(ram_addr_t target) return 1; } -static int qemu_balloon_status(MonitorCompletion cb, void *opaque) +static int qemu_balloon_status(BalloonInfo *info) { if (!balloon_stat_fn) { return 0; } - balloon_stat_fn(balloon_opaque, cb, opaque); + balloon_stat_fn(balloon_opaque, info); return 1; } -static void print_balloon_stat(const char *key, QObject *obj, void *opaque) +BalloonInfo *qmp_query_balloon(Error **errp) { - Monitor *mon = opaque; - - if (strcmp(key, "actual")) { - monitor_printf(mon, ",%s=%" PRId64, key, - qint_get_int(qobject_to_qint(obj))); - } -} - -void monitor_print_balloon(Monitor *mon, const QObject *data) -{ - QDict *qdict; - - qdict = qobject_to_qdict(data); - if (!qdict_haskey(qdict, "actual")) { - return; - } - monitor_printf(mon, "balloon: actual=%" PRId64, - qdict_get_int(qdict, "actual") >> 20); - qdict_iter(qdict, print_balloon_stat, mon); - monitor_printf(mon, "\n"); -} - -/** - * do_info_balloon(): Balloon information - * - * Make an asynchronous request for balloon info. When the request completes - * a QDict will be returned according to the following specification: - * - * - "actual": current balloon value in bytes - * The following fields may or may not be present: - * - "mem_swapped_in": Amount of memory swapped in (bytes) - * - "mem_swapped_out": Amount of memory swapped out (bytes) - * - "major_page_faults": Number of major faults - * - "minor_page_faults": Number of minor faults - * - "free_mem": Total amount of free and unused memory (bytes) - * - "total_mem": Total amount of available memory (bytes) - * - * Example: - * - * { "actual": 1073741824, "mem_swapped_in": 0, "mem_swapped_out": 0, - * "major_page_faults": 142, "minor_page_faults": 239245, - * "free_mem": 1014185984, "total_mem": 1044668416 } - */ -int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque) -{ - int ret; + BalloonInfo *info; if (kvm_enabled() && !kvm_has_sync_mmu()) { - qerror_report(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon"); - return -1; + error_set(errp, QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon"); + return NULL; } - ret = qemu_balloon_status(cb, opaque); - if (!ret) { - qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon"); - return -1; + info = g_malloc0(sizeof(*info)); + + if (qemu_balloon_status(info) == 0) { + error_set(errp, QERR_DEVICE_NOT_ACTIVE, "balloon"); + qapi_free_BalloonInfo(info); + return NULL; } - return 0; + return info; } /** diff --git a/balloon.h b/balloon.h index f59e2881f6..b36abeadf0 100644 --- a/balloon.h +++ b/balloon.h @@ -15,17 +15,15 @@ #define _QEMU_BALLOON_H #include "monitor.h" +#include "qapi-types.h" typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target); -typedef void (QEMUBalloonStatus)(void *opaque, MonitorCompletion cb, - void *cb_data); +typedef void (QEMUBalloonStatus)(void *opaque, BalloonInfo *info); int qemu_add_balloon_handler(QEMUBalloonEvent *event_func, QEMUBalloonStatus *stat_func, void *opaque); void qemu_remove_balloon_handler(void *opaque); -void monitor_print_balloon(Monitor *mon, const QObject *data); -int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque); int do_balloon(Monitor *mon, const QDict *params, MonitorCompletion cb, void *opaque); diff --git a/hmp.c b/hmp.c index aae13c093b..e0b40b16e5 100644 --- a/hmp.c +++ b/hmp.c @@ -349,6 +349,45 @@ out: qapi_free_SpiceInfo(info); } +void hmp_info_balloon(Monitor *mon) +{ + BalloonInfo *info; + Error *err = NULL; + + info = qmp_query_balloon(&err); + if (err) { + monitor_printf(mon, "%s\n", error_get_pretty(err)); + error_free(err); + return; + } + + monitor_printf(mon, "balloon: actual=%" PRId64, info->actual >> 20); + if (info->has_mem_swapped_in) { + monitor_printf(mon, " mem_swapped_in=%" PRId64, info->mem_swapped_in); + } + if (info->has_mem_swapped_out) { + monitor_printf(mon, " mem_swapped_out=%" PRId64, info->mem_swapped_out); + } + if (info->has_major_page_faults) { + monitor_printf(mon, " major_page_faults=%" PRId64, + info->major_page_faults); + } + if (info->has_minor_page_faults) { + monitor_printf(mon, " minor_page_faults=%" PRId64, + info->minor_page_faults); + } + if (info->has_free_mem) { + monitor_printf(mon, " free_mem=%" PRId64, info->free_mem); + } + if (info->has_total_mem) { + monitor_printf(mon, " total_mem=%" PRId64, info->total_mem); + } + + monitor_printf(mon, "\n"); + + qapi_free_BalloonInfo(info); +} + void hmp_quit(Monitor *mon, const QDict *qdict) { monitor_suspend(mon); diff --git a/hmp.h b/hmp.h index 09f3a01cee..d2c2d88795 100644 --- a/hmp.h +++ b/hmp.h @@ -30,6 +30,7 @@ void hmp_info_block(Monitor *mon); void hmp_info_blockstats(Monitor *mon); void hmp_info_vnc(Monitor *mon); void hmp_info_spice(Monitor *mon); +void hmp_info_balloon(Monitor *mon); void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c index 5f8f4bdb9f..e24a2bf1f3 100644 --- a/hw/virtio-balloon.c +++ b/hw/virtio-balloon.c @@ -18,22 +18,14 @@ #include "virtio.h" #include "pc.h" #include "cpu.h" -#include "monitor.h" #include "balloon.h" #include "virtio-balloon.h" #include "kvm.h" -#include "qlist.h" -#include "qint.h" -#include "qstring.h" #if defined(__linux__) #include #endif -/* Disable guest-provided stats by now (https://bugzilla.redhat.com/show_bug.cgi?id=623903) */ -#define ENABLE_GUEST_STATS 0 - - typedef struct VirtIOBalloon { VirtIODevice vdev; @@ -43,8 +35,6 @@ typedef struct VirtIOBalloon uint64_t stats[VIRTIO_BALLOON_S_NR]; VirtQueueElement stats_vq_elem; size_t stats_vq_offset; - MonitorCompletion *stats_callback; - void *stats_opaque_callback_data; DeviceState *qdev; } VirtIOBalloon; @@ -76,31 +66,6 @@ static inline void reset_stats(VirtIOBalloon *dev) for (i = 0; i < VIRTIO_BALLOON_S_NR; dev->stats[i++] = -1); } -static void stat_put(QDict *dict, const char *label, uint64_t val) -{ - if (val != -1) - qdict_put(dict, label, qint_from_int(val)); -} - -static QObject *get_stats_qobject(VirtIOBalloon *dev) -{ - QDict *dict = qdict_new(); - uint64_t actual = ram_size - ((uint64_t) dev->actual << - VIRTIO_BALLOON_PFN_SHIFT); - - stat_put(dict, "actual", actual); -#if ENABLE_GUEST_STATS - stat_put(dict, "mem_swapped_in", dev->stats[VIRTIO_BALLOON_S_SWAP_IN]); - stat_put(dict, "mem_swapped_out", dev->stats[VIRTIO_BALLOON_S_SWAP_OUT]); - stat_put(dict, "major_page_faults", dev->stats[VIRTIO_BALLOON_S_MAJFLT]); - stat_put(dict, "minor_page_faults", dev->stats[VIRTIO_BALLOON_S_MINFLT]); - stat_put(dict, "free_mem", dev->stats[VIRTIO_BALLOON_S_MEMFREE]); - stat_put(dict, "total_mem", dev->stats[VIRTIO_BALLOON_S_MEMTOT]); -#endif - - return QOBJECT(dict); -} - static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) { VirtIOBalloon *s = to_virtio_balloon(vdev); @@ -131,20 +96,6 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) } } -static void complete_stats_request(VirtIOBalloon *vb) -{ - QObject *stats; - - if (!vb->stats_opaque_callback_data) - return; - - stats = get_stats_qobject(vb); - vb->stats_callback(vb->stats_opaque_callback_data, stats); - qobject_decref(stats); - vb->stats_opaque_callback_data = NULL; - vb->stats_callback = NULL; -} - static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq) { VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev); @@ -172,8 +123,6 @@ static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq) s->stats[tag] = val; } s->stats_vq_offset = offset; - - complete_stats_request(s); } static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data) @@ -202,32 +151,33 @@ static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f) return f; } -static void virtio_balloon_stat(void *opaque, MonitorCompletion cb, - void *cb_data) +static void virtio_balloon_stat(void *opaque, BalloonInfo *info) { VirtIOBalloon *dev = opaque; - /* For now, only allow one request at a time. This restriction can be - * removed later by queueing callback and data pairs. +#if 0 + /* Disable guest-provided stats for now. For more details please check: + * https://bugzilla.redhat.com/show_bug.cgi?id=623903 + * + * If you do enable it (which is probably not going to happen as we + * need a new command for it), remember that you also need to fill the + * appropriate members of the BalloonInfo structure so that the stats + * are returned to the client. */ - if (dev->stats_callback != NULL) { - return; - } - dev->stats_callback = cb; - dev->stats_opaque_callback_data = cb_data; - - if (ENABLE_GUEST_STATS - && (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ))) { + if (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ)) { virtqueue_push(dev->svq, &dev->stats_vq_elem, dev->stats_vq_offset); virtio_notify(&dev->vdev, dev->svq); return; } +#endif /* Stats are not supported. Clear out any stale values that might * have been set by a more featureful guest kernel. */ reset_stats(dev); - complete_stats_request(dev); + + info->actual = ram_size - ((uint64_t) dev->actual << + VIRTIO_BALLOON_PFN_SHIFT); } static void virtio_balloon_to_target(void *opaque, ram_addr_t target) diff --git a/monitor.c b/monitor.c index fc3da382f0..379b7d4a58 100644 --- a/monitor.c +++ b/monitor.c @@ -2904,9 +2904,7 @@ static const mon_cmd_t info_cmds[] = { .args_type = "", .params = "", .help = "show balloon information", - .user_print = monitor_print_balloon, - .mhandler.info_async = do_info_balloon, - .flags = MONITOR_CMD_ASYNC, + .mhandler.info = hmp_info_balloon, }, { .name = "qtree", @@ -2964,15 +2962,6 @@ static const mon_cmd_t qmp_query_cmds[] = { .user_print = do_pci_info_print, .mhandler.info_new = do_pci_info, }, - { - .name = "balloon", - .args_type = "", - .params = "", - .help = "show balloon information", - .user_print = monitor_print_balloon, - .mhandler.info_async = do_info_balloon, - .flags = MONITOR_CMD_ASYNC, - }, { /* NULL */ }, }; diff --git a/qapi-schema.json b/qapi-schema.json index 087a46305e..b2814cd510 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -658,6 +658,50 @@ ## { 'command': 'query-spice', 'returns': 'SpiceInfo' } +## +# @BalloonInfo: +# +# Information about the guest balloon device. +# +# @actual: the number of bytes the balloon currently contains +# +# @mem_swapped_in: #optional number of pages swapped in within the guest +# +# @mem_swapped_out: #optional number of pages swapped out within the guest +# +# @major_page_faults: #optional number of major page faults within the guest +# +# @minor_page_faults: #optional number of minor page faults within the guest +# +# @free_mem: #optional amount of memory (in bytes) free in the guest +# +# @total_mem: #optional amount of memory (in bytes) visible to the guest +# +# Since: 0.14.0 +# +# Notes: all current versions of QEMU do not fill out optional information in +# this structure. +## +{ 'type': 'BalloonInfo', + 'data': {'actual': 'int', '*mem_swapped_in': 'int', + '*mem_swapped_out': 'int', '*major_page_faults': 'int', + '*minor_page_faults': 'int', '*free_mem': 'int', + '*total_mem': 'int'} } + +## +# @query-balloon: +# +# Return information about the balloon device. +# +# Returns: @BalloonInfo on success +# If the balloon driver is enabled but not functional because the KVM +# kernel module cannot support it, KvmMissingCap +# If no balloon device is present, DeviceNotActive +# +# Since: 0.14.0 +## +{ 'command': 'query-balloon', 'returns': 'BalloonInfo' } + ## # @quit: # diff --git a/qmp-commands.hx b/qmp-commands.hx index e99c240f1a..8ef6ca276a 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1989,3 +1989,8 @@ Example: EQMP + { + .name = "query-balloon", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_balloon, + }, -- cgit v1.2.1 From 79627472db3629de66fe81019560aa9cb6900268 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 21 Oct 2011 14:15:33 -0200 Subject: qapi: Convert query-pci This also fixes a bug with the old version: QMP would invert device id and vendor id. This would look ok on HMP because it was printing "device:vendor" instead of "vendor:device". Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- hmp.c | 101 +++++++++++++++++ hmp.h | 1 + hw/pci-stub.c | 15 ++- hw/pci.c | 322 +++++++++++++++++++++---------------------------------- hw/pci.h | 4 - monitor.c | 11 +- qapi-schema.json | 128 ++++++++++++++++++++++ qmp-commands.hx | 6 ++ 8 files changed, 363 insertions(+), 225 deletions(-) diff --git a/hmp.c b/hmp.c index e0b40b16e5..443d3a7ff4 100644 --- a/hmp.c +++ b/hmp.c @@ -388,6 +388,107 @@ void hmp_info_balloon(Monitor *mon) qapi_free_BalloonInfo(info); } +static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev) +{ + PciMemoryRegionList *region; + + monitor_printf(mon, " Bus %2" PRId64 ", ", dev->bus); + monitor_printf(mon, "device %3" PRId64 ", function %" PRId64 ":\n", + dev->slot, dev->function); + monitor_printf(mon, " "); + + if (dev->class_info.has_desc) { + monitor_printf(mon, "%s", dev->class_info.desc); + } else { + monitor_printf(mon, "Class %04" PRId64, dev->class_info.class); + } + + monitor_printf(mon, ": PCI device %04" PRIx64 ":%04" PRIx64 "\n", + dev->id.vendor, dev->id.device); + + if (dev->has_irq) { + monitor_printf(mon, " IRQ %" PRId64 ".\n", dev->irq); + } + + if (dev->has_pci_bridge) { + monitor_printf(mon, " BUS %" PRId64 ".\n", + dev->pci_bridge->bus.number); + monitor_printf(mon, " secondary bus %" PRId64 ".\n", + dev->pci_bridge->bus.secondary); + monitor_printf(mon, " subordinate bus %" PRId64 ".\n", + dev->pci_bridge->bus.subordinate); + + monitor_printf(mon, " IO range [0x%04"PRIx64", 0x%04"PRIx64"]\n", + dev->pci_bridge->bus.io_range->base, + dev->pci_bridge->bus.io_range->limit); + + monitor_printf(mon, + " memory range [0x%08"PRIx64", 0x%08"PRIx64"]\n", + dev->pci_bridge->bus.memory_range->base, + dev->pci_bridge->bus.memory_range->limit); + + monitor_printf(mon, " prefetchable memory range " + "[0x%08"PRIx64", 0x%08"PRIx64"]\n", + dev->pci_bridge->bus.prefetchable_range->base, + dev->pci_bridge->bus.prefetchable_range->limit); + } + + for (region = dev->regions; region; region = region->next) { + uint64_t addr, size; + + addr = region->value->address; + size = region->value->size; + + monitor_printf(mon, " BAR%" PRId64 ": ", region->value->bar); + + if (!strcmp(region->value->type, "io")) { + monitor_printf(mon, "I/O at 0x%04" PRIx64 + " [0x%04" PRIx64 "].\n", + addr, addr + size - 1); + } else { + monitor_printf(mon, "%d bit%s memory at 0x%08" PRIx64 + " [0x%08" PRIx64 "].\n", + region->value->mem_type_64 ? 64 : 32, + region->value->prefetch ? " prefetchable" : "", + addr, addr + size - 1); + } + } + + monitor_printf(mon, " id \"%s\"\n", dev->qdev_id); + + if (dev->has_pci_bridge) { + if (dev->pci_bridge->has_devices) { + PciDeviceInfoList *cdev; + for (cdev = dev->pci_bridge->devices; cdev; cdev = cdev->next) { + hmp_info_pci_device(mon, cdev->value); + } + } + } +} + +void hmp_info_pci(Monitor *mon) +{ + PciInfoList *info; + Error *err = NULL; + + info = qmp_query_pci(&err); + if (err) { + monitor_printf(mon, "PCI devices not supported\n"); + error_free(err); + return; + } + + for (; info; info = info->next) { + PciDeviceInfoList *dev; + + for (dev = info->value->devices; dev; dev = dev->next) { + hmp_info_pci_device(mon, dev->value); + } + } + + qapi_free_PciInfoList(info); +} + void hmp_quit(Monitor *mon, const QDict *qdict) { monitor_suspend(mon); diff --git a/hmp.h b/hmp.h index d2c2d88795..4422578448 100644 --- a/hmp.h +++ b/hmp.h @@ -31,6 +31,7 @@ void hmp_info_blockstats(Monitor *mon); void hmp_info_vnc(Monitor *mon); void hmp_info_spice(Monitor *mon); void hmp_info_balloon(Monitor *mon); +void hmp_info_pci(Monitor *mon); void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); diff --git a/hw/pci-stub.c b/hw/pci-stub.c index 1fb105d51c..636171c16f 100644 --- a/hw/pci-stub.c +++ b/hw/pci-stub.c @@ -21,20 +21,17 @@ #include "sysemu.h" #include "monitor.h" #include "pci.h" +#include "qmp-commands.h" -static void pci_error_message(Monitor *mon) +PciInfoList *qmp_query_pci(Error **errp) { - monitor_printf(mon, "PCI devices not supported\n"); + error_set(errp, QERR_UNSUPPORTED); + return NULL; } -void do_pci_info(Monitor *mon, QObject **ret_data) -{ - pci_error_message(mon); -} - -void do_pci_info_print(Monitor *mon, const QObject *data) +static void pci_error_message(Monitor *mon) { - pci_error_message(mon); + monitor_printf(mon, "PCI devices not supported\n"); } int do_pcie_aer_inejct_error(Monitor *mon, diff --git a/hw/pci.c b/hw/pci.c index e8cc1b046f..399227fc3d 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -29,8 +29,8 @@ #include "net.h" #include "sysemu.h" #include "loader.h" -#include "qemu-objects.h" #include "range.h" +#include "qmp-commands.h" //#define DEBUG_PCI #ifdef DEBUG_PCI @@ -1164,276 +1164,194 @@ void pci_for_each_device(PCIBus *bus, int bus_num, } } -static void pci_device_print(Monitor *mon, QDict *device) +static const pci_class_desc *get_class_desc(int class) { - QDict *qdict; - QListEntry *entry; - uint64_t addr, size; - - monitor_printf(mon, " Bus %2" PRId64 ", ", qdict_get_int(device, "bus")); - monitor_printf(mon, "device %3" PRId64 ", function %" PRId64 ":\n", - qdict_get_int(device, "slot"), - qdict_get_int(device, "function")); - monitor_printf(mon, " "); - - qdict = qdict_get_qdict(device, "class_info"); - if (qdict_haskey(qdict, "desc")) { - monitor_printf(mon, "%s", qdict_get_str(qdict, "desc")); - } else { - monitor_printf(mon, "Class %04" PRId64, qdict_get_int(qdict, "class")); - } - - qdict = qdict_get_qdict(device, "id"); - monitor_printf(mon, ": PCI device %04" PRIx64 ":%04" PRIx64 "\n", - qdict_get_int(qdict, "device"), - qdict_get_int(qdict, "vendor")); + const pci_class_desc *desc; - if (qdict_haskey(device, "irq")) { - monitor_printf(mon, " IRQ %" PRId64 ".\n", - qdict_get_int(device, "irq")); + desc = pci_class_descriptions; + while (desc->desc && class != desc->class) { + desc++; } - if (qdict_haskey(device, "pci_bridge")) { - QDict *info; - - qdict = qdict_get_qdict(device, "pci_bridge"); - - info = qdict_get_qdict(qdict, "bus"); - monitor_printf(mon, " BUS %" PRId64 ".\n", - qdict_get_int(info, "number")); - monitor_printf(mon, " secondary bus %" PRId64 ".\n", - qdict_get_int(info, "secondary")); - monitor_printf(mon, " subordinate bus %" PRId64 ".\n", - qdict_get_int(info, "subordinate")); + return desc; +} - info = qdict_get_qdict(qdict, "io_range"); - monitor_printf(mon, " IO range [0x%04"PRIx64", 0x%04"PRIx64"]\n", - qdict_get_int(info, "base"), - qdict_get_int(info, "limit")); +static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num); - info = qdict_get_qdict(qdict, "memory_range"); - monitor_printf(mon, - " memory range [0x%08"PRIx64", 0x%08"PRIx64"]\n", - qdict_get_int(info, "base"), - qdict_get_int(info, "limit")); +static PciMemoryRegionList *qmp_query_pci_regions(const PCIDevice *dev) +{ + PciMemoryRegionList *head = NULL, *cur_item = NULL; + int i; - info = qdict_get_qdict(qdict, "prefetchable_range"); - monitor_printf(mon, " prefetchable memory range " - "[0x%08"PRIx64", 0x%08"PRIx64"]\n", - qdict_get_int(info, "base"), - qdict_get_int(info, "limit")); - } + for (i = 0; i < PCI_NUM_REGIONS; i++) { + const PCIIORegion *r = &dev->io_regions[i]; + PciMemoryRegionList *region; - QLIST_FOREACH_ENTRY(qdict_get_qlist(device, "regions"), entry) { - qdict = qobject_to_qdict(qlist_entry_obj(entry)); - monitor_printf(mon, " BAR%d: ", (int) qdict_get_int(qdict, "bar")); + if (!r->size) { + continue; + } - addr = qdict_get_int(qdict, "address"); - size = qdict_get_int(qdict, "size"); + region = g_malloc0(sizeof(*region)); + region->value = g_malloc0(sizeof(*region->value)); - if (!strcmp(qdict_get_str(qdict, "type"), "io")) { - monitor_printf(mon, "I/O at 0x%04"FMT_PCIBUS - " [0x%04"FMT_PCIBUS"].\n", - addr, addr + size - 1); + if (r->type & PCI_BASE_ADDRESS_SPACE_IO) { + region->value->type = g_strdup("io"); } else { - monitor_printf(mon, "%d bit%s memory at 0x%08"FMT_PCIBUS - " [0x%08"FMT_PCIBUS"].\n", - qdict_get_bool(qdict, "mem_type_64") ? 64 : 32, - qdict_get_bool(qdict, "prefetch") ? - " prefetchable" : "", addr, addr + size - 1); + region->value->type = g_strdup("memory"); + region->value->has_prefetch = true; + region->value->prefetch = !!(r->type & PCI_BASE_ADDRESS_MEM_PREFETCH); + region->value->has_mem_type_64 = true; + region->value->mem_type_64 = !!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64); } - } - monitor_printf(mon, " id \"%s\"\n", qdict_get_str(device, "qdev_id")); + region->value->bar = i; + region->value->address = r->addr; + region->value->size = r->size; - if (qdict_haskey(device, "pci_bridge")) { - qdict = qdict_get_qdict(device, "pci_bridge"); - if (qdict_haskey(qdict, "devices")) { - QListEntry *dev; - QLIST_FOREACH_ENTRY(qdict_get_qlist(qdict, "devices"), dev) { - pci_device_print(mon, qobject_to_qdict(qlist_entry_obj(dev))); - } + /* XXX: waiting for the qapi to support GSList */ + if (!cur_item) { + head = cur_item = region; + } else { + cur_item->next = region; + cur_item = region; } } -} - -void do_pci_info_print(Monitor *mon, const QObject *data) -{ - QListEntry *bus, *dev; - QLIST_FOREACH_ENTRY(qobject_to_qlist(data), bus) { - QDict *qdict = qobject_to_qdict(qlist_entry_obj(bus)); - QLIST_FOREACH_ENTRY(qdict_get_qlist(qdict, "devices"), dev) { - pci_device_print(mon, qobject_to_qdict(qlist_entry_obj(dev))); - } - } + return head; } -static QObject *pci_get_dev_class(const PCIDevice *dev) +static PciBridgeInfo *qmp_query_pci_bridge(PCIDevice *dev, PCIBus *bus, + int bus_num) { - int class; - const pci_class_desc *desc; + PciBridgeInfo *info; - class = pci_get_word(dev->config + PCI_CLASS_DEVICE); - desc = pci_class_descriptions; - while (desc->desc && class != desc->class) - desc++; + info = g_malloc0(sizeof(*info)); - if (desc->desc) { - return qobject_from_jsonf("{ 'desc': %s, 'class': %d }", - desc->desc, class); - } else { - return qobject_from_jsonf("{ 'class': %d }", class); - } -} + info->bus.number = dev->config[PCI_PRIMARY_BUS]; + info->bus.secondary = dev->config[PCI_SECONDARY_BUS]; + info->bus.subordinate = dev->config[PCI_SUBORDINATE_BUS]; -static QObject *pci_get_dev_id(const PCIDevice *dev) -{ - return qobject_from_jsonf("{ 'device': %d, 'vendor': %d }", - pci_get_word(dev->config + PCI_VENDOR_ID), - pci_get_word(dev->config + PCI_DEVICE_ID)); -} + info->bus.io_range = g_malloc0(sizeof(*info->bus.io_range)); + info->bus.io_range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO); + info->bus.io_range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO); -static QObject *pci_get_regions_list(const PCIDevice *dev) -{ - int i; - QList *regions_list; - - regions_list = qlist_new(); - - for (i = 0; i < PCI_NUM_REGIONS; i++) { - QObject *obj; - const PCIIORegion *r = &dev->io_regions[i]; + info->bus.memory_range = g_malloc0(sizeof(*info->bus.memory_range)); + info->bus.memory_range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY); + info->bus.memory_range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY); - if (!r->size) { - continue; - } + info->bus.prefetchable_range = g_malloc0(sizeof(*info->bus.prefetchable_range)); + info->bus.prefetchable_range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); + info->bus.prefetchable_range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); - if (r->type & PCI_BASE_ADDRESS_SPACE_IO) { - obj = qobject_from_jsonf("{ 'bar': %d, 'type': 'io', " - "'address': %" PRId64 ", " - "'size': %" PRId64 " }", - i, r->addr, r->size); - } else { - int mem_type_64 = r->type & PCI_BASE_ADDRESS_MEM_TYPE_64; - - obj = qobject_from_jsonf("{ 'bar': %d, 'type': 'memory', " - "'mem_type_64': %i, 'prefetch': %i, " - "'address': %" PRId64 ", " - "'size': %" PRId64 " }", - i, mem_type_64, - r->type & PCI_BASE_ADDRESS_MEM_PREFETCH, - r->addr, r->size); + if (dev->config[PCI_SECONDARY_BUS] != 0) { + PCIBus *child_bus = pci_find_bus(bus, dev->config[PCI_SECONDARY_BUS]); + if (child_bus) { + info->has_devices = true; + info->devices = qmp_query_pci_devices(child_bus, dev->config[PCI_SECONDARY_BUS]); } - - qlist_append_obj(regions_list, obj); } - return QOBJECT(regions_list); + return info; } -static QObject *pci_get_devices_list(PCIBus *bus, int bus_num); - -static QObject *pci_get_dev_dict(PCIDevice *dev, PCIBus *bus, int bus_num) +static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus, + int bus_num) { + const pci_class_desc *desc; + PciDeviceInfo *info; uint8_t type; - QObject *obj; + int class; + + info = g_malloc0(sizeof(*info)); + info->bus = bus_num; + info->slot = PCI_SLOT(dev->devfn); + info->function = PCI_FUNC(dev->devfn); - obj = qobject_from_jsonf("{ 'bus': %d, 'slot': %d, 'function': %d," "'class_info': %p, 'id': %p, 'regions': %p," - " 'qdev_id': %s }", - bus_num, - PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), - pci_get_dev_class(dev), pci_get_dev_id(dev), - pci_get_regions_list(dev), - dev->qdev.id ? dev->qdev.id : ""); + class = pci_get_word(dev->config + PCI_CLASS_DEVICE); + info->class_info.class = class; + desc = get_class_desc(class); + if (desc->desc) { + info->class_info.has_desc = true; + info->class_info.desc = g_strdup(desc->desc); + } + + info->id.vendor = pci_get_word(dev->config + PCI_VENDOR_ID); + info->id.device = pci_get_word(dev->config + PCI_DEVICE_ID); + info->regions = qmp_query_pci_regions(dev); + info->qdev_id = g_strdup(dev->qdev.id ? dev->qdev.id : ""); if (dev->config[PCI_INTERRUPT_PIN] != 0) { - QDict *qdict = qobject_to_qdict(obj); - qdict_put(qdict, "irq", qint_from_int(dev->config[PCI_INTERRUPT_LINE])); + info->has_irq = true; + info->irq = dev->config[PCI_INTERRUPT_LINE]; } type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION; if (type == PCI_HEADER_TYPE_BRIDGE) { - QDict *qdict; - QObject *pci_bridge; - - pci_bridge = qobject_from_jsonf("{ 'bus': " - "{ 'number': %d, 'secondary': %d, 'subordinate': %d }, " - "'io_range': { 'base': %" PRId64 ", 'limit': %" PRId64 "}, " - "'memory_range': { 'base': %" PRId64 ", 'limit': %" PRId64 "}, " - "'prefetchable_range': { 'base': %" PRId64 ", 'limit': %" PRId64 "} }", - dev->config[PCI_PRIMARY_BUS], dev->config[PCI_SECONDARY_BUS], - dev->config[PCI_SUBORDINATE_BUS], - pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO), - pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO), - pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY), - pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY), - pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY | - PCI_BASE_ADDRESS_MEM_PREFETCH), - pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY | - PCI_BASE_ADDRESS_MEM_PREFETCH)); - - if (dev->config[PCI_SECONDARY_BUS] != 0) { - PCIBus *child_bus = pci_find_bus(bus, dev->config[PCI_SECONDARY_BUS]); - - if (child_bus) { - qdict = qobject_to_qdict(pci_bridge); - qdict_put_obj(qdict, "devices", - pci_get_devices_list(child_bus, - dev->config[PCI_SECONDARY_BUS])); - } - } - qdict = qobject_to_qdict(obj); - qdict_put_obj(qdict, "pci_bridge", pci_bridge); + info->has_pci_bridge = true; + info->pci_bridge = qmp_query_pci_bridge(dev, bus, bus_num); } - return obj; + return info; } -static QObject *pci_get_devices_list(PCIBus *bus, int bus_num) +static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num) { - int devfn; + PciDeviceInfoList *info, *head = NULL, *cur_item = NULL; PCIDevice *dev; - QList *dev_list; - - dev_list = qlist_new(); + int devfn; for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) { dev = bus->devices[devfn]; if (dev) { - qlist_append_obj(dev_list, pci_get_dev_dict(dev, bus, bus_num)); + info = g_malloc0(sizeof(*info)); + info->value = qmp_query_pci_device(dev, bus, bus_num); + + /* XXX: waiting for the qapi to support GSList */ + if (!cur_item) { + head = cur_item = info; + } else { + cur_item->next = info; + cur_item = info; + } } } - return QOBJECT(dev_list); + return head; } -static QObject *pci_get_bus_dict(PCIBus *bus, int bus_num) +static PciInfo *qmp_query_pci_bus(PCIBus *bus, int bus_num) { + PciInfo *info = NULL; + bus = pci_find_bus(bus, bus_num); if (bus) { - return qobject_from_jsonf("{ 'bus': %d, 'devices': %p }", - bus_num, pci_get_devices_list(bus, bus_num)); + info = g_malloc0(sizeof(*info)); + info->bus = bus_num; + info->devices = qmp_query_pci_devices(bus, bus_num); } - return NULL; + return info; } -void do_pci_info(Monitor *mon, QObject **ret_data) +PciInfoList *qmp_query_pci(Error **errp) { - QList *bus_list; + PciInfoList *info, *head = NULL, *cur_item = NULL; struct PCIHostBus *host; - bus_list = qlist_new(); - QLIST_FOREACH(host, &host_buses, next) { - QObject *obj = pci_get_bus_dict(host->bus, 0); - if (obj) { - qlist_append_obj(bus_list, obj); + info = g_malloc0(sizeof(*info)); + info->value = qmp_query_pci_bus(host->bus, 0); + + /* XXX: waiting for the qapi to support GSList */ + if (!cur_item) { + head = cur_item = info; + } else { + cur_item->next = info; + cur_item = info; } } - *ret_data = QOBJECT(bus_list); + return head; } static const char * const pci_nic_models[] = { diff --git a/hw/pci.h b/hw/pci.h index 86a81c8273..98f30f748c 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -2,7 +2,6 @@ #define QEMU_PCI_H #include "qemu-common.h" -#include "qobject.h" #include "qdev.h" #include "memory.h" @@ -271,9 +270,6 @@ int pci_parse_devaddr(const char *addr, int *domp, int *busp, int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp, unsigned *slotp); -void do_pci_info_print(Monitor *mon, const QObject *data); -void do_pci_info(Monitor *mon, QObject **ret_data); - void pci_device_deassert_intx(PCIDevice *dev); static inline void diff --git a/monitor.c b/monitor.c index 379b7d4a58..edcacdad1e 100644 --- a/monitor.c +++ b/monitor.c @@ -2738,8 +2738,7 @@ static const mon_cmd_t info_cmds[] = { .args_type = "", .params = "", .help = "show PCI info", - .user_print = do_pci_info_print, - .mhandler.info_new = do_pci_info, + .mhandler.info = hmp_info_pci, }, #if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC) || \ defined(TARGET_PPC) @@ -2954,14 +2953,6 @@ static const mon_cmd_t qmp_cmds[] = { }; static const mon_cmd_t qmp_query_cmds[] = { - { - .name = "pci", - .args_type = "", - .params = "", - .help = "show PCI info", - .user_print = do_pci_info_print, - .mhandler.info_new = do_pci_info, - }, { /* NULL */ }, }; diff --git a/qapi-schema.json b/qapi-schema.json index b2814cd510..cb1ba776df 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -702,6 +702,134 @@ ## { 'command': 'query-balloon', 'returns': 'BalloonInfo' } +## +# @PciMemoryRange: +# +# A PCI device memory region +# +# @base: the starting address (guest physical) +# +# @limit: the ending address (guest physical) +# +# Since: 0.14.0 +## +{ 'type': 'PciMemoryRange', 'data': {'base': 'int', 'limit': 'int'} } + +## +# @PciMemoryRegion +# +# Information about a PCI device I/O region. +# +# @bar: the index of the Base Address Register for this region +# +# @type: 'io' if the region is a PIO region +# 'memory' if the region is a MMIO region +# +# @prefetch: #optional if @type is 'memory', true if the memory is prefetchable +# +# @mem_type_64: #optional if @type is 'memory', true if the BAR is 64-bit +# +# Since: 0.14.0 +## +{ 'type': 'PciMemoryRegion', + 'data': {'bar': 'int', 'type': 'str', 'address': 'int', 'size': 'int', + '*prefetch': 'bool', '*mem_type_64': 'bool' } } + +## +# @PciBridgeInfo: +# +# Information about a PCI Bridge device +# +# @bus.number: primary bus interface number. This should be the number of the +# bus the device resides on. +# +# @bus.secondary: secondary bus interface number. This is the number of the +# main bus for the bridge +# +# @bus.subordinate: This is the highest number bus that resides below the +# bridge. +# +# @bus.io_range: The PIO range for all devices on this bridge +# +# @bus.memory_range: The MMIO range for all devices on this bridge +# +# @bus.prefetchable_range: The range of prefetchable MMIO for all devices on +# this bridge +# +# @devices: a list of @PciDeviceInfo for each device on this bridge +# +# Since: 0.14.0 +## +{ 'type': 'PciBridgeInfo', + 'data': {'bus': { 'number': 'int', 'secondary': 'int', 'subordinate': 'int', + 'io_range': 'PciMemoryRange', + 'memory_range': 'PciMemoryRange', + 'prefetchable_range': 'PciMemoryRange' }, + '*devices': ['PciDeviceInfo']} } + +## +# @PciDeviceInfo: +# +# Information about a PCI device +# +# @bus: the bus number of the device +# +# @slot: the slot the device is located in +# +# @function: the function of the slot used by the device +# +# @class_info.desc: #optional a string description of the device's class +# +# @class_info.class: the class code of the device +# +# @id.device: the PCI device id +# +# @id.vendor: the PCI vendor id +# +# @irq: #optional if an IRQ is assigned to the device, the IRQ number +# +# @qdev_id: the device name of the PCI device +# +# @pci_bridge: if the device is a PCI bridge, the bridge information +# +# @regions: a list of the PCI I/O regions associated with the device +# +# Notes: the contents of @class_info.desc are not stable and should only be +# treated as informational. +# +# Since: 0.14.0 +## +{ 'type': 'PciDeviceInfo', + 'data': {'bus': 'int', 'slot': 'int', 'function': 'int', + 'class_info': {'*desc': 'str', 'class': 'int'}, + 'id': {'device': 'int', 'vendor': 'int'}, + '*irq': 'int', 'qdev_id': 'str', '*pci_bridge': 'PciBridgeInfo', + 'regions': ['PciMemoryRegion']} } + +## +# @PciInfo: +# +# Information about a PCI bus +# +# @bus: the bus index +# +# @devices: a list of devices on this bus +# +# Since: 0.14.0 +## +{ 'type': 'PciInfo', 'data': {'bus': 'int', 'devices': ['PciDeviceInfo']} } + +## +# @query-pci: +# +# Return information about the PCI bus topology of the guest. +# +# Returns: a list of @PciInfo for each PCI bus +# +# Since: 0.14.0 +## +{ 'command': 'query-pci', 'returns': ['PciInfo'] } + ## # @quit: # diff --git a/qmp-commands.hx b/qmp-commands.hx index 8ef6ca276a..eb3072c504 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1576,6 +1576,12 @@ Note: This example has been shortened as the real response is too long. EQMP + { + .name = "query-pci", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_pci, + }, + SQMP query-kvm --------- -- cgit v1.2.1 From 40e5a01d1add8cca5732dd079c92e9bf4f07d7ff Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 21 Oct 2011 16:15:31 -0200 Subject: QMP: Drop the query commands dispatch table Because QMP development originated in the monitor, it has inherited the monitor's distinction between query- and non-query commands. However, previous commits unified both commands and the distinction is gone. This commit drops the query commands dispatch table and does some simplifications along the way. Signed-off-by: Luiz Capitulino --- monitor.c | 63 +++++---------------------------------------------------------- 1 file changed, 5 insertions(+), 58 deletions(-) diff --git a/monitor.c b/monitor.c index edcacdad1e..1e09b91faf 100644 --- a/monitor.c +++ b/monitor.c @@ -205,7 +205,6 @@ static const mon_cmd_t mon_cmds[]; static const mon_cmd_t info_cmds[]; static const mon_cmd_t qmp_cmds[]; -static const mon_cmd_t qmp_query_cmds[]; Monitor *cur_mon; Monitor *default_mon; @@ -663,11 +662,6 @@ static int qmp_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd, return cmd->mhandler.cmd_async(mon, params, qmp_monitor_complete, mon); } -static void qmp_async_info_handler(Monitor *mon, const mon_cmd_t *cmd) -{ - cmd->mhandler.info_async(mon, qmp_monitor_complete, mon); -} - static void user_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd, const QDict *params) { @@ -738,32 +732,16 @@ help: help_cmd(mon, "info"); } -static CommandInfoList *alloc_cmd_entry(const char *cmd_name) -{ - CommandInfoList *info; - - info = g_malloc0(sizeof(*info)); - info->value = g_malloc0(sizeof(*info->value)); - info->value->name = g_strdup(cmd_name); - - return info; -} - CommandInfoList *qmp_query_commands(Error **errp) { CommandInfoList *info, *cmd_list = NULL; const mon_cmd_t *cmd; for (cmd = qmp_cmds; cmd->name != NULL; cmd++) { - info = alloc_cmd_entry(cmd->name); - info->next = cmd_list; - cmd_list = info; - } + info = g_malloc0(sizeof(*info)); + info->value = g_malloc0(sizeof(*info->value)); + info->value->name = g_strdup(cmd->name); - for (cmd = qmp_query_cmds; cmd->name != NULL; cmd++) { - char buf[128]; - snprintf(buf, sizeof(buf), "query-%s", cmd->name); - info = alloc_cmd_entry(buf); info->next = cmd_list; cmd_list = info; } @@ -2952,10 +2930,6 @@ static const mon_cmd_t qmp_cmds[] = { { /* NULL */ }, }; -static const mon_cmd_t qmp_query_cmds[] = { - { /* NULL */ }, -}; - /*******************************************************************/ static const char *pch; @@ -3750,11 +3724,6 @@ static const mon_cmd_t *monitor_find_command(const char *cmdname) return search_dispatch_table(mon_cmds, cmdname); } -static const mon_cmd_t *qmp_find_query_cmd(const char *info_item) -{ - return search_dispatch_table(qmp_query_cmds, info_item); -} - static const mon_cmd_t *qmp_find_cmd(const char *cmdname) { return search_dispatch_table(qmp_cmds, cmdname); @@ -4678,22 +4647,6 @@ static QDict *qmp_check_input_obj(QObject *input_obj) return input_dict; } -static void qmp_call_query_cmd(Monitor *mon, const mon_cmd_t *cmd) -{ - QObject *ret_data = NULL; - - if (handler_is_async(cmd)) { - qmp_async_info_handler(mon, cmd); - if (monitor_has_error(mon)) { - monitor_protocol_emitter(mon, NULL); - } - } else { - cmd->mhandler.info_new(mon, &ret_data); - monitor_protocol_emitter(mon, ret_data); - qobject_decref(ret_data); - } -} - static void qmp_call_cmd(Monitor *mon, const mon_cmd_t *cmd, const QDict *params) { @@ -4714,10 +4667,9 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) QObject *obj; QDict *input, *args; const mon_cmd_t *cmd; + const char *cmd_name; Monitor *mon = cur_mon; - const char *cmd_name, *query_cmd; - query_cmd = NULL; args = input = NULL; obj = json_parser_parse(tokens, NULL); @@ -4744,9 +4696,6 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) } cmd = qmp_find_cmd(cmd_name); - if (!cmd && strstart(cmd_name, "query-", &query_cmd)) { - cmd = qmp_find_query_cmd(query_cmd); - } if (!cmd) { qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name); goto err_out; @@ -4765,9 +4714,7 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) goto err_out; } - if (query_cmd) { - qmp_call_query_cmd(mon, cmd); - } else if (handler_is_async(cmd)) { + if (handler_is_async(cmd)) { err = qmp_async_cmd_handler(mon, cmd, args); if (err) { /* emit the error response */ -- cgit v1.2.1 From b5c30586c91f15c1d80ad2d56ed1815077719b9b Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 21 Oct 2011 16:24:28 -0200 Subject: Monitor: do_info(): Drop QMP command handling code Previous commits converted all existing QMP commands to the QAPI, now each info command does its own QMP call. Let's then drop all QMP command handling code from do_info(). Signed-off-by: Luiz Capitulino --- monitor.c | 32 +------------------------------- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/monitor.c b/monitor.c index 1e09b91faf..e3c7d0d564 100644 --- a/monitor.c +++ b/monitor.c @@ -123,8 +123,6 @@ typedef struct mon_cmd_t { void (*user_print)(Monitor *mon, const QObject *data); union { void (*info)(Monitor *mon); - void (*info_new)(Monitor *mon, QObject **ret_data); - int (*info_async)(Monitor *mon, MonitorCompletion *cb, void *opaque); 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, @@ -679,21 +677,6 @@ static void user_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd, } } -static void user_async_info_handler(Monitor *mon, const mon_cmd_t *cmd) -{ - 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.info_async(mon, user_monitor_complete, cb_data); - if (ret < 0) { - monitor_resume(mon); - g_free(cb_data); - } -} - static void do_info(Monitor *mon, const QDict *qdict) { const mon_cmd_t *cmd; @@ -712,20 +695,7 @@ static void do_info(Monitor *mon, const QDict *qdict) goto help; } - if (handler_is_async(cmd)) { - user_async_info_handler(mon, cmd); - } else if (handler_is_qobject(cmd)) { - QObject *info_data = NULL; - - cmd->mhandler.info_new(mon, &info_data); - if (info_data) { - cmd->user_print(mon, info_data); - qobject_decref(info_data); - } - } else { - cmd->mhandler.info(mon); - } - + cmd->mhandler.info(mon); return; help: -- cgit v1.2.1 From f795e743bd026471bcf7952d272424f1fd32e83b Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 21 Oct 2011 16:05:43 -0200 Subject: Drop qemu-objects.h from modules that don't require it Previous commits dropped most qobjects usage from qemu modules (now they are a low level interface used by the QAPI). However, some modules still include the qemu-objects.h header file. This commit drops qemu-objects.h from some of those modules and includes qjson.h instead, which is what they actually need. Signed-off-by: Luiz Capitulino --- block.c | 2 +- error.c | 3 ++- vl.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/block.c b/block.c index 551aa80af9..b5c154420f 100644 --- a/block.c +++ b/block.c @@ -27,7 +27,7 @@ #include "monitor.h" #include "block_int.h" #include "module.h" -#include "qemu-objects.h" +#include "qjson.h" #include "qemu-coroutine.h" #include "qmp-commands.h" diff --git a/error.c b/error.c index 68c0039dba..990050f792 100644 --- a/error.c +++ b/error.c @@ -12,8 +12,9 @@ #include "qemu-common.h" #include "error.h" +#include "qjson.h" +#include "qdict.h" #include "error_int.h" -#include "qemu-objects.h" #include "qerror.h" struct Error diff --git a/vl.c b/vl.c index 1ddb17bfd9..fb28ffcdfb 100644 --- a/vl.c +++ b/vl.c @@ -143,9 +143,9 @@ int main(int argc, char **argv) #include "audio/audio.h" #include "migration.h" #include "kvm.h" +#include "qjson.h" #include "qemu-option.h" #include "qemu-config.h" -#include "qemu-objects.h" #include "qemu-options.h" #include "qmp-commands.h" #include "main-loop.h" -- cgit v1.2.1