qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

block-hmp-cmds.c (31693B)


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