qemu/block/monitor/block-hmp-cmds.c
<<
>>
Prefs
   1/*
   2 * Blockdev HMP commands
   3 *
   4 *  Authors:
   5 *  Anthony Liguori   <aliguori@us.ibm.com>
   6 *
   7 * Copyright (c) 2003-2008 Fabrice Bellard
   8 *
   9 * This work is licensed under the terms of the GNU GPL, version 2.
  10 * See the COPYING file in the top-level directory.
  11 * Contributions after 2012-01-13 are licensed under the terms of the
  12 * GNU GPL, version 2 or (at your option) any later version.
  13 *
  14 * This file incorporates work covered by the following copyright and
  15 * permission notice:
  16 *
  17 * Copyright (c) 2003-2008 Fabrice Bellard
  18 *
  19 * Permission is hereby granted, free of charge, to any person obtaining a copy
  20 * of this software and associated documentation files (the "Software"), to deal
  21 * in the Software without restriction, including without limitation the rights
  22 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  23 * copies of the Software, and to permit persons to whom the Software is
  24 * furnished to do so, subject to the following conditions:
  25 *
  26 * The above copyright notice and this permission notice shall be included in
  27 * all copies or substantial portions of the Software.
  28 *
  29 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  30 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  31 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  32 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  33 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  34 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  35 * THE SOFTWARE.
  36 */
  37
  38#include "qemu/osdep.h"
  39#include "hw/boards.h"
  40#include "sysemu/block-backend.h"
  41#include "sysemu/blockdev.h"
  42#include "qapi/qapi-commands-block.h"
  43#include "qapi/qmp/qdict.h"
  44#include "qapi/error.h"
  45#include "qapi/qmp/qerror.h"
  46#include "qemu/config-file.h"
  47#include "qemu/option.h"
  48#include "qemu/sockets.h"
  49#include "qemu/cutils.h"
  50#include "sysemu/sysemu.h"
  51#include "monitor/monitor.h"
  52#include "monitor/hmp.h"
  53#include "block/nbd.h"
  54#include "block/qapi.h"
  55#include "block/block_int.h"
  56#include "block/block-hmp-cmds.h"
  57#include "qemu-io.h"
  58
  59static void hmp_drive_add_node(Monitor *mon, const char *optstr)
  60{
  61    QemuOpts *opts;
  62    QDict *qdict;
  63    Error *local_err = NULL;
  64
  65    opts = qemu_opts_parse_noisily(&qemu_drive_opts, optstr, false);
  66    if (!opts) {
  67        return;
  68    }
  69
  70    qdict = qemu_opts_to_qdict(opts, NULL);
  71
  72    if (!qdict_get_try_str(qdict, "node-name")) {
  73        qobject_unref(qdict);
  74        error_report("'node-name' needs to be specified");
  75        goto out;
  76    }
  77
  78    BlockDriverState *bs = bds_tree_init(qdict, &local_err);
  79    if (!bs) {
  80        error_report_err(local_err);
  81        goto out;
  82    }
  83
  84    bdrv_set_monitor_owned(bs);
  85out:
  86    qemu_opts_del(opts);
  87}
  88
  89void hmp_drive_add(Monitor *mon, const QDict *qdict)
  90{
  91    Error *err = NULL;
  92    DriveInfo *dinfo;
  93    QemuOpts *opts;
  94    MachineClass *mc;
  95    const char *optstr = qdict_get_str(qdict, "opts");
  96    bool node = qdict_get_try_bool(qdict, "node", false);
  97
  98    if (node) {
  99        hmp_drive_add_node(mon, optstr);
 100        return;
 101    }
 102
 103    opts = drive_def(optstr);
 104    if (!opts)
 105        return;
 106
 107    mc = MACHINE_GET_CLASS(current_machine);
 108    dinfo = drive_new(opts, mc->block_default_type, &err);
 109    if (err) {
 110        error_report_err(err);
 111        qemu_opts_del(opts);
 112        goto err;
 113    }
 114
 115    if (!dinfo) {
 116        return;
 117    }
 118
 119    switch (dinfo->type) {
 120    case IF_NONE:
 121        monitor_printf(mon, "OK\n");
 122        break;
 123    default:
 124        monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type);
 125        goto err;
 126    }
 127    return;
 128
 129err:
 130    if (dinfo) {
 131        BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
 132        monitor_remove_blk(blk);
 133        blk_unref(blk);
 134    }
 135}
 136
 137void hmp_drive_del(Monitor *mon, const QDict *qdict)
 138{
 139    const char *id = qdict_get_str(qdict, "id");
 140    BlockBackend *blk;
 141    BlockDriverState *bs;
 142    AioContext *aio_context;
 143    Error *local_err = NULL;
 144
 145    bs = bdrv_find_node(id);
 146    if (bs) {
 147        qmp_blockdev_del(id, &local_err);
 148        if (local_err) {
 149            error_report_err(local_err);
 150        }
 151        return;
 152    }
 153
 154    blk = blk_by_name(id);
 155    if (!blk) {
 156        error_report("Device '%s' not found", id);
 157        return;
 158    }
 159
 160    if (!blk_legacy_dinfo(blk)) {
 161        error_report("Deleting device added with blockdev-add"
 162                     " is not supported");
 163        return;
 164    }
 165
 166    aio_context = blk_get_aio_context(blk);
 167    aio_context_acquire(aio_context);
 168
 169    bs = blk_bs(blk);
 170    if (bs) {
 171        if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) {
 172            error_report_err(local_err);
 173            aio_context_release(aio_context);
 174            return;
 175        }
 176
 177        blk_remove_bs(blk);
 178    }
 179
 180    /* Make the BlockBackend and the attached BlockDriverState anonymous */
 181    monitor_remove_blk(blk);
 182
 183    /*
 184     * If this BlockBackend has a device attached to it, its refcount will be
 185     * decremented when the device is removed; otherwise we have to do so here.
 186     */
 187    if (blk_get_attached_dev(blk)) {
 188        /* Further I/O must not pause the guest */
 189        blk_set_on_error(blk, BLOCKDEV_ON_ERROR_REPORT,
 190                         BLOCKDEV_ON_ERROR_REPORT);
 191    } else {
 192        blk_unref(blk);
 193    }
 194
 195    aio_context_release(aio_context);
 196}
 197
 198void hmp_commit(Monitor *mon, const QDict *qdict)
 199{
 200    const char *device = qdict_get_str(qdict, "device");
 201    BlockBackend *blk;
 202    int ret;
 203
 204    if (!strcmp(device, "all")) {
 205        ret = blk_commit_all();
 206    } else {
 207        BlockDriverState *bs;
 208        AioContext *aio_context;
 209
 210        blk = blk_by_name(device);
 211        if (!blk) {
 212            error_report("Device '%s' not found", device);
 213            return;
 214        }
 215        if (!blk_is_available(blk)) {
 216            error_report("Device '%s' has no medium", device);
 217            return;
 218        }
 219
 220        bs = blk_bs(blk);
 221        aio_context = bdrv_get_aio_context(bs);
 222        aio_context_acquire(aio_context);
 223
 224        ret = bdrv_commit(bs);
 225
 226        aio_context_release(aio_context);
 227    }
 228    if (ret < 0) {
 229        error_report("'commit' error for '%s': %s", device, strerror(-ret));
 230    }
 231}
 232
 233void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
 234{
 235    const char *filename = qdict_get_str(qdict, "target");
 236    const char *format = qdict_get_try_str(qdict, "format");
 237    bool reuse = qdict_get_try_bool(qdict, "reuse", false);
 238    bool full = qdict_get_try_bool(qdict, "full", false);
 239    Error *err = NULL;
 240    DriveMirror mirror = {
 241        .device = (char *)qdict_get_str(qdict, "device"),
 242        .target = (char *)filename,
 243        .has_format = !!format,
 244        .format = (char *)format,
 245        .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
 246        .has_mode = true,
 247        .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
 248        .unmap = true,
 249    };
 250
 251    if (!filename) {
 252        error_setg(&err, QERR_MISSING_PARAMETER, "target");
 253        hmp_handle_error(mon, err);
 254        return;
 255    }
 256    qmp_drive_mirror(&mirror, &err);
 257    hmp_handle_error(mon, err);
 258}
 259
 260void hmp_drive_backup(Monitor *mon, const QDict *qdict)
 261{
 262    const char *device = qdict_get_str(qdict, "device");
 263    const char *filename = qdict_get_str(qdict, "target");
 264    const char *format = qdict_get_try_str(qdict, "format");
 265    bool reuse = qdict_get_try_bool(qdict, "reuse", false);
 266    bool full = qdict_get_try_bool(qdict, "full", false);
 267    bool compress = qdict_get_try_bool(qdict, "compress", false);
 268    Error *err = NULL;
 269    DriveBackup backup = {
 270        .device = (char *)device,
 271        .target = (char *)filename,
 272        .has_format = !!format,
 273        .format = (char *)format,
 274        .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
 275        .has_mode = true,
 276        .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
 277        .has_compress = !!compress,
 278        .compress = compress,
 279    };
 280
 281    if (!filename) {
 282        error_setg(&err, QERR_MISSING_PARAMETER, "target");
 283        hmp_handle_error(mon, err);
 284        return;
 285    }
 286
 287    qmp_drive_backup(&backup, &err);
 288    hmp_handle_error(mon, err);
 289}
 290
 291void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict)
 292{
 293    Error *error = NULL;
 294    const char *device = qdict_get_str(qdict, "device");
 295    int64_t value = qdict_get_int(qdict, "speed");
 296
 297    qmp_block_job_set_speed(device, value, &error);
 298
 299    hmp_handle_error(mon, error);
 300}
 301
 302void hmp_block_job_cancel(Monitor *mon, const QDict *qdict)
 303{
 304    Error *error = NULL;
 305    const char *device = qdict_get_str(qdict, "device");
 306    bool force = qdict_get_try_bool(qdict, "force", false);
 307
 308    qmp_block_job_cancel(device, true, force, &error);
 309
 310    hmp_handle_error(mon, error);
 311}
 312
 313void hmp_block_job_pause(Monitor *mon, const QDict *qdict)
 314{
 315    Error *error = NULL;
 316    const char *device = qdict_get_str(qdict, "device");
 317
 318    qmp_block_job_pause(device, &error);
 319
 320    hmp_handle_error(mon, error);
 321}
 322
 323void hmp_block_job_resume(Monitor *mon, const QDict *qdict)
 324{
 325    Error *error = NULL;
 326    const char *device = qdict_get_str(qdict, "device");
 327
 328    qmp_block_job_resume(device, &error);
 329
 330    hmp_handle_error(mon, error);
 331}
 332
 333void hmp_block_job_complete(Monitor *mon, const QDict *qdict)
 334{
 335    Error *error = NULL;
 336    const char *device = qdict_get_str(qdict, "device");
 337
 338    qmp_block_job_complete(device, &error);
 339
 340    hmp_handle_error(mon, error);
 341}
 342
 343void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
 344{
 345    const char *device = qdict_get_str(qdict, "device");
 346    const char *filename = qdict_get_try_str(qdict, "snapshot-file");
 347    const char *format = qdict_get_try_str(qdict, "format");
 348    bool reuse = qdict_get_try_bool(qdict, "reuse", false);
 349    enum NewImageMode mode;
 350    Error *err = NULL;
 351
 352    if (!filename) {
 353        /*
 354         * In the future, if 'snapshot-file' is not specified, the snapshot
 355         * will be taken internally. Today it's actually required.
 356         */
 357        error_setg(&err, QERR_MISSING_PARAMETER, "snapshot-file");
 358        hmp_handle_error(mon, err);
 359        return;
 360    }
 361
 362    mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
 363    qmp_blockdev_snapshot_sync(true, device, false, NULL,
 364                               filename, false, NULL,
 365                               !!format, format,
 366                               true, mode, &err);
 367    hmp_handle_error(mon, err);
 368}
 369
 370void hmp_snapshot_blkdev_internal(Monitor *mon, const QDict *qdict)
 371{
 372    const char *device = qdict_get_str(qdict, "device");
 373    const char *name = qdict_get_str(qdict, "name");
 374    Error *err = NULL;
 375
 376    qmp_blockdev_snapshot_internal_sync(device, name, &err);
 377    hmp_handle_error(mon, err);
 378}
 379
 380void hmp_snapshot_delete_blkdev_internal(Monitor *mon, const QDict *qdict)
 381{
 382    const char *device = qdict_get_str(qdict, "device");
 383    const char *name = qdict_get_str(qdict, "name");
 384    const char *id = qdict_get_try_str(qdict, "id");
 385    Error *err = NULL;
 386
 387    qmp_blockdev_snapshot_delete_internal_sync(device, !!id, id,
 388                                               true, name, &err);
 389    hmp_handle_error(mon, err);
 390}
 391
 392void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
 393{
 394    const char *uri = qdict_get_str(qdict, "uri");
 395    bool writable = qdict_get_try_bool(qdict, "writable", false);
 396    bool all = qdict_get_try_bool(qdict, "all", false);
 397    Error *local_err = NULL;
 398    BlockInfoList *block_list, *info;
 399    SocketAddress *addr;
 400    BlockExportNbd export;
 401
 402    if (writable && !all) {
 403        error_setg(&local_err, "-w only valid together with -a");
 404        goto exit;
 405    }
 406
 407    /* First check if the address is valid and start the server.  */
 408    addr = socket_parse(uri, &local_err);
 409    if (local_err != NULL) {
 410        goto exit;
 411    }
 412
 413    nbd_server_start(addr, NULL, NULL, &local_err);
 414    qapi_free_SocketAddress(addr);
 415    if (local_err != NULL) {
 416        goto exit;
 417    }
 418
 419    if (!all) {
 420        return;
 421    }
 422
 423    /* Then try adding all block devices.  If one fails, close all and
 424     * exit.
 425     */
 426    block_list = qmp_query_block(NULL);
 427
 428    for (info = block_list; info; info = info->next) {
 429        if (!info->value->has_inserted) {
 430            continue;
 431        }
 432
 433        export = (BlockExportNbd) {
 434            .device         = info->value->device,
 435            .has_writable   = true,
 436            .writable       = writable,
 437        };
 438
 439        qmp_nbd_server_add(&export, &local_err);
 440
 441        if (local_err != NULL) {
 442            qmp_nbd_server_stop(NULL);
 443            break;
 444        }
 445    }
 446
 447    qapi_free_BlockInfoList(block_list);
 448
 449exit:
 450    hmp_handle_error(mon, local_err);
 451}
 452
 453void hmp_nbd_server_add(Monitor *mon, const QDict *qdict)
 454{
 455    const char *device = qdict_get_str(qdict, "device");
 456    const char *name = qdict_get_try_str(qdict, "name");
 457    bool writable = qdict_get_try_bool(qdict, "writable", false);
 458    Error *local_err = NULL;
 459
 460    BlockExportNbd export = {
 461        .device         = (char *) device,
 462        .has_name       = !!name,
 463        .name           = (char *) name,
 464        .has_writable   = true,
 465        .writable       = writable,
 466    };
 467
 468    qmp_nbd_server_add(&export, &local_err);
 469    hmp_handle_error(mon, local_err);
 470}
 471
 472void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict)
 473{
 474    const char *name = qdict_get_str(qdict, "name");
 475    bool force = qdict_get_try_bool(qdict, "force", false);
 476    Error *err = NULL;
 477
 478    /* Rely on NBD_SERVER_REMOVE_MODE_SAFE being the default */
 479    qmp_nbd_server_remove(name, force, NBD_SERVER_REMOVE_MODE_HARD, &err);
 480    hmp_handle_error(mon, err);
 481}
 482
 483void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict)
 484{
 485    Error *err = NULL;
 486
 487    qmp_nbd_server_stop(&err);
 488    hmp_handle_error(mon, err);
 489}
 490
 491void hmp_block_resize(Monitor *mon, const QDict *qdict)
 492{
 493    const char *device = qdict_get_str(qdict, "device");
 494    int64_t size = qdict_get_int(qdict, "size");
 495    Error *err = NULL;
 496
 497    qmp_block_resize(true, device, false, NULL, size, &err);
 498    hmp_handle_error(mon, err);
 499}
 500
 501void hmp_block_stream(Monitor *mon, const QDict *qdict)
 502{
 503    Error *error = NULL;
 504    const char *device = qdict_get_str(qdict, "device");
 505    const char *base = qdict_get_try_str(qdict, "base");
 506    int64_t speed = qdict_get_try_int(qdict, "speed", 0);
 507
 508    qmp_block_stream(true, device, device, base != NULL, base, false, NULL,
 509                     false, NULL, qdict_haskey(qdict, "speed"), speed, true,
 510                     BLOCKDEV_ON_ERROR_REPORT, false, false, false, false,
 511                     &error);
 512
 513    hmp_handle_error(mon, error);
 514}
 515
 516void hmp_block_passwd(Monitor *mon, const QDict *qdict)
 517{
 518    const char *device = qdict_get_str(qdict, "device");
 519    const char *password = qdict_get_str(qdict, "password");
 520    Error *err = NULL;
 521
 522    qmp_block_passwd(true, device, false, NULL, password, &err);
 523    hmp_handle_error(mon, err);
 524}
 525
 526void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict)
 527{
 528    Error *err = NULL;
 529    char *device = (char *) qdict_get_str(qdict, "device");
 530    BlockIOThrottle throttle = {
 531        .bps = qdict_get_int(qdict, "bps"),
 532        .bps_rd = qdict_get_int(qdict, "bps_rd"),
 533        .bps_wr = qdict_get_int(qdict, "bps_wr"),
 534        .iops = qdict_get_int(qdict, "iops"),
 535        .iops_rd = qdict_get_int(qdict, "iops_rd"),
 536        .iops_wr = qdict_get_int(qdict, "iops_wr"),
 537    };
 538
 539    /*
 540     * qmp_block_set_io_throttle has separate parameters for the
 541     * (deprecated) block device name and the qdev ID but the HMP
 542     * version has only one, so we must decide which one to pass.
 543     */
 544    if (blk_by_name(device)) {
 545        throttle.has_device = true;
 546        throttle.device = device;
 547    } else {
 548        throttle.has_id = true;
 549        throttle.id = device;
 550    }
 551
 552    qmp_block_set_io_throttle(&throttle, &err);
 553    hmp_handle_error(mon, err);
 554}
 555
 556void hmp_eject(Monitor *mon, const QDict *qdict)
 557{
 558    bool force = qdict_get_try_bool(qdict, "force", false);
 559    const char *device = qdict_get_str(qdict, "device");
 560    Error *err = NULL;
 561
 562    qmp_eject(true, device, false, NULL, true, force, &err);
 563    hmp_handle_error(mon, err);
 564}
 565
 566void hmp_qemu_io(Monitor *mon, const QDict *qdict)
 567{
 568    BlockBackend *blk;
 569    BlockBackend *local_blk = NULL;
 570    bool qdev = qdict_get_try_bool(qdict, "qdev", false);
 571    const char *device = qdict_get_str(qdict, "device");
 572    const char *command = qdict_get_str(qdict, "command");
 573    Error *err = NULL;
 574    int ret;
 575
 576    if (qdev) {
 577        blk = blk_by_qdev_id(device, &err);
 578        if (!blk) {
 579            goto fail;
 580        }
 581    } else {
 582        blk = blk_by_name(device);
 583        if (!blk) {
 584            BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err);
 585            if (bs) {
 586                blk = local_blk = blk_new(bdrv_get_aio_context(bs),
 587                                          0, BLK_PERM_ALL);
 588                ret = blk_insert_bs(blk, bs, &err);
 589                if (ret < 0) {
 590                    goto fail;
 591                }
 592            } else {
 593                goto fail;
 594            }
 595        }
 596    }
 597
 598    /*
 599     * Notably absent: Proper permission management. This is sad, but it seems
 600     * almost impossible to achieve without changing the semantics and thereby
 601     * limiting the use cases of the qemu-io HMP command.
 602     *
 603     * In an ideal world we would unconditionally create a new BlockBackend for
 604     * qemuio_command(), but we have commands like 'reopen' and want them to
 605     * take effect on the exact BlockBackend whose name the user passed instead
 606     * of just on a temporary copy of it.
 607     *
 608     * Another problem is that deleting the temporary BlockBackend involves
 609     * draining all requests on it first, but some qemu-iotests cases want to
 610     * issue multiple aio_read/write requests and expect them to complete in
 611     * the background while the monitor has already returned.
 612     *
 613     * This is also what prevents us from saving the original permissions and
 614     * restoring them later: We can't revoke permissions until all requests
 615     * have completed, and we don't know when that is nor can we really let
 616     * anything else run before we have revoken them to avoid race conditions.
 617     *
 618     * What happens now is that command() in qemu-io-cmds.c can extend the
 619     * permissions if necessary for the qemu-io command. And they simply stay
 620     * extended, possibly resulting in a read-only guest device keeping write
 621     * permissions. Ugly, but it appears to be the lesser evil.
 622     */
 623    qemuio_command(blk, command);
 624
 625fail:
 626    blk_unref(local_blk);
 627    hmp_handle_error(mon, err);
 628}
 629
 630static void print_block_info(Monitor *mon, BlockInfo *info,
 631                             BlockDeviceInfo *inserted, bool verbose)
 632{
 633    ImageInfo *image_info;
 634
 635    assert(!info || !info->has_inserted || info->inserted == inserted);
 636
 637    if (info && *info->device) {
 638        monitor_printf(mon, "%s", info->device);
 639        if (inserted && inserted->has_node_name) {
 640            monitor_printf(mon, " (%s)", inserted->node_name);
 641        }
 642    } else {
 643        assert(info || inserted);
 644        monitor_printf(mon, "%s",
 645                       inserted && inserted->has_node_name ? inserted->node_name
 646                       : info && info->has_qdev ? info->qdev
 647                       : "<anonymous>");
 648    }
 649
 650    if (inserted) {
 651        monitor_printf(mon, ": %s (%s%s%s)\n",
 652                       inserted->file,
 653                       inserted->drv,
 654                       inserted->ro ? ", read-only" : "",
 655                       inserted->encrypted ? ", encrypted" : "");
 656    } else {
 657        monitor_printf(mon, ": [not inserted]\n");
 658    }
 659
 660    if (info) {
 661        if (info->has_qdev) {
 662            monitor_printf(mon, "    Attached to:      %s\n", info->qdev);
 663        }
 664        if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) {
 665            monitor_printf(mon, "    I/O status:       %s\n",
 666                           BlockDeviceIoStatus_str(info->io_status));
 667        }
 668
 669        if (info->removable) {
 670            monitor_printf(mon, "    Removable device: %slocked, tray %s\n",
 671                           info->locked ? "" : "not ",
 672                           info->tray_open ? "open" : "closed");
 673        }
 674    }
 675
 676
 677    if (!inserted) {
 678        return;
 679    }
 680
 681    monitor_printf(mon, "    Cache mode:       %s%s%s\n",
 682                   inserted->cache->writeback ? "writeback" : "writethrough",
 683                   inserted->cache->direct ? ", direct" : "",
 684                   inserted->cache->no_flush ? ", ignore flushes" : "");
 685
 686    if (inserted->has_backing_file) {
 687        monitor_printf(mon,
 688                       "    Backing file:     %s "
 689                       "(chain depth: %" PRId64 ")\n",
 690                       inserted->backing_file,
 691                       inserted->backing_file_depth);
 692    }
 693
 694    if (inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) {
 695        monitor_printf(mon, "    Detect zeroes:    %s\n",
 696                BlockdevDetectZeroesOptions_str(inserted->detect_zeroes));
 697    }
 698
 699    if (inserted->bps  || inserted->bps_rd  || inserted->bps_wr  ||
 700        inserted->iops || inserted->iops_rd || inserted->iops_wr)
 701    {
 702        monitor_printf(mon, "    I/O throttling:   bps=%" PRId64
 703                        " bps_rd=%" PRId64  " bps_wr=%" PRId64
 704                        " bps_max=%" PRId64
 705                        " bps_rd_max=%" PRId64
 706                        " bps_wr_max=%" PRId64
 707                        " iops=%" PRId64 " iops_rd=%" PRId64
 708                        " iops_wr=%" PRId64
 709                        " iops_max=%" PRId64
 710                        " iops_rd_max=%" PRId64
 711                        " iops_wr_max=%" PRId64
 712                        " iops_size=%" PRId64
 713                        " group=%s\n",
 714                        inserted->bps,
 715                        inserted->bps_rd,
 716                        inserted->bps_wr,
 717                        inserted->bps_max,
 718                        inserted->bps_rd_max,
 719                        inserted->bps_wr_max,
 720                        inserted->iops,
 721                        inserted->iops_rd,
 722                        inserted->iops_wr,
 723                        inserted->iops_max,
 724                        inserted->iops_rd_max,
 725                        inserted->iops_wr_max,
 726                        inserted->iops_size,
 727                        inserted->group);
 728    }
 729
 730    if (verbose) {
 731        monitor_printf(mon, "\nImages:\n");
 732        image_info = inserted->image;
 733        while (1) {
 734                bdrv_image_info_dump(image_info);
 735            if (image_info->has_backing_image) {
 736                image_info = image_info->backing_image;
 737            } else {
 738                break;
 739            }
 740        }
 741    }
 742}
 743
 744void hmp_info_block(Monitor *mon, const QDict *qdict)
 745{
 746    BlockInfoList *block_list, *info;
 747    BlockDeviceInfoList *blockdev_list, *blockdev;
 748    const char *device = qdict_get_try_str(qdict, "device");
 749    bool verbose = qdict_get_try_bool(qdict, "verbose", false);
 750    bool nodes = qdict_get_try_bool(qdict, "nodes", false);
 751    bool printed = false;
 752
 753    /* Print BlockBackend information */
 754    if (!nodes) {
 755        block_list = qmp_query_block(NULL);
 756    } else {
 757        block_list = NULL;
 758    }
 759
 760    for (info = block_list; info; info = info->next) {
 761        if (device && strcmp(device, info->value->device)) {
 762            continue;
 763        }
 764
 765        if (info != block_list) {
 766            monitor_printf(mon, "\n");
 767        }
 768
 769        print_block_info(mon, info->value, info->value->has_inserted
 770                                           ? info->value->inserted : NULL,
 771                         verbose);
 772        printed = true;
 773    }
 774
 775    qapi_free_BlockInfoList(block_list);
 776
 777    if ((!device && !nodes) || printed) {
 778        return;
 779    }
 780
 781    /* Print node information */
 782    blockdev_list = qmp_query_named_block_nodes(false, false, NULL);
 783    for (blockdev = blockdev_list; blockdev; blockdev = blockdev->next) {
 784        assert(blockdev->value->has_node_name);
 785        if (device && strcmp(device, blockdev->value->node_name)) {
 786            continue;
 787        }
 788
 789        if (blockdev != blockdev_list) {
 790            monitor_printf(mon, "\n");
 791        }
 792
 793        print_block_info(mon, NULL, blockdev->value, verbose);
 794    }
 795    qapi_free_BlockDeviceInfoList(blockdev_list);
 796}
 797
 798void hmp_info_blockstats(Monitor *mon, const QDict *qdict)
 799{
 800    BlockStatsList *stats_list, *stats;
 801
 802    stats_list = qmp_query_blockstats(false, false, NULL);
 803
 804    for (stats = stats_list; stats; stats = stats->next) {
 805        if (!stats->value->has_device) {
 806            continue;
 807        }
 808
 809        monitor_printf(mon, "%s:", stats->value->device);
 810        monitor_printf(mon, " rd_bytes=%" PRId64
 811                       " wr_bytes=%" PRId64
 812                       " rd_operations=%" PRId64
 813                       " wr_operations=%" PRId64
 814                       " flush_operations=%" PRId64
 815                       " wr_total_time_ns=%" PRId64
 816                       " rd_total_time_ns=%" PRId64
 817                       " flush_total_time_ns=%" PRId64
 818                       " rd_merged=%" PRId64
 819                       " wr_merged=%" PRId64
 820                       " idle_time_ns=%" PRId64
 821                       "\n",
 822                       stats->value->stats->rd_bytes,
 823                       stats->value->stats->wr_bytes,
 824                       stats->value->stats->rd_operations,
 825                       stats->value->stats->wr_operations,
 826                       stats->value->stats->flush_operations,
 827                       stats->value->stats->wr_total_time_ns,
 828                       stats->value->stats->rd_total_time_ns,
 829                       stats->value->stats->flush_total_time_ns,
 830                       stats->value->stats->rd_merged,
 831                       stats->value->stats->wr_merged,
 832                       stats->value->stats->idle_time_ns);
 833    }
 834
 835    qapi_free_BlockStatsList(stats_list);
 836}
 837
 838void hmp_info_block_jobs(Monitor *mon, const QDict *qdict)
 839{
 840    BlockJobInfoList *list;
 841
 842    list = qmp_query_block_jobs(&error_abort);
 843
 844    if (!list) {
 845        monitor_printf(mon, "No active jobs\n");
 846        return;
 847    }
 848
 849    while (list) {
 850        if (strcmp(list->value->type, "stream") == 0) {
 851            monitor_printf(mon, "Streaming device %s: Completed %" PRId64
 852                           " of %" PRId64 " bytes, speed limit %" PRId64
 853                           " bytes/s\n",
 854                           list->value->device,
 855                           list->value->offset,
 856                           list->value->len,
 857                           list->value->speed);
 858        } else {
 859            monitor_printf(mon, "Type %s, device %s: Completed %" PRId64
 860                           " of %" PRId64 " bytes, speed limit %" PRId64
 861                           " bytes/s\n",
 862                           list->value->type,
 863                           list->value->device,
 864                           list->value->offset,
 865                           list->value->len,
 866                           list->value->speed);
 867        }
 868        list = list->next;
 869    }
 870
 871    qapi_free_BlockJobInfoList(list);
 872}
 873
 874void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
 875{
 876    BlockDriverState *bs, *bs1;
 877    BdrvNextIterator it1;
 878    QEMUSnapshotInfo *sn_tab, *sn;
 879    bool no_snapshot = true;
 880    int nb_sns, i;
 881    int total;
 882    int *global_snapshots;
 883    AioContext *aio_context;
 884
 885    typedef struct SnapshotEntry {
 886        QEMUSnapshotInfo sn;
 887        QTAILQ_ENTRY(SnapshotEntry) next;
 888    } SnapshotEntry;
 889
 890    typedef struct ImageEntry {
 891        const char *imagename;
 892        QTAILQ_ENTRY(ImageEntry) next;
 893        QTAILQ_HEAD(, SnapshotEntry) snapshots;
 894    } ImageEntry;
 895
 896    QTAILQ_HEAD(, ImageEntry) image_list =
 897        QTAILQ_HEAD_INITIALIZER(image_list);
 898
 899    ImageEntry *image_entry, *next_ie;
 900    SnapshotEntry *snapshot_entry;
 901
 902    bs = bdrv_all_find_vmstate_bs();
 903    if (!bs) {
 904        monitor_printf(mon, "No available block device supports snapshots\n");
 905        return;
 906    }
 907    aio_context = bdrv_get_aio_context(bs);
 908
 909    aio_context_acquire(aio_context);
 910    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
 911    aio_context_release(aio_context);
 912
 913    if (nb_sns < 0) {
 914        monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
 915        return;
 916    }
 917
 918    for (bs1 = bdrv_first(&it1); bs1; bs1 = bdrv_next(&it1)) {
 919        int bs1_nb_sns = 0;
 920        ImageEntry *ie;
 921        SnapshotEntry *se;
 922        AioContext *ctx = bdrv_get_aio_context(bs1);
 923
 924        aio_context_acquire(ctx);
 925        if (bdrv_can_snapshot(bs1)) {
 926            sn = NULL;
 927            bs1_nb_sns = bdrv_snapshot_list(bs1, &sn);
 928            if (bs1_nb_sns > 0) {
 929                no_snapshot = false;
 930                ie = g_new0(ImageEntry, 1);
 931                ie->imagename = bdrv_get_device_name(bs1);
 932                QTAILQ_INIT(&ie->snapshots);
 933                QTAILQ_INSERT_TAIL(&image_list, ie, next);
 934                for (i = 0; i < bs1_nb_sns; i++) {
 935                    se = g_new0(SnapshotEntry, 1);
 936                    se->sn = sn[i];
 937                    QTAILQ_INSERT_TAIL(&ie->snapshots, se, next);
 938                }
 939            }
 940            g_free(sn);
 941        }
 942        aio_context_release(ctx);
 943    }
 944
 945    if (no_snapshot) {
 946        monitor_printf(mon, "There is no snapshot available.\n");
 947        return;
 948    }
 949
 950    global_snapshots = g_new0(int, nb_sns);
 951    total = 0;
 952    for (i = 0; i < nb_sns; i++) {
 953        SnapshotEntry *next_sn;
 954        if (bdrv_all_find_snapshot(sn_tab[i].name, &bs1) == 0) {
 955            global_snapshots[total] = i;
 956            total++;
 957            QTAILQ_FOREACH(image_entry, &image_list, next) {
 958                QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots,
 959                                    next, next_sn) {
 960                    if (!strcmp(sn_tab[i].name, snapshot_entry->sn.name)) {
 961                        QTAILQ_REMOVE(&image_entry->snapshots, snapshot_entry,
 962                                      next);
 963                        g_free(snapshot_entry);
 964                    }
 965                }
 966            }
 967        }
 968    }
 969    monitor_printf(mon, "List of snapshots present on all disks:\n");
 970
 971    if (total > 0) {
 972        bdrv_snapshot_dump(NULL);
 973        monitor_printf(mon, "\n");
 974        for (i = 0; i < total; i++) {
 975            sn = &sn_tab[global_snapshots[i]];
 976            /*
 977             * The ID is not guaranteed to be the same on all images, so
 978             * overwrite it.
 979             */
 980            pstrcpy(sn->id_str, sizeof(sn->id_str), "--");
 981            bdrv_snapshot_dump(sn);
 982            monitor_printf(mon, "\n");
 983        }
 984    } else {
 985        monitor_printf(mon, "None\n");
 986    }
 987
 988    QTAILQ_FOREACH(image_entry, &image_list, next) {
 989        if (QTAILQ_EMPTY(&image_entry->snapshots)) {
 990            continue;
 991        }
 992        monitor_printf(mon,
 993                       "\nList of partial (non-loadable) snapshots on '%s':\n",
 994                       image_entry->imagename);
 995        bdrv_snapshot_dump(NULL);
 996        monitor_printf(mon, "\n");
 997        QTAILQ_FOREACH(snapshot_entry, &image_entry->snapshots, next) {
 998            bdrv_snapshot_dump(&snapshot_entry->sn);
 999            monitor_printf(mon, "\n");
1000        }
1001    }
1002
1003    QTAILQ_FOREACH_SAFE(image_entry, &image_list, next, next_ie) {
1004        SnapshotEntry *next_sn;
1005        QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots, next,
1006                            next_sn) {
1007            g_free(snapshot_entry);
1008        }
1009        g_free(image_entry);
1010    }
1011    g_free(sn_tab);
1012    g_free(global_snapshots);
1013}
1014