mirror of https://gitee.com/openkylin/qemu.git
monitor/hmp: move hmp_info_block* to block-hmp-cmds.c
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Message-Id: <20200308092440.23564-11-mlevitsk@redhat.com> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
This commit is contained in:
parent
1061f8dd80
commit
2bcad73c4b
|
@ -46,10 +46,12 @@
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
#include "qemu/option.h"
|
#include "qemu/option.h"
|
||||||
#include "qemu/sockets.h"
|
#include "qemu/sockets.h"
|
||||||
|
#include "qemu/cutils.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "monitor/monitor.h"
|
#include "monitor/monitor.h"
|
||||||
#include "monitor/hmp.h"
|
#include "monitor/hmp.h"
|
||||||
#include "block/nbd.h"
|
#include "block/nbd.h"
|
||||||
|
#include "block/qapi.h"
|
||||||
#include "block/block_int.h"
|
#include "block/block_int.h"
|
||||||
#include "block/block-hmp-cmds.h"
|
#include "block/block-hmp-cmds.h"
|
||||||
#include "qemu-io.h"
|
#include "qemu-io.h"
|
||||||
|
@ -594,3 +596,390 @@ fail:
|
||||||
blk_unref(local_blk);
|
blk_unref(local_blk);
|
||||||
hmp_handle_error(mon, err);
|
hmp_handle_error(mon, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 && *info->device) {
|
||||||
|
monitor_printf(mon, "%s", info->device);
|
||||||
|
if (inserted && inserted->has_node_name) {
|
||||||
|
monitor_printf(mon, " (%s)", inserted->node_name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(info || inserted);
|
||||||
|
monitor_printf(mon, "%s",
|
||||||
|
inserted && inserted->has_node_name ? inserted->node_name
|
||||||
|
: info && info->has_qdev ? info->qdev
|
||||||
|
: "<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_qdev) {
|
||||||
|
monitor_printf(mon, " Attached to: %s\n", info->qdev);
|
||||||
|
}
|
||||||
|
if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) {
|
||||||
|
monitor_printf(mon, " I/O status: %s\n",
|
||||||
|
BlockDeviceIoStatus_str(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_str(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
|
||||||
|
" group=%s\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,
|
||||||
|
inserted->group);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
monitor_printf(mon, "\nImages:\n");
|
||||||
|
image_info = inserted->image;
|
||||||
|
while (1) {
|
||||||
|
bdrv_image_info_dump(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;
|
||||||
|
BlockDeviceInfoList *blockdev_list, *blockdev;
|
||||||
|
const char *device = qdict_get_try_str(qdict, "device");
|
||||||
|
bool verbose = qdict_get_try_bool(qdict, "verbose", false);
|
||||||
|
bool nodes = qdict_get_try_bool(qdict, "nodes", false);
|
||||||
|
bool printed = false;
|
||||||
|
|
||||||
|
/* 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)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info != block_list) {
|
||||||
|
monitor_printf(mon, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
print_block_info(mon, info->value, info->value->has_inserted
|
||||||
|
? info->value->inserted : NULL,
|
||||||
|
verbose);
|
||||||
|
printed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
qapi_free_BlockInfoList(block_list);
|
||||||
|
|
||||||
|
if ((!device && !nodes) || printed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print node information */
|
||||||
|
blockdev_list = qmp_query_named_block_nodes(false, false, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hmp_info_blockstats(Monitor *mon, const QDict *qdict)
|
||||||
|
{
|
||||||
|
BlockStatsList *stats_list, *stats;
|
||||||
|
|
||||||
|
stats_list = qmp_query_blockstats(false, false, NULL);
|
||||||
|
|
||||||
|
for (stats = stats_list; stats; stats = stats->next) {
|
||||||
|
if (!stats->value->has_device) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor_printf(mon, "%s:", stats->value->device);
|
||||||
|
monitor_printf(mon, " rd_bytes=%" PRId64
|
||||||
|
" wr_bytes=%" PRId64
|
||||||
|
" rd_operations=%" PRId64
|
||||||
|
" wr_operations=%" PRId64
|
||||||
|
" flush_operations=%" PRId64
|
||||||
|
" wr_total_time_ns=%" PRId64
|
||||||
|
" rd_total_time_ns=%" PRId64
|
||||||
|
" flush_total_time_ns=%" PRId64
|
||||||
|
" rd_merged=%" PRId64
|
||||||
|
" wr_merged=%" PRId64
|
||||||
|
" idle_time_ns=%" PRId64
|
||||||
|
"\n",
|
||||||
|
stats->value->stats->rd_bytes,
|
||||||
|
stats->value->stats->wr_bytes,
|
||||||
|
stats->value->stats->rd_operations,
|
||||||
|
stats->value->stats->wr_operations,
|
||||||
|
stats->value->stats->flush_operations,
|
||||||
|
stats->value->stats->wr_total_time_ns,
|
||||||
|
stats->value->stats->rd_total_time_ns,
|
||||||
|
stats->value->stats->flush_total_time_ns,
|
||||||
|
stats->value->stats->rd_merged,
|
||||||
|
stats->value->stats->wr_merged,
|
||||||
|
stats->value->stats->idle_time_ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
qapi_free_BlockStatsList(stats_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hmp_info_block_jobs(Monitor *mon, const QDict *qdict)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
qapi_free_BlockJobInfoList(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
|
||||||
|
{
|
||||||
|
BlockDriverState *bs, *bs1;
|
||||||
|
BdrvNextIterator it1;
|
||||||
|
QEMUSnapshotInfo *sn_tab, *sn;
|
||||||
|
bool no_snapshot = true;
|
||||||
|
int nb_sns, i;
|
||||||
|
int total;
|
||||||
|
int *global_snapshots;
|
||||||
|
AioContext *aio_context;
|
||||||
|
|
||||||
|
typedef struct SnapshotEntry {
|
||||||
|
QEMUSnapshotInfo sn;
|
||||||
|
QTAILQ_ENTRY(SnapshotEntry) next;
|
||||||
|
} SnapshotEntry;
|
||||||
|
|
||||||
|
typedef struct ImageEntry {
|
||||||
|
const char *imagename;
|
||||||
|
QTAILQ_ENTRY(ImageEntry) next;
|
||||||
|
QTAILQ_HEAD(, SnapshotEntry) snapshots;
|
||||||
|
} ImageEntry;
|
||||||
|
|
||||||
|
QTAILQ_HEAD(, ImageEntry) image_list =
|
||||||
|
QTAILQ_HEAD_INITIALIZER(image_list);
|
||||||
|
|
||||||
|
ImageEntry *image_entry, *next_ie;
|
||||||
|
SnapshotEntry *snapshot_entry;
|
||||||
|
|
||||||
|
bs = bdrv_all_find_vmstate_bs();
|
||||||
|
if (!bs) {
|
||||||
|
monitor_printf(mon, "No available block device supports snapshots\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
|
|
||||||
|
aio_context_acquire(aio_context);
|
||||||
|
nb_sns = bdrv_snapshot_list(bs, &sn_tab);
|
||||||
|
aio_context_release(aio_context);
|
||||||
|
|
||||||
|
if (nb_sns < 0) {
|
||||||
|
monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bs1 = bdrv_first(&it1); bs1; bs1 = bdrv_next(&it1)) {
|
||||||
|
int bs1_nb_sns = 0;
|
||||||
|
ImageEntry *ie;
|
||||||
|
SnapshotEntry *se;
|
||||||
|
AioContext *ctx = bdrv_get_aio_context(bs1);
|
||||||
|
|
||||||
|
aio_context_acquire(ctx);
|
||||||
|
if (bdrv_can_snapshot(bs1)) {
|
||||||
|
sn = NULL;
|
||||||
|
bs1_nb_sns = bdrv_snapshot_list(bs1, &sn);
|
||||||
|
if (bs1_nb_sns > 0) {
|
||||||
|
no_snapshot = false;
|
||||||
|
ie = g_new0(ImageEntry, 1);
|
||||||
|
ie->imagename = bdrv_get_device_name(bs1);
|
||||||
|
QTAILQ_INIT(&ie->snapshots);
|
||||||
|
QTAILQ_INSERT_TAIL(&image_list, ie, next);
|
||||||
|
for (i = 0; i < bs1_nb_sns; i++) {
|
||||||
|
se = g_new0(SnapshotEntry, 1);
|
||||||
|
se->sn = sn[i];
|
||||||
|
QTAILQ_INSERT_TAIL(&ie->snapshots, se, next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_free(sn);
|
||||||
|
}
|
||||||
|
aio_context_release(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (no_snapshot) {
|
||||||
|
monitor_printf(mon, "There is no snapshot available.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
global_snapshots = g_new0(int, nb_sns);
|
||||||
|
total = 0;
|
||||||
|
for (i = 0; i < nb_sns; i++) {
|
||||||
|
SnapshotEntry *next_sn;
|
||||||
|
if (bdrv_all_find_snapshot(sn_tab[i].name, &bs1) == 0) {
|
||||||
|
global_snapshots[total] = i;
|
||||||
|
total++;
|
||||||
|
QTAILQ_FOREACH(image_entry, &image_list, next) {
|
||||||
|
QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots,
|
||||||
|
next, next_sn) {
|
||||||
|
if (!strcmp(sn_tab[i].name, snapshot_entry->sn.name)) {
|
||||||
|
QTAILQ_REMOVE(&image_entry->snapshots, snapshot_entry,
|
||||||
|
next);
|
||||||
|
g_free(snapshot_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
monitor_printf(mon, "List of snapshots present on all disks:\n");
|
||||||
|
|
||||||
|
if (total > 0) {
|
||||||
|
bdrv_snapshot_dump(NULL);
|
||||||
|
monitor_printf(mon, "\n");
|
||||||
|
for (i = 0; i < total; i++) {
|
||||||
|
sn = &sn_tab[global_snapshots[i]];
|
||||||
|
/*
|
||||||
|
* The ID is not guaranteed to be the same on all images, so
|
||||||
|
* overwrite it.
|
||||||
|
*/
|
||||||
|
pstrcpy(sn->id_str, sizeof(sn->id_str), "--");
|
||||||
|
bdrv_snapshot_dump(sn);
|
||||||
|
monitor_printf(mon, "\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
monitor_printf(mon, "None\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
QTAILQ_FOREACH(image_entry, &image_list, next) {
|
||||||
|
if (QTAILQ_EMPTY(&image_entry->snapshots)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
monitor_printf(mon,
|
||||||
|
"\nList of partial (non-loadable) snapshots on '%s':\n",
|
||||||
|
image_entry->imagename);
|
||||||
|
bdrv_snapshot_dump(NULL);
|
||||||
|
monitor_printf(mon, "\n");
|
||||||
|
QTAILQ_FOREACH(snapshot_entry, &image_entry->snapshots, next) {
|
||||||
|
bdrv_snapshot_dump(&snapshot_entry->sn);
|
||||||
|
monitor_printf(mon, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QTAILQ_FOREACH_SAFE(image_entry, &image_list, next, next_ie) {
|
||||||
|
SnapshotEntry *next_sn;
|
||||||
|
QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots, next,
|
||||||
|
next_sn) {
|
||||||
|
g_free(snapshot_entry);
|
||||||
|
}
|
||||||
|
g_free(image_entry);
|
||||||
|
}
|
||||||
|
g_free(sn_tab);
|
||||||
|
g_free(global_snapshots);
|
||||||
|
}
|
||||||
|
|
|
@ -46,5 +46,9 @@ void hmp_eject(Monitor *mon, const QDict *qdict);
|
||||||
|
|
||||||
void hmp_qemu_io(Monitor *mon, const QDict *qdict);
|
void hmp_qemu_io(Monitor *mon, const QDict *qdict);
|
||||||
|
|
||||||
|
void hmp_info_block(Monitor *mon, const QDict *qdict);
|
||||||
|
void hmp_info_blockstats(Monitor *mon, const QDict *qdict);
|
||||||
|
void hmp_info_block_jobs(Monitor *mon, const QDict *qdict);
|
||||||
|
void hmp_info_snapshots(Monitor *mon, const QDict *qdict);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,8 +30,6 @@ void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict);
|
void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_info_migrate_cache_size(Monitor *mon, const QDict *qdict);
|
void hmp_info_migrate_cache_size(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_info_cpus(Monitor *mon, const QDict *qdict);
|
void hmp_info_cpus(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_info_block(Monitor *mon, const QDict *qdict);
|
|
||||||
void hmp_info_blockstats(Monitor *mon, const QDict *qdict);
|
|
||||||
void hmp_info_vnc(Monitor *mon, const QDict *qdict);
|
void hmp_info_vnc(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_info_spice(Monitor *mon, const QDict *qdict);
|
void hmp_info_spice(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_info_balloon(Monitor *mon, const QDict *qdict);
|
void hmp_info_balloon(Monitor *mon, const QDict *qdict);
|
||||||
|
@ -39,7 +37,6 @@ void hmp_info_irq(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_info_pic(Monitor *mon, const QDict *qdict);
|
void hmp_info_pic(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_info_rdma(Monitor *mon, const QDict *qdict);
|
void hmp_info_rdma(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_info_pci(Monitor *mon, const QDict *qdict);
|
void hmp_info_pci(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_info_block_jobs(Monitor *mon, const QDict *qdict);
|
|
||||||
void hmp_info_tpm(Monitor *mon, const QDict *qdict);
|
void hmp_info_tpm(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_info_iothreads(Monitor *mon, const QDict *qdict);
|
void hmp_info_iothreads(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_quit(Monitor *mon, const QDict *qdict);
|
void hmp_quit(Monitor *mon, const QDict *qdict);
|
||||||
|
@ -62,7 +59,6 @@ void hmp_balloon(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_loadvm(Monitor *mon, const QDict *qdict);
|
void hmp_loadvm(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_savevm(Monitor *mon, const QDict *qdict);
|
void hmp_savevm(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_delvm(Monitor *mon, const QDict *qdict);
|
void hmp_delvm(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_info_snapshots(Monitor *mon, const QDict *qdict);
|
|
||||||
void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
|
void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_migrate_continue(Monitor *mon, const QDict *qdict);
|
void hmp_migrate_continue(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_migrate_incoming(Monitor *mon, const QDict *qdict);
|
void hmp_migrate_incoming(Monitor *mon, const QDict *qdict);
|
||||||
|
|
|
@ -47,7 +47,6 @@
|
||||||
#include "qapi/string-output-visitor.h"
|
#include "qapi/string-output-visitor.h"
|
||||||
#include "qom/object_interfaces.h"
|
#include "qom/object_interfaces.h"
|
||||||
#include "ui/console.h"
|
#include "ui/console.h"
|
||||||
#include "block/qapi.h"
|
|
||||||
#include "qemu/cutils.h"
|
#include "qemu/cutils.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "exec/ramlist.h"
|
#include "exec/ramlist.h"
|
||||||
|
@ -470,213 +469,6 @@ void hmp_info_migrate_cache_size(Monitor *mon, const QDict *qdict)
|
||||||
qmp_query_migrate_cache_size(NULL) >> 10);
|
qmp_query_migrate_cache_size(NULL) >> 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 && *info->device) {
|
|
||||||
monitor_printf(mon, "%s", info->device);
|
|
||||||
if (inserted && inserted->has_node_name) {
|
|
||||||
monitor_printf(mon, " (%s)", inserted->node_name);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
assert(info || inserted);
|
|
||||||
monitor_printf(mon, "%s",
|
|
||||||
inserted && inserted->has_node_name ? inserted->node_name
|
|
||||||
: info && info->has_qdev ? info->qdev
|
|
||||||
: "<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_qdev) {
|
|
||||||
monitor_printf(mon, " Attached to: %s\n", info->qdev);
|
|
||||||
}
|
|
||||||
if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) {
|
|
||||||
monitor_printf(mon, " I/O status: %s\n",
|
|
||||||
BlockDeviceIoStatus_str(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_str(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
|
|
||||||
" group=%s\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,
|
|
||||||
inserted->group);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
monitor_printf(mon, "\nImages:\n");
|
|
||||||
image_info = inserted->image;
|
|
||||||
while (1) {
|
|
||||||
bdrv_image_info_dump(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;
|
|
||||||
BlockDeviceInfoList *blockdev_list, *blockdev;
|
|
||||||
const char *device = qdict_get_try_str(qdict, "device");
|
|
||||||
bool verbose = qdict_get_try_bool(qdict, "verbose", false);
|
|
||||||
bool nodes = qdict_get_try_bool(qdict, "nodes", false);
|
|
||||||
bool printed = false;
|
|
||||||
|
|
||||||
/* 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)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info != block_list) {
|
|
||||||
monitor_printf(mon, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
print_block_info(mon, info->value, info->value->has_inserted
|
|
||||||
? info->value->inserted : NULL,
|
|
||||||
verbose);
|
|
||||||
printed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
qapi_free_BlockInfoList(block_list);
|
|
||||||
|
|
||||||
if ((!device && !nodes) || printed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print node information */
|
|
||||||
blockdev_list = qmp_query_named_block_nodes(false, false, 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hmp_info_blockstats(Monitor *mon, const QDict *qdict)
|
|
||||||
{
|
|
||||||
BlockStatsList *stats_list, *stats;
|
|
||||||
|
|
||||||
stats_list = qmp_query_blockstats(false, false, NULL);
|
|
||||||
|
|
||||||
for (stats = stats_list; stats; stats = stats->next) {
|
|
||||||
if (!stats->value->has_device) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
monitor_printf(mon, "%s:", stats->value->device);
|
|
||||||
monitor_printf(mon, " rd_bytes=%" PRId64
|
|
||||||
" wr_bytes=%" PRId64
|
|
||||||
" rd_operations=%" PRId64
|
|
||||||
" wr_operations=%" PRId64
|
|
||||||
" flush_operations=%" PRId64
|
|
||||||
" wr_total_time_ns=%" PRId64
|
|
||||||
" rd_total_time_ns=%" PRId64
|
|
||||||
" flush_total_time_ns=%" PRId64
|
|
||||||
" rd_merged=%" PRId64
|
|
||||||
" wr_merged=%" PRId64
|
|
||||||
" idle_time_ns=%" PRId64
|
|
||||||
"\n",
|
|
||||||
stats->value->stats->rd_bytes,
|
|
||||||
stats->value->stats->wr_bytes,
|
|
||||||
stats->value->stats->rd_operations,
|
|
||||||
stats->value->stats->wr_operations,
|
|
||||||
stats->value->stats->flush_operations,
|
|
||||||
stats->value->stats->wr_total_time_ns,
|
|
||||||
stats->value->stats->rd_total_time_ns,
|
|
||||||
stats->value->stats->flush_total_time_ns,
|
|
||||||
stats->value->stats->rd_merged,
|
|
||||||
stats->value->stats->wr_merged,
|
|
||||||
stats->value->stats->idle_time_ns);
|
|
||||||
}
|
|
||||||
|
|
||||||
qapi_free_BlockStatsList(stats_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_VNC
|
#ifdef CONFIG_VNC
|
||||||
/* Helper for hmp_info_vnc_clients, _servers */
|
/* Helper for hmp_info_vnc_clients, _servers */
|
||||||
|
@ -1056,44 +848,6 @@ void hmp_info_pci(Monitor *mon, const QDict *qdict)
|
||||||
qapi_free_PciInfoList(info_list);
|
qapi_free_PciInfoList(info_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hmp_info_block_jobs(Monitor *mon, const QDict *qdict)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
qapi_free_BlockJobInfoList(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hmp_info_tpm(Monitor *mon, const QDict *qdict)
|
void hmp_info_tpm(Monitor *mon, const QDict *qdict)
|
||||||
{
|
{
|
||||||
TPMInfoList *info_list, *info;
|
TPMInfoList *info_list, *info;
|
||||||
|
@ -1356,148 +1110,6 @@ void hmp_delvm(Monitor *mon, const QDict *qdict)
|
||||||
hmp_handle_error(mon, err);
|
hmp_handle_error(mon, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
|
|
||||||
{
|
|
||||||
BlockDriverState *bs, *bs1;
|
|
||||||
BdrvNextIterator it1;
|
|
||||||
QEMUSnapshotInfo *sn_tab, *sn;
|
|
||||||
bool no_snapshot = true;
|
|
||||||
int nb_sns, i;
|
|
||||||
int total;
|
|
||||||
int *global_snapshots;
|
|
||||||
AioContext *aio_context;
|
|
||||||
|
|
||||||
typedef struct SnapshotEntry {
|
|
||||||
QEMUSnapshotInfo sn;
|
|
||||||
QTAILQ_ENTRY(SnapshotEntry) next;
|
|
||||||
} SnapshotEntry;
|
|
||||||
|
|
||||||
typedef struct ImageEntry {
|
|
||||||
const char *imagename;
|
|
||||||
QTAILQ_ENTRY(ImageEntry) next;
|
|
||||||
QTAILQ_HEAD(, SnapshotEntry) snapshots;
|
|
||||||
} ImageEntry;
|
|
||||||
|
|
||||||
QTAILQ_HEAD(, ImageEntry) image_list =
|
|
||||||
QTAILQ_HEAD_INITIALIZER(image_list);
|
|
||||||
|
|
||||||
ImageEntry *image_entry, *next_ie;
|
|
||||||
SnapshotEntry *snapshot_entry;
|
|
||||||
|
|
||||||
bs = bdrv_all_find_vmstate_bs();
|
|
||||||
if (!bs) {
|
|
||||||
monitor_printf(mon, "No available block device supports snapshots\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
aio_context = bdrv_get_aio_context(bs);
|
|
||||||
|
|
||||||
aio_context_acquire(aio_context);
|
|
||||||
nb_sns = bdrv_snapshot_list(bs, &sn_tab);
|
|
||||||
aio_context_release(aio_context);
|
|
||||||
|
|
||||||
if (nb_sns < 0) {
|
|
||||||
monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (bs1 = bdrv_first(&it1); bs1; bs1 = bdrv_next(&it1)) {
|
|
||||||
int bs1_nb_sns = 0;
|
|
||||||
ImageEntry *ie;
|
|
||||||
SnapshotEntry *se;
|
|
||||||
AioContext *ctx = bdrv_get_aio_context(bs1);
|
|
||||||
|
|
||||||
aio_context_acquire(ctx);
|
|
||||||
if (bdrv_can_snapshot(bs1)) {
|
|
||||||
sn = NULL;
|
|
||||||
bs1_nb_sns = bdrv_snapshot_list(bs1, &sn);
|
|
||||||
if (bs1_nb_sns > 0) {
|
|
||||||
no_snapshot = false;
|
|
||||||
ie = g_new0(ImageEntry, 1);
|
|
||||||
ie->imagename = bdrv_get_device_name(bs1);
|
|
||||||
QTAILQ_INIT(&ie->snapshots);
|
|
||||||
QTAILQ_INSERT_TAIL(&image_list, ie, next);
|
|
||||||
for (i = 0; i < bs1_nb_sns; i++) {
|
|
||||||
se = g_new0(SnapshotEntry, 1);
|
|
||||||
se->sn = sn[i];
|
|
||||||
QTAILQ_INSERT_TAIL(&ie->snapshots, se, next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_free(sn);
|
|
||||||
}
|
|
||||||
aio_context_release(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (no_snapshot) {
|
|
||||||
monitor_printf(mon, "There is no snapshot available.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
global_snapshots = g_new0(int, nb_sns);
|
|
||||||
total = 0;
|
|
||||||
for (i = 0; i < nb_sns; i++) {
|
|
||||||
SnapshotEntry *next_sn;
|
|
||||||
if (bdrv_all_find_snapshot(sn_tab[i].name, &bs1) == 0) {
|
|
||||||
global_snapshots[total] = i;
|
|
||||||
total++;
|
|
||||||
QTAILQ_FOREACH(image_entry, &image_list, next) {
|
|
||||||
QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots,
|
|
||||||
next, next_sn) {
|
|
||||||
if (!strcmp(sn_tab[i].name, snapshot_entry->sn.name)) {
|
|
||||||
QTAILQ_REMOVE(&image_entry->snapshots, snapshot_entry,
|
|
||||||
next);
|
|
||||||
g_free(snapshot_entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
monitor_printf(mon, "List of snapshots present on all disks:\n");
|
|
||||||
|
|
||||||
if (total > 0) {
|
|
||||||
bdrv_snapshot_dump(NULL);
|
|
||||||
monitor_printf(mon, "\n");
|
|
||||||
for (i = 0; i < total; i++) {
|
|
||||||
sn = &sn_tab[global_snapshots[i]];
|
|
||||||
/* The ID is not guaranteed to be the same on all images, so
|
|
||||||
* overwrite it.
|
|
||||||
*/
|
|
||||||
pstrcpy(sn->id_str, sizeof(sn->id_str), "--");
|
|
||||||
bdrv_snapshot_dump(sn);
|
|
||||||
monitor_printf(mon, "\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
monitor_printf(mon, "None\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
QTAILQ_FOREACH(image_entry, &image_list, next) {
|
|
||||||
if (QTAILQ_EMPTY(&image_entry->snapshots)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
monitor_printf(mon,
|
|
||||||
"\nList of partial (non-loadable) snapshots on '%s':\n",
|
|
||||||
image_entry->imagename);
|
|
||||||
bdrv_snapshot_dump(NULL);
|
|
||||||
monitor_printf(mon, "\n");
|
|
||||||
QTAILQ_FOREACH(snapshot_entry, &image_entry->snapshots, next) {
|
|
||||||
bdrv_snapshot_dump(&snapshot_entry->sn);
|
|
||||||
monitor_printf(mon, "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QTAILQ_FOREACH_SAFE(image_entry, &image_list, next, next_ie) {
|
|
||||||
SnapshotEntry *next_sn;
|
|
||||||
QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots, next,
|
|
||||||
next_sn) {
|
|
||||||
g_free(snapshot_entry);
|
|
||||||
}
|
|
||||||
g_free(image_entry);
|
|
||||||
}
|
|
||||||
g_free(sn_tab);
|
|
||||||
g_free(global_snapshots);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void hmp_announce_self(Monitor *mon, const QDict *qdict)
|
void hmp_announce_self(Monitor *mon, const QDict *qdict)
|
||||||
{
|
{
|
||||||
const char *interfaces_str = qdict_get_try_str(qdict, "interfaces");
|
const char *interfaces_str = qdict_get_try_str(qdict, "interfaces");
|
||||||
|
|
Loading…
Reference in New Issue