qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging

Block layer patches:

- Add qemu-storage-daemon (still experimental)
- rbd: Add support for ceph namespaces
- Fix bdrv_reopen() with backing file in different AioContext
- qcow2: Fix read-write reopen with persistent dirty bitmaps
- qcow2: Fix alloc_cluster_abort() for pre-existing clusters

# gpg: Signature made Fri 06 Mar 2020 17:12:31 GMT
# gpg: using RSA key 7F09B272C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full]
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6

* remotes/kevin/tags/for-upstream: (29 commits)
block: bdrv_reopen() with backing file in different AioContext
iotests: Refactor blockdev-reopen test for iothreads
block/rbd: Add support for ceph namespaces
qemu-storage-daemon: Add --monitor option
monitor: Add allow_hmp parameter to monitor_init()
hmp: Fail gracefully if chardev is already in use
qmp: Fail gracefully if chardev is already in use
monitor: Create QAPIfied monitor_init()
qapi: Create 'pragma' module
stubs: Update monitor stubs for qemu-storage-daemon
qemu-storage-daemon: Add --chardev option
qemu-storage-daemon: Add main loop
qemu-storage-daemon: Add --export option
blockdev-nbd: Boxed argument type for nbd-server-add
qemu-storage-daemon: Add --nbd-server option
qemu-storage-daemon: Add --object option
qapi: Flatten object-add
qemu-storage-daemon: Add --blockdev option
block: Move sysemu QMP commands to QAPI block module
block: Move common QMP commands to block-core QAPI module
...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

