2 * QMP command handlers specific to the system emulators
4 * Copyright (c) 2003-2008 Fabrice Bellard
6 * This work is licensed under the terms of the GNU GPL, version 2 or
7 * later. See the COPYING file in the top-level directory.
9 * This file incorporates work covered by the following copyright and
12 * Copyright (c) 2003-2008 Fabrice Bellard
14 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this software and associated documentation files (the "Software"), to deal
16 * in the Software without restriction, including without limitation the rights
17 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18 * copies of the Software, and to permit persons to whom the Software is
19 * furnished to do so, subject to the following conditions:
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
33 #include "qemu/osdep.h"
35 #include "block/block_int.h"
36 #include "qapi/error.h"
37 #include "qapi/qapi-commands-block.h"
38 #include "qapi/qmp/qdict.h"
39 #include "sysemu/block-backend.h"
40 #include "sysemu/blockdev.h"
42 static BlockBackend
*qmp_get_blk(const char *blk_name
, const char *qdev_id
,
47 if (!blk_name
== !qdev_id
) {
48 error_setg(errp
, "Need exactly one of 'device' and 'id'");
53 blk
= blk_by_qdev_id(qdev_id
, errp
);
55 blk
= blk_by_name(blk_name
);
57 error_set(errp
, ERROR_CLASS_DEVICE_NOT_FOUND
,
58 "Device '%s' not found", blk_name
);
66 * Attempt to open the tray of @device.
67 * If @force, ignore its tray lock.
68 * Else, if the tray is locked, don't open it, but ask the guest to open it.
69 * On error, store an error through @errp and return -errno.
70 * If @device does not exist, return -ENODEV.
71 * If it has no removable media, return -ENOTSUP.
72 * If it has no tray, return -ENOSYS.
73 * If the guest was asked to open the tray, return -EINPROGRESS.
76 static int do_open_tray(const char *blk_name
, const char *qdev_id
,
77 bool force
, Error
**errp
)
80 const char *device
= qdev_id
?: blk_name
;
83 blk
= qmp_get_blk(blk_name
, qdev_id
, errp
);
88 if (!blk_dev_has_removable_media(blk
)) {
89 error_setg(errp
, "Device '%s' is not removable", device
);
93 if (!blk_dev_has_tray(blk
)) {
94 error_setg(errp
, "Device '%s' does not have a tray", device
);
98 if (blk_dev_is_tray_open(blk
)) {
102 locked
= blk_dev_is_medium_locked(blk
);
104 blk_dev_eject_request(blk
, force
);
107 if (!locked
|| force
) {
108 blk_dev_change_media_cb(blk
, false, &error_abort
);
111 if (locked
&& !force
) {
112 error_setg(errp
, "Device '%s' is locked and force was not specified, "
113 "wait for tray to open and try again", device
);
120 void qmp_blockdev_open_tray(const char *device
,
122 bool has_force
, bool force
,
125 Error
*local_err
= NULL
;
131 rc
= do_open_tray(device
, id
, force
, &local_err
);
132 if (rc
&& rc
!= -ENOSYS
&& rc
!= -EINPROGRESS
) {
133 error_propagate(errp
, local_err
);
136 error_free(local_err
);
139 void qmp_blockdev_close_tray(const char *device
,
144 Error
*local_err
= NULL
;
146 blk
= qmp_get_blk(device
, id
, errp
);
151 if (!blk_dev_has_removable_media(blk
)) {
152 error_setg(errp
, "Device '%s' is not removable", device
?: id
);
156 if (!blk_dev_has_tray(blk
)) {
157 /* Ignore this command on tray-less devices */
161 if (!blk_dev_is_tray_open(blk
)) {
165 blk_dev_change_media_cb(blk
, true, &local_err
);
167 error_propagate(errp
, local_err
);
172 static void GRAPH_UNLOCKED
173 blockdev_remove_medium(const char *device
, const char *id
, Error
**errp
)
176 BlockDriverState
*bs
;
177 AioContext
*aio_context
;
178 bool has_attached_device
;
182 blk
= qmp_get_blk(device
, id
, errp
);
187 /* For BBs without a device, we can exchange the BDS tree at will */
188 has_attached_device
= blk_get_attached_dev(blk
);
190 if (has_attached_device
&& !blk_dev_has_removable_media(blk
)) {
191 error_setg(errp
, "Device '%s' is not removable", device
?: id
);
195 if (has_attached_device
&& blk_dev_has_tray(blk
) &&
196 !blk_dev_is_tray_open(blk
))
198 error_setg(errp
, "Tray of device '%s' is not open", device
?: id
);
207 aio_context
= bdrv_get_aio_context(bs
);
208 aio_context_acquire(aio_context
);
210 bdrv_graph_rdlock_main_loop();
211 if (bdrv_op_is_blocked(bs
, BLOCK_OP_TYPE_EJECT
, errp
)) {
212 bdrv_graph_rdunlock_main_loop();
215 bdrv_graph_rdunlock_main_loop();
219 if (!blk_dev_has_tray(blk
)) {
220 /* For tray-less devices, blockdev-open-tray is a no-op (or may not be
221 * called at all); therefore, the medium needs to be ejected here.
222 * Do it after blk_remove_bs() so blk_is_inserted(blk) returns the @load
223 * value passed here (i.e. false). */
224 blk_dev_change_media_cb(blk
, false, &error_abort
);
228 aio_context_release(aio_context
);
231 void qmp_blockdev_remove_medium(const char *id
, Error
**errp
)
233 blockdev_remove_medium(NULL
, id
, errp
);
236 static void qmp_blockdev_insert_anon_medium(BlockBackend
*blk
,
237 BlockDriverState
*bs
, Error
**errp
)
239 Error
*local_err
= NULL
;
244 /* For BBs without a device, we can exchange the BDS tree at will */
245 has_device
= blk_get_attached_dev(blk
);
247 if (has_device
&& !blk_dev_has_removable_media(blk
)) {
248 error_setg(errp
, "Device is not removable");
252 if (has_device
&& blk_dev_has_tray(blk
) && !blk_dev_is_tray_open(blk
)) {
253 error_setg(errp
, "Tray of the device is not open");
258 error_setg(errp
, "There already is a medium in the device");
262 ctx
= bdrv_get_aio_context(bs
);
263 aio_context_acquire(ctx
);
264 ret
= blk_insert_bs(blk
, bs
, errp
);
265 aio_context_release(ctx
);
271 if (!blk_dev_has_tray(blk
)) {
272 /* For tray-less devices, blockdev-close-tray is a no-op (or may not be
273 * called at all); therefore, the medium needs to be pushed into the
275 * Do it after blk_insert_bs() so blk_is_inserted(blk) returns the @load
276 * value passed here (i.e. true). */
277 blk_dev_change_media_cb(blk
, true, &local_err
);
279 error_propagate(errp
, local_err
);
286 static void blockdev_insert_medium(const char *device
, const char *id
,
287 const char *node_name
, Error
**errp
)
290 BlockDriverState
*bs
;
292 GRAPH_RDLOCK_GUARD_MAINLOOP();
294 blk
= qmp_get_blk(device
, id
, errp
);
299 bs
= bdrv_find_node(node_name
);
301 error_setg(errp
, "Node '%s' not found", node_name
);
305 if (bdrv_has_blk(bs
)) {
306 error_setg(errp
, "Node '%s' is already in use", node_name
);
310 qmp_blockdev_insert_anon_medium(blk
, bs
, errp
);
313 void qmp_blockdev_insert_medium(const char *id
, const char *node_name
,
316 blockdev_insert_medium(NULL
, id
, node_name
, errp
);
319 void qmp_blockdev_change_medium(const char *device
,
321 const char *filename
,
323 bool has_force
, bool force
,
325 BlockdevChangeReadOnlyMode read_only
,
329 BlockDriverState
*medium_bs
= NULL
;
333 QDict
*options
= NULL
;
336 blk
= qmp_get_blk(device
, id
, errp
);
342 blk_update_root_state(blk
);
345 bdrv_flags
= blk_get_open_flags_from_root_state(blk
);
346 bdrv_flags
&= ~(BDRV_O_TEMPORARY
| BDRV_O_SNAPSHOT
| BDRV_O_NO_BACKING
|
347 BDRV_O_PROTOCOL
| BDRV_O_AUTO_RDONLY
);
349 if (!has_read_only
) {
350 read_only
= BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN
;
354 case BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN
:
357 case BLOCKDEV_CHANGE_READ_ONLY_MODE_READ_ONLY
:
358 bdrv_flags
&= ~BDRV_O_RDWR
;
361 case BLOCKDEV_CHANGE_READ_ONLY_MODE_READ_WRITE
:
362 bdrv_flags
|= BDRV_O_RDWR
;
369 options
= qdict_new();
370 detect_zeroes
= blk_get_detect_zeroes_from_root_state(blk
);
371 qdict_put_str(options
, "detect-zeroes", detect_zeroes
? "on" : "off");
374 qdict_put_str(options
, "driver", format
);
377 aio_context_acquire(qemu_get_aio_context());
378 medium_bs
= bdrv_open(filename
, NULL
, options
, bdrv_flags
, errp
);
379 aio_context_release(qemu_get_aio_context());
385 rc
= do_open_tray(device
, id
, force
, &err
);
386 if (rc
&& rc
!= -ENOSYS
) {
387 error_propagate(errp
, err
);
393 blockdev_remove_medium(device
, id
, &err
);
395 error_propagate(errp
, err
);
399 qmp_blockdev_insert_anon_medium(blk
, medium_bs
, &err
);
401 error_propagate(errp
, err
);
405 qmp_blockdev_close_tray(device
, id
, errp
);
408 /* If the medium has been inserted, the device has its own reference, so
409 * ours must be relinquished; and if it has not been inserted successfully,
410 * the reference must be relinquished anyway */
411 bdrv_unref(medium_bs
);
414 void qmp_eject(const char *device
, const char *id
,
415 bool has_force
, bool force
, Error
**errp
)
417 Error
*local_err
= NULL
;
424 rc
= do_open_tray(device
, id
, force
, &local_err
);
425 if (rc
&& rc
!= -ENOSYS
) {
426 error_propagate(errp
, local_err
);
429 error_free(local_err
);
431 blockdev_remove_medium(device
, id
, errp
);
434 /* throttling disk I/O limits */
435 void qmp_block_set_io_throttle(BlockIOThrottle
*arg
, Error
**errp
)
438 BlockDriverState
*bs
;
440 AioContext
*aio_context
;
442 blk
= qmp_get_blk(arg
->device
, arg
->id
, errp
);
447 aio_context
= blk_get_aio_context(blk
);
448 aio_context_acquire(aio_context
);
452 error_setg(errp
, "Device has no medium");
456 throttle_config_init(&cfg
);
457 cfg
.buckets
[THROTTLE_BPS_TOTAL
].avg
= arg
->bps
;
458 cfg
.buckets
[THROTTLE_BPS_READ
].avg
= arg
->bps_rd
;
459 cfg
.buckets
[THROTTLE_BPS_WRITE
].avg
= arg
->bps_wr
;
461 cfg
.buckets
[THROTTLE_OPS_TOTAL
].avg
= arg
->iops
;
462 cfg
.buckets
[THROTTLE_OPS_READ
].avg
= arg
->iops_rd
;
463 cfg
.buckets
[THROTTLE_OPS_WRITE
].avg
= arg
->iops_wr
;
465 if (arg
->has_bps_max
) {
466 cfg
.buckets
[THROTTLE_BPS_TOTAL
].max
= arg
->bps_max
;
468 if (arg
->has_bps_rd_max
) {
469 cfg
.buckets
[THROTTLE_BPS_READ
].max
= arg
->bps_rd_max
;
471 if (arg
->has_bps_wr_max
) {
472 cfg
.buckets
[THROTTLE_BPS_WRITE
].max
= arg
->bps_wr_max
;
474 if (arg
->has_iops_max
) {
475 cfg
.buckets
[THROTTLE_OPS_TOTAL
].max
= arg
->iops_max
;
477 if (arg
->has_iops_rd_max
) {
478 cfg
.buckets
[THROTTLE_OPS_READ
].max
= arg
->iops_rd_max
;
480 if (arg
->has_iops_wr_max
) {
481 cfg
.buckets
[THROTTLE_OPS_WRITE
].max
= arg
->iops_wr_max
;
484 if (arg
->has_bps_max_length
) {
485 cfg
.buckets
[THROTTLE_BPS_TOTAL
].burst_length
= arg
->bps_max_length
;
487 if (arg
->has_bps_rd_max_length
) {
488 cfg
.buckets
[THROTTLE_BPS_READ
].burst_length
= arg
->bps_rd_max_length
;
490 if (arg
->has_bps_wr_max_length
) {
491 cfg
.buckets
[THROTTLE_BPS_WRITE
].burst_length
= arg
->bps_wr_max_length
;
493 if (arg
->has_iops_max_length
) {
494 cfg
.buckets
[THROTTLE_OPS_TOTAL
].burst_length
= arg
->iops_max_length
;
496 if (arg
->has_iops_rd_max_length
) {
497 cfg
.buckets
[THROTTLE_OPS_READ
].burst_length
= arg
->iops_rd_max_length
;
499 if (arg
->has_iops_wr_max_length
) {
500 cfg
.buckets
[THROTTLE_OPS_WRITE
].burst_length
= arg
->iops_wr_max_length
;
503 if (arg
->has_iops_size
) {
504 cfg
.op_size
= arg
->iops_size
;
507 if (!throttle_is_valid(&cfg
, errp
)) {
511 if (throttle_enabled(&cfg
)) {
512 /* Enable I/O limits if they're not enabled yet, otherwise
513 * just update the throttling group. */
514 if (!blk_get_public(blk
)->throttle_group_member
.throttle_state
) {
515 blk_io_limits_enable(blk
, arg
->group
?: arg
->device
?: arg
->id
);
516 } else if (arg
->group
) {
517 blk_io_limits_update_group(blk
, arg
->group
);
519 /* Set the new throttling configuration */
520 blk_set_io_limits(blk
, &cfg
);
521 } else if (blk_get_public(blk
)->throttle_group_member
.throttle_state
) {
522 /* If all throttling settings are set to 0, disable I/O limits */
523 blk_io_limits_disable(blk
);
527 aio_context_release(aio_context
);
530 void qmp_block_latency_histogram_set(
532 bool has_boundaries
, uint64List
*boundaries
,
533 bool has_boundaries_read
, uint64List
*boundaries_read
,
534 bool has_boundaries_write
, uint64List
*boundaries_write
,
535 bool has_boundaries_append
, uint64List
*boundaries_append
,
536 bool has_boundaries_flush
, uint64List
*boundaries_flush
,
539 BlockBackend
*blk
= qmp_get_blk(NULL
, id
, errp
);
540 BlockAcctStats
*stats
;
547 stats
= blk_get_stats(blk
);
549 if (!has_boundaries
&& !has_boundaries_read
&& !has_boundaries_write
&&
550 !has_boundaries_flush
)
552 block_latency_histograms_clear(stats
);
556 if (has_boundaries
|| has_boundaries_read
) {
557 ret
= block_latency_histogram_set(
558 stats
, BLOCK_ACCT_READ
,
559 has_boundaries_read
? boundaries_read
: boundaries
);
561 error_setg(errp
, "Device '%s' set read boundaries fail", id
);
566 if (has_boundaries
|| has_boundaries_write
) {
567 ret
= block_latency_histogram_set(
568 stats
, BLOCK_ACCT_WRITE
,
569 has_boundaries_write
? boundaries_write
: boundaries
);
571 error_setg(errp
, "Device '%s' set write boundaries fail", id
);
576 if (has_boundaries
|| has_boundaries_append
) {
577 ret
= block_latency_histogram_set(
578 stats
, BLOCK_ACCT_ZONE_APPEND
,
579 has_boundaries_append
? boundaries_append
: boundaries
);
581 error_setg(errp
, "Device '%s' set append write boundaries fail", id
);
586 if (has_boundaries
|| has_boundaries_flush
) {
587 ret
= block_latency_histogram_set(
588 stats
, BLOCK_ACCT_FLUSH
,
589 has_boundaries_flush
? boundaries_flush
: boundaries
);
591 error_setg(errp
, "Device '%s' set flush boundaries fail", id
);