2011-09-02 19:34:48 +02:00
|
|
|
/*
|
|
|
|
* Human Monitor Interface
|
|
|
|
*
|
|
|
|
* Copyright IBM, Corp. 2011
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Anthony Liguori <aliguori@us.ibm.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2. See
|
|
|
|
* the COPYING file in the top-level directory.
|
|
|
|
*
|
2012-01-13 17:44:23 +01:00
|
|
|
* Contributions after 2012-01-13 are licensed under the terms of the
|
|
|
|
* GNU GPL, version 2 or (at your option) any later version.
|
2011-09-02 19:34:48 +02:00
|
|
|
*/
|
|
|
|
|
2016-01-29 18:50:05 +01:00
|
|
|
#include "qemu/osdep.h"
|
2011-09-02 19:34:48 +02:00
|
|
|
#include "hmp.h"
|
2012-10-24 08:43:34 +02:00
|
|
|
#include "net/net.h"
|
2015-06-11 03:21:21 +02:00
|
|
|
#include "net/eth.h"
|
2013-04-08 16:55:25 +02:00
|
|
|
#include "sysemu/char.h"
|
2015-02-05 19:58:22 +01:00
|
|
|
#include "sysemu/block-backend.h"
|
2012-12-17 18:20:00 +01:00
|
|
|
#include "qemu/option.h"
|
|
|
|
#include "qemu/timer.h"
|
2011-09-02 19:34:48 +02:00
|
|
|
#include "qmp-commands.h"
|
2012-12-17 18:20:00 +01:00
|
|
|
#include "qemu/sockets.h"
|
2012-12-17 18:19:49 +01:00
|
|
|
#include "monitor/monitor.h"
|
2015-03-05 17:24:48 +01:00
|
|
|
#include "monitor/qdev.h"
|
2013-12-20 23:21:10 +01:00
|
|
|
#include "qapi/opts-visitor.h"
|
2015-03-17 17:22:46 +01:00
|
|
|
#include "qapi/qmp/qerror.h"
|
2014-05-14 11:43:35 +02:00
|
|
|
#include "qapi/string-output-visitor.h"
|
2015-10-26 21:39:18 +01:00
|
|
|
#include "qapi/util.h"
|
2014-05-14 11:43:35 +02:00
|
|
|
#include "qapi-visit.h"
|
2016-02-10 19:40:59 +01:00
|
|
|
#include "qom/object_interfaces.h"
|
2012-11-28 12:06:30 +01:00
|
|
|
#include "ui/console.h"
|
2013-06-06 06:28:00 +02:00
|
|
|
#include "block/qapi.h"
|
2013-06-05 14:19:41 +02:00
|
|
|
#include "qemu-io.h"
|
2016-03-20 18:16:19 +01:00
|
|
|
#include "qemu/cutils.h"
|
migration: add reporting of errors for outgoing migration
Currently if an application initiates an outgoing migration,
it may or may not, get an error reported back on failure. If
the error occurs synchronously to the 'migrate' command
execution, the client app will see the error message. This
is the case for DNS lookup failures. If the error occurs
asynchronously to the monitor command though, the error
will be thrown away and the client left guessing about
what went wrong. This is the case for failure to connect
to the TCP server (eg due to wrong port, or firewall
rules, or other similar errors).
In the future we'll be adding more scope for errors to
happen asynchronously with the TLS protocol handshake.
TLS errors are hard to diagnose even when they are well
reported, so discarding errors entirely will make it
impossible to debug TLS connection problems.
Management apps which do migration are already using
'query-migrate' / 'info migrate' to check up on progress
of background migration operations and to see their end
status. This is a fine place to also include the error
message when things go wrong.
This patch thus adds an 'error-desc' field to the
MigrationInfo struct, which will be populated when
the 'status' is set to 'failed':
(qemu) migrate -d tcp:localhost:9001
(qemu) info migrate
capabilities: xbzrle: off rdma-pin-all: off auto-converge: off zero-blocks: off compress: off events: off x-postcopy-ram: off
Migration status: failed (Error connecting to socket: Connection refused)
total time: 0 milliseconds
In the HMP, when doing non-detached migration, it is
also possible to display this error message directly
to the app.
(qemu) migrate tcp:localhost:9001
Error connecting to socket: Connection refused
Or with QMP
{
"execute": "query-migrate",
"arguments": {}
}
{
"return": {
"status": "failed",
"error-desc": "address resolution failed for myhost:9000: No address associated with hostname"
}
}
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Message-Id: <1461751518-12128-11-git-send-email-berrange@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
2016-04-27 12:05:00 +02:00
|
|
|
#include "qemu/error-report.h"
|
2011-09-02 19:34:48 +02:00
|
|
|
|
2015-03-01 15:29:18 +01:00
|
|
|
#ifdef CONFIG_SPICE
|
|
|
|
#include <spice/enums.h>
|
|
|
|
#endif
|
|
|
|
|
2011-11-22 19:32:37 +01:00
|
|
|
static void hmp_handle_error(Monitor *mon, Error **errp)
|
|
|
|
{
|
2014-05-02 13:26:34 +02:00
|
|
|
assert(errp);
|
|
|
|
if (*errp) {
|
error: Use error_report_err() instead of monitor_printf()
Both error_report_err() and monitor_printf() print to the same
destination when monitor_printf() is used correctly, i.e. within an
HMP monitor. Elsewhere, monitor_printf() does nothing, while
error_report_err() reports to stderr.
Most changed functions are HMP command handlers. These should only
run within an HMP monitor. The one exception is bdrv_password_cb(),
which should also only run within an HMP monitor.
Four command handlers prefix the error message with the command name:
balloon, migrate_set_capability, migrate_set_parameter, migrate.
Pointless, drop.
Unlike monitor_printf(), error_report_err() uses the error whole
instead of just its message obtained with error_get_pretty(). This
avoids suppressing its hint (see commit 50b7b00). Example:
(qemu) device_add ivshmem,id=666
Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Try "help device_add" for more information
The "Identifiers consist of..." line is new with this patch.
Coccinelle semantic patch:
@@
expression M, E;
@@
- monitor_printf(M, "%s\n", error_get_pretty(E));
- error_free(E);
+ error_report_err(E);
@r1@
expression M, E;
format F;
position p;
@@
- monitor_printf(M, "...%@F@\n", error_get_pretty(E));@p
- error_free(E);
+ error_report_err(E);
@script:python@
p << r1.p;
@@
print "%s:%s:%s: prefix dropped" % (p[0].file, p[0].line, p[0].column)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1450452927-8346-4-git-send-email-armbru@redhat.com>
2015-12-18 16:35:06 +01:00
|
|
|
error_report_err(*errp);
|
2011-11-22 19:32:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_name(Monitor *mon, const QDict *qdict)
|
2011-09-02 19:34:48 +02:00
|
|
|
{
|
|
|
|
NameInfo *info;
|
|
|
|
|
|
|
|
info = qmp_query_name(NULL);
|
|
|
|
if (info->has_name) {
|
|
|
|
monitor_printf(mon, "%s\n", info->name);
|
|
|
|
}
|
|
|
|
qapi_free_NameInfo(info);
|
|
|
|
}
|
2011-08-26 22:38:13 +02:00
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_version(Monitor *mon, const QDict *qdict)
|
2011-08-26 22:38:13 +02:00
|
|
|
{
|
|
|
|
VersionInfo *info;
|
|
|
|
|
|
|
|
info = qmp_query_version(NULL);
|
|
|
|
|
|
|
|
monitor_printf(mon, "%" PRId64 ".%" PRId64 ".%" PRId64 "%s\n",
|
2015-05-04 17:05:31 +02:00
|
|
|
info->qemu->major, info->qemu->minor, info->qemu->micro,
|
2011-08-26 22:38:13 +02:00
|
|
|
info->package);
|
|
|
|
|
|
|
|
qapi_free_VersionInfo(info);
|
|
|
|
}
|
2011-09-12 20:10:53 +02:00
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_kvm(Monitor *mon, const QDict *qdict)
|
2011-09-12 20:10:53 +02:00
|
|
|
{
|
|
|
|
KvmInfo *info;
|
|
|
|
|
|
|
|
info = qmp_query_kvm(NULL);
|
|
|
|
monitor_printf(mon, "kvm support: ");
|
|
|
|
if (info->present) {
|
|
|
|
monitor_printf(mon, "%s\n", info->enabled ? "enabled" : "disabled");
|
|
|
|
} else {
|
|
|
|
monitor_printf(mon, "not compiled\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_KvmInfo(info);
|
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_status(Monitor *mon, const QDict *qdict)
|
2011-09-12 22:54:20 +02:00
|
|
|
{
|
|
|
|
StatusInfo *info;
|
|
|
|
|
|
|
|
info = qmp_query_status(NULL);
|
|
|
|
|
|
|
|
monitor_printf(mon, "VM status: %s%s",
|
|
|
|
info->running ? "running" : "paused",
|
|
|
|
info->singlestep ? " (single step mode)" : "");
|
|
|
|
|
|
|
|
if (!info->running && info->status != RUN_STATE_PAUSED) {
|
|
|
|
monitor_printf(mon, " (%s)", RunState_lookup[info->status]);
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
|
|
|
|
qapi_free_StatusInfo(info);
|
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_uuid(Monitor *mon, const QDict *qdict)
|
2011-09-13 22:16:25 +02:00
|
|
|
{
|
|
|
|
UuidInfo *info;
|
|
|
|
|
|
|
|
info = qmp_query_uuid(NULL);
|
|
|
|
monitor_printf(mon, "%s\n", info->UUID);
|
|
|
|
qapi_free_UuidInfo(info);
|
|
|
|
}
|
2011-09-14 21:05:49 +02:00
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_chardev(Monitor *mon, const QDict *qdict)
|
2011-09-14 21:05:49 +02:00
|
|
|
{
|
|
|
|
ChardevInfoList *char_info, *info;
|
|
|
|
|
|
|
|
char_info = qmp_query_chardev(NULL);
|
|
|
|
for (info = char_info; info; info = info->next) {
|
|
|
|
monitor_printf(mon, "%s: filename=%s\n", info->value->label,
|
|
|
|
info->value->filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_ChardevInfoList(char_info);
|
|
|
|
}
|
2011-09-15 19:20:28 +02:00
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_mice(Monitor *mon, const QDict *qdict)
|
2011-09-21 20:29:55 +02:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_migrate(Monitor *mon, const QDict *qdict)
|
2011-09-13 22:37:16 +02:00
|
|
|
{
|
|
|
|
MigrationInfo *info;
|
2012-08-06 20:42:47 +02:00
|
|
|
MigrationCapabilityStatusList *caps, *cap;
|
2011-09-13 22:37:16 +02:00
|
|
|
|
|
|
|
info = qmp_query_migrate(NULL);
|
2012-08-06 20:42:47 +02:00
|
|
|
caps = qmp_query_migrate_capabilities(NULL);
|
|
|
|
|
|
|
|
/* do not display parameters during setup */
|
|
|
|
if (info->has_status && caps) {
|
|
|
|
monitor_printf(mon, "capabilities: ");
|
|
|
|
for (cap = caps; cap; cap = cap->next) {
|
|
|
|
monitor_printf(mon, "%s: %s ",
|
|
|
|
MigrationCapability_lookup[cap->value->capability],
|
|
|
|
cap->value->state ? "on" : "off");
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
}
|
2011-09-13 22:37:16 +02:00
|
|
|
|
|
|
|
if (info->has_status) {
|
migration: add reporting of errors for outgoing migration
Currently if an application initiates an outgoing migration,
it may or may not, get an error reported back on failure. If
the error occurs synchronously to the 'migrate' command
execution, the client app will see the error message. This
is the case for DNS lookup failures. If the error occurs
asynchronously to the monitor command though, the error
will be thrown away and the client left guessing about
what went wrong. This is the case for failure to connect
to the TCP server (eg due to wrong port, or firewall
rules, or other similar errors).
In the future we'll be adding more scope for errors to
happen asynchronously with the TLS protocol handshake.
TLS errors are hard to diagnose even when they are well
reported, so discarding errors entirely will make it
impossible to debug TLS connection problems.
Management apps which do migration are already using
'query-migrate' / 'info migrate' to check up on progress
of background migration operations and to see their end
status. This is a fine place to also include the error
message when things go wrong.
This patch thus adds an 'error-desc' field to the
MigrationInfo struct, which will be populated when
the 'status' is set to 'failed':
(qemu) migrate -d tcp:localhost:9001
(qemu) info migrate
capabilities: xbzrle: off rdma-pin-all: off auto-converge: off zero-blocks: off compress: off events: off x-postcopy-ram: off
Migration status: failed (Error connecting to socket: Connection refused)
total time: 0 milliseconds
In the HMP, when doing non-detached migration, it is
also possible to display this error message directly
to the app.
(qemu) migrate tcp:localhost:9001
Error connecting to socket: Connection refused
Or with QMP
{
"execute": "query-migrate",
"arguments": {}
}
{
"return": {
"status": "failed",
"error-desc": "address resolution failed for myhost:9000: No address associated with hostname"
}
}
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Message-Id: <1461751518-12128-11-git-send-email-berrange@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
2016-04-27 12:05:00 +02:00
|
|
|
monitor_printf(mon, "Migration status: %s",
|
2015-03-13 09:08:40 +01:00
|
|
|
MigrationStatus_lookup[info->status]);
|
migration: add reporting of errors for outgoing migration
Currently if an application initiates an outgoing migration,
it may or may not, get an error reported back on failure. If
the error occurs synchronously to the 'migrate' command
execution, the client app will see the error message. This
is the case for DNS lookup failures. If the error occurs
asynchronously to the monitor command though, the error
will be thrown away and the client left guessing about
what went wrong. This is the case for failure to connect
to the TCP server (eg due to wrong port, or firewall
rules, or other similar errors).
In the future we'll be adding more scope for errors to
happen asynchronously with the TLS protocol handshake.
TLS errors are hard to diagnose even when they are well
reported, so discarding errors entirely will make it
impossible to debug TLS connection problems.
Management apps which do migration are already using
'query-migrate' / 'info migrate' to check up on progress
of background migration operations and to see their end
status. This is a fine place to also include the error
message when things go wrong.
This patch thus adds an 'error-desc' field to the
MigrationInfo struct, which will be populated when
the 'status' is set to 'failed':
(qemu) migrate -d tcp:localhost:9001
(qemu) info migrate
capabilities: xbzrle: off rdma-pin-all: off auto-converge: off zero-blocks: off compress: off events: off x-postcopy-ram: off
Migration status: failed (Error connecting to socket: Connection refused)
total time: 0 milliseconds
In the HMP, when doing non-detached migration, it is
also possible to display this error message directly
to the app.
(qemu) migrate tcp:localhost:9001
Error connecting to socket: Connection refused
Or with QMP
{
"execute": "query-migrate",
"arguments": {}
}
{
"return": {
"status": "failed",
"error-desc": "address resolution failed for myhost:9000: No address associated with hostname"
}
}
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Message-Id: <1461751518-12128-11-git-send-email-berrange@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
2016-04-27 12:05:00 +02:00
|
|
|
if (info->status == MIGRATION_STATUS_FAILED &&
|
|
|
|
info->has_error_desc) {
|
|
|
|
monitor_printf(mon, " (%s)\n", info->error_desc);
|
|
|
|
} else {
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
}
|
|
|
|
|
2012-08-18 13:17:10 +02:00
|
|
|
monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n",
|
|
|
|
info->total_time);
|
2012-08-13 09:53:12 +02:00
|
|
|
if (info->has_expected_downtime) {
|
|
|
|
monitor_printf(mon, "expected downtime: %" PRIu64 " milliseconds\n",
|
|
|
|
info->expected_downtime);
|
|
|
|
}
|
2012-08-13 09:35:16 +02:00
|
|
|
if (info->has_downtime) {
|
|
|
|
monitor_printf(mon, "downtime: %" PRIu64 " milliseconds\n",
|
|
|
|
info->downtime);
|
|
|
|
}
|
2013-07-22 16:01:58 +02:00
|
|
|
if (info->has_setup_time) {
|
|
|
|
monitor_printf(mon, "setup: %" PRIu64 " milliseconds\n",
|
|
|
|
info->setup_time);
|
|
|
|
}
|
2011-09-13 22:37:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (info->has_ram) {
|
|
|
|
monitor_printf(mon, "transferred ram: %" PRIu64 " kbytes\n",
|
|
|
|
info->ram->transferred >> 10);
|
2013-06-26 03:35:30 +02:00
|
|
|
monitor_printf(mon, "throughput: %0.2f mbps\n",
|
|
|
|
info->ram->mbps);
|
2011-09-13 22:37:16 +02:00
|
|
|
monitor_printf(mon, "remaining ram: %" PRIu64 " kbytes\n",
|
|
|
|
info->ram->remaining >> 10);
|
|
|
|
monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n",
|
|
|
|
info->ram->total >> 10);
|
2012-08-06 20:42:56 +02:00
|
|
|
monitor_printf(mon, "duplicate: %" PRIu64 " pages\n",
|
|
|
|
info->ram->duplicate);
|
2013-03-26 10:58:37 +01:00
|
|
|
monitor_printf(mon, "skipped: %" PRIu64 " pages\n",
|
|
|
|
info->ram->skipped);
|
2012-08-06 20:42:56 +02:00
|
|
|
monitor_printf(mon, "normal: %" PRIu64 " pages\n",
|
|
|
|
info->ram->normal);
|
|
|
|
monitor_printf(mon, "normal bytes: %" PRIu64 " kbytes\n",
|
|
|
|
info->ram->normal_bytes >> 10);
|
2014-04-04 11:57:55 +02:00
|
|
|
monitor_printf(mon, "dirty sync count: %" PRIu64 "\n",
|
|
|
|
info->ram->dirty_sync_count);
|
2012-08-13 12:31:25 +02:00
|
|
|
if (info->ram->dirty_pages_rate) {
|
|
|
|
monitor_printf(mon, "dirty pages rate: %" PRIu64 " pages\n",
|
|
|
|
info->ram->dirty_pages_rate);
|
|
|
|
}
|
2011-09-13 22:37:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2012-08-06 20:42:57 +02:00
|
|
|
if (info->has_xbzrle_cache) {
|
|
|
|
monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
|
|
|
|
info->xbzrle_cache->cache_size);
|
|
|
|
monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n",
|
|
|
|
info->xbzrle_cache->bytes >> 10);
|
|
|
|
monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n",
|
|
|
|
info->xbzrle_cache->pages);
|
|
|
|
monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n",
|
|
|
|
info->xbzrle_cache->cache_miss);
|
2014-04-04 11:57:56 +02:00
|
|
|
monitor_printf(mon, "xbzrle cache miss rate: %0.2f\n",
|
|
|
|
info->xbzrle_cache->cache_miss_rate);
|
2012-08-06 20:42:57 +02:00
|
|
|
monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n",
|
|
|
|
info->xbzrle_cache->overflow);
|
|
|
|
}
|
|
|
|
|
2016-04-21 20:07:18 +02:00
|
|
|
if (info->has_cpu_throttle_percentage) {
|
2015-09-08 19:12:36 +02:00
|
|
|
monitor_printf(mon, "cpu throttle percentage: %" PRIu64 "\n",
|
2016-04-21 20:07:18 +02:00
|
|
|
info->cpu_throttle_percentage);
|
2015-09-08 19:12:36 +02:00
|
|
|
}
|
|
|
|
|
2011-09-13 22:37:16 +02:00
|
|
|
qapi_free_MigrationInfo(info);
|
2012-08-06 20:42:47 +02:00
|
|
|
qapi_free_MigrationCapabilityStatusList(caps);
|
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict)
|
2012-08-06 20:42:47 +02:00
|
|
|
{
|
|
|
|
MigrationCapabilityStatusList *caps, *cap;
|
|
|
|
|
|
|
|
caps = qmp_query_migrate_capabilities(NULL);
|
|
|
|
|
|
|
|
if (caps) {
|
|
|
|
monitor_printf(mon, "capabilities: ");
|
|
|
|
for (cap = caps; cap; cap = cap->next) {
|
|
|
|
monitor_printf(mon, "%s: %s ",
|
|
|
|
MigrationCapability_lookup[cap->value->capability],
|
|
|
|
cap->value->state ? "on" : "off");
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_MigrationCapabilityStatusList(caps);
|
2011-09-13 22:37:16 +02:00
|
|
|
}
|
|
|
|
|
2015-03-23 09:32:29 +01:00
|
|
|
void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
MigrationParameters *params;
|
|
|
|
|
|
|
|
params = qmp_query_migrate_parameters(NULL);
|
|
|
|
|
|
|
|
if (params) {
|
|
|
|
monitor_printf(mon, "parameters:");
|
|
|
|
monitor_printf(mon, " %s: %" PRId64,
|
|
|
|
MigrationParameter_lookup[MIGRATION_PARAMETER_COMPRESS_LEVEL],
|
|
|
|
params->compress_level);
|
|
|
|
monitor_printf(mon, " %s: %" PRId64,
|
|
|
|
MigrationParameter_lookup[MIGRATION_PARAMETER_COMPRESS_THREADS],
|
|
|
|
params->compress_threads);
|
|
|
|
monitor_printf(mon, " %s: %" PRId64,
|
|
|
|
MigrationParameter_lookup[MIGRATION_PARAMETER_DECOMPRESS_THREADS],
|
|
|
|
params->decompress_threads);
|
2015-09-08 19:12:34 +02:00
|
|
|
monitor_printf(mon, " %s: %" PRId64,
|
2016-04-21 20:07:18 +02:00
|
|
|
MigrationParameter_lookup[MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL],
|
|
|
|
params->cpu_throttle_initial);
|
2015-09-08 19:12:34 +02:00
|
|
|
monitor_printf(mon, " %s: %" PRId64,
|
2016-04-21 20:07:18 +02:00
|
|
|
MigrationParameter_lookup[MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT],
|
|
|
|
params->cpu_throttle_increment);
|
2015-03-23 09:32:29 +01:00
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_MigrationParameters(params);
|
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_migrate_cache_size(Monitor *mon, const QDict *qdict)
|
2012-08-06 20:42:54 +02:00
|
|
|
{
|
|
|
|
monitor_printf(mon, "xbzrel cache size: %" PRId64 " kbytes\n",
|
|
|
|
qmp_query_migrate_cache_size(NULL) >> 10);
|
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_cpus(Monitor *mon, const QDict *qdict)
|
2011-09-21 21:38:35 +02:00
|
|
|
{
|
|
|
|
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 = '*';
|
|
|
|
}
|
|
|
|
|
2012-10-19 23:19:19 +02:00
|
|
|
monitor_printf(mon, "%c CPU #%" PRId64 ":", active, cpu->value->CPU);
|
2011-09-21 21:38:35 +02:00
|
|
|
|
cpu: Convert CpuInfo into flat union
The CpuInfo struct is used only by the 'query-cpus' output
command, so we are free to modify it by adding fields (clients
are already supposed to ignore unknown output fields), or by
changing optional members to mandatory, while still keeping
QMP wire compatibility with older versions of qemu.
When qapi type CpuInfo was originally created for 0.14, we had
no notion of a flat union, and instead just listed a bunch of
optional fields with documentation about the mutually-exclusive
choice of which instruction pointer field(s) would be provided
for a given architecture. But now that we have flat unions and
introspection, it is better to segregate off which fields will
be provided according to the actual architecture. With this in
place, we no longer need the fields to be optional, because the
choice of the new 'arch' discriminator serves that role.
This has an additional benefit: the old all-in-one struct was
the only place in the code base that had a case-sensitive
naming of members 'pc' vs. 'PC'. Separating these spellings
into different branches of the flat union will allow us to add
restrictions against future case-insensitive collisions, since
that is generally a poor interface practice.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-25-git-send-email-eblake@redhat.com>
[Spelling of CPUInfo{SPARC,PPC,MIPS} fixed]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 09:52:59 +01:00
|
|
|
switch (cpu->value->arch) {
|
|
|
|
case CPU_INFO_ARCH_X86:
|
qapi: Don't box branches of flat unions
There's no reason to do two malloc's for a flat union; let's just
inline the branch struct directly into the C union branch of the
flat union.
Surprisingly, fewer clients were actually using explicit references
to the branch types in comparison to the number of flat unions
thus modified.
This lets us reduce the hack in qapi-types:gen_variants() added in
the previous patch; we no longer need to distinguish between
alternates and flat unions.
The change to unboxed structs means that u.data (added in commit
cee2dedb) is now coincident with random fields of each branch of
the flat union, whereas beforehand it was only coincident with
pointers (since all branches of a flat union have to be objects).
Note that this was already the case for simple unions - but there
we got lucky. Remember, visit_start_union() blindly returns true
for all visitors except for the dealloc visitor, where it returns
the value !!obj->u.data, and that this result then controls
whether to proceed with the visit to the variant. Pre-patch,
this meant that flat unions were testing whether the boxed pointer
was still NULL, and thereby skipping visit_end_implicit_struct()
and avoiding a NULL dereference if the pointer had not been
allocated. The same was true for simple unions where the current
branch had pointer type, except there we bypassed visit_type_FOO().
But for simple unions where the current branch had scalar type, the
contents of that scalar meant that the decision to call
visit_type_FOO() was data-dependent - the reason we got lucky there
is that visit_type_FOO() for all scalar types in the dealloc visitor
is a no-op (only the pointer variants had anything to free), so it
did not matter whether the dealloc visit was skipped. But with this
patch, we would risk leaking memory if we could skip a call to
visit_type_FOO_fields() based solely on a data-dependent decision.
But notice: in the dealloc visitor, visit_type_FOO() already handles
a NULL obj - it was only the visit_type_implicit_FOO() that was
failing to check for NULL. And now that we have refactored things to
have the branch be part of the parent struct, we no longer have a
separate pointer that can be NULL in the first place. So we can just
delete the call to visit_start_union() altogether, and blindly visit
the branch type; there is no change in behavior except to the dealloc
visitor, where we now unconditionally visit the branch, but where that
visit is now always safe (for a flat union, we can no longer
dereference NULL, and for a simple union, visit_type_FOO() was already
safely handling NULL on pointer types).
Unfortunately, simple unions are not as easy to switch to unboxed
layout; because we are special-casing the hidden implicit type with
a single 'data' member, we really DO need to keep calling another
layer of visit_start_struct(), with a second malloc; although there
are some cleanups planned for simple unions in later patches.
visit_start_union() and gen_visit_implicit_struct() are now unused.
Drop them.
Note that after this patch, the only remaining use of
visit_start_implicit_struct() is for alternate types; the next patch
will do further cleanup based on that fact.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-14-git-send-email-eblake@redhat.com>
[Dead code deletion squashed in, commit message updated accordingly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 07:48:27 +01:00
|
|
|
monitor_printf(mon, " pc=0x%016" PRIx64, cpu->value->u.x86.pc);
|
cpu: Convert CpuInfo into flat union
The CpuInfo struct is used only by the 'query-cpus' output
command, so we are free to modify it by adding fields (clients
are already supposed to ignore unknown output fields), or by
changing optional members to mandatory, while still keeping
QMP wire compatibility with older versions of qemu.
When qapi type CpuInfo was originally created for 0.14, we had
no notion of a flat union, and instead just listed a bunch of
optional fields with documentation about the mutually-exclusive
choice of which instruction pointer field(s) would be provided
for a given architecture. But now that we have flat unions and
introspection, it is better to segregate off which fields will
be provided according to the actual architecture. With this in
place, we no longer need the fields to be optional, because the
choice of the new 'arch' discriminator serves that role.
This has an additional benefit: the old all-in-one struct was
the only place in the code base that had a case-sensitive
naming of members 'pc' vs. 'PC'. Separating these spellings
into different branches of the flat union will allow us to add
restrictions against future case-insensitive collisions, since
that is generally a poor interface practice.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-25-git-send-email-eblake@redhat.com>
[Spelling of CPUInfo{SPARC,PPC,MIPS} fixed]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 09:52:59 +01:00
|
|
|
break;
|
|
|
|
case CPU_INFO_ARCH_PPC:
|
qapi: Don't box branches of flat unions
There's no reason to do two malloc's for a flat union; let's just
inline the branch struct directly into the C union branch of the
flat union.
Surprisingly, fewer clients were actually using explicit references
to the branch types in comparison to the number of flat unions
thus modified.
This lets us reduce the hack in qapi-types:gen_variants() added in
the previous patch; we no longer need to distinguish between
alternates and flat unions.
The change to unboxed structs means that u.data (added in commit
cee2dedb) is now coincident with random fields of each branch of
the flat union, whereas beforehand it was only coincident with
pointers (since all branches of a flat union have to be objects).
Note that this was already the case for simple unions - but there
we got lucky. Remember, visit_start_union() blindly returns true
for all visitors except for the dealloc visitor, where it returns
the value !!obj->u.data, and that this result then controls
whether to proceed with the visit to the variant. Pre-patch,
this meant that flat unions were testing whether the boxed pointer
was still NULL, and thereby skipping visit_end_implicit_struct()
and avoiding a NULL dereference if the pointer had not been
allocated. The same was true for simple unions where the current
branch had pointer type, except there we bypassed visit_type_FOO().
But for simple unions where the current branch had scalar type, the
contents of that scalar meant that the decision to call
visit_type_FOO() was data-dependent - the reason we got lucky there
is that visit_type_FOO() for all scalar types in the dealloc visitor
is a no-op (only the pointer variants had anything to free), so it
did not matter whether the dealloc visit was skipped. But with this
patch, we would risk leaking memory if we could skip a call to
visit_type_FOO_fields() based solely on a data-dependent decision.
But notice: in the dealloc visitor, visit_type_FOO() already handles
a NULL obj - it was only the visit_type_implicit_FOO() that was
failing to check for NULL. And now that we have refactored things to
have the branch be part of the parent struct, we no longer have a
separate pointer that can be NULL in the first place. So we can just
delete the call to visit_start_union() altogether, and blindly visit
the branch type; there is no change in behavior except to the dealloc
visitor, where we now unconditionally visit the branch, but where that
visit is now always safe (for a flat union, we can no longer
dereference NULL, and for a simple union, visit_type_FOO() was already
safely handling NULL on pointer types).
Unfortunately, simple unions are not as easy to switch to unboxed
layout; because we are special-casing the hidden implicit type with
a single 'data' member, we really DO need to keep calling another
layer of visit_start_struct(), with a second malloc; although there
are some cleanups planned for simple unions in later patches.
visit_start_union() and gen_visit_implicit_struct() are now unused.
Drop them.
Note that after this patch, the only remaining use of
visit_start_implicit_struct() is for alternate types; the next patch
will do further cleanup based on that fact.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-14-git-send-email-eblake@redhat.com>
[Dead code deletion squashed in, commit message updated accordingly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 07:48:27 +01:00
|
|
|
monitor_printf(mon, " nip=0x%016" PRIx64, cpu->value->u.ppc.nip);
|
cpu: Convert CpuInfo into flat union
The CpuInfo struct is used only by the 'query-cpus' output
command, so we are free to modify it by adding fields (clients
are already supposed to ignore unknown output fields), or by
changing optional members to mandatory, while still keeping
QMP wire compatibility with older versions of qemu.
When qapi type CpuInfo was originally created for 0.14, we had
no notion of a flat union, and instead just listed a bunch of
optional fields with documentation about the mutually-exclusive
choice of which instruction pointer field(s) would be provided
for a given architecture. But now that we have flat unions and
introspection, it is better to segregate off which fields will
be provided according to the actual architecture. With this in
place, we no longer need the fields to be optional, because the
choice of the new 'arch' discriminator serves that role.
This has an additional benefit: the old all-in-one struct was
the only place in the code base that had a case-sensitive
naming of members 'pc' vs. 'PC'. Separating these spellings
into different branches of the flat union will allow us to add
restrictions against future case-insensitive collisions, since
that is generally a poor interface practice.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-25-git-send-email-eblake@redhat.com>
[Spelling of CPUInfo{SPARC,PPC,MIPS} fixed]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 09:52:59 +01:00
|
|
|
break;
|
|
|
|
case CPU_INFO_ARCH_SPARC:
|
2016-02-02 15:51:41 +01:00
|
|
|
monitor_printf(mon, " pc=0x%016" PRIx64,
|
qapi: Don't box branches of flat unions
There's no reason to do two malloc's for a flat union; let's just
inline the branch struct directly into the C union branch of the
flat union.
Surprisingly, fewer clients were actually using explicit references
to the branch types in comparison to the number of flat unions
thus modified.
This lets us reduce the hack in qapi-types:gen_variants() added in
the previous patch; we no longer need to distinguish between
alternates and flat unions.
The change to unboxed structs means that u.data (added in commit
cee2dedb) is now coincident with random fields of each branch of
the flat union, whereas beforehand it was only coincident with
pointers (since all branches of a flat union have to be objects).
Note that this was already the case for simple unions - but there
we got lucky. Remember, visit_start_union() blindly returns true
for all visitors except for the dealloc visitor, where it returns
the value !!obj->u.data, and that this result then controls
whether to proceed with the visit to the variant. Pre-patch,
this meant that flat unions were testing whether the boxed pointer
was still NULL, and thereby skipping visit_end_implicit_struct()
and avoiding a NULL dereference if the pointer had not been
allocated. The same was true for simple unions where the current
branch had pointer type, except there we bypassed visit_type_FOO().
But for simple unions where the current branch had scalar type, the
contents of that scalar meant that the decision to call
visit_type_FOO() was data-dependent - the reason we got lucky there
is that visit_type_FOO() for all scalar types in the dealloc visitor
is a no-op (only the pointer variants had anything to free), so it
did not matter whether the dealloc visit was skipped. But with this
patch, we would risk leaking memory if we could skip a call to
visit_type_FOO_fields() based solely on a data-dependent decision.
But notice: in the dealloc visitor, visit_type_FOO() already handles
a NULL obj - it was only the visit_type_implicit_FOO() that was
failing to check for NULL. And now that we have refactored things to
have the branch be part of the parent struct, we no longer have a
separate pointer that can be NULL in the first place. So we can just
delete the call to visit_start_union() altogether, and blindly visit
the branch type; there is no change in behavior except to the dealloc
visitor, where we now unconditionally visit the branch, but where that
visit is now always safe (for a flat union, we can no longer
dereference NULL, and for a simple union, visit_type_FOO() was already
safely handling NULL on pointer types).
Unfortunately, simple unions are not as easy to switch to unboxed
layout; because we are special-casing the hidden implicit type with
a single 'data' member, we really DO need to keep calling another
layer of visit_start_struct(), with a second malloc; although there
are some cleanups planned for simple unions in later patches.
visit_start_union() and gen_visit_implicit_struct() are now unused.
Drop them.
Note that after this patch, the only remaining use of
visit_start_implicit_struct() is for alternate types; the next patch
will do further cleanup based on that fact.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-14-git-send-email-eblake@redhat.com>
[Dead code deletion squashed in, commit message updated accordingly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 07:48:27 +01:00
|
|
|
cpu->value->u.q_sparc.pc);
|
2016-02-02 15:51:41 +01:00
|
|
|
monitor_printf(mon, " npc=0x%016" PRIx64,
|
qapi: Don't box branches of flat unions
There's no reason to do two malloc's for a flat union; let's just
inline the branch struct directly into the C union branch of the
flat union.
Surprisingly, fewer clients were actually using explicit references
to the branch types in comparison to the number of flat unions
thus modified.
This lets us reduce the hack in qapi-types:gen_variants() added in
the previous patch; we no longer need to distinguish between
alternates and flat unions.
The change to unboxed structs means that u.data (added in commit
cee2dedb) is now coincident with random fields of each branch of
the flat union, whereas beforehand it was only coincident with
pointers (since all branches of a flat union have to be objects).
Note that this was already the case for simple unions - but there
we got lucky. Remember, visit_start_union() blindly returns true
for all visitors except for the dealloc visitor, where it returns
the value !!obj->u.data, and that this result then controls
whether to proceed with the visit to the variant. Pre-patch,
this meant that flat unions were testing whether the boxed pointer
was still NULL, and thereby skipping visit_end_implicit_struct()
and avoiding a NULL dereference if the pointer had not been
allocated. The same was true for simple unions where the current
branch had pointer type, except there we bypassed visit_type_FOO().
But for simple unions where the current branch had scalar type, the
contents of that scalar meant that the decision to call
visit_type_FOO() was data-dependent - the reason we got lucky there
is that visit_type_FOO() for all scalar types in the dealloc visitor
is a no-op (only the pointer variants had anything to free), so it
did not matter whether the dealloc visit was skipped. But with this
patch, we would risk leaking memory if we could skip a call to
visit_type_FOO_fields() based solely on a data-dependent decision.
But notice: in the dealloc visitor, visit_type_FOO() already handles
a NULL obj - it was only the visit_type_implicit_FOO() that was
failing to check for NULL. And now that we have refactored things to
have the branch be part of the parent struct, we no longer have a
separate pointer that can be NULL in the first place. So we can just
delete the call to visit_start_union() altogether, and blindly visit
the branch type; there is no change in behavior except to the dealloc
visitor, where we now unconditionally visit the branch, but where that
visit is now always safe (for a flat union, we can no longer
dereference NULL, and for a simple union, visit_type_FOO() was already
safely handling NULL on pointer types).
Unfortunately, simple unions are not as easy to switch to unboxed
layout; because we are special-casing the hidden implicit type with
a single 'data' member, we really DO need to keep calling another
layer of visit_start_struct(), with a second malloc; although there
are some cleanups planned for simple unions in later patches.
visit_start_union() and gen_visit_implicit_struct() are now unused.
Drop them.
Note that after this patch, the only remaining use of
visit_start_implicit_struct() is for alternate types; the next patch
will do further cleanup based on that fact.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-14-git-send-email-eblake@redhat.com>
[Dead code deletion squashed in, commit message updated accordingly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 07:48:27 +01:00
|
|
|
cpu->value->u.q_sparc.npc);
|
cpu: Convert CpuInfo into flat union
The CpuInfo struct is used only by the 'query-cpus' output
command, so we are free to modify it by adding fields (clients
are already supposed to ignore unknown output fields), or by
changing optional members to mandatory, while still keeping
QMP wire compatibility with older versions of qemu.
When qapi type CpuInfo was originally created for 0.14, we had
no notion of a flat union, and instead just listed a bunch of
optional fields with documentation about the mutually-exclusive
choice of which instruction pointer field(s) would be provided
for a given architecture. But now that we have flat unions and
introspection, it is better to segregate off which fields will
be provided according to the actual architecture. With this in
place, we no longer need the fields to be optional, because the
choice of the new 'arch' discriminator serves that role.
This has an additional benefit: the old all-in-one struct was
the only place in the code base that had a case-sensitive
naming of members 'pc' vs. 'PC'. Separating these spellings
into different branches of the flat union will allow us to add
restrictions against future case-insensitive collisions, since
that is generally a poor interface practice.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-25-git-send-email-eblake@redhat.com>
[Spelling of CPUInfo{SPARC,PPC,MIPS} fixed]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 09:52:59 +01:00
|
|
|
break;
|
|
|
|
case CPU_INFO_ARCH_MIPS:
|
qapi: Don't box branches of flat unions
There's no reason to do two malloc's for a flat union; let's just
inline the branch struct directly into the C union branch of the
flat union.
Surprisingly, fewer clients were actually using explicit references
to the branch types in comparison to the number of flat unions
thus modified.
This lets us reduce the hack in qapi-types:gen_variants() added in
the previous patch; we no longer need to distinguish between
alternates and flat unions.
The change to unboxed structs means that u.data (added in commit
cee2dedb) is now coincident with random fields of each branch of
the flat union, whereas beforehand it was only coincident with
pointers (since all branches of a flat union have to be objects).
Note that this was already the case for simple unions - but there
we got lucky. Remember, visit_start_union() blindly returns true
for all visitors except for the dealloc visitor, where it returns
the value !!obj->u.data, and that this result then controls
whether to proceed with the visit to the variant. Pre-patch,
this meant that flat unions were testing whether the boxed pointer
was still NULL, and thereby skipping visit_end_implicit_struct()
and avoiding a NULL dereference if the pointer had not been
allocated. The same was true for simple unions where the current
branch had pointer type, except there we bypassed visit_type_FOO().
But for simple unions where the current branch had scalar type, the
contents of that scalar meant that the decision to call
visit_type_FOO() was data-dependent - the reason we got lucky there
is that visit_type_FOO() for all scalar types in the dealloc visitor
is a no-op (only the pointer variants had anything to free), so it
did not matter whether the dealloc visit was skipped. But with this
patch, we would risk leaking memory if we could skip a call to
visit_type_FOO_fields() based solely on a data-dependent decision.
But notice: in the dealloc visitor, visit_type_FOO() already handles
a NULL obj - it was only the visit_type_implicit_FOO() that was
failing to check for NULL. And now that we have refactored things to
have the branch be part of the parent struct, we no longer have a
separate pointer that can be NULL in the first place. So we can just
delete the call to visit_start_union() altogether, and blindly visit
the branch type; there is no change in behavior except to the dealloc
visitor, where we now unconditionally visit the branch, but where that
visit is now always safe (for a flat union, we can no longer
dereference NULL, and for a simple union, visit_type_FOO() was already
safely handling NULL on pointer types).
Unfortunately, simple unions are not as easy to switch to unboxed
layout; because we are special-casing the hidden implicit type with
a single 'data' member, we really DO need to keep calling another
layer of visit_start_struct(), with a second malloc; although there
are some cleanups planned for simple unions in later patches.
visit_start_union() and gen_visit_implicit_struct() are now unused.
Drop them.
Note that after this patch, the only remaining use of
visit_start_implicit_struct() is for alternate types; the next patch
will do further cleanup based on that fact.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-14-git-send-email-eblake@redhat.com>
[Dead code deletion squashed in, commit message updated accordingly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 07:48:27 +01:00
|
|
|
monitor_printf(mon, " PC=0x%016" PRIx64, cpu->value->u.q_mips.PC);
|
cpu: Convert CpuInfo into flat union
The CpuInfo struct is used only by the 'query-cpus' output
command, so we are free to modify it by adding fields (clients
are already supposed to ignore unknown output fields), or by
changing optional members to mandatory, while still keeping
QMP wire compatibility with older versions of qemu.
When qapi type CpuInfo was originally created for 0.14, we had
no notion of a flat union, and instead just listed a bunch of
optional fields with documentation about the mutually-exclusive
choice of which instruction pointer field(s) would be provided
for a given architecture. But now that we have flat unions and
introspection, it is better to segregate off which fields will
be provided according to the actual architecture. With this in
place, we no longer need the fields to be optional, because the
choice of the new 'arch' discriminator serves that role.
This has an additional benefit: the old all-in-one struct was
the only place in the code base that had a case-sensitive
naming of members 'pc' vs. 'PC'. Separating these spellings
into different branches of the flat union will allow us to add
restrictions against future case-insensitive collisions, since
that is generally a poor interface practice.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-25-git-send-email-eblake@redhat.com>
[Spelling of CPUInfo{SPARC,PPC,MIPS} fixed]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 09:52:59 +01:00
|
|
|
break;
|
|
|
|
case CPU_INFO_ARCH_TRICORE:
|
qapi: Don't box branches of flat unions
There's no reason to do two malloc's for a flat union; let's just
inline the branch struct directly into the C union branch of the
flat union.
Surprisingly, fewer clients were actually using explicit references
to the branch types in comparison to the number of flat unions
thus modified.
This lets us reduce the hack in qapi-types:gen_variants() added in
the previous patch; we no longer need to distinguish between
alternates and flat unions.
The change to unboxed structs means that u.data (added in commit
cee2dedb) is now coincident with random fields of each branch of
the flat union, whereas beforehand it was only coincident with
pointers (since all branches of a flat union have to be objects).
Note that this was already the case for simple unions - but there
we got lucky. Remember, visit_start_union() blindly returns true
for all visitors except for the dealloc visitor, where it returns
the value !!obj->u.data, and that this result then controls
whether to proceed with the visit to the variant. Pre-patch,
this meant that flat unions were testing whether the boxed pointer
was still NULL, and thereby skipping visit_end_implicit_struct()
and avoiding a NULL dereference if the pointer had not been
allocated. The same was true for simple unions where the current
branch had pointer type, except there we bypassed visit_type_FOO().
But for simple unions where the current branch had scalar type, the
contents of that scalar meant that the decision to call
visit_type_FOO() was data-dependent - the reason we got lucky there
is that visit_type_FOO() for all scalar types in the dealloc visitor
is a no-op (only the pointer variants had anything to free), so it
did not matter whether the dealloc visit was skipped. But with this
patch, we would risk leaking memory if we could skip a call to
visit_type_FOO_fields() based solely on a data-dependent decision.
But notice: in the dealloc visitor, visit_type_FOO() already handles
a NULL obj - it was only the visit_type_implicit_FOO() that was
failing to check for NULL. And now that we have refactored things to
have the branch be part of the parent struct, we no longer have a
separate pointer that can be NULL in the first place. So we can just
delete the call to visit_start_union() altogether, and blindly visit
the branch type; there is no change in behavior except to the dealloc
visitor, where we now unconditionally visit the branch, but where that
visit is now always safe (for a flat union, we can no longer
dereference NULL, and for a simple union, visit_type_FOO() was already
safely handling NULL on pointer types).
Unfortunately, simple unions are not as easy to switch to unboxed
layout; because we are special-casing the hidden implicit type with
a single 'data' member, we really DO need to keep calling another
layer of visit_start_struct(), with a second malloc; although there
are some cleanups planned for simple unions in later patches.
visit_start_union() and gen_visit_implicit_struct() are now unused.
Drop them.
Note that after this patch, the only remaining use of
visit_start_implicit_struct() is for alternate types; the next patch
will do further cleanup based on that fact.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-14-git-send-email-eblake@redhat.com>
[Dead code deletion squashed in, commit message updated accordingly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 07:48:27 +01:00
|
|
|
monitor_printf(mon, " PC=0x%016" PRIx64, cpu->value->u.tricore.PC);
|
cpu: Convert CpuInfo into flat union
The CpuInfo struct is used only by the 'query-cpus' output
command, so we are free to modify it by adding fields (clients
are already supposed to ignore unknown output fields), or by
changing optional members to mandatory, while still keeping
QMP wire compatibility with older versions of qemu.
When qapi type CpuInfo was originally created for 0.14, we had
no notion of a flat union, and instead just listed a bunch of
optional fields with documentation about the mutually-exclusive
choice of which instruction pointer field(s) would be provided
for a given architecture. But now that we have flat unions and
introspection, it is better to segregate off which fields will
be provided according to the actual architecture. With this in
place, we no longer need the fields to be optional, because the
choice of the new 'arch' discriminator serves that role.
This has an additional benefit: the old all-in-one struct was
the only place in the code base that had a case-sensitive
naming of members 'pc' vs. 'PC'. Separating these spellings
into different branches of the flat union will allow us to add
restrictions against future case-insensitive collisions, since
that is generally a poor interface practice.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-25-git-send-email-eblake@redhat.com>
[Spelling of CPUInfo{SPARC,PPC,MIPS} fixed]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 09:52:59 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2011-09-21 21:38:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->value->halted) {
|
|
|
|
monitor_printf(mon, " (halted)");
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, " thread_id=%" PRId64 "\n", cpu->value->thread_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_CpuInfoList(cpu_list);
|
|
|
|
}
|
|
|
|
|
2014-09-15 12:06:39 +02:00
|
|
|
static void print_block_info(Monitor *mon, BlockInfo *info,
|
|
|
|
BlockDeviceInfo *inserted, bool verbose)
|
2011-09-21 22:16:47 +02:00
|
|
|
{
|
2013-06-06 06:28:00 +02:00
|
|
|
ImageInfo *image_info;
|
2011-09-21 22:16:47 +02:00
|
|
|
|
2014-09-15 12:12:52 +02:00
|
|
|
assert(!info || !info->has_inserted || info->inserted == inserted);
|
|
|
|
|
|
|
|
if (info) {
|
|
|
|
monitor_printf(mon, "%s", info->device);
|
|
|
|
if (inserted && inserted->has_node_name) {
|
|
|
|
monitor_printf(mon, " (%s)", inserted->node_name);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
assert(inserted);
|
|
|
|
monitor_printf(mon, "%s",
|
|
|
|
inserted->has_node_name
|
|
|
|
? inserted->node_name
|
|
|
|
: "<anonymous>");
|
|
|
|
}
|
|
|
|
|
2014-09-15 12:06:39 +02:00
|
|
|
if (inserted) {
|
|
|
|
monitor_printf(mon, ": %s (%s%s%s)\n",
|
|
|
|
inserted->file,
|
|
|
|
inserted->drv,
|
|
|
|
inserted->ro ? ", read-only" : "",
|
|
|
|
inserted->encrypted ? ", encrypted" : "");
|
|
|
|
} else {
|
|
|
|
monitor_printf(mon, ": [not inserted]\n");
|
|
|
|
}
|
2011-09-21 22:16:47 +02:00
|
|
|
|
2014-09-15 12:12:52 +02:00
|
|
|
if (info) {
|
|
|
|
if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) {
|
|
|
|
monitor_printf(mon, " I/O status: %s\n",
|
|
|
|
BlockDeviceIoStatus_lookup[info->io_status]);
|
|
|
|
}
|
2011-09-21 22:16:47 +02:00
|
|
|
|
2014-09-15 12:12:52 +02:00
|
|
|
if (info->removable) {
|
|
|
|
monitor_printf(mon, " Removable device: %slocked, tray %s\n",
|
|
|
|
info->locked ? "" : "not ",
|
|
|
|
info->tray_open ? "open" : "closed");
|
|
|
|
}
|
2014-09-15 12:06:39 +02:00
|
|
|
}
|
2013-06-19 16:10:55 +02:00
|
|
|
|
2011-09-21 22:16:47 +02:00
|
|
|
|
2014-09-15 12:06:39 +02:00
|
|
|
if (!inserted) {
|
|
|
|
return;
|
|
|
|
}
|
2011-09-21 22:16:47 +02:00
|
|
|
|
2014-09-15 12:06:39 +02:00
|
|
|
monitor_printf(mon, " Cache mode: %s%s%s\n",
|
|
|
|
inserted->cache->writeback ? "writeback" : "writethrough",
|
|
|
|
inserted->cache->direct ? ", direct" : "",
|
|
|
|
inserted->cache->no_flush ? ", ignore flushes" : "");
|
|
|
|
|
|
|
|
if (inserted->has_backing_file) {
|
|
|
|
monitor_printf(mon,
|
|
|
|
" Backing file: %s "
|
|
|
|
"(chain depth: %" PRId64 ")\n",
|
|
|
|
inserted->backing_file,
|
|
|
|
inserted->backing_file_depth);
|
|
|
|
}
|
2011-11-08 06:00:31 +01:00
|
|
|
|
2014-09-15 12:06:39 +02:00
|
|
|
if (inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) {
|
|
|
|
monitor_printf(mon, " Detect zeroes: %s\n",
|
|
|
|
BlockdevDetectZeroesOptions_lookup[inserted->detect_zeroes]);
|
|
|
|
}
|
2013-06-19 16:10:55 +02:00
|
|
|
|
2014-09-15 12:06:39 +02:00
|
|
|
if (inserted->bps || inserted->bps_rd || inserted->bps_wr ||
|
|
|
|
inserted->iops || inserted->iops_rd || inserted->iops_wr)
|
|
|
|
{
|
|
|
|
monitor_printf(mon, " I/O throttling: bps=%" PRId64
|
|
|
|
" bps_rd=%" PRId64 " bps_wr=%" PRId64
|
|
|
|
" bps_max=%" PRId64
|
|
|
|
" bps_rd_max=%" PRId64
|
|
|
|
" bps_wr_max=%" PRId64
|
|
|
|
" iops=%" PRId64 " iops_rd=%" PRId64
|
|
|
|
" iops_wr=%" PRId64
|
|
|
|
" iops_max=%" PRId64
|
|
|
|
" iops_rd_max=%" PRId64
|
|
|
|
" iops_wr_max=%" PRId64
|
2015-06-08 18:17:46 +02:00
|
|
|
" iops_size=%" PRId64
|
|
|
|
" group=%s\n",
|
2014-09-15 12:06:39 +02:00
|
|
|
inserted->bps,
|
|
|
|
inserted->bps_rd,
|
|
|
|
inserted->bps_wr,
|
|
|
|
inserted->bps_max,
|
|
|
|
inserted->bps_rd_max,
|
|
|
|
inserted->bps_wr_max,
|
|
|
|
inserted->iops,
|
|
|
|
inserted->iops_rd,
|
|
|
|
inserted->iops_wr,
|
|
|
|
inserted->iops_max,
|
|
|
|
inserted->iops_rd_max,
|
|
|
|
inserted->iops_wr_max,
|
2015-06-08 18:17:46 +02:00
|
|
|
inserted->iops_size,
|
|
|
|
inserted->group);
|
2014-09-15 12:06:39 +02:00
|
|
|
}
|
2013-06-19 16:10:55 +02:00
|
|
|
|
2015-04-22 12:15:10 +02:00
|
|
|
if (verbose) {
|
2014-09-15 12:06:39 +02:00
|
|
|
monitor_printf(mon, "\nImages:\n");
|
|
|
|
image_info = inserted->image;
|
|
|
|
while (1) {
|
|
|
|
bdrv_image_info_dump((fprintf_function)monitor_printf,
|
|
|
|
mon, image_info);
|
|
|
|
if (image_info->has_backing_image) {
|
|
|
|
image_info = image_info->backing_image;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-22 13:28:45 +02:00
|
|
|
|
2014-09-15 12:06:39 +02:00
|
|
|
void hmp_info_block(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
BlockInfoList *block_list, *info;
|
2014-09-15 12:19:14 +02:00
|
|
|
BlockDeviceInfoList *blockdev_list, *blockdev;
|
2014-09-15 12:06:39 +02:00
|
|
|
const char *device = qdict_get_try_str(qdict, "device");
|
2015-05-16 00:25:00 +02:00
|
|
|
bool verbose = qdict_get_try_bool(qdict, "verbose", false);
|
|
|
|
bool nodes = qdict_get_try_bool(qdict, "nodes", false);
|
2014-09-15 12:19:14 +02:00
|
|
|
bool printed = false;
|
2014-05-22 13:28:45 +02:00
|
|
|
|
2014-09-15 12:19:14 +02:00
|
|
|
/* Print BlockBackend information */
|
|
|
|
if (!nodes) {
|
2015-02-08 15:40:48 +01:00
|
|
|
block_list = qmp_query_block(NULL);
|
2014-09-15 12:19:14 +02:00
|
|
|
} else {
|
|
|
|
block_list = NULL;
|
|
|
|
}
|
2013-06-19 16:10:55 +02:00
|
|
|
|
2014-09-15 12:06:39 +02:00
|
|
|
for (info = block_list; info; info = info->next) {
|
|
|
|
if (device && strcmp(device, info->value->device)) {
|
|
|
|
continue;
|
2014-05-18 00:58:19 +02:00
|
|
|
}
|
|
|
|
|
2014-09-15 12:06:39 +02:00
|
|
|
if (info != block_list) {
|
|
|
|
monitor_printf(mon, "\n");
|
2013-06-19 16:10:55 +02:00
|
|
|
}
|
2013-06-06 06:28:00 +02:00
|
|
|
|
2014-09-15 12:06:39 +02:00
|
|
|
print_block_info(mon, info->value, info->value->has_inserted
|
|
|
|
? info->value->inserted : NULL,
|
|
|
|
verbose);
|
2014-09-15 12:19:14 +02:00
|
|
|
printed = true;
|
2011-09-21 22:16:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_BlockInfoList(block_list);
|
2014-09-15 12:19:14 +02:00
|
|
|
|
|
|
|
if ((!device && !nodes) || printed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Print node information */
|
|
|
|
blockdev_list = qmp_query_named_block_nodes(NULL);
|
|
|
|
for (blockdev = blockdev_list; blockdev; blockdev = blockdev->next) {
|
|
|
|
assert(blockdev->value->has_node_name);
|
|
|
|
if (device && strcmp(device, blockdev->value->node_name)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (blockdev != blockdev_list) {
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
print_block_info(mon, NULL, blockdev->value, verbose);
|
|
|
|
}
|
|
|
|
qapi_free_BlockDeviceInfoList(blockdev_list);
|
2011-09-21 22:16:47 +02:00
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_blockstats(Monitor *mon, const QDict *qdict)
|
2011-09-22 20:56:36 +02:00
|
|
|
{
|
|
|
|
BlockStatsList *stats_list, *stats;
|
|
|
|
|
2014-10-31 04:32:57 +01:00
|
|
|
stats_list = qmp_query_blockstats(false, false, NULL);
|
2011-09-22 20:56:36 +02:00
|
|
|
|
|
|
|
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
|
2015-02-02 14:52:18 +01:00
|
|
|
" rd_merged=%" PRId64
|
|
|
|
" wr_merged=%" PRId64
|
2015-10-28 16:33:02 +01:00
|
|
|
" idle_time_ns=%" PRId64
|
2011-09-22 20:56:36 +02:00
|
|
|
"\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,
|
2015-02-02 14:52:18 +01:00
|
|
|
stats->value->stats->flush_total_time_ns,
|
|
|
|
stats->value->stats->rd_merged,
|
2015-10-28 16:33:02 +01:00
|
|
|
stats->value->stats->wr_merged,
|
|
|
|
stats->value->stats->idle_time_ns);
|
2011-09-22 20:56:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_BlockStatsList(stats_list);
|
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_vnc(Monitor *mon, const QDict *qdict)
|
2011-10-17 20:41:22 +02:00
|
|
|
{
|
|
|
|
VncInfo *info;
|
|
|
|
Error *err = NULL;
|
|
|
|
VncClientInfoList *client;
|
|
|
|
|
|
|
|
info = qmp_query_vnc(&err);
|
|
|
|
if (err) {
|
error: Use error_report_err() instead of monitor_printf()
Both error_report_err() and monitor_printf() print to the same
destination when monitor_printf() is used correctly, i.e. within an
HMP monitor. Elsewhere, monitor_printf() does nothing, while
error_report_err() reports to stderr.
Most changed functions are HMP command handlers. These should only
run within an HMP monitor. The one exception is bdrv_password_cb(),
which should also only run within an HMP monitor.
Four command handlers prefix the error message with the command name:
balloon, migrate_set_capability, migrate_set_parameter, migrate.
Pointless, drop.
Unlike monitor_printf(), error_report_err() uses the error whole
instead of just its message obtained with error_get_pretty(). This
avoids suppressing its hint (see commit 50b7b00). Example:
(qemu) device_add ivshmem,id=666
Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Try "help device_add" for more information
The "Identifiers consist of..." line is new with this patch.
Coccinelle semantic patch:
@@
expression M, E;
@@
- monitor_printf(M, "%s\n", error_get_pretty(E));
- error_free(E);
+ error_report_err(E);
@r1@
expression M, E;
format F;
position p;
@@
- monitor_printf(M, "...%@F@\n", error_get_pretty(E));@p
- error_free(E);
+ error_report_err(E);
@script:python@
p << r1.p;
@@
print "%s:%s:%s: prefix dropped" % (p[0].file, p[0].line, p[0].column)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1450452927-8346-4-git-send-email-armbru@redhat.com>
2015-12-18 16:35:06 +01:00
|
|
|
error_report_err(err);
|
2011-10-17 20:41:22 +02:00
|
|
|
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",
|
qapi: Unbox base members
Rather than storing a base class as a pointer to a box, just
store the fields of that base class in the same order, so that
a child struct can be directly cast to its parent. This gives
less malloc overhead, less pointer dereferencing, and even less
generated code. Compare to the earlier commit 1e6c1616a "qapi:
Generate a nicer struct for flat unions" (although that patch
had fewer places to change, as less of qemu was directly using
qapi structs for flat unions). It also allows us to turn on
automatic type-safe wrappers for upcasting to the base class
of a struct.
Changes to the generated code look like this in qapi-types.h:
| struct SpiceChannel {
|- SpiceBasicInfo *base;
|+ /* Members inherited from SpiceBasicInfo: */
|+ char *host;
|+ char *port;
|+ NetworkAddressFamily family;
|+ /* Own members: */
| int64_t connection_id;
as well as additional upcast functions like qapi_SpiceChannel_base().
Meanwhile, changes to qapi-visit.c look like:
| static void visit_type_SpiceChannel_fields(Visitor *v, SpiceChannel **obj, Error **errp)
| {
| Error *err = NULL;
|
|- visit_type_implicit_SpiceBasicInfo(v, &(*obj)->base, &err);
|+ visit_type_SpiceBasicInfo_fields(v, (SpiceBasicInfo **)obj, &err);
| if (err) {
(the cast is necessary, since our upcast wrappers only deal with a
single pointer, not pointer-to-pointer); plus the wholesale
elimination of some now-unused visit_type_implicit_FOO() functions.
Without boxing, the corner case of one empty struct having
another empty struct as its base type now requires inserting a
dummy member (previously, the 'Base *base' member sufficed).
And now that we no longer consume a 'base' member in the generated
C struct, we can delete the former negative struct-base-clash-base
test.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-11-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-10-26 23:34:49 +01:00
|
|
|
client->value->host,
|
|
|
|
client->value->service);
|
2011-10-17 20:41:22 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2015-01-13 15:46:39 +01:00
|
|
|
#ifdef CONFIG_SPICE
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_spice(Monitor *mon, const QDict *qdict)
|
2011-10-20 21:01:33 +02:00
|
|
|
{
|
|
|
|
SpiceChannelList *chan;
|
|
|
|
SpiceInfo *info;
|
2015-03-01 15:29:18 +01:00
|
|
|
const char *channel_name;
|
|
|
|
const char * const channel_names[] = {
|
|
|
|
[SPICE_CHANNEL_MAIN] = "main",
|
|
|
|
[SPICE_CHANNEL_DISPLAY] = "display",
|
|
|
|
[SPICE_CHANNEL_INPUTS] = "inputs",
|
|
|
|
[SPICE_CHANNEL_CURSOR] = "cursor",
|
|
|
|
[SPICE_CHANNEL_PLAYBACK] = "playback",
|
|
|
|
[SPICE_CHANNEL_RECORD] = "record",
|
|
|
|
[SPICE_CHANNEL_TUNNEL] = "tunnel",
|
|
|
|
[SPICE_CHANNEL_SMARTCARD] = "smartcard",
|
|
|
|
[SPICE_CHANNEL_USBREDIR] = "usbredir",
|
|
|
|
[SPICE_CHANNEL_PORT] = "port",
|
2015-03-03 09:27:28 +01:00
|
|
|
#if 0
|
|
|
|
/* minimum spice-protocol is 0.12.3, webdav was added in 0.12.7,
|
|
|
|
* no easy way to #ifdef (SPICE_CHANNEL_* is a enum). Disable
|
|
|
|
* as quick fix for build failures with older versions. */
|
2015-03-01 15:29:18 +01:00
|
|
|
[SPICE_CHANNEL_WEBDAV] = "webdav",
|
2015-03-03 09:27:28 +01:00
|
|
|
#endif
|
2015-03-01 15:29:18 +01:00
|
|
|
};
|
2011-10-20 21:01:33 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2012-08-21 10:51:58 +02:00
|
|
|
monitor_printf(mon, " migrated: %s\n",
|
|
|
|
info->migrated ? "true" : "false");
|
2011-10-20 21:01:33 +02:00
|
|
|
monitor_printf(mon, " auth: %s\n", info->auth);
|
|
|
|
monitor_printf(mon, " compiled: %s\n", info->compiled_version);
|
2012-03-29 23:23:14 +02:00
|
|
|
monitor_printf(mon, " mouse-mode: %s\n",
|
|
|
|
SpiceQueryMouseMode_lookup[info->mouse_mode]);
|
2011-10-20 21:01:33 +02:00
|
|
|
|
|
|
|
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",
|
qapi: Unbox base members
Rather than storing a base class as a pointer to a box, just
store the fields of that base class in the same order, so that
a child struct can be directly cast to its parent. This gives
less malloc overhead, less pointer dereferencing, and even less
generated code. Compare to the earlier commit 1e6c1616a "qapi:
Generate a nicer struct for flat unions" (although that patch
had fewer places to change, as less of qemu was directly using
qapi structs for flat unions). It also allows us to turn on
automatic type-safe wrappers for upcasting to the base class
of a struct.
Changes to the generated code look like this in qapi-types.h:
| struct SpiceChannel {
|- SpiceBasicInfo *base;
|+ /* Members inherited from SpiceBasicInfo: */
|+ char *host;
|+ char *port;
|+ NetworkAddressFamily family;
|+ /* Own members: */
| int64_t connection_id;
as well as additional upcast functions like qapi_SpiceChannel_base().
Meanwhile, changes to qapi-visit.c look like:
| static void visit_type_SpiceChannel_fields(Visitor *v, SpiceChannel **obj, Error **errp)
| {
| Error *err = NULL;
|
|- visit_type_implicit_SpiceBasicInfo(v, &(*obj)->base, &err);
|+ visit_type_SpiceBasicInfo_fields(v, (SpiceBasicInfo **)obj, &err);
| if (err) {
(the cast is necessary, since our upcast wrappers only deal with a
single pointer, not pointer-to-pointer); plus the wholesale
elimination of some now-unused visit_type_implicit_FOO() functions.
Without boxing, the corner case of one empty struct having
another empty struct as its base type now requires inserting a
dummy member (previously, the 'Base *base' member sufficed).
And now that we no longer consume a 'base' member in the generated
C struct, we can delete the former negative struct-base-clash-base
test.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-11-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-10-26 23:34:49 +01:00
|
|
|
chan->value->host, chan->value->port,
|
2011-10-20 21:01:33 +02:00
|
|
|
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);
|
2015-03-01 15:29:18 +01:00
|
|
|
|
|
|
|
channel_name = "unknown";
|
|
|
|
if (chan->value->channel_type > 0 &&
|
|
|
|
chan->value->channel_type < ARRAY_SIZE(channel_names) &&
|
|
|
|
channel_names[chan->value->channel_type]) {
|
|
|
|
channel_name = channel_names[chan->value->channel_type];
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, " channel name: %s\n", channel_name);
|
2011-10-20 21:01:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
qapi_free_SpiceInfo(info);
|
|
|
|
}
|
2015-01-13 15:46:39 +01:00
|
|
|
#endif
|
2011-10-20 21:01:33 +02:00
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_balloon(Monitor *mon, const QDict *qdict)
|
2011-10-21 15:41:37 +02:00
|
|
|
{
|
|
|
|
BalloonInfo *info;
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
info = qmp_query_balloon(&err);
|
|
|
|
if (err) {
|
error: Use error_report_err() instead of monitor_printf()
Both error_report_err() and monitor_printf() print to the same
destination when monitor_printf() is used correctly, i.e. within an
HMP monitor. Elsewhere, monitor_printf() does nothing, while
error_report_err() reports to stderr.
Most changed functions are HMP command handlers. These should only
run within an HMP monitor. The one exception is bdrv_password_cb(),
which should also only run within an HMP monitor.
Four command handlers prefix the error message with the command name:
balloon, migrate_set_capability, migrate_set_parameter, migrate.
Pointless, drop.
Unlike monitor_printf(), error_report_err() uses the error whole
instead of just its message obtained with error_get_pretty(). This
avoids suppressing its hint (see commit 50b7b00). Example:
(qemu) device_add ivshmem,id=666
Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Try "help device_add" for more information
The "Identifiers consist of..." line is new with this patch.
Coccinelle semantic patch:
@@
expression M, E;
@@
- monitor_printf(M, "%s\n", error_get_pretty(E));
- error_free(E);
+ error_report_err(E);
@r1@
expression M, E;
format F;
position p;
@@
- monitor_printf(M, "...%@F@\n", error_get_pretty(E));@p
- error_free(E);
+ error_report_err(E);
@script:python@
p << r1.p;
@@
print "%s:%s:%s: prefix dropped" % (p[0].file, p[0].line, p[0].column)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1450452927-8346-4-git-send-email-armbru@redhat.com>
2015-12-18 16:35:06 +01:00
|
|
|
error_report_err(err);
|
2011-10-21 15:41:37 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-12-03 18:56:41 +01:00
|
|
|
monitor_printf(mon, "balloon: actual=%" PRId64 "\n", info->actual >> 20);
|
2011-10-21 15:41:37 +02:00
|
|
|
|
|
|
|
qapi_free_BalloonInfo(info);
|
|
|
|
}
|
|
|
|
|
2011-10-21 18:15:33 +02:00
|
|
|
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, " ");
|
|
|
|
|
2015-05-04 17:05:32 +02:00
|
|
|
if (dev->class_info->has_desc) {
|
|
|
|
monitor_printf(mon, "%s", dev->class_info->desc);
|
2011-10-21 18:15:33 +02:00
|
|
|
} else {
|
2015-05-04 17:05:32 +02:00
|
|
|
monitor_printf(mon, "Class %04" PRId64, dev->class_info->q_class);
|
2011-10-21 18:15:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, ": PCI device %04" PRIx64 ":%04" PRIx64 "\n",
|
2015-05-04 17:05:32 +02:00
|
|
|
dev->id->vendor, dev->id->device);
|
2011-10-21 18:15:33 +02:00
|
|
|
|
|
|
|
if (dev->has_irq) {
|
|
|
|
monitor_printf(mon, " IRQ %" PRId64 ".\n", dev->irq);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dev->has_pci_bridge) {
|
|
|
|
monitor_printf(mon, " BUS %" PRId64 ".\n",
|
2015-05-04 17:05:32 +02:00
|
|
|
dev->pci_bridge->bus->number);
|
2011-10-21 18:15:33 +02:00
|
|
|
monitor_printf(mon, " secondary bus %" PRId64 ".\n",
|
2015-05-04 17:05:32 +02:00
|
|
|
dev->pci_bridge->bus->secondary);
|
2011-10-21 18:15:33 +02:00
|
|
|
monitor_printf(mon, " subordinate bus %" PRId64 ".\n",
|
2015-05-04 17:05:32 +02:00
|
|
|
dev->pci_bridge->bus->subordinate);
|
2011-10-21 18:15:33 +02:00
|
|
|
|
|
|
|
monitor_printf(mon, " IO range [0x%04"PRIx64", 0x%04"PRIx64"]\n",
|
2015-05-04 17:05:32 +02:00
|
|
|
dev->pci_bridge->bus->io_range->base,
|
|
|
|
dev->pci_bridge->bus->io_range->limit);
|
2011-10-21 18:15:33 +02:00
|
|
|
|
|
|
|
monitor_printf(mon,
|
|
|
|
" memory range [0x%08"PRIx64", 0x%08"PRIx64"]\n",
|
2015-05-04 17:05:32 +02:00
|
|
|
dev->pci_bridge->bus->memory_range->base,
|
|
|
|
dev->pci_bridge->bus->memory_range->limit);
|
2011-10-21 18:15:33 +02:00
|
|
|
|
|
|
|
monitor_printf(mon, " prefetchable memory range "
|
|
|
|
"[0x%08"PRIx64", 0x%08"PRIx64"]\n",
|
2015-05-04 17:05:32 +02:00
|
|
|
dev->pci_bridge->bus->prefetchable_range->base,
|
|
|
|
dev->pci_bridge->bus->prefetchable_range->limit);
|
2011-10-21 18:15:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_pci(Monitor *mon, const QDict *qdict)
|
2011-10-21 18:15:33 +02:00
|
|
|
{
|
2012-01-11 16:51:52 +01:00
|
|
|
PciInfoList *info_list, *info;
|
2011-10-21 18:15:33 +02:00
|
|
|
Error *err = NULL;
|
|
|
|
|
2012-01-11 16:51:52 +01:00
|
|
|
info_list = qmp_query_pci(&err);
|
2011-10-21 18:15:33 +02:00
|
|
|
if (err) {
|
|
|
|
monitor_printf(mon, "PCI devices not supported\n");
|
|
|
|
error_free(err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-01-11 16:51:52 +01:00
|
|
|
for (info = info_list; info; info = info->next) {
|
2011-10-21 18:15:33 +02:00
|
|
|
PciDeviceInfoList *dev;
|
|
|
|
|
|
|
|
for (dev = info->value->devices; dev; dev = dev->next) {
|
|
|
|
hmp_info_pci_device(mon, dev->value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-11 16:51:52 +01:00
|
|
|
qapi_free_PciInfoList(info_list);
|
2011-10-21 18:15:33 +02:00
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_block_jobs(Monitor *mon, const QDict *qdict)
|
2012-01-18 15:40:49 +01:00
|
|
|
{
|
|
|
|
BlockJobInfoList *list;
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
list = qmp_query_block_jobs(&err);
|
|
|
|
assert(!err);
|
|
|
|
|
|
|
|
if (!list) {
|
|
|
|
monitor_printf(mon, "No active jobs\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (list) {
|
|
|
|
if (strcmp(list->value->type, "stream") == 0) {
|
|
|
|
monitor_printf(mon, "Streaming device %s: Completed %" PRId64
|
|
|
|
" of %" PRId64 " bytes, speed limit %" PRId64
|
|
|
|
" bytes/s\n",
|
|
|
|
list->value->device,
|
|
|
|
list->value->offset,
|
|
|
|
list->value->len,
|
|
|
|
list->value->speed);
|
|
|
|
} else {
|
|
|
|
monitor_printf(mon, "Type %s, device %s: Completed %" PRId64
|
|
|
|
" of %" PRId64 " bytes, speed limit %" PRId64
|
|
|
|
" bytes/s\n",
|
|
|
|
list->value->type,
|
|
|
|
list->value->device,
|
|
|
|
list->value->offset,
|
|
|
|
list->value->len,
|
|
|
|
list->value->speed);
|
|
|
|
}
|
|
|
|
list = list->next;
|
|
|
|
}
|
2014-09-16 15:36:55 +02:00
|
|
|
|
|
|
|
qapi_free_BlockJobInfoList(list);
|
2012-01-18 15:40:49 +01:00
|
|
|
}
|
|
|
|
|
Support for TPM command line options
This patch adds support for TPM command line options.
The command line options supported here are
./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
-device tpm-tis,tpmdev=<id>,id=<other id>
and
./qemu-... -tpmdev help
where the latter works similar to -soundhw help and shows a list of
available TPM backends (for example 'passthrough').
Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
passthrough driver. The interpretation of the other parameters along
with determining whether enough parameters were provided is pushed into
the backend driver, which needs to implement the interface function
'create' and return a TPMDriverOpts structure if the VM can be started or
'NULL' if not enough or bad parameters were provided.
Monitor support for 'info tpm' has been added. It for example prints the
following:
(qemu) info tpm
TPM devices:
tpm0: model=tpm-tis
\ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Message-id: 1361987275-26289-2-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-27 18:47:49 +01:00
|
|
|
void hmp_info_tpm(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
TPMInfoList *info_list, *info;
|
|
|
|
Error *err = NULL;
|
|
|
|
unsigned int c = 0;
|
|
|
|
TPMPassthroughOptions *tpo;
|
|
|
|
|
|
|
|
info_list = qmp_query_tpm(&err);
|
|
|
|
if (err) {
|
|
|
|
monitor_printf(mon, "TPM device not supported\n");
|
|
|
|
error_free(err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info_list) {
|
|
|
|
monitor_printf(mon, "TPM device:\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (info = info_list; info; info = info->next) {
|
|
|
|
TPMInfo *ti = info->value;
|
|
|
|
monitor_printf(mon, " tpm%d: model=%s\n",
|
|
|
|
c, TpmModel_lookup[ti->model]);
|
|
|
|
|
|
|
|
monitor_printf(mon, " \\ %s: type=%s",
|
2015-10-26 23:35:00 +01:00
|
|
|
ti->id, TpmTypeOptionsKind_lookup[ti->options->type]);
|
Support for TPM command line options
This patch adds support for TPM command line options.
The command line options supported here are
./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
-device tpm-tis,tpmdev=<id>,id=<other id>
and
./qemu-... -tpmdev help
where the latter works similar to -soundhw help and shows a list of
available TPM backends (for example 'passthrough').
Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
passthrough driver. The interpretation of the other parameters along
with determining whether enough parameters were provided is pushed into
the backend driver, which needs to implement the interface function
'create' and return a TPMDriverOpts structure if the VM can be started or
'NULL' if not enough or bad parameters were provided.
Monitor support for 'info tpm' has been added. It for example prints the
following:
(qemu) info tpm
TPM devices:
tpm0: model=tpm-tis
\ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Message-id: 1361987275-26289-2-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-27 18:47:49 +01:00
|
|
|
|
2015-10-26 23:35:00 +01:00
|
|
|
switch (ti->options->type) {
|
2013-03-20 17:34:48 +01:00
|
|
|
case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:
|
qapi: Don't special-case simple union wrappers
Simple unions were carrying a special case that hid their 'data'
QMP member from the resulting C struct, via the hack method
QAPISchemaObjectTypeVariant.simple_union_type(). But by using
the work we started by unboxing flat union and alternate
branches, coupled with the ability to visit the members of an
implicit type, we can now expose the simple union's implicit
type in qapi-types.h:
| struct q_obj_ImageInfoSpecificQCow2_wrapper {
| ImageInfoSpecificQCow2 *data;
| };
|
| struct q_obj_ImageInfoSpecificVmdk_wrapper {
| ImageInfoSpecificVmdk *data;
| };
...
| struct ImageInfoSpecific {
| ImageInfoSpecificKind type;
| union { /* union tag is @type */
| void *data;
|- ImageInfoSpecificQCow2 *qcow2;
|- ImageInfoSpecificVmdk *vmdk;
|+ q_obj_ImageInfoSpecificQCow2_wrapper qcow2;
|+ q_obj_ImageInfoSpecificVmdk_wrapper vmdk;
| } u;
| };
Doing this removes asymmetry between QAPI's QMP side and its
C side (both sides now expose 'data'), and means that the
treatment of a simple union as sugar for a flat union is now
equivalent in both languages (previously the two approaches used
a different layer of dereferencing, where the simple union could
be converted to a flat union with equivalent C layout but
different {} on the wire, or to an equivalent QMP wire form
but with different C representation). Using the implicit type
also lets us get rid of the simple_union_type() hack.
Of course, now all clients of simple unions have to adjust from
using su->u.member to using su->u.member.data; while this touches
a number of files in the tree, some earlier cleanup patches
helped minimize the change to the initialization of a temporary
variable rather than every single member access. The generated
qapi-visit.c code is also affected by the layout change:
|@@ -7393,10 +7393,10 @@ void visit_type_ImageInfoSpecific_member
| }
| switch (obj->type) {
| case IMAGE_INFO_SPECIFIC_KIND_QCOW2:
|- visit_type_ImageInfoSpecificQCow2(v, "data", &obj->u.qcow2, &err);
|+ visit_type_q_obj_ImageInfoSpecificQCow2_wrapper_members(v, &obj->u.qcow2, &err);
| break;
| case IMAGE_INFO_SPECIFIC_KIND_VMDK:
|- visit_type_ImageInfoSpecificVmdk(v, "data", &obj->u.vmdk, &err);
|+ visit_type_q_obj_ImageInfoSpecificVmdk_wrapper_members(v, &obj->u.vmdk, &err);
| break;
| default:
| abort();
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-17 23:48:37 +01:00
|
|
|
tpo = ti->options->u.passthrough.data;
|
Support for TPM command line options
This patch adds support for TPM command line options.
The command line options supported here are
./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
-device tpm-tis,tpmdev=<id>,id=<other id>
and
./qemu-... -tpmdev help
where the latter works similar to -soundhw help and shows a list of
available TPM backends (for example 'passthrough').
Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
passthrough driver. The interpretation of the other parameters along
with determining whether enough parameters were provided is pushed into
the backend driver, which needs to implement the interface function
'create' and return a TPMDriverOpts structure if the VM can be started or
'NULL' if not enough or bad parameters were provided.
Monitor support for 'info tpm' has been added. It for example prints the
following:
(qemu) info tpm
TPM devices:
tpm0: model=tpm-tis
\ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Message-id: 1361987275-26289-2-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-27 18:47:49 +01:00
|
|
|
monitor_printf(mon, "%s%s%s%s",
|
|
|
|
tpo->has_path ? ",path=" : "",
|
|
|
|
tpo->has_path ? tpo->path : "",
|
|
|
|
tpo->has_cancel_path ? ",cancel-path=" : "",
|
|
|
|
tpo->has_cancel_path ? tpo->cancel_path : "");
|
|
|
|
break;
|
qapi: Don't let implicit enum MAX member collide
Now that we guarantee the user doesn't have any enum values
beginning with a single underscore, we can use that for our
own purposes. Renaming ENUM_MAX to ENUM__MAX makes it obvious
that the sentinel is generated.
This patch was mostly generated by applying a temporary patch:
|diff --git a/scripts/qapi.py b/scripts/qapi.py
|index e6d014b..b862ec9 100644
|--- a/scripts/qapi.py
|+++ b/scripts/qapi.py
|@@ -1570,6 +1570,7 @@ const char *const %(c_name)s_lookup[] = {
| max_index = c_enum_const(name, 'MAX', prefix)
| ret += mcgen('''
| [%(max_index)s] = NULL,
|+// %(max_index)s
| };
| ''',
| max_index=max_index)
then running:
$ cat qapi-{types,event}.c tests/test-qapi-types.c |
sed -n 's,^// \(.*\)MAX,s|\1MAX|\1_MAX|g,p' > list
$ git grep -l _MAX | xargs sed -i -f list
The only things not generated are the changes in scripts/qapi.py.
Rejecting enum members named 'MAX' is now useless, and will be dropped
in the next patch.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-23-git-send-email-eblake@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
[Rebased to current master, commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 09:52:57 +01:00
|
|
|
case TPM_TYPE_OPTIONS_KIND__MAX:
|
Support for TPM command line options
This patch adds support for TPM command line options.
The command line options supported here are
./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
-device tpm-tis,tpmdev=<id>,id=<other id>
and
./qemu-... -tpmdev help
where the latter works similar to -soundhw help and shows a list of
available TPM backends (for example 'passthrough').
Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
passthrough driver. The interpretation of the other parameters along
with determining whether enough parameters were provided is pushed into
the backend driver, which needs to implement the interface function
'create' and return a TPMDriverOpts structure if the VM can be started or
'NULL' if not enough or bad parameters were provided.
Monitor support for 'info tpm' has been added. It for example prints the
following:
(qemu) info tpm
TPM devices:
tpm0: model=tpm-tis
\ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Message-id: 1361987275-26289-2-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-27 18:47:49 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
qapi_free_TPMInfoList(info_list);
|
|
|
|
}
|
|
|
|
|
2011-09-15 19:20:28 +02:00
|
|
|
void hmp_quit(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
monitor_suspend(mon);
|
|
|
|
qmp_quit(NULL);
|
|
|
|
}
|
2011-09-15 19:34:39 +02:00
|
|
|
|
|
|
|
void hmp_stop(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
qmp_stop(NULL);
|
|
|
|
}
|
2011-09-15 19:41:46 +02:00
|
|
|
|
|
|
|
void hmp_system_reset(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
qmp_system_reset(NULL);
|
|
|
|
}
|
2011-09-28 16:06:15 +02:00
|
|
|
|
|
|
|
void hmp_system_powerdown(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
qmp_system_powerdown(NULL);
|
|
|
|
}
|
2011-10-06 19:31:39 +02:00
|
|
|
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
2011-11-22 19:32:37 +01:00
|
|
|
|
|
|
|
void hmp_memsave(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
uint32_t size = qdict_get_int(qdict, "size");
|
|
|
|
const char *filename = qdict_get_str(qdict, "filename");
|
|
|
|
uint64_t addr = qdict_get_int(qdict, "val");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2011-11-22 19:32:37 +01:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_memsave(addr, size, filename, true, monitor_get_cpu_index(), &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2011-11-22 19:32:37 +01:00
|
|
|
}
|
2011-11-22 20:26:46 +01:00
|
|
|
|
|
|
|
void hmp_pmemsave(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
uint32_t size = qdict_get_int(qdict, "size");
|
|
|
|
const char *filename = qdict_get_str(qdict, "filename");
|
|
|
|
uint64_t addr = qdict_get_int(qdict, "val");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2011-11-22 20:26:46 +01:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_pmemsave(addr, size, filename, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2013-01-24 17:03:20 +01:00
|
|
|
}
|
|
|
|
|
qemu-char: Saner naming of memchar stuff & doc fixes
New device, has never been released, so we can still improve things
without worrying about compatibility.
Naming is a mess. The code calls the device driver CirMemCharDriver,
the public API calls it "memory", "memchardev", or "memchar", and the
special commands are named like "memchar-FOO". "memory" is a
particularly unfortunate choice, because there's another character
device driver called MemoryDriver. Moreover, the device's distinctive
property is that it's a ring buffer, not that's in memory. Therefore:
* Rename CirMemCharDriver to RingBufCharDriver, and call the thing a
"ringbuf" in the API.
* Rename QMP and HMP commands from memchar-FOO to ringbuf-FOO.
* Rename device parameter from maxcapacity to size (simple words are
good for you).
* Clearly mark the parameter as optional in documentation.
* Fix error reporting so that chardev-add reports to current monitor,
not stderr.
* Replace cirmem in C identifiers by ringbuf.
* Rework documentation. Document the impact of our crappy UTF-8
handling on reading.
* QMP examples that even work.
I could split this up into multiple commits, but they'd change the
same documentation lines multiple times. Not worth it.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-06 21:27:24 +01:00
|
|
|
void hmp_ringbuf_write(Monitor *mon, const QDict *qdict)
|
2013-01-24 17:03:20 +01:00
|
|
|
{
|
|
|
|
const char *chardev = qdict_get_str(qdict, "device");
|
|
|
|
const char *data = qdict_get_str(qdict, "data");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2013-01-24 17:03:20 +01:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_ringbuf_write(chardev, data, false, 0, &err);
|
2013-01-24 17:03:20 +01:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
hmp_handle_error(mon, &err);
|
2011-11-22 20:26:46 +01:00
|
|
|
}
|
2011-11-22 20:58:31 +01:00
|
|
|
|
qemu-char: Saner naming of memchar stuff & doc fixes
New device, has never been released, so we can still improve things
without worrying about compatibility.
Naming is a mess. The code calls the device driver CirMemCharDriver,
the public API calls it "memory", "memchardev", or "memchar", and the
special commands are named like "memchar-FOO". "memory" is a
particularly unfortunate choice, because there's another character
device driver called MemoryDriver. Moreover, the device's distinctive
property is that it's a ring buffer, not that's in memory. Therefore:
* Rename CirMemCharDriver to RingBufCharDriver, and call the thing a
"ringbuf" in the API.
* Rename QMP and HMP commands from memchar-FOO to ringbuf-FOO.
* Rename device parameter from maxcapacity to size (simple words are
good for you).
* Clearly mark the parameter as optional in documentation.
* Fix error reporting so that chardev-add reports to current monitor,
not stderr.
* Replace cirmem in C identifiers by ringbuf.
* Rework documentation. Document the impact of our crappy UTF-8
handling on reading.
* QMP examples that even work.
I could split this up into multiple commits, but they'd change the
same documentation lines multiple times. Not worth it.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-06 21:27:24 +01:00
|
|
|
void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
|
2013-01-24 17:03:21 +01:00
|
|
|
{
|
|
|
|
uint32_t size = qdict_get_int(qdict, "size");
|
|
|
|
const char *chardev = qdict_get_str(qdict, "device");
|
2013-02-06 21:27:15 +01:00
|
|
|
char *data;
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2013-02-06 21:27:26 +01:00
|
|
|
int i;
|
2013-01-24 17:03:21 +01:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
data = qmp_ringbuf_read(chardev, size, false, 0, &err);
|
|
|
|
if (err) {
|
error: Use error_report_err() instead of monitor_printf()
Both error_report_err() and monitor_printf() print to the same
destination when monitor_printf() is used correctly, i.e. within an
HMP monitor. Elsewhere, monitor_printf() does nothing, while
error_report_err() reports to stderr.
Most changed functions are HMP command handlers. These should only
run within an HMP monitor. The one exception is bdrv_password_cb(),
which should also only run within an HMP monitor.
Four command handlers prefix the error message with the command name:
balloon, migrate_set_capability, migrate_set_parameter, migrate.
Pointless, drop.
Unlike monitor_printf(), error_report_err() uses the error whole
instead of just its message obtained with error_get_pretty(). This
avoids suppressing its hint (see commit 50b7b00). Example:
(qemu) device_add ivshmem,id=666
Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Try "help device_add" for more information
The "Identifiers consist of..." line is new with this patch.
Coccinelle semantic patch:
@@
expression M, E;
@@
- monitor_printf(M, "%s\n", error_get_pretty(E));
- error_free(E);
+ error_report_err(E);
@r1@
expression M, E;
format F;
position p;
@@
- monitor_printf(M, "...%@F@\n", error_get_pretty(E));@p
- error_free(E);
+ error_report_err(E);
@script:python@
p << r1.p;
@@
print "%s:%s:%s: prefix dropped" % (p[0].file, p[0].line, p[0].column)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1450452927-8346-4-git-send-email-armbru@redhat.com>
2015-12-18 16:35:06 +01:00
|
|
|
error_report_err(err);
|
2013-01-24 17:03:21 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-02-06 21:27:26 +01:00
|
|
|
for (i = 0; data[i]; i++) {
|
|
|
|
unsigned char ch = data[i];
|
|
|
|
|
|
|
|
if (ch == '\\') {
|
|
|
|
monitor_printf(mon, "\\\\");
|
|
|
|
} else if ((ch < 0x20 && ch != '\n' && ch != '\t') || ch == 0x7F) {
|
|
|
|
monitor_printf(mon, "\\u%04X", ch);
|
|
|
|
} else {
|
|
|
|
monitor_printf(mon, "%c", ch);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "\n");
|
2013-02-06 21:27:15 +01:00
|
|
|
g_free(data);
|
2013-01-24 17:03:21 +01:00
|
|
|
}
|
|
|
|
|
2011-11-22 20:58:31 +01:00
|
|
|
static void hmp_cont_cb(void *opaque, int err)
|
|
|
|
{
|
|
|
|
if (!err) {
|
2012-07-27 01:41:53 +02:00
|
|
|
qmp_cont(NULL);
|
2011-11-22 20:58:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-27 01:41:53 +02:00
|
|
|
static bool key_is_missing(const BlockInfo *bdev)
|
|
|
|
{
|
|
|
|
return (bdev->inserted && bdev->inserted->encryption_key_missing);
|
|
|
|
}
|
|
|
|
|
2011-11-22 20:58:31 +01:00
|
|
|
void hmp_cont(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
2012-07-27 01:41:53 +02:00
|
|
|
BlockInfoList *bdev_list, *bdev;
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2011-11-22 20:58:31 +01:00
|
|
|
|
2012-07-27 01:41:53 +02:00
|
|
|
bdev_list = qmp_query_block(NULL);
|
|
|
|
for (bdev = bdev_list; bdev; bdev = bdev->next) {
|
|
|
|
if (key_is_missing(bdev->value)) {
|
|
|
|
monitor_read_block_device_key(mon, bdev->value->device,
|
|
|
|
hmp_cont_cb, NULL);
|
|
|
|
goto out;
|
2011-11-22 20:58:31 +01:00
|
|
|
}
|
|
|
|
}
|
2012-07-27 01:41:53 +02:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_cont(&err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2012-07-27 01:41:53 +02:00
|
|
|
|
|
|
|
out:
|
|
|
|
qapi_free_BlockInfoList(bdev_list);
|
2011-11-22 20:58:31 +01:00
|
|
|
}
|
2011-11-23 15:55:53 +01:00
|
|
|
|
2012-02-23 13:45:21 +01:00
|
|
|
void hmp_system_wakeup(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
qmp_system_wakeup(NULL);
|
|
|
|
}
|
|
|
|
|
hmp: Name HMP command handler functions hmp_COMMAND()
Some are called do_COMMAND() (old ones, usually), some hmp_COMMAND(),
and sometimes COMMAND pointlessly differs in spelling.
Normalize to hmp_COMMAND(), where COMMAND is exactly the command name
with '-' replaced by '_'.
Exceptions:
* do_device_add() and client_migrate_info() *not* renamed to
hmp_device_add(), hmp_client_migrate_info(), because they're also
QMP handlers. They still need to be converted to QAPI.
* do_memory_dump(), do_physical_memory_dump(), do_ioport_read(),
do_ioport_write() renamed do hmp_* instead of hmp_x(), hmp_xp(),
hmp_i(), hmp_o(), because those names are too cryptic for my taste.
* do_info_help() renamed to hmp_info_help() instead of hmp_info(),
because it only covers help.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-02-06 13:55:43 +01:00
|
|
|
void hmp_nmi(Monitor *mon, const QDict *qdict)
|
2011-11-23 15:55:53 +01:00
|
|
|
{
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2011-11-23 15:55:53 +01:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_inject_nmi(&err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2011-11-23 15:55:53 +01:00
|
|
|
}
|
2011-11-23 16:11:55 +01:00
|
|
|
|
|
|
|
void hmp_set_link(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
2015-05-16 00:25:00 +02:00
|
|
|
bool up = qdict_get_bool(qdict, "up");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2011-11-23 16:11:55 +01:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_set_link(name, up, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2011-11-23 16:11:55 +01:00
|
|
|
}
|
2011-11-23 16:28:21 +01:00
|
|
|
|
|
|
|
void hmp_block_passwd(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
const char *password = qdict_get_str(qdict, "password");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2011-11-23 16:28:21 +01:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_block_passwd(true, device, false, NULL, password, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2011-11-23 16:28:21 +01:00
|
|
|
}
|
2011-11-25 17:38:09 +01:00
|
|
|
|
|
|
|
void hmp_balloon(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
int64_t value = qdict_get_int(qdict, "value");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2011-11-25 17:38:09 +01:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_balloon(value, &err);
|
|
|
|
if (err) {
|
error: Use error_report_err() instead of monitor_printf()
Both error_report_err() and monitor_printf() print to the same
destination when monitor_printf() is used correctly, i.e. within an
HMP monitor. Elsewhere, monitor_printf() does nothing, while
error_report_err() reports to stderr.
Most changed functions are HMP command handlers. These should only
run within an HMP monitor. The one exception is bdrv_password_cb(),
which should also only run within an HMP monitor.
Four command handlers prefix the error message with the command name:
balloon, migrate_set_capability, migrate_set_parameter, migrate.
Pointless, drop.
Unlike monitor_printf(), error_report_err() uses the error whole
instead of just its message obtained with error_get_pretty(). This
avoids suppressing its hint (see commit 50b7b00). Example:
(qemu) device_add ivshmem,id=666
Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Try "help device_add" for more information
The "Identifiers consist of..." line is new with this patch.
Coccinelle semantic patch:
@@
expression M, E;
@@
- monitor_printf(M, "%s\n", error_get_pretty(E));
- error_free(E);
+ error_report_err(E);
@r1@
expression M, E;
format F;
position p;
@@
- monitor_printf(M, "...%@F@\n", error_get_pretty(E));@p
- error_free(E);
+ error_report_err(E);
@script:python@
p << r1.p;
@@
print "%s:%s:%s: prefix dropped" % (p[0].file, p[0].line, p[0].column)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1450452927-8346-4-git-send-email-armbru@redhat.com>
2015-12-18 16:35:06 +01:00
|
|
|
error_report_err(err);
|
2011-11-25 17:38:09 +01:00
|
|
|
}
|
|
|
|
}
|
2011-11-25 17:57:10 +01:00
|
|
|
|
|
|
|
void hmp_block_resize(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
int64_t size = qdict_get_int(qdict, "size");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2011-11-25 17:57:10 +01:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_block_resize(true, device, false, NULL, size, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2011-11-25 17:57:10 +01:00
|
|
|
}
|
2011-11-25 19:15:19 +01:00
|
|
|
|
2012-10-18 16:49:24 +02:00
|
|
|
void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
const char *filename = qdict_get_str(qdict, "target");
|
|
|
|
const char *format = qdict_get_try_str(qdict, "format");
|
2015-05-16 00:25:00 +02:00
|
|
|
bool reuse = qdict_get_try_bool(qdict, "reuse", false);
|
|
|
|
bool full = qdict_get_try_bool(qdict, "full", false);
|
2012-10-18 16:49:24 +02:00
|
|
|
enum NewImageMode mode;
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2012-10-18 16:49:24 +02:00
|
|
|
|
|
|
|
if (!filename) {
|
2015-03-17 11:54:50 +01:00
|
|
|
error_setg(&err, QERR_MISSING_PARAMETER, "target");
|
2014-05-02 13:26:29 +02:00
|
|
|
hmp_handle_error(mon, &err);
|
2012-10-18 16:49:24 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reuse) {
|
|
|
|
mode = NEW_IMAGE_MODE_EXISTING;
|
|
|
|
} else {
|
|
|
|
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
|
|
|
}
|
|
|
|
|
|
|
|
qmp_drive_mirror(device, filename, !!format, format,
|
2014-06-27 18:25:25 +02:00
|
|
|
false, NULL, false, NULL,
|
2012-10-18 16:49:24 +02:00
|
|
|
full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
|
2013-01-22 09:03:13 +01:00
|
|
|
true, mode, false, 0, false, 0, false, 0,
|
2015-06-08 07:56:08 +02:00
|
|
|
false, 0, false, 0, false, true, &err);
|
2014-05-02 13:26:29 +02:00
|
|
|
hmp_handle_error(mon, &err);
|
2012-10-18 16:49:24 +02:00
|
|
|
}
|
|
|
|
|
2013-06-26 14:11:58 +02:00
|
|
|
void hmp_drive_backup(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
const char *filename = qdict_get_str(qdict, "target");
|
|
|
|
const char *format = qdict_get_try_str(qdict, "format");
|
2015-05-16 00:25:00 +02:00
|
|
|
bool reuse = qdict_get_try_bool(qdict, "reuse", false);
|
|
|
|
bool full = qdict_get_try_bool(qdict, "full", false);
|
2013-06-26 14:11:58 +02:00
|
|
|
enum NewImageMode mode;
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2013-06-26 14:11:58 +02:00
|
|
|
|
|
|
|
if (!filename) {
|
2015-03-17 11:54:50 +01:00
|
|
|
error_setg(&err, QERR_MISSING_PARAMETER, "target");
|
2014-05-02 13:26:29 +02:00
|
|
|
hmp_handle_error(mon, &err);
|
2013-06-26 14:11:58 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reuse) {
|
|
|
|
mode = NEW_IMAGE_MODE_EXISTING;
|
|
|
|
} else {
|
|
|
|
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
|
|
|
}
|
|
|
|
|
|
|
|
qmp_drive_backup(device, filename, !!format, format,
|
|
|
|
full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
|
2015-04-18 01:49:58 +02:00
|
|
|
true, mode, false, 0, false, NULL,
|
|
|
|
false, 0, false, 0, &err);
|
2014-05-02 13:26:29 +02:00
|
|
|
hmp_handle_error(mon, &err);
|
2013-06-26 14:11:58 +02:00
|
|
|
}
|
|
|
|
|
2011-11-25 19:15:19 +01:00
|
|
|
void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
const char *filename = qdict_get_try_str(qdict, "snapshot-file");
|
|
|
|
const char *format = qdict_get_try_str(qdict, "format");
|
2015-05-16 00:25:00 +02:00
|
|
|
bool reuse = qdict_get_try_bool(qdict, "reuse", false);
|
2012-03-06 18:55:59 +01:00
|
|
|
enum NewImageMode mode;
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2011-11-25 19:15:19 +01:00
|
|
|
|
|
|
|
if (!filename) {
|
|
|
|
/* In the future, if 'snapshot-file' is not specified, the snapshot
|
|
|
|
will be taken internally. Today it's actually required. */
|
2015-03-17 11:54:50 +01:00
|
|
|
error_setg(&err, QERR_MISSING_PARAMETER, "snapshot-file");
|
2014-05-02 13:26:29 +02:00
|
|
|
hmp_handle_error(mon, &err);
|
2011-11-25 19:15:19 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-06 18:55:59 +01:00
|
|
|
mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
2014-01-23 21:31:38 +01:00
|
|
|
qmp_blockdev_snapshot_sync(true, device, false, NULL,
|
|
|
|
filename, false, NULL,
|
|
|
|
!!format, format,
|
2014-05-02 13:26:29 +02:00
|
|
|
true, mode, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2011-11-25 19:15:19 +01:00
|
|
|
}
|
2011-11-28 01:54:09 +01:00
|
|
|
|
2013-09-11 08:04:37 +02:00
|
|
|
void hmp_snapshot_blkdev_internal(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2013-09-11 08:04:37 +02:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_blockdev_snapshot_internal_sync(device, name, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2013-09-11 08:04:37 +02:00
|
|
|
}
|
|
|
|
|
2013-09-11 08:04:38 +02:00
|
|
|
void hmp_snapshot_delete_blkdev_internal(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
|
|
|
const char *id = qdict_get_try_str(qdict, "id");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2013-09-11 08:04:38 +02:00
|
|
|
|
|
|
|
qmp_blockdev_snapshot_delete_internal_sync(device, !!id, id,
|
2014-05-02 13:26:29 +02:00
|
|
|
true, name, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2013-09-11 08:04:38 +02:00
|
|
|
}
|
|
|
|
|
2011-11-28 01:54:09 +01:00
|
|
|
void hmp_migrate_cancel(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
qmp_migrate_cancel(NULL);
|
|
|
|
}
|
2011-11-28 02:18:01 +01:00
|
|
|
|
2015-02-19 12:40:28 +01:00
|
|
|
void hmp_migrate_incoming(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
const char *uri = qdict_get_str(qdict, "uri");
|
|
|
|
|
|
|
|
qmp_migrate_incoming(uri, &err);
|
|
|
|
|
2015-02-26 15:54:39 +01:00
|
|
|
hmp_handle_error(mon, &err);
|
2015-02-19 12:40:28 +01:00
|
|
|
}
|
|
|
|
|
2011-11-28 02:18:01 +01:00
|
|
|
void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
double value = qdict_get_double(qdict, "value");
|
|
|
|
qmp_migrate_set_downtime(value, NULL);
|
|
|
|
}
|
2011-11-28 14:59:37 +01:00
|
|
|
|
2012-08-06 20:42:54 +02:00
|
|
|
void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
int64_t value = qdict_get_int(qdict, "value");
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
qmp_migrate_set_cache_size(value, &err);
|
|
|
|
if (err) {
|
error: Use error_report_err() instead of monitor_printf()
Both error_report_err() and monitor_printf() print to the same
destination when monitor_printf() is used correctly, i.e. within an
HMP monitor. Elsewhere, monitor_printf() does nothing, while
error_report_err() reports to stderr.
Most changed functions are HMP command handlers. These should only
run within an HMP monitor. The one exception is bdrv_password_cb(),
which should also only run within an HMP monitor.
Four command handlers prefix the error message with the command name:
balloon, migrate_set_capability, migrate_set_parameter, migrate.
Pointless, drop.
Unlike monitor_printf(), error_report_err() uses the error whole
instead of just its message obtained with error_get_pretty(). This
avoids suppressing its hint (see commit 50b7b00). Example:
(qemu) device_add ivshmem,id=666
Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Try "help device_add" for more information
The "Identifiers consist of..." line is new with this patch.
Coccinelle semantic patch:
@@
expression M, E;
@@
- monitor_printf(M, "%s\n", error_get_pretty(E));
- error_free(E);
+ error_report_err(E);
@r1@
expression M, E;
format F;
position p;
@@
- monitor_printf(M, "...%@F@\n", error_get_pretty(E));@p
- error_free(E);
+ error_report_err(E);
@script:python@
p << r1.p;
@@
print "%s:%s:%s: prefix dropped" % (p[0].file, p[0].line, p[0].column)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1450452927-8346-4-git-send-email-armbru@redhat.com>
2015-12-18 16:35:06 +01:00
|
|
|
error_report_err(err);
|
2012-08-06 20:42:54 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-28 14:59:37 +01:00
|
|
|
void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
int64_t value = qdict_get_int(qdict, "value");
|
|
|
|
qmp_migrate_set_speed(value, NULL);
|
|
|
|
}
|
2011-12-07 14:17:51 +01:00
|
|
|
|
2012-08-06 20:42:48 +02:00
|
|
|
void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *cap = qdict_get_str(qdict, "capability");
|
|
|
|
bool state = qdict_get_bool(qdict, "state");
|
|
|
|
Error *err = NULL;
|
|
|
|
MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps));
|
|
|
|
int i;
|
|
|
|
|
qapi: Don't let implicit enum MAX member collide
Now that we guarantee the user doesn't have any enum values
beginning with a single underscore, we can use that for our
own purposes. Renaming ENUM_MAX to ENUM__MAX makes it obvious
that the sentinel is generated.
This patch was mostly generated by applying a temporary patch:
|diff --git a/scripts/qapi.py b/scripts/qapi.py
|index e6d014b..b862ec9 100644
|--- a/scripts/qapi.py
|+++ b/scripts/qapi.py
|@@ -1570,6 +1570,7 @@ const char *const %(c_name)s_lookup[] = {
| max_index = c_enum_const(name, 'MAX', prefix)
| ret += mcgen('''
| [%(max_index)s] = NULL,
|+// %(max_index)s
| };
| ''',
| max_index=max_index)
then running:
$ cat qapi-{types,event}.c tests/test-qapi-types.c |
sed -n 's,^// \(.*\)MAX,s|\1MAX|\1_MAX|g,p' > list
$ git grep -l _MAX | xargs sed -i -f list
The only things not generated are the changes in scripts/qapi.py.
Rejecting enum members named 'MAX' is now useless, and will be dropped
in the next patch.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-23-git-send-email-eblake@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
[Rebased to current master, commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 09:52:57 +01:00
|
|
|
for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
|
2012-08-06 20:42:48 +02:00
|
|
|
if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
|
|
|
|
caps->value = g_malloc0(sizeof(*caps->value));
|
|
|
|
caps->value->capability = i;
|
|
|
|
caps->value->state = state;
|
|
|
|
caps->next = NULL;
|
|
|
|
qmp_migrate_set_capabilities(caps, &err);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
qapi: Don't let implicit enum MAX member collide
Now that we guarantee the user doesn't have any enum values
beginning with a single underscore, we can use that for our
own purposes. Renaming ENUM_MAX to ENUM__MAX makes it obvious
that the sentinel is generated.
This patch was mostly generated by applying a temporary patch:
|diff --git a/scripts/qapi.py b/scripts/qapi.py
|index e6d014b..b862ec9 100644
|--- a/scripts/qapi.py
|+++ b/scripts/qapi.py
|@@ -1570,6 +1570,7 @@ const char *const %(c_name)s_lookup[] = {
| max_index = c_enum_const(name, 'MAX', prefix)
| ret += mcgen('''
| [%(max_index)s] = NULL,
|+// %(max_index)s
| };
| ''',
| max_index=max_index)
then running:
$ cat qapi-{types,event}.c tests/test-qapi-types.c |
sed -n 's,^// \(.*\)MAX,s|\1MAX|\1_MAX|g,p' > list
$ git grep -l _MAX | xargs sed -i -f list
The only things not generated are the changes in scripts/qapi.py.
Rejecting enum members named 'MAX' is now useless, and will be dropped
in the next patch.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-23-git-send-email-eblake@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
[Rebased to current master, commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 09:52:57 +01:00
|
|
|
if (i == MIGRATION_CAPABILITY__MAX) {
|
2015-03-17 11:54:50 +01:00
|
|
|
error_setg(&err, QERR_INVALID_PARAMETER, cap);
|
2012-08-06 20:42:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_MigrationCapabilityStatusList(caps);
|
|
|
|
|
|
|
|
if (err) {
|
error: Use error_report_err() instead of monitor_printf()
Both error_report_err() and monitor_printf() print to the same
destination when monitor_printf() is used correctly, i.e. within an
HMP monitor. Elsewhere, monitor_printf() does nothing, while
error_report_err() reports to stderr.
Most changed functions are HMP command handlers. These should only
run within an HMP monitor. The one exception is bdrv_password_cb(),
which should also only run within an HMP monitor.
Four command handlers prefix the error message with the command name:
balloon, migrate_set_capability, migrate_set_parameter, migrate.
Pointless, drop.
Unlike monitor_printf(), error_report_err() uses the error whole
instead of just its message obtained with error_get_pretty(). This
avoids suppressing its hint (see commit 50b7b00). Example:
(qemu) device_add ivshmem,id=666
Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Try "help device_add" for more information
The "Identifiers consist of..." line is new with this patch.
Coccinelle semantic patch:
@@
expression M, E;
@@
- monitor_printf(M, "%s\n", error_get_pretty(E));
- error_free(E);
+ error_report_err(E);
@r1@
expression M, E;
format F;
position p;
@@
- monitor_printf(M, "...%@F@\n", error_get_pretty(E));@p
- error_free(E);
+ error_report_err(E);
@script:python@
p << r1.p;
@@
print "%s:%s:%s: prefix dropped" % (p[0].file, p[0].line, p[0].column)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1450452927-8346-4-git-send-email-armbru@redhat.com>
2015-12-18 16:35:06 +01:00
|
|
|
error_report_err(err);
|
2012-08-06 20:42:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-23 09:32:29 +01:00
|
|
|
void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *param = qdict_get_str(qdict, "parameter");
|
|
|
|
int value = qdict_get_int(qdict, "value");
|
|
|
|
Error *err = NULL;
|
|
|
|
bool has_compress_level = false;
|
|
|
|
bool has_compress_threads = false;
|
|
|
|
bool has_decompress_threads = false;
|
2016-04-21 20:07:18 +02:00
|
|
|
bool has_cpu_throttle_initial = false;
|
|
|
|
bool has_cpu_throttle_increment = false;
|
2015-03-23 09:32:29 +01:00
|
|
|
int i;
|
|
|
|
|
qapi: Don't let implicit enum MAX member collide
Now that we guarantee the user doesn't have any enum values
beginning with a single underscore, we can use that for our
own purposes. Renaming ENUM_MAX to ENUM__MAX makes it obvious
that the sentinel is generated.
This patch was mostly generated by applying a temporary patch:
|diff --git a/scripts/qapi.py b/scripts/qapi.py
|index e6d014b..b862ec9 100644
|--- a/scripts/qapi.py
|+++ b/scripts/qapi.py
|@@ -1570,6 +1570,7 @@ const char *const %(c_name)s_lookup[] = {
| max_index = c_enum_const(name, 'MAX', prefix)
| ret += mcgen('''
| [%(max_index)s] = NULL,
|+// %(max_index)s
| };
| ''',
| max_index=max_index)
then running:
$ cat qapi-{types,event}.c tests/test-qapi-types.c |
sed -n 's,^// \(.*\)MAX,s|\1MAX|\1_MAX|g,p' > list
$ git grep -l _MAX | xargs sed -i -f list
The only things not generated are the changes in scripts/qapi.py.
Rejecting enum members named 'MAX' is now useless, and will be dropped
in the next patch.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-23-git-send-email-eblake@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
[Rebased to current master, commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 09:52:57 +01:00
|
|
|
for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
|
2015-03-23 09:32:29 +01:00
|
|
|
if (strcmp(param, MigrationParameter_lookup[i]) == 0) {
|
|
|
|
switch (i) {
|
|
|
|
case MIGRATION_PARAMETER_COMPRESS_LEVEL:
|
|
|
|
has_compress_level = true;
|
|
|
|
break;
|
|
|
|
case MIGRATION_PARAMETER_COMPRESS_THREADS:
|
|
|
|
has_compress_threads = true;
|
|
|
|
break;
|
|
|
|
case MIGRATION_PARAMETER_DECOMPRESS_THREADS:
|
|
|
|
has_decompress_threads = true;
|
|
|
|
break;
|
2016-04-21 20:07:18 +02:00
|
|
|
case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL:
|
|
|
|
has_cpu_throttle_initial = true;
|
2015-09-08 19:12:34 +02:00
|
|
|
break;
|
2016-04-21 20:07:18 +02:00
|
|
|
case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT:
|
|
|
|
has_cpu_throttle_increment = true;
|
2015-09-08 19:12:34 +02:00
|
|
|
break;
|
2015-03-23 09:32:29 +01:00
|
|
|
}
|
|
|
|
qmp_migrate_set_parameters(has_compress_level, value,
|
|
|
|
has_compress_threads, value,
|
|
|
|
has_decompress_threads, value,
|
2016-04-21 20:07:18 +02:00
|
|
|
has_cpu_throttle_initial, value,
|
|
|
|
has_cpu_throttle_increment, value,
|
2015-03-23 09:32:29 +01:00
|
|
|
&err);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
qapi: Don't let implicit enum MAX member collide
Now that we guarantee the user doesn't have any enum values
beginning with a single underscore, we can use that for our
own purposes. Renaming ENUM_MAX to ENUM__MAX makes it obvious
that the sentinel is generated.
This patch was mostly generated by applying a temporary patch:
|diff --git a/scripts/qapi.py b/scripts/qapi.py
|index e6d014b..b862ec9 100644
|--- a/scripts/qapi.py
|+++ b/scripts/qapi.py
|@@ -1570,6 +1570,7 @@ const char *const %(c_name)s_lookup[] = {
| max_index = c_enum_const(name, 'MAX', prefix)
| ret += mcgen('''
| [%(max_index)s] = NULL,
|+// %(max_index)s
| };
| ''',
| max_index=max_index)
then running:
$ cat qapi-{types,event}.c tests/test-qapi-types.c |
sed -n 's,^// \(.*\)MAX,s|\1MAX|\1_MAX|g,p' > list
$ git grep -l _MAX | xargs sed -i -f list
The only things not generated are the changes in scripts/qapi.py.
Rejecting enum members named 'MAX' is now useless, and will be dropped
in the next patch.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-23-git-send-email-eblake@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
[Rebased to current master, commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 09:52:57 +01:00
|
|
|
if (i == MIGRATION_PARAMETER__MAX) {
|
2015-03-17 11:54:50 +01:00
|
|
|
error_setg(&err, QERR_INVALID_PARAMETER, param);
|
2015-03-23 09:32:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (err) {
|
error: Use error_report_err() instead of monitor_printf()
Both error_report_err() and monitor_printf() print to the same
destination when monitor_printf() is used correctly, i.e. within an
HMP monitor. Elsewhere, monitor_printf() does nothing, while
error_report_err() reports to stderr.
Most changed functions are HMP command handlers. These should only
run within an HMP monitor. The one exception is bdrv_password_cb(),
which should also only run within an HMP monitor.
Four command handlers prefix the error message with the command name:
balloon, migrate_set_capability, migrate_set_parameter, migrate.
Pointless, drop.
Unlike monitor_printf(), error_report_err() uses the error whole
instead of just its message obtained with error_get_pretty(). This
avoids suppressing its hint (see commit 50b7b00). Example:
(qemu) device_add ivshmem,id=666
Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Try "help device_add" for more information
The "Identifiers consist of..." line is new with this patch.
Coccinelle semantic patch:
@@
expression M, E;
@@
- monitor_printf(M, "%s\n", error_get_pretty(E));
- error_free(E);
+ error_report_err(E);
@r1@
expression M, E;
format F;
position p;
@@
- monitor_printf(M, "...%@F@\n", error_get_pretty(E));@p
- error_free(E);
+ error_report_err(E);
@script:python@
p << r1.p;
@@
print "%s:%s:%s: prefix dropped" % (p[0].file, p[0].line, p[0].column)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1450452927-8346-4-git-send-email-armbru@redhat.com>
2015-12-18 16:35:06 +01:00
|
|
|
error_report_err(err);
|
2015-03-23 09:32:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-05 17:29:02 +01:00
|
|
|
void hmp_client_migrate_info(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
const char *protocol = qdict_get_str(qdict, "protocol");
|
|
|
|
const char *hostname = qdict_get_str(qdict, "hostname");
|
|
|
|
bool has_port = qdict_haskey(qdict, "port");
|
|
|
|
int port = qdict_get_try_int(qdict, "port", -1);
|
|
|
|
bool has_tls_port = qdict_haskey(qdict, "tls-port");
|
|
|
|
int tls_port = qdict_get_try_int(qdict, "tls-port", -1);
|
|
|
|
const char *cert_subject = qdict_get_try_str(qdict, "cert-subject");
|
|
|
|
|
|
|
|
qmp_client_migrate_info(protocol, hostname,
|
|
|
|
has_port, port, has_tls_port, tls_port,
|
|
|
|
!!cert_subject, cert_subject, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
|
|
|
|
2015-11-05 19:10:56 +01:00
|
|
|
void hmp_migrate_start_postcopy(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
qmp_migrate_start_postcopy(&err);
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
|
|
|
|
2011-12-07 14:17:51 +01:00
|
|
|
void hmp_set_password(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *protocol = qdict_get_str(qdict, "protocol");
|
|
|
|
const char *password = qdict_get_str(qdict, "password");
|
|
|
|
const char *connected = qdict_get_try_str(qdict, "connected");
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
qmp_set_password(protocol, password, !!connected, connected, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
2011-12-07 14:47:57 +01:00
|
|
|
|
|
|
|
void hmp_expire_password(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *protocol = qdict_get_str(qdict, "protocol");
|
|
|
|
const char *whenstr = qdict_get_str(qdict, "time");
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
qmp_expire_password(protocol, whenstr, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
2011-12-07 19:02:36 +01:00
|
|
|
|
|
|
|
void hmp_eject(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
2015-05-16 00:25:00 +02:00
|
|
|
bool force = qdict_get_try_bool(qdict, "force", false);
|
2011-12-07 19:02:36 +01:00
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
qmp_eject(device, true, force, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
2011-12-08 14:13:50 +01:00
|
|
|
|
2013-11-14 11:54:14 +01:00
|
|
|
static void hmp_change_read_arg(void *opaque, const char *password,
|
|
|
|
void *readline_opaque)
|
2011-12-08 14:13:50 +01:00
|
|
|
{
|
|
|
|
qmp_change_vnc_password(password, NULL);
|
2013-11-14 11:54:14 +01:00
|
|
|
monitor_read_command(opaque, 1);
|
2011-12-08 14:13:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_change(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
const char *target = qdict_get_str(qdict, "target");
|
|
|
|
const char *arg = qdict_get_try_str(qdict, "arg");
|
2015-10-26 21:39:18 +01:00
|
|
|
const char *read_only = qdict_get_try_str(qdict, "read-only-mode");
|
|
|
|
BlockdevChangeReadOnlyMode read_only_mode = 0;
|
2011-12-08 14:13:50 +01:00
|
|
|
Error *err = NULL;
|
|
|
|
|
2015-10-26 21:39:16 +01:00
|
|
|
if (strcmp(device, "vnc") == 0) {
|
2015-10-26 21:39:18 +01:00
|
|
|
if (read_only) {
|
|
|
|
monitor_printf(mon,
|
|
|
|
"Parameter 'read-only-mode' is invalid for VNC\n");
|
|
|
|
return;
|
|
|
|
}
|
2015-10-26 21:39:16 +01:00
|
|
|
if (strcmp(target, "passwd") == 0 ||
|
|
|
|
strcmp(target, "password") == 0) {
|
|
|
|
if (!arg) {
|
|
|
|
monitor_read_password(mon, hmp_change_read_arg, NULL);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
qmp_change("vnc", target, !!arg, arg, &err);
|
|
|
|
} else {
|
2015-10-26 21:39:18 +01:00
|
|
|
if (read_only) {
|
|
|
|
read_only_mode =
|
|
|
|
qapi_enum_parse(BlockdevChangeReadOnlyMode_lookup,
|
qapi: Don't let implicit enum MAX member collide
Now that we guarantee the user doesn't have any enum values
beginning with a single underscore, we can use that for our
own purposes. Renaming ENUM_MAX to ENUM__MAX makes it obvious
that the sentinel is generated.
This patch was mostly generated by applying a temporary patch:
|diff --git a/scripts/qapi.py b/scripts/qapi.py
|index e6d014b..b862ec9 100644
|--- a/scripts/qapi.py
|+++ b/scripts/qapi.py
|@@ -1570,6 +1570,7 @@ const char *const %(c_name)s_lookup[] = {
| max_index = c_enum_const(name, 'MAX', prefix)
| ret += mcgen('''
| [%(max_index)s] = NULL,
|+// %(max_index)s
| };
| ''',
| max_index=max_index)
then running:
$ cat qapi-{types,event}.c tests/test-qapi-types.c |
sed -n 's,^// \(.*\)MAX,s|\1MAX|\1_MAX|g,p' > list
$ git grep -l _MAX | xargs sed -i -f list
The only things not generated are the changes in scripts/qapi.py.
Rejecting enum members named 'MAX' is now useless, and will be dropped
in the next patch.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-23-git-send-email-eblake@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
[Rebased to current master, commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 09:52:57 +01:00
|
|
|
read_only, BLOCKDEV_CHANGE_READ_ONLY_MODE__MAX,
|
2015-10-26 21:39:18 +01:00
|
|
|
BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, &err);
|
|
|
|
if (err) {
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qmp_blockdev_change_medium(device, target, !!arg, arg,
|
|
|
|
!!read_only, read_only_mode, &err);
|
2015-10-26 21:39:16 +01:00
|
|
|
if (err &&
|
|
|
|
error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) {
|
|
|
|
error_free(err);
|
|
|
|
monitor_read_block_device_key(mon, device, NULL, NULL);
|
2011-12-08 14:13:50 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
2011-12-14 19:49:14 +01:00
|
|
|
|
|
|
|
void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
qmp_block_set_io_throttle(qdict_get_str(qdict, "device"),
|
|
|
|
qdict_get_int(qdict, "bps"),
|
|
|
|
qdict_get_int(qdict, "bps_rd"),
|
|
|
|
qdict_get_int(qdict, "bps_wr"),
|
|
|
|
qdict_get_int(qdict, "iops"),
|
|
|
|
qdict_get_int(qdict, "iops_rd"),
|
2013-09-02 14:14:40 +02:00
|
|
|
qdict_get_int(qdict, "iops_wr"),
|
|
|
|
false, /* no burst max via HMP */
|
|
|
|
0,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
false,
|
2013-09-02 14:14:41 +02:00
|
|
|
0,
|
2016-02-18 11:27:03 +01:00
|
|
|
false, /* no burst length via HMP */
|
|
|
|
0,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
false,
|
|
|
|
0,
|
2013-09-02 14:14:41 +02:00
|
|
|
false, /* No default I/O size */
|
2015-06-08 18:17:44 +02:00
|
|
|
0,
|
|
|
|
false,
|
|
|
|
NULL, &err);
|
2011-12-14 19:49:14 +01:00
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
2012-01-18 15:40:46 +01:00
|
|
|
|
|
|
|
void hmp_block_stream(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *error = NULL;
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
const char *base = qdict_get_try_str(qdict, "base");
|
2012-04-25 17:51:03 +02:00
|
|
|
int64_t speed = qdict_get_try_int(qdict, "speed", 0);
|
2012-01-18 15:40:46 +01:00
|
|
|
|
block: add backing-file option to block-stream
On some image chains, QEMU may not always be able to resolve the
filenames properly, when updating the backing file of an image
after a block job.
For instance, certain relative pathnames may fail, or drives may
have been specified originally by file descriptor (e.g. /dev/fd/???),
or a relative protocol pathname may have been used.
In these instances, QEMU may lack the information to be able to make
the correct choice, but the user or management layer most likely does
have that knowledge.
With this extension to the block-stream api, the user is able to change
the backing file of the active layer as part of the block-stream
operation.
This allows the change to be 'safe', in the sense that if the attempt
to write the active image metadata fails, then the block-stream
operation returns failure, without disrupting the guest.
If a backing file string is not specified in the command, the backing
file string to use is determined in the same manner as it was
previously.
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-25 21:40:11 +02:00
|
|
|
qmp_block_stream(device, base != NULL, base, false, NULL,
|
2012-09-28 17:22:59 +02:00
|
|
|
qdict_haskey(qdict, "speed"), speed,
|
2013-09-17 18:10:47 +02:00
|
|
|
true, BLOCKDEV_ON_ERROR_REPORT, &error);
|
2012-01-18 15:40:46 +01:00
|
|
|
|
|
|
|
hmp_handle_error(mon, &error);
|
|
|
|
}
|
2012-01-18 15:40:47 +01:00
|
|
|
|
|
|
|
void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *error = NULL;
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
2012-05-08 16:51:56 +02:00
|
|
|
int64_t value = qdict_get_int(qdict, "speed");
|
2012-01-18 15:40:47 +01:00
|
|
|
|
|
|
|
qmp_block_job_set_speed(device, value, &error);
|
|
|
|
|
|
|
|
hmp_handle_error(mon, &error);
|
|
|
|
}
|
2012-01-18 15:40:48 +01:00
|
|
|
|
|
|
|
void hmp_block_job_cancel(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *error = NULL;
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
2015-05-16 00:25:00 +02:00
|
|
|
bool force = qdict_get_try_bool(qdict, "force", false);
|
2012-01-18 15:40:48 +01:00
|
|
|
|
2012-09-28 17:22:51 +02:00
|
|
|
qmp_block_job_cancel(device, true, force, &error);
|
|
|
|
|
|
|
|
hmp_handle_error(mon, &error);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_block_job_pause(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *error = NULL;
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
|
|
|
|
qmp_block_job_pause(device, &error);
|
|
|
|
|
|
|
|
hmp_handle_error(mon, &error);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_block_job_resume(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *error = NULL;
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
|
|
|
|
qmp_block_job_resume(device, &error);
|
2012-01-18 15:40:48 +01:00
|
|
|
|
|
|
|
hmp_handle_error(mon, &error);
|
|
|
|
}
|
2011-12-05 17:48:01 +01:00
|
|
|
|
2012-10-18 16:49:21 +02:00
|
|
|
void hmp_block_job_complete(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *error = NULL;
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
|
|
|
|
qmp_block_job_complete(device, &error);
|
|
|
|
|
|
|
|
hmp_handle_error(mon, &error);
|
|
|
|
}
|
|
|
|
|
2015-03-13 09:08:39 +01:00
|
|
|
typedef struct HMPMigrationStatus
|
2011-12-05 17:48:01 +01:00
|
|
|
{
|
|
|
|
QEMUTimer *timer;
|
|
|
|
Monitor *mon;
|
|
|
|
bool is_block_migration;
|
2015-03-13 09:08:39 +01:00
|
|
|
} HMPMigrationStatus;
|
2011-12-05 17:48:01 +01:00
|
|
|
|
|
|
|
static void hmp_migrate_status_cb(void *opaque)
|
|
|
|
{
|
2015-03-13 09:08:39 +01:00
|
|
|
HMPMigrationStatus *status = opaque;
|
2011-12-05 17:48:01 +01:00
|
|
|
MigrationInfo *info;
|
|
|
|
|
|
|
|
info = qmp_query_migrate(NULL);
|
2015-03-13 09:08:40 +01:00
|
|
|
if (!info->has_status || info->status == MIGRATION_STATUS_ACTIVE ||
|
|
|
|
info->status == MIGRATION_STATUS_SETUP) {
|
2011-12-05 17:48:01 +01:00
|
|
|
if (info->has_disk) {
|
|
|
|
int progress;
|
|
|
|
|
|
|
|
if (info->disk->remaining) {
|
|
|
|
progress = info->disk->transferred * 100 / info->disk->total;
|
|
|
|
} else {
|
|
|
|
progress = 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(status->mon, "Completed %d %%\r", progress);
|
|
|
|
monitor_flush(status->mon);
|
|
|
|
}
|
|
|
|
|
2013-08-21 17:03:08 +02:00
|
|
|
timer_mod(status->timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
|
2011-12-05 17:48:01 +01:00
|
|
|
} else {
|
|
|
|
if (status->is_block_migration) {
|
|
|
|
monitor_printf(status->mon, "\n");
|
|
|
|
}
|
migration: add reporting of errors for outgoing migration
Currently if an application initiates an outgoing migration,
it may or may not, get an error reported back on failure. If
the error occurs synchronously to the 'migrate' command
execution, the client app will see the error message. This
is the case for DNS lookup failures. If the error occurs
asynchronously to the monitor command though, the error
will be thrown away and the client left guessing about
what went wrong. This is the case for failure to connect
to the TCP server (eg due to wrong port, or firewall
rules, or other similar errors).
In the future we'll be adding more scope for errors to
happen asynchronously with the TLS protocol handshake.
TLS errors are hard to diagnose even when they are well
reported, so discarding errors entirely will make it
impossible to debug TLS connection problems.
Management apps which do migration are already using
'query-migrate' / 'info migrate' to check up on progress
of background migration operations and to see their end
status. This is a fine place to also include the error
message when things go wrong.
This patch thus adds an 'error-desc' field to the
MigrationInfo struct, which will be populated when
the 'status' is set to 'failed':
(qemu) migrate -d tcp:localhost:9001
(qemu) info migrate
capabilities: xbzrle: off rdma-pin-all: off auto-converge: off zero-blocks: off compress: off events: off x-postcopy-ram: off
Migration status: failed (Error connecting to socket: Connection refused)
total time: 0 milliseconds
In the HMP, when doing non-detached migration, it is
also possible to display this error message directly
to the app.
(qemu) migrate tcp:localhost:9001
Error connecting to socket: Connection refused
Or with QMP
{
"execute": "query-migrate",
"arguments": {}
}
{
"return": {
"status": "failed",
"error-desc": "address resolution failed for myhost:9000: No address associated with hostname"
}
}
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Message-Id: <1461751518-12128-11-git-send-email-berrange@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
2016-04-27 12:05:00 +02:00
|
|
|
if (info->has_error_desc) {
|
|
|
|
error_report("%s", info->error_desc);
|
|
|
|
}
|
2011-12-05 17:48:01 +01:00
|
|
|
monitor_resume(status->mon);
|
2013-08-21 17:03:08 +02:00
|
|
|
timer_del(status->timer);
|
2011-12-05 17:48:01 +01:00
|
|
|
g_free(status);
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_MigrationInfo(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_migrate(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
2015-05-16 00:25:00 +02:00
|
|
|
bool detach = qdict_get_try_bool(qdict, "detach", false);
|
|
|
|
bool blk = qdict_get_try_bool(qdict, "blk", false);
|
|
|
|
bool inc = qdict_get_try_bool(qdict, "inc", false);
|
2011-12-05 17:48:01 +01:00
|
|
|
const char *uri = qdict_get_str(qdict, "uri");
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
qmp_migrate(uri, !!blk, blk, !!inc, inc, false, false, &err);
|
|
|
|
if (err) {
|
error: Use error_report_err() instead of monitor_printf()
Both error_report_err() and monitor_printf() print to the same
destination when monitor_printf() is used correctly, i.e. within an
HMP monitor. Elsewhere, monitor_printf() does nothing, while
error_report_err() reports to stderr.
Most changed functions are HMP command handlers. These should only
run within an HMP monitor. The one exception is bdrv_password_cb(),
which should also only run within an HMP monitor.
Four command handlers prefix the error message with the command name:
balloon, migrate_set_capability, migrate_set_parameter, migrate.
Pointless, drop.
Unlike monitor_printf(), error_report_err() uses the error whole
instead of just its message obtained with error_get_pretty(). This
avoids suppressing its hint (see commit 50b7b00). Example:
(qemu) device_add ivshmem,id=666
Parameter 'id' expects an identifier
Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.
Try "help device_add" for more information
The "Identifiers consist of..." line is new with this patch.
Coccinelle semantic patch:
@@
expression M, E;
@@
- monitor_printf(M, "%s\n", error_get_pretty(E));
- error_free(E);
+ error_report_err(E);
@r1@
expression M, E;
format F;
position p;
@@
- monitor_printf(M, "...%@F@\n", error_get_pretty(E));@p
- error_free(E);
+ error_report_err(E);
@script:python@
p << r1.p;
@@
print "%s:%s:%s: prefix dropped" % (p[0].file, p[0].line, p[0].column)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1450452927-8346-4-git-send-email-armbru@redhat.com>
2015-12-18 16:35:06 +01:00
|
|
|
error_report_err(err);
|
2011-12-05 17:48:01 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!detach) {
|
2015-03-13 09:08:39 +01:00
|
|
|
HMPMigrationStatus *status;
|
2011-12-05 17:48:01 +01:00
|
|
|
|
|
|
|
if (monitor_suspend(mon) < 0) {
|
|
|
|
monitor_printf(mon, "terminal does not allow synchronous "
|
|
|
|
"migration, continuing detached\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
status = g_malloc0(sizeof(*status));
|
|
|
|
status->mon = mon;
|
|
|
|
status->is_block_migration = blk || inc;
|
2013-08-21 17:03:08 +02:00
|
|
|
status->timer = timer_new_ms(QEMU_CLOCK_REALTIME, hmp_migrate_status_cb,
|
2011-12-05 17:48:01 +01:00
|
|
|
status);
|
2013-08-21 17:03:08 +02:00
|
|
|
timer_mod(status->timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
|
2011-12-05 17:48:01 +01:00
|
|
|
}
|
|
|
|
}
|
2012-03-29 17:38:50 +02:00
|
|
|
|
2015-03-05 17:24:48 +01:00
|
|
|
void hmp_device_add(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
qmp: Wean off qerror_report()
The traditional QMP command handler interface
int qmp_FOO(Monitor *mon, const QDict *params, QObject **ret_data);
doesn't provide for returning an Error object. Instead, the handler
is expected to stash it in the monitor with qerror_report().
When we rebased QMP on top of QAPI, we didn't change this interface.
Instead, commit 776574d introduced "middle mode" as a temporary aid
for converting existing QMP commands to QAPI one by one. More than
three years later, we're still using it.
Middle mode has two effects:
* Instead of the native input marshallers
static void qmp_marshal_input_FOO(QDict *, QObject **, Error **)
it generates input marshallers conforming to the traditional QMP
command handler interface.
* It suppresses generation of code to register them with
qmp_register_command()
This permits giving them internal linkage.
As long as we need qmp-commands.hx, we can't use the registry behind
qmp_register_command(), so the latter has to stay for now.
The former has to go to get rid of qerror_report(). Changing all QMP
commands to fit the QAPI mold in one go was impractical back when we
started, but by now there are just a few stragglers left:
do_qmp_capabilities(), qmp_qom_set(), qmp_qom_get(), qmp_object_add(),
qmp_netdev_add(), do_device_add().
Switch middle mode to generate native input marshallers, and adapt the
stragglers. Simplifies both the monitor code and the stragglers.
Rename do_qmp_capabilities() to qmp_capabilities(), and
do_device_add() to qmp_device_add, because that's how QMP command
handlers are named today.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-03-13 17:25:50 +01:00
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
qmp_device_add((QDict *)qdict, NULL, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2015-03-05 17:24:48 +01:00
|
|
|
}
|
|
|
|
|
2012-03-29 17:38:50 +02:00
|
|
|
void hmp_device_del(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *id = qdict_get_str(qdict, "id");
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
qmp_device_del(id, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
2012-05-07 06:10:47 +02:00
|
|
|
|
|
|
|
void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2015-05-16 00:25:00 +02:00
|
|
|
bool paging = qdict_get_try_bool(qdict, "paging", false);
|
|
|
|
bool zlib = qdict_get_try_bool(qdict, "zlib", false);
|
|
|
|
bool lzo = qdict_get_try_bool(qdict, "lzo", false);
|
|
|
|
bool snappy = qdict_get_try_bool(qdict, "snappy", false);
|
2012-09-21 18:53:00 +02:00
|
|
|
const char *file = qdict_get_str(qdict, "filename");
|
2012-05-07 06:10:47 +02:00
|
|
|
bool has_begin = qdict_haskey(qdict, "begin");
|
|
|
|
bool has_length = qdict_haskey(qdict, "length");
|
2016-02-18 06:16:47 +01:00
|
|
|
bool has_detach = qdict_haskey(qdict, "detach");
|
2012-05-07 06:10:47 +02:00
|
|
|
int64_t begin = 0;
|
|
|
|
int64_t length = 0;
|
2016-02-18 06:16:47 +01:00
|
|
|
bool detach = false;
|
2014-02-18 07:11:36 +01:00
|
|
|
enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF;
|
2012-09-21 18:53:00 +02:00
|
|
|
char *prot;
|
2012-05-07 06:10:47 +02:00
|
|
|
|
2014-04-17 10:15:07 +02:00
|
|
|
if (zlib + lzo + snappy > 1) {
|
2014-05-02 13:26:29 +02:00
|
|
|
error_setg(&err, "only one of '-z|-l|-s' can be set");
|
|
|
|
hmp_handle_error(mon, &err);
|
2014-04-17 10:15:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zlib) {
|
|
|
|
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lzo) {
|
|
|
|
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (snappy) {
|
|
|
|
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY;
|
|
|
|
}
|
|
|
|
|
2012-05-07 06:10:47 +02:00
|
|
|
if (has_begin) {
|
|
|
|
begin = qdict_get_int(qdict, "begin");
|
|
|
|
}
|
|
|
|
if (has_length) {
|
|
|
|
length = qdict_get_int(qdict, "length");
|
|
|
|
}
|
2016-02-18 06:16:47 +01:00
|
|
|
if (has_detach) {
|
|
|
|
detach = qdict_get_bool(qdict, "detach");
|
|
|
|
}
|
2012-05-07 06:10:47 +02:00
|
|
|
|
2012-09-21 18:53:00 +02:00
|
|
|
prot = g_strconcat("file:", file, NULL);
|
|
|
|
|
2016-02-18 06:16:47 +01:00
|
|
|
qmp_dump_guest_memory(paging, prot, true, detach, has_begin, begin,
|
|
|
|
has_length, length, true, dump_format, &err);
|
2014-05-02 13:26:29 +02:00
|
|
|
hmp_handle_error(mon, &err);
|
2012-09-21 18:53:00 +02:00
|
|
|
g_free(prot);
|
2012-05-07 06:10:47 +02:00
|
|
|
}
|
2012-04-18 22:34:15 +02:00
|
|
|
|
|
|
|
void hmp_netdev_add(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
QemuOpts *opts;
|
|
|
|
|
|
|
|
opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err);
|
2014-01-30 15:07:28 +01:00
|
|
|
if (err) {
|
2012-04-18 22:34:15 +02:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
netdev_add(opts, &err);
|
2014-01-30 15:07:28 +01:00
|
|
|
if (err) {
|
2012-04-18 22:34:15 +02:00
|
|
|
qemu_opts_del(opts);
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
2012-04-16 19:36:32 +02:00
|
|
|
|
|
|
|
void hmp_netdev_del(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *id = qdict_get_str(qdict, "id");
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
qmp_netdev_del(id, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
2012-06-22 20:36:09 +02:00
|
|
|
|
2013-12-20 23:21:10 +01:00
|
|
|
void hmp_object_add(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
QemuOpts *opts;
|
|
|
|
OptsVisitor *ov;
|
2016-02-10 19:40:59 +01:00
|
|
|
Object *obj = NULL;
|
2013-12-20 23:21:10 +01:00
|
|
|
|
|
|
|
opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err);
|
|
|
|
if (err) {
|
2016-02-10 19:40:59 +01:00
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
return;
|
2013-12-20 23:21:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ov = opts_visitor_new(opts);
|
2016-02-10 19:40:59 +01:00
|
|
|
obj = user_creatable_add(qdict, opts_get_visitor(ov), &err);
|
|
|
|
opts_visitor_cleanup(ov);
|
|
|
|
qemu_opts_del(opts);
|
2013-12-20 23:21:10 +01:00
|
|
|
|
|
|
|
if (err) {
|
2016-02-10 19:40:59 +01:00
|
|
|
hmp_handle_error(mon, &err);
|
2013-12-20 23:21:10 +01:00
|
|
|
}
|
2016-02-10 19:40:59 +01:00
|
|
|
if (obj) {
|
|
|
|
object_unref(obj);
|
2013-12-20 23:21:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-22 20:36:09 +02:00
|
|
|
void hmp_getfd(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *fdname = qdict_get_str(qdict, "fdname");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2012-06-22 20:36:09 +02:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_getfd(fdname, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2012-06-22 20:36:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_closefd(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *fdname = qdict_get_str(qdict, "fdname");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2012-06-22 20:36:09 +02:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_closefd(fdname, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2012-06-22 20:36:09 +02:00
|
|
|
}
|
2012-08-31 04:56:26 +02:00
|
|
|
|
hmp: Name HMP command handler functions hmp_COMMAND()
Some are called do_COMMAND() (old ones, usually), some hmp_COMMAND(),
and sometimes COMMAND pointlessly differs in spelling.
Normalize to hmp_COMMAND(), where COMMAND is exactly the command name
with '-' replaced by '_'.
Exceptions:
* do_device_add() and client_migrate_info() *not* renamed to
hmp_device_add(), hmp_client_migrate_info(), because they're also
QMP handlers. They still need to be converted to QAPI.
* do_memory_dump(), do_physical_memory_dump(), do_ioport_read(),
do_ioport_write() renamed do hmp_* instead of hmp_x(), hmp_xp(),
hmp_i(), hmp_o(), because those names are too cryptic for my taste.
* do_info_help() renamed to hmp_info_help() instead of hmp_info(),
because it only covers help.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-02-06 13:55:43 +01:00
|
|
|
void hmp_sendkey(Monitor *mon, const QDict *qdict)
|
2012-08-31 04:56:26 +02:00
|
|
|
{
|
|
|
|
const char *keys = qdict_get_str(qdict, "keys");
|
2012-09-20 19:19:47 +02:00
|
|
|
KeyValueList *keylist, *head = NULL, *tmp = NULL;
|
2012-08-31 04:56:26 +02:00
|
|
|
int has_hold_time = qdict_haskey(qdict, "hold-time");
|
|
|
|
int hold_time = qdict_get_try_int(qdict, "hold-time", -1);
|
|
|
|
Error *err = NULL;
|
|
|
|
char *separator;
|
2012-09-20 19:19:47 +02:00
|
|
|
int keyname_len;
|
2012-08-31 04:56:26 +02:00
|
|
|
|
|
|
|
while (1) {
|
|
|
|
separator = strchr(keys, '-');
|
|
|
|
keyname_len = separator ? separator - keys : strlen(keys);
|
|
|
|
|
|
|
|
/* Be compatible with old interface, convert user inputted "<" */
|
2016-01-13 09:09:58 +01:00
|
|
|
if (keys[0] == '<' && keyname_len == 1) {
|
|
|
|
keys = "less";
|
2012-08-31 04:56:26 +02:00
|
|
|
keyname_len = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
keylist = g_malloc0(sizeof(*keylist));
|
2012-09-20 19:19:47 +02:00
|
|
|
keylist->value = g_malloc0(sizeof(*keylist->value));
|
2012-08-31 04:56:26 +02:00
|
|
|
|
|
|
|
if (!head) {
|
|
|
|
head = keylist;
|
|
|
|
}
|
|
|
|
if (tmp) {
|
|
|
|
tmp->next = keylist;
|
|
|
|
}
|
|
|
|
tmp = keylist;
|
|
|
|
|
2016-01-13 09:09:58 +01:00
|
|
|
if (strstart(keys, "0x", NULL)) {
|
2012-09-20 19:19:47 +02:00
|
|
|
char *endp;
|
2016-01-13 09:09:58 +01:00
|
|
|
int value = strtoul(keys, &endp, 0);
|
|
|
|
assert(endp <= keys + keyname_len);
|
|
|
|
if (endp != keys + keyname_len) {
|
2012-09-20 19:19:47 +02:00
|
|
|
goto err_out;
|
|
|
|
}
|
2015-10-26 23:34:58 +01:00
|
|
|
keylist->value->type = KEY_VALUE_KIND_NUMBER;
|
qapi: Don't special-case simple union wrappers
Simple unions were carrying a special case that hid their 'data'
QMP member from the resulting C struct, via the hack method
QAPISchemaObjectTypeVariant.simple_union_type(). But by using
the work we started by unboxing flat union and alternate
branches, coupled with the ability to visit the members of an
implicit type, we can now expose the simple union's implicit
type in qapi-types.h:
| struct q_obj_ImageInfoSpecificQCow2_wrapper {
| ImageInfoSpecificQCow2 *data;
| };
|
| struct q_obj_ImageInfoSpecificVmdk_wrapper {
| ImageInfoSpecificVmdk *data;
| };
...
| struct ImageInfoSpecific {
| ImageInfoSpecificKind type;
| union { /* union tag is @type */
| void *data;
|- ImageInfoSpecificQCow2 *qcow2;
|- ImageInfoSpecificVmdk *vmdk;
|+ q_obj_ImageInfoSpecificQCow2_wrapper qcow2;
|+ q_obj_ImageInfoSpecificVmdk_wrapper vmdk;
| } u;
| };
Doing this removes asymmetry between QAPI's QMP side and its
C side (both sides now expose 'data'), and means that the
treatment of a simple union as sugar for a flat union is now
equivalent in both languages (previously the two approaches used
a different layer of dereferencing, where the simple union could
be converted to a flat union with equivalent C layout but
different {} on the wire, or to an equivalent QMP wire form
but with different C representation). Using the implicit type
also lets us get rid of the simple_union_type() hack.
Of course, now all clients of simple unions have to adjust from
using su->u.member to using su->u.member.data; while this touches
a number of files in the tree, some earlier cleanup patches
helped minimize the change to the initialization of a temporary
variable rather than every single member access. The generated
qapi-visit.c code is also affected by the layout change:
|@@ -7393,10 +7393,10 @@ void visit_type_ImageInfoSpecific_member
| }
| switch (obj->type) {
| case IMAGE_INFO_SPECIFIC_KIND_QCOW2:
|- visit_type_ImageInfoSpecificQCow2(v, "data", &obj->u.qcow2, &err);
|+ visit_type_q_obj_ImageInfoSpecificQCow2_wrapper_members(v, &obj->u.qcow2, &err);
| break;
| case IMAGE_INFO_SPECIFIC_KIND_VMDK:
|- visit_type_ImageInfoSpecificVmdk(v, "data", &obj->u.vmdk, &err);
|+ visit_type_q_obj_ImageInfoSpecificVmdk_wrapper_members(v, &obj->u.vmdk, &err);
| break;
| default:
| abort();
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-17 23:48:37 +01:00
|
|
|
keylist->value->u.number.data = value;
|
2012-09-20 19:19:47 +02:00
|
|
|
} else {
|
2016-01-13 09:09:58 +01:00
|
|
|
int idx = index_from_key(keys, keyname_len);
|
qapi: Don't let implicit enum MAX member collide
Now that we guarantee the user doesn't have any enum values
beginning with a single underscore, we can use that for our
own purposes. Renaming ENUM_MAX to ENUM__MAX makes it obvious
that the sentinel is generated.
This patch was mostly generated by applying a temporary patch:
|diff --git a/scripts/qapi.py b/scripts/qapi.py
|index e6d014b..b862ec9 100644
|--- a/scripts/qapi.py
|+++ b/scripts/qapi.py
|@@ -1570,6 +1570,7 @@ const char *const %(c_name)s_lookup[] = {
| max_index = c_enum_const(name, 'MAX', prefix)
| ret += mcgen('''
| [%(max_index)s] = NULL,
|+// %(max_index)s
| };
| ''',
| max_index=max_index)
then running:
$ cat qapi-{types,event}.c tests/test-qapi-types.c |
sed -n 's,^// \(.*\)MAX,s|\1MAX|\1_MAX|g,p' > list
$ git grep -l _MAX | xargs sed -i -f list
The only things not generated are the changes in scripts/qapi.py.
Rejecting enum members named 'MAX' is now useless, and will be dropped
in the next patch.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-23-git-send-email-eblake@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
[Rebased to current master, commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 09:52:57 +01:00
|
|
|
if (idx == Q_KEY_CODE__MAX) {
|
2012-09-20 19:19:47 +02:00
|
|
|
goto err_out;
|
|
|
|
}
|
2015-10-26 23:34:58 +01:00
|
|
|
keylist->value->type = KEY_VALUE_KIND_QCODE;
|
qapi: Don't special-case simple union wrappers
Simple unions were carrying a special case that hid their 'data'
QMP member from the resulting C struct, via the hack method
QAPISchemaObjectTypeVariant.simple_union_type(). But by using
the work we started by unboxing flat union and alternate
branches, coupled with the ability to visit the members of an
implicit type, we can now expose the simple union's implicit
type in qapi-types.h:
| struct q_obj_ImageInfoSpecificQCow2_wrapper {
| ImageInfoSpecificQCow2 *data;
| };
|
| struct q_obj_ImageInfoSpecificVmdk_wrapper {
| ImageInfoSpecificVmdk *data;
| };
...
| struct ImageInfoSpecific {
| ImageInfoSpecificKind type;
| union { /* union tag is @type */
| void *data;
|- ImageInfoSpecificQCow2 *qcow2;
|- ImageInfoSpecificVmdk *vmdk;
|+ q_obj_ImageInfoSpecificQCow2_wrapper qcow2;
|+ q_obj_ImageInfoSpecificVmdk_wrapper vmdk;
| } u;
| };
Doing this removes asymmetry between QAPI's QMP side and its
C side (both sides now expose 'data'), and means that the
treatment of a simple union as sugar for a flat union is now
equivalent in both languages (previously the two approaches used
a different layer of dereferencing, where the simple union could
be converted to a flat union with equivalent C layout but
different {} on the wire, or to an equivalent QMP wire form
but with different C representation). Using the implicit type
also lets us get rid of the simple_union_type() hack.
Of course, now all clients of simple unions have to adjust from
using su->u.member to using su->u.member.data; while this touches
a number of files in the tree, some earlier cleanup patches
helped minimize the change to the initialization of a temporary
variable rather than every single member access. The generated
qapi-visit.c code is also affected by the layout change:
|@@ -7393,10 +7393,10 @@ void visit_type_ImageInfoSpecific_member
| }
| switch (obj->type) {
| case IMAGE_INFO_SPECIFIC_KIND_QCOW2:
|- visit_type_ImageInfoSpecificQCow2(v, "data", &obj->u.qcow2, &err);
|+ visit_type_q_obj_ImageInfoSpecificQCow2_wrapper_members(v, &obj->u.qcow2, &err);
| break;
| case IMAGE_INFO_SPECIFIC_KIND_VMDK:
|- visit_type_ImageInfoSpecificVmdk(v, "data", &obj->u.vmdk, &err);
|+ visit_type_q_obj_ImageInfoSpecificVmdk_wrapper_members(v, &obj->u.vmdk, &err);
| break;
| default:
| abort();
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-17 23:48:37 +01:00
|
|
|
keylist->value->u.qcode.data = idx;
|
2012-09-20 19:19:47 +02:00
|
|
|
}
|
|
|
|
|
2012-08-31 04:56:26 +02:00
|
|
|
if (!separator) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
keys = separator + 1;
|
|
|
|
}
|
|
|
|
|
2012-09-20 19:19:47 +02:00
|
|
|
qmp_send_key(head, has_hold_time, hold_time, &err);
|
2012-08-31 04:56:26 +02:00
|
|
|
hmp_handle_error(mon, &err);
|
2012-09-20 19:19:47 +02:00
|
|
|
|
|
|
|
out:
|
|
|
|
qapi_free_KeyValueList(head);
|
|
|
|
return;
|
|
|
|
|
|
|
|
err_out:
|
2016-01-13 09:09:58 +01:00
|
|
|
monitor_printf(mon, "invalid parameter: %.*s\n", keyname_len, keys);
|
2012-09-20 19:19:47 +02:00
|
|
|
goto out;
|
2012-08-31 04:56:26 +02:00
|
|
|
}
|
2012-05-24 18:48:23 +02:00
|
|
|
|
hmp: Name HMP command handler functions hmp_COMMAND()
Some are called do_COMMAND() (old ones, usually), some hmp_COMMAND(),
and sometimes COMMAND pointlessly differs in spelling.
Normalize to hmp_COMMAND(), where COMMAND is exactly the command name
with '-' replaced by '_'.
Exceptions:
* do_device_add() and client_migrate_info() *not* renamed to
hmp_device_add(), hmp_client_migrate_info(), because they're also
QMP handlers. They still need to be converted to QAPI.
* do_memory_dump(), do_physical_memory_dump(), do_ioport_read(),
do_ioport_write() renamed do hmp_* instead of hmp_x(), hmp_xp(),
hmp_i(), hmp_o(), because those names are too cryptic for my taste.
* do_info_help() renamed to hmp_info_help() instead of hmp_info(),
because it only covers help.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-02-06 13:55:43 +01:00
|
|
|
void hmp_screendump(Monitor *mon, const QDict *qdict)
|
2012-05-24 18:48:23 +02:00
|
|
|
{
|
|
|
|
const char *filename = qdict_get_str(qdict, "filename");
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
qmp_screendump(filename, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
2012-08-23 11:53:04 +02:00
|
|
|
|
|
|
|
void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *uri = qdict_get_str(qdict, "uri");
|
2015-05-16 00:25:00 +02:00
|
|
|
bool writable = qdict_get_try_bool(qdict, "writable", false);
|
|
|
|
bool all = qdict_get_try_bool(qdict, "all", false);
|
2012-08-23 11:53:04 +02:00
|
|
|
Error *local_err = NULL;
|
|
|
|
BlockInfoList *block_list, *info;
|
|
|
|
SocketAddress *addr;
|
|
|
|
|
|
|
|
if (writable && !all) {
|
|
|
|
error_setg(&local_err, "-w only valid together with -a");
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* First check if the address is valid and start the server. */
|
|
|
|
addr = socket_parse(uri, &local_err);
|
|
|
|
if (local_err != NULL) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2016-02-10 19:41:14 +01:00
|
|
|
qmp_nbd_server_start(addr, false, NULL, &local_err);
|
2012-08-23 11:53:04 +02:00
|
|
|
qapi_free_SocketAddress(addr);
|
|
|
|
if (local_err != NULL) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!all) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Then try adding all block devices. If one fails, close all and
|
|
|
|
* exit.
|
|
|
|
*/
|
|
|
|
block_list = qmp_query_block(NULL);
|
|
|
|
|
|
|
|
for (info = block_list; info; info = info->next) {
|
|
|
|
if (!info->value->has_inserted) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
qmp_nbd_server_add(info->value->device, true, writable, &local_err);
|
|
|
|
|
|
|
|
if (local_err != NULL) {
|
|
|
|
qmp_nbd_server_stop(NULL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_BlockInfoList(block_list);
|
|
|
|
|
|
|
|
exit:
|
|
|
|
hmp_handle_error(mon, &local_err);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_nbd_server_add(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
2015-05-16 00:25:00 +02:00
|
|
|
bool writable = qdict_get_try_bool(qdict, "writable", false);
|
2012-08-23 11:53:04 +02:00
|
|
|
Error *local_err = NULL;
|
|
|
|
|
|
|
|
qmp_nbd_server_add(device, true, writable, &local_err);
|
|
|
|
|
|
|
|
if (local_err != NULL) {
|
|
|
|
hmp_handle_error(mon, &local_err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2012-08-23 11:53:04 +02:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_nbd_server_stop(&err);
|
|
|
|
hmp_handle_error(mon, &err);
|
2012-08-23 11:53:04 +02:00
|
|
|
}
|
2012-12-19 10:33:40 +01:00
|
|
|
|
2013-12-11 19:24:14 +01:00
|
|
|
void hmp_cpu_add(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
int cpuid;
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
cpuid = qdict_get_int(qdict, "id");
|
|
|
|
qmp_cpu_add(cpuid, &err);
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
|
|
|
|
2012-12-19 10:33:40 +01:00
|
|
|
void hmp_chardev_add(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *args = qdict_get_str(qdict, "args");
|
|
|
|
Error *err = NULL;
|
|
|
|
QemuOpts *opts;
|
|
|
|
|
QemuOpts: Wean off qerror_report_err()
qerror_report_err() is a transitional interface to help with
converting existing monitor commands to QMP. It should not be used
elsewhere.
The only remaining user in qemu-option.c is qemu_opts_parse(). Is it
used in QMP context? If not, we can simply replace
qerror_report_err() by error_report_err().
The uses in qemu-img.c, qemu-io.c, qemu-nbd.c and under tests/ are
clearly not in QMP context.
The uses in vl.c aren't either, because the only QMP command handlers
there are qmp_query_status() and qmp_query_machines(), and they don't
call it.
Remaining uses:
* drive_def(): Command line -drive and such, HMP drive_add and pci_add
* hmp_chardev_add(): HMP chardev-add
* monitor_parse_command(): HMP core
* tmp_config_parse(): Command line -tpmdev
* net_host_device_add(): HMP host_net_add
* net_client_parse(): Command line -net and -netdev
* qemu_global_option(): Command line -global
* vnc_parse_func(): Command line -display, -vnc, default display, HMP
change, QMP change. Bummer.
* qemu_pci_hot_add_nic(): HMP pci_add
* usb_net_init(): Command line -usbdevice, HMP usb_add
Propagate errors through qemu_opts_parse(). Create a convenience
function qemu_opts_parse_noisily() that passes errors to
error_report_err(). Switch all non-QMP users outside tests to it.
That leaves vnc_parse_func(). Propagate errors through it. Since I'm
touching it anyway, rename it to vnc_parse().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-02-13 12:50:26 +01:00
|
|
|
opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"), args, true);
|
2012-12-19 10:33:40 +01:00
|
|
|
if (opts == NULL) {
|
error: Strip trailing '\n' from error string arguments (again)
Commit 6daf194d and be62a2eb got rid of a bunch, but they keep coming
back. Tracked down with this Coccinelle semantic patch:
@r@
expression err, eno, cls, fmt;
position p;
@@
(
error_report(fmt, ...)@p
|
error_set(err, cls, fmt, ...)@p
|
error_set_errno(err, eno, cls, fmt, ...)@p
|
error_setg(err, fmt, ...)@p
|
error_setg_errno(err, eno, fmt, ...)@p
)
@script:python@
fmt << r.fmt;
p << r.p;
@@
if "\\n" in str(fmt):
print "%s:%s:%s:%s" % (p[0].file, p[0].line, p[0].column, fmt)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1360354939-10994-4-git-send-email-armbru@redhat.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-08 21:22:16 +01:00
|
|
|
error_setg(&err, "Parsing chardev args failed");
|
2012-12-19 10:33:40 +01:00
|
|
|
} else {
|
|
|
|
qemu_chr_new_from_opts(opts, NULL, &err);
|
|
|
|
}
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *local_err = NULL;
|
|
|
|
|
|
|
|
qmp_chardev_remove(qdict_get_str(qdict, "id"), &local_err);
|
|
|
|
hmp_handle_error(mon, &local_err);
|
|
|
|
}
|
2013-06-05 14:19:41 +02:00
|
|
|
|
|
|
|
void hmp_qemu_io(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
2015-02-05 19:58:22 +01:00
|
|
|
BlockBackend *blk;
|
2013-06-05 14:19:41 +02:00
|
|
|
const char* device = qdict_get_str(qdict, "device");
|
|
|
|
const char* command = qdict_get_str(qdict, "command");
|
|
|
|
Error *err = NULL;
|
|
|
|
|
2015-02-05 19:58:22 +01:00
|
|
|
blk = blk_by_name(device);
|
|
|
|
if (blk) {
|
|
|
|
qemuio_command(blk, command);
|
2013-06-05 14:19:41 +02:00
|
|
|
} else {
|
2015-03-16 08:57:47 +01:00
|
|
|
error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND,
|
|
|
|
"Device '%s' not found", device);
|
2013-06-05 14:19:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
2013-12-20 23:21:09 +01:00
|
|
|
|
|
|
|
void hmp_object_del(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *id = qdict_get_str(qdict, "id");
|
|
|
|
Error *err = NULL;
|
|
|
|
|
2016-02-10 19:40:59 +01:00
|
|
|
user_creatable_del(id, &err);
|
2013-12-20 23:21:09 +01:00
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
2014-05-14 11:43:35 +02:00
|
|
|
|
|
|
|
void hmp_info_memdev(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
MemdevList *memdev_list = qmp_query_memdev(&err);
|
|
|
|
MemdevList *m = memdev_list;
|
|
|
|
StringOutputVisitor *ov;
|
2014-08-18 08:46:34 +02:00
|
|
|
char *str;
|
2014-05-14 11:43:35 +02:00
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
|
|
while (m) {
|
|
|
|
ov = string_output_visitor_new(false);
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 14:48:54 +01:00
|
|
|
visit_type_uint16List(string_output_get_visitor(ov), NULL,
|
|
|
|
&m->value->host_nodes, NULL);
|
2014-06-19 16:14:43 +02:00
|
|
|
monitor_printf(mon, "memory backend: %d\n", i);
|
2014-05-14 11:43:35 +02:00
|
|
|
monitor_printf(mon, " size: %" PRId64 "\n", m->value->size);
|
|
|
|
monitor_printf(mon, " merge: %s\n",
|
|
|
|
m->value->merge ? "true" : "false");
|
|
|
|
monitor_printf(mon, " dump: %s\n",
|
|
|
|
m->value->dump ? "true" : "false");
|
|
|
|
monitor_printf(mon, " prealloc: %s\n",
|
|
|
|
m->value->prealloc ? "true" : "false");
|
|
|
|
monitor_printf(mon, " policy: %s\n",
|
|
|
|
HostMemPolicy_lookup[m->value->policy]);
|
2014-08-18 08:46:34 +02:00
|
|
|
str = string_output_get_string(ov);
|
|
|
|
monitor_printf(mon, " host nodes: %s\n", str);
|
2014-05-14 11:43:35 +02:00
|
|
|
|
2014-08-18 08:46:34 +02:00
|
|
|
g_free(str);
|
2014-05-14 11:43:35 +02:00
|
|
|
string_output_visitor_cleanup(ov);
|
|
|
|
m = m->next;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "\n");
|
2014-08-18 08:46:35 +02:00
|
|
|
|
|
|
|
qapi_free_MemdevList(memdev_list);
|
2014-05-14 11:43:35 +02:00
|
|
|
}
|
2014-09-23 07:35:19 +02:00
|
|
|
|
|
|
|
void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
MemoryDeviceInfoList *info_list = qmp_query_memory_devices(&err);
|
|
|
|
MemoryDeviceInfoList *info;
|
|
|
|
MemoryDeviceInfo *value;
|
|
|
|
PCDIMMDeviceInfo *di;
|
|
|
|
|
|
|
|
for (info = info_list; info; info = info->next) {
|
|
|
|
value = info->value;
|
|
|
|
|
|
|
|
if (value) {
|
2015-10-26 23:34:59 +01:00
|
|
|
switch (value->type) {
|
2014-09-23 07:35:19 +02:00
|
|
|
case MEMORY_DEVICE_INFO_KIND_DIMM:
|
qapi: Don't special-case simple union wrappers
Simple unions were carrying a special case that hid their 'data'
QMP member from the resulting C struct, via the hack method
QAPISchemaObjectTypeVariant.simple_union_type(). But by using
the work we started by unboxing flat union and alternate
branches, coupled with the ability to visit the members of an
implicit type, we can now expose the simple union's implicit
type in qapi-types.h:
| struct q_obj_ImageInfoSpecificQCow2_wrapper {
| ImageInfoSpecificQCow2 *data;
| };
|
| struct q_obj_ImageInfoSpecificVmdk_wrapper {
| ImageInfoSpecificVmdk *data;
| };
...
| struct ImageInfoSpecific {
| ImageInfoSpecificKind type;
| union { /* union tag is @type */
| void *data;
|- ImageInfoSpecificQCow2 *qcow2;
|- ImageInfoSpecificVmdk *vmdk;
|+ q_obj_ImageInfoSpecificQCow2_wrapper qcow2;
|+ q_obj_ImageInfoSpecificVmdk_wrapper vmdk;
| } u;
| };
Doing this removes asymmetry between QAPI's QMP side and its
C side (both sides now expose 'data'), and means that the
treatment of a simple union as sugar for a flat union is now
equivalent in both languages (previously the two approaches used
a different layer of dereferencing, where the simple union could
be converted to a flat union with equivalent C layout but
different {} on the wire, or to an equivalent QMP wire form
but with different C representation). Using the implicit type
also lets us get rid of the simple_union_type() hack.
Of course, now all clients of simple unions have to adjust from
using su->u.member to using su->u.member.data; while this touches
a number of files in the tree, some earlier cleanup patches
helped minimize the change to the initialization of a temporary
variable rather than every single member access. The generated
qapi-visit.c code is also affected by the layout change:
|@@ -7393,10 +7393,10 @@ void visit_type_ImageInfoSpecific_member
| }
| switch (obj->type) {
| case IMAGE_INFO_SPECIFIC_KIND_QCOW2:
|- visit_type_ImageInfoSpecificQCow2(v, "data", &obj->u.qcow2, &err);
|+ visit_type_q_obj_ImageInfoSpecificQCow2_wrapper_members(v, &obj->u.qcow2, &err);
| break;
| case IMAGE_INFO_SPECIFIC_KIND_VMDK:
|- visit_type_ImageInfoSpecificVmdk(v, "data", &obj->u.vmdk, &err);
|+ visit_type_q_obj_ImageInfoSpecificVmdk_wrapper_members(v, &obj->u.vmdk, &err);
| break;
| default:
| abort();
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-17 23:48:37 +01:00
|
|
|
di = value->u.dimm.data;
|
2014-09-23 07:35:19 +02:00
|
|
|
|
|
|
|
monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
|
2015-10-26 23:34:59 +01:00
|
|
|
MemoryDeviceInfoKind_lookup[value->type],
|
2014-09-23 07:35:19 +02:00
|
|
|
di->id ? di->id : "");
|
|
|
|
monitor_printf(mon, " addr: 0x%" PRIx64 "\n", di->addr);
|
|
|
|
monitor_printf(mon, " slot: %" PRId64 "\n", di->slot);
|
|
|
|
monitor_printf(mon, " node: %" PRId64 "\n", di->node);
|
|
|
|
monitor_printf(mon, " size: %" PRIu64 "\n", di->size);
|
|
|
|
monitor_printf(mon, " memdev: %s\n", di->memdev);
|
|
|
|
monitor_printf(mon, " hotplugged: %s\n",
|
|
|
|
di->hotplugged ? "true" : "false");
|
|
|
|
monitor_printf(mon, " hotpluggable: %s\n",
|
|
|
|
di->hotpluggable ? "true" : "false");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_MemoryDeviceInfoList(info_list);
|
|
|
|
}
|
2014-05-07 18:08:29 +02:00
|
|
|
|
2015-06-26 10:07:13 +02:00
|
|
|
void hmp_info_iothreads(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
IOThreadInfoList *info_list = qmp_query_iothreads(NULL);
|
|
|
|
IOThreadInfoList *info;
|
|
|
|
|
|
|
|
for (info = info_list; info; info = info->next) {
|
|
|
|
monitor_printf(mon, "%s: thread_id=%" PRId64 "\n",
|
|
|
|
info->value->id, info->value->thread_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_IOThreadInfoList(info_list);
|
|
|
|
}
|
|
|
|
|
2014-05-07 18:08:29 +02:00
|
|
|
void hmp_qom_list(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *path = qdict_get_try_str(qdict, "path");
|
|
|
|
ObjectPropertyInfoList *list;
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
if (path == NULL) {
|
|
|
|
monitor_printf(mon, "/\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
list = qmp_qom_list(path, &err);
|
|
|
|
if (err == NULL) {
|
|
|
|
ObjectPropertyInfoList *start = list;
|
|
|
|
while (list != NULL) {
|
|
|
|
ObjectPropertyInfo *value = list->value;
|
|
|
|
|
|
|
|
monitor_printf(mon, "%s (%s)\n",
|
|
|
|
value->name, value->type);
|
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
qapi_free_ObjectPropertyInfoList(start);
|
|
|
|
}
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
2014-05-07 19:48:15 +02:00
|
|
|
|
|
|
|
void hmp_qom_set(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *path = qdict_get_str(qdict, "path");
|
|
|
|
const char *property = qdict_get_str(qdict, "property");
|
|
|
|
const char *value = qdict_get_str(qdict, "value");
|
|
|
|
Error *err = NULL;
|
|
|
|
bool ambiguous = false;
|
|
|
|
Object *obj;
|
|
|
|
|
|
|
|
obj = object_resolve_path(path, &ambiguous);
|
|
|
|
if (obj == NULL) {
|
2015-03-16 08:57:47 +01:00
|
|
|
error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND,
|
|
|
|
"Device '%s' not found", path);
|
2014-05-07 19:48:15 +02:00
|
|
|
} else {
|
|
|
|
if (ambiguous) {
|
|
|
|
monitor_printf(mon, "Warning: Path '%s' is ambiguous\n", path);
|
|
|
|
}
|
|
|
|
object_property_parse(obj, value, property, &err);
|
|
|
|
}
|
|
|
|
hmp_handle_error(mon, &err);
|
|
|
|
}
|
2015-06-11 03:21:21 +02:00
|
|
|
|
|
|
|
void hmp_rocker(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
|
|
|
RockerSwitch *rocker;
|
2015-12-18 16:35:27 +01:00
|
|
|
Error *err = NULL;
|
2015-06-11 03:21:21 +02:00
|
|
|
|
2015-12-18 16:35:27 +01:00
|
|
|
rocker = qmp_query_rocker(name, &err);
|
|
|
|
if (err != NULL) {
|
|
|
|
hmp_handle_error(mon, &err);
|
2015-06-11 03:21:21 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "name: %s\n", rocker->name);
|
|
|
|
monitor_printf(mon, "id: 0x%" PRIx64 "\n", rocker->id);
|
|
|
|
monitor_printf(mon, "ports: %d\n", rocker->ports);
|
|
|
|
|
|
|
|
qapi_free_RockerSwitch(rocker);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_rocker_ports(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
RockerPortList *list, *port;
|
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
2015-12-18 16:35:27 +01:00
|
|
|
Error *err = NULL;
|
2015-06-11 03:21:21 +02:00
|
|
|
|
2015-12-18 16:35:27 +01:00
|
|
|
list = qmp_query_rocker_ports(name, &err);
|
|
|
|
if (err != NULL) {
|
|
|
|
hmp_handle_error(mon, &err);
|
2015-06-11 03:21:21 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, " ena/ speed/ auto\n");
|
|
|
|
monitor_printf(mon, " port link duplex neg?\n");
|
|
|
|
|
|
|
|
for (port = list; port; port = port->next) {
|
|
|
|
monitor_printf(mon, "%10s %-4s %-3s %2s %-3s\n",
|
|
|
|
port->value->name,
|
|
|
|
port->value->enabled ? port->value->link_up ?
|
|
|
|
"up" : "down" : "!ena",
|
|
|
|
port->value->speed == 10000 ? "10G" : "??",
|
|
|
|
port->value->duplex ? "FD" : "HD",
|
|
|
|
port->value->autoneg ? "Yes" : "No");
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_RockerPortList(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_rocker_of_dpa_flows(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
RockerOfDpaFlowList *list, *info;
|
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
|
|
|
uint32_t tbl_id = qdict_get_try_int(qdict, "tbl_id", -1);
|
2015-12-18 16:35:27 +01:00
|
|
|
Error *err = NULL;
|
2015-06-11 03:21:21 +02:00
|
|
|
|
2015-12-18 16:35:27 +01:00
|
|
|
list = qmp_query_rocker_of_dpa_flows(name, tbl_id != -1, tbl_id, &err);
|
|
|
|
if (err != NULL) {
|
|
|
|
hmp_handle_error(mon, &err);
|
2015-06-11 03:21:21 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "prio tbl hits key(mask) --> actions\n");
|
|
|
|
|
|
|
|
for (info = list; info; info = info->next) {
|
|
|
|
RockerOfDpaFlow *flow = info->value;
|
|
|
|
RockerOfDpaFlowKey *key = flow->key;
|
|
|
|
RockerOfDpaFlowMask *mask = flow->mask;
|
|
|
|
RockerOfDpaFlowAction *action = flow->action;
|
|
|
|
|
|
|
|
if (flow->hits) {
|
|
|
|
monitor_printf(mon, "%-4d %-3d %-4" PRIu64,
|
|
|
|
key->priority, key->tbl_id, flow->hits);
|
|
|
|
} else {
|
|
|
|
monitor_printf(mon, "%-4d %-3d ",
|
|
|
|
key->priority, key->tbl_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_in_pport) {
|
|
|
|
monitor_printf(mon, " pport %d", key->in_pport);
|
|
|
|
if (mask->has_in_pport) {
|
|
|
|
monitor_printf(mon, "(0x%x)", mask->in_pport);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_vlan_id) {
|
|
|
|
monitor_printf(mon, " vlan %d",
|
|
|
|
key->vlan_id & VLAN_VID_MASK);
|
|
|
|
if (mask->has_vlan_id) {
|
|
|
|
monitor_printf(mon, "(0x%x)", mask->vlan_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_tunnel_id) {
|
|
|
|
monitor_printf(mon, " tunnel %d", key->tunnel_id);
|
|
|
|
if (mask->has_tunnel_id) {
|
|
|
|
monitor_printf(mon, "(0x%x)", mask->tunnel_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_eth_type) {
|
|
|
|
switch (key->eth_type) {
|
|
|
|
case 0x0806:
|
|
|
|
monitor_printf(mon, " ARP");
|
|
|
|
break;
|
|
|
|
case 0x0800:
|
|
|
|
monitor_printf(mon, " IP");
|
|
|
|
break;
|
|
|
|
case 0x86dd:
|
|
|
|
monitor_printf(mon, " IPv6");
|
|
|
|
break;
|
|
|
|
case 0x8809:
|
|
|
|
monitor_printf(mon, " LACP");
|
|
|
|
break;
|
|
|
|
case 0x88cc:
|
|
|
|
monitor_printf(mon, " LLDP");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
monitor_printf(mon, " eth type 0x%04x", key->eth_type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_eth_src) {
|
|
|
|
if ((strcmp(key->eth_src, "01:00:00:00:00:00") == 0) &&
|
|
|
|
(mask->has_eth_src) &&
|
|
|
|
(strcmp(mask->eth_src, "01:00:00:00:00:00") == 0)) {
|
|
|
|
monitor_printf(mon, " src <any mcast/bcast>");
|
|
|
|
} else if ((strcmp(key->eth_src, "00:00:00:00:00:00") == 0) &&
|
|
|
|
(mask->has_eth_src) &&
|
|
|
|
(strcmp(mask->eth_src, "01:00:00:00:00:00") == 0)) {
|
|
|
|
monitor_printf(mon, " src <any ucast>");
|
|
|
|
} else {
|
|
|
|
monitor_printf(mon, " src %s", key->eth_src);
|
|
|
|
if (mask->has_eth_src) {
|
|
|
|
monitor_printf(mon, "(%s)", mask->eth_src);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_eth_dst) {
|
|
|
|
if ((strcmp(key->eth_dst, "01:00:00:00:00:00") == 0) &&
|
|
|
|
(mask->has_eth_dst) &&
|
|
|
|
(strcmp(mask->eth_dst, "01:00:00:00:00:00") == 0)) {
|
|
|
|
monitor_printf(mon, " dst <any mcast/bcast>");
|
|
|
|
} else if ((strcmp(key->eth_dst, "00:00:00:00:00:00") == 0) &&
|
|
|
|
(mask->has_eth_dst) &&
|
|
|
|
(strcmp(mask->eth_dst, "01:00:00:00:00:00") == 0)) {
|
|
|
|
monitor_printf(mon, " dst <any ucast>");
|
|
|
|
} else {
|
|
|
|
monitor_printf(mon, " dst %s", key->eth_dst);
|
|
|
|
if (mask->has_eth_dst) {
|
|
|
|
monitor_printf(mon, "(%s)", mask->eth_dst);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_ip_proto) {
|
|
|
|
monitor_printf(mon, " proto %d", key->ip_proto);
|
|
|
|
if (mask->has_ip_proto) {
|
|
|
|
monitor_printf(mon, "(0x%x)", mask->ip_proto);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_ip_tos) {
|
|
|
|
monitor_printf(mon, " TOS %d", key->ip_tos);
|
|
|
|
if (mask->has_ip_tos) {
|
|
|
|
monitor_printf(mon, "(0x%x)", mask->ip_tos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_ip_dst) {
|
|
|
|
monitor_printf(mon, " dst %s", key->ip_dst);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action->has_goto_tbl || action->has_group_id ||
|
|
|
|
action->has_new_vlan_id) {
|
|
|
|
monitor_printf(mon, " -->");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action->has_new_vlan_id) {
|
|
|
|
monitor_printf(mon, " apply new vlan %d",
|
|
|
|
ntohs(action->new_vlan_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action->has_group_id) {
|
|
|
|
monitor_printf(mon, " write group 0x%08x", action->group_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action->has_goto_tbl) {
|
|
|
|
monitor_printf(mon, " goto tbl %d", action->goto_tbl);
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_RockerOfDpaFlowList(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
RockerOfDpaGroupList *list, *g;
|
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
|
|
|
uint8_t type = qdict_get_try_int(qdict, "type", 9);
|
2015-12-18 16:35:27 +01:00
|
|
|
Error *err = NULL;
|
2015-06-11 03:21:21 +02:00
|
|
|
bool set = false;
|
|
|
|
|
2015-12-18 16:35:27 +01:00
|
|
|
list = qmp_query_rocker_of_dpa_groups(name, type != 9, type, &err);
|
|
|
|
if (err != NULL) {
|
|
|
|
hmp_handle_error(mon, &err);
|
2015-06-11 03:21:21 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "id (decode) --> buckets\n");
|
|
|
|
|
|
|
|
for (g = list; g; g = g->next) {
|
|
|
|
RockerOfDpaGroup *group = g->value;
|
|
|
|
|
|
|
|
monitor_printf(mon, "0x%08x", group->id);
|
|
|
|
|
|
|
|
monitor_printf(mon, " (type %s", group->type == 0 ? "L2 interface" :
|
|
|
|
group->type == 1 ? "L2 rewrite" :
|
|
|
|
group->type == 2 ? "L3 unicast" :
|
|
|
|
group->type == 3 ? "L2 multicast" :
|
|
|
|
group->type == 4 ? "L2 flood" :
|
|
|
|
group->type == 5 ? "L3 interface" :
|
|
|
|
group->type == 6 ? "L3 multicast" :
|
|
|
|
group->type == 7 ? "L3 ECMP" :
|
|
|
|
group->type == 8 ? "L2 overlay" :
|
|
|
|
"unknown");
|
|
|
|
|
|
|
|
if (group->has_vlan_id) {
|
|
|
|
monitor_printf(mon, " vlan %d", group->vlan_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_pport) {
|
|
|
|
monitor_printf(mon, " pport %d", group->pport);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_index) {
|
|
|
|
monitor_printf(mon, " index %d", group->index);
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, ") -->");
|
|
|
|
|
|
|
|
if (group->has_set_vlan_id && group->set_vlan_id) {
|
|
|
|
set = true;
|
|
|
|
monitor_printf(mon, " set vlan %d",
|
|
|
|
group->set_vlan_id & VLAN_VID_MASK);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_set_eth_src) {
|
|
|
|
if (!set) {
|
|
|
|
set = true;
|
|
|
|
monitor_printf(mon, " set");
|
|
|
|
}
|
|
|
|
monitor_printf(mon, " src %s", group->set_eth_src);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_set_eth_dst) {
|
|
|
|
if (!set) {
|
|
|
|
set = true;
|
|
|
|
monitor_printf(mon, " set");
|
|
|
|
}
|
|
|
|
monitor_printf(mon, " dst %s", group->set_eth_dst);
|
|
|
|
}
|
|
|
|
|
|
|
|
set = false;
|
|
|
|
|
|
|
|
if (group->has_ttl_check && group->ttl_check) {
|
|
|
|
monitor_printf(mon, " check TTL");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_group_id && group->group_id) {
|
|
|
|
monitor_printf(mon, " group id 0x%08x", group->group_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_pop_vlan && group->pop_vlan) {
|
|
|
|
monitor_printf(mon, " pop vlan");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_out_pport) {
|
|
|
|
monitor_printf(mon, " out pport %d", group->out_pport);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_group_ids) {
|
|
|
|
struct uint32List *id;
|
|
|
|
|
|
|
|
monitor_printf(mon, " groups [");
|
|
|
|
for (id = group->group_ids; id; id = id->next) {
|
|
|
|
monitor_printf(mon, "0x%08x", id->value);
|
|
|
|
if (id->next) {
|
|
|
|
monitor_printf(mon, ",");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "]");
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_RockerOfDpaGroupList(list);
|
|
|
|
}
|
2016-02-18 06:16:55 +01:00
|
|
|
|
|
|
|
void hmp_info_dump(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
DumpQueryResult *result = qmp_query_dump(NULL);
|
|
|
|
|
|
|
|
assert(result && result->status < DUMP_STATUS__MAX);
|
|
|
|
monitor_printf(mon, "Status: %s\n", DumpStatus_lookup[result->status]);
|
|
|
|
|
|
|
|
if (result->status == DUMP_STATUS_ACTIVE) {
|
|
|
|
float percent = 0;
|
|
|
|
assert(result->total != 0);
|
|
|
|
percent = 100.0 * result->completed / result->total;
|
|
|
|
monitor_printf(mon, "Finished: %.2f %%\n", percent);
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_DumpQueryResult(result);
|
|
|
|
}
|