xref: /qemu/block/monitor/block-hmp-cmds.c (revision ec6f3fc3)
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 
61 static 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);
87 out:
88     qemu_opts_del(opts);
89 }
90 
91 void 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 
131 err:
132     if (dinfo) {
133         BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
134         monitor_remove_blk(blk);
135         blk_unref(blk);
136     }
137 }
138 
139 void 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     GLOBAL_STATE_CODE();
148     GRAPH_RDLOCK_GUARD_MAINLOOP();
149 
150     bs = bdrv_find_node(id);
151     if (bs) {
152         qmp_blockdev_del(id, &local_err);
153         if (local_err) {
154             error_report_err(local_err);
155         }
156         return;
157     }
158 
159     blk = blk_by_name(id);
160     if (!blk) {
161         error_report("Device '%s' not found", id);
162         return;
163     }
164 
165     if (!blk_legacy_dinfo(blk)) {
166         error_report("Deleting device added with blockdev-add"
167                      " is not supported");
168         return;
169     }
170 
171     aio_context = blk_get_aio_context(blk);
172     aio_context_acquire(aio_context);
173 
174     bs = blk_bs(blk);
175     if (bs) {
176         if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) {
177             error_report_err(local_err);
178             aio_context_release(aio_context);
179             return;
180         }
181 
182         blk_remove_bs(blk);
183     }
184 
185     /* Make the BlockBackend and the attached BlockDriverState anonymous */
186     monitor_remove_blk(blk);
187 
188     /*
189      * If this BlockBackend has a device attached to it, its refcount will be
190      * decremented when the device is removed; otherwise we have to do so here.
191      */
192     if (blk_get_attached_dev(blk)) {
193         /* Further I/O must not pause the guest */
194         blk_set_on_error(blk, BLOCKDEV_ON_ERROR_REPORT,
195                          BLOCKDEV_ON_ERROR_REPORT);
196     } else {
197         blk_unref(blk);
198     }
199 
200     aio_context_release(aio_context);
201 }
202 
203 void hmp_commit(Monitor *mon, const QDict *qdict)
204 {
205     const char *device = qdict_get_str(qdict, "device");
206     BlockBackend *blk;
207     int ret;
208 
209     GLOBAL_STATE_CODE();
210     GRAPH_RDLOCK_GUARD_MAINLOOP();
211 
212     if (!strcmp(device, "all")) {
213         ret = blk_commit_all();
214     } else {
215         BlockDriverState *bs;
216         AioContext *aio_context;
217 
218         blk = blk_by_name(device);
219         if (!blk) {
220             error_report("Device '%s' not found", device);
221             return;
222         }
223 
224         bs = bdrv_skip_implicit_filters(blk_bs(blk));
225         aio_context = bdrv_get_aio_context(bs);
226         aio_context_acquire(aio_context);
227 
228         if (!blk_is_available(blk)) {
229             error_report("Device '%s' has no medium", device);
230             aio_context_release(aio_context);
231             return;
232         }
233 
234         ret = bdrv_commit(bs);
235 
236         aio_context_release(aio_context);
237     }
238     if (ret < 0) {
239         error_report("'commit' error for '%s': %s", device, strerror(-ret));
240     }
241 }
242 
243 void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
244 {
245     const char *filename = qdict_get_str(qdict, "target");
246     const char *format = qdict_get_try_str(qdict, "format");
247     bool reuse = qdict_get_try_bool(qdict, "reuse", false);
248     bool full = qdict_get_try_bool(qdict, "full", false);
249     Error *err = NULL;
250     DriveMirror mirror = {
251         .device = (char *)qdict_get_str(qdict, "device"),
252         .target = (char *)filename,
253         .format = (char *)format,
254         .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
255         .has_mode = true,
256         .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
257         .unmap = true,
258     };
259 
260     if (!filename) {
261         error_setg(&err, QERR_MISSING_PARAMETER, "target");
262         goto end;
263     }
264     qmp_drive_mirror(&mirror, &err);
265 end:
266     hmp_handle_error(mon, err);
267 }
268 
269 void hmp_drive_backup(Monitor *mon, const QDict *qdict)
270 {
271     const char *device = qdict_get_str(qdict, "device");
272     const char *filename = qdict_get_str(qdict, "target");
273     const char *format = qdict_get_try_str(qdict, "format");
274     bool reuse = qdict_get_try_bool(qdict, "reuse", false);
275     bool full = qdict_get_try_bool(qdict, "full", false);
276     bool compress = qdict_get_try_bool(qdict, "compress", false);
277     Error *err = NULL;
278     DriveBackup backup = {
279         .device = (char *)device,
280         .target = (char *)filename,
281         .format = (char *)format,
282         .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
283         .has_mode = true,
284         .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
285         .has_compress = !!compress,
286         .compress = compress,
287     };
288 
289     if (!filename) {
290         error_setg(&err, QERR_MISSING_PARAMETER, "target");
291         goto end;
292     }
293 
294     qmp_drive_backup(&backup, &err);
295 end:
296     hmp_handle_error(mon, err);
297 }
298 
299 void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict)
300 {
301     Error *error = NULL;
302     const char *device = qdict_get_str(qdict, "device");
303     int64_t value = qdict_get_int(qdict, "speed");
304 
305     qmp_block_job_set_speed(device, value, &error);
306 
307     hmp_handle_error(mon, error);
308 }
309 
310 void hmp_block_job_cancel(Monitor *mon, const QDict *qdict)
311 {
312     Error *error = NULL;
313     const char *device = qdict_get_str(qdict, "device");
314     bool force = qdict_get_try_bool(qdict, "force", false);
315 
316     qmp_block_job_cancel(device, true, force, &error);
317 
318     hmp_handle_error(mon, error);
319 }
320 
321 void hmp_block_job_pause(Monitor *mon, const QDict *qdict)
322 {
323     Error *error = NULL;
324     const char *device = qdict_get_str(qdict, "device");
325 
326     qmp_block_job_pause(device, &error);
327 
328     hmp_handle_error(mon, error);
329 }
330 
331 void hmp_block_job_resume(Monitor *mon, const QDict *qdict)
332 {
333     Error *error = NULL;
334     const char *device = qdict_get_str(qdict, "device");
335 
336     qmp_block_job_resume(device, &error);
337 
338     hmp_handle_error(mon, error);
339 }
340 
341 void hmp_block_job_complete(Monitor *mon, const QDict *qdict)
342 {
343     Error *error = NULL;
344     const char *device = qdict_get_str(qdict, "device");
345 
346     qmp_block_job_complete(device, &error);
347 
348     hmp_handle_error(mon, error);
349 }
350 
351 void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
352 {
353     const char *device = qdict_get_str(qdict, "device");
354     const char *filename = qdict_get_try_str(qdict, "snapshot-file");
355     const char *format = qdict_get_try_str(qdict, "format");
356     bool reuse = qdict_get_try_bool(qdict, "reuse", false);
357     enum NewImageMode mode;
358     Error *err = NULL;
359 
360     if (!filename) {
361         /*
362          * In the future, if 'snapshot-file' is not specified, the snapshot
363          * will be taken internally. Today it's actually required.
364          */
365         error_setg(&err, QERR_MISSING_PARAMETER, "snapshot-file");
366         goto end;
367     }
368 
369     mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
370     qmp_blockdev_snapshot_sync(device, NULL, filename, NULL, format,
371                                true, mode, &err);
372 end:
373     hmp_handle_error(mon, err);
374 }
375 
376 void hmp_snapshot_blkdev_internal(Monitor *mon, const QDict *qdict)
377 {
378     const char *device = qdict_get_str(qdict, "device");
379     const char *name = qdict_get_str(qdict, "name");
380     Error *err = NULL;
381 
382     qmp_blockdev_snapshot_internal_sync(device, name, &err);
383     hmp_handle_error(mon, err);
384 }
385 
386 void hmp_snapshot_delete_blkdev_internal(Monitor *mon, const QDict *qdict)
387 {
388     const char *device = qdict_get_str(qdict, "device");
389     const char *name = qdict_get_str(qdict, "name");
390     const char *id = qdict_get_try_str(qdict, "id");
391     Error *err = NULL;
392 
393     qmp_blockdev_snapshot_delete_internal_sync(device, id, name, &err);
394     hmp_handle_error(mon, err);
395 }
396 
397 void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
398 {
399     const char *uri = qdict_get_str(qdict, "uri");
400     bool writable = qdict_get_try_bool(qdict, "writable", false);
401     bool all = qdict_get_try_bool(qdict, "all", false);
402     Error *local_err = NULL;
403     BlockInfoList *block_list, *info;
404     SocketAddress *addr;
405     NbdServerAddOptions export;
406 
407     if (writable && !all) {
408         error_setg(&local_err, "-w only valid together with -a");
409         goto exit;
410     }
411 
412     /* First check if the address is valid and start the server.  */
413     addr = socket_parse(uri, &local_err);
414     if (local_err != NULL) {
415         goto exit;
416     }
417 
418     nbd_server_start(addr, NULL, NULL, 0, &local_err);
419     qapi_free_SocketAddress(addr);
420     if (local_err != NULL) {
421         goto exit;
422     }
423 
424     if (!all) {
425         return;
426     }
427 
428     /* Then try adding all block devices.  If one fails, close all and
429      * exit.
430      */
431     block_list = qmp_query_block(NULL);
432 
433     for (info = block_list; info; info = info->next) {
434         if (!info->value->inserted) {
435             continue;
436         }
437 
438         export = (NbdServerAddOptions) {
439             .device         = info->value->device,
440             .has_writable   = true,
441             .writable       = writable,
442         };
443 
444         qmp_nbd_server_add(&export, &local_err);
445 
446         if (local_err != NULL) {
447             qmp_nbd_server_stop(NULL);
448             break;
449         }
450     }
451 
452     qapi_free_BlockInfoList(block_list);
453 
454 exit:
455     hmp_handle_error(mon, local_err);
456 }
457 
458 void hmp_nbd_server_add(Monitor *mon, const QDict *qdict)
459 {
460     const char *device = qdict_get_str(qdict, "device");
461     const char *name = qdict_get_try_str(qdict, "name");
462     bool writable = qdict_get_try_bool(qdict, "writable", false);
463     Error *local_err = NULL;
464 
465     NbdServerAddOptions export = {
466         .device         = (char *) device,
467         .name           = (char *) name,
468         .has_writable   = true,
469         .writable       = writable,
470     };
471 
472     qmp_nbd_server_add(&export, &local_err);
473     hmp_handle_error(mon, local_err);
474 }
475 
476 void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict)
477 {
478     const char *name = qdict_get_str(qdict, "name");
479     bool force = qdict_get_try_bool(qdict, "force", false);
480     Error *err = NULL;
481 
482     /* Rely on BLOCK_EXPORT_REMOVE_MODE_SAFE being the default */
483     qmp_nbd_server_remove(name, force, BLOCK_EXPORT_REMOVE_MODE_HARD, &err);
484     hmp_handle_error(mon, err);
485 }
486 
487 void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict)
488 {
489     Error *err = NULL;
490 
491     qmp_nbd_server_stop(&err);
492     hmp_handle_error(mon, err);
493 }
494 
495 void coroutine_fn hmp_block_resize(Monitor *mon, const QDict *qdict)
496 {
497     const char *device = qdict_get_str(qdict, "device");
498     int64_t size = qdict_get_int(qdict, "size");
499     Error *err = NULL;
500 
501     qmp_block_resize(device, NULL, size, &err);
502     hmp_handle_error(mon, err);
503 }
504 
505 void hmp_block_stream(Monitor *mon, const QDict *qdict)
506 {
507     Error *error = NULL;
508     const char *device = qdict_get_str(qdict, "device");
509     const char *base = qdict_get_try_str(qdict, "base");
510     int64_t speed = qdict_get_try_int(qdict, "speed", 0);
511 
512     qmp_block_stream(device, device, base, NULL, NULL, NULL,
513                      qdict_haskey(qdict, "speed"), speed,
514                      true, BLOCKDEV_ON_ERROR_REPORT, NULL,
515                      false, false, false, false, &error);
516 
517     hmp_handle_error(mon, error);
518 }
519 
520 void 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.device = device;
540     } else {
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(device, 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->inserted || info->inserted == inserted);
639 
640     if (info && *info->device) {
641         monitor_puts(mon, info->device);
642         if (inserted && inserted->node_name) {
643             monitor_printf(mon, " (%s)", inserted->node_name);
644         }
645     } else {
646         assert(info || inserted);
647         monitor_puts(mon,
648                      inserted && inserted->node_name ? inserted->node_name
649                      : info && info->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->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->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_node_info_dump(qapi_ImageInfo_base(image_info), 0, false);
738             if (image_info->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->inserted,
773                          verbose);
774         printed = true;
775     }
776 
777     qapi_free_BlockInfoList(block_list);
778 
779     if ((!device && !nodes) || printed) {
780         return;
781     }
782 
783     /* Print node information */
784     blockdev_list = qmp_query_named_block_nodes(false, false, NULL);
785     for (blockdev = blockdev_list; blockdev; blockdev = blockdev->next) {
786         assert(blockdev->value->node_name);
787         if (device && strcmp(device, blockdev->value->node_name)) {
788             continue;
789         }
790 
791         if (blockdev != blockdev_list) {
792             monitor_printf(mon, "\n");
793         }
794 
795         print_block_info(mon, NULL, blockdev->value, verbose);
796     }
797     qapi_free_BlockDeviceInfoList(blockdev_list);
798 }
799 
800 void hmp_info_blockstats(Monitor *mon, const QDict *qdict)
801 {
802     BlockStatsList *stats_list, *stats;
803 
804     stats_list = qmp_query_blockstats(false, false, NULL);
805 
806     for (stats = stats_list; stats; stats = stats->next) {
807         if (!stats->value->device) {
808             continue;
809         }
810 
811         monitor_printf(mon, "%s:", stats->value->device);
812         monitor_printf(mon, " rd_bytes=%" PRId64
813                        " wr_bytes=%" PRId64
814                        " rd_operations=%" PRId64
815                        " wr_operations=%" PRId64
816                        " flush_operations=%" PRId64
817                        " wr_total_time_ns=%" PRId64
818                        " rd_total_time_ns=%" PRId64
819                        " flush_total_time_ns=%" PRId64
820                        " rd_merged=%" PRId64
821                        " wr_merged=%" PRId64
822                        " idle_time_ns=%" PRId64
823                        "\n",
824                        stats->value->stats->rd_bytes,
825                        stats->value->stats->wr_bytes,
826                        stats->value->stats->rd_operations,
827                        stats->value->stats->wr_operations,
828                        stats->value->stats->flush_operations,
829                        stats->value->stats->wr_total_time_ns,
830                        stats->value->stats->rd_total_time_ns,
831                        stats->value->stats->flush_total_time_ns,
832                        stats->value->stats->rd_merged,
833                        stats->value->stats->wr_merged,
834                        stats->value->stats->idle_time_ns);
835     }
836 
837     qapi_free_BlockStatsList(stats_list);
838 }
839 
840 void hmp_info_block_jobs(Monitor *mon, const QDict *qdict)
841 {
842     BlockJobInfoList *list;
843 
844     list = qmp_query_block_jobs(&error_abort);
845 
846     if (!list) {
847         monitor_printf(mon, "No active jobs\n");
848         return;
849     }
850 
851     while (list) {
852         if (list->value->type == JOB_TYPE_STREAM) {
853             monitor_printf(mon, "Streaming device %s: Completed %" PRId64
854                            " of %" PRId64 " bytes, speed limit %" PRId64
855                            " bytes/s\n",
856                            list->value->device,
857                            list->value->offset,
858                            list->value->len,
859                            list->value->speed);
860         } else {
861             monitor_printf(mon, "Type %s, device %s: Completed %" PRId64
862                            " of %" PRId64 " bytes, speed limit %" PRId64
863                            " bytes/s\n",
864                            JobType_str(list->value->type),
865                            list->value->device,
866                            list->value->offset,
867                            list->value->len,
868                            list->value->speed);
869         }
870         list = list->next;
871     }
872 
873     qapi_free_BlockJobInfoList(list);
874 }
875 
876 void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
877 {
878     BlockDriverState *bs, *bs1;
879     BdrvNextIterator it1;
880     QEMUSnapshotInfo *sn_tab, *sn;
881     bool no_snapshot = true;
882     int nb_sns, i;
883     int total;
884     int *global_snapshots;
885     AioContext *aio_context;
886 
887     typedef struct SnapshotEntry {
888         QEMUSnapshotInfo sn;
889         QTAILQ_ENTRY(SnapshotEntry) next;
890     } SnapshotEntry;
891 
892     typedef struct ImageEntry {
893         const char *imagename;
894         QTAILQ_ENTRY(ImageEntry) next;
895         QTAILQ_HEAD(, SnapshotEntry) snapshots;
896     } ImageEntry;
897 
898     QTAILQ_HEAD(, ImageEntry) image_list =
899         QTAILQ_HEAD_INITIALIZER(image_list);
900 
901     ImageEntry *image_entry, *next_ie;
902     SnapshotEntry *snapshot_entry;
903     Error *err = NULL;
904 
905     GRAPH_RDLOCK_GUARD_MAINLOOP();
906 
907     bs = bdrv_all_find_vmstate_bs(NULL, false, NULL, &err);
908     if (!bs) {
909         error_report_err(err);
910         return;
911     }
912     aio_context = bdrv_get_aio_context(bs);
913 
914     aio_context_acquire(aio_context);
915     nb_sns = bdrv_snapshot_list(bs, &sn_tab);
916     aio_context_release(aio_context);
917 
918     if (nb_sns < 0) {
919         monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
920         return;
921     }
922 
923     for (bs1 = bdrv_first(&it1); bs1; bs1 = bdrv_next(&it1)) {
924         int bs1_nb_sns = 0;
925         ImageEntry *ie;
926         SnapshotEntry *se;
927         AioContext *ctx = bdrv_get_aio_context(bs1);
928 
929         aio_context_acquire(ctx);
930         if (bdrv_can_snapshot(bs1)) {
931             sn = NULL;
932             bs1_nb_sns = bdrv_snapshot_list(bs1, &sn);
933             if (bs1_nb_sns > 0) {
934                 no_snapshot = false;
935                 ie = g_new0(ImageEntry, 1);
936                 ie->imagename = bdrv_get_device_name(bs1);
937                 QTAILQ_INIT(&ie->snapshots);
938                 QTAILQ_INSERT_TAIL(&image_list, ie, next);
939                 for (i = 0; i < bs1_nb_sns; i++) {
940                     se = g_new0(SnapshotEntry, 1);
941                     se->sn = sn[i];
942                     QTAILQ_INSERT_TAIL(&ie->snapshots, se, next);
943                 }
944             }
945             g_free(sn);
946         }
947         aio_context_release(ctx);
948     }
949 
950     if (no_snapshot) {
951         monitor_printf(mon, "There is no snapshot available.\n");
952         return;
953     }
954 
955     global_snapshots = g_new0(int, nb_sns);
956     total = 0;
957     for (i = 0; i < nb_sns; i++) {
958         SnapshotEntry *next_sn;
959         if (bdrv_all_has_snapshot(sn_tab[i].name, false, NULL, NULL) == 1) {
960             global_snapshots[total] = i;
961             total++;
962             QTAILQ_FOREACH(image_entry, &image_list, next) {
963                 QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots,
964                                     next, next_sn) {
965                     if (!strcmp(sn_tab[i].name, snapshot_entry->sn.name)) {
966                         QTAILQ_REMOVE(&image_entry->snapshots, snapshot_entry,
967                                       next);
968                         g_free(snapshot_entry);
969                     }
970                 }
971             }
972         }
973     }
974     monitor_printf(mon, "List of snapshots present on all disks:\n");
975 
976     if (total > 0) {
977         bdrv_snapshot_dump(NULL);
978         monitor_printf(mon, "\n");
979         for (i = 0; i < total; i++) {
980             sn = &sn_tab[global_snapshots[i]];
981             /*
982              * The ID is not guaranteed to be the same on all images, so
983              * overwrite it.
984              */
985             pstrcpy(sn->id_str, sizeof(sn->id_str), "--");
986             bdrv_snapshot_dump(sn);
987             monitor_printf(mon, "\n");
988         }
989     } else {
990         monitor_printf(mon, "None\n");
991     }
992 
993     QTAILQ_FOREACH(image_entry, &image_list, next) {
994         if (QTAILQ_EMPTY(&image_entry->snapshots)) {
995             continue;
996         }
997         monitor_printf(mon,
998                        "\nList of partial (non-loadable) snapshots on '%s':\n",
999                        image_entry->imagename);
1000         bdrv_snapshot_dump(NULL);
1001         monitor_printf(mon, "\n");
1002         QTAILQ_FOREACH(snapshot_entry, &image_entry->snapshots, next) {
1003             bdrv_snapshot_dump(&snapshot_entry->sn);
1004             monitor_printf(mon, "\n");
1005         }
1006     }
1007 
1008     QTAILQ_FOREACH_SAFE(image_entry, &image_list, next, next_ie) {
1009         SnapshotEntry *next_sn;
1010         QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots, next,
1011                             next_sn) {
1012             g_free(snapshot_entry);
1013         }
1014         g_free(image_entry);
1015     }
1016     g_free(sn_tab);
1017     g_free(global_snapshots);
1018 }
1019 
1020 void hmp_change_medium(Monitor *mon, const char *device, const char *target,
1021                        const char *arg, const char *read_only, bool force,
1022                        Error **errp)
1023 {
1024     ERRP_GUARD();
1025     BlockdevChangeReadOnlyMode read_only_mode = 0;
1026 
1027     if (read_only) {
1028         read_only_mode =
1029             qapi_enum_parse(&BlockdevChangeReadOnlyMode_lookup,
1030                             read_only,
1031                             BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, errp);
1032         if (*errp) {
1033             return;
1034         }
1035     }
1036 
1037     qmp_blockdev_change_medium(device, NULL, target, arg, true, force,
1038                                !!read_only, read_only_mode, errp);
1039 }
1040