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