+2154 -1303
+37
Makefile
··· 128 128 GENERATED_QAPI_FILES += qapi/qapi-introspect.c qapi/qapi-introspect.h 129 129 GENERATED_QAPI_FILES += qapi/qapi-doc.texi 130 130 131 + # The following list considers only the storage daemon main module. All other 132 + # modules are currently shared with the main schema, so we don't actually 133 + # generate additional files. 134 + 135 + GENERATED_STORAGE_DAEMON_QAPI_FILES = storage-daemon/qapi/qapi-commands.h 136 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-commands.c 137 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-emit-events.h 138 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-emit-events.c 139 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-events.h 140 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-events.c 141 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-init-commands.h 142 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-init-commands.c 143 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-introspect.h 144 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-introspect.c 145 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-types.h 146 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-types.c 147 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-visit.h 148 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-visit.c 149 + GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-doc.texi 150 + 131 151 generated-files-y += $(GENERATED_QAPI_FILES) 152 + generated-files-y += $(GENERATED_STORAGE_DAEMON_QAPI_FILES) 132 153 133 154 generated-files-y += trace/generated-tcg-tracers.h 134 155 ··· 450 471 qga-vss-dll-obj-y \ 451 472 block-obj-y \ 452 473 block-obj-m \ 474 + storage-daemon-obj-y \ 475 + storage-daemon-obj-m \ 453 476 crypto-obj-y \ 454 477 qom-obj-y \ 455 478 io-obj-y \ ··· 482 505 SOFTMMU_ALL_RULES=$(filter %-softmmu/all, $(TARGET_DIRS_RULES)) 483 506 $(SOFTMMU_ALL_RULES): $(authz-obj-y) 484 507 $(SOFTMMU_ALL_RULES): $(block-obj-y) 508 + $(SOFTMMU_ALL_RULES): $(storage-daemon-obj-y) 485 509 $(SOFTMMU_ALL_RULES): $(chardev-obj-y) 486 510 $(SOFTMMU_ALL_RULES): $(crypto-obj-y) 487 511 $(SOFTMMU_ALL_RULES): $(io-obj-y) ··· 586 610 qemu-img$(EXESUF): qemu-img.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS) 587 611 qemu-nbd$(EXESUF): qemu-nbd.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS) 588 612 qemu-io$(EXESUF): qemu-io.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS) 613 + qemu-storage-daemon$(EXESUF): qemu-storage-daemon.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(chardev-obj-y) $(io-obj-y) $(qom-obj-y) $(storage-daemon-obj-y) $(COMMON_LDADDS) 589 614 590 615 qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o $(COMMON_LDADDS) 591 616 ··· 647 672 "GEN","$(@:%-timestamp=%)") 648 673 @>$@ 649 674 675 + qapi-modules-storage-daemon = \ 676 + $(SRC_PATH)/storage-daemon/qapi/qapi-schema.json \ 677 + $(QAPI_MODULES_STORAGE_DAEMON:%=$(SRC_PATH)/qapi/%.json) 678 + 679 + $(GENERATED_STORAGE_DAEMON_QAPI_FILES): storage-daemon/qapi/qapi-gen-timestamp ; 680 + storage-daemon/qapi/qapi-gen-timestamp: $(qapi-modules-storage-daemon) $(qapi-py) 681 + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \ 682 + -o "storage-daemon/qapi" $<, \ 683 + "GEN","$(@:%-timestamp=%)") 684 + @>$@ 685 + 650 686 QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qapi-commands.h qga-qapi-init-commands.h) 651 687 $(qga-obj-y): $(QGALIB_GEN) 652 688 ··· 745 781 rm -f trace/generated-tracers-dtrace.h* 746 782 rm -f $(foreach f,$(generated-files-y),$(f) $(f)-timestamp) 747 783 rm -f qapi-gen-timestamp 784 + rm -f storage-daemon/qapi/qapi-gen-timestamp 748 785 rm -rf qga/qapi-generated 749 786 rm -f config-all-devices.mak 750 787
+9
Makefile.objs
··· 27 27 28 28 endif # CONFIG_SOFTMMU or CONFIG_TOOLS 29 29 30 + ####################################################################### 31 + # storage-daemon-obj-y is code used by qemu-storage-daemon (these objects are 32 + # used for system emulation, too, but specified separately there) 33 + 34 + storage-daemon-obj-y = block/ monitor/ qapi/ qom/ storage-daemon/ 35 + storage-daemon-obj-y += blockdev.o blockdev-nbd.o iothread.o job-qmp.o 36 + storage-daemon-obj-$(CONFIG_WIN32) += os-win32.o 37 + storage-daemon-obj-$(CONFIG_POSIX) += os-posix.o 38 + 30 39 ###################################################################### 31 40 # Target independent part of system emulation. The long term path is to 32 41 # suppress *all* target specific code in case of system emulation, i.e. a
+37 -7
block.c
··· 600 600 QemuOpts *opts, Error **errp) 601 601 { 602 602 BlockBackend *blk; 603 - QDict *options = qdict_new(); 603 + QDict *options; 604 604 int64_t size = 0; 605 605 char *buf = NULL; 606 606 PreallocMode prealloc; ··· 623 623 return -ENOTSUP; 624 624 } 625 625 626 + options = qdict_new(); 626 627 qdict_put_str(options, "driver", drv->format_name); 627 628 628 629 blk = blk_new_open(filename, NULL, options, ··· 3694 3695 } 3695 3696 } 3696 3697 } 3698 + 3699 + if (ret == 0) { 3700 + QTAILQ_FOREACH_REVERSE(bs_entry, bs_queue, entry) { 3701 + BlockDriverState *bs = bs_entry->state.bs; 3702 + 3703 + if (bs->drv->bdrv_reopen_commit_post) 3704 + bs->drv->bdrv_reopen_commit_post(&bs_entry->state); 3705 + } 3706 + } 3697 3707 cleanup: 3698 3708 QTAILQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) { 3699 3709 if (ret) { ··· 3777 3787 *shared = cumulative_shared_perms; 3778 3788 } 3779 3789 3790 + static bool bdrv_reopen_can_attach(BlockDriverState *parent, 3791 + BdrvChild *child, 3792 + BlockDriverState *new_child, 3793 + Error **errp) 3794 + { 3795 + AioContext *parent_ctx = bdrv_get_aio_context(parent); 3796 + AioContext *child_ctx = bdrv_get_aio_context(new_child); 3797 + GSList *ignore; 3798 + bool ret; 3799 + 3800 + ignore = g_slist_prepend(NULL, child); 3801 + ret = bdrv_can_set_aio_context(new_child, parent_ctx, &ignore, NULL); 3802 + g_slist_free(ignore); 3803 + if (ret) { 3804 + return ret; 3805 + } 3806 + 3807 + ignore = g_slist_prepend(NULL, child); 3808 + ret = bdrv_can_set_aio_context(parent, child_ctx, &ignore, errp); 3809 + g_slist_free(ignore); 3810 + return ret; 3811 + } 3812 + 3780 3813 /* 3781 3814 * Take a BDRVReopenState and check if the value of 'backing' in the 3782 3815 * reopen_state->options QDict is valid or not. ··· 3828 3861 } 3829 3862 3830 3863 /* 3831 - * TODO: before removing the x- prefix from x-blockdev-reopen we 3832 - * should move the new backing file into the right AioContext 3833 - * instead of returning an error. 3864 + * Check AioContext compatibility so that the bdrv_set_backing_hd() call in 3865 + * bdrv_reopen_commit() won't fail. 3834 3866 */ 3835 3867 if (new_backing_bs) { 3836 - if (bdrv_get_aio_context(new_backing_bs) != bdrv_get_aio_context(bs)) { 3837 - error_setg(errp, "Cannot use a new backing file " 3838 - "with a different AioContext"); 3868 + if (!bdrv_reopen_can_attach(bs, bs->backing, new_backing_bs, errp)) { 3839 3869 return -EINVAL; 3840 3870 } 3841 3871 }
+3 -1
block/Makefile.objs
··· 46 46 block-obj-y += backup-top.o 47 47 block-obj-y += filter-compress.o 48 48 49 - common-obj-y += stream.o 49 + block-obj-y += stream.o 50 + 51 + common-obj-y += qapi-sysemu.o 50 52 51 53 nfs.o-libs := $(LIBNFS_LIBS) 52 54 iscsi.o-cflags := $(LIBISCSI_CFLAGS)
+590
block/qapi-sysemu.c
··· 1 + /* 2 + * QMP command handlers specific to the system emulators 3 + * 4 + * Copyright (c) 2003-2008 Fabrice Bellard 5 + * 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. 8 + * 9 + * This file incorporates work covered by the following copyright and 10 + * permission notice: 11 + * 12 + * Copyright (c) 2003-2008 Fabrice Bellard 13 + * 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: 20 + * 21 + * The above copyright notice and this permission notice shall be included in 22 + * all copies or substantial portions of the Software. 23 + * 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 30 + * THE SOFTWARE. 31 + */ 32 + 33 + #include "qemu/osdep.h" 34 + 35 + #include "qapi/error.h" 36 + #include "qapi/qapi-commands-block.h" 37 + #include "qapi/qmp/qdict.h" 38 + #include "sysemu/block-backend.h" 39 + #include "sysemu/blockdev.h" 40 + 41 + static BlockBackend *qmp_get_blk(const char *blk_name, const char *qdev_id, 42 + Error **errp) 43 + { 44 + BlockBackend *blk; 45 + 46 + if (!blk_name == !qdev_id) { 47 + error_setg(errp, "Need exactly one of 'device' and 'id'"); 48 + return NULL; 49 + } 50 + 51 + if (qdev_id) { 52 + blk = blk_by_qdev_id(qdev_id, errp); 53 + } else { 54 + blk = blk_by_name(blk_name); 55 + if (blk == NULL) { 56 + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 57 + "Device '%s' not found", blk_name); 58 + } 59 + } 60 + 61 + return blk; 62 + } 63 + 64 + /* 65 + * Attempt to open the tray of @device. 66 + * If @force, ignore its tray lock. 67 + * Else, if the tray is locked, don't open it, but ask the guest to open it. 68 + * On error, store an error through @errp and return -errno. 69 + * If @device does not exist, return -ENODEV. 70 + * If it has no removable media, return -ENOTSUP. 71 + * If it has no tray, return -ENOSYS. 72 + * If the guest was asked to open the tray, return -EINPROGRESS. 73 + * Else, return 0. 74 + */ 75 + static int do_open_tray(const char *blk_name, const char *qdev_id, 76 + bool force, Error **errp) 77 + { 78 + BlockBackend *blk; 79 + const char *device = qdev_id ?: blk_name; 80 + bool locked; 81 + 82 + blk = qmp_get_blk(blk_name, qdev_id, errp); 83 + if (!blk) { 84 + return -ENODEV; 85 + } 86 + 87 + if (!blk_dev_has_removable_media(blk)) { 88 + error_setg(errp, "Device '%s' is not removable", device); 89 + return -ENOTSUP; 90 + } 91 + 92 + if (!blk_dev_has_tray(blk)) { 93 + error_setg(errp, "Device '%s' does not have a tray", device); 94 + return -ENOSYS; 95 + } 96 + 97 + if (blk_dev_is_tray_open(blk)) { 98 + return 0; 99 + } 100 + 101 + locked = blk_dev_is_medium_locked(blk); 102 + if (locked) { 103 + blk_dev_eject_request(blk, force); 104 + } 105 + 106 + if (!locked || force) { 107 + blk_dev_change_media_cb(blk, false, &error_abort); 108 + } 109 + 110 + if (locked && !force) { 111 + error_setg(errp, "Device '%s' is locked and force was not specified, " 112 + "wait for tray to open and try again", device); 113 + return -EINPROGRESS; 114 + } 115 + 116 + return 0; 117 + } 118 + 119 + void qmp_blockdev_open_tray(bool has_device, const char *device, 120 + bool has_id, const char *id, 121 + bool has_force, bool force, 122 + Error **errp) 123 + { 124 + Error *local_err = NULL; 125 + int rc; 126 + 127 + if (!has_force) { 128 + force = false; 129 + } 130 + rc = do_open_tray(has_device ? device : NULL, 131 + has_id ? id : NULL, 132 + force, &local_err); 133 + if (rc && rc != -ENOSYS && rc != -EINPROGRESS) { 134 + error_propagate(errp, local_err); 135 + return; 136 + } 137 + error_free(local_err); 138 + } 139 + 140 + void qmp_blockdev_close_tray(bool has_device, const char *device, 141 + bool has_id, const char *id, 142 + Error **errp) 143 + { 144 + BlockBackend *blk; 145 + Error *local_err = NULL; 146 + 147 + device = has_device ? device : NULL; 148 + id = has_id ? id : NULL; 149 + 150 + blk = qmp_get_blk(device, id, errp); 151 + if (!blk) { 152 + return; 153 + } 154 + 155 + if (!blk_dev_has_removable_media(blk)) { 156 + error_setg(errp, "Device '%s' is not removable", device ?: id); 157 + return; 158 + } 159 + 160 + if (!blk_dev_has_tray(blk)) { 161 + /* Ignore this command on tray-less devices */ 162 + return; 163 + } 164 + 165 + if (!blk_dev_is_tray_open(blk)) { 166 + return; 167 + } 168 + 169 + blk_dev_change_media_cb(blk, true, &local_err); 170 + if (local_err) { 171 + error_propagate(errp, local_err); 172 + return; 173 + } 174 + } 175 + 176 + static void blockdev_remove_medium(bool has_device, const char *device, 177 + bool has_id, const char *id, Error **errp) 178 + { 179 + BlockBackend *blk; 180 + BlockDriverState *bs; 181 + AioContext *aio_context; 182 + bool has_attached_device; 183 + 184 + device = has_device ? device : NULL; 185 + id = has_id ? id : NULL; 186 + 187 + blk = qmp_get_blk(device, id, errp); 188 + if (!blk) { 189 + return; 190 + } 191 + 192 + /* For BBs without a device, we can exchange the BDS tree at will */ 193 + has_attached_device = blk_get_attached_dev(blk); 194 + 195 + if (has_attached_device && !blk_dev_has_removable_media(blk)) { 196 + error_setg(errp, "Device '%s' is not removable", device ?: id); 197 + return; 198 + } 199 + 200 + if (has_attached_device && blk_dev_has_tray(blk) && 201 + !blk_dev_is_tray_open(blk)) 202 + { 203 + error_setg(errp, "Tray of device '%s' is not open", device ?: id); 204 + return; 205 + } 206 + 207 + bs = blk_bs(blk); 208 + if (!bs) { 209 + return; 210 + } 211 + 212 + aio_context = bdrv_get_aio_context(bs); 213 + aio_context_acquire(aio_context); 214 + 215 + if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) { 216 + goto out; 217 + } 218 + 219 + blk_remove_bs(blk); 220 + 221 + if (!blk_dev_has_tray(blk)) { 222 + /* For tray-less devices, blockdev-open-tray is a no-op (or may not be 223 + * called at all); therefore, the medium needs to be ejected here. 224 + * Do it after blk_remove_bs() so blk_is_inserted(blk) returns the @load 225 + * value passed here (i.e. false). */ 226 + blk_dev_change_media_cb(blk, false, &error_abort); 227 + } 228 + 229 + out: 230 + aio_context_release(aio_context); 231 + } 232 + 233 + void qmp_blockdev_remove_medium(const char *id, Error **errp) 234 + { 235 + blockdev_remove_medium(false, NULL, true, id, errp); 236 + } 237 + 238 + static void qmp_blockdev_insert_anon_medium(BlockBackend *blk, 239 + BlockDriverState *bs, Error **errp) 240 + { 241 + Error *local_err = NULL; 242 + bool has_device; 243 + int ret; 244 + 245 + /* For BBs without a device, we can exchange the BDS tree at will */ 246 + has_device = blk_get_attached_dev(blk); 247 + 248 + if (has_device && !blk_dev_has_removable_media(blk)) { 249 + error_setg(errp, "Device is not removable"); 250 + return; 251 + } 252 + 253 + if (has_device && blk_dev_has_tray(blk) && !blk_dev_is_tray_open(blk)) { 254 + error_setg(errp, "Tray of the device is not open"); 255 + return; 256 + } 257 + 258 + if (blk_bs(blk)) { 259 + error_setg(errp, "There already is a medium in the device"); 260 + return; 261 + } 262 + 263 + ret = blk_insert_bs(blk, bs, errp); 264 + if (ret < 0) { 265 + return; 266 + } 267 + 268 + if (!blk_dev_has_tray(blk)) { 269 + /* For tray-less devices, blockdev-close-tray is a no-op (or may not be 270 + * called at all); therefore, the medium needs to be pushed into the 271 + * slot here. 272 + * Do it after blk_insert_bs() so blk_is_inserted(blk) returns the @load 273 + * value passed here (i.e. true). */ 274 + blk_dev_change_media_cb(blk, true, &local_err); 275 + if (local_err) { 276 + error_propagate(errp, local_err); 277 + blk_remove_bs(blk); 278 + return; 279 + } 280 + } 281 + } 282 + 283 + static void blockdev_insert_medium(bool has_device, const char *device, 284 + bool has_id, const char *id, 285 + const char *node_name, Error **errp) 286 + { 287 + BlockBackend *blk; 288 + BlockDriverState *bs; 289 + 290 + blk = qmp_get_blk(has_device ? device : NULL, 291 + has_id ? id : NULL, 292 + errp); 293 + if (!blk) { 294 + return; 295 + } 296 + 297 + bs = bdrv_find_node(node_name); 298 + if (!bs) { 299 + error_setg(errp, "Node '%s' not found", node_name); 300 + return; 301 + } 302 + 303 + if (bdrv_has_blk(bs)) { 304 + error_setg(errp, "Node '%s' is already in use", node_name); 305 + return; 306 + } 307 + 308 + qmp_blockdev_insert_anon_medium(blk, bs, errp); 309 + } 310 + 311 + void qmp_blockdev_insert_medium(const char *id, const char *node_name, 312 + Error **errp) 313 + { 314 + blockdev_insert_medium(false, NULL, true, id, node_name, errp); 315 + } 316 + 317 + void qmp_blockdev_change_medium(bool has_device, const char *device, 318 + bool has_id, const char *id, 319 + const char *filename, 320 + bool has_format, const char *format, 321 + bool has_read_only, 322 + BlockdevChangeReadOnlyMode read_only, 323 + Error **errp) 324 + { 325 + BlockBackend *blk; 326 + BlockDriverState *medium_bs = NULL; 327 + int bdrv_flags; 328 + bool detect_zeroes; 329 + int rc; 330 + QDict *options = NULL; 331 + Error *err = NULL; 332 + 333 + blk = qmp_get_blk(has_device ? device : NULL, 334 + has_id ? id : NULL, 335 + errp); 336 + if (!blk) { 337 + goto fail; 338 + } 339 + 340 + if (blk_bs(blk)) { 341 + blk_update_root_state(blk); 342 + } 343 + 344 + bdrv_flags = blk_get_open_flags_from_root_state(blk); 345 + bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | 346 + BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY); 347 + 348 + if (!has_read_only) { 349 + read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN; 350 + } 351 + 352 + switch (read_only) { 353 + case BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN: 354 + break; 355 + 356 + case BLOCKDEV_CHANGE_READ_ONLY_MODE_READ_ONLY: 357 + bdrv_flags &= ~BDRV_O_RDWR; 358 + break; 359 + 360 + case BLOCKDEV_CHANGE_READ_ONLY_MODE_READ_WRITE: 361 + bdrv_flags |= BDRV_O_RDWR; 362 + break; 363 + 364 + default: 365 + abort(); 366 + } 367 + 368 + options = qdict_new(); 369 + detect_zeroes = blk_get_detect_zeroes_from_root_state(blk); 370 + qdict_put_str(options, "detect-zeroes", detect_zeroes ? "on" : "off"); 371 + 372 + if (has_format) { 373 + qdict_put_str(options, "driver", format); 374 + } 375 + 376 + medium_bs = bdrv_open(filename, NULL, options, bdrv_flags, errp); 377 + if (!medium_bs) { 378 + goto fail; 379 + } 380 + 381 + rc = do_open_tray(has_device ? device : NULL, 382 + has_id ? id : NULL, 383 + false, &err); 384 + if (rc && rc != -ENOSYS) { 385 + error_propagate(errp, err); 386 + goto fail; 387 + } 388 + error_free(err); 389 + err = NULL; 390 + 391 + blockdev_remove_medium(has_device, device, has_id, id, &err); 392 + if (err) { 393 + error_propagate(errp, err); 394 + goto fail; 395 + } 396 + 397 + qmp_blockdev_insert_anon_medium(blk, medium_bs, &err); 398 + if (err) { 399 + error_propagate(errp, err); 400 + goto fail; 401 + } 402 + 403 + qmp_blockdev_close_tray(has_device, device, has_id, id, errp); 404 + 405 + fail: 406 + /* If the medium has been inserted, the device has its own reference, so 407 + * ours must be relinquished; and if it has not been inserted successfully, 408 + * the reference must be relinquished anyway */ 409 + bdrv_unref(medium_bs); 410 + } 411 + 412 + void qmp_eject(bool has_device, const char *device, 413 + bool has_id, const char *id, 414 + bool has_force, bool force, Error **errp) 415 + { 416 + Error *local_err = NULL; 417 + int rc; 418 + 419 + if (!has_force) { 420 + force = false; 421 + } 422 + 423 + rc = do_open_tray(has_device ? device : NULL, 424 + has_id ? id : NULL, 425 + force, &local_err); 426 + if (rc && rc != -ENOSYS) { 427 + error_propagate(errp, local_err); 428 + return; 429 + } 430 + error_free(local_err); 431 + 432 + blockdev_remove_medium(has_device, device, has_id, id, errp); 433 + } 434 + 435 + /* throttling disk I/O limits */ 436 + void qmp_block_set_io_throttle(BlockIOThrottle *arg, Error **errp) 437 + { 438 + ThrottleConfig cfg; 439 + BlockDriverState *bs; 440 + BlockBackend *blk; 441 + AioContext *aio_context; 442 + 443 + blk = qmp_get_blk(arg->has_device ? arg->device : NULL, 444 + arg->has_id ? arg->id : NULL, 445 + errp); 446 + if (!blk) { 447 + return; 448 + } 449 + 450 + aio_context = blk_get_aio_context(blk); 451 + aio_context_acquire(aio_context); 452 + 453 + bs = blk_bs(blk); 454 + if (!bs) { 455 + error_setg(errp, "Device has no medium"); 456 + goto out; 457 + } 458 + 459 + throttle_config_init(&cfg); 460 + cfg.buckets[THROTTLE_BPS_TOTAL].avg = arg->bps; 461 + cfg.buckets[THROTTLE_BPS_READ].avg = arg->bps_rd; 462 + cfg.buckets[THROTTLE_BPS_WRITE].avg = arg->bps_wr; 463 + 464 + cfg.buckets[THROTTLE_OPS_TOTAL].avg = arg->iops; 465 + cfg.buckets[THROTTLE_OPS_READ].avg = arg->iops_rd; 466 + cfg.buckets[THROTTLE_OPS_WRITE].avg = arg->iops_wr; 467 + 468 + if (arg->has_bps_max) { 469 + cfg.buckets[THROTTLE_BPS_TOTAL].max = arg->bps_max; 470 + } 471 + if (arg->has_bps_rd_max) { 472 + cfg.buckets[THROTTLE_BPS_READ].max = arg->bps_rd_max; 473 + } 474 + if (arg->has_bps_wr_max) { 475 + cfg.buckets[THROTTLE_BPS_WRITE].max = arg->bps_wr_max; 476 + } 477 + if (arg->has_iops_max) { 478 + cfg.buckets[THROTTLE_OPS_TOTAL].max = arg->iops_max; 479 + } 480 + if (arg->has_iops_rd_max) { 481 + cfg.buckets[THROTTLE_OPS_READ].max = arg->iops_rd_max; 482 + } 483 + if (arg->has_iops_wr_max) { 484 + cfg.buckets[THROTTLE_OPS_WRITE].max = arg->iops_wr_max; 485 + } 486 + 487 + if (arg->has_bps_max_length) { 488 + cfg.buckets[THROTTLE_BPS_TOTAL].burst_length = arg->bps_max_length; 489 + } 490 + if (arg->has_bps_rd_max_length) { 491 + cfg.buckets[THROTTLE_BPS_READ].burst_length = arg->bps_rd_max_length; 492 + } 493 + if (arg->has_bps_wr_max_length) { 494 + cfg.buckets[THROTTLE_BPS_WRITE].burst_length = arg->bps_wr_max_length; 495 + } 496 + if (arg->has_iops_max_length) { 497 + cfg.buckets[THROTTLE_OPS_TOTAL].burst_length = arg->iops_max_length; 498 + } 499 + if (arg->has_iops_rd_max_length) { 500 + cfg.buckets[THROTTLE_OPS_READ].burst_length = arg->iops_rd_max_length; 501 + } 502 + if (arg->has_iops_wr_max_length) { 503 + cfg.buckets[THROTTLE_OPS_WRITE].burst_length = arg->iops_wr_max_length; 504 + } 505 + 506 + if (arg->has_iops_size) { 507 + cfg.op_size = arg->iops_size; 508 + } 509 + 510 + if (!throttle_is_valid(&cfg, errp)) { 511 + goto out; 512 + } 513 + 514 + if (throttle_enabled(&cfg)) { 515 + /* Enable I/O limits if they're not enabled yet, otherwise 516 + * just update the throttling group. */ 517 + if (!blk_get_public(blk)->throttle_group_member.throttle_state) { 518 + blk_io_limits_enable(blk, 519 + arg->has_group ? arg->group : 520 + arg->has_device ? arg->device : 521 + arg->id); 522 + } else if (arg->has_group) { 523 + blk_io_limits_update_group(blk, arg->group); 524 + } 525 + /* Set the new throttling configuration */ 526 + blk_set_io_limits(blk, &cfg); 527 + } else if (blk_get_public(blk)->throttle_group_member.throttle_state) { 528 + /* If all throttling settings are set to 0, disable I/O limits */ 529 + blk_io_limits_disable(blk); 530 + } 531 + 532 + out: 533 + aio_context_release(aio_context); 534 + } 535 + 536 + void qmp_block_latency_histogram_set( 537 + const char *id, 538 + bool has_boundaries, uint64List *boundaries, 539 + bool has_boundaries_read, uint64List *boundaries_read, 540 + bool has_boundaries_write, uint64List *boundaries_write, 541 + bool has_boundaries_flush, uint64List *boundaries_flush, 542 + Error **errp) 543 + { 544 + BlockBackend *blk = qmp_get_blk(NULL, id, errp); 545 + BlockAcctStats *stats; 546 + int ret; 547 + 548 + if (!blk) { 549 + return; 550 + } 551 + 552 + stats = blk_get_stats(blk); 553 + 554 + if (!has_boundaries && !has_boundaries_read && !has_boundaries_write && 555 + !has_boundaries_flush) 556 + { 557 + block_latency_histograms_clear(stats); 558 + return; 559 + } 560 + 561 + if (has_boundaries || has_boundaries_read) { 562 + ret = block_latency_histogram_set( 563 + stats, BLOCK_ACCT_READ, 564 + has_boundaries_read ? boundaries_read : boundaries); 565 + if (ret) { 566 + error_setg(errp, "Device '%s' set read boundaries fail", id); 567 + return; 568 + } 569 + } 570 + 571 + if (has_boundaries || has_boundaries_write) { 572 + ret = block_latency_histogram_set( 573 + stats, BLOCK_ACCT_WRITE, 574 + has_boundaries_write ? boundaries_write : boundaries); 575 + if (ret) { 576 + error_setg(errp, "Device '%s' set write boundaries fail", id); 577 + return; 578 + } 579 + } 580 + 581 + if (has_boundaries || has_boundaries_flush) { 582 + ret = block_latency_histogram_set( 583 + stats, BLOCK_ACCT_FLUSH, 584 + has_boundaries_flush ? boundaries_flush : boundaries); 585 + if (ret) { 586 + error_setg(errp, "Device '%s' set flush boundaries fail", id); 587 + return; 588 + } 589 + } 590 + }
+1 -1
block/qcow2-cluster.c
··· 1026 1026 void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m) 1027 1027 { 1028 1028 BDRVQcow2State *s = bs->opaque; 1029 - if (!has_data_file(bs)) { 1029 + if (!has_data_file(bs) && !m->keep_old_clusters) { 1030 1030 qcow2_free_clusters(bs, m->alloc_offset, 1031 1031 m->nb_clusters << s->cluster_bits, 1032 1032 QCOW2_DISCARD_NEVER);
+6 -1
block/qcow2.c
··· 1884 1884 static void qcow2_reopen_commit(BDRVReopenState *state) 1885 1885 { 1886 1886 qcow2_update_options_commit(state->bs, state->opaque); 1887 + g_free(state->opaque); 1888 + } 1889 + 1890 + static void qcow2_reopen_commit_post(BDRVReopenState *state) 1891 + { 1887 1892 if (state->flags & BDRV_O_RDWR) { 1888 1893 Error *local_err = NULL; 1889 1894 ··· 1898 1903 bdrv_get_node_name(state->bs)); 1899 1904 } 1900 1905 } 1901 - g_free(state->opaque); 1902 1906 } 1903 1907 1904 1908 static void qcow2_reopen_abort(BDRVReopenState *state) ··· 5534 5538 .bdrv_close = qcow2_close, 5535 5539 .bdrv_reopen_prepare = qcow2_reopen_prepare, 5536 5540 .bdrv_reopen_commit = qcow2_reopen_commit, 5541 + .bdrv_reopen_commit_post = qcow2_reopen_commit_post, 5537 5542 .bdrv_reopen_abort = qcow2_reopen_abort, 5538 5543 .bdrv_join_options = qcow2_join_options, 5539 5544 .bdrv_child_perm = bdrv_format_default_perms,
+31 -13
block/rbd.c
··· 104 104 rbd_image_t image; 105 105 char *image_name; 106 106 char *snap; 107 + char *namespace; 107 108 uint64_t image_size; 108 109 } BDRVRBDState; 109 110 ··· 152 153 const char *start; 153 154 char *p, *buf; 154 155 QList *keypairs = NULL; 155 - char *found_str; 156 + char *found_str, *image_name; 156 157 157 158 if (!strstart(filename, "rbd:", &start)) { 158 159 error_setg(errp, "File name must start with 'rbd:'"); ··· 171 172 qdict_put_str(options, "pool", found_str); 172 173 173 174 if (strchr(p, '@')) { 174 - found_str = qemu_rbd_next_tok(p, '@', &p); 175 - qemu_rbd_unescape(found_str); 176 - qdict_put_str(options, "image", found_str); 175 + image_name = qemu_rbd_next_tok(p, '@', &p); 177 176 178 177 found_str = qemu_rbd_next_tok(p, ':', &p); 179 178 qemu_rbd_unescape(found_str); 180 179 qdict_put_str(options, "snapshot", found_str); 181 180 } else { 182 - found_str = qemu_rbd_next_tok(p, ':', &p); 181 + image_name = qemu_rbd_next_tok(p, ':', &p); 182 + } 183 + /* Check for namespace in the image_name */ 184 + if (strchr(image_name, '/')) { 185 + found_str = qemu_rbd_next_tok(image_name, '/', &image_name); 183 186 qemu_rbd_unescape(found_str); 184 - qdict_put_str(options, "image", found_str); 187 + qdict_put_str(options, "namespace", found_str); 188 + } else { 189 + qdict_put_str(options, "namespace", ""); 185 190 } 191 + qemu_rbd_unescape(image_name); 192 + qdict_put_str(options, "image", image_name); 186 193 if (!p) { 187 194 goto done; 188 195 } ··· 344 351 .help = "Rados pool name", 345 352 }, 346 353 { 354 + .name = "namespace", 355 + .type = QEMU_OPT_STRING, 356 + .help = "Rados namespace name in the pool", 357 + }, 358 + { 347 359 .name = "image", 348 360 .type = QEMU_OPT_STRING, 349 361 .help = "Image name in the pool", ··· 467 479 * schema, but when they come from -drive, they're all QString. 468 480 */ 469 481 loc = rbd_opts->location; 470 - loc->pool = g_strdup(qdict_get_try_str(options, "pool")); 471 - loc->conf = g_strdup(qdict_get_try_str(options, "conf")); 472 - loc->has_conf = !!loc->conf; 473 - loc->user = g_strdup(qdict_get_try_str(options, "user")); 474 - loc->has_user = !!loc->user; 475 - loc->image = g_strdup(qdict_get_try_str(options, "image")); 476 - keypairs = qdict_get_try_str(options, "=keyvalue-pairs"); 482 + loc->pool = g_strdup(qdict_get_try_str(options, "pool")); 483 + loc->conf = g_strdup(qdict_get_try_str(options, "conf")); 484 + loc->has_conf = !!loc->conf; 485 + loc->user = g_strdup(qdict_get_try_str(options, "user")); 486 + loc->has_user = !!loc->user; 487 + loc->q_namespace = g_strdup(qdict_get_try_str(options, "namespace")); 488 + loc->image = g_strdup(qdict_get_try_str(options, "image")); 489 + keypairs = qdict_get_try_str(options, "=keyvalue-pairs"); 477 490 478 491 ret = qemu_rbd_do_create(create_options, keypairs, password_secret, errp); 479 492 if (ret < 0) { ··· 648 661 error_setg_errno(errp, -r, "error opening pool %s", opts->pool); 649 662 goto failed_shutdown; 650 663 } 664 + /* 665 + * Set the namespace after opening the io context on the pool, 666 + * if nspace == NULL or if nspace == "", it is just as we did nothing 667 + */ 668 + rados_ioctx_set_namespace(*io_ctx, opts->q_namespace); 651 669 652 670 return 0; 653 671
+21 -19
blockdev-nbd.c
··· 132 132 nbd_server = NULL; 133 133 } 134 134 135 + void nbd_server_start_options(NbdServerOptions *arg, Error **errp) 136 + { 137 + nbd_server_start(arg->addr, arg->tls_creds, arg->tls_authz, errp); 138 + } 139 + 135 140 void qmp_nbd_server_start(SocketAddressLegacy *addr, 136 141 bool has_tls_creds, const char *tls_creds, 137 142 bool has_tls_authz, const char *tls_authz, ··· 143 148 qapi_free_SocketAddress(addr_flat); 144 149 } 145 150 146 - void qmp_nbd_server_add(const char *device, bool has_name, const char *name, 147 - bool has_description, const char *description, 148 - bool has_writable, bool writable, 149 - bool has_bitmap, const char *bitmap, Error **errp) 151 + void qmp_nbd_server_add(BlockExportNbd *arg, Error **errp) 150 152 { 151 153 BlockDriverState *bs = NULL; 152 154 BlockBackend *on_eject_blk; ··· 159 161 return; 160 162 } 161 163 162 - if (!has_name) { 163 - name = device; 164 + if (!arg->has_name) { 165 + arg->name = arg->device; 164 166 } 165 167 166 - if (strlen(name) > NBD_MAX_STRING_SIZE) { 167 - error_setg(errp, "export name '%s' too long", name); 168 + if (strlen(arg->name) > NBD_MAX_STRING_SIZE) { 169 + error_setg(errp, "export name '%s' too long", arg->name); 168 170 return; 169 171 } 170 172 171 - if (has_description && strlen(description) > NBD_MAX_STRING_SIZE) { 172 - error_setg(errp, "description '%s' too long", description); 173 + if (arg->description && strlen(arg->description) > NBD_MAX_STRING_SIZE) { 174 + error_setg(errp, "description '%s' too long", arg->description); 173 175 return; 174 176 } 175 177 176 - if (nbd_export_find(name)) { 177 - error_setg(errp, "NBD server already has export named '%s'", name); 178 + if (nbd_export_find(arg->name)) { 179 + error_setg(errp, "NBD server already has export named '%s'", arg->name); 178 180 return; 179 181 } 180 182 181 - on_eject_blk = blk_by_name(device); 183 + on_eject_blk = blk_by_name(arg->device); 182 184 183 - bs = bdrv_lookup_bs(device, device, errp); 185 + bs = bdrv_lookup_bs(arg->device, arg->device, errp); 184 186 if (!bs) { 185 187 return; 186 188 } ··· 194 196 goto out; 195 197 } 196 198 197 - if (!has_writable) { 198 - writable = false; 199 + if (!arg->has_writable) { 200 + arg->writable = false; 199 201 } 200 202 if (bdrv_is_read_only(bs)) { 201 - writable = false; 203 + arg->writable = false; 202 204 } 203 205 204 - exp = nbd_export_new(bs, 0, len, name, description, bitmap, 205 - !writable, !writable, 206 + exp = nbd_export_new(bs, 0, len, arg->name, arg->description, arg->bitmap, 207 + !arg->writable, !arg->writable, 206 208 NULL, false, on_eject_blk, errp); 207 209 if (!exp) { 208 210 goto out;
-559
blockdev.c
··· 67 67 static QTAILQ_HEAD(, BlockDriverState) monitor_bdrv_states = 68 68 QTAILQ_HEAD_INITIALIZER(monitor_bdrv_states); 69 69 70 - static int do_open_tray(const char *blk_name, const char *qdev_id, 71 - bool force, Error **errp); 72 - static void blockdev_remove_medium(bool has_device, const char *device, 73 - bool has_id, const char *id, Error **errp); 74 - static void blockdev_insert_medium(bool has_device, const char *device, 75 - bool has_id, const char *id, 76 - const char *node_name, Error **errp); 77 - 78 70 static const char *const if_name[IF_COUNT] = { 79 71 [IF_NONE] = "none", 80 72 [IF_IDE] = "ide", ··· 1045 1037 } 1046 1038 1047 1039 return bs; 1048 - } 1049 - 1050 - static BlockBackend *qmp_get_blk(const char *blk_name, const char *qdev_id, 1051 - Error **errp) 1052 - { 1053 - BlockBackend *blk; 1054 - 1055 - if (!blk_name == !qdev_id) { 1056 - error_setg(errp, "Need exactly one of 'device' and 'id'"); 1057 - return NULL; 1058 - } 1059 - 1060 - if (qdev_id) { 1061 - blk = blk_by_qdev_id(qdev_id, errp); 1062 - } else { 1063 - blk = blk_by_name(blk_name); 1064 - if (blk == NULL) { 1065 - error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 1066 - "Device '%s' not found", blk_name); 1067 - } 1068 - } 1069 - 1070 - return blk; 1071 1040 } 1072 1041 1073 1042 void hmp_commit(Monitor *mon, const QDict *qdict) ··· 2508 2477 job_txn_unref(block_job_txn); 2509 2478 } 2510 2479 2511 - void qmp_eject(bool has_device, const char *device, 2512 - bool has_id, const char *id, 2513 - bool has_force, bool force, Error **errp) 2514 - { 2515 - Error *local_err = NULL; 2516 - int rc; 2517 - 2518 - if (!has_force) { 2519 - force = false; 2520 - } 2521 - 2522 - rc = do_open_tray(has_device ? device : NULL, 2523 - has_id ? id : NULL, 2524 - force, &local_err); 2525 - if (rc && rc != -ENOSYS) { 2526 - error_propagate(errp, local_err); 2527 - return; 2528 - } 2529 - error_free(local_err); 2530 - 2531 - blockdev_remove_medium(has_device, device, has_id, id, errp); 2532 - } 2533 - 2534 2480 void qmp_block_passwd(bool has_device, const char *device, 2535 2481 bool has_node_name, const char *node_name, 2536 2482 const char *password, Error **errp) ··· 2539 2485 "Setting block passwords directly is no longer supported"); 2540 2486 } 2541 2487 2542 - /* 2543 - * Attempt to open the tray of @device. 2544 - * If @force, ignore its tray lock. 2545 - * Else, if the tray is locked, don't open it, but ask the guest to open it. 2546 - * On error, store an error through @errp and return -errno. 2547 - * If @device does not exist, return -ENODEV. 2548 - * If it has no removable media, return -ENOTSUP. 2549 - * If it has no tray, return -ENOSYS. 2550 - * If the guest was asked to open the tray, return -EINPROGRESS. 2551 - * Else, return 0. 2552 - */ 2553 - static int do_open_tray(const char *blk_name, const char *qdev_id, 2554 - bool force, Error **errp) 2555 - { 2556 - BlockBackend *blk; 2557 - const char *device = qdev_id ?: blk_name; 2558 - bool locked; 2559 - 2560 - blk = qmp_get_blk(blk_name, qdev_id, errp); 2561 - if (!blk) { 2562 - return -ENODEV; 2563 - } 2564 - 2565 - if (!blk_dev_has_removable_media(blk)) { 2566 - error_setg(errp, "Device '%s' is not removable", device); 2567 - return -ENOTSUP; 2568 - } 2569 - 2570 - if (!blk_dev_has_tray(blk)) { 2571 - error_setg(errp, "Device '%s' does not have a tray", device); 2572 - return -ENOSYS; 2573 - } 2574 - 2575 - if (blk_dev_is_tray_open(blk)) { 2576 - return 0; 2577 - } 2578 - 2579 - locked = blk_dev_is_medium_locked(blk); 2580 - if (locked) { 2581 - blk_dev_eject_request(blk, force); 2582 - } 2583 - 2584 - if (!locked || force) { 2585 - blk_dev_change_media_cb(blk, false, &error_abort); 2586 - } 2587 - 2588 - if (locked && !force) { 2589 - error_setg(errp, "Device '%s' is locked and force was not specified, " 2590 - "wait for tray to open and try again", device); 2591 - return -EINPROGRESS; 2592 - } 2593 - 2594 - return 0; 2595 - } 2596 - 2597 - void qmp_blockdev_open_tray(bool has_device, const char *device, 2598 - bool has_id, const char *id, 2599 - bool has_force, bool force, 2600 - Error **errp) 2601 - { 2602 - Error *local_err = NULL; 2603 - int rc; 2604 - 2605 - if (!has_force) { 2606 - force = false; 2607 - } 2608 - rc = do_open_tray(has_device ? device : NULL, 2609 - has_id ? id : NULL, 2610 - force, &local_err); 2611 - if (rc && rc != -ENOSYS && rc != -EINPROGRESS) { 2612 - error_propagate(errp, local_err); 2613 - return; 2614 - } 2615 - error_free(local_err); 2616 - } 2617 - 2618 - void qmp_blockdev_close_tray(bool has_device, const char *device, 2619 - bool has_id, const char *id, 2620 - Error **errp) 2621 - { 2622 - BlockBackend *blk; 2623 - Error *local_err = NULL; 2624 - 2625 - device = has_device ? device : NULL; 2626 - id = has_id ? id : NULL; 2627 - 2628 - blk = qmp_get_blk(device, id, errp); 2629 - if (!blk) { 2630 - return; 2631 - } 2632 - 2633 - if (!blk_dev_has_removable_media(blk)) { 2634 - error_setg(errp, "Device '%s' is not removable", device ?: id); 2635 - return; 2636 - } 2637 - 2638 - if (!blk_dev_has_tray(blk)) { 2639 - /* Ignore this command on tray-less devices */ 2640 - return; 2641 - } 2642 - 2643 - if (!blk_dev_is_tray_open(blk)) { 2644 - return; 2645 - } 2646 - 2647 - blk_dev_change_media_cb(blk, true, &local_err); 2648 - if (local_err) { 2649 - error_propagate(errp, local_err); 2650 - return; 2651 - } 2652 - } 2653 - 2654 - static void blockdev_remove_medium(bool has_device, const char *device, 2655 - bool has_id, const char *id, Error **errp) 2656 - { 2657 - BlockBackend *blk; 2658 - BlockDriverState *bs; 2659 - AioContext *aio_context; 2660 - bool has_attached_device; 2661 - 2662 - device = has_device ? device : NULL; 2663 - id = has_id ? id : NULL; 2664 - 2665 - blk = qmp_get_blk(device, id, errp); 2666 - if (!blk) { 2667 - return; 2668 - } 2669 - 2670 - /* For BBs without a device, we can exchange the BDS tree at will */ 2671 - has_attached_device = blk_get_attached_dev(blk); 2672 - 2673 - if (has_attached_device && !blk_dev_has_removable_media(blk)) { 2674 - error_setg(errp, "Device '%s' is not removable", device ?: id); 2675 - return; 2676 - } 2677 - 2678 - if (has_attached_device && blk_dev_has_tray(blk) && 2679 - !blk_dev_is_tray_open(blk)) 2680 - { 2681 - error_setg(errp, "Tray of device '%s' is not open", device ?: id); 2682 - return; 2683 - } 2684 - 2685 - bs = blk_bs(blk); 2686 - if (!bs) { 2687 - return; 2688 - } 2689 - 2690 - aio_context = bdrv_get_aio_context(bs); 2691 - aio_context_acquire(aio_context); 2692 - 2693 - if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) { 2694 - goto out; 2695 - } 2696 - 2697 - blk_remove_bs(blk); 2698 - 2699 - if (!blk_dev_has_tray(blk)) { 2700 - /* For tray-less devices, blockdev-open-tray is a no-op (or may not be 2701 - * called at all); therefore, the medium needs to be ejected here. 2702 - * Do it after blk_remove_bs() so blk_is_inserted(blk) returns the @load 2703 - * value passed here (i.e. false). */ 2704 - blk_dev_change_media_cb(blk, false, &error_abort); 2705 - } 2706 - 2707 - out: 2708 - aio_context_release(aio_context); 2709 - } 2710 - 2711 - void qmp_blockdev_remove_medium(const char *id, Error **errp) 2712 - { 2713 - blockdev_remove_medium(false, NULL, true, id, errp); 2714 - } 2715 - 2716 - static void qmp_blockdev_insert_anon_medium(BlockBackend *blk, 2717 - BlockDriverState *bs, Error **errp) 2718 - { 2719 - Error *local_err = NULL; 2720 - bool has_device; 2721 - int ret; 2722 - 2723 - /* For BBs without a device, we can exchange the BDS tree at will */ 2724 - has_device = blk_get_attached_dev(blk); 2725 - 2726 - if (has_device && !blk_dev_has_removable_media(blk)) { 2727 - error_setg(errp, "Device is not removable"); 2728 - return; 2729 - } 2730 - 2731 - if (has_device && blk_dev_has_tray(blk) && !blk_dev_is_tray_open(blk)) { 2732 - error_setg(errp, "Tray of the device is not open"); 2733 - return; 2734 - } 2735 - 2736 - if (blk_bs(blk)) { 2737 - error_setg(errp, "There already is a medium in the device"); 2738 - return; 2739 - } 2740 - 2741 - ret = blk_insert_bs(blk, bs, errp); 2742 - if (ret < 0) { 2743 - return; 2744 - } 2745 - 2746 - if (!blk_dev_has_tray(blk)) { 2747 - /* For tray-less devices, blockdev-close-tray is a no-op (or may not be 2748 - * called at all); therefore, the medium needs to be pushed into the 2749 - * slot here. 2750 - * Do it after blk_insert_bs() so blk_is_inserted(blk) returns the @load 2751 - * value passed here (i.e. true). */ 2752 - blk_dev_change_media_cb(blk, true, &local_err); 2753 - if (local_err) { 2754 - error_propagate(errp, local_err); 2755 - blk_remove_bs(blk); 2756 - return; 2757 - } 2758 - } 2759 - } 2760 - 2761 - static void blockdev_insert_medium(bool has_device, const char *device, 2762 - bool has_id, const char *id, 2763 - const char *node_name, Error **errp) 2764 - { 2765 - BlockBackend *blk; 2766 - BlockDriverState *bs; 2767 - 2768 - blk = qmp_get_blk(has_device ? device : NULL, 2769 - has_id ? id : NULL, 2770 - errp); 2771 - if (!blk) { 2772 - return; 2773 - } 2774 - 2775 - bs = bdrv_find_node(node_name); 2776 - if (!bs) { 2777 - error_setg(errp, "Node '%s' not found", node_name); 2778 - return; 2779 - } 2780 - 2781 - if (bdrv_has_blk(bs)) { 2782 - error_setg(errp, "Node '%s' is already in use", node_name); 2783 - return; 2784 - } 2785 - 2786 - qmp_blockdev_insert_anon_medium(blk, bs, errp); 2787 - } 2788 - 2789 - void qmp_blockdev_insert_medium(const char *id, const char *node_name, 2790 - Error **errp) 2791 - { 2792 - blockdev_insert_medium(false, NULL, true, id, node_name, errp); 2793 - } 2794 - 2795 - void qmp_blockdev_change_medium(bool has_device, const char *device, 2796 - bool has_id, const char *id, 2797 - const char *filename, 2798 - bool has_format, const char *format, 2799 - bool has_read_only, 2800 - BlockdevChangeReadOnlyMode read_only, 2801 - Error **errp) 2802 - { 2803 - BlockBackend *blk; 2804 - BlockDriverState *medium_bs = NULL; 2805 - int bdrv_flags; 2806 - bool detect_zeroes; 2807 - int rc; 2808 - QDict *options = NULL; 2809 - Error *err = NULL; 2810 - 2811 - blk = qmp_get_blk(has_device ? device : NULL, 2812 - has_id ? id : NULL, 2813 - errp); 2814 - if (!blk) { 2815 - goto fail; 2816 - } 2817 - 2818 - if (blk_bs(blk)) { 2819 - blk_update_root_state(blk); 2820 - } 2821 - 2822 - bdrv_flags = blk_get_open_flags_from_root_state(blk); 2823 - bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | 2824 - BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY); 2825 - 2826 - if (!has_read_only) { 2827 - read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN; 2828 - } 2829 - 2830 - switch (read_only) { 2831 - case BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN: 2832 - break; 2833 - 2834 - case BLOCKDEV_CHANGE_READ_ONLY_MODE_READ_ONLY: 2835 - bdrv_flags &= ~BDRV_O_RDWR; 2836 - break; 2837 - 2838 - case BLOCKDEV_CHANGE_READ_ONLY_MODE_READ_WRITE: 2839 - bdrv_flags |= BDRV_O_RDWR; 2840 - break; 2841 - 2842 - default: 2843 - abort(); 2844 - } 2845 - 2846 - options = qdict_new(); 2847 - detect_zeroes = blk_get_detect_zeroes_from_root_state(blk); 2848 - qdict_put_str(options, "detect-zeroes", detect_zeroes ? "on" : "off"); 2849 - 2850 - if (has_format) { 2851 - qdict_put_str(options, "driver", format); 2852 - } 2853 - 2854 - medium_bs = bdrv_open(filename, NULL, options, bdrv_flags, errp); 2855 - if (!medium_bs) { 2856 - goto fail; 2857 - } 2858 - 2859 - rc = do_open_tray(has_device ? device : NULL, 2860 - has_id ? id : NULL, 2861 - false, &err); 2862 - if (rc && rc != -ENOSYS) { 2863 - error_propagate(errp, err); 2864 - goto fail; 2865 - } 2866 - error_free(err); 2867 - err = NULL; 2868 - 2869 - blockdev_remove_medium(has_device, device, has_id, id, &err); 2870 - if (err) { 2871 - error_propagate(errp, err); 2872 - goto fail; 2873 - } 2874 - 2875 - qmp_blockdev_insert_anon_medium(blk, medium_bs, &err); 2876 - if (err) { 2877 - error_propagate(errp, err); 2878 - goto fail; 2879 - } 2880 - 2881 - qmp_blockdev_close_tray(has_device, device, has_id, id, errp); 2882 - 2883 - fail: 2884 - /* If the medium has been inserted, the device has its own reference, so 2885 - * ours must be relinquished; and if it has not been inserted successfully, 2886 - * the reference must be relinquished anyway */ 2887 - bdrv_unref(medium_bs); 2888 - } 2889 - 2890 - /* throttling disk I/O limits */ 2891 - void qmp_block_set_io_throttle(BlockIOThrottle *arg, Error **errp) 2892 - { 2893 - ThrottleConfig cfg; 2894 - BlockDriverState *bs; 2895 - BlockBackend *blk; 2896 - AioContext *aio_context; 2897 - 2898 - blk = qmp_get_blk(arg->has_device ? arg->device : NULL, 2899 - arg->has_id ? arg->id : NULL, 2900 - errp); 2901 - if (!blk) { 2902 - return; 2903 - } 2904 - 2905 - aio_context = blk_get_aio_context(blk); 2906 - aio_context_acquire(aio_context); 2907 - 2908 - bs = blk_bs(blk); 2909 - if (!bs) { 2910 - error_setg(errp, "Device has no medium"); 2911 - goto out; 2912 - } 2913 - 2914 - throttle_config_init(&cfg); 2915 - cfg.buckets[THROTTLE_BPS_TOTAL].avg = arg->bps; 2916 - cfg.buckets[THROTTLE_BPS_READ].avg = arg->bps_rd; 2917 - cfg.buckets[THROTTLE_BPS_WRITE].avg = arg->bps_wr; 2918 - 2919 - cfg.buckets[THROTTLE_OPS_TOTAL].avg = arg->iops; 2920 - cfg.buckets[THROTTLE_OPS_READ].avg = arg->iops_rd; 2921 - cfg.buckets[THROTTLE_OPS_WRITE].avg = arg->iops_wr; 2922 - 2923 - if (arg->has_bps_max) { 2924 - cfg.buckets[THROTTLE_BPS_TOTAL].max = arg->bps_max; 2925 - } 2926 - if (arg->has_bps_rd_max) { 2927 - cfg.buckets[THROTTLE_BPS_READ].max = arg->bps_rd_max; 2928 - } 2929 - if (arg->has_bps_wr_max) { 2930 - cfg.buckets[THROTTLE_BPS_WRITE].max = arg->bps_wr_max; 2931 - } 2932 - if (arg->has_iops_max) { 2933 - cfg.buckets[THROTTLE_OPS_TOTAL].max = arg->iops_max; 2934 - } 2935 - if (arg->has_iops_rd_max) { 2936 - cfg.buckets[THROTTLE_OPS_READ].max = arg->iops_rd_max; 2937 - } 2938 - if (arg->has_iops_wr_max) { 2939 - cfg.buckets[THROTTLE_OPS_WRITE].max = arg->iops_wr_max; 2940 - } 2941 - 2942 - if (arg->has_bps_max_length) { 2943 - cfg.buckets[THROTTLE_BPS_TOTAL].burst_length = arg->bps_max_length; 2944 - } 2945 - if (arg->has_bps_rd_max_length) { 2946 - cfg.buckets[THROTTLE_BPS_READ].burst_length = arg->bps_rd_max_length; 2947 - } 2948 - if (arg->has_bps_wr_max_length) { 2949 - cfg.buckets[THROTTLE_BPS_WRITE].burst_length = arg->bps_wr_max_length; 2950 - } 2951 - if (arg->has_iops_max_length) { 2952 - cfg.buckets[THROTTLE_OPS_TOTAL].burst_length = arg->iops_max_length; 2953 - } 2954 - if (arg->has_iops_rd_max_length) { 2955 - cfg.buckets[THROTTLE_OPS_READ].burst_length = arg->iops_rd_max_length; 2956 - } 2957 - if (arg->has_iops_wr_max_length) { 2958 - cfg.buckets[THROTTLE_OPS_WRITE].burst_length = arg->iops_wr_max_length; 2959 - } 2960 - 2961 - if (arg->has_iops_size) { 2962 - cfg.op_size = arg->iops_size; 2963 - } 2964 - 2965 - if (!throttle_is_valid(&cfg, errp)) { 2966 - goto out; 2967 - } 2968 - 2969 - if (throttle_enabled(&cfg)) { 2970 - /* Enable I/O limits if they're not enabled yet, otherwise 2971 - * just update the throttling group. */ 2972 - if (!blk_get_public(blk)->throttle_group_member.throttle_state) { 2973 - blk_io_limits_enable(blk, 2974 - arg->has_group ? arg->group : 2975 - arg->has_device ? arg->device : 2976 - arg->id); 2977 - } else if (arg->has_group) { 2978 - blk_io_limits_update_group(blk, arg->group); 2979 - } 2980 - /* Set the new throttling configuration */ 2981 - blk_set_io_limits(blk, &cfg); 2982 - } else if (blk_get_public(blk)->throttle_group_member.throttle_state) { 2983 - /* If all throttling settings are set to 0, disable I/O limits */ 2984 - blk_io_limits_disable(blk); 2985 - } 2986 - 2987 - out: 2988 - aio_context_release(aio_context); 2989 - } 2990 - 2991 2488 void qmp_block_dirty_bitmap_add(const char *node, const char *name, 2992 2489 bool has_granularity, uint32_t granularity, 2993 2490 bool has_persistent, bool persistent, ··· 4593 4090 bdrv_try_set_aio_context(bs, new_context, errp); 4594 4091 4595 4092 aio_context_release(old_context); 4596 - } 4597 - 4598 - void qmp_block_latency_histogram_set( 4599 - const char *id, 4600 - bool has_boundaries, uint64List *boundaries, 4601 - bool has_boundaries_read, uint64List *boundaries_read, 4602 - bool has_boundaries_write, uint64List *boundaries_write, 4603 - bool has_boundaries_flush, uint64List *boundaries_flush, 4604 - Error **errp) 4605 - { 4606 - BlockBackend *blk = qmp_get_blk(NULL, id, errp); 4607 - BlockAcctStats *stats; 4608 - int ret; 4609 - 4610 - if (!blk) { 4611 - return; 4612 - } 4613 - 4614 - stats = blk_get_stats(blk); 4615 - 4616 - if (!has_boundaries && !has_boundaries_read && !has_boundaries_write && 4617 - !has_boundaries_flush) 4618 - { 4619 - block_latency_histograms_clear(stats); 4620 - return; 4621 - } 4622 - 4623 - if (has_boundaries || has_boundaries_read) { 4624 - ret = block_latency_histogram_set( 4625 - stats, BLOCK_ACCT_READ, 4626 - has_boundaries_read ? boundaries_read : boundaries); 4627 - if (ret) { 4628 - error_setg(errp, "Device '%s' set read boundaries fail", id); 4629 - return; 4630 - } 4631 - } 4632 - 4633 - if (has_boundaries || has_boundaries_write) { 4634 - ret = block_latency_histogram_set( 4635 - stats, BLOCK_ACCT_WRITE, 4636 - has_boundaries_write ? boundaries_write : boundaries); 4637 - if (ret) { 4638 - error_setg(errp, "Device '%s' set write boundaries fail", id); 4639 - return; 4640 - } 4641 - } 4642 - 4643 - if (has_boundaries || has_boundaries_flush) { 4644 - ret = block_latency_histogram_set( 4645 - stats, BLOCK_ACCT_FLUSH, 4646 - has_boundaries_flush ? boundaries_flush : boundaries); 4647 - if (ret) { 4648 - error_setg(errp, "Device '%s' set flush boundaries fail", id); 4649 - return; 4650 - } 4651 - } 4652 4093 } 4653 4094 4654 4095 QemuOptsList qemu_common_drive_opts = {
+7 -1
chardev/char.c
··· 737 737 738 738 if (qemu_opt_get_bool(opts, "mux", 0)) { 739 739 assert(permit_mux_mon); 740 - monitor_init_hmp(chr, true); 740 + monitor_init_hmp(chr, true, &err); 741 + if (err) { 742 + error_report_err(err); 743 + object_unparent(OBJECT(chr)); 744 + chr = NULL; 745 + goto out; 746 + } 741 747 } 742 748 743 749 out:
+1 -1
configure
··· 6316 6316 if test "$want_tools" = "yes" ; then 6317 6317 tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) qemu-edid\$(EXESUF) $tools" 6318 6318 if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then 6319 - tools="qemu-nbd\$(EXESUF) $tools" 6319 + tools="qemu-nbd\$(EXESUF) qemu-storage-daemon\$(EXESUF) $tools" 6320 6320 fi 6321 6321 if [ "$ivshmem" = "yes" ]; then 6322 6322 tools="ivshmem-client\$(EXESUF) ivshmem-server\$(EXESUF) $tools"
+5
docs/system/deprecated.rst
··· 190 190 191 191 Use ``migrate-set-parameters`` and ``query-migrate-parameters`` instead. 192 192 193 + ``object-add`` option ``props`` (since 5.0) 194 + ''''''''''''''''''''''''''''''''''''''''''' 195 + 196 + Specify the properties for the object as top-level arguments instead. 197 + 193 198 ``query-block`` result field ``dirty-bitmaps[i].status`` (since 4.0) 194 199 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 195 200
+1 -1
gdbstub.c
··· 3367 3367 /* Initialize a monitor terminal for gdb */ 3368 3368 mon_chr = qemu_chardev_new(NULL, TYPE_CHARDEV_GDB, 3369 3369 NULL, NULL, &error_abort); 3370 - monitor_init_hmp(mon_chr, false); 3370 + monitor_init_hmp(mon_chr, false, &error_abort); 3371 3371 } else { 3372 3372 qemu_chr_fe_deinit(&s->chr, true); 3373 3373 mon_chr = s->mon_chr;
+10 -1
hw/block/xen-block.c
··· 18 18 #include "qapi/visitor.h" 19 19 #include "qapi/qmp/qdict.h" 20 20 #include "qapi/qmp/qstring.h" 21 + #include "qom/object_interfaces.h" 21 22 #include "hw/xen/xen_common.h" 22 23 #include "hw/block/xen_blkif.h" 23 24 #include "hw/qdev-properties.h" ··· 858 859 { 859 860 XenBlockIOThread *iothread = g_new(XenBlockIOThread, 1); 860 861 Error *local_err = NULL; 862 + QDict *opts; 863 + QObject *ret_data; 861 864 862 865 iothread->id = g_strdup(id); 863 866 864 - qmp_object_add(TYPE_IOTHREAD, id, false, NULL, &local_err); 867 + opts = qdict_new(); 868 + qdict_put_str(opts, "qom-type", TYPE_IOTHREAD); 869 + qdict_put_str(opts, "id", id); 870 + qmp_object_add(opts, &ret_data, &local_err); 871 + qobject_unref(opts); 872 + qobject_unref(ret_data); 873 + 865 874 if (local_err) { 866 875 error_propagate(errp, local_err); 867 876
+1
include/block/block_int.h
··· 122 122 int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state, 123 123 BlockReopenQueue *queue, Error **errp); 124 124 void (*bdrv_reopen_commit)(BDRVReopenState *reopen_state); 125 + void (*bdrv_reopen_commit_post)(BDRVReopenState *reopen_state); 125 126 void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state); 126 127 void (*bdrv_join_options)(QDict *options, QDict *old_options); 127 128
+1
include/block/nbd.h
··· 353 353 354 354 void nbd_server_start(SocketAddress *addr, const char *tls_creds, 355 355 const char *tls_authz, Error **errp); 356 + void nbd_server_start_options(NbdServerOptions *arg, Error **errp); 356 357 357 358 /* nbd_read 358 359 * Reads @size bytes from @ioc. Returns 0 on success.
+4 -2
include/monitor/monitor.h
··· 7 7 8 8 extern __thread Monitor *cur_mon; 9 9 typedef struct MonitorHMP MonitorHMP; 10 + typedef struct MonitorOptions MonitorOptions; 10 11 11 12 #define QMP_REQ_QUEUE_LEN_MAX 8 12 13 ··· 16 17 17 18 void monitor_init_globals(void); 18 19 void monitor_init_globals_core(void); 19 - void monitor_init_qmp(Chardev *chr, bool pretty); 20 - void monitor_init_hmp(Chardev *chr, bool use_readline); 20 + void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp); 21 + void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp); 22 + int monitor_init(MonitorOptions *opts, bool allow_hmp, Error **errp); 21 23 int monitor_init_opts(QemuOpts *opts, Error **errp); 22 24 void monitor_cleanup(void); 23 25
+7
include/qom/object_interfaces.h
··· 162 162 */ 163 163 void user_creatable_cleanup(void); 164 164 165 + /** 166 + * qmp_object_add: 167 + * 168 + * QMP command handler for object-add. See the QAPI schema for documentation. 169 + */ 170 + void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp); 171 + 165 172 #endif
+2
include/sysemu/arch_init.h
··· 24 24 QEMU_ARCH_NIOS2 = (1 << 17), 25 25 QEMU_ARCH_HPPA = (1 << 18), 26 26 QEMU_ARCH_RISCV = (1 << 19), 27 + 28 + QEMU_ARCH_NONE = (1 << 31), 27 29 }; 28 30 29 31 extern const uint32_t arch_type;
+2
monitor/Makefile.objs
··· 2 2 common-obj-y += monitor.o qmp.o hmp.o 3 3 common-obj-y += qmp-cmds.o qmp-cmds-control.o 4 4 common-obj-y += hmp-cmds.o 5 + 6 + storage-daemon-obj-y += monitor.o qmp.o qmp-cmds-control.o
+17 -4
monitor/hmp-cmds.c
··· 2341 2341 Error *local_err = NULL; 2342 2342 BlockInfoList *block_list, *info; 2343 2343 SocketAddress *addr; 2344 + BlockExportNbd export; 2344 2345 2345 2346 if (writable && !all) { 2346 2347 error_setg(&local_err, "-w only valid together with -a"); ··· 2373 2374 continue; 2374 2375 } 2375 2376 2376 - qmp_nbd_server_add(info->value->device, false, NULL, false, NULL, 2377 - true, writable, false, NULL, &local_err); 2377 + export = (BlockExportNbd) { 2378 + .device = info->value->device, 2379 + .has_writable = true, 2380 + .writable = writable, 2381 + }; 2382 + 2383 + qmp_nbd_server_add(&export, &local_err); 2378 2384 2379 2385 if (local_err != NULL) { 2380 2386 qmp_nbd_server_stop(NULL); ··· 2395 2401 bool writable = qdict_get_try_bool(qdict, "writable", false); 2396 2402 Error *local_err = NULL; 2397 2403 2398 - qmp_nbd_server_add(device, !!name, name, false, NULL, true, writable, 2399 - false, NULL, &local_err); 2404 + BlockExportNbd export = { 2405 + .device = (char *) device, 2406 + .has_name = !!name, 2407 + .name = (char *) name, 2408 + .has_writable = true, 2409 + .writable = writable, 2410 + }; 2411 + 2412 + qmp_nbd_server_add(&export, &local_err); 2400 2413 hmp_handle_error(mon, local_err); 2401 2414 } 2402 2415
+6 -2
monitor/hmp.c
··· 1399 1399 monitor_flush(&mon->common); 1400 1400 } 1401 1401 1402 - void monitor_init_hmp(Chardev *chr, bool use_readline) 1402 + void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp) 1403 1403 { 1404 1404 MonitorHMP *mon = g_new0(MonitorHMP, 1); 1405 1405 1406 + if (!qemu_chr_fe_init(&mon->common.chr, chr, errp)) { 1407 + g_free(mon); 1408 + return; 1409 + } 1410 + 1406 1411 monitor_data_init(&mon->common, false, false, false); 1407 - qemu_chr_fe_init(&mon->common.chr, chr, &error_abort); 1408 1412 1409 1413 mon->use_readline = use_readline; 1410 1414 if (mon->use_readline) {
+2
monitor/misc.c
··· 248 248 QCO_NO_OPTIONS); 249 249 qmp_register_command(&qmp_commands, "netdev_add", qmp_netdev_add, 250 250 QCO_NO_OPTIONS); 251 + qmp_register_command(&qmp_commands, "object-add", qmp_object_add, 252 + QCO_NO_OPTIONS); 251 253 252 254 QTAILQ_INIT(&qmp_cap_negotiation_commands); 253 255 qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
+52 -32
monitor/monitor.c
··· 25 25 #include "qemu/osdep.h" 26 26 #include "monitor-internal.h" 27 27 #include "qapi/error.h" 28 + #include "qapi/opts-visitor.h" 28 29 #include "qapi/qapi-emit-events.h" 30 + #include "qapi/qapi-visit-control.h" 29 31 #include "qapi/qmp/qdict.h" 30 32 #include "qapi/qmp/qstring.h" 31 33 #include "qemu/error-report.h" ··· 609 611 NULL); 610 612 } 611 613 612 - int monitor_init_opts(QemuOpts *opts, Error **errp) 614 + int monitor_init(MonitorOptions *opts, bool allow_hmp, Error **errp) 613 615 { 614 616 Chardev *chr; 615 - bool qmp; 616 - bool pretty = false; 617 - const char *chardev; 618 - const char *mode; 617 + Error *local_err = NULL; 619 618 620 - mode = qemu_opt_get(opts, "mode"); 621 - if (mode == NULL) { 622 - mode = "readline"; 623 - } 624 - if (strcmp(mode, "readline") == 0) { 625 - qmp = false; 626 - } else if (strcmp(mode, "control") == 0) { 627 - qmp = true; 628 - } else { 629 - error_setg(errp, "unknown monitor mode \"%s\"", mode); 619 + chr = qemu_chr_find(opts->chardev); 620 + if (chr == NULL) { 621 + error_setg(errp, "chardev \"%s\" not found", opts->chardev); 630 622 return -1; 631 623 } 632 624 633 - if (!qmp && qemu_opt_get(opts, "pretty")) { 634 - warn_report("'pretty' is deprecated for HMP monitors, it has no effect " 635 - "and will be removed in future versions"); 636 - } 637 - if (qemu_opt_get_bool(opts, "pretty", 0)) { 638 - pretty = true; 625 + if (!opts->has_mode) { 626 + opts->mode = allow_hmp ? MONITOR_MODE_READLINE : MONITOR_MODE_CONTROL; 639 627 } 640 628 641 - chardev = qemu_opt_get(opts, "chardev"); 642 - if (!chardev) { 643 - error_report("chardev is required"); 644 - exit(1); 629 + switch (opts->mode) { 630 + case MONITOR_MODE_CONTROL: 631 + monitor_init_qmp(chr, opts->pretty, &local_err); 632 + break; 633 + case MONITOR_MODE_READLINE: 634 + if (!allow_hmp) { 635 + error_setg(errp, "Only QMP is supported"); 636 + return -1; 637 + } 638 + if (opts->pretty) { 639 + warn_report("'pretty' is deprecated for HMP monitors, it has no " 640 + "effect and will be removed in future versions"); 641 + } 642 + monitor_init_hmp(chr, true, &local_err); 643 + break; 644 + default: 645 + g_assert_not_reached(); 645 646 } 646 - chr = qemu_chr_find(chardev); 647 - if (chr == NULL) { 648 - error_setg(errp, "chardev \"%s\" not found", chardev); 647 + 648 + if (local_err) { 649 + error_propagate(errp, local_err); 649 650 return -1; 650 651 } 652 + return 0; 653 + } 651 654 652 - if (qmp) { 653 - monitor_init_qmp(chr, pretty); 654 - } else { 655 - monitor_init_hmp(chr, true); 655 + int monitor_init_opts(QemuOpts *opts, Error **errp) 656 + { 657 + Visitor *v; 658 + MonitorOptions *options; 659 + Error *local_err = NULL; 660 + 661 + v = opts_visitor_new(opts); 662 + visit_type_MonitorOptions(v, NULL, &options, &local_err); 663 + visit_free(v); 664 + 665 + if (local_err) { 666 + goto out; 667 + } 668 + 669 + monitor_init(options, true, &local_err); 670 + qapi_free_MonitorOptions(options); 671 + 672 + out: 673 + if (local_err) { 674 + error_propagate(errp, local_err); 675 + return -1; 656 676 } 657 677 return 0; 658 678 }
+1 -1
monitor/qmp-cmds.c
··· 30 30 #include "sysemu/blockdev.h" 31 31 #include "sysemu/block-backend.h" 32 32 #include "qapi/error.h" 33 - #include "qapi/qapi-commands-block-core.h" 33 + #include "qapi/qapi-commands-block.h" 34 34 #include "qapi/qapi-commands-control.h" 35 35 #include "qapi/qapi-commands-machine.h" 36 36 #include "qapi/qapi-commands-misc.h"
+7 -4
monitor/qmp.c
··· 395 395 monitor_list_append(&mon->common); 396 396 } 397 397 398 - void monitor_init_qmp(Chardev *chr, bool pretty) 398 + void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp) 399 399 { 400 400 MonitorQMP *mon = g_new0(MonitorQMP, 1); 401 + 402 + if (!qemu_chr_fe_init(&mon->common.chr, chr, errp)) { 403 + g_free(mon); 404 + return; 405 + } 406 + qemu_chr_fe_set_echo(&mon->common.chr, true); 401 407 402 408 /* Note: we run QMP monitor in I/O thread when @chr supports that */ 403 409 monitor_data_init(&mon->common, true, false, ··· 407 413 408 414 qemu_mutex_init(&mon->qmp_queue_lock); 409 415 mon->qmp_requests = g_queue_new(); 410 - 411 - qemu_chr_fe_init(&mon->common.chr, chr, &error_abort); 412 - qemu_chr_fe_set_echo(&mon->common.chr, true); 413 416 414 417 json_message_parser_init(&mon->parser, handle_qmp_command, mon, NULL); 415 418 if (mon->common.use_io_thread) {
+6 -1
qapi/Makefile.objs
··· 7 7 8 8 QAPI_COMMON_MODULES = audio authz block-core block char common control crypto 9 9 QAPI_COMMON_MODULES += dump error introspect job machine migration misc 10 - QAPI_COMMON_MODULES += net qdev qom rdma rocker run-state sockets tpm 10 + QAPI_COMMON_MODULES += net pragma qdev qom rdma rocker run-state sockets tpm 11 11 QAPI_COMMON_MODULES += trace transaction ui 12 12 QAPI_TARGET_MODULES = machine-target misc-target 13 13 QAPI_MODULES = $(QAPI_COMMON_MODULES) $(QAPI_TARGET_MODULES) ··· 31 31 obj-y += $(QAPI_TARGET_MODULES:%=qapi-commands-%.o) 32 32 obj-y += qapi-commands.o 33 33 obj-y += qapi-init-commands.o 34 + 35 + QAPI_MODULES_STORAGE_DAEMON = block-core char common control crypto 36 + QAPI_MODULES_STORAGE_DAEMON += introspect job qom sockets pragma transaction 37 + 38 + storage-daemon-obj-y += $(QAPI_MODULES_STORAGE_DAEMON:%=qapi-commands-%.o)
+347 -386
qapi/block-core.json
··· 564 564 'data': {'boundaries': ['uint64'], 'bins': ['uint64'] } } 565 565 566 566 ## 567 - # @block-latency-histogram-set: 568 - # 569 - # Manage read, write and flush latency histograms for the device. 570 - # 571 - # If only @id parameter is specified, remove all present latency histograms 572 - # for the device. Otherwise, add/reset some of (or all) latency histograms. 573 - # 574 - # @id: The name or QOM path of the guest device. 575 - # 576 - # @boundaries: list of interval boundary values (see description in 577 - # BlockLatencyHistogramInfo definition). If specified, all 578 - # latency histograms are removed, and empty ones created for all 579 - # io types with intervals corresponding to @boundaries (except for 580 - # io types, for which specific boundaries are set through the 581 - # following parameters). 582 - # 583 - # @boundaries-read: list of interval boundary values for read latency 584 - # histogram. If specified, old read latency histogram is 585 - # removed, and empty one created with intervals 586 - # corresponding to @boundaries-read. The parameter has higher 587 - # priority then @boundaries. 588 - # 589 - # @boundaries-write: list of interval boundary values for write latency 590 - # histogram. 591 - # 592 - # @boundaries-flush: list of interval boundary values for flush latency 593 - # histogram. 594 - # 595 - # Returns: error if device is not found or any boundary arrays are invalid. 596 - # 597 - # Since: 4.0 598 - # 599 - # Example: set new histograms for all io types with intervals 600 - # [0, 10), [10, 50), [50, 100), [100, +inf): 601 - # 602 - # -> { "execute": "block-latency-histogram-set", 603 - # "arguments": { "id": "drive0", 604 - # "boundaries": [10, 50, 100] } } 605 - # <- { "return": {} } 606 - # 607 - # Example: set new histogram only for write, other histograms will remain 608 - # not changed (or not created): 609 - # 610 - # -> { "execute": "block-latency-histogram-set", 611 - # "arguments": { "id": "drive0", 612 - # "boundaries-write": [10, 50, 100] } } 613 - # <- { "return": {} } 614 - # 615 - # Example: set new histograms with the following intervals: 616 - # read, flush: [0, 10), [10, 50), [50, 100), [100, +inf) 617 - # write: [0, 1000), [1000, 5000), [5000, +inf) 618 - # 619 - # -> { "execute": "block-latency-histogram-set", 620 - # "arguments": { "id": "drive0", 621 - # "boundaries": [10, 50, 100], 622 - # "boundaries-write": [1000, 5000] } } 623 - # <- { "return": {} } 624 - # 625 - # Example: remove all latency histograms: 626 - # 627 - # -> { "execute": "block-latency-histogram-set", 628 - # "arguments": { "id": "drive0" } } 629 - # <- { "return": {} } 630 - ## 631 - { 'command': 'block-latency-histogram-set', 632 - 'data': {'id': 'str', 633 - '*boundaries': ['uint64'], 634 - '*boundaries-read': ['uint64'], 635 - '*boundaries-write': ['uint64'], 636 - '*boundaries-flush': ['uint64'] } } 637 - 638 - ## 639 567 # @BlockInfo: 640 568 # 641 569 # Block device information. This structure describes a virtual device and ··· 2357 2285 '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } } 2358 2286 2359 2287 ## 2360 - # @block_set_io_throttle: 2361 - # 2362 - # Change I/O throttle limits for a block drive. 2363 - # 2364 - # Since QEMU 2.4, each device with I/O limits is member of a throttle 2365 - # group. 2366 - # 2367 - # If two or more devices are members of the same group, the limits 2368 - # will apply to the combined I/O of the whole group in a round-robin 2369 - # fashion. Therefore, setting new I/O limits to a device will affect 2370 - # the whole group. 2371 - # 2372 - # The name of the group can be specified using the 'group' parameter. 2373 - # If the parameter is unset, it is assumed to be the current group of 2374 - # that device. If it's not in any group yet, the name of the device 2375 - # will be used as the name for its group. 2376 - # 2377 - # The 'group' parameter can also be used to move a device to a 2378 - # different group. In this case the limits specified in the parameters 2379 - # will be applied to the new group only. 2380 - # 2381 - # I/O limits can be disabled by setting all of them to 0. In this case 2382 - # the device will be removed from its group and the rest of its 2383 - # members will not be affected. The 'group' parameter is ignored. 2384 - # 2385 - # Returns: - Nothing on success 2386 - # - If @device is not a valid block device, DeviceNotFound 2387 - # 2388 - # Since: 1.1 2389 - # 2390 - # Example: 2391 - # 2392 - # -> { "execute": "block_set_io_throttle", 2393 - # "arguments": { "id": "virtio-blk-pci0/virtio-backend", 2394 - # "bps": 0, 2395 - # "bps_rd": 0, 2396 - # "bps_wr": 0, 2397 - # "iops": 512, 2398 - # "iops_rd": 0, 2399 - # "iops_wr": 0, 2400 - # "bps_max": 0, 2401 - # "bps_rd_max": 0, 2402 - # "bps_wr_max": 0, 2403 - # "iops_max": 0, 2404 - # "iops_rd_max": 0, 2405 - # "iops_wr_max": 0, 2406 - # "bps_max_length": 0, 2407 - # "iops_size": 0 } } 2408 - # <- { "return": {} } 2409 - # 2410 - # -> { "execute": "block_set_io_throttle", 2411 - # "arguments": { "id": "ide0-1-0", 2412 - # "bps": 1000000, 2413 - # "bps_rd": 0, 2414 - # "bps_wr": 0, 2415 - # "iops": 0, 2416 - # "iops_rd": 0, 2417 - # "iops_wr": 0, 2418 - # "bps_max": 8000000, 2419 - # "bps_rd_max": 0, 2420 - # "bps_wr_max": 0, 2421 - # "iops_max": 0, 2422 - # "iops_rd_max": 0, 2423 - # "iops_wr_max": 0, 2424 - # "bps_max_length": 60, 2425 - # "iops_size": 0 } } 2426 - # <- { "return": {} } 2427 - ## 2428 - { 'command': 'block_set_io_throttle', 'boxed': true, 2429 - 'data': 'BlockIOThrottle' } 2430 - 2431 - ## 2432 2288 # @BlockIOThrottle: 2433 2289 # 2434 2290 # A set of parameters describing block throttling. ··· 3688 3544 # 3689 3545 # @pool: Ceph pool name. 3690 3546 # 3547 + # @namespace: Rados namespace name in the Ceph pool. (Since 5.0) 3548 + # 3691 3549 # @image: Image name in the Ceph pool. 3692 3550 # 3693 3551 # @conf: path to Ceph configuration file. Values ··· 3714 3572 ## 3715 3573 { 'struct': 'BlockdevOptionsRbd', 3716 3574 'data': { 'pool': 'str', 3575 + '*namespace': 'str', 3717 3576 'image': 'str', 3718 3577 '*conf': 'str', 3719 3578 '*snapshot': 'str', ··· 4758 4617 'options': 'BlockdevCreateOptions' } } 4759 4618 4760 4619 ## 4761 - # @blockdev-open-tray: 4762 - # 4763 - # Opens a block device's tray. If there is a block driver state tree inserted as 4764 - # a medium, it will become inaccessible to the guest (but it will remain 4765 - # associated to the block device, so closing the tray will make it accessible 4766 - # again). 4767 - # 4768 - # If the tray was already open before, this will be a no-op. 4769 - # 4770 - # Once the tray opens, a DEVICE_TRAY_MOVED event is emitted. There are cases in 4771 - # which no such event will be generated, these include: 4772 - # 4773 - # - if the guest has locked the tray, @force is false and the guest does not 4774 - # respond to the eject request 4775 - # - if the BlockBackend denoted by @device does not have a guest device attached 4776 - # to it 4777 - # - if the guest device does not have an actual tray 4778 - # 4779 - # @device: Block device name (deprecated, use @id instead) 4780 - # 4781 - # @id: The name or QOM path of the guest device (since: 2.8) 4782 - # 4783 - # @force: if false (the default), an eject request will be sent to 4784 - # the guest if it has locked the tray (and the tray will not be opened 4785 - # immediately); if true, the tray will be opened regardless of whether 4786 - # it is locked 4787 - # 4788 - # Since: 2.5 4789 - # 4790 - # Example: 4791 - # 4792 - # -> { "execute": "blockdev-open-tray", 4793 - # "arguments": { "id": "ide0-1-0" } } 4794 - # 4795 - # <- { "timestamp": { "seconds": 1418751016, 4796 - # "microseconds": 716996 }, 4797 - # "event": "DEVICE_TRAY_MOVED", 4798 - # "data": { "device": "ide1-cd0", 4799 - # "id": "ide0-1-0", 4800 - # "tray-open": true } } 4801 - # 4802 - # <- { "return": {} } 4803 - # 4804 - ## 4805 - { 'command': 'blockdev-open-tray', 4806 - 'data': { '*device': 'str', 4807 - '*id': 'str', 4808 - '*force': 'bool' } } 4809 - 4810 - ## 4811 - # @blockdev-close-tray: 4812 - # 4813 - # Closes a block device's tray. If there is a block driver state tree associated 4814 - # with the block device (which is currently ejected), that tree will be loaded 4815 - # as the medium. 4816 - # 4817 - # If the tray was already closed before, this will be a no-op. 4818 - # 4819 - # @device: Block device name (deprecated, use @id instead) 4820 - # 4821 - # @id: The name or QOM path of the guest device (since: 2.8) 4822 - # 4823 - # Since: 2.5 4824 - # 4825 - # Example: 4826 - # 4827 - # -> { "execute": "blockdev-close-tray", 4828 - # "arguments": { "id": "ide0-1-0" } } 4829 - # 4830 - # <- { "timestamp": { "seconds": 1418751345, 4831 - # "microseconds": 272147 }, 4832 - # "event": "DEVICE_TRAY_MOVED", 4833 - # "data": { "device": "ide1-cd0", 4834 - # "id": "ide0-1-0", 4835 - # "tray-open": false } } 4836 - # 4837 - # <- { "return": {} } 4838 - # 4839 - ## 4840 - { 'command': 'blockdev-close-tray', 4841 - 'data': { '*device': 'str', 4842 - '*id': 'str' } } 4843 - 4844 - ## 4845 - # @blockdev-remove-medium: 4846 - # 4847 - # Removes a medium (a block driver state tree) from a block device. That block 4848 - # device's tray must currently be open (unless there is no attached guest 4849 - # device). 4850 - # 4851 - # If the tray is open and there is no medium inserted, this will be a no-op. 4852 - # 4853 - # @id: The name or QOM path of the guest device 4854 - # 4855 - # Since: 2.12 4856 - # 4857 - # Example: 4858 - # 4859 - # -> { "execute": "blockdev-remove-medium", 4860 - # "arguments": { "id": "ide0-1-0" } } 4861 - # 4862 - # <- { "error": { "class": "GenericError", 4863 - # "desc": "Tray of device 'ide0-1-0' is not open" } } 4864 - # 4865 - # -> { "execute": "blockdev-open-tray", 4866 - # "arguments": { "id": "ide0-1-0" } } 4867 - # 4868 - # <- { "timestamp": { "seconds": 1418751627, 4869 - # "microseconds": 549958 }, 4870 - # "event": "DEVICE_TRAY_MOVED", 4871 - # "data": { "device": "ide1-cd0", 4872 - # "id": "ide0-1-0", 4873 - # "tray-open": true } } 4874 - # 4875 - # <- { "return": {} } 4876 - # 4877 - # -> { "execute": "blockdev-remove-medium", 4878 - # "arguments": { "id": "ide0-1-0" } } 4879 - # 4880 - # <- { "return": {} } 4881 - # 4882 - ## 4883 - { 'command': 'blockdev-remove-medium', 4884 - 'data': { 'id': 'str' } } 4885 - 4886 - ## 4887 - # @blockdev-insert-medium: 4888 - # 4889 - # Inserts a medium (a block driver state tree) into a block device. That block 4890 - # device's tray must currently be open (unless there is no attached guest 4891 - # device) and there must be no medium inserted already. 4892 - # 4893 - # @id: The name or QOM path of the guest device 4894 - # 4895 - # @node-name: name of a node in the block driver state graph 4896 - # 4897 - # Since: 2.12 4898 - # 4899 - # Example: 4900 - # 4901 - # -> { "execute": "blockdev-add", 4902 - # "arguments": { 4903 - # "node-name": "node0", 4904 - # "driver": "raw", 4905 - # "file": { "driver": "file", 4906 - # "filename": "fedora.iso" } } } 4907 - # <- { "return": {} } 4908 - # 4909 - # -> { "execute": "blockdev-insert-medium", 4910 - # "arguments": { "id": "ide0-1-0", 4911 - # "node-name": "node0" } } 4912 - # 4913 - # <- { "return": {} } 4914 - # 4915 - ## 4916 - { 'command': 'blockdev-insert-medium', 4917 - 'data': { 'id': 'str', 4918 - 'node-name': 'str'} } 4919 - 4920 - 4921 - ## 4922 - # @BlockdevChangeReadOnlyMode: 4923 - # 4924 - # Specifies the new read-only mode of a block device subject to the 4925 - # @blockdev-change-medium command. 4926 - # 4927 - # @retain: Retains the current read-only mode 4928 - # 4929 - # @read-only: Makes the device read-only 4930 - # 4931 - # @read-write: Makes the device writable 4932 - # 4933 - # Since: 2.3 4934 - # 4935 - ## 4936 - { 'enum': 'BlockdevChangeReadOnlyMode', 4937 - 'data': ['retain', 'read-only', 'read-write'] } 4938 - 4939 - 4940 - ## 4941 - # @blockdev-change-medium: 4942 - # 4943 - # Changes the medium inserted into a block device by ejecting the current medium 4944 - # and loading a new image file which is inserted as the new medium (this command 4945 - # combines blockdev-open-tray, blockdev-remove-medium, blockdev-insert-medium 4946 - # and blockdev-close-tray). 4947 - # 4948 - # @device: Block device name (deprecated, use @id instead) 4949 - # 4950 - # @id: The name or QOM path of the guest device 4951 - # (since: 2.8) 4952 - # 4953 - # @filename: filename of the new image to be loaded 4954 - # 4955 - # @format: format to open the new image with (defaults to 4956 - # the probed format) 4957 - # 4958 - # @read-only-mode: change the read-only mode of the device; defaults 4959 - # to 'retain' 4960 - # 4961 - # Since: 2.5 4962 - # 4963 - # Examples: 4964 - # 4965 - # 1. Change a removable medium 4966 - # 4967 - # -> { "execute": "blockdev-change-medium", 4968 - # "arguments": { "id": "ide0-1-0", 4969 - # "filename": "/srv/images/Fedora-12-x86_64-DVD.iso", 4970 - # "format": "raw" } } 4971 - # <- { "return": {} } 4972 - # 4973 - # 2. Load a read-only medium into a writable drive 4974 - # 4975 - # -> { "execute": "blockdev-change-medium", 4976 - # "arguments": { "id": "floppyA", 4977 - # "filename": "/srv/images/ro.img", 4978 - # "format": "raw", 4979 - # "read-only-mode": "retain" } } 4980 - # 4981 - # <- { "error": 4982 - # { "class": "GenericError", 4983 - # "desc": "Could not open '/srv/images/ro.img': Permission denied" } } 4984 - # 4985 - # -> { "execute": "blockdev-change-medium", 4986 - # "arguments": { "id": "floppyA", 4987 - # "filename": "/srv/images/ro.img", 4988 - # "format": "raw", 4989 - # "read-only-mode": "read-only" } } 4990 - # 4991 - # <- { "return": {} } 4992 - # 4993 - ## 4994 - { 'command': 'blockdev-change-medium', 4995 - 'data': { '*device': 'str', 4996 - '*id': 'str', 4997 - 'filename': 'str', 4998 - '*format': 'str', 4999 - '*read-only-mode': 'BlockdevChangeReadOnlyMode' } } 5000 - 5001 - 5002 - ## 5003 4620 # @BlockErrorAction: 5004 4621 # 5005 4622 # An enumeration of action that has been taken when a DISK I/O occurs ··· 5447 5064 'data' : { 'node-name': 'str', 5448 5065 'iothread': 'StrOrNull', 5449 5066 '*force': 'bool' } } 5067 + 5068 + ## 5069 + # @NbdServerOptions: 5070 + # 5071 + # @addr: Address on which to listen. 5072 + # @tls-creds: ID of the TLS credentials object (since 2.6). 5073 + # @tls-authz: ID of the QAuthZ authorization object used to validate 5074 + # the client's x509 distinguished name. This object is 5075 + # is only resolved at time of use, so can be deleted and 5076 + # recreated on the fly while the NBD server is active. 5077 + # If missing, it will default to denying access (since 4.0). 5078 + # 5079 + # Keep this type consistent with the nbd-server-start arguments. The only 5080 + # intended difference is using SocketAddress instead of SocketAddressLegacy. 5081 + # 5082 + # Since: 4.2 5083 + ## 5084 + { 'struct': 'NbdServerOptions', 5085 + 'data': { 'addr': 'SocketAddress', 5086 + '*tls-creds': 'str', 5087 + '*tls-authz': 'str'} } 5088 + 5089 + ## 5090 + # @nbd-server-start: 5091 + # 5092 + # Start an NBD server listening on the given host and port. Block 5093 + # devices can then be exported using @nbd-server-add. The NBD 5094 + # server will present them as named exports; for example, another 5095 + # QEMU instance could refer to them as "nbd:HOST:PORT:exportname=NAME". 5096 + # 5097 + # @addr: Address on which to listen. 5098 + # @tls-creds: ID of the TLS credentials object (since 2.6). 5099 + # @tls-authz: ID of the QAuthZ authorization object used to validate 5100 + # the client's x509 distinguished name. This object is 5101 + # is only resolved at time of use, so can be deleted and 5102 + # recreated on the fly while the NBD server is active. 5103 + # If missing, it will default to denying access (since 4.0). 5104 + # 5105 + # Returns: error if the server is already running. 5106 + # 5107 + # Keep this type consistent with the NbdServerOptions type. The only intended 5108 + # difference is using SocketAddressLegacy instead of SocketAddress. 5109 + # 5110 + # Since: 1.3.0 5111 + ## 5112 + { 'command': 'nbd-server-start', 5113 + 'data': { 'addr': 'SocketAddressLegacy', 5114 + '*tls-creds': 'str', 5115 + '*tls-authz': 'str'} } 5116 + 5117 + ## 5118 + # @BlockExportNbd: 5119 + # 5120 + # An NBD block export. 5121 + # 5122 + # @device: The device name or node name of the node to be exported 5123 + # 5124 + # @name: Export name. If unspecified, the @device parameter is used as the 5125 + # export name. (Since 2.12) 5126 + # 5127 + # @description: Free-form description of the export, up to 4096 bytes. 5128 + # (Since 5.0) 5129 + # 5130 + # @writable: Whether clients should be able to write to the device via the 5131 + # NBD connection (default false). 5132 + # 5133 + # @bitmap: Also export the dirty bitmap reachable from @device, so the 5134 + # NBD client can use NBD_OPT_SET_META_CONTEXT with 5135 + # "qemu:dirty-bitmap:NAME" to inspect the bitmap. (since 4.0) 5136 + # 5137 + # Since: 5.0 5138 + ## 5139 + { 'struct': 'BlockExportNbd', 5140 + 'data': {'device': 'str', '*name': 'str', '*description': 'str', 5141 + '*writable': 'bool', '*bitmap': 'str' } } 5142 + 5143 + ## 5144 + # @nbd-server-add: 5145 + # 5146 + # Export a block node to QEMU's embedded NBD server. 5147 + # 5148 + # Returns: error if the server is not running, or export with the same name 5149 + # already exists. 5150 + # 5151 + # Since: 1.3.0 5152 + ## 5153 + { 'command': 'nbd-server-add', 5154 + 'data': 'BlockExportNbd', 'boxed': true } 5155 + 5156 + ## 5157 + # @NbdServerRemoveMode: 5158 + # 5159 + # Mode for removing an NBD export. 5160 + # 5161 + # @safe: Remove export if there are no existing connections, fail otherwise. 5162 + # 5163 + # @hard: Drop all connections immediately and remove export. 5164 + # 5165 + # Potential additional modes to be added in the future: 5166 + # 5167 + # hide: Just hide export from new clients, leave existing connections as is. 5168 + # Remove export after all clients are disconnected. 5169 + # 5170 + # soft: Hide export from new clients, answer with ESHUTDOWN for all further 5171 + # requests from existing clients. 5172 + # 5173 + # Since: 2.12 5174 + ## 5175 + {'enum': 'NbdServerRemoveMode', 'data': ['safe', 'hard']} 5176 + 5177 + ## 5178 + # @nbd-server-remove: 5179 + # 5180 + # Remove NBD export by name. 5181 + # 5182 + # @name: Export name. 5183 + # 5184 + # @mode: Mode of command operation. See @NbdServerRemoveMode description. 5185 + # Default is 'safe'. 5186 + # 5187 + # Returns: error if 5188 + # - the server is not running 5189 + # - export is not found 5190 + # - mode is 'safe' and there are existing connections 5191 + # 5192 + # Since: 2.12 5193 + ## 5194 + { 'command': 'nbd-server-remove', 5195 + 'data': {'name': 'str', '*mode': 'NbdServerRemoveMode'} } 5196 + 5197 + ## 5198 + # @nbd-server-stop: 5199 + # 5200 + # Stop QEMU's embedded NBD server, and unregister all devices previously 5201 + # added via @nbd-server-add. 5202 + # 5203 + # Since: 1.3.0 5204 + ## 5205 + { 'command': 'nbd-server-stop' } 5206 + 5207 + ## 5208 + # @BlockExportType: 5209 + # 5210 + # An enumeration of block export types 5211 + # 5212 + # @nbd: NBD export 5213 + # 5214 + # Since: 4.2 5215 + ## 5216 + { 'enum': 'BlockExportType', 5217 + 'data': [ 'nbd' ] } 5218 + 5219 + ## 5220 + # @BlockExport: 5221 + # 5222 + # Describes a block export, i.e. how single node should be exported on an 5223 + # external interface. 5224 + # 5225 + # Since: 4.2 5226 + ## 5227 + { 'union': 'BlockExport', 5228 + 'base': { 'type': 'BlockExportType' }, 5229 + 'discriminator': 'type', 5230 + 'data': { 5231 + 'nbd': 'BlockExportNbd' 5232 + } } 5233 + 5234 + ## 5235 + # @QuorumOpType: 5236 + # 5237 + # An enumeration of the quorum operation types 5238 + # 5239 + # @read: read operation 5240 + # 5241 + # @write: write operation 5242 + # 5243 + # @flush: flush operation 5244 + # 5245 + # Since: 2.6 5246 + ## 5247 + { 'enum': 'QuorumOpType', 5248 + 'data': [ 'read', 'write', 'flush' ] } 5249 + 5250 + ## 5251 + # @QUORUM_FAILURE: 5252 + # 5253 + # Emitted by the Quorum block driver if it fails to establish a quorum 5254 + # 5255 + # @reference: device name if defined else node name 5256 + # 5257 + # @sector-num: number of the first sector of the failed read operation 5258 + # 5259 + # @sectors-count: failed read operation sector count 5260 + # 5261 + # Note: This event is rate-limited. 5262 + # 5263 + # Since: 2.0 5264 + # 5265 + # Example: 5266 + # 5267 + # <- { "event": "QUORUM_FAILURE", 5268 + # "data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 }, 5269 + # "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } 5270 + # 5271 + ## 5272 + { 'event': 'QUORUM_FAILURE', 5273 + 'data': { 'reference': 'str', 'sector-num': 'int', 'sectors-count': 'int' } } 5274 + 5275 + ## 5276 + # @QUORUM_REPORT_BAD: 5277 + # 5278 + # Emitted to report a corruption of a Quorum file 5279 + # 5280 + # @type: quorum operation type (Since 2.6) 5281 + # 5282 + # @error: error message. Only present on failure. This field 5283 + # contains a human-readable error message. There are no semantics other 5284 + # than that the block layer reported an error and clients should not 5285 + # try to interpret the error string. 5286 + # 5287 + # @node-name: the graph node name of the block driver state 5288 + # 5289 + # @sector-num: number of the first sector of the failed read operation 5290 + # 5291 + # @sectors-count: failed read operation sector count 5292 + # 5293 + # Note: This event is rate-limited. 5294 + # 5295 + # Since: 2.0 5296 + # 5297 + # Example: 5298 + # 5299 + # 1. Read operation 5300 + # 5301 + # { "event": "QUORUM_REPORT_BAD", 5302 + # "data": { "node-name": "node0", "sector-num": 345435, "sectors-count": 5, 5303 + # "type": "read" }, 5304 + # "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } 5305 + # 5306 + # 2. Flush operation 5307 + # 5308 + # { "event": "QUORUM_REPORT_BAD", 5309 + # "data": { "node-name": "node0", "sector-num": 0, "sectors-count": 2097120, 5310 + # "type": "flush", "error": "Broken pipe" }, 5311 + # "timestamp": { "seconds": 1456406829, "microseconds": 291763 } } 5312 + # 5313 + ## 5314 + { 'event': 'QUORUM_REPORT_BAD', 5315 + 'data': { 'type': 'QuorumOpType', '*error': 'str', 'node-name': 'str', 5316 + 'sector-num': 'int', 'sectors-count': 'int' } } 5317 + 5318 + ## 5319 + # @BlockdevSnapshotInternal: 5320 + # 5321 + # @device: the device name or node-name of a root node to generate the snapshot 5322 + # from 5323 + # 5324 + # @name: the name of the internal snapshot to be created 5325 + # 5326 + # Notes: In transaction, if @name is empty, or any snapshot matching @name 5327 + # exists, the operation will fail. Only some image formats support it, 5328 + # for example, qcow2, rbd, and sheepdog. 5329 + # 5330 + # Since: 1.7 5331 + ## 5332 + { 'struct': 'BlockdevSnapshotInternal', 5333 + 'data': { 'device': 'str', 'name': 'str' } } 5334 + 5335 + ## 5336 + # @blockdev-snapshot-internal-sync: 5337 + # 5338 + # Synchronously take an internal snapshot of a block device, when the 5339 + # format of the image used supports it. If the name is an empty 5340 + # string, or a snapshot with name already exists, the operation will 5341 + # fail. 5342 + # 5343 + # For the arguments, see the documentation of BlockdevSnapshotInternal. 5344 + # 5345 + # Returns: - nothing on success 5346 + # - If @device is not a valid block device, GenericError 5347 + # - If any snapshot matching @name exists, or @name is empty, 5348 + # GenericError 5349 + # - If the format of the image used does not support it, 5350 + # BlockFormatFeatureNotSupported 5351 + # 5352 + # Since: 1.7 5353 + # 5354 + # Example: 5355 + # 5356 + # -> { "execute": "blockdev-snapshot-internal-sync", 5357 + # "arguments": { "device": "ide-hd0", 5358 + # "name": "snapshot0" } 5359 + # } 5360 + # <- { "return": {} } 5361 + # 5362 + ## 5363 + { 'command': 'blockdev-snapshot-internal-sync', 5364 + 'data': 'BlockdevSnapshotInternal' } 5365 + 5366 + ## 5367 + # @blockdev-snapshot-delete-internal-sync: 5368 + # 5369 + # Synchronously delete an internal snapshot of a block device, when the format 5370 + # of the image used support it. The snapshot is identified by name or id or 5371 + # both. One of the name or id is required. Return SnapshotInfo for the 5372 + # successfully deleted snapshot. 5373 + # 5374 + # @device: the device name or node-name of a root node to delete the snapshot 5375 + # from 5376 + # 5377 + # @id: optional the snapshot's ID to be deleted 5378 + # 5379 + # @name: optional the snapshot's name to be deleted 5380 + # 5381 + # Returns: - SnapshotInfo on success 5382 + # - If @device is not a valid block device, GenericError 5383 + # - If snapshot not found, GenericError 5384 + # - If the format of the image used does not support it, 5385 + # BlockFormatFeatureNotSupported 5386 + # - If @id and @name are both not specified, GenericError 5387 + # 5388 + # Since: 1.7 5389 + # 5390 + # Example: 5391 + # 5392 + # -> { "execute": "blockdev-snapshot-delete-internal-sync", 5393 + # "arguments": { "device": "ide-hd0", 5394 + # "name": "snapshot0" } 5395 + # } 5396 + # <- { "return": { 5397 + # "id": "1", 5398 + # "name": "snapshot0", 5399 + # "vm-state-size": 0, 5400 + # "date-sec": 1000012, 5401 + # "date-nsec": 10, 5402 + # "vm-clock-sec": 100, 5403 + # "vm-clock-nsec": 20 5404 + # } 5405 + # } 5406 + # 5407 + ## 5408 + { 'command': 'blockdev-snapshot-delete-internal-sync', 5409 + 'data': { 'device': 'str', '*id': 'str', '*name': 'str'}, 5410 + 'returns': 'SnapshotInfo' }
+305 -203
qapi/block.json
··· 61 61 'data': ['144', '288', '120', 'none', 'auto']} 62 62 63 63 ## 64 - # @BlockdevSnapshotInternal: 65 - # 66 - # @device: the device name or node-name of a root node to generate the snapshot 67 - # from 68 - # 69 - # @name: the name of the internal snapshot to be created 70 - # 71 - # Notes: In transaction, if @name is empty, or any snapshot matching @name 72 - # exists, the operation will fail. Only some image formats support it, 73 - # for example, qcow2, rbd, and sheepdog. 74 - # 75 - # Since: 1.7 76 - ## 77 - { 'struct': 'BlockdevSnapshotInternal', 78 - 'data': { 'device': 'str', 'name': 'str' } } 79 - 80 - ## 81 64 # @PRManagerInfo: 82 65 # 83 66 # Information about a persistent reservation manager ··· 104 87 { 'command': 'query-pr-managers', 'returns': ['PRManagerInfo'], 105 88 'allow-preconfig': true } 106 89 107 - 108 90 ## 109 - # @blockdev-snapshot-internal-sync: 91 + # @eject: 110 92 # 111 - # Synchronously take an internal snapshot of a block device, when the 112 - # format of the image used supports it. If the name is an empty 113 - # string, or a snapshot with name already exists, the operation will 114 - # fail. 93 + # Ejects a device from a removable drive. 115 94 # 116 - # For the arguments, see the documentation of BlockdevSnapshotInternal. 95 + # @device: Block device name (deprecated, use @id instead) 117 96 # 118 - # Returns: - nothing on success 119 - # - If @device is not a valid block device, GenericError 120 - # - If any snapshot matching @name exists, or @name is empty, 121 - # GenericError 122 - # - If the format of the image used does not support it, 123 - # BlockFormatFeatureNotSupported 97 + # @id: The name or QOM path of the guest device (since: 2.8) 124 98 # 125 - # Since: 1.7 99 + # @force: If true, eject regardless of whether the drive is locked. 100 + # If not specified, the default value is false. 101 + # 102 + # Returns: - Nothing on success 103 + # - If @device is not a valid block device, DeviceNotFound 104 + # Notes: Ejecting a device with no media results in success 105 + # 106 + # Since: 0.14.0 126 107 # 127 108 # Example: 128 109 # 129 - # -> { "execute": "blockdev-snapshot-internal-sync", 130 - # "arguments": { "device": "ide-hd0", 131 - # "name": "snapshot0" } 132 - # } 110 + # -> { "execute": "eject", "arguments": { "id": "ide1-0-1" } } 133 111 # <- { "return": {} } 134 - # 135 112 ## 136 - { 'command': 'blockdev-snapshot-internal-sync', 137 - 'data': 'BlockdevSnapshotInternal' } 113 + { 'command': 'eject', 114 + 'data': { '*device': 'str', 115 + '*id': 'str', 116 + '*force': 'bool' } } 138 117 139 118 ## 140 - # @blockdev-snapshot-delete-internal-sync: 119 + # @blockdev-open-tray: 120 + # 121 + # Opens a block device's tray. If there is a block driver state tree inserted as 122 + # a medium, it will become inaccessible to the guest (but it will remain 123 + # associated to the block device, so closing the tray will make it accessible 124 + # again). 125 + # 126 + # If the tray was already open before, this will be a no-op. 141 127 # 142 - # Synchronously delete an internal snapshot of a block device, when the format 143 - # of the image used support it. The snapshot is identified by name or id or 144 - # both. One of the name or id is required. Return SnapshotInfo for the 145 - # successfully deleted snapshot. 128 + # Once the tray opens, a DEVICE_TRAY_MOVED event is emitted. There are cases in 129 + # which no such event will be generated, these include: 146 130 # 147 - # @device: the device name or node-name of a root node to delete the snapshot 148 - # from 131 + # - if the guest has locked the tray, @force is false and the guest does not 132 + # respond to the eject request 133 + # - if the BlockBackend denoted by @device does not have a guest device attached 134 + # to it 135 + # - if the guest device does not have an actual tray 149 136 # 150 - # @id: optional the snapshot's ID to be deleted 137 + # @device: Block device name (deprecated, use @id instead) 151 138 # 152 - # @name: optional the snapshot's name to be deleted 139 + # @id: The name or QOM path of the guest device (since: 2.8) 153 140 # 154 - # Returns: - SnapshotInfo on success 155 - # - If @device is not a valid block device, GenericError 156 - # - If snapshot not found, GenericError 157 - # - If the format of the image used does not support it, 158 - # BlockFormatFeatureNotSupported 159 - # - If @id and @name are both not specified, GenericError 141 + # @force: if false (the default), an eject request will be sent to 142 + # the guest if it has locked the tray (and the tray will not be opened 143 + # immediately); if true, the tray will be opened regardless of whether 144 + # it is locked 160 145 # 161 - # Since: 1.7 146 + # Since: 2.5 162 147 # 163 148 # Example: 164 149 # 165 - # -> { "execute": "blockdev-snapshot-delete-internal-sync", 166 - # "arguments": { "device": "ide-hd0", 167 - # "name": "snapshot0" } 168 - # } 169 - # <- { "return": { 170 - # "id": "1", 171 - # "name": "snapshot0", 172 - # "vm-state-size": 0, 173 - # "date-sec": 1000012, 174 - # "date-nsec": 10, 175 - # "vm-clock-sec": 100, 176 - # "vm-clock-nsec": 20 177 - # } 178 - # } 150 + # -> { "execute": "blockdev-open-tray", 151 + # "arguments": { "id": "ide0-1-0" } } 152 + # 153 + # <- { "timestamp": { "seconds": 1418751016, 154 + # "microseconds": 716996 }, 155 + # "event": "DEVICE_TRAY_MOVED", 156 + # "data": { "device": "ide1-cd0", 157 + # "id": "ide0-1-0", 158 + # "tray-open": true } } 159 + # 160 + # <- { "return": {} } 179 161 # 180 162 ## 181 - { 'command': 'blockdev-snapshot-delete-internal-sync', 182 - 'data': { 'device': 'str', '*id': 'str', '*name': 'str'}, 183 - 'returns': 'SnapshotInfo' } 163 + { 'command': 'blockdev-open-tray', 164 + 'data': { '*device': 'str', 165 + '*id': 'str', 166 + '*force': 'bool' } } 184 167 185 168 ## 186 - # @eject: 169 + # @blockdev-close-tray: 187 170 # 188 - # Ejects a device from a removable drive. 171 + # Closes a block device's tray. If there is a block driver state tree associated 172 + # with the block device (which is currently ejected), that tree will be loaded 173 + # as the medium. 174 + # 175 + # If the tray was already closed before, this will be a no-op. 189 176 # 190 177 # @device: Block device name (deprecated, use @id instead) 191 178 # 192 179 # @id: The name or QOM path of the guest device (since: 2.8) 193 180 # 194 - # @force: If true, eject regardless of whether the drive is locked. 195 - # If not specified, the default value is false. 181 + # Since: 2.5 196 182 # 197 - # Returns: - Nothing on success 198 - # - If @device is not a valid block device, DeviceNotFound 199 - # Notes: Ejecting a device with no media results in success 183 + # Example: 200 184 # 201 - # Since: 0.14.0 185 + # -> { "execute": "blockdev-close-tray", 186 + # "arguments": { "id": "ide0-1-0" } } 202 187 # 203 - # Example: 188 + # <- { "timestamp": { "seconds": 1418751345, 189 + # "microseconds": 272147 }, 190 + # "event": "DEVICE_TRAY_MOVED", 191 + # "data": { "device": "ide1-cd0", 192 + # "id": "ide0-1-0", 193 + # "tray-open": false } } 204 194 # 205 - # -> { "execute": "eject", "arguments": { "id": "ide1-0-1" } } 206 195 # <- { "return": {} } 196 + # 207 197 ## 208 - { 'command': 'eject', 198 + { 'command': 'blockdev-close-tray', 209 199 'data': { '*device': 'str', 210 - '*id': 'str', 211 - '*force': 'bool' } } 200 + '*id': 'str' } } 212 201 213 202 ## 214 - # @nbd-server-start: 203 + # @blockdev-remove-medium: 215 204 # 216 - # Start an NBD server listening on the given host and port. Block 217 - # devices can then be exported using @nbd-server-add. The NBD 218 - # server will present them as named exports; for example, another 219 - # QEMU instance could refer to them as "nbd:HOST:PORT:exportname=NAME". 205 + # Removes a medium (a block driver state tree) from a block device. That block 206 + # device's tray must currently be open (unless there is no attached guest 207 + # device). 220 208 # 221 - # @addr: Address on which to listen. 222 - # @tls-creds: ID of the TLS credentials object (since 2.6). 223 - # @tls-authz: ID of the QAuthZ authorization object used to validate 224 - # the client's x509 distinguished name. This object is 225 - # is only resolved at time of use, so can be deleted and 226 - # recreated on the fly while the NBD server is active. 227 - # If missing, it will default to denying access (since 4.0). 209 + # If the tray is open and there is no medium inserted, this will be a no-op. 228 210 # 229 - # Returns: error if the server is already running. 211 + # @id: The name or QOM path of the guest device 230 212 # 231 - # Since: 1.3.0 232 - ## 233 - { 'command': 'nbd-server-start', 234 - 'data': { 'addr': 'SocketAddressLegacy', 235 - '*tls-creds': 'str', 236 - '*tls-authz': 'str'} } 237 - 238 - ## 239 - # @nbd-server-add: 213 + # Since: 2.12 240 214 # 241 - # Export a block node to QEMU's embedded NBD server. 215 + # Example: 216 + # 217 + # -> { "execute": "blockdev-remove-medium", 218 + # "arguments": { "id": "ide0-1-0" } } 242 219 # 243 - # @device: The device name or node name of the node to be exported 220 + # <- { "error": { "class": "GenericError", 221 + # "desc": "Tray of device 'ide0-1-0' is not open" } } 244 222 # 245 - # @name: Export name. If unspecified, the @device parameter is used as the 246 - # export name. (Since 2.12) 223 + # -> { "execute": "blockdev-open-tray", 224 + # "arguments": { "id": "ide0-1-0" } } 247 225 # 248 - # @description: Free-form description of the export, up to 4096 bytes. 249 - # (Since 5.0) 226 + # <- { "timestamp": { "seconds": 1418751627, 227 + # "microseconds": 549958 }, 228 + # "event": "DEVICE_TRAY_MOVED", 229 + # "data": { "device": "ide1-cd0", 230 + # "id": "ide0-1-0", 231 + # "tray-open": true } } 250 232 # 251 - # @writable: Whether clients should be able to write to the device via the 252 - # NBD connection (default false). 233 + # <- { "return": {} } 253 234 # 254 - # @bitmap: Also export the dirty bitmap reachable from @device, so the 255 - # NBD client can use NBD_OPT_SET_META_CONTEXT with 256 - # "qemu:dirty-bitmap:NAME" to inspect the bitmap. (since 4.0) 235 + # -> { "execute": "blockdev-remove-medium", 236 + # "arguments": { "id": "ide0-1-0" } } 257 237 # 258 - # Returns: error if the server is not running, or export with the same name 259 - # already exists. 238 + # <- { "return": {} } 260 239 # 261 - # Since: 1.3.0 262 240 ## 263 - { 'command': 'nbd-server-add', 264 - 'data': {'device': 'str', '*name': 'str', '*description': 'str', 265 - '*writable': 'bool', '*bitmap': 'str' } } 241 + { 'command': 'blockdev-remove-medium', 242 + 'data': { 'id': 'str' } } 266 243 267 244 ## 268 - # @NbdServerRemoveMode: 245 + # @blockdev-insert-medium: 269 246 # 270 - # Mode for removing an NBD export. 247 + # Inserts a medium (a block driver state tree) into a block device. That block 248 + # device's tray must currently be open (unless there is no attached guest 249 + # device) and there must be no medium inserted already. 271 250 # 272 - # @safe: Remove export if there are no existing connections, fail otherwise. 251 + # @id: The name or QOM path of the guest device 273 252 # 274 - # @hard: Drop all connections immediately and remove export. 253 + # @node-name: name of a node in the block driver state graph 254 + # 255 + # Since: 2.12 275 256 # 276 - # Potential additional modes to be added in the future: 257 + # Example: 258 + # 259 + # -> { "execute": "blockdev-add", 260 + # "arguments": { 261 + # "node-name": "node0", 262 + # "driver": "raw", 263 + # "file": { "driver": "file", 264 + # "filename": "fedora.iso" } } } 265 + # <- { "return": {} } 277 266 # 278 - # hide: Just hide export from new clients, leave existing connections as is. 279 - # Remove export after all clients are disconnected. 267 + # -> { "execute": "blockdev-insert-medium", 268 + # "arguments": { "id": "ide0-1-0", 269 + # "node-name": "node0" } } 280 270 # 281 - # soft: Hide export from new clients, answer with ESHUTDOWN for all further 282 - # requests from existing clients. 271 + # <- { "return": {} } 283 272 # 284 - # Since: 2.12 285 273 ## 286 - {'enum': 'NbdServerRemoveMode', 'data': ['safe', 'hard']} 274 + { 'command': 'blockdev-insert-medium', 275 + 'data': { 'id': 'str', 276 + 'node-name': 'str'} } 277 + 287 278 288 279 ## 289 - # @nbd-server-remove: 280 + # @BlockdevChangeReadOnlyMode: 290 281 # 291 - # Remove NBD export by name. 282 + # Specifies the new read-only mode of a block device subject to the 283 + # @blockdev-change-medium command. 292 284 # 293 - # @name: Export name. 285 + # @retain: Retains the current read-only mode 294 286 # 295 - # @mode: Mode of command operation. See @NbdServerRemoveMode description. 296 - # Default is 'safe'. 287 + # @read-only: Makes the device read-only 297 288 # 298 - # Returns: error if 299 - # - the server is not running 300 - # - export is not found 301 - # - mode is 'safe' and there are existing connections 289 + # @read-write: Makes the device writable 302 290 # 303 - # Since: 2.12 291 + # Since: 2.3 292 + # 304 293 ## 305 - { 'command': 'nbd-server-remove', 306 - 'data': {'name': 'str', '*mode': 'NbdServerRemoveMode'} } 294 + { 'enum': 'BlockdevChangeReadOnlyMode', 295 + 'data': ['retain', 'read-only', 'read-write'] } 296 + 307 297 308 298 ## 309 - # @nbd-server-stop: 299 + # @blockdev-change-medium: 300 + # 301 + # Changes the medium inserted into a block device by ejecting the current medium 302 + # and loading a new image file which is inserted as the new medium (this command 303 + # combines blockdev-open-tray, blockdev-remove-medium, blockdev-insert-medium 304 + # and blockdev-close-tray). 305 + # 306 + # @device: Block device name (deprecated, use @id instead) 307 + # 308 + # @id: The name or QOM path of the guest device 309 + # (since: 2.8) 310 + # 311 + # @filename: filename of the new image to be loaded 312 + # 313 + # @format: format to open the new image with (defaults to 314 + # the probed format) 315 + # 316 + # @read-only-mode: change the read-only mode of the device; defaults 317 + # to 'retain' 318 + # 319 + # Since: 2.5 320 + # 321 + # Examples: 322 + # 323 + # 1. Change a removable medium 324 + # 325 + # -> { "execute": "blockdev-change-medium", 326 + # "arguments": { "id": "ide0-1-0", 327 + # "filename": "/srv/images/Fedora-12-x86_64-DVD.iso", 328 + # "format": "raw" } } 329 + # <- { "return": {} } 330 + # 331 + # 2. Load a read-only medium into a writable drive 332 + # 333 + # -> { "execute": "blockdev-change-medium", 334 + # "arguments": { "id": "floppyA", 335 + # "filename": "/srv/images/ro.img", 336 + # "format": "raw", 337 + # "read-only-mode": "retain" } } 310 338 # 311 - # Stop QEMU's embedded NBD server, and unregister all devices previously 312 - # added via @nbd-server-add. 339 + # <- { "error": 340 + # { "class": "GenericError", 341 + # "desc": "Could not open '/srv/images/ro.img': Permission denied" } } 313 342 # 314 - # Since: 1.3.0 343 + # -> { "execute": "blockdev-change-medium", 344 + # "arguments": { "id": "floppyA", 345 + # "filename": "/srv/images/ro.img", 346 + # "format": "raw", 347 + # "read-only-mode": "read-only" } } 348 + # 349 + # <- { "return": {} } 350 + # 315 351 ## 316 - { 'command': 'nbd-server-stop' } 352 + { 'command': 'blockdev-change-medium', 353 + 'data': { '*device': 'str', 354 + '*id': 'str', 355 + 'filename': 'str', 356 + '*format': 'str', 357 + '*read-only-mode': 'BlockdevChangeReadOnlyMode' } } 358 + 317 359 318 360 ## 319 361 # @DEVICE_TRAY_MOVED: ··· 369 411 'data': { 'id': 'str', 'connected': 'bool' } } 370 412 371 413 ## 372 - # @QuorumOpType: 414 + # @block_set_io_throttle: 373 415 # 374 - # An enumeration of the quorum operation types 416 + # Change I/O throttle limits for a block drive. 375 417 # 376 - # @read: read operation 418 + # Since QEMU 2.4, each device with I/O limits is member of a throttle 419 + # group. 377 420 # 378 - # @write: write operation 421 + # If two or more devices are members of the same group, the limits 422 + # will apply to the combined I/O of the whole group in a round-robin 423 + # fashion. Therefore, setting new I/O limits to a device will affect 424 + # the whole group. 379 425 # 380 - # @flush: flush operation 426 + # The name of the group can be specified using the 'group' parameter. 427 + # If the parameter is unset, it is assumed to be the current group of 428 + # that device. If it's not in any group yet, the name of the device 429 + # will be used as the name for its group. 381 430 # 382 - # Since: 2.6 383 - ## 384 - { 'enum': 'QuorumOpType', 385 - 'data': [ 'read', 'write', 'flush' ] } 386 - 387 - ## 388 - # @QUORUM_FAILURE: 389 - # 390 - # Emitted by the Quorum block driver if it fails to establish a quorum 431 + # The 'group' parameter can also be used to move a device to a 432 + # different group. In this case the limits specified in the parameters 433 + # will be applied to the new group only. 391 434 # 392 - # @reference: device name if defined else node name 393 - # 394 - # @sector-num: number of the first sector of the failed read operation 395 - # 396 - # @sectors-count: failed read operation sector count 435 + # I/O limits can be disabled by setting all of them to 0. In this case 436 + # the device will be removed from its group and the rest of its 437 + # members will not be affected. The 'group' parameter is ignored. 397 438 # 398 - # Note: This event is rate-limited. 439 + # Returns: - Nothing on success 440 + # - If @device is not a valid block device, DeviceNotFound 399 441 # 400 - # Since: 2.0 442 + # Since: 1.1 401 443 # 402 444 # Example: 403 445 # 404 - # <- { "event": "QUORUM_FAILURE", 405 - # "data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 }, 406 - # "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } 446 + # -> { "execute": "block_set_io_throttle", 447 + # "arguments": { "id": "virtio-blk-pci0/virtio-backend", 448 + # "bps": 0, 449 + # "bps_rd": 0, 450 + # "bps_wr": 0, 451 + # "iops": 512, 452 + # "iops_rd": 0, 453 + # "iops_wr": 0, 454 + # "bps_max": 0, 455 + # "bps_rd_max": 0, 456 + # "bps_wr_max": 0, 457 + # "iops_max": 0, 458 + # "iops_rd_max": 0, 459 + # "iops_wr_max": 0, 460 + # "bps_max_length": 0, 461 + # "iops_size": 0 } } 462 + # <- { "return": {} } 407 463 # 464 + # -> { "execute": "block_set_io_throttle", 465 + # "arguments": { "id": "ide0-1-0", 466 + # "bps": 1000000, 467 + # "bps_rd": 0, 468 + # "bps_wr": 0, 469 + # "iops": 0, 470 + # "iops_rd": 0, 471 + # "iops_wr": 0, 472 + # "bps_max": 8000000, 473 + # "bps_rd_max": 0, 474 + # "bps_wr_max": 0, 475 + # "iops_max": 0, 476 + # "iops_rd_max": 0, 477 + # "iops_wr_max": 0, 478 + # "bps_max_length": 60, 479 + # "iops_size": 0 } } 480 + # <- { "return": {} } 408 481 ## 409 - { 'event': 'QUORUM_FAILURE', 410 - 'data': { 'reference': 'str', 'sector-num': 'int', 'sectors-count': 'int' } } 482 + { 'command': 'block_set_io_throttle', 'boxed': true, 483 + 'data': 'BlockIOThrottle' } 411 484 412 485 ## 413 - # @QUORUM_REPORT_BAD: 486 + # @block-latency-histogram-set: 414 487 # 415 - # Emitted to report a corruption of a Quorum file 488 + # Manage read, write and flush latency histograms for the device. 416 489 # 417 - # @type: quorum operation type (Since 2.6) 490 + # If only @id parameter is specified, remove all present latency histograms 491 + # for the device. Otherwise, add/reset some of (or all) latency histograms. 492 + # 493 + # @id: The name or QOM path of the guest device. 494 + # 495 + # @boundaries: list of interval boundary values (see description in 496 + # BlockLatencyHistogramInfo definition). If specified, all 497 + # latency histograms are removed, and empty ones created for all 498 + # io types with intervals corresponding to @boundaries (except for 499 + # io types, for which specific boundaries are set through the 500 + # following parameters). 501 + # 502 + # @boundaries-read: list of interval boundary values for read latency 503 + # histogram. If specified, old read latency histogram is 504 + # removed, and empty one created with intervals 505 + # corresponding to @boundaries-read. The parameter has higher 506 + # priority then @boundaries. 418 507 # 419 - # @error: error message. Only present on failure. This field 420 - # contains a human-readable error message. There are no semantics other 421 - # than that the block layer reported an error and clients should not 422 - # try to interpret the error string. 508 + # @boundaries-write: list of interval boundary values for write latency 509 + # histogram. 423 510 # 424 - # @node-name: the graph node name of the block driver state 511 + # @boundaries-flush: list of interval boundary values for flush latency 512 + # histogram. 425 513 # 426 - # @sector-num: number of the first sector of the failed read operation 514 + # Returns: error if device is not found or any boundary arrays are invalid. 427 515 # 428 - # @sectors-count: failed read operation sector count 516 + # Since: 4.0 429 517 # 430 - # Note: This event is rate-limited. 518 + # Example: set new histograms for all io types with intervals 519 + # [0, 10), [10, 50), [50, 100), [100, +inf): 431 520 # 432 - # Since: 2.0 521 + # -> { "execute": "block-latency-histogram-set", 522 + # "arguments": { "id": "drive0", 523 + # "boundaries": [10, 50, 100] } } 524 + # <- { "return": {} } 433 525 # 434 - # Example: 526 + # Example: set new histogram only for write, other histograms will remain 527 + # not changed (or not created): 435 528 # 436 - # 1. Read operation 529 + # -> { "execute": "block-latency-histogram-set", 530 + # "arguments": { "id": "drive0", 531 + # "boundaries-write": [10, 50, 100] } } 532 + # <- { "return": {} } 437 533 # 438 - # { "event": "QUORUM_REPORT_BAD", 439 - # "data": { "node-name": "node0", "sector-num": 345435, "sectors-count": 5, 440 - # "type": "read" }, 441 - # "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } 534 + # Example: set new histograms with the following intervals: 535 + # read, flush: [0, 10), [10, 50), [50, 100), [100, +inf) 536 + # write: [0, 1000), [1000, 5000), [5000, +inf) 442 537 # 443 - # 2. Flush operation 538 + # -> { "execute": "block-latency-histogram-set", 539 + # "arguments": { "id": "drive0", 540 + # "boundaries": [10, 50, 100], 541 + # "boundaries-write": [1000, 5000] } } 542 + # <- { "return": {} } 444 543 # 445 - # { "event": "QUORUM_REPORT_BAD", 446 - # "data": { "node-name": "node0", "sector-num": 0, "sectors-count": 2097120, 447 - # "type": "flush", "error": "Broken pipe" }, 448 - # "timestamp": { "seconds": 1456406829, "microseconds": 291763 } } 544 + # Example: remove all latency histograms: 449 545 # 546 + # -> { "execute": "block-latency-histogram-set", 547 + # "arguments": { "id": "drive0" } } 548 + # <- { "return": {} } 450 549 ## 451 - { 'event': 'QUORUM_REPORT_BAD', 452 - 'data': { 'type': 'QuorumOpType', '*error': 'str', 'node-name': 'str', 453 - 'sector-num': 'int', 'sectors-count': 'int' } } 550 + { 'command': 'block-latency-histogram-set', 551 + 'data': {'id': 'str', 552 + '*boundaries': ['uint64'], 553 + '*boundaries-read': ['uint64'], 554 + '*boundaries-write': ['uint64'], 555 + '*boundaries-flush': ['uint64'] } }
+37
qapi/control.json
··· 216 216 # <- { "return": {} } 217 217 ## 218 218 { 'command': 'quit' } 219 + 220 + ## 221 + # @MonitorMode: 222 + # 223 + # An enumeration of monitor modes. 224 + # 225 + # @readline: HMP monitor (human-oriented command line interface) 226 + # 227 + # @control: QMP monitor (JSON-based machine interface) 228 + # 229 + # Since: 5.0 230 + ## 231 + { 'enum': 'MonitorMode', 'data': [ 'readline', 'control' ] } 232 + 233 + ## 234 + # @MonitorOptions: 235 + # 236 + # Options to be used for adding a new monitor. 237 + # 238 + # @id: Name of the monitor 239 + # 240 + # @mode: Selects the monitor mode (default: readline in the system 241 + # emulator, control in qemu-storage-daemon) 242 + # 243 + # @pretty: Enables pretty printing (QMP only) 244 + # 245 + # @chardev: Name of a character device to expose the monitor on 246 + # 247 + # Since: 5.0 248 + ## 249 + { 'struct': 'MonitorOptions', 250 + 'data': { 251 + '*id': 'str', 252 + '*mode': 'MonitorMode', 253 + '*pretty': 'bool', 254 + 'chardev': 'str' 255 + } }
+24
qapi/pragma.json
··· 1 + { 'pragma': { 'doc-required': true } } 2 + 3 + # Whitelists to permit QAPI rule violations; think twice before you 4 + # add to them! 5 + { 'pragma': { 6 + # Commands allowed to return a non-dictionary: 7 + 'returns-whitelist': [ 8 + 'human-monitor-command', 9 + 'qom-get', 10 + 'query-migrate-cache-size', 11 + 'query-tpm-models', 12 + 'query-tpm-types', 13 + 'ringbuf-read' ], 14 + 'name-case-whitelist': [ 15 + 'ACPISlotType', # DIMM, visible through query-acpi-ospm-status 16 + 'CpuInfoMIPS', # PC, visible through query-cpu 17 + 'CpuInfoTricore', # PC, visible through query-cpu 18 + 'BlockdevVmdkSubformat', # all members, to match VMDK spec spellings 19 + 'BlockdevVmdkAdapterType', # legacyESX, to match VMDK spec spellings 20 + 'QapiErrorClass', # all members, visible through errors 21 + 'UuidInfo', # UUID, visible through query-uuid 22 + 'X86CPURegister32', # all members, visible indirectly through qom-get 23 + 'CpuInfo' # CPU, visible through query-cpu 24 + ] } }
+1 -24
qapi/qapi-schema.json
··· 49 49 # 50 50 ## 51 51 52 - { 'pragma': { 'doc-required': true } } 53 - 54 - # Whitelists to permit QAPI rule violations; think twice before you 55 - # add to them! 56 - { 'pragma': { 57 - # Commands allowed to return a non-dictionary: 58 - 'returns-whitelist': [ 59 - 'human-monitor-command', 60 - 'qom-get', 61 - 'query-migrate-cache-size', 62 - 'query-tpm-models', 63 - 'query-tpm-types', 64 - 'ringbuf-read' ], 65 - 'name-case-whitelist': [ 66 - 'ACPISlotType', # DIMM, visible through query-acpi-ospm-status 67 - 'CpuInfoMIPS', # PC, visible through query-cpu 68 - 'CpuInfoTricore', # PC, visible through query-cpu 69 - 'BlockdevVmdkSubformat', # all members, to match VMDK spec spellings 70 - 'BlockdevVmdkAdapterType', # legacyESX, to match VMDK spec spellings 71 - 'QapiErrorClass', # all members, visible through errors 72 - 'UuidInfo', # UUID, visible through query-uuid 73 - 'X86CPURegister32', # all members, visible indirectly through qom-get 74 - 'CpuInfo' # CPU, visible through query-cpu 75 - ] } } 52 + { 'include': 'pragma.json' } 76 53 77 54 # Documentation generated with qapi-gen.py is in source order, with 78 55 # included sub-schemas inserted at the first include directive
+9 -3
qapi/qom.json
··· 210 210 # 211 211 # @id: the name of the new object 212 212 # 213 - # @props: a dictionary of properties to be passed to the backend 213 + # @props: a dictionary of properties to be passed to the backend. Deprecated 214 + # since 5.0, specify the properties on the top level instead. It is an 215 + # error to specify the same option both on the top level and in @props. 216 + # 217 + # Additional arguments depend on qom-type and are passed to the backend 218 + # unchanged. 214 219 # 215 220 # Returns: Nothing on success 216 221 # Error if @qom-type is not a valid class name ··· 221 226 # 222 227 # -> { "execute": "object-add", 223 228 # "arguments": { "qom-type": "rng-random", "id": "rng1", 224 - # "props": { "filename": "/dev/hwrng" } } } 229 + # "filename": "/dev/hwrng" } } 225 230 # <- { "return": {} } 226 231 # 227 232 ## 228 233 { 'command': 'object-add', 229 - 'data': {'qom-type': 'str', 'id': 'str', '*props': 'any'} } 234 + 'data': {'qom-type': 'str', 'id': 'str', '*props': 'any'}, 235 + 'gen': false } # so we can get the additional arguments 230 236 231 237 ## 232 238 # @object-del:
+1 -1
qapi/transaction.json
··· 5 5 # = Transactions 6 6 ## 7 7 8 - { 'include': 'block.json' } 8 + { 'include': 'block-core.json' } 9 9 10 10 ## 11 11 # @Abort:
+340
qemu-storage-daemon.c
··· 1 + /* 2 + * QEMU storage daemon 3 + * 4 + * Copyright (c) 2003-2008 Fabrice Bellard 5 + * Copyright (c) 2019 Kevin Wolf <kwolf@redhat.com> 6 + * 7 + * Permission is hereby granted, free of charge, to any person obtaining a copy 8 + * of this software and associated documentation files (the "Software"), to deal 9 + * in the Software without restriction, including without limitation the rights 10 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 + * copies of the Software, and to permit persons to whom the Software is 12 + * furnished to do so, subject to the following conditions: 13 + * 14 + * The above copyright notice and this permission notice shall be included in 15 + * all copies or substantial portions of the Software. 16 + * 17 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 + * THE SOFTWARE. 24 + */ 25 + 26 + #include "qemu/osdep.h" 27 + 28 + #include <getopt.h> 29 + 30 + #include "block/block.h" 31 + #include "block/nbd.h" 32 + #include "chardev/char.h" 33 + #include "crypto/init.h" 34 + #include "monitor/monitor.h" 35 + #include "monitor/monitor-internal.h" 36 + 37 + #include "qapi/error.h" 38 + #include "qapi/qapi-visit-block.h" 39 + #include "qapi/qapi-visit-block-core.h" 40 + #include "qapi/qapi-visit-control.h" 41 + #include "qapi/qmp/qdict.h" 42 + #include "qapi/qmp/qstring.h" 43 + #include "qapi/qobject-input-visitor.h" 44 + 45 + #include "qemu-common.h" 46 + #include "qemu-version.h" 47 + #include "qemu/config-file.h" 48 + #include "qemu/error-report.h" 49 + #include "qemu/help_option.h" 50 + #include "qemu/log.h" 51 + #include "qemu/main-loop.h" 52 + #include "qemu/module.h" 53 + #include "qemu/option.h" 54 + #include "qom/object_interfaces.h" 55 + 56 + #include "storage-daemon/qapi/qapi-commands.h" 57 + #include "storage-daemon/qapi/qapi-init-commands.h" 58 + 59 + #include "sysemu/runstate.h" 60 + #include "trace/control.h" 61 + 62 + static volatile bool exit_requested = false; 63 + 64 + void qemu_system_killed(int signal, pid_t pid) 65 + { 66 + exit_requested = true; 67 + } 68 + 69 + void qmp_quit(Error **errp) 70 + { 71 + exit_requested = true; 72 + } 73 + 74 + static void help(void) 75 + { 76 + printf( 77 + "Usage: %s [options]\n" 78 + "QEMU storage daemon\n" 79 + "\n" 80 + " -h, --help display this help and exit\n" 81 + " -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n" 82 + " specify tracing options\n" 83 + " -V, --version output version information and exit\n" 84 + "\n" 85 + " --blockdev [driver=]<driver>[,node-name=<N>][,discard=ignore|unmap]\n" 86 + " [,cache.direct=on|off][,cache.no-flush=on|off]\n" 87 + " [,read-only=on|off][,auto-read-only=on|off]\n" 88 + " [,force-share=on|off][,detect-zeroes=on|off|unmap]\n" 89 + " [,driver specific parameters...]\n" 90 + " configure a block backend\n" 91 + "\n" 92 + " --chardev <options> configure a character device backend\n" 93 + " (see the qemu(1) man page for possible options)\n" 94 + "\n" 95 + " --export [type=]nbd,device=<node-name>[,name=<export-name>]\n" 96 + " [,writable=on|off][,bitmap=<name>]\n" 97 + " export the specified block node over NBD\n" 98 + " (requires --nbd-server)\n" 99 + "\n" 100 + " --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n" 101 + " configure a QMP monitor\n" 102 + "\n" 103 + " --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>\n" 104 + " [,tls-creds=<id>][,tls-authz=<id>]\n" 105 + " --nbd-server addr.type=unix,addr.path=<path>\n" 106 + " [,tls-creds=<id>][,tls-authz=<id>]\n" 107 + " start an NBD server for exporting block nodes\n" 108 + "\n" 109 + " --object help list object types that can be added\n" 110 + " --object <type>,help list properties for the given object type\n" 111 + " --object <type>[,<property>=<value>...]\n" 112 + " create a new object of type <type>, setting\n" 113 + " properties in the order they are specified. Note\n" 114 + " that the 'id' property must be set.\n" 115 + " See the qemu(1) man page for documentation of the\n" 116 + " objects that can be added.\n" 117 + "\n" 118 + QEMU_HELP_BOTTOM "\n", 119 + error_get_progname()); 120 + } 121 + 122 + enum { 123 + OPTION_BLOCKDEV = 256, 124 + OPTION_CHARDEV, 125 + OPTION_EXPORT, 126 + OPTION_MONITOR, 127 + OPTION_NBD_SERVER, 128 + OPTION_OBJECT, 129 + }; 130 + 131 + extern QemuOptsList qemu_chardev_opts; 132 + 133 + static QemuOptsList qemu_object_opts = { 134 + .name = "object", 135 + .implied_opt_name = "qom-type", 136 + .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head), 137 + .desc = { 138 + { } 139 + }, 140 + }; 141 + 142 + static void init_qmp_commands(void) 143 + { 144 + qmp_init_marshal(&qmp_commands); 145 + qmp_register_command(&qmp_commands, "query-qmp-schema", 146 + qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG); 147 + 148 + QTAILQ_INIT(&qmp_cap_negotiation_commands); 149 + qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities", 150 + qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG); 151 + } 152 + 153 + static void init_export(BlockExport *export, Error **errp) 154 + { 155 + switch (export->type) { 156 + case BLOCK_EXPORT_TYPE_NBD: 157 + qmp_nbd_server_add(&export->u.nbd, errp); 158 + break; 159 + default: 160 + g_assert_not_reached(); 161 + } 162 + } 163 + 164 + static void process_options(int argc, char *argv[]) 165 + { 166 + int c; 167 + 168 + static const struct option long_options[] = { 169 + {"blockdev", required_argument, NULL, OPTION_BLOCKDEV}, 170 + {"chardev", required_argument, NULL, OPTION_CHARDEV}, 171 + {"export", required_argument, NULL, OPTION_EXPORT}, 172 + {"help", no_argument, NULL, 'h'}, 173 + {"monitor", required_argument, NULL, OPTION_MONITOR}, 174 + {"nbd-server", required_argument, NULL, OPTION_NBD_SERVER}, 175 + {"object", required_argument, NULL, OPTION_OBJECT}, 176 + {"trace", required_argument, NULL, 'T'}, 177 + {"version", no_argument, NULL, 'V'}, 178 + {0, 0, 0, 0} 179 + }; 180 + 181 + /* 182 + * In contrast to the system emulator, options are processed in the order 183 + * they are given on the command lines. This means that things must be 184 + * defined first before they can be referenced in another option. 185 + */ 186 + while ((c = getopt_long(argc, argv, "hT:V", long_options, NULL)) != -1) { 187 + switch (c) { 188 + case '?': 189 + exit(EXIT_FAILURE); 190 + case 'h': 191 + help(); 192 + exit(EXIT_SUCCESS); 193 + case 'T': 194 + { 195 + char *trace_file = trace_opt_parse(optarg); 196 + trace_init_file(trace_file); 197 + g_free(trace_file); 198 + break; 199 + } 200 + case 'V': 201 + printf("qemu-storage-daemon version " 202 + QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n"); 203 + exit(EXIT_SUCCESS); 204 + case OPTION_BLOCKDEV: 205 + { 206 + Visitor *v; 207 + BlockdevOptions *options; 208 + 209 + v = qobject_input_visitor_new_str(optarg, "driver", 210 + &error_fatal); 211 + 212 + visit_type_BlockdevOptions(v, NULL, &options, &error_fatal); 213 + visit_free(v); 214 + 215 + qmp_blockdev_add(options, &error_fatal); 216 + qapi_free_BlockdevOptions(options); 217 + break; 218 + } 219 + case OPTION_CHARDEV: 220 + { 221 + /* TODO This interface is not stable until we QAPIfy it */ 222 + QemuOpts *opts = qemu_opts_parse_noisily(&qemu_chardev_opts, 223 + optarg, true); 224 + if (opts == NULL) { 225 + exit(EXIT_FAILURE); 226 + } 227 + 228 + if (!qemu_chr_new_from_opts(opts, NULL, &error_fatal)) { 229 + /* No error, but NULL returned means help was printed */ 230 + exit(EXIT_SUCCESS); 231 + } 232 + qemu_opts_del(opts); 233 + break; 234 + } 235 + case OPTION_EXPORT: 236 + { 237 + Visitor *v; 238 + BlockExport *export; 239 + 240 + v = qobject_input_visitor_new_str(optarg, "type", &error_fatal); 241 + visit_type_BlockExport(v, NULL, &export, &error_fatal); 242 + visit_free(v); 243 + 244 + init_export(export, &error_fatal); 245 + qapi_free_BlockExport(export); 246 + break; 247 + } 248 + case OPTION_MONITOR: 249 + { 250 + Visitor *v; 251 + MonitorOptions *monitor; 252 + 253 + v = qobject_input_visitor_new_str(optarg, "chardev", 254 + &error_fatal); 255 + visit_type_MonitorOptions(v, NULL, &monitor, &error_fatal); 256 + visit_free(v); 257 + 258 + /* TODO Catch duplicate monitor IDs */ 259 + monitor_init(monitor, false, &error_fatal); 260 + qapi_free_MonitorOptions(monitor); 261 + break; 262 + } 263 + case OPTION_NBD_SERVER: 264 + { 265 + Visitor *v; 266 + NbdServerOptions *options; 267 + 268 + v = qobject_input_visitor_new_str(optarg, NULL, &error_fatal); 269 + visit_type_NbdServerOptions(v, NULL, &options, &error_fatal); 270 + visit_free(v); 271 + 272 + nbd_server_start_options(options, &error_fatal); 273 + qapi_free_NbdServerOptions(options); 274 + break; 275 + } 276 + case OPTION_OBJECT: 277 + { 278 + QemuOpts *opts; 279 + const char *type; 280 + QDict *args; 281 + QObject *ret_data = NULL; 282 + 283 + /* FIXME The keyval parser rejects 'help' arguments, so we must 284 + * unconditionall try QemuOpts first. */ 285 + opts = qemu_opts_parse(&qemu_object_opts, 286 + optarg, true, &error_fatal); 287 + type = qemu_opt_get(opts, "qom-type"); 288 + if (type && user_creatable_print_help(type, opts)) { 289 + exit(EXIT_SUCCESS); 290 + } 291 + qemu_opts_del(opts); 292 + 293 + args = keyval_parse(optarg, "qom-type", &error_fatal); 294 + qmp_object_add(args, &ret_data, &error_fatal); 295 + qobject_unref(args); 296 + qobject_unref(ret_data); 297 + break; 298 + } 299 + default: 300 + g_assert_not_reached(); 301 + } 302 + } 303 + if (optind != argc) { 304 + error_report("Unexpected argument: %s", argv[optind]); 305 + exit(EXIT_FAILURE); 306 + } 307 + } 308 + 309 + int main(int argc, char *argv[]) 310 + { 311 + #ifdef CONFIG_POSIX 312 + signal(SIGPIPE, SIG_IGN); 313 + #endif 314 + 315 + error_init(argv[0]); 316 + qemu_init_exec_dir(argv[0]); 317 + os_setup_signal_handling(); 318 + 319 + module_call_init(MODULE_INIT_QOM); 320 + module_call_init(MODULE_INIT_TRACE); 321 + qemu_add_opts(&qemu_trace_opts); 322 + qcrypto_init(&error_fatal); 323 + bdrv_init(); 324 + monitor_init_globals_core(); 325 + init_qmp_commands(); 326 + 327 + if (!trace_init_backends()) { 328 + return EXIT_FAILURE; 329 + } 330 + qemu_set_log(LOG_TRACE); 331 + 332 + qemu_init_main_loop(&error_fatal); 333 + process_options(argc, argv); 334 + 335 + while (!exit_requested) { 336 + main_loop_wait(false); 337 + } 338 + 339 + return EXIT_SUCCESS; 340 + }
+1
qom/Makefile.objs
··· 2 2 qom-obj-y += object_interfaces.o 3 3 4 4 common-obj-$(CONFIG_SOFTMMU) += qom-hmp-cmds.o qom-qmp-cmds.o 5 + storage-daemon-obj-y += qom-qmp-cmds.o
+35 -7
qom/qom-qmp-cmds.c
··· 14 14 */ 15 15 16 16 #include "qemu/osdep.h" 17 + #include "block/qdict.h" 17 18 #include "hw/qdev-core.h" 18 19 #include "qapi/error.h" 19 20 #include "qapi/qapi-commands-qdev.h" ··· 240 241 return prop_list; 241 242 } 242 243 243 - void qmp_object_add(const char *type, const char *id, 244 - bool has_props, QObject *props, Error **errp) 244 + void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp) 245 245 { 246 + QObject *props; 246 247 QDict *pdict; 247 248 Visitor *v; 248 249 Object *obj; 250 + const char *type; 251 + const char *id; 249 252 253 + type = qdict_get_try_str(qdict, "qom-type"); 254 + if (!type) { 255 + error_setg(errp, QERR_MISSING_PARAMETER, "qom-type"); 256 + return; 257 + } else { 258 + type = g_strdup(type); 259 + qdict_del(qdict, "qom-type"); 260 + } 261 + 262 + id = qdict_get_try_str(qdict, "id"); 263 + if (!id) { 264 + error_setg(errp, QERR_MISSING_PARAMETER, "id"); 265 + return; 266 + } else { 267 + id = g_strdup(id); 268 + qdict_del(qdict, "id"); 269 + } 270 + 271 + props = qdict_get(qdict, "props"); 250 272 if (props) { 251 273 pdict = qobject_to(QDict, props); 252 274 if (!pdict) { ··· 254 276 return; 255 277 } 256 278 qobject_ref(pdict); 257 - } else { 258 - pdict = qdict_new(); 279 + qdict_del(qdict, "props"); 280 + qdict_join(qdict, pdict, false); 281 + if (qdict_size(pdict) != 0) { 282 + error_setg(errp, "Option in 'props' conflicts with top level"); 283 + qobject_unref(pdict); 284 + return; 285 + } 286 + qobject_unref(pdict); 259 287 } 260 288 261 - v = qobject_input_visitor_new(QOBJECT(pdict)); 262 - obj = user_creatable_add_type(type, id, pdict, v, errp); 289 + v = qobject_input_visitor_new(QOBJECT(qdict)); 290 + obj = user_creatable_add_type(type, id, qdict, v, errp); 263 291 visit_free(v); 264 292 if (obj) { 265 293 object_unref(obj); 266 294 } 267 - qobject_unref(pdict); 295 + *ret_data = QOBJECT(qdict_new()); 268 296 } 269 297 270 298 void qmp_object_del(const char *id, Error **errp)
+5
scripts/qapi/gen.py
··· 44 44 return '' 45 45 46 46 def write(self, output_dir): 47 + # Include paths starting with ../ are used to reuse modules of the main 48 + # schema in specialised schemas. Don't overwrite the files that are 49 + # already generated for the main schema. 50 + if self.fname.startswith('../'): 51 + return 47 52 pathname = os.path.join(output_dir, self.fname) 48 53 odir = os.path.dirname(pathname) 49 54 if odir:
+1
storage-daemon/Makefile.objs
··· 1 + storage-daemon-obj-y += qapi/
+1
storage-daemon/qapi/Makefile.objs
··· 1 + storage-daemon-obj-y += qapi-commands.o qapi-init-commands.o qapi-introspect.o
+26
storage-daemon/qapi/qapi-schema.json
··· 1 + # -*- Mode: Python -*- 2 + 3 + # Note that modules are shared with the QEMU main schema under the assumption 4 + # that the storage daemon schema is a subset of the main schema. For the shared 5 + # modules, no code is generated here, but we reuse the code files generated 6 + # from the main schema. 7 + # 8 + # If you wish to extend the storage daemon schema to contain things that are 9 + # not in the main schema, be aware that array types of types defined in shared 10 + # modules are only generated if an array of the respective type is already used 11 + # in the main schema. Therefore, if you use such arrays, you may need to define 12 + # the array type in the main schema, even if it is unused outside of the 13 + # storage daemon. 14 + 15 + { 'include': '../../qapi/pragma.json' } 16 + 17 + { 'include': '../../qapi/block-core.json' } 18 + { 'include': '../../qapi/char.json' } 19 + { 'include': '../../qapi/common.json' } 20 + { 'include': '../../qapi/control.json' } 21 + { 'include': '../../qapi/crypto.json' } 22 + { 'include': '../../qapi/introspect.json' } 23 + { 'include': '../../qapi/job.json' } 24 + { 'include': '../../qapi/qom.json' } 25 + { 'include': '../../qapi/sockets.json' } 26 + { 'include': '../../qapi/transaction.json' }
+2
stubs/Makefile.objs
··· 1 + stub-obj-y += arch_type.o 1 2 stub-obj-y += bdrv-next-monitor-owned.o 2 3 stub-obj-y += blk-commit-all.o 3 4 stub-obj-y += blockdev-close-all-bdrv-states.o ··· 18 19 stub-obj-y += migr-blocker.o 19 20 stub-obj-y += change-state-handler.o 20 21 stub-obj-y += monitor.o 22 + stub-obj-y += monitor-core.o 21 23 stub-obj-y += notify-event.o 22 24 stub-obj-y += qtest.o 23 25 stub-obj-y += replay.o
+4
stubs/arch_type.c
··· 1 + #include "qemu/osdep.h" 2 + #include "sysemu/arch_init.h" 3 + 4 + const uint32_t arch_type = QEMU_ARCH_NONE;
+21
stubs/monitor-core.c
··· 1 + #include "qemu/osdep.h" 2 + #include "monitor/monitor.h" 3 + #include "qemu-common.h" 4 + #include "qapi/qapi-emit-events.h" 5 + 6 + __thread Monitor *cur_mon; 7 + 8 + void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp) 9 + { 10 + } 11 + 12 + void qapi_event_emit(QAPIEvent event, QDict *qdict) 13 + { 14 + } 15 + 16 + int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) 17 + { 18 + abort(); 19 + } 20 + 21 +
+3 -14
stubs/monitor.c
··· 1 1 #include "qemu/osdep.h" 2 2 #include "qapi/error.h" 3 - #include "qapi/qapi-emit-events.h" 4 3 #include "monitor/monitor.h" 5 - 6 - __thread Monitor *cur_mon; 7 - 8 - int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) 9 - { 10 - abort(); 11 - } 4 + #include "../monitor/monitor-internal.h" 12 5 13 6 int monitor_get_fd(Monitor *mon, const char *name, Error **errp) 14 7 { ··· 16 9 return -1; 17 10 } 18 11 19 - void monitor_init_qmp(Chardev *chr, bool pretty) 20 - { 21 - } 22 - 23 - void monitor_init_hmp(Chardev *chr, bool use_readline) 12 + void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp) 24 13 { 25 14 } 26 15 27 - void qapi_event_emit(QAPIEvent event, QDict *qdict) 16 + void monitor_fdsets_cleanup(void) 28 17 { 29 18 }
+53
tests/qemu-iotests/026
··· 30 30 { 31 31 _cleanup_test_img 32 32 rm "$TEST_DIR/blkdebug.conf" 33 + rm -f "$TEST_IMG.data_file" 33 34 } 34 35 trap "_cleanup; exit \$status" 0 1 2 3 15 35 36 ··· 216 217 # block is actually written back 217 218 _make_test_img 64M 218 219 $QEMU_IO -c "write 0 1M" -c "write 0 1M" "$BLKDBG_TEST_IMG" | _filter_qemu_io 220 + _check_test_img 221 + 222 + echo 223 + echo === Avoid freeing preallocated zero clusters on failure === 224 + echo 225 + 226 + cat > "$TEST_DIR/blkdebug.conf" <<EOF 227 + [inject-error] 228 + event = "write_aio" 229 + errno = "5" 230 + once = "on" 231 + EOF 232 + 233 + _make_test_img $CLUSTER_SIZE 234 + # Create a preallocated zero cluster 235 + $QEMU_IO -c "write 0 $CLUSTER_SIZE" -c "write -z 0 $CLUSTER_SIZE" "$TEST_IMG" \ 236 + | _filter_qemu_io 237 + # Try to overwrite it (prompting an I/O error from blkdebug), thus 238 + # triggering the alloc abort code 239 + $QEMU_IO -c "write 0 $CLUSTER_SIZE" "$BLKDBG_TEST_IMG" | _filter_qemu_io 240 + 241 + _check_test_img 242 + 243 + echo 244 + echo === Avoid freeing external data clusters on failure === 245 + echo 246 + 247 + # Similar test as the last one, except we test what happens when there 248 + # is an error when writing to an external data file instead of when 249 + # writing to a preallocated zero cluster 250 + _make_test_img -o "data_file=$TEST_IMG.data_file" $CLUSTER_SIZE 251 + 252 + # Put blkdebug above the data-file, and a raw node on top of that so 253 + # that blkdebug will see a write_aio event and emit an error 254 + $QEMU_IO -c "write 0 $CLUSTER_SIZE" \ 255 + "json:{ 256 + 'driver': 'qcow2', 257 + 'file': { 'driver': 'file', 'filename': '$TEST_IMG' }, 258 + 'data-file': { 259 + 'driver': 'raw', 260 + 'file': { 261 + 'driver': 'blkdebug', 262 + 'config': '$TEST_DIR/blkdebug.conf', 263 + 'image': { 264 + 'driver': 'file', 265 + 'filename': '$TEST_IMG.data_file' 266 + } 267 + } 268 + } 269 + }" \ 270 + | _filter_qemu_io 271 + 219 272 _check_test_img 220 273 221 274 # success, all done
+16
tests/qemu-iotests/026.out
··· 643 643 wrote 1048576/1048576 bytes at offset 0 644 644 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 645 645 No errors were found on the image. 646 + 647 + === Avoid freeing preallocated zero clusters on failure === 648 + 649 + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024 650 + wrote 1024/1024 bytes at offset 0 651 + 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 652 + wrote 1024/1024 bytes at offset 0 653 + 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 654 + write failed: Input/output error 655 + No errors were found on the image. 656 + 657 + === Avoid freeing external data clusters on failure === 658 + 659 + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024 data_file=TEST_DIR/t.IMGFMT.data_file 660 + write failed: Input/output error 661 + No errors were found on the image. 646 662 *** done
+16
tests/qemu-iotests/026.out.nocache
··· 651 651 wrote 1048576/1048576 bytes at offset 0 652 652 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 653 653 No errors were found on the image. 654 + 655 + === Avoid freeing preallocated zero clusters on failure === 656 + 657 + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024 658 + wrote 1024/1024 bytes at offset 0 659 + 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 660 + wrote 1024/1024 bytes at offset 0 661 + 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 662 + write failed: Input/output error 663 + No errors were found on the image. 664 + 665 + === Avoid freeing external data clusters on failure === 666 + 667 + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024 data_file=TEST_DIR/t.IMGFMT.data_file 668 + write failed: Input/output error 669 + No errors were found on the image. 654 670 *** done
+35 -10
tests/qemu-iotests/245
··· 970 970 self.assertEqual(self.get_node('hd1'), None) 971 971 self.assert_qmp(self.get_node('hd2'), 'ro', True) 972 972 973 - # We don't allow setting a backing file that uses a different AioContext 974 - def test_iothreads(self): 973 + def run_test_iothreads(self, iothread_a, iothread_b, errmsg = None): 975 974 opts = hd_opts(0) 976 975 result = self.vm.qmp('blockdev-add', conv_keys = False, **opts) 977 976 self.assert_qmp(result, 'return', {}) ··· 986 985 result = self.vm.qmp('object-add', qom_type='iothread', id='iothread1') 987 986 self.assert_qmp(result, 'return', {}) 988 987 989 - result = self.vm.qmp('x-blockdev-set-iothread', node_name='hd0', iothread='iothread0') 988 + result = self.vm.qmp('device_add', driver='virtio-scsi', id='scsi0', 989 + iothread=iothread_a) 990 + self.assert_qmp(result, 'return', {}) 991 + 992 + result = self.vm.qmp('device_add', driver='virtio-scsi', id='scsi1', 993 + iothread=iothread_b) 990 994 self.assert_qmp(result, 'return', {}) 991 995 992 - self.reopen(opts, {'backing': 'hd2'}, "Cannot use a new backing file with a different AioContext") 996 + if iothread_a: 997 + result = self.vm.qmp('device_add', driver='scsi-hd', drive='hd0', 998 + share_rw=True, bus="scsi0.0") 999 + self.assert_qmp(result, 'return', {}) 1000 + 1001 + if iothread_b: 1002 + result = self.vm.qmp('device_add', driver='scsi-hd', drive='hd2', 1003 + share_rw=True, bus="scsi1.0") 1004 + self.assert_qmp(result, 'return', {}) 1005 + 1006 + # Attaching the backing file may or may not work 1007 + self.reopen(opts, {'backing': 'hd2'}, errmsg) 1008 + 1009 + # But removing the backing file should always work 1010 + self.reopen(opts, {'backing': None}) 993 1011 994 - result = self.vm.qmp('x-blockdev-set-iothread', node_name='hd2', iothread='iothread1') 995 - self.assert_qmp(result, 'return', {}) 1012 + self.vm.shutdown() 996 1013 997 - self.reopen(opts, {'backing': 'hd2'}, "Cannot use a new backing file with a different AioContext") 1014 + # We don't allow setting a backing file that uses a different AioContext if 1015 + # neither of them can switch to the other AioContext 1016 + def test_iothreads_error(self): 1017 + self.run_test_iothreads('iothread0', 'iothread1', 1018 + "Cannot change iothread of active block backend") 998 1019 999 - result = self.vm.qmp('x-blockdev-set-iothread', node_name='hd2', iothread='iothread0') 1000 - self.assert_qmp(result, 'return', {}) 1020 + def test_iothreads_compatible_users(self): 1021 + self.run_test_iothreads('iothread0', 'iothread0') 1022 + 1023 + def test_iothreads_switch_backing(self): 1024 + self.run_test_iothreads('iothread0', None) 1001 1025 1002 - self.reopen(opts, {'backing': 'hd2'}) 1026 + def test_iothreads_switch_overlay(self): 1027 + self.run_test_iothreads(None, 'iothread0') 1003 1028 1004 1029 if __name__ == '__main__': 1005 1030 iotests.main(supported_fmts=["qcow2"],
+2 -2
tests/qemu-iotests/245.out
··· 1 - .................. 1 + ..................... 2 2 ---------------------------------------------------------------------- 3 - Ran 18 tests 3 + Ran 21 tests 4 4 5 5 OK 6 6 {"execute": "job-finalize", "arguments": {"id": "commit0"}}
+2 -2
tests/test-util-sockets.c
··· 71 71 */ 72 72 __thread Monitor *cur_mon; 73 73 int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); } 74 - void monitor_init_qmp(Chardev *chr, bool pretty) {} 75 - void monitor_init_hmp(Chardev *chr, bool use_readline) {} 74 + void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp) {} 75 + void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp) {} 76 76 77 77 78 78 static void test_socket_fd_pass_name_good(void)