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