#include "hmp.h"
#include "net/net.h"
#include "sysemu/char.h"
+#include "sysemu/block-backend.h"
#include "qemu/option.h"
#include "qemu/timer.h"
#include "qmp-commands.h"
#include "block/qapi.h"
#include "qemu-io.h"
+#ifdef CONFIG_SPICE
+#include <spice/enums.h>
+#endif
+
static void hmp_handle_error(Monitor *mon, Error **errp)
{
assert(errp);
qapi_free_CpuInfoList(cpu_list);
}
+static void print_block_info(Monitor *mon, BlockInfo *info,
+ BlockDeviceInfo *inserted, bool verbose)
+{
+ ImageInfo *image_info;
+
+ 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>");
+ }
+
+ 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");
+ }
+
+ 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]);
+ }
+
+ if (info->removable) {
+ monitor_printf(mon, " Removable device: %slocked, tray %s\n",
+ info->locked ? "" : "not ",
+ info->tray_open ? "open" : "closed");
+ }
+ }
+
+
+ if (!inserted) {
+ return;
+ }
+
+ 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);
+ }
+
+ if (inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) {
+ monitor_printf(mon, " Detect zeroes: %s\n",
+ BlockdevDetectZeroesOptions_lookup[inserted->detect_zeroes]);
+ }
+
+ 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
+ " iops_size=%" PRId64 "\n",
+ 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,
+ inserted->iops_size);
+ }
+
+ if (verbose) {
+ 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;
+ }
+ }
+ }
+}
+
void hmp_info_block(Monitor *mon, const QDict *qdict)
{
BlockInfoList *block_list, *info;
- ImageInfo *image_info;
+ BlockDeviceInfoList *blockdev_list, *blockdev;
const char *device = qdict_get_try_str(qdict, "device");
bool verbose = qdict_get_try_bool(qdict, "verbose", 0);
+ bool nodes = qdict_get_try_bool(qdict, "nodes", 0);
+ bool printed = false;
- block_list = qmp_query_block(NULL);
+ /* Print BlockBackend information */
+ if (!nodes) {
+ block_list = qmp_query_block(NULL);
+ } else {
+ block_list = NULL;
+ }
for (info = block_list; info; info = info->next) {
if (device && strcmp(device, info->value->device)) {
monitor_printf(mon, "\n");
}
- monitor_printf(mon, "%s", info->value->device);
- if (info->value->has_inserted) {
- monitor_printf(mon, ": %s (%s%s%s)\n",
- info->value->inserted->file,
- info->value->inserted->drv,
- info->value->inserted->ro ? ", read-only" : "",
- info->value->inserted->encrypted ? ", encrypted" : "");
- } else {
- monitor_printf(mon, ": [not inserted]\n");
- }
-
- if (info->value->has_io_status && info->value->io_status != BLOCK_DEVICE_IO_STATUS_OK) {
- monitor_printf(mon, " I/O status: %s\n",
- BlockDeviceIoStatus_lookup[info->value->io_status]);
- }
+ print_block_info(mon, info->value, info->value->has_inserted
+ ? info->value->inserted : NULL,
+ verbose);
+ printed = true;
+ }
- if (info->value->removable) {
- monitor_printf(mon, " Removable device: %slocked, tray %s\n",
- info->value->locked ? "" : "not ",
- info->value->tray_open ? "open" : "closed");
- }
+ qapi_free_BlockInfoList(block_list);
+ if ((!device && !nodes) || printed) {
+ return;
+ }
- if (!info->value->has_inserted) {
+ /* 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 (info->value->inserted->has_backing_file) {
- monitor_printf(mon,
- " Backing file: %s "
- "(chain depth: %" PRId64 ")\n",
- info->value->inserted->backing_file,
- info->value->inserted->backing_file_depth);
- }
-
- if (info->value->inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) {
- monitor_printf(mon, " Detect zeroes: %s\n",
- BlockdevDetectZeroesOptions_lookup[info->value->inserted->detect_zeroes]);
- }
-
- if (info->value->inserted->bps
- || info->value->inserted->bps_rd
- || info->value->inserted->bps_wr
- || info->value->inserted->iops
- || info->value->inserted->iops_rd
- || info->value->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
- " iops_size=%" PRId64 "\n",
- info->value->inserted->bps,
- info->value->inserted->bps_rd,
- info->value->inserted->bps_wr,
- info->value->inserted->bps_max,
- info->value->inserted->bps_rd_max,
- info->value->inserted->bps_wr_max,
- info->value->inserted->iops,
- info->value->inserted->iops_rd,
- info->value->inserted->iops_wr,
- info->value->inserted->iops_max,
- info->value->inserted->iops_rd_max,
- info->value->inserted->iops_wr_max,
- info->value->inserted->iops_size);
+ if (blockdev != blockdev_list) {
+ monitor_printf(mon, "\n");
}
- if (verbose) {
- monitor_printf(mon, "\nImages:\n");
- image_info = info->value->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;
- }
- }
- }
+ print_block_info(mon, NULL, blockdev->value, verbose);
}
-
- qapi_free_BlockInfoList(block_list);
+ qapi_free_BlockDeviceInfoList(blockdev_list);
}
void hmp_info_blockstats(Monitor *mon, const QDict *qdict)
{
BlockStatsList *stats_list, *stats;
- stats_list = qmp_query_blockstats(NULL);
+ stats_list = qmp_query_blockstats(false, false, NULL);
for (stats = stats_list; stats; stats = stats->next) {
if (!stats->value->has_device) {
" wr_total_time_ns=%" PRId64
" rd_total_time_ns=%" PRId64
" flush_total_time_ns=%" PRId64
+ " rd_merged=%" PRId64
+ " wr_merged=%" PRId64
"\n",
stats->value->stats->rd_bytes,
stats->value->stats->wr_bytes,
stats->value->stats->flush_operations,
stats->value->stats->wr_total_time_ns,
stats->value->stats->rd_total_time_ns,
- stats->value->stats->flush_total_time_ns);
+ stats->value->stats->flush_total_time_ns,
+ stats->value->stats->rd_merged,
+ stats->value->stats->wr_merged);
}
qapi_free_BlockStatsList(stats_list);
qapi_free_VncInfo(info);
}
+#ifdef CONFIG_SPICE
void hmp_info_spice(Monitor *mon, const QDict *qdict)
{
SpiceChannelList *chan;
SpiceInfo *info;
+ 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",
+#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. */
+ [SPICE_CHANNEL_WEBDAV] = "webdav",
+#endif
+ };
info = qmp_query_spice(NULL);
chan->value->connection_id);
monitor_printf(mon, " channel: %" PRId64 ":%" PRId64 "\n",
chan->value->channel_type, chan->value->channel_id);
+
+ 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);
}
}
out:
qapi_free_SpiceInfo(info);
}
+#endif
void hmp_info_balloon(Monitor *mon, const QDict *qdict)
{
}
list = list->next;
}
+
+ qapi_free_BlockJobInfoList(list);
}
void hmp_info_tpm(Monitor *mon, const QDict *qdict)
qmp_system_wakeup(NULL);
}
-void hmp_inject_nmi(Monitor *mon, const QDict *qdict)
+void hmp_nmi(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
hmp_handle_error(mon, &err);
}
-void hmp_send_key(Monitor *mon, const QDict *qdict)
+void hmp_sendkey(Monitor *mon, const QDict *qdict)
{
const char *keys = qdict_get_str(qdict, "keys");
KeyValueList *keylist, *head = NULL, *tmp = NULL;
goto out;
}
-void hmp_screen_dump(Monitor *mon, const QDict *qdict)
+void hmp_screendump(Monitor *mon, const QDict *qdict)
{
const char *filename = qdict_get_str(qdict, "filename");
Error *err = NULL;
void hmp_qemu_io(Monitor *mon, const QDict *qdict)
{
- BlockDriverState *bs;
+ BlockBackend *blk;
const char* device = qdict_get_str(qdict, "device");
const char* command = qdict_get_str(qdict, "command");
Error *err = NULL;
- bs = bdrv_find(device);
- if (bs) {
- qemuio_command(bs, command);
+ blk = blk_by_name(device);
+ if (blk) {
+ qemuio_command(blk, command);
} else {
error_set(&err, QERR_DEVICE_NOT_FOUND, device);
}
qapi_free_MemdevList(memdev_list);
}
+
+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) {
+ switch (value->kind) {
+ case MEMORY_DEVICE_INFO_KIND_DIMM:
+ di = value->dimm;
+
+ monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
+ MemoryDeviceInfoKind_lookup[value->kind],
+ 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);
+}