diff options
95 files changed, 2192 insertions, 1507 deletions
diff --git a/block.c b/block.c index f377158c42..c5b887cec1 100644 --- a/block.c +++ b/block.c @@ -670,14 +670,48 @@ out: int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp) { + QemuOpts *protocol_opts; BlockDriver *drv; + QDict *qdict; + int ret; drv = bdrv_find_protocol(filename, true, errp); if (drv == NULL) { return -ENOENT; } - return bdrv_create(drv, filename, opts, errp); + if (!drv->create_opts) { + error_setg(errp, "Driver '%s' does not support image creation", + drv->format_name); + return -ENOTSUP; + } + + /* + * 'opts' contains a QemuOptsList with a combination of format and protocol + * default values. + * + * The format properly removes its options, but the default values remain + * in 'opts->list'. So if the protocol has options with the same name + * (e.g. rbd has 'cluster_size' as qcow2), it will see the default values + * of the format, since for overlapping options, the format wins. + * + * To avoid this issue, lets convert QemuOpts to QDict, in this way we take + * only the set options, and then convert it back to QemuOpts, using the + * create_opts of the protocol. So the new QemuOpts, will contain only the + * protocol defaults. + */ + qdict = qemu_opts_to_qdict(opts, NULL); + protocol_opts = qemu_opts_from_qdict(drv->create_opts, qdict, errp); + if (protocol_opts == NULL) { + ret = -EINVAL; + goto out; + } + + ret = bdrv_create(drv, filename, protocol_opts, errp); +out: + qemu_opts_del(protocol_opts); + qobject_unref(qdict); + return ret; } int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp) diff --git a/block/curl.c b/block/curl.c index 4ff895df8f..50e741a0d7 100644 --- a/block/curl.c +++ b/block/curl.c @@ -78,8 +78,7 @@ typedef struct CURLAIOCB { typedef struct CURLSocket { int fd; - struct CURLState *state; - QLIST_ENTRY(CURLSocket) next; + struct BDRVCURLState *s; } CURLSocket; typedef struct CURLState @@ -87,7 +86,6 @@ typedef struct CURLState struct BDRVCURLState *s; CURLAIOCB *acb[CURL_NUM_ACB]; CURL *curl; - QLIST_HEAD(, CURLSocket) sockets; char *orig_buf; uint64_t buf_start; size_t buf_off; @@ -102,6 +100,7 @@ typedef struct BDRVCURLState { QEMUTimer timer; uint64_t len; CURLState states[CURL_NUM_STATES]; + GHashTable *sockets; /* GINT_TO_POINTER(fd) -> socket */ char *url; size_t readahead_size; bool sslverify; @@ -120,6 +119,21 @@ typedef struct BDRVCURLState { static void curl_clean_state(CURLState *s); static void curl_multi_do(void *arg); +static gboolean curl_drop_socket(void *key, void *value, void *opaque) +{ + CURLSocket *socket = value; + BDRVCURLState *s = socket->s; + + aio_set_fd_handler(s->aio_context, socket->fd, false, + NULL, NULL, NULL, NULL); + return true; +} + +static void curl_drop_all_sockets(GHashTable *sockets) +{ + g_hash_table_foreach_remove(sockets, curl_drop_socket, NULL); +} + /* Called from curl_multi_do_locked, with s->mutex held. */ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque) { @@ -147,16 +161,12 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state); s = state->s; - QLIST_FOREACH(socket, &state->sockets, next) { - if (socket->fd == fd) { - break; - } - } + socket = g_hash_table_lookup(s->sockets, GINT_TO_POINTER(fd)); if (!socket) { socket = g_new0(CURLSocket, 1); socket->fd = fd; - socket->state = state; - QLIST_INSERT_HEAD(&state->sockets, socket, next); + socket->s = s; + g_hash_table_insert(s->sockets, GINT_TO_POINTER(fd), socket); } trace_curl_sock_cb(action, (int)fd); @@ -180,8 +190,7 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, } if (action == CURL_POLL_REMOVE) { - QLIST_REMOVE(socket, next); - g_free(socket); + g_hash_table_remove(s->sockets, GINT_TO_POINTER(fd)); } return 0; @@ -385,7 +394,7 @@ static void curl_multi_check_completion(BDRVCURLState *s) /* Called with s->mutex held. */ static void curl_multi_do_locked(CURLSocket *socket) { - BDRVCURLState *s = socket->state->s; + BDRVCURLState *s = socket->s; int running; int r; @@ -401,7 +410,7 @@ static void curl_multi_do_locked(CURLSocket *socket) static void curl_multi_do(void *arg) { CURLSocket *socket = arg; - BDRVCURLState *s = socket->state->s; + BDRVCURLState *s = socket->s; qemu_mutex_lock(&s->mutex); curl_multi_do_locked(socket); @@ -498,7 +507,6 @@ static int curl_init_state(BDRVCURLState *s, CURLState *state) #endif } - QLIST_INIT(&state->sockets); state->s = s; return 0; @@ -515,13 +523,6 @@ static void curl_clean_state(CURLState *s) if (s->s->multi) curl_multi_remove_handle(s->s->multi, s->curl); - while (!QLIST_EMPTY(&s->sockets)) { - CURLSocket *socket = QLIST_FIRST(&s->sockets); - - QLIST_REMOVE(socket, next); - g_free(socket); - } - s->in_use = 0; qemu_co_enter_next(&s->s->free_state_waitq, &s->s->mutex); @@ -539,6 +540,7 @@ static void curl_detach_aio_context(BlockDriverState *bs) int i; WITH_QEMU_LOCK_GUARD(&s->mutex) { + curl_drop_all_sockets(s->sockets); for (i = 0; i < CURL_NUM_STATES; i++) { if (s->states[i].in_use) { curl_clean_state(&s->states[i]); @@ -745,6 +747,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, qemu_co_queue_init(&s->free_state_waitq); s->aio_context = bdrv_get_aio_context(bs); s->url = g_strdup(file); + s->sockets = g_hash_table_new_full(NULL, NULL, NULL, g_free); qemu_mutex_lock(&s->mutex); state = curl_find_state(s); qemu_mutex_unlock(&s->mutex); @@ -818,6 +821,8 @@ out_noclean: g_free(s->username); g_free(s->proxyusername); g_free(s->proxypassword); + curl_drop_all_sockets(s->sockets); + g_hash_table_destroy(s->sockets); qemu_opts_del(opts); return -EINVAL; } @@ -916,6 +921,7 @@ static void curl_close(BlockDriverState *bs) curl_detach_aio_context(bs); qemu_mutex_destroy(&s->mutex); + g_hash_table_destroy(s->sockets); g_free(s->cookie); g_free(s->url); g_free(s->username); diff --git a/block/export/vhost-user-blk-server.c b/block/export/vhost-user-blk-server.c index cb5d896b7b..fa06996d37 100644 --- a/block/export/vhost-user-blk-server.c +++ b/block/export/vhost-user-blk-server.c @@ -345,8 +345,7 @@ static uint64_t vu_blk_get_features(VuDev *dev) static uint64_t vu_blk_get_protocol_features(VuDev *dev) { - return 1ull << VHOST_USER_PROTOCOL_F_CONFIG | - 1ull << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD; + return 1ull << VHOST_USER_PROTOCOL_F_CONFIG; } static int diff --git a/block/stream.c b/block/stream.c index 1fa742b0db..97bee482dc 100644 --- a/block/stream.c +++ b/block/stream.c @@ -206,7 +206,7 @@ void stream_start(const char *job_id, BlockDriverState *bs, const char *filter_node_name, Error **errp) { - StreamBlockJob *s; + StreamBlockJob *s = NULL; BlockDriverState *iter; bool bs_read_only; int basic_flags = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED; @@ -214,6 +214,7 @@ void stream_start(const char *job_id, BlockDriverState *bs, BlockDriverState *cor_filter_bs = NULL; BlockDriverState *above_base; QDict *opts; + int ret; assert(!(base && bottom)); assert(!(backing_file_str && bottom)); @@ -303,7 +304,7 @@ void stream_start(const char *job_id, BlockDriverState *bs, * queried only at the job start and then cached. */ if (block_job_add_bdrv(&s->common, "active node", bs, 0, - basic_flags | BLK_PERM_WRITE, &error_abort)) { + basic_flags | BLK_PERM_WRITE, errp)) { goto fail; } @@ -320,8 +321,11 @@ void stream_start(const char *job_id, BlockDriverState *bs, for (iter = bdrv_filter_or_cow_bs(bs); iter != base; iter = bdrv_filter_or_cow_bs(iter)) { - block_job_add_bdrv(&s->common, "intermediate node", iter, 0, - basic_flags, &error_abort); + ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0, + basic_flags, errp); + if (ret < 0) { + goto fail; + } } s->base_overlay = base_overlay; @@ -337,6 +341,9 @@ void stream_start(const char *job_id, BlockDriverState *bs, return; fail: + if (s) { + job_early_fail(&s->common.job); + } if (cor_filter_bs) { bdrv_cor_filter_drop(cor_filter_bs); } diff --git a/blockdev.c b/blockdev.c index 5cc7c7effe..cf70bb4e43 100644 --- a/blockdev.c +++ b/blockdev.c @@ -239,19 +239,10 @@ DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) return NULL; } -void drive_mark_claimed_by_board(void) -{ - BlockBackend *blk; - DriveInfo *dinfo; - - for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { - dinfo = blk_legacy_dinfo(blk); - if (dinfo && blk_get_attached_dev(blk)) { - dinfo->claimed_by_board = true; - } - } -} - +/* + * Check board claimed all -drive that are meant to be claimed. + * Fatal error if any remain unclaimed. + */ void drive_check_orphaned(void) { BlockBackend *blk; @@ -261,7 +252,17 @@ void drive_check_orphaned(void) for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { dinfo = blk_legacy_dinfo(blk); - if (dinfo->is_default || dinfo->type == IF_NONE) { + /* + * Ignore default drives, because we create certain default + * drives unconditionally, then leave them unclaimed. Not the + * users fault. + * Ignore IF_VIRTIO, because it gets desugared into -device, + * so we can leave failing to -device. + * Ignore IF_NONE, because leaving unclaimed IF_NONE remains + * available for device_add is a feature. + */ + if (dinfo->is_default || dinfo->type == IF_VIRTIO + || dinfo->type == IF_NONE) { continue; } if (!blk_get_attached_dev(blk)) { @@ -272,14 +273,6 @@ void drive_check_orphaned(void) if_name[dinfo->type], dinfo->bus, dinfo->unit); loc_pop(&loc); orphans = true; - continue; - } - if (!dinfo->claimed_by_board && dinfo->type != IF_VIRTIO) { - loc_push_none(&loc); - qemu_opts_loc_restore(dinfo->opts); - warn_report("bogus if=%s is deprecated, use if=none", - if_name[dinfo->type]); - loc_pop(&loc); } } diff --git a/chardev/char.c b/chardev/char.c index 97cafd6849..140d6d9d36 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -534,9 +534,10 @@ static const ChardevClass *char_get_class(const char *driver, Error **errp) return cc; } -static const struct ChardevAlias { +static struct ChardevAlias { const char *typename; const char *alias; + bool deprecation_warning_printed; } chardev_alias_table[] = { #ifdef HAVE_CHARDEV_PARPORT { "parallel", "parport" }, @@ -565,16 +566,12 @@ chardev_class_foreach(ObjectClass *klass, void *opaque) } static void -chardev_name_foreach(void (*fn)(const char *name, void *opaque), void *opaque) +chardev_name_foreach(void (*fn)(const char *name, void *opaque), + void *opaque) { ChadevClassFE fe = { .fn = fn, .opaque = opaque }; - int i; object_class_foreach(chardev_class_foreach, TYPE_CHARDEV, false, &fe); - - for (i = 0; i < (int)ARRAY_SIZE(chardev_alias_table); i++) { - fn(chardev_alias_table[i].alias, opaque); - } } static void @@ -590,6 +587,11 @@ static const char *chardev_alias_translate(const char *name) int i; for (i = 0; i < (int)ARRAY_SIZE(chardev_alias_table); i++) { if (g_strcmp0(chardev_alias_table[i].alias, name) == 0) { + if (!chardev_alias_table[i].deprecation_warning_printed) { + warn_report("The alias '%s' is deprecated, use '%s' instead", + name, chardev_alias_table[i].typename); + chardev_alias_table[i].deprecation_warning_printed = true; + } return chardev_alias_table[i].typename; } } @@ -801,8 +803,9 @@ static void qmp_prepend_backend(const char *name, void *opaque) { ChardevBackendInfoList **list = opaque; - ChardevBackendInfo *value = g_new0(ChardevBackendInfo, 1); + ChardevBackendInfo *value; + value = g_new0(ChardevBackendInfo, 1); value->name = g_strdup(name); QAPI_LIST_PREPEND(*list, value); } diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index d5e80d66eb..67c98dcaa0 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -46,6 +46,12 @@ needs two devices (``-device intel-hda -device hda-duplex``) and ``pcspk`` which can be activated using ``-machine pcspk-audiodev=<name>``. +``-chardev`` backend aliases ``tty`` and ``parport`` (since 6.0) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +``tty`` and ``parport`` are aliases that will be removed. Instead, the +actual backend names ``serial`` and ``parallel`` should be used. + RISC-V ``-bios`` (since 5.1) '''''''''''''''''''''''''''' @@ -65,39 +71,6 @@ QEMU 5.1 has three options: to the user to load all the images they need. 3. ``-bios <file>`` - Tells QEMU to load the specified file as the firmwrae. -``Configuring floppies with ``-global`` -''''''''''''''''''''''''''''''''''''''' - -Use ``-device floppy,...`` instead: -:: - - -global isa-fdc.driveA=... - -global sysbus-fdc.driveA=... - -global SUNW,fdtwo.drive=... - -become -:: - - -device floppy,unit=0,drive=... - -and -:: - - -global isa-fdc.driveB=... - -global sysbus-fdc.driveB=... - -become -:: - - -device floppy,unit=1,drive=... - -``-drive`` with bogus interface type -'''''''''''''''''''''''''''''''''''' - -Drives with interface types other than ``if=none`` are for onboard -devices. It is possible to use drives the board doesn't pick up with --device. This usage is now deprecated. Use ``if=none`` instead. - Short-form boolean options (since 6.0) '''''''''''''''''''''''''''''''''''''' @@ -153,6 +126,26 @@ the process listing. This is replaced by the new ``password-secret`` option which lets the password be securely provided on the command line using a ``secret`` object instance. +``opened`` property of ``rng-*`` objects (since 6.0.0) +'''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The only effect of specifying ``opened=on`` in the command line or QMP +``object-add`` is that the device is opened immediately, possibly before all +other options have been processed. This will either have no effect (if +``opened`` was the last option) or cause errors. The property is therefore +useless and should not be specified. + +``loaded`` property of ``secret`` and ``secret_keyring`` objects (since 6.0.0) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The only effect of specifying ``loaded=on`` in the command line or QMP +``object-add`` is that the secret is loaded immediately, possibly before all +other options have been processed. This will either have no effect (if +``loaded`` was the last option) or cause options to be effectively ignored as +if they were not given. The property is therefore useless and should not be +specified. + + QEMU Machine Protocol (QMP) commands ------------------------------------ @@ -186,11 +179,6 @@ Use argument value ``null`` instead. Use arguments ``base-node`` and ``top-node`` instead. -``object-add`` option ``props`` (since 5.0) -''''''''''''''''''''''''''''''''''''''''''' - -Specify the properties for the object as top-level arguments instead. - ``nbd-server-add`` and ``nbd-server-remove`` (since 5.2) '''''''''''''''''''''''''''''''''''''''''''''''''''''''' diff --git a/docs/system/removed-features.rst b/docs/system/removed-features.rst index bff16b7b05..f28387f183 100644 --- a/docs/system/removed-features.rst +++ b/docs/system/removed-features.rst @@ -64,6 +64,63 @@ The 'file' driver for drives is no longer appropriate for character or host devices and will only accept regular files (S_IFREG). The correct driver for these file types is 'host_cdrom' or 'host_device' as appropriate. +Floppy controllers' drive properties (removed in 6.0) +''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Use ``-device floppy,...`` instead. When configuring onboard floppy +controllers +:: + + -global isa-fdc.driveA=... + -global sysbus-fdc.driveA=... + -global SUNW,fdtwo.drive=... + +become +:: + + -device floppy,unit=0,drive=... + +and +:: + + -global isa-fdc.driveB=... + -global sysbus-fdc.driveB=... + +become +:: + + -device floppy,unit=1,drive=... + +When plugging in a floppy controller +:: + + -device isa-fdc,...,driveA=... + +becomes +:: + + -device isa-fdc,... + -device floppy,unit=0,drive=... + +and +:: + + -device isa-fdc,...,driveB=... + +becomes +:: + + -device isa-fdc,... + -device floppy,unit=1,drive=... + +``-drive`` with bogus interface type (removed in 6.0) +''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Drives with interface types other than ``if=none`` are for onboard +devices. Drives the board doesn't pick up can no longer be used with +-device. Use ``if=none`` instead. + + QEMU Machine Protocol (QMP) commands ------------------------------------ @@ -143,6 +200,11 @@ field of the ``BlockDeviceInfo`` struct should be used instead, which is the type of the ``inserted`` field in query-block replies, as well as the type of array items in query-named-block-nodes. +``object-add`` option ``props`` (removed in 6.0) +'''''''''''''''''''''''''''''''''''''''''''''''' + +Specify the properties for the object as top-level arguments instead. + Human Monitor Protocol (HMP) commands ------------------------------------- diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst index b615aa8419..c9efcfaefc 100644 --- a/docs/tools/qemu-img.rst +++ b/docs/tools/qemu-img.rst @@ -404,7 +404,7 @@ Command description: The following table sumarizes all exit codes of the compare subcommand: 0 - Images are identical + Images are identical (or requested help was printed) 1 Images differ 2 diff --git a/hmp-commands.hx b/hmp-commands.hx index 2bbe133bb6..9b88c45174 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1292,7 +1292,7 @@ ERST { .name = "object_add", - .args_type = "object:O", + .args_type = "object:S", .params = "[qom-type=]type,id=str[,prop=value][,...]", .help = "create QOM object", .cmd = hmp_object_add, diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c index b72772bc82..8db6cfd47f 100644 --- a/hw/arm/xilinx_zynq.c +++ b/hw/arm/xilinx_zynq.c @@ -231,7 +231,7 @@ static void zynq_init(MachineState *machine) clock_set_hz(zynq_machine->ps_clk, PS_CLK_FREQUENCY); /* Create slcr, keep a pointer to connect clocks */ - slcr = qdev_new("xilinx,zynq_slcr"); + slcr = qdev_new("xilinx-zynq_slcr"); qdev_connect_clock_in(slcr, "ps_clk", zynq_machine->ps_clk); sysbus_realize_and_unref(SYS_BUS_DEVICE(slcr), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(slcr), 0, 0xF8000000); diff --git a/hw/audio/cs4231.c b/hw/audio/cs4231.c index 209c05a0a0..aefc3edea1 100644 --- a/hw/audio/cs4231.c +++ b/hw/audio/cs4231.c @@ -37,7 +37,7 @@ #define CS_DREGS 32 #define CS_MAXDREG (CS_DREGS - 1) -#define TYPE_CS4231 "SUNW,CS4231" +#define TYPE_CS4231 "sun-CS4231" typedef struct CSState CSState; DECLARE_INSTANCE_CHECKER(CSState, CS4231, TYPE_CS4231) diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 198940e737..82afda7f3a 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -870,7 +870,6 @@ struct FDCtrl { uint8_t num_floppies; FDrive drives[MAX_FD]; struct { - BlockBackend *blk; FloppyDriveType type; } qdev_for_drives[MAX_FD]; int reset_sensei; @@ -2512,64 +2511,6 @@ void isa_fdc_init_drives(ISADevice *fdc, DriveInfo **fds) fdctrl_init_drives(&ISA_FDC(fdc)->state.bus, fds); } -static void fdctrl_connect_drives(FDCtrl *fdctrl, DeviceState *fdc_dev, - Error **errp) -{ - unsigned int i; - FDrive *drive; - DeviceState *dev; - BlockBackend *blk; - bool ok; - const char *fdc_name, *drive_suffix; - - for (i = 0; i < MAX_FD; i++) { - drive = &fdctrl->drives[i]; - drive->fdctrl = fdctrl; - - /* If the drive is not present, we skip creating the qdev device, but - * still have to initialise the controller. */ - blk = fdctrl->qdev_for_drives[i].blk; - if (!blk) { - fd_init(drive); - fd_revalidate(drive); - continue; - } - - fdc_name = object_get_typename(OBJECT(fdc_dev)); - drive_suffix = !strcmp(fdc_name, "SUNW,fdtwo") ? "" : i ? "B" : "A"; - warn_report("warning: property %s.drive%s is deprecated", - fdc_name, drive_suffix); - error_printf("Use -device floppy,unit=%d,drive=... instead.\n", i); - - dev = qdev_new("floppy"); - qdev_prop_set_uint32(dev, "unit", i); - qdev_prop_set_enum(dev, "drive-type", fdctrl->qdev_for_drives[i].type); - - /* - * Hack alert: we move the backend from the floppy controller - * device to the floppy device. We first need to detach the - * controller, or else floppy_create()'s qdev_prop_set_drive() - * will die when it attaches floppy device. We also need to - * take another reference so that blk_detach_dev() doesn't - * free blk while we still need it. - * - * The hack is probably a bad idea. - */ - blk_ref(blk); - blk_detach_dev(blk, fdc_dev); - fdctrl->qdev_for_drives[i].blk = NULL; - ok = qdev_prop_set_drive_err(dev, "drive", blk, errp); - blk_unref(blk); - if (!ok) { - return; - } - - if (!qdev_realize_and_unref(dev, &fdctrl->bus.bus, errp)) { - return; - } - } -} - void fdctrl_init_sysbus(qemu_irq irq, int dma_chann, hwaddr mmio_base, DriveInfo **fds) { @@ -2596,7 +2537,7 @@ void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base, DeviceState *dev; FDCtrlSysBus *sys; - dev = qdev_new("SUNW,fdtwo"); + dev = qdev_new("sun-fdtwo"); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sys = SYSBUS_FDC(dev); sysbus_connect_irq(SYS_BUS_DEVICE(sys), 0, irq); @@ -2610,6 +2551,7 @@ static void fdctrl_realize_common(DeviceState *dev, FDCtrl *fdctrl, Error **errp) { int i, j; + FDrive *drive; static int command_tables_inited = 0; if (fdctrl->fallback == FLOPPY_DRIVE_TYPE_AUTO) { @@ -2649,7 +2591,13 @@ static void fdctrl_realize_common(DeviceState *dev, FDCtrl *fdctrl, } floppy_bus_create(fdctrl, &fdctrl->bus, dev); - fdctrl_connect_drives(fdctrl, dev, errp); + + for (i = 0; i < MAX_FD; i++) { + drive = &fdctrl->drives[i]; + drive->fdctrl = fdctrl; + fd_init(drive); + fd_revalidate(drive); + } } static const MemoryRegionPortio fdc_portio_list[] = { @@ -2882,8 +2830,6 @@ static Property isa_fdc_properties[] = { DEFINE_PROP_UINT32("iobase", FDCtrlISABus, iobase, 0x3f0), DEFINE_PROP_UINT32("irq", FDCtrlISABus, irq, 6), DEFINE_PROP_UINT32("dma", FDCtrlISABus, dma, 2), - DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.qdev_for_drives[0].blk), - DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.qdev_for_drives[1].blk), DEFINE_PROP_SIGNED("fdtypeA", FDCtrlISABus, state.qdev_for_drives[0].type, FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type, FloppyDriveType), @@ -2941,8 +2887,6 @@ static const VMStateDescription vmstate_sysbus_fdc ={ }; static Property sysbus_fdc_properties[] = { - DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.qdev_for_drives[0].blk), - DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.qdev_for_drives[1].blk), DEFINE_PROP_SIGNED("fdtypeA", FDCtrlSysBus, state.qdev_for_drives[0].type, FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type, FloppyDriveType), @@ -2971,7 +2915,6 @@ static const TypeInfo sysbus_fdc_info = { }; static Property sun4m_fdc_properties[] = { - DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.qdev_for_drives[0].blk), DEFINE_PROP_SIGNED("fdtype", FDCtrlSysBus, state.qdev_for_drives[0].type, FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type, FloppyDriveType), @@ -2990,7 +2933,7 @@ static void sun4m_fdc_class_init(ObjectClass *klass, void *data) } static const TypeInfo sun4m_fdc_info = { - .name = "SUNW,fdtwo", + .name = "sun-fdtwo", .parent = TYPE_SYSBUS_FDC, .instance_init = sun4m_fdc_initfn, .class_init = sun4m_fdc_class_init, diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index a3b69e2709..ac82d54063 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -836,17 +836,17 @@ static XenBlockIOThread *xen_block_iothread_create(const char *id, { ERRP_GUARD(); XenBlockIOThread *iothread = g_new(XenBlockIOThread, 1); - QDict *opts; - QObject *ret_data = NULL; + ObjectOptions *opts; iothread->id = g_strdup(id); - opts = qdict_new(); - qdict_put_str(opts, "qom-type", TYPE_IOTHREAD); - qdict_put_str(opts, "id", id); - qmp_object_add(opts, &ret_data, errp); - qobject_unref(opts); - qobject_unref(ret_data); + opts = g_new(ObjectOptions, 1); + *opts = (ObjectOptions) { + .qom_type = OBJECT_TYPE_IOTHREAD, + .id = g_strdup(id), + }; + qmp_object_add(opts, errp); + qapi_free_ObjectOptions(opts); if (*errp) { g_free(iothread->id); diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c index 6bee3ee18e..e8c3017724 100644 --- a/hw/char/etraxfs_ser.c +++ b/hw/char/etraxfs_ser.c @@ -50,7 +50,7 @@ #define STAT_TR_IDLE 22 #define STAT_TR_RDY 24 -#define TYPE_ETRAX_FS_SERIAL "etraxfs,serial" +#define TYPE_ETRAX_FS_SERIAL "etraxfs-serial" typedef struct ETRAXSerial ETRAXSerial; DECLARE_INSTANCE_CHECKER(ETRAXSerial, ETRAX_SERIAL, TYPE_ETRAX_FS_SERIAL) diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c index b0cb6d84af..af5a0e3517 100644 --- a/hw/cris/axis_dev88.c +++ b/hw/cris/axis_dev88.c @@ -289,7 +289,7 @@ void axisdev88_init(MachineState *machine) &gpio_state.iomem); - dev = qdev_new("etraxfs,pic"); + dev = qdev_new("etraxfs-pic"); s = SYS_BUS_DEVICE(dev); sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, 0x3001c000); @@ -323,8 +323,8 @@ void axisdev88_init(MachineState *machine) } /* 2 timers. */ - sysbus_create_varargs("etraxfs,timer", 0x3001e000, irq[0x1b], nmi[1], NULL); - sysbus_create_varargs("etraxfs,timer", 0x3005e000, irq[0x1b], nmi[1], NULL); + sysbus_create_varargs("etraxfs-timer", 0x3001e000, irq[0x1b], nmi[1], NULL); + sysbus_create_varargs("etraxfs-timer", 0x3005e000, irq[0x1b], nmi[1], NULL); for (i = 0; i < 4; i++) { etraxfs_ser_create(0x30026000 + i * 0x2000, irq[0x14 + i], serial_hd(i)); diff --git a/hw/display/tcx.c b/hw/display/tcx.c index d3db304657..d4d09d0df8 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -56,7 +56,7 @@ #define TCX_THC_CURSMASK 0x900 #define TCX_THC_CURSBITS 0x980 -#define TYPE_TCX "SUNW,tcx" +#define TYPE_TCX "sun-tcx" OBJECT_DECLARE_SIMPLE_TYPE(TCXState, TCX) struct TCXState { diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c index 54ed4c77f7..bd37d1cca0 100644 --- a/hw/intc/etraxfs_pic.c +++ b/hw/intc/etraxfs_pic.c @@ -38,7 +38,7 @@ #define R_R_GURU 4 #define R_MAX 5 -#define TYPE_ETRAX_FS_PIC "etraxfs,pic" +#define TYPE_ETRAX_FS_PIC "etraxfs-pic" DECLARE_INSTANCE_CHECKER(struct etrax_pic, ETRAX_FS_PIC, TYPE_ETRAX_FS_PIC) diff --git a/hw/microblaze/xlnx-zynqmp-pmu.c b/hw/microblaze/xlnx-zynqmp-pmu.c index 1d1b4b5c19..5a2016672a 100644 --- a/hw/microblaze/xlnx-zynqmp-pmu.c +++ b/hw/microblaze/xlnx-zynqmp-pmu.c @@ -28,7 +28,7 @@ /* Define the PMU device */ -#define TYPE_XLNX_ZYNQMP_PMU_SOC "xlnx,zynqmp-pmu-soc" +#define TYPE_XLNX_ZYNQMP_PMU_SOC "xlnx-zynqmp-pmu-soc" OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPPMUSoCState, XLNX_ZYNQMP_PMU_SOC) #define XLNX_ZYNQMP_PMU_ROM_SIZE 0x8000 diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c index c66d7db177..5086e6b7ed 100644 --- a/hw/misc/zynq_slcr.c +++ b/hw/misc/zynq_slcr.c @@ -182,7 +182,7 @@ REG32(DDRIOB, 0xb40) #define ZYNQ_SLCR_MMIO_SIZE 0x1000 #define ZYNQ_SLCR_NUM_REGS (ZYNQ_SLCR_MMIO_SIZE / 4) -#define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr" +#define TYPE_ZYNQ_SLCR "xilinx-zynq_slcr" OBJECT_DECLARE_SIMPLE_TYPE(ZynqSLCRState, ZYNQ_SLCR) struct ZynqSLCRState { diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 312e2afaf9..1a00816d9a 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -496,7 +496,7 @@ static void tcx_init(hwaddr addr, qemu_irq irq, int vram_size, int width, DeviceState *dev; SysBusDevice *s; - dev = qdev_new("SUNW,tcx"); + dev = qdev_new("sun-tcx"); qdev_prop_set_uint32(dev, "vram_size", vram_size); qdev_prop_set_uint16(dev, "width", width); qdev_prop_set_uint16(dev, "height", height); @@ -970,7 +970,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, } if (hwdef->sx_base) { - create_unimplemented_device("SUNW,sx", hwdef->sx_base, 0x2000); + create_unimplemented_device("sun-sx", hwdef->sx_base, 0x2000); } dev = qdev_new("sysbus-m48t08"); @@ -1045,23 +1045,23 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, slavio_irq[30], fdc_tc); if (hwdef->cs_base) { - sysbus_create_simple("SUNW,CS4231", hwdef->cs_base, + sysbus_create_simple("sun-CS4231", hwdef->cs_base, slavio_irq[5]); } if (hwdef->dbri_base) { /* ISDN chip with attached CS4215 audio codec */ /* prom space */ - create_unimplemented_device("SUNW,DBRI.prom", + create_unimplemented_device("sun-DBRI.prom", hwdef->dbri_base + 0x1000, 0x30); /* reg space */ - create_unimplemented_device("SUNW,DBRI", + create_unimplemented_device("sun-DBRI", hwdef->dbri_base + 0x10000, 0x100); } if (hwdef->bpp_base) { /* parallel port */ - create_unimplemented_device("SUNW,bpp", hwdef->bpp_base, 0x20); + create_unimplemented_device("sun-bpp", hwdef->bpp_base, 0x20); } initrd_size = 0; diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c index 48f2e3ade2..5379006086 100644 --- a/hw/timer/etraxfs_timer.c +++ b/hw/timer/etraxfs_timer.c @@ -48,7 +48,7 @@ #define R_INTR 0x50 #define R_MASKED_INTR 0x54 -#define TYPE_ETRAX_FS_TIMER "etraxfs,timer" +#define TYPE_ETRAX_FS_TIMER "etraxfs-timer" typedef struct ETRAXTimerState ETRAXTimerState; DECLARE_INSTANCE_CHECKER(ETRAXTimerState, ETRAX_TIMER, TYPE_ETRAX_FS_TIMER) diff --git a/include/exec/memory.h b/include/exec/memory.h index 54ccf1a5f0..260ddd8ade 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -33,11 +33,11 @@ #define MAX_PHYS_ADDR_SPACE_BITS 62 #define MAX_PHYS_ADDR (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1) -#define TYPE_MEMORY_REGION "qemu:memory-region" +#define TYPE_MEMORY_REGION "memory-region" DECLARE_INSTANCE_CHECKER(MemoryRegion, MEMORY_REGION, TYPE_MEMORY_REGION) -#define TYPE_IOMMU_MEMORY_REGION "qemu:iommu-memory-region" +#define TYPE_IOMMU_MEMORY_REGION "iommu-memory-region" typedef struct IOMMUMemoryRegionClass IOMMUMemoryRegionClass; DECLARE_OBJ_CHECKERS(IOMMUMemoryRegion, IOMMUMemoryRegionClass, IOMMU_MEMORY_REGION, TYPE_IOMMU_MEMORY_REGION) diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h index 0791dcb68a..189b23a8ce 100644 --- a/include/hw/arm/armv7m.h +++ b/include/hw/arm/armv7m.h @@ -15,7 +15,7 @@ #include "target/arm/idau.h" #include "qom/object.h" -#define TYPE_BITBAND "ARM,bitband-memory" +#define TYPE_BITBAND "ARM-bitband-memory" OBJECT_DECLARE_SIMPLE_TYPE(BitBandState, BITBAND) struct BitBandState { diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h index c1603b2ac2..1b1086e945 100644 --- a/include/hw/arm/fsl-imx25.h +++ b/include/hw/arm/fsl-imx25.h @@ -34,7 +34,7 @@ #include "target/arm/cpu.h" #include "qom/object.h" -#define TYPE_FSL_IMX25 "fsl,imx25" +#define TYPE_FSL_IMX25 "fsl-imx25" OBJECT_DECLARE_SIMPLE_TYPE(FslIMX25State, FSL_IMX25) #define FSL_IMX25_NUM_UARTS 5 diff --git a/include/hw/arm/fsl-imx31.h b/include/hw/arm/fsl-imx31.h index b9792d58ae..c116a73e0b 100644 --- a/include/hw/arm/fsl-imx31.h +++ b/include/hw/arm/fsl-imx31.h @@ -30,7 +30,7 @@ #include "target/arm/cpu.h" #include "qom/object.h" -#define TYPE_FSL_IMX31 "fsl,imx31" +#define TYPE_FSL_IMX31 "fsl-imx31" OBJECT_DECLARE_SIMPLE_TYPE(FslIMX31State, FSL_IMX31) #define FSL_IMX31_NUM_UARTS 2 diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h index 29cc425acc..83291457cf 100644 --- a/include/hw/arm/fsl-imx6.h +++ b/include/hw/arm/fsl-imx6.h @@ -36,7 +36,7 @@ #include "cpu.h" #include "qom/object.h" -#define TYPE_FSL_IMX6 "fsl,imx6" +#define TYPE_FSL_IMX6 "fsl-imx6" OBJECT_DECLARE_SIMPLE_TYPE(FslIMX6State, FSL_IMX6) #define FSL_IMX6_NUM_CPUS 4 diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h index f8ebfba4f9..7812e516a5 100644 --- a/include/hw/arm/fsl-imx6ul.h +++ b/include/hw/arm/fsl-imx6ul.h @@ -40,7 +40,7 @@ #include "cpu.h" #include "qom/object.h" -#define TYPE_FSL_IMX6UL "fsl,imx6ul" +#define TYPE_FSL_IMX6UL "fsl-imx6ul" OBJECT_DECLARE_SIMPLE_TYPE(FslIMX6ULState, FSL_IMX6UL) enum FslIMX6ULConfiguration { diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h index 161fdc36da..f5d527a490 100644 --- a/include/hw/arm/fsl-imx7.h +++ b/include/hw/arm/fsl-imx7.h @@ -41,7 +41,7 @@ #include "cpu.h" #include "qom/object.h" -#define TYPE_FSL_IMX7 "fsl,imx7" +#define TYPE_FSL_IMX7 "fsl-imx7" OBJECT_DECLARE_SIMPLE_TYPE(FslIMX7State, FSL_IMX7) enum FslIMX7Configuration { diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index 1676a84ec8..d3e2ef97f6 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -37,7 +37,7 @@ #include "net/can_emu.h" #include "hw/dma/xlnx_csu_dma.h" -#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp" +#define TYPE_XLNX_ZYNQMP "xlnx-zynqmp" OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) #define XLNX_ZYNQMP_NUM_APU_CPUS 4 diff --git a/include/hw/cris/etraxfs.h b/include/hw/cris/etraxfs.h index 9e99380e0c..8b01ed67d3 100644 --- a/include/hw/cris/etraxfs.h +++ b/include/hw/cris/etraxfs.h @@ -41,7 +41,7 @@ static inline DeviceState *etraxfs_ser_create(hwaddr addr, DeviceState *dev; SysBusDevice *s; - dev = qdev_new("etraxfs,serial"); + dev = qdev_new("etraxfs-serial"); s = SYS_BUS_DEVICE(dev); qdev_prop_set_chr(dev, "chardev", chr); sysbus_realize_and_unref(s, &error_fatal); diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h index d1ea000d3d..23ee8e371b 100644 --- a/include/hw/i386/ich9.h +++ b/include/hw/i386/ich9.h @@ -216,7 +216,7 @@ struct ICH9LPCState { /* D31:F3 SMBus controller */ -#define TYPE_ICH9_SMB_DEVICE "ICH9 SMB" +#define TYPE_ICH9_SMB_DEVICE "ICH9-SMB" #define ICH9_A2_SMB_REVISION 0x02 #define ICH9_SMB_PI 0x00 diff --git a/include/hw/misc/grlib_ahb_apb_pnp.h b/include/hw/misc/grlib_ahb_apb_pnp.h index 341451bff6..bab0b5f47f 100644 --- a/include/hw/misc/grlib_ahb_apb_pnp.h +++ b/include/hw/misc/grlib_ahb_apb_pnp.h @@ -25,10 +25,10 @@ #define GRLIB_AHB_APB_PNP_H #include "qom/object.h" -#define TYPE_GRLIB_AHB_PNP "grlib,ahbpnp" +#define TYPE_GRLIB_AHB_PNP "grlib-ahbpnp" OBJECT_DECLARE_SIMPLE_TYPE(AHBPnp, GRLIB_AHB_PNP) -#define TYPE_GRLIB_APB_PNP "grlib,apbpnp" +#define TYPE_GRLIB_APB_PNP "grlib-apbpnp" OBJECT_DECLARE_SIMPLE_TYPE(APBPnp, GRLIB_APB_PNP) void grlib_ahb_pnp_add_entry(AHBPnp *dev, uint32_t address, uint32_t mask, diff --git a/include/hw/misc/zynq-xadc.h b/include/hw/misc/zynq-xadc.h index 602bfb4ab1..2017b7a803 100644 --- a/include/hw/misc/zynq-xadc.h +++ b/include/hw/misc/zynq-xadc.h @@ -23,7 +23,7 @@ #define ZYNQ_XADC_NUM_ADC_REGS 128 #define ZYNQ_XADC_FIFO_DEPTH 15 -#define TYPE_ZYNQ_XADC "xlnx,zynq-xadc" +#define TYPE_ZYNQ_XADC "xlnx-zynq-xadc" OBJECT_DECLARE_SIMPLE_TYPE(ZynqXADCState, ZYNQ_XADC) struct ZynqXADCState { diff --git a/include/hw/register.h b/include/hw/register.h index 03c8926d27..b480e3882c 100644 --- a/include/hw/register.h +++ b/include/hw/register.h @@ -87,7 +87,7 @@ struct RegisterInfo { void *opaque; }; -#define TYPE_REGISTER "qemu,register" +#define TYPE_REGISTER "qemu-register" DECLARE_INSTANCE_CHECKER(RegisterInfo, REGISTER, TYPE_REGISTER) diff --git a/include/hw/sparc/grlib.h b/include/hw/sparc/grlib.h index 2104f493f3..ef1946c7f8 100644 --- a/include/hw/sparc/grlib.h +++ b/include/hw/sparc/grlib.h @@ -32,14 +32,14 @@ */ /* IRQMP */ -#define TYPE_GRLIB_IRQMP "grlib,irqmp" +#define TYPE_GRLIB_IRQMP "grlib-irqmp" void grlib_irqmp_ack(DeviceState *dev, int intno); /* GPTimer */ -#define TYPE_GRLIB_GPTIMER "grlib,gptimer" +#define TYPE_GRLIB_GPTIMER "grlib-gptimer" /* APB UART */ -#define TYPE_GRLIB_APB_UART "grlib,apbuart" +#define TYPE_GRLIB_APB_UART "grlib-apbuart" #endif /* GRLIB_H */ diff --git a/include/qapi/compat-policy.h b/include/qapi/compat-policy.h new file mode 100644 index 0000000000..1083f95122 --- /dev/null +++ b/include/qapi/compat-policy.h @@ -0,0 +1,38 @@ +/* + * Policy for handling "funny" management interfaces + * + * Copyright (C) 2020 Red Hat, Inc. + * + * Authors: + * Markus Armbruster <armbru@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ + +#ifndef QAPI_COMPAT_POLICY_H +#define QAPI_COMPAT_POLICY_H + +#include "qapi/qapi-types-compat.h" + +extern CompatPolicy compat_policy; + +/* + * Create a QObject input visitor for @obj for use with QMP + * + * This is like qobject_input_visitor_new(), except it obeys the + * policy for handling deprecated management interfaces set with + * -compat. + */ +Visitor *qobject_input_visitor_new_qmp(QObject *obj); + +/* + * Create a QObject output visitor for @obj for use with QMP + * + * This is like qobject_output_visitor_new(), except it obeys the + * policy for handling deprecated management interfaces set with + * -compat. + */ +Visitor *qobject_output_visitor_new_qmp(QObject **result); + +#endif diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 135dfdef71..075203dc67 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -26,6 +26,7 @@ typedef enum QmpCommandOptions QCO_ALLOW_OOB = (1U << 1), QCO_ALLOW_PRECONFIG = (1U << 2), QCO_COROUTINE = (1U << 3), + QCO_DEPRECATED = (1U << 4), } QmpCommandOptions; typedef struct QmpCommand diff --git a/include/qapi/qobject-input-visitor.h b/include/qapi/qobject-input-visitor.h index 95985e25e5..8d69388810 100644 --- a/include/qapi/qobject-input-visitor.h +++ b/include/qapi/qobject-input-visitor.h @@ -15,6 +15,7 @@ #ifndef QOBJECT_INPUT_VISITOR_H #define QOBJECT_INPUT_VISITOR_H +#include "qapi/qapi-types-compat.h" #include "qapi/visitor.h" typedef struct QObjectInputVisitor QObjectInputVisitor; @@ -58,6 +59,9 @@ typedef struct QObjectInputVisitor QObjectInputVisitor; */ Visitor *qobject_input_visitor_new(QObject *obj); +void qobject_input_visitor_set_policy(Visitor *v, + CompatPolicyInput deprecated); + /* * Create a QObject input visitor for @obj for use with keyval_parse() * diff --git a/include/qapi/qobject-output-visitor.h b/include/qapi/qobject-output-visitor.h index 2b1726baf5..f2a2f92a00 100644 --- a/include/qapi/qobject-output-visitor.h +++ b/include/qapi/qobject-output-visitor.h @@ -15,6 +15,7 @@ #define QOBJECT_OUTPUT_VISITOR_H #include "qapi/visitor.h" +#include "qapi/qapi-types-compat.h" typedef struct QObjectOutputVisitor QObjectOutputVisitor; @@ -53,4 +54,7 @@ typedef struct QObjectOutputVisitor QObjectOutputVisitor; */ Visitor *qobject_output_visitor_new(QObject **result); +void qobject_output_visitor_set_policy(Visitor *v, + CompatPolicyOutput deprecated); + #endif diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h index 7362c043be..3b950f6e3d 100644 --- a/include/qapi/visitor-impl.h +++ b/include/qapi/visitor-impl.h @@ -113,6 +113,12 @@ struct Visitor The core takes care of the return type in the public interface. */ void (*optional)(Visitor *v, const char *name, bool *present); + /* Optional */ + bool (*deprecated_accept)(Visitor *v, const char *name, Error **errp); + + /* Optional */ + bool (*deprecated)(Visitor *v, const char *name); + /* Must be set */ VisitorType type; diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index ebc19ede7f..b3c9ef7a81 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -460,6 +460,24 @@ void visit_end_alternate(Visitor *v, void **obj); bool visit_optional(Visitor *v, const char *name, bool *present); /* + * Should we reject deprecated member @name? + * + * @name must not be NULL. This function is only useful between + * visit_start_struct() and visit_end_struct(), since only objects + * have deprecated members. + */ +bool visit_deprecated_accept(Visitor *v, const char *name, Error **errp); + +/* + * Should we visit deprecated member @name? + * + * @name must not be NULL. This function is only useful between + * visit_start_struct() and visit_end_struct(), since only objects + * have deprecated members. + */ +bool visit_deprecated(Visitor *v, const char *name); + +/* * Visit an enum value. * * @name expresses the relationship of this enum to its parent diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h index 07d5cc8832..81541e2080 100644 --- a/include/qom/object_interfaces.h +++ b/include/qom/object_interfaces.h @@ -2,6 +2,7 @@ #define OBJECT_INTERFACES_H #include "qom/object.h" +#include "qapi/qapi-types-qom.h" #include "qapi/visitor.h" #define TYPE_USER_CREATABLE "user-creatable" @@ -87,67 +88,60 @@ Object *user_creatable_add_type(const char *type, const char *id, Visitor *v, Error **errp); /** - * user_creatable_add_dict: - * @qdict: the object definition - * @keyval: if true, use a keyval visitor for processing @qdict (i.e. - * assume that all @qdict values are strings); otherwise, use - * the normal QObject visitor (i.e. assume all @qdict values - * have the QType expected by the QOM object type) + * user_creatable_add_qapi: + * @options: the object definition * @errp: if an error occurs, a pointer to an area to store the error * - * Create an instance of the user creatable object that is defined by - * @qdict. The object type is taken from the QDict key 'qom-type', its - * ID from the key 'id'. The remaining entries in @qdict are used to - * initialize the object properties. - * - * Returns: %true on success, %false on failure. + * Create an instance of the user creatable object according to the + * options passed in @opts as described in the QAPI schema documentation. */ -bool user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp); +void user_creatable_add_qapi(ObjectOptions *options, Error **errp); /** - * user_creatable_add_opts: - * @opts: the object definition + * user_creatable_parse_str: + * @optarg: the object definition string as passed on the command line * @errp: if an error occurs, a pointer to an area to store the error * - * Create an instance of the user creatable object whose type - * is defined in @opts by the 'qom-type' option, placing it - * in the object composition tree with name provided by the - * 'id' field. The remaining options in @opts are used to - * initialize the object properties. + * Parses the option for the user creatable object with a keyval parser and + * implicit key 'qom-type', converting the result to ObjectOptions. * - * Returns: the newly created object or NULL on error + * If a help option is given, print help instead. + * + * Returns: ObjectOptions on success, NULL when an error occurred (*errp is set + * then) or help was printed (*errp is not set). */ -Object *user_creatable_add_opts(QemuOpts *opts, Error **errp); - +ObjectOptions *user_creatable_parse_str(const char *optarg, Error **errp); /** - * user_creatable_add_opts_predicate: - * @type: the QOM type to be added + * user_creatable_add_from_str: + * @optarg: the object definition string as passed on the command line + * @errp: if an error occurs, a pointer to an area to store the error + * + * Create an instance of the user creatable object by parsing optarg + * with a keyval parser and implicit key 'qom-type', converting the + * result to ObjectOptions and calling into qmp_object_add(). * - * A callback function to determine whether an object - * of type @type should be created. Instances of this - * callback should be passed to user_creatable_add_opts_foreach + * If a help option is given, print help instead. + * + * Returns: true when an object was successfully created, false when an error + * occurred (*errp is set then) or help was printed (*errp is not set). */ -typedef bool (*user_creatable_add_opts_predicate)(const char *type); +bool user_creatable_add_from_str(const char *optarg, Error **errp); /** - * user_creatable_add_opts_foreach: - * @opaque: a user_creatable_add_opts_predicate callback or NULL - * @opts: options to create - * @errp: unused + * user_creatable_process_cmdline: + * @optarg: the object definition string as passed on the command line * - * An iterator callback to be used in conjunction with - * the qemu_opts_foreach() method for creating a list of - * objects from a set of QemuOpts + * Create an instance of the user creatable object by parsing optarg + * with a keyval parser and implicit key 'qom-type', converting the + * result to ObjectOptions and calling into qmp_object_add(). * - * The @opaque parameter can be passed a user_creatable_add_opts_predicate - * callback to filter which types of object are created during iteration. - * When it fails, report the error. + * If a help option is given, print help instead and exit. * - * Returns: 0 on success, -1 when an error was reported. + * This function is only meant to be called during command line parsing. + * It exits the process on failure or after printing help. */ -int user_creatable_add_opts_foreach(void *opaque, - QemuOpts *opts, Error **errp); +void user_creatable_process_cmdline(const char *optarg); /** * user_creatable_print_help: @@ -164,19 +158,6 @@ int user_creatable_add_opts_foreach(void *opaque, bool user_creatable_print_help(const char *type, QemuOpts *opts); /** - * user_creatable_print_help_from_qdict: - * @args: options to create - * - * Prints help considering the other options given in @args (if "qom-type" is - * given and valid, print properties for the type, otherwise print valid types) - * - * In contrast to user_creatable_print_help(), this function can't return that - * no help was requested. It should only be called if we know that help is - * requested and it will always print some help. - */ -void user_creatable_print_help_from_qdict(QDict *args); - -/** * user_creatable_del: * @id: the unique ID for the object * @errp: if an error occurs, a pointer to an area to store the error @@ -196,11 +177,4 @@ bool user_creatable_del(const char *id, Error **errp); */ void user_creatable_cleanup(void); -/** - * qmp_object_add: - * - * QMP command handler for object-add. See the QAPI schema for documentation. - */ -void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp); - #endif diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index 3b5fcda08d..32c2d6023c 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -35,7 +35,6 @@ struct DriveInfo { bool is_default; /* Added by default_drive() ? */ int media_cd; QemuOpts *opts; - bool claimed_by_board; QTAILQ_ENTRY(DriveInfo) next; }; diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 8a47ba8fbb..0ad5b77477 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -1636,24 +1636,11 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict) void hmp_object_add(Monitor *mon, const QDict *qdict) { + const char *options = qdict_get_str(qdict, "object"); Error *err = NULL; - QemuOpts *opts; - Object *obj = NULL; - - opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err); - if (err) { - goto end; - } - obj = user_creatable_add_opts(opts, &err); - qemu_opts_del(opts); - -end: + user_creatable_add_from_str(options, &err); hmp_handle_error(mon, err); - - if (obj) { - object_unref(obj); - } } void hmp_getfd(Monitor *mon, const QDict *qdict) diff --git a/monitor/misc.c b/monitor/misc.c index d9ed2bacef..55f3744053 100644 --- a/monitor/misc.c +++ b/monitor/misc.c @@ -231,12 +231,8 @@ static void monitor_init_qmp_commands(void) qmp_init_marshal(&qmp_commands); - qmp_register_command(&qmp_commands, "query-qmp-schema", - qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG); qmp_register_command(&qmp_commands, "device_add", qmp_device_add, QCO_NO_OPTIONS); - qmp_register_command(&qmp_commands, "object-add", qmp_object_add, - QCO_NO_OPTIONS); QTAILQ_INIT(&qmp_cap_negotiation_commands); qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities", diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h index 40903d6386..9c3a09cb01 100644 --- a/monitor/monitor-internal.h +++ b/monitor/monitor-internal.h @@ -183,7 +183,4 @@ void help_cmd(Monitor *mon, const char *name); void handle_hmp_command(MonitorHMP *mon, const char *cmdline); int hmp_compare_cmd(const char *name, const char *list); -void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data, - Error **errp); - #endif diff --git a/monitor/qmp-cmds-control.c b/monitor/qmp-cmds-control.c index 513b547233..6e581713a3 100644 --- a/monitor/qmp-cmds-control.c +++ b/monitor/qmp-cmds-control.c @@ -26,10 +26,14 @@ #include "monitor-internal.h" #include "qemu-version.h" +#include "qapi/compat-policy.h" #include "qapi/error.h" #include "qapi/qapi-commands-control.h" +#include "qapi/qapi-commands-introspect.h" #include "qapi/qapi-emit-events.h" #include "qapi/qapi-introspect.h" +#include "qapi/qapi-visit-introspect.h" +#include "qapi/qobject-input-visitor.h" /* * Accept QMP capabilities in @list for @mon. @@ -130,17 +134,89 @@ CommandInfoList *qmp_query_commands(Error **errp) return list; } -/* - * Minor hack: generated marshalling suppressed for this command - * ('gen': false in the schema) so we can parse the JSON string - * directly into QObject instead of first parsing it with - * visit_type_SchemaInfoList() into a SchemaInfoList, then marshal it - * to QObject with generated output marshallers, every time. Instead, - * we do it in test-qobject-input-visitor.c, just to make sure - * qapi-gen.py's output actually conforms to the schema. - */ -void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data, - Error **errp) +static void *split_off_generic_list(void *list, + bool (*splitp)(void *elt), + void **part) +{ + GenericList *keep = NULL, **keep_tailp = &keep; + GenericList *split = NULL, **split_tailp = &split; + GenericList *tail; + + for (tail = list; tail; tail = tail->next) { + if (splitp(tail)) { + *split_tailp = tail; + split_tailp = &tail->next; + } else { + *keep_tailp = tail; + keep_tailp = &tail->next; + } + } + + *keep_tailp = *split_tailp = NULL; + *part = split; + return keep; +} + +static bool is_in(const char *s, strList *list) +{ + strList *tail; + + for (tail = list; tail; tail = tail->next) { + if (!strcmp(tail->value, s)) { + return true; + } + } + return false; +} + +static bool is_entity_deprecated(void *link) +{ + return is_in("deprecated", ((SchemaInfoList *)link)->value->features); +} + +static bool is_member_deprecated(void *link) +{ + return is_in("deprecated", + ((SchemaInfoObjectMemberList *)link)->value->features); +} + +static SchemaInfoList *zap_deprecated(SchemaInfoList *schema) { - *ret_data = qobject_from_qlit(&qmp_schema_qlit); + void *to_zap; + SchemaInfoList *tail; + SchemaInfo *ent; + + schema = split_off_generic_list(schema, is_entity_deprecated, &to_zap); + qapi_free_SchemaInfoList(to_zap); + + for (tail = schema; tail; tail = tail->next) { + ent = tail->value; + if (ent->meta_type == SCHEMA_META_TYPE_OBJECT) { + ent->u.object.members + = split_off_generic_list(ent->u.object.members, + is_member_deprecated, &to_zap); + qapi_free_SchemaInfoObjectMemberList(to_zap); + } + } + + return schema; +} + +SchemaInfoList *qmp_query_qmp_schema(Error **errp) +{ + QObject *obj = qobject_from_qlit(&qmp_schema_qlit); + Visitor *v = qobject_input_visitor_new(obj); + SchemaInfoList *schema = NULL; + + /* test_visitor_in_qmp_introspect() ensures this can't fail */ + visit_type_SchemaInfoList(v, NULL, &schema, &error_abort); + g_assert(schema); + + qobject_unref(obj); + visit_free(v); + + if (compat_policy.deprecated_output == COMPAT_POLICY_OUTPUT_HIDE) { + return zap_deprecated(schema); + } + return schema; } diff --git a/qapi/authz.json b/qapi/authz.json index 42afe752d1..51845e37cc 100644 --- a/qapi/authz.json +++ b/qapi/authz.json @@ -50,12 +50,63 @@ '*format': 'QAuthZListFormat'}} ## -# @QAuthZListRuleListHack: +# @AuthZListProperties: # -# Not exposed via QMP; hack to generate QAuthZListRuleList -# for use internally by the code. +# Properties for authz-list objects. +# +# @policy: Default policy to apply when no rule matches (default: deny) +# +# @rules: Authorization rules based on matching user +# +# Since: 4.0 +## +{ 'struct': 'AuthZListProperties', + 'data': { '*policy': 'QAuthZListPolicy', + '*rules': ['QAuthZListRule'] } } + +## +# @AuthZListFileProperties: +# +# Properties for authz-listfile objects. +# +# @filename: File name to load the configuration from. The file must +# contain valid JSON for AuthZListProperties. +# +# @refresh: If true, inotify is used to monitor the file, automatically +# reloading changes. If an error occurs during reloading, all +# authorizations will fail until the file is next successfully +# loaded. (default: true if the binary was built with +# CONFIG_INOTIFY1, false otherwise) +# +# Since: 4.0 +## +{ 'struct': 'AuthZListFileProperties', + 'data': { 'filename': 'str', + '*refresh': 'bool' } } + +## +# @AuthZPAMProperties: +# +# Properties for authz-pam objects. +# +# @service: PAM service name to use for authorization +# +# Since: 4.0 +## +{ 'struct': 'AuthZPAMProperties', + 'data': { 'service': 'str' } } + +## +# @AuthZSimpleProperties: +# +# Properties for authz-simple objects. +# +# @identity: Identifies the allowed user. Its format depends on the network +# service that authorization object is associated with. For +# authorizing based on TLS x509 certificates, the identity must be +# the x509 distinguished name. # # Since: 4.0 ## -{ 'struct': 'QAuthZListRuleListHack', - 'data': { 'unused': ['QAuthZListRule'] } } +{ 'struct': 'AuthZSimpleProperties', + 'data': { 'identity': 'str' } } diff --git a/qapi/block-core.json b/qapi/block-core.json index 0399449e13..1c3f1deb03 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2443,6 +2443,33 @@ '*iops-size' : 'int' } } ## +# @ThrottleGroupProperties: +# +# Properties for throttle-group objects. +# +# The options starting with x- are aliases for the same key without x- in +# the @limits object. As indicated by the x- prefix, this is not a stable +# interface and may be removed or changed incompatibly in the future. Use +# @limits for a supported stable interface. +# +# @limits: limits to apply for this throttle group +# +# Since: 2.11 +## +{ 'struct': 'ThrottleGroupProperties', + 'data': { '*limits': 'ThrottleLimits', + '*x-iops-total' : 'int', '*x-iops-total-max' : 'int', + '*x-iops-total-max-length' : 'int', '*x-iops-read' : 'int', + '*x-iops-read-max' : 'int', '*x-iops-read-max-length' : 'int', + '*x-iops-write' : 'int', '*x-iops-write-max' : 'int', + '*x-iops-write-max-length' : 'int', '*x-bps-total' : 'int', + '*x-bps-total-max' : 'int', '*x-bps-total-max-length' : 'int', + '*x-bps-read' : 'int', '*x-bps-read-max' : 'int', + '*x-bps-read-max-length' : 'int', '*x-bps-write' : 'int', + '*x-bps-write-max' : 'int', '*x-bps-write-max-length' : 'int', + '*x-iops-size' : 'int' } } + +## # @block-stream: # # Copy data from a backing file into a block device. diff --git a/qapi/common.json b/qapi/common.json index 716712d4b3..7c976296f0 100644 --- a/qapi/common.json +++ b/qapi/common.json @@ -145,3 +145,55 @@ ## { 'enum': 'PCIELinkWidth', 'data': [ '1', '2', '4', '8', '12', '16', '32' ] } + +## +# @HostMemPolicy: +# +# Host memory policy types +# +# @default: restore default policy, remove any nondefault policy +# +# @preferred: set the preferred host nodes for allocation +# +# @bind: a strict policy that restricts memory allocation to the +# host nodes specified +# +# @interleave: memory allocations are interleaved across the set +# of host nodes specified +# +# Since: 2.1 +## +{ 'enum': 'HostMemPolicy', + 'data': [ 'default', 'preferred', 'bind', 'interleave' ] } + +## +# @NetFilterDirection: +# +# Indicates whether a netfilter is attached to a netdev's transmit queue or +# receive queue or both. +# +# @all: the filter is attached both to the receive and the transmit +# queue of the netdev (default). +# +# @rx: the filter is attached to the receive queue of the netdev, +# where it will receive packets sent to the netdev. +# +# @tx: the filter is attached to the transmit queue of the netdev, +# where it will receive packets sent by the netdev. +# +# Since: 2.5 +## +{ 'enum': 'NetFilterDirection', + 'data': [ 'all', 'rx', 'tx' ] } + +## +# @GrabToggleKeys: +# +# Keys to toggle input-linux between host and guest. +# +# Since: 4.0 +# +## +{ 'enum': 'GrabToggleKeys', + 'data': [ 'ctrl-ctrl', 'alt-alt', 'shift-shift','meta-meta', 'scrolllock', + 'ctrl-scrolllock' ] } diff --git a/qapi/compat.json b/qapi/compat.json new file mode 100644 index 0000000000..ae3afc22df --- /dev/null +++ b/qapi/compat.json @@ -0,0 +1,52 @@ +# -*- Mode: Python -*- + +## +# = Compatibility policy +## + +## +# @CompatPolicyInput: +# +# Policy for handling "funny" input. +# +# @accept: Accept silently +# @reject: Reject with an error +# @crash: abort() the process +# +# Since: 6.0 +## +{ 'enum': 'CompatPolicyInput', + 'data': [ 'accept', 'reject', 'crash' ] } + +## +# @CompatPolicyOutput: +# +# Policy for handling "funny" output. +# +# @accept: Pass on unchanged +# @hide: Filter out +# +# Since: 6.0 +## +{ 'enum': 'CompatPolicyOutput', + 'data': [ 'accept', 'hide' ] } + +## +# @CompatPolicy: +# +# Policy for handling deprecated management interfaces. +# +# This is intended for testing users of the management interfaces. +# +# Limitation: covers only syntactic aspects of QMP, i.e. stuff tagged +# with feature 'deprecated'. We may want to extend it to cover +# semantic aspects, CLI, and experimental features. +# +# @deprecated-input: how to handle deprecated input (default 'accept') +# @deprecated-output: how to handle deprecated output (default 'accept') +# +# Since: 6.0 +## +{ 'struct': 'CompatPolicy', + 'data': { '*deprecated-input': 'CompatPolicyInput', + '*deprecated-output': 'CompatPolicyOutput' } } diff --git a/qapi/crypto.json b/qapi/crypto.json index 2aebe6fa20..7116ae9a46 100644 --- a/qapi/crypto.json +++ b/qapi/crypto.json @@ -381,3 +381,162 @@ 'discriminator': 'format', 'data': { 'luks': 'QCryptoBlockAmendOptionsLUKS' } } + +## +# @SecretCommonProperties: +# +# Properties for objects of classes derived from secret-common. +# +# @loaded: if true, the secret is loaded immediately when applying this option +# and will probably fail when processing the next option. Don't use; +# only provided for compatibility. (default: false) +# +# @format: the data format that the secret is provided in (default: raw) +# +# @keyid: the name of another secret that should be used to decrypt the +# provided data. If not present, the data is assumed to be unencrypted. +# +# @iv: the random initialization vector used for encryption of this particular +# secret. Should be a base64 encrypted string of the 16-byte IV. Mandatory +# if @keyid is given. Ignored if @keyid is absent. +# +# Features: +# @deprecated: Member @loaded is deprecated. Setting true doesn't make sense, +# and false is already the default. +# +# Since: 2.6 +## +{ 'struct': 'SecretCommonProperties', + 'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] }, + '*format': 'QCryptoSecretFormat', + '*keyid': 'str', + '*iv': 'str' } } + +## +# @SecretProperties: +# +# Properties for secret objects. +# +# Either @data or @file must be provided, but not both. +# +# @data: the associated with the secret from +# +# @file: the filename to load the data associated with the secret from +# +# Since: 2.6 +## +{ 'struct': 'SecretProperties', + 'base': 'SecretCommonProperties', + 'data': { '*data': 'str', + '*file': 'str' } } + +## +# @SecretKeyringProperties: +# +# Properties for secret_keyring objects. +# +# @serial: serial number that identifies a key to get from the kernel +# +# Since: 5.1 +## +{ 'struct': 'SecretKeyringProperties', + 'base': 'SecretCommonProperties', + 'data': { 'serial': 'int32' } } + +## +# @TlsCredsProperties: +# +# Properties for objects of classes derived from tls-creds. +# +# @verify-peer: if true the peer credentials will be verified once the +# handshake is completed. This is a no-op for anonymous +# credentials. (default: true) +# +# @dir: the path of the directory that contains the credential files +# +# @endpoint: whether the QEMU network backend that uses the credentials will be +# acting as a client or as a server (default: client) +# +# @priority: a gnutls priority string as described at +# https://gnutls.org/manual/html_node/Priority-Strings.html +# +# Since: 2.5 +## +{ 'struct': 'TlsCredsProperties', + 'data': { '*verify-peer': 'bool', + '*dir': 'str', + '*endpoint': 'QCryptoTLSCredsEndpoint', + '*priority': 'str' } } + +## +# @TlsCredsAnonProperties: +# +# Properties for tls-creds-anon objects. +# +# @loaded: if true, the credentials are loaded immediately when applying this +# option and will ignore options that are processed later. Don't use; +# only provided for compatibility. (default: false) +# +# Features: +# @deprecated: Member @loaded is deprecated. Setting true doesn't make sense, +# and false is already the default. +# +# Since: 2.5 +## +{ 'struct': 'TlsCredsAnonProperties', + 'base': 'TlsCredsProperties', + 'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] } } } + +## +# @TlsCredsPskProperties: +# +# Properties for tls-creds-psk objects. +# +# @loaded: if true, the credentials are loaded immediately when applying this +# option and will ignore options that are processed later. Don't use; +# only provided for compatibility. (default: false) +# +# @username: the username which will be sent to the server. For clients only. +# If absent, "qemu" is sent and the property will read back as an +# empty string. +# +# Features: +# @deprecated: Member @loaded is deprecated. Setting true doesn't make sense, +# and false is already the default. +# +# Since: 3.0 +## +{ 'struct': 'TlsCredsPskProperties', + 'base': 'TlsCredsProperties', + 'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] }, + '*username': 'str' } } + +## +# @TlsCredsX509Properties: +# +# Properties for tls-creds-x509 objects. +# +# @loaded: if true, the credentials are loaded immediately when applying this +# option and will ignore options that are processed later. Don't use; +# only provided for compatibility. (default: false) +# +# @sanity-check: if true, perform some sanity checks before using the +# credentials (default: true) +# +# @passwordid: For the server-key.pem and client-key.pem files which contain +# sensitive private keys, it is possible to use an encrypted +# version by providing the @passwordid parameter. This provides +# the ID of a previously created secret object containing the +# password for decryption. +# +# Features: +# @deprecated: Member @loaded is deprecated. Setting true doesn't make sense, +# and false is already the default. +# +# Since: 2.5 +## +{ 'struct': 'TlsCredsX509Properties', + 'base': 'TlsCredsProperties', + 'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] }, + '*sanity-check': 'bool', + '*passwordid': 'str' } } diff --git a/qapi/introspect.json b/qapi/introspect.json index 944bb87a20..39bd303778 100644 --- a/qapi/introspect.json +++ b/qapi/introspect.json @@ -49,7 +49,7 @@ ## { 'command': 'query-qmp-schema', 'returns': [ 'SchemaInfo' ], - 'gen': false } # just to simplify qmp_query_json() + 'allow-preconfig': true } ## # @SchemaMetaType: diff --git a/qapi/machine.json b/qapi/machine.json index c0c52aef10..6e90d463fc 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -8,6 +8,8 @@ # = Machines ## +{ 'include': 'common.json' } + ## # @SysEmuTarget: # @@ -719,26 +721,6 @@ 'line': 'uint16' }} ## -# @HostMemPolicy: -# -# Host memory policy types -# -# @default: restore default policy, remove any nondefault policy -# -# @preferred: set the preferred host nodes for allocation -# -# @bind: a strict policy that restricts memory allocation to the -# host nodes specified -# -# @interleave: memory allocations are interleaved across the set -# of host nodes specified -# -# Since: 2.1 -## -{ 'enum': 'HostMemPolicy', - 'data': [ 'default', 'preferred', 'bind', 'interleave' ] } - -## # @memsave: # # Save a portion of guest memory to a file. diff --git a/qapi/meson.build b/qapi/meson.build index d4424ae6e7..0d20226fa3 100644 --- a/qapi/meson.build +++ b/qapi/meson.build @@ -25,6 +25,7 @@ qapi_all_modules = [ 'block-export', 'char', 'common', + 'compat', 'control', 'crypto', 'dump', diff --git a/qapi/net.json b/qapi/net.json index 87361ebd9a..b86d053ad6 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -493,26 +493,6 @@ 'vhost-vdpa': 'NetdevVhostVDPAOptions' } } ## -# @NetFilterDirection: -# -# Indicates whether a netfilter is attached to a netdev's transmit queue or -# receive queue or both. -# -# @all: the filter is attached both to the receive and the transmit -# queue of the netdev (default). -# -# @rx: the filter is attached to the receive queue of the netdev, -# where it will receive packets sent to the netdev. -# -# @tx: the filter is attached to the transmit queue of the netdev, -# where it will receive packets sent by the netdev. -# -# Since: 2.5 -## -{ 'enum': 'NetFilterDirection', - 'data': [ 'all', 'rx', 'tx' ] } - -## # @RxState: # # Packets receiving state diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json index 3441c9a9ae..4912b9744e 100644 --- a/qapi/qapi-schema.json +++ b/qapi/qapi-schema.json @@ -79,6 +79,7 @@ { 'include': 'migration.json' } { 'include': 'transaction.json' } { 'include': 'trace.json' } +{ 'include': 'compat.json' } { 'include': 'control.json' } { 'include': 'introspect.json' } { 'include': 'qom.json' } diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index 7e5f40e7f0..a641adec51 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -135,6 +135,24 @@ bool visit_optional(Visitor *v, const char *name, bool *present) return *present; } +bool visit_deprecated_accept(Visitor *v, const char *name, Error **errp) +{ + trace_visit_deprecated_accept(v, name); + if (v->deprecated_accept) { + return v->deprecated_accept(v, name, errp); + } + return true; +} + +bool visit_deprecated(Visitor *v, const char *name) +{ + trace_visit_deprecated(v, name); + if (v->deprecated) { + return v->deprecated(v, name); + } + return true; +} + bool visit_is_input(Visitor *v) { return v->type == VISITOR_INPUT; diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 5e597c76f7..59600210ce 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -14,15 +14,36 @@ #include "qemu/osdep.h" #include "block/aio.h" +#include "qapi/compat-policy.h" #include "qapi/error.h" #include "qapi/qmp/dispatch.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qjson.h" +#include "qapi/qobject-input-visitor.h" +#include "qapi/qobject-output-visitor.h" #include "sysemu/runstate.h" #include "qapi/qmp/qbool.h" #include "qemu/coroutine.h" #include "qemu/main-loop.h" +CompatPolicy compat_policy; + +Visitor *qobject_input_visitor_new_qmp(QObject *obj) +{ + Visitor *v = qobject_input_visitor_new(obj); + + qobject_input_visitor_set_policy(v, compat_policy.deprecated_input); + return v; +} + +Visitor *qobject_output_visitor_new_qmp(QObject **result) +{ + Visitor *v = qobject_output_visitor_new(result); + + qobject_output_visitor_set_policy(v, compat_policy.deprecated_output); + return v; +} + static QDict *qmp_dispatch_check_obj(QDict *dict, bool allow_oob, Error **errp) { @@ -155,6 +176,20 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, "The command %s has not been found", command); goto out; } + if (cmd->options & QCO_DEPRECATED) { + switch (compat_policy.deprecated_input) { + case COMPAT_POLICY_INPUT_ACCEPT: + break; + case COMPAT_POLICY_INPUT_REJECT: + error_set(&err, ERROR_CLASS_COMMAND_NOT_FOUND, + "Deprecated command %s disabled by policy", + command); + goto out; + case COMPAT_POLICY_INPUT_CRASH: + default: + abort(); + } + } if (!cmd->enabled) { error_set(&err, ERROR_CLASS_COMMAND_NOT_FOUND, "Command %s has been disabled%s%s", diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 23843b242e..04b790412e 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -14,6 +14,7 @@ #include "qemu/osdep.h" #include <math.h> +#include "qapi/compat-policy.h" #include "qapi/error.h" #include "qapi/qobject-input-visitor.h" #include "qapi/visitor-impl.h" @@ -43,6 +44,7 @@ typedef struct StackObject { struct QObjectInputVisitor { Visitor visitor; + CompatPolicyInput deprecated_policy; /* Root of visit at visitor creation. */ QObject *root; @@ -662,6 +664,24 @@ static void qobject_input_optional(Visitor *v, const char *name, bool *present) *present = true; } +static bool qobject_input_deprecated_accept(Visitor *v, const char *name, + Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + + switch (qiv->deprecated_policy) { + case COMPAT_POLICY_INPUT_ACCEPT: + return true; + case COMPAT_POLICY_INPUT_REJECT: + error_setg(errp, "Deprecated parameter '%s' disabled by policy", + name); + return false; + case COMPAT_POLICY_INPUT_CRASH: + default: + abort(); + } +} + static void qobject_input_free(Visitor *v) { QObjectInputVisitor *qiv = to_qiv(v); @@ -696,6 +716,7 @@ static QObjectInputVisitor *qobject_input_visitor_base_new(QObject *obj) v->visitor.end_list = qobject_input_end_list; v->visitor.start_alternate = qobject_input_start_alternate; v->visitor.optional = qobject_input_optional; + v->visitor.deprecated_accept = qobject_input_deprecated_accept; v->visitor.free = qobject_input_free; v->root = qobject_ref(obj); @@ -718,6 +739,14 @@ Visitor *qobject_input_visitor_new(QObject *obj) return &v->visitor; } +void qobject_input_visitor_set_policy(Visitor *v, + CompatPolicyInput deprecated) +{ + QObjectInputVisitor *qiv = to_qiv(v); + + qiv->deprecated_policy = deprecated; +} + Visitor *qobject_input_visitor_new_keyval(QObject *obj) { QObjectInputVisitor *v = qobject_input_visitor_base_new(obj); diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c index ba6f6ac8a7..e4873308d4 100644 --- a/qapi/qobject-output-visitor.c +++ b/qapi/qobject-output-visitor.c @@ -13,6 +13,7 @@ */ #include "qemu/osdep.h" +#include "qapi/compat-policy.h" #include "qapi/qobject-output-visitor.h" #include "qapi/visitor-impl.h" #include "qemu/queue.h" @@ -31,6 +32,8 @@ typedef struct QStackEntry { struct QObjectOutputVisitor { Visitor visitor; + CompatPolicyOutput deprecated_policy; + QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */ QObject *root; /* Root of the output visit */ QObject **result; /* User's storage location for result */ @@ -207,6 +210,13 @@ static bool qobject_output_type_null(Visitor *v, const char *name, return true; } +static bool qobject_output_deprecated(Visitor *v, const char *name) +{ + QObjectOutputVisitor *qov = to_qov(v); + + return qov->deprecated_policy != COMPAT_POLICY_OUTPUT_HIDE; +} + /* Finish building, and return the root object. * The root object is never null. The caller becomes the object's * owner, and should use qobject_unref() when done with it. */ @@ -256,6 +266,7 @@ Visitor *qobject_output_visitor_new(QObject **result) v->visitor.type_number = qobject_output_type_number; v->visitor.type_any = qobject_output_type_any; v->visitor.type_null = qobject_output_type_null; + v->visitor.deprecated = qobject_output_deprecated; v->visitor.complete = qobject_output_complete; v->visitor.free = qobject_output_free; @@ -264,3 +275,11 @@ Visitor *qobject_output_visitor_new(QObject **result) return &v->visitor; } + +void qobject_output_visitor_set_policy(Visitor *v, + CompatPolicyOutput deprecated) +{ + QObjectOutputVisitor *qov = to_qov(v); + + qov->deprecated_policy = deprecated; +} diff --git a/qapi/qom.json b/qapi/qom.json index 0b0b92944b..2056edc072 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -4,6 +4,11 @@ # This work is licensed under the terms of the GNU GPL, version 2 or later. # See the COPYING file in the top-level directory. +{ 'include': 'authz.json' } +{ 'include': 'block-core.json' } +{ 'include': 'common.json' } +{ 'include': 'crypto.json' } + ## # = QEMU Object Model (QOM) ## @@ -203,20 +208,643 @@ 'allow-preconfig': true } ## -# @object-add: +# @CanHostSocketcanProperties: # -# Create a QOM object. +# Properties for can-host-socketcan objects. +# +# @if: interface name of the host system CAN bus to connect to +# +# @canbus: object ID of the can-bus object to connect to the host interface +# +# Since: 2.12 +## +{ 'struct': 'CanHostSocketcanProperties', + 'data': { 'if': 'str', + 'canbus': 'str' } } + +## +# @ColoCompareProperties: +# +# Properties for colo-compare objects. +# +# @primary_in: name of the character device backend to use for the primary +# input (incoming packets are redirected to @outdev) +# +# @secondary_in: name of the character device backend to use for secondary +# input (incoming packets are only compared to the input on +# @primary_in and then dropped) +# +# @outdev: name of the character device backend to use for output +# +# @iothread: name of the iothread to run in +# +# @notify_dev: name of the character device backend to be used to communicate +# with the remote colo-frame (only for Xen COLO) +# +# @compare_timeout: the maximum time to hold a packet from @primary_in for +# comparison with an incoming packet on @secondary_in in +# milliseconds (default: 3000) +# +# @expired_scan_cycle: the interval at which colo-compare checks whether +# packets from @primary have timed out, in milliseconds +# (default: 3000) +# +# @max_queue_size: the maximum number of packets to keep in the queue for +# comparing with incoming packets from @secondary_in. If the +# queue is full and addtional packets are received, the +# addtional packets are dropped. (default: 1024) +# +# @vnet_hdr_support: if true, vnet header support is enabled (default: false) +# +# Since: 2.8 +## +{ 'struct': 'ColoCompareProperties', + 'data': { 'primary_in': 'str', + 'secondary_in': 'str', + 'outdev': 'str', + 'iothread': 'str', + '*notify_dev': 'str', + '*compare_timeout': 'uint64', + '*expired_scan_cycle': 'uint32', + '*max_queue_size': 'uint32', + '*vnet_hdr_support': 'bool' } } + +## +# @CryptodevBackendProperties: +# +# Properties for cryptodev-backend and cryptodev-backend-builtin objects. +# +# @queues: the number of queues for the cryptodev backend. Ignored for +# cryptodev-backend and must be 1 for cryptodev-backend-builtin. +# (default: 1) +# +# Since: 2.8 +## +{ 'struct': 'CryptodevBackendProperties', + 'data': { '*queues': 'uint32' } } + +## +# @CryptodevVhostUserProperties: +# +# Properties for cryptodev-vhost-user objects. +# +# @chardev: the name of a Unix domain socket character device that connects to +# the vhost-user server +# +# Since: 2.12 +## +{ 'struct': 'CryptodevVhostUserProperties', + 'base': 'CryptodevBackendProperties', + 'data': { 'chardev': 'str' } } + +## +# @DBusVMStateProperties: +# +# Properties for dbus-vmstate objects. +# +# @addr: the name of the DBus bus to connect to +# +# @id-list: a comma separated list of DBus IDs of helpers whose data should be +# included in the VM state on migration +# +# Since: 5.0 +## +{ 'struct': 'DBusVMStateProperties', + 'data': { 'addr': 'str' , + '*id-list': 'str' } } + +## +# @NetfilterInsert: +# +# Indicates where to insert a netfilter relative to a given other filter. +# +# @before: insert before the specified filter +# +# @behind: insert behind the specified filter +# +# Since: 5.0 +## +{ 'enum': 'NetfilterInsert', + 'data': [ 'before', 'behind' ] } + +## +# @NetfilterProperties: +# +# Properties for objects of classes derived from netfilter. +# +# @netdev: id of the network device backend to filter +# +# @queue: indicates which queue(s) to filter (default: all) +# +# @status: indicates whether the filter is enabled ("on") or disabled ("off") +# (default: "on") +# +# @position: specifies where the filter should be inserted in the filter list. +# "head" means the filter is inserted at the head of the filter list, +# before any existing filters. +# "tail" means the filter is inserted at the tail of the filter list, +# behind any existing filters (default). +# "id=<id>" means the filter is inserted before or behind the filter +# specified by <id>, depending on the @insert property. +# (default: "tail") +# +# @insert: where to insert the filter relative to the filter given in @position. +# Ignored if @position is "head" or "tail". (default: behind) +# +# Since: 2.5 +## +{ 'struct': 'NetfilterProperties', + 'data': { 'netdev': 'str', + '*queue': 'NetFilterDirection', + '*status': 'str', + '*position': 'str', + '*insert': 'NetfilterInsert' } } + +## +# @FilterBufferProperties: +# +# Properties for filter-buffer objects. +# +# @interval: a non-zero interval in microseconds. All packets arriving in the +# given interval are delayed until the end of the interval. +# +# Since: 2.5 +## +{ 'struct': 'FilterBufferProperties', + 'base': 'NetfilterProperties', + 'data': { 'interval': 'uint32' } } + +## +# @FilterDumpProperties: +# +# Properties for filter-dump objects. +# +# @file: the filename where the dumped packets should be stored +# +# @maxlen: maximum number of bytes in a packet that are stored (default: 65536) +# +# Since: 2.5 +## +{ 'struct': 'FilterDumpProperties', + 'base': 'NetfilterProperties', + 'data': { 'file': 'str', + '*maxlen': 'uint32' } } + +## +# @FilterMirrorProperties: +# +# Properties for filter-mirror objects. +# +# @outdev: the name of a character device backend to which all incoming packets +# are mirrored +# +# @vnet_hdr_support: if true, vnet header support is enabled (default: false) +# +# Since: 2.6 +## +{ 'struct': 'FilterMirrorProperties', + 'base': 'NetfilterProperties', + 'data': { 'outdev': 'str', + '*vnet_hdr_support': 'bool' } } + +## +# @FilterRedirectorProperties: +# +# Properties for filter-redirector objects. +# +# At least one of @indev or @outdev must be present. If both are present, they +# must not refer to the same character device backend. +# +# @indev: the name of a character device backend from which packets are +# received and redirected to the filtered network device +# +# @outdev: the name of a character device backend to which all incoming packets +# are redirected +# +# @vnet_hdr_support: if true, vnet header support is enabled (default: false) +# +# Since: 2.6 +## +{ 'struct': 'FilterRedirectorProperties', + 'base': 'NetfilterProperties', + 'data': { '*indev': 'str', + '*outdev': 'str', + '*vnet_hdr_support': 'bool' } } + +## +# @FilterRewriterProperties: +# +# Properties for filter-rewriter objects. +# +# @vnet_hdr_support: if true, vnet header support is enabled (default: false) +# +# Since: 2.8 +## +{ 'struct': 'FilterRewriterProperties', + 'base': 'NetfilterProperties', + 'data': { '*vnet_hdr_support': 'bool' } } + +## +# @InputBarrierProperties: +# +# Properties for input-barrier objects. +# +# @name: the screen name as declared in the screens section of barrier.conf +# +# @server: hostname of the Barrier server (default: "localhost") +# +# @port: TCP port of the Barrier server (default: "24800") +# +# @x-origin: x coordinate of the leftmost pixel on the guest screen +# (default: "0") +# +# @y-origin: y coordinate of the topmost pixel on the guest screen +# (default: "0") +# +# @width: the width of secondary screen in pixels (default: "1920") +# +# @height: the height of secondary screen in pixels (default: "1080") +# +# Since: 4.2 +## +{ 'struct': 'InputBarrierProperties', + 'data': { 'name': 'str', + '*server': 'str', + '*port': 'str', + '*x-origin': 'str', + '*y-origin': 'str', + '*width': 'str', + '*height': 'str' } } + +## +# @InputLinuxProperties: +# +# Properties for input-linux objects. +# +# @evdev: the path of the host evdev device to use +# +# @grab_all: if true, grab is toggled for all devices (e.g. both keyboard and +# mouse) instead of just one device (default: false) +# +# @repeat: enables auto-repeat events (default: false) +# +# @grab-toggle: the key or key combination that toggles device grab +# (default: ctrl-ctrl) +# +# Since: 2.6 +## +{ 'struct': 'InputLinuxProperties', + 'data': { 'evdev': 'str', + '*grab_all': 'bool', + '*repeat': 'bool', + '*grab-toggle': 'GrabToggleKeys' } } + +## +# @IothreadProperties: +# +# Properties for iothread objects. +# +# @poll-max-ns: the maximum number of nanoseconds to busy wait for events. +# 0 means polling is disabled (default: 32768 on POSIX hosts, +# 0 otherwise) +# +# @poll-grow: the multiplier used to increase the polling time when the +# algorithm detects it is missing events due to not polling long +# enough. 0 selects a default behaviour (default: 0) +# +# @poll-shrink: the divisor used to decrease the polling time when the +# algorithm detects it is spending too long polling without +# encountering events. 0 selects a default behaviour (default: 0) +# +# Since: 2.0 +## +{ 'struct': 'IothreadProperties', + 'data': { '*poll-max-ns': 'int', + '*poll-grow': 'int', + '*poll-shrink': 'int' } } + +## +# @MemoryBackendProperties: +# +# Properties for objects of classes derived from memory-backend. +# +# @merge: if true, mark the memory as mergeable (default depends on the machine +# type) +# +# @dump: if true, include the memory in core dumps (default depends on the +# machine type) +# +# @host-nodes: the list of NUMA host nodes to bind the memory to +# +# @policy: the NUMA policy (default: 'default') +# +# @prealloc: if true, preallocate memory (default: false) +# +# @prealloc-threads: number of CPU threads to use for prealloc (default: 1) +# +# @share: if false, the memory is private to QEMU; if true, it is shared +# (default: false) +# +# @size: size of the memory region in bytes +# +# @x-use-canonical-path-for-ramblock-id: if true, the canoncial path is used +# for ramblock-id. Disable this for 4.0 +# machine types or older to allow +# migration with newer QEMU versions. +# This option is considered stable +# despite the x- prefix. (default: +# false generally, but true for machine +# types <= 4.0) +# +# Since: 2.1 +## +{ 'struct': 'MemoryBackendProperties', + 'data': { '*dump': 'bool', + '*host-nodes': ['uint16'], + '*merge': 'bool', + '*policy': 'HostMemPolicy', + '*prealloc': 'bool', + '*prealloc-threads': 'uint32', + '*share': 'bool', + 'size': 'size', + '*x-use-canonical-path-for-ramblock-id': 'bool' } } + +## +# @MemoryBackendFileProperties: +# +# Properties for memory-backend-file objects. +# +# @align: the base address alignment when QEMU mmap(2)s @mem-path. Some +# backend stores specified by @mem-path require an alignment different +# than the default one used by QEMU, e.g. the device DAX /dev/dax0.0 +# requires 2M alignment rather than 4K. In such cases, users can +# specify the required alignment via this option. +# 0 selects a default alignment (currently the page size). (default: 0) +# +# @discard-data: if true, the file contents can be destroyed when QEMU exits, +# to avoid unnecessarily flushing data to the backing file. Note +# that ``discard-data`` is only an optimization, and QEMU might +# not discard file contents if it aborts unexpectedly or is +# terminated using SIGKILL. (default: false) +# +# @mem-path: the path to either a shared memory or huge page filesystem mount +# +# @pmem: specifies whether the backing file specified by @mem-path is in +# host persistent memory that can be accessed using the SNIA NVM +# programming model (e.g. Intel NVDIMM). +# +# @readonly: if true, the backing file is opened read-only; if false, it is +# opened read-write. (default: false) +# +# Since: 2.1 +## +{ 'struct': 'MemoryBackendFileProperties', + 'base': 'MemoryBackendProperties', + 'data': { '*align': 'size', + '*discard-data': 'bool', + 'mem-path': 'str', + '*pmem': { 'type': 'bool', 'if': 'defined(CONFIG_LIBPMEM)' }, + '*readonly': 'bool' } } + +## +# @MemoryBackendMemfdProperties: +# +# Properties for memory-backend-memfd objects. +# +# The @share boolean option is true by default with memfd. +# +# @hugetlb: if true, the file to be created resides in the hugetlbfs filesystem +# (default: false) +# +# @hugetlbsize: the hugetlb page size on systems that support multiple hugetlb +# page sizes (it must be a power of 2 value supported by the +# system). 0 selects a default page size. This option is ignored +# if @hugetlb is false. (default: 0) +# +# @seal: if true, create a sealed-file, which will block further resizing of +# the memory (default: true) +# +# Since: 2.12 +## +{ 'struct': 'MemoryBackendMemfdProperties', + 'base': 'MemoryBackendProperties', + 'data': { '*hugetlb': 'bool', + '*hugetlbsize': 'size', + '*seal': 'bool' } } + +## +# @PrManagerHelperProperties: +# +# Properties for pr-manager-helper objects. +# +# @path: the path to a Unix domain socket for connecting to the external helper +# +# Since: 2.11 +## +{ 'struct': 'PrManagerHelperProperties', + 'data': { 'path': 'str' } } + +## +# @RemoteObjectProperties: +# +# Properties for x-remote-object objects. +# +# @fd: file descriptor name previously passed via 'getfd' command +# +# @devid: the id of the device to be associated with the file descriptor +# +# Since: 6.0 +## +{ 'struct': 'RemoteObjectProperties', + 'data': { 'fd': 'str', 'devid': 'str' } } + +## +# @RngProperties: +# +# Properties for objects of classes derived from rng. +# +# @opened: if true, the device is opened immediately when applying this option +# and will probably fail when processing the next option. Don't use; +# only provided for compatibility. (default: false) +# +# Features: +# @deprecated: Member @opened is deprecated. Setting true doesn't make sense, +# and false is already the default. +# +# Since: 1.3 +## +{ 'struct': 'RngProperties', + 'data': { '*opened': { 'type': 'bool', 'features': ['deprecated'] } } } + +## +# @RngEgdProperties: +# +# Properties for rng-egd objects. +# +# @chardev: the name of a character device backend that provides the connection +# to the RNG daemon +# +# Since: 1.3 +## +{ 'struct': 'RngEgdProperties', + 'base': 'RngProperties', + 'data': { 'chardev': 'str' } } + +## +# @RngRandomProperties: +# +# Properties for rng-random objects. +# +# @filename: the filename of the device on the host to obtain entropy from +# (default: "/dev/urandom") +# +# Since: 1.3 +## +{ 'struct': 'RngRandomProperties', + 'base': 'RngProperties', + 'data': { '*filename': 'str' } } + +## +# @SevGuestProperties: +# +# Properties for sev-guest objects. +# +# @sev-device: SEV device to use (default: "/dev/sev") +# +# @dh-cert-file: guest owners DH certificate (encoded with base64) +# +# @session-file: guest owners session parameters (encoded with base64) +# +# @policy: SEV policy value (default: 0x1) +# +# @handle: SEV firmware handle (default: 0) +# +# @cbitpos: C-bit location in page table entry (default: 0) +# +# @reduced-phys-bits: number of bits in physical addresses that become +# unavailable when SEV is enabled +# +# Since: 2.12 +## +{ 'struct': 'SevGuestProperties', + 'data': { '*sev-device': 'str', + '*dh-cert-file': 'str', + '*session-file': 'str', + '*policy': 'uint32', + '*handle': 'uint32', + '*cbitpos': 'uint32', + 'reduced-phys-bits': 'uint32' }, + 'if': 'defined(CONFIG_SEV)' } + +## +# @ObjectType: +# +# Since: 6.0 +## +{ 'enum': 'ObjectType', + 'data': [ + 'authz-list', + 'authz-listfile', + 'authz-pam', + 'authz-simple', + 'can-bus', + 'can-host-socketcan', + 'colo-compare', + 'cryptodev-backend', + 'cryptodev-backend-builtin', + { 'name': 'cryptodev-vhost-user', + 'if': 'defined(CONFIG_VIRTIO_CRYPTO) && defined(CONFIG_VHOST_CRYPTO)' }, + 'dbus-vmstate', + 'filter-buffer', + 'filter-dump', + 'filter-mirror', + 'filter-redirector', + 'filter-replay', + 'filter-rewriter', + 'input-barrier', + 'input-linux', + 'iothread', + 'memory-backend-file', + { 'name': 'memory-backend-memfd', + 'if': 'defined(CONFIG_LINUX)' }, + 'memory-backend-ram', + {'name': 'pef-guest', 'if': 'defined(CONFIG_PSERIES)' }, + 'pr-manager-helper', + 'rng-builtin', + 'rng-egd', + 'rng-random', + 'secret', + 'secret_keyring', + {'name': 'sev-guest', 'if': 'defined(CONFIG_SEV)' }, + 's390-pv-guest', + 'throttle-group', + 'tls-creds-anon', + 'tls-creds-psk', + 'tls-creds-x509', + 'tls-cipher-suites', + 'x-remote-object' + ] } + +## +# @ObjectOptions: +# +# Describes the options of a user creatable QOM object. # # @qom-type: the class name for the object to be created # # @id: the name of the new object # -# @props: a dictionary of properties to be passed to the backend. Deprecated -# since 5.0, specify the properties on the top level instead. It is an -# error to specify the same option both on the top level and in @props. +# Since: 6.0 +## +{ 'union': 'ObjectOptions', + 'base': { 'qom-type': 'ObjectType', + 'id': 'str' }, + 'discriminator': 'qom-type', + 'data': { + 'authz-list': 'AuthZListProperties', + 'authz-listfile': 'AuthZListFileProperties', + 'authz-pam': 'AuthZPAMProperties', + 'authz-simple': 'AuthZSimpleProperties', + 'can-host-socketcan': 'CanHostSocketcanProperties', + 'colo-compare': 'ColoCompareProperties', + 'cryptodev-backend': 'CryptodevBackendProperties', + 'cryptodev-backend-builtin': 'CryptodevBackendProperties', + 'cryptodev-vhost-user': { 'type': 'CryptodevVhostUserProperties', + 'if': 'defined(CONFIG_VIRTIO_CRYPTO) && defined(CONFIG_VHOST_CRYPTO)' }, + 'dbus-vmstate': 'DBusVMStateProperties', + 'filter-buffer': 'FilterBufferProperties', + 'filter-dump': 'FilterDumpProperties', + 'filter-mirror': 'FilterMirrorProperties', + 'filter-redirector': 'FilterRedirectorProperties', + 'filter-replay': 'NetfilterProperties', + 'filter-rewriter': 'FilterRewriterProperties', + 'input-barrier': 'InputBarrierProperties', + 'input-linux': 'InputLinuxProperties', + 'iothread': 'IothreadProperties', + 'memory-backend-file': 'MemoryBackendFileProperties', + 'memory-backend-memfd': { 'type': 'MemoryBackendMemfdProperties', + 'if': 'defined(CONFIG_LINUX)' }, + 'memory-backend-ram': 'MemoryBackendProperties', + 'pr-manager-helper': 'PrManagerHelperProperties', + 'rng-builtin': 'RngProperties', + 'rng-egd': 'RngEgdProperties', + 'rng-random': 'RngRandomProperties', + 'secret': 'SecretProperties', + 'secret_keyring': 'SecretKeyringProperties', + 'sev-guest': { 'type': 'SevGuestProperties', + 'if': 'defined(CONFIG_SEV)' }, + 'throttle-group': 'ThrottleGroupProperties', + 'tls-creds-anon': 'TlsCredsAnonProperties', + 'tls-creds-psk': 'TlsCredsPskProperties', + 'tls-creds-x509': 'TlsCredsX509Properties', + 'tls-cipher-suites': 'TlsCredsProperties', + 'x-remote-object': 'RemoteObjectProperties' + } } + +## +# @object-add: # -# Additional arguments depend on qom-type and are passed to the backend -# unchanged. +# Create a QOM object. # # Returns: Nothing on success # Error if @qom-type is not a valid class name @@ -231,9 +859,7 @@ # <- { "return": {} } # ## -{ 'command': 'object-add', - 'data': {'qom-type': 'str', 'id': 'str', '*props': 'any'}, - 'gen': false } # so we can get the additional arguments +{ 'command': 'object-add', 'data': 'ObjectOptions', 'boxed': true } ## # @object-del: diff --git a/qapi/trace-events b/qapi/trace-events index 5eb4afa110..3cabe912ae 100644 --- a/qapi/trace-events +++ b/qapi/trace-events @@ -17,6 +17,8 @@ visit_start_alternate(void *v, const char *name, void *obj, size_t size) "v=%p n visit_end_alternate(void *v, void *obj) "v=%p obj=%p" visit_optional(void *v, const char *name, bool *present) "v=%p name=%s present=%p" +visit_deprecated_accept(void *v, const char *name) "v=%p name=%s" +visit_deprecated(void *v, const char *name) "v=%p name=%s" visit_type_enum(void *v, const char *name, int *obj) "v=%p name=%s obj=%p" visit_type_int(void *v, const char *name, int64_t *obj) "v=%p name=%s obj=%p" diff --git a/qapi/ui.json b/qapi/ui.json index d08d72b439..cc1882108b 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -6,6 +6,7 @@ # = Remote desktop ## +{ 'include': 'common.json' } { 'include': 'sockets.json' } ## @@ -1022,18 +1023,6 @@ 'events' : [ 'InputEvent' ] } } ## -# @GrabToggleKeys: -# -# Keys to toggle input-linux between host and guest. -# -# Since: 4.0 -# -## -{ 'enum': 'GrabToggleKeys', - 'data': [ 'ctrl-ctrl', 'alt-alt', 'shift-shift','meta-meta', 'scrolllock', - 'ctrl-scrolllock' ] } - -## # @DisplayGTK: # # GTK display options. diff --git a/qemu-img.c b/qemu-img.c index e2952fe955..babb5573ab 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -226,23 +226,6 @@ static void QEMU_NORETURN help(void) exit(EXIT_SUCCESS); } -static QemuOptsList qemu_object_opts = { - .name = "object", - .implied_opt_name = "qom-type", - .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head), - .desc = { - { } - }, -}; - -static bool qemu_img_object_print_help(const char *type, QemuOpts *opts) -{ - if (user_creatable_print_help(type, opts)) { - exit(0); - } - return true; -} - /* * Is @optarg safe for accumulate_options()? * It is when multiple of them can be joined together separated by ','. @@ -566,14 +549,9 @@ static int img_create(int argc, char **argv) case 'u': flags |= BDRV_O_NO_BACKING; break; - case OPTION_OBJECT: { - QemuOpts *opts; - opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!opts) { - goto fail; - } - } break; + case OPTION_OBJECT: + user_creatable_process_cmdline(optarg); + break; } } @@ -589,12 +567,6 @@ static int img_create(int argc, char **argv) } optind++; - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - goto fail; - } - /* Get image size, if specified */ if (optind < argc) { int64_t sval; @@ -804,14 +776,9 @@ static int img_check(int argc, char **argv) case 'U': force_share = true; break; - case OPTION_OBJECT: { - QemuOpts *opts; - opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!opts) { - return 1; - } - } break; + case OPTION_OBJECT: + user_creatable_process_cmdline(optarg); + break; case OPTION_IMAGE_OPTS: image_opts = true; break; @@ -831,12 +798,6 @@ static int img_check(int argc, char **argv) return 1; } - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - return 1; - } - ret = bdrv_parse_cache_mode(cache, &flags, &writethrough); if (ret < 0) { error_report("Invalid source cache option: %s", cache); @@ -1034,14 +995,9 @@ static int img_commit(int argc, char **argv) return 1; } break; - case OPTION_OBJECT: { - QemuOpts *opts; - opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!opts) { - return 1; - } - } break; + case OPTION_OBJECT: + user_creatable_process_cmdline(optarg); + break; case OPTION_IMAGE_OPTS: image_opts = true; break; @@ -1058,12 +1014,6 @@ static int img_commit(int argc, char **argv) } filename = argv[optind++]; - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - return 1; - } - flags = BDRV_O_RDWR | BDRV_O_UNMAP; ret = bdrv_parse_cache_mode(cache, &flags, &writethrough); if (ret < 0) { @@ -1353,7 +1303,7 @@ static int check_empty_sectors(BlockBackend *blk, int64_t offset, /* * Compares two images. Exit codes: * - * 0 - Images are identical + * 0 - Images are identical or the requested help was printed * 1 - Images differ * >1 - Error occurred */ @@ -1423,15 +1373,21 @@ static int img_compare(int argc, char **argv) case 'U': force_share = true; break; - case OPTION_OBJECT: { - QemuOpts *opts; - opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!opts) { - ret = 2; - goto out4; + case OPTION_OBJECT: + { + Error *local_err = NULL; + + if (!user_creatable_add_from_str(optarg, &local_err)) { + if (local_err) { + error_report_err(local_err); + exit(2); + } else { + /* Help was printed */ + exit(EXIT_SUCCESS); + } + } + break; } - } break; case OPTION_IMAGE_OPTS: image_opts = true; break; @@ -1450,13 +1406,6 @@ static int img_compare(int argc, char **argv) filename1 = argv[optind++]; filename2 = argv[optind++]; - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - ret = 2; - goto out4; - } - /* Initialize before goto out */ qemu_progress_init(progress, 2.0); @@ -1641,7 +1590,6 @@ out2: blk_unref(blk1); out3: qemu_progress_end(); -out4: return ret; } @@ -2342,15 +2290,9 @@ static int img_convert(int argc, char **argv) goto fail_getopt; } break; - case OPTION_OBJECT: { - QemuOpts *object_opts; - object_opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!object_opts) { - goto fail_getopt; - } + case OPTION_OBJECT: + user_creatable_process_cmdline(optarg); break; - } case OPTION_IMAGE_OPTS: image_opts = true; break; @@ -2378,12 +2320,6 @@ static int img_convert(int argc, char **argv) out_fmt = "raw"; } - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - goto fail_getopt; - } - if (s.compressed && s.copy_range) { error_report("Cannot enable copy offloading when -c is used"); goto fail_getopt; @@ -2971,14 +2907,9 @@ static int img_info(int argc, char **argv) case OPTION_BACKING_CHAIN: chain = true; break; - case OPTION_OBJECT: { - QemuOpts *opts; - opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!opts) { - return 1; - } - } break; + case OPTION_OBJECT: + user_creatable_process_cmdline(optarg); + break; case OPTION_IMAGE_OPTS: image_opts = true; break; @@ -2998,12 +2929,6 @@ static int img_info(int argc, char **argv) return 1; } - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - return 1; - } - list = collect_image_info_list(image_opts, filename, fmt, chain, force_share); if (!list) { @@ -3213,14 +3138,9 @@ static int img_map(int argc, char **argv) return 1; } break; - case OPTION_OBJECT: { - QemuOpts *opts; - opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!opts) { - return 1; - } - } break; + case OPTION_OBJECT: + user_creatable_process_cmdline(optarg); + break; case OPTION_IMAGE_OPTS: image_opts = true; break; @@ -3240,12 +3160,6 @@ static int img_map(int argc, char **argv) return 1; } - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - return 1; - } - blk = img_open(image_opts, filename, fmt, 0, false, false, force_share); if (!blk) { return 1; @@ -3384,14 +3298,9 @@ static int img_snapshot(int argc, char **argv) case 'U': force_share = true; break; - case OPTION_OBJECT: { - QemuOpts *opts; - opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!opts) { - return 1; - } - } break; + case OPTION_OBJECT: + user_creatable_process_cmdline(optarg); + break; case OPTION_IMAGE_OPTS: image_opts = true; break; @@ -3403,12 +3312,6 @@ static int img_snapshot(int argc, char **argv) } filename = argv[optind++]; - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - return 1; - } - /* Open the image */ blk = img_open(image_opts, filename, NULL, bdrv_oflags, false, quiet, force_share); @@ -3542,14 +3445,9 @@ static int img_rebase(int argc, char **argv) case 'q': quiet = true; break; - case OPTION_OBJECT: { - QemuOpts *opts; - opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!opts) { - return 1; - } - } break; + case OPTION_OBJECT: + user_creatable_process_cmdline(optarg); + break; case OPTION_IMAGE_OPTS: image_opts = true; break; @@ -3571,12 +3469,6 @@ static int img_rebase(int argc, char **argv) } filename = argv[optind++]; - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - return 1; - } - qemu_progress_init(progress, 2.0); qemu_progress_print(0, 100); @@ -3967,14 +3859,9 @@ static int img_resize(int argc, char **argv) case 'q': quiet = true; break; - case OPTION_OBJECT: { - QemuOpts *opts; - opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!opts) { - return 1; - } - } break; + case OPTION_OBJECT: + user_creatable_process_cmdline(optarg); + break; case OPTION_IMAGE_OPTS: image_opts = true; break; @@ -3996,12 +3883,6 @@ static int img_resize(int argc, char **argv) } filename = argv[optind++]; - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - return 1; - } - /* Choose grow, shrink, or absolute resize mode */ switch (size[0]) { case '+': @@ -4181,12 +4062,7 @@ static int img_amend(int argc, char **argv) quiet = true; break; case OPTION_OBJECT: - opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!opts) { - ret = -1; - goto out_no_progress; - } + user_creatable_process_cmdline(optarg); break; case OPTION_IMAGE_OPTS: image_opts = true; @@ -4201,13 +4077,6 @@ static int img_amend(int argc, char **argv) error_exit("Must specify options (-o)"); } - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - ret = -1; - goto out_no_progress; - } - if (quiet) { progress = false; } @@ -4760,10 +4629,7 @@ static int img_bitmap(int argc, char **argv) merge = true; break; case OPTION_OBJECT: - opts = qemu_opts_parse_noisily(&qemu_object_opts, optarg, true); - if (!opts) { - goto out; - } + user_creatable_process_cmdline(optarg); break; case OPTION_IMAGE_OPTS: image_opts = true; @@ -4771,12 +4637,6 @@ static int img_bitmap(int argc, char **argv) } } - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - goto out; - } - if (QSIMPLEQ_EMPTY(&actions)) { error_report("Need at least one of --add, --remove, --clear, " "--enable, --disable, or --merge"); @@ -5034,10 +4894,7 @@ static int img_dd(int argc, char **argv) force_share = true; break; case OPTION_OBJECT: - if (!qemu_opts_parse_noisily(&qemu_object_opts, optarg, true)) { - ret = -1; - goto out; - } + user_creatable_process_cmdline(optarg); break; case OPTION_IMAGE_OPTS: image_opts = true; @@ -5084,13 +4941,6 @@ static int img_dd(int argc, char **argv) goto out; } - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - ret = -1; - goto out; - } - blk1 = img_open(image_opts, in.filename, fmt, 0, false, false, force_share); @@ -5311,11 +5161,7 @@ static int img_measure(int argc, char **argv) force_share = true; break; case OPTION_OBJECT: - object_opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!object_opts) { - goto out; - } + user_creatable_process_cmdline(optarg); break; case OPTION_IMAGE_OPTS: image_opts = true; @@ -5345,12 +5191,6 @@ static int img_measure(int argc, char **argv) } } - if (qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_img_object_print_help, &error_fatal)) { - goto out; - } - if (argc - optind > 1) { error_report("At most one filename argument is allowed."); goto out; @@ -5490,7 +5330,6 @@ int main(int argc, char **argv) error_exit("Not enough arguments"); } - qemu_add_opts(&qemu_object_opts); qemu_add_opts(&qemu_source_opts); qemu_add_opts(&qemu_trace_opts); diff --git a/qemu-io.c b/qemu-io.c index ac88d8bd40..bf902302e9 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -477,23 +477,6 @@ enum { OPTION_IMAGE_OPTS = 257, }; -static QemuOptsList qemu_object_opts = { - .name = "object", - .implied_opt_name = "qom-type", - .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head), - .desc = { - { } - }, -}; - -static bool qemu_io_object_print_help(const char *type, QemuOpts *opts) -{ - if (user_creatable_print_help(type, opts)) { - exit(0); - } - return true; -} - static QemuOptsList file_opts = { .name = "file", .implied_opt_name = "file", @@ -550,7 +533,6 @@ int main(int argc, char **argv) qcrypto_init(&error_fatal); module_call_init(MODULE_INIT_QOM); - qemu_add_opts(&qemu_object_opts); qemu_add_opts(&qemu_trace_opts); bdrv_init(); @@ -612,14 +594,9 @@ int main(int argc, char **argv) case 'U': force_share = true; break; - case OPTION_OBJECT: { - QemuOpts *qopts; - qopts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!qopts) { - exit(1); - } - } break; + case OPTION_OBJECT: + user_creatable_process_cmdline(optarg); + break; case OPTION_IMAGE_OPTS: imageOpts = true; break; @@ -644,10 +621,6 @@ int main(int argc, char **argv) exit(1); } - qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_io_object_print_help, &error_fatal); - if (!trace_init_backends()) { exit(1); } diff --git a/qemu-nbd.c b/qemu-nbd.c index b1b9430a8f..93ef4e288f 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -401,24 +401,6 @@ static QemuOptsList file_opts = { }, }; -static QemuOptsList qemu_object_opts = { - .name = "object", - .implied_opt_name = "qom-type", - .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head), - .desc = { - { } - }, -}; - -static bool qemu_nbd_object_print_help(const char *type, QemuOpts *opts) -{ - if (user_creatable_print_help(type, opts)) { - exit(0); - } - return true; -} - - static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, bool list, Error **errp) { @@ -594,7 +576,6 @@ int main(int argc, char **argv) qcrypto_init(&error_fatal); module_call_init(MODULE_INIT_QOM); - qemu_add_opts(&qemu_object_opts); qemu_add_opts(&qemu_trace_opts); qemu_init_exec_dir(argv[0]); @@ -747,14 +728,9 @@ int main(int argc, char **argv) case '?': error_report("Try `%s --help' for more information.", argv[0]); exit(EXIT_FAILURE); - case QEMU_NBD_OPT_OBJECT: { - QemuOpts *opts; - opts = qemu_opts_parse_noisily(&qemu_object_opts, - optarg, true); - if (!opts) { - exit(EXIT_FAILURE); - } - } break; + case QEMU_NBD_OPT_OBJECT: + user_creatable_process_cmdline(optarg); + break; case QEMU_NBD_OPT_TLSCREDS: tlscredsid = optarg; break; @@ -802,10 +778,6 @@ int main(int argc, char **argv) export_name = ""; } - qemu_opts_foreach(&qemu_object_opts, - user_creatable_add_opts_foreach, - qemu_nbd_object_print_help, &error_fatal); - if (!trace_init_backends()) { exit(1); } diff --git a/qemu-options.hx b/qemu-options.hx index 671b310ab8..d60a03d3a9 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3507,6 +3507,28 @@ DEFHEADING() DEFHEADING(Debug/Expert options:) +DEF("compat", HAS_ARG, QEMU_OPTION_compat, + "-compat [deprecated-input=accept|reject|crash][,deprecated-output=accept|hide]\n" + " Policy for handling deprecated management interfaces\n", + QEMU_ARCH_ALL) +SRST +``-compat [deprecated-input=@var{input-policy}][,deprecated-output=@var{output-policy}]`` + Set policy for handling deprecated management interfaces (experimental): + + ``deprecated-input=accept`` (default) + Accept deprecated commands and arguments + ``deprecated-input=reject`` + Reject deprecated commands and arguments + ``deprecated-input=crash`` + Crash on deprecated commands and arguments + ``deprecated-output=accept`` (default) + Emit deprecated command results and events + ``deprecated-output=hide`` + Suppress deprecated command results and events + + Limitation: covers only syntactic aspects of QMP. +ERST + DEF("fw_cfg", HAS_ARG, QEMU_OPTION_fwcfg, "-fw_cfg [name=]<name>,file=<file>\n" " add named fw_cfg entry with contents from file\n" diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c index 11ad2e2078..c3324b0f86 100644 --- a/qom/object_interfaces.c +++ b/qom/object_interfaces.c @@ -2,15 +2,19 @@ #include "qemu/cutils.h" #include "qapi/error.h" +#include "qapi/qapi-commands-qom.h" +#include "qapi/qapi-visit-qom.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" #include "qapi/qmp/qjson.h" #include "qapi/qobject-input-visitor.h" +#include "qapi/qobject-output-visitor.h" #include "qom/object_interfaces.h" #include "qemu/help_option.h" #include "qemu/id.h" #include "qemu/module.h" #include "qemu/option.h" +#include "qemu/qemu-print.h" #include "qapi/opts-visitor.h" #include "qemu/config-file.h" #include "qemu/qemu-print.h" @@ -114,90 +118,28 @@ out: return obj; } -bool user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp) -{ - Visitor *v; - Object *obj; - g_autofree char *type = NULL; - g_autofree char *id = NULL; - - type = g_strdup(qdict_get_try_str(qdict, "qom-type")); - if (!type) { - error_setg(errp, QERR_MISSING_PARAMETER, "qom-type"); - return false; - } - qdict_del(qdict, "qom-type"); - - id = g_strdup(qdict_get_try_str(qdict, "id")); - if (!id) { - error_setg(errp, QERR_MISSING_PARAMETER, "id"); - return false; - } - qdict_del(qdict, "id"); - - if (keyval) { - v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); - } else { - v = qobject_input_visitor_new(QOBJECT(qdict)); - } - obj = user_creatable_add_type(type, id, qdict, v, errp); - visit_free(v); - object_unref(obj); - return !!obj; -} - -Object *user_creatable_add_opts(QemuOpts *opts, Error **errp) +void user_creatable_add_qapi(ObjectOptions *options, Error **errp) { Visitor *v; - QDict *pdict; + QObject *qobj; + QDict *props; Object *obj; - const char *id = qemu_opts_id(opts); - char *type = qemu_opt_get_del(opts, "qom-type"); - - if (!type) { - error_setg(errp, QERR_MISSING_PARAMETER, "qom-type"); - return NULL; - } - if (!id) { - error_setg(errp, QERR_MISSING_PARAMETER, "id"); - qemu_opt_set(opts, "qom-type", type, &error_abort); - g_free(type); - return NULL; - } - - qemu_opts_set_id(opts, NULL); - pdict = qemu_opts_to_qdict(opts, NULL); - v = opts_visitor_new(opts); - obj = user_creatable_add_type(type, id, pdict, v, errp); + v = qobject_output_visitor_new(&qobj); + visit_type_ObjectOptions(v, NULL, &options, &error_abort); + visit_complete(v, &qobj); visit_free(v); - qemu_opts_set_id(opts, (char *) id); - qemu_opt_set(opts, "qom-type", type, &error_abort); - g_free(type); - qobject_unref(pdict); - return obj; -} + props = qobject_to(QDict, qobj); + qdict_del(props, "qom-type"); + qdict_del(props, "id"); - -int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp) -{ - bool (*type_opt_predicate)(const char *, QemuOpts *) = opaque; - Object *obj = NULL; - const char *type; - - type = qemu_opt_get(opts, "qom-type"); - if (type && type_opt_predicate && - !type_opt_predicate(type, opts)) { - return 0; - } - - obj = user_creatable_add_opts(opts, errp); - if (!obj) { - return -1; - } + v = qobject_input_visitor_new(QOBJECT(props)); + obj = user_creatable_add_type(ObjectType_str(options->qom_type), + options->id, props, v, errp); object_unref(obj); - return 0; + qobject_unref(qobj); + visit_free(v); } char *object_property_help(const char *name, const char *type, @@ -228,11 +170,11 @@ static void user_creatable_print_types(void) { GSList *l, *list; - printf("List of user creatable objects:\n"); + qemu_printf("List of user creatable objects:\n"); list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false); for (l = list; l != NULL; l = l->next) { ObjectClass *oc = OBJECT_CLASS(l->data); - printf(" %s\n", object_class_get_name(oc)); + qemu_printf(" %s\n", object_class_get_name(oc)); } g_slist_free(list); } @@ -263,12 +205,12 @@ static bool user_creatable_print_type_properites(const char *type) } g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0); if (array->len > 0) { - printf("%s options:\n", type); + qemu_printf("%s options:\n", type); } else { - printf("There are no options for %s.\n", type); + qemu_printf("There are no options for %s.\n", type); } for (i = 0; i < array->len; i++) { - printf("%s\n", (char *)array->pdata[i]); + qemu_printf("%s\n", (char *)array->pdata[i]); } g_ptr_array_set_free_func(array, g_free); g_ptr_array_free(array, true); @@ -289,7 +231,7 @@ bool user_creatable_print_help(const char *type, QemuOpts *opts) return false; } -void user_creatable_print_help_from_qdict(QDict *args) +static void user_creatable_print_help_from_qdict(QDict *args) { const char *type = qdict_get_try_str(args, "qom-type"); @@ -298,8 +240,68 @@ void user_creatable_print_help_from_qdict(QDict *args) } } +ObjectOptions *user_creatable_parse_str(const char *optarg, Error **errp) +{ + ERRP_GUARD(); + QObject *obj; + bool help; + Visitor *v; + ObjectOptions *options; + + if (optarg[0] == '{') { + obj = qobject_from_json(optarg, errp); + if (!obj) { + return NULL; + } + v = qobject_input_visitor_new(obj); + } else { + QDict *args = keyval_parse(optarg, "qom-type", &help, errp); + if (*errp) { + return NULL; + } + if (help) { + user_creatable_print_help_from_qdict(args); + qobject_unref(args); + return NULL; + } + + obj = QOBJECT(args); + v = qobject_input_visitor_new_keyval(obj); + } + + visit_type_ObjectOptions(v, NULL, &options, errp); + visit_free(v); + qobject_unref(obj); + + return options; +} + +bool user_creatable_add_from_str(const char *optarg, Error **errp) +{ + ERRP_GUARD(); + ObjectOptions *options; + + options = user_creatable_parse_str(optarg, errp); + if (!options) { + return false; + } + + user_creatable_add_qapi(options, errp); + qapi_free_ObjectOptions(options); + return !*errp; +} + +void user_creatable_process_cmdline(const char *optarg) +{ + if (!user_creatable_add_from_str(optarg, &error_fatal)) { + /* Help was printed */ + exit(EXIT_SUCCESS); + } +} + bool user_creatable_del(const char *id, Error **errp) { + QemuOptsList *opts_list; Object *container; Object *obj; @@ -319,8 +321,10 @@ bool user_creatable_del(const char *id, Error **errp) * if object was defined on the command-line, remove its corresponding * option group entry */ - qemu_opts_del(qemu_opts_find(qemu_find_opts_err("object", &error_abort), - id)); + opts_list = qemu_find_opts_err("object", NULL); + if (opts_list) { + qemu_opts_del(qemu_opts_find(opts_list, id)); + } object_unparent(obj); return true; diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c index b40ac39f30..2d6f41ecc7 100644 --- a/qom/qom-qmp-cmds.c +++ b/qom/qom-qmp-cmds.c @@ -19,8 +19,11 @@ #include "qapi/error.h" #include "qapi/qapi-commands-qdev.h" #include "qapi/qapi-commands-qom.h" +#include "qapi/qapi-visit-qom.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" +#include "qapi/qobject-input-visitor.h" +#include "qapi/qobject-output-visitor.h" #include "qemu/cutils.h" #include "qom/object_interfaces.h" #include "qom/qom-qobject.h" @@ -223,30 +226,9 @@ ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename, return prop_list; } -void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp) +void qmp_object_add(ObjectOptions *options, Error **errp) { - QObject *props; - QDict *pdict; - - props = qdict_get(qdict, "props"); - if (props) { - pdict = qobject_to(QDict, props); - if (!pdict) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); - return; - } - qobject_ref(pdict); - qdict_del(qdict, "props"); - qdict_join(qdict, pdict, false); - if (qdict_size(pdict) != 0) { - error_setg(errp, "Option in 'props' conflicts with top level"); - qobject_unref(pdict); - return; - } - qobject_unref(pdict); - } - - user_creatable_add_dict(qdict, false, errp); + user_creatable_add_qapi(options, errp); } void qmp_object_del(const char *id, Error **errp) diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 0a75a9371b..0e13d51054 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -96,7 +96,7 @@ static void qmp_marshal_output_%(c_name)s(%(c_type)s ret_in, { Visitor *v; - v = qobject_output_visitor_new(ret_out); + v = qobject_output_visitor_new_qmp(ret_out); if (visit_type_%(c_name)s(v, "unused", &ret_in, errp)) { visit_complete(v, ret_out); } @@ -154,7 +154,7 @@ def gen_marshal(name: str, ret += mcgen(''' - v = qobject_input_visitor_new(QOBJECT(args)); + v = qobject_input_visitor_new_qmp(QOBJECT(args)); if (!visit_start_struct(v, NULL, NULL, 0, errp)) { goto out; } @@ -210,12 +210,16 @@ out: def gen_register_command(name: str, + features: List[QAPISchemaFeature], success_response: bool, allow_oob: bool, allow_preconfig: bool, coroutine: bool) -> str: options = [] + if 'deprecated' in [f.name for f in features]: + options += ['QCO_DEPRECATED'] + if not success_response: options += ['QCO_NO_SUCCESS_RESP'] if allow_oob: @@ -251,10 +255,9 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor): visit = self._module_basename('qapi-visit', name) self._genc.add(mcgen(''' #include "qemu/osdep.h" +#include "qapi/compat-policy.h" #include "qapi/visitor.h" #include "qapi/qmp/qdict.h" -#include "qapi/qobject-output-visitor.h" -#include "qapi/qobject-input-visitor.h" #include "qapi/dealloc-visitor.h" #include "qapi/error.h" #include "%(visit)s.h" @@ -326,9 +329,9 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds) self._genc.add(gen_marshal(name, arg_type, boxed, ret_type)) with self._temp_module('./init'): with ifcontext(ifcond, self._genh, self._genc): - self._genc.add(gen_register_command(name, success_response, - allow_oob, allow_preconfig, - coroutine)) + self._genc.add(gen_register_command( + name, features, success_response, allow_oob, + allow_preconfig, coroutine)) def gen_commands(schema: QAPISchema, diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py index 90d2f6156d..fee8c671e7 100644 --- a/scripts/qapi/events.py +++ b/scripts/qapi/events.py @@ -79,6 +79,7 @@ def gen_param_var(typ: QAPISchemaObjectType) -> str: def gen_event_send(name: str, arg_type: Optional[QAPISchemaObjectType], + features: List[QAPISchemaFeature], boxed: bool, event_enum_name: str, event_emit: str) -> str: @@ -107,6 +108,14 @@ def gen_event_send(name: str, if not boxed: ret += gen_param_var(arg_type) + if 'deprecated' in [f.name for f in features]: + ret += mcgen(''' + + if (compat_policy.deprecated_output == COMPAT_POLICY_OUTPUT_HIDE) { + return; + } +''') + ret += mcgen(''' qmp = qmp_event_build_dict("%(name)s"); @@ -117,7 +126,7 @@ def gen_event_send(name: str, if have_args: assert arg_type is not None ret += mcgen(''' - v = qobject_output_visitor_new(&obj); + v = qobject_output_visitor_new_qmp(&obj); ''') if not arg_type.is_implicit(): ret += mcgen(''' @@ -136,7 +145,11 @@ def gen_event_send(name: str, ret += mcgen(''' visit_complete(v, &obj); - qdict_put_obj(qmp, "data", obj); + if (qdict_size(qobject_to(QDict, obj))) { + qdict_put_obj(qmp, "data", obj); + } else { + qobject_unref(obj); + } ''') ret += mcgen(''' @@ -176,9 +189,9 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor): #include "%(prefix)sqapi-emit-events.h" #include "%(events)s.h" #include "%(visit)s.h" +#include "qapi/compat-policy.h" #include "qapi/error.h" #include "qapi/qmp/qdict.h" -#include "qapi/qobject-output-visitor.h" #include "qapi/qmp-event.h" ''', @@ -220,7 +233,7 @@ void %(event_emit)s(%(event_enum)s event, QDict *qdict); boxed: bool) -> None: with ifcontext(ifcond, self._genh, self._genc): self._genh.add(gen_event_send_decl(name, arg_type, boxed)) - self._genc.add(gen_event_send(name, arg_type, boxed, + self._genc.add(gen_event_send(name, arg_type, features, boxed, self._event_enum_name, self._event_emit_name)) # Note: we generate the enum member regardless of @ifcond, to diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py index 9aa0b1e11e..9e96f3c566 100644 --- a/scripts/qapi/visit.py +++ b/scripts/qapi/visit.py @@ -77,6 +77,7 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp) c_type=base.c_name()) for memb in members: + deprecated = 'deprecated' in [f.name for f in memb.features] ret += gen_if(memb.ifcond) if memb.optional: ret += mcgen(''' @@ -84,6 +85,15 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp) ''', name=memb.name, c_name=c_name(memb.name)) indent.increase() + if deprecated: + ret += mcgen(''' + if (!visit_deprecated_accept(v, "%(name)s", errp)) { + return false; + } + if (visit_deprecated(v, "%(name)s")) { +''', + name=memb.name) + indent.increase() ret += mcgen(''' if (!visit_type_%(c_type)s(v, "%(name)s", &obj->%(c_name)s, errp)) { return false; @@ -91,6 +101,11 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp) ''', c_type=memb.type.c_name(), name=memb.name, c_name=c_name(memb.name)) + if deprecated: + indent.decrease() + ret += mcgen(''' + } +''') if memb.optional: indent.decrease() ret += mcgen(''' diff --git a/softmmu/vl.c b/softmmu/vl.c index 4208f5f958..aadb526138 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -29,8 +29,10 @@ #include "exec/cpu-common.h" #include "hw/boards.h" #include "hw/qdev-properties.h" +#include "qapi/compat-policy.h" #include "qapi/error.h" #include "qapi/qmp/qdict.h" +#include "qapi/qmp/qjson.h" #include "qemu-version.h" #include "qemu/cutils.h" #include "qemu/help_option.h" @@ -113,10 +115,12 @@ #include "sysemu/replay.h" #include "qapi/qapi-events-run-state.h" #include "qapi/qapi-visit-block-core.h" +#include "qapi/qapi-visit-compat.h" #include "qapi/qapi-visit-ui.h" #include "qapi/qapi-commands-block-core.h" #include "qapi/qapi-commands-migration.h" #include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-visit-qom.h" #include "qapi/qapi-commands-ui.h" #include "qapi/qmp/qerror.h" #include "sysemu/iothread.h" @@ -132,10 +136,16 @@ typedef struct BlockdevOptionsQueueEntry { typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue; +typedef struct ObjectOption { + ObjectOptions *opts; + QTAILQ_ENTRY(ObjectOption) next; +} ObjectOption; + static const char *cpu_option; static const char *mem_path; static const char *incoming; static const char *loadvm; +static QTAILQ_HEAD(, ObjectOption) object_opts = QTAILQ_HEAD_INITIALIZER(object_opts); static ram_addr_t maxram_size; static uint64_t ram_slots; static int display_remote; @@ -917,7 +927,7 @@ static const VGAInterfaceInfo vga_interfaces[VGA_TYPE_MAX] = { [VGA_TCX] = { .opt_name = "tcx", .name = "TCX framebuffer", - .class_names = { "SUNW,tcx" }, + .class_names = { "sun-tcx" }, }, [VGA_CG3] = { .opt_name = "cg3", @@ -1683,6 +1693,58 @@ static int machine_set_property(void *opaque, return object_parse_property_opt(opaque, name, value, "type", errp); } +static void object_option_foreach_add(bool (*type_opt_predicate)(const char *)) +{ + ObjectOption *opt, *next; + + QTAILQ_FOREACH_SAFE(opt, &object_opts, next, next) { + const char *type = ObjectType_str(opt->opts->qom_type); + if (type_opt_predicate(type)) { + user_creatable_add_qapi(opt->opts, &error_fatal); + qapi_free_ObjectOptions(opt->opts); + QTAILQ_REMOVE(&object_opts, opt, next); + g_free(opt); + } + } +} + +static void object_option_parse(const char *optarg) +{ + ObjectOption *opt; + QemuOpts *opts; + const char *type; + Visitor *v; + + if (optarg[0] == '{') { + QObject *obj = qobject_from_json(optarg, &error_fatal); + + v = qobject_input_visitor_new(obj); + qobject_unref(obj); + } else { + opts = qemu_opts_parse_noisily(qemu_find_opts("object"), + optarg, true); + if (!opts) { + exit(1); + } + + type = qemu_opt_get(opts, "qom-type"); + if (!type) { + error_setg(&error_fatal, QERR_MISSING_PARAMETER, "qom-type"); + } + if (user_creatable_print_help(type, opts)) { + exit(0); + } + + v = opts_visitor_new(opts); + } + + opt = g_new0(ObjectOption, 1); + visit_type_ObjectOptions(v, NULL, &opt->opts, &error_fatal); + visit_free(v); + + QTAILQ_INSERT_TAIL(&object_opts, opt, next); +} + /* * Initial object creation happens before all other * QEMU data types are created. The majority of objects @@ -1690,12 +1752,8 @@ static int machine_set_property(void *opaque, * cannot be created here, as it depends on the chardev * already existing. */ -static bool object_create_early(const char *type, QemuOpts *opts) +static bool object_create_early(const char *type) { - if (user_creatable_print_help(type, opts)) { - exit(0); - } - /* * Objects should not be made "delayed" without a reason. If you * add one, state the reason in a comment! @@ -1814,9 +1872,7 @@ static void qemu_create_early_backends(void) exit(1); } - qemu_opts_foreach(qemu_find_opts("object"), - user_creatable_add_opts_foreach, - object_create_early, &error_fatal); + object_option_foreach_add(object_create_early); /* spice needs the timers to be initialized by this point */ /* spice must initialize before audio as it changes the default auiodev */ @@ -1845,9 +1901,9 @@ static void qemu_create_early_backends(void) * The remainder of object creation happens after the * creation of chardev, fsdev, net clients and device data types. */ -static bool object_create_late(const char *type, QemuOpts *opts) +static bool object_create_late(const char *type) { - return !object_create_early(type, opts); + return !object_create_early(type); } static void qemu_create_late_backends(void) @@ -1858,9 +1914,7 @@ static void qemu_create_late_backends(void) net_init_clients(&error_fatal); - qemu_opts_foreach(qemu_find_opts("object"), - user_creatable_add_opts_foreach, - object_create_late, &error_fatal); + object_option_foreach_add(object_create_late); if (tpm_init() < 0) { exit(1); @@ -2459,13 +2513,7 @@ static void qemu_init_board(void) /* From here on we enter MACHINE_PHASE_INITIALIZED. */ machine_run_board_init(current_machine); - /* - * TODO To drop support for deprecated bogus if=..., move - * drive_check_orphaned() here, replacing this call. Also drop - * its deprecation warning, along with DriveInfo member - * @claimed_by_board. - */ - drive_mark_claimed_by_board(); + drive_check_orphaned(); realtime_init(); @@ -3395,11 +3443,7 @@ void qemu_init(int argc, char **argv, char **envp) #endif break; case QEMU_OPTION_object: - opts = qemu_opts_parse_noisily(qemu_find_opts("object"), - optarg, true); - if (!opts) { - exit(1); - } + object_option_parse(optarg); break; case QEMU_OPTION_overcommit: opts = qemu_opts_parse_noisily(qemu_find_opts("overcommit"), @@ -3410,6 +3454,21 @@ void qemu_init(int argc, char **argv, char **envp) enable_mlock = qemu_opt_get_bool(opts, "mem-lock", false); enable_cpu_pm = qemu_opt_get_bool(opts, "cpu-pm", false); break; + case QEMU_OPTION_compat: + { + CompatPolicy *opts; + Visitor *v; + + v = qobject_input_visitor_new_str(optarg, NULL, + &error_fatal); + + visit_type_CompatPolicy(v, NULL, &opts, &error_fatal); + QAPI_CLONE_MEMBERS(CompatPolicy, &compat_policy, opts); + + qapi_free_CompatPolicy(opts); + visit_free(v); + break; + } case QEMU_OPTION_msg: opts = qemu_opts_parse_noisily(qemu_find_opts("msg"), optarg, false); diff --git a/storage-daemon/qapi/qapi-schema.json b/storage-daemon/qapi/qapi-schema.json index 28117c3aac..67749d1101 100644 --- a/storage-daemon/qapi/qapi-schema.json +++ b/storage-daemon/qapi/qapi-schema.json @@ -26,6 +26,7 @@ { 'include': '../../qapi/crypto.json' } { 'include': '../../qapi/introspect.json' } { 'include': '../../qapi/job.json' } +{ 'include': '../../qapi/authz.json' } { 'include': '../../qapi/qom.json' } { 'include': '../../qapi/sockets.json' } { 'include': '../../qapi/transaction.json' } diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c index 23756fc8e5..72900dc2ec 100644 --- a/storage-daemon/qemu-storage-daemon.c +++ b/storage-daemon/qemu-storage-daemon.c @@ -134,22 +134,9 @@ enum { extern QemuOptsList qemu_chardev_opts; -static QemuOptsList qemu_object_opts = { - .name = "object", - .implied_opt_name = "qom-type", - .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head), - .desc = { - { } - }, -}; - static void init_qmp_commands(void) { qmp_init_marshal(&qmp_commands); - qmp_register_command(&qmp_commands, "query-qmp-schema", - qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG); - qmp_register_command(&qmp_commands, "object-add", qmp_object_add, - QCO_NO_OPTIONS); QTAILQ_INIT(&qmp_cap_negotiation_commands); qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities", @@ -281,19 +268,8 @@ static void process_options(int argc, char *argv[]) break; } case OPTION_OBJECT: - { - QDict *args; - bool help; - - args = keyval_parse(optarg, "qom-type", &help, &error_fatal); - if (help) { - user_creatable_print_help_from_qdict(args); - exit(EXIT_SUCCESS); - } - user_creatable_add_dict(args, true, &error_fatal); - qobject_unref(args); - break; - } + user_creatable_process_cmdline(optarg); + break; case OPTION_PIDFILE: pid_file = optarg; break; @@ -340,7 +316,6 @@ int main(int argc, char *argv[]) module_call_init(MODULE_INIT_QOM); module_call_init(MODULE_INIT_TRACE); - qemu_add_opts(&qemu_object_opts); qemu_add_opts(&qemu_trace_opts); qcrypto_init(&error_fatal); bdrv_init(); @@ -368,6 +343,7 @@ int main(int argc, char *argv[]) blk_exp_close_all(); bdrv_drain_all_begin(); + job_cancel_sync_all(); bdrv_close_all(); monitor_cleanup(); diff --git a/stubs/meson.build b/stubs/meson.build index a054d5877f..8a3e804cf0 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -34,7 +34,6 @@ stub_ss.add(files('ram-block.c')) stub_ss.add(files('ramfb.c')) stub_ss.add(files('replay.c')) stub_ss.add(files('runstate-check.c')) -stub_ss.add(files('set-fd-handler.c')) stub_ss.add(files('sysbus.c')) stub_ss.add(files('target-get-monitor-def.c')) stub_ss.add(files('target-monitor-defs.c')) diff --git a/stubs/set-fd-handler.c b/stubs/set-fd-handler.c deleted file mode 100644 index bff7e0a45a..0000000000 --- a/stubs/set-fd-handler.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "qemu/osdep.h" -#include "qemu/main-loop.h" - -void qemu_set_fd_handler(int fd, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque) -{ - abort(); -} diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index 63f92adf68..12ec588b52 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -299,14 +299,15 @@ 'features': [ 'feature1' ] } { 'command': 'test-features0', - 'data': { 'fs0': 'FeatureStruct0', - 'fs1': 'FeatureStruct1', - 'fs2': 'FeatureStruct2', - 'fs3': 'FeatureStruct3', - 'fs4': 'FeatureStruct4', - 'cfs1': 'CondFeatureStruct1', - 'cfs2': 'CondFeatureStruct2', - 'cfs3': 'CondFeatureStruct3' }, + 'data': { '*fs0': 'FeatureStruct0', + '*fs1': 'FeatureStruct1', + '*fs2': 'FeatureStruct2', + '*fs3': 'FeatureStruct3', + '*fs4': 'FeatureStruct4', + '*cfs1': 'CondFeatureStruct1', + '*cfs2': 'CondFeatureStruct2', + '*cfs3': 'CondFeatureStruct3' }, + 'returns': 'FeatureStruct1', 'features': [] } { 'command': 'test-command-features1', @@ -323,5 +324,8 @@ 'features': [ { 'name': 'feature1', 'if': [ 'defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)'] } ] } +{ 'event': 'TEST-EVENT-FEATURES0', + 'data': 'FeatureStruct1' } + { 'event': 'TEST-EVENT-FEATURES1', 'features': [ 'deprecated' ] } diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index 3b1387d9f1..f5741df97f 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -409,15 +409,15 @@ alternate FeatureAlternate1 case eins: FeatureStruct1 feature feature1 object q_obj_test-features0-arg - member fs0: FeatureStruct0 optional=False - member fs1: FeatureStruct1 optional=False - member fs2: FeatureStruct2 optional=False - member fs3: FeatureStruct3 optional=False - member fs4: FeatureStruct4 optional=False - member cfs1: CondFeatureStruct1 optional=False - member cfs2: CondFeatureStruct2 optional=False - member cfs3: CondFeatureStruct3 optional=False -command test-features0 q_obj_test-features0-arg -> None + member fs0: FeatureStruct0 optional=True + member fs1: FeatureStruct1 optional=True + member fs2: FeatureStruct2 optional=True + member fs3: FeatureStruct3 optional=True + member fs4: FeatureStruct4 optional=True + member cfs1: CondFeatureStruct1 optional=True + member cfs2: CondFeatureStruct2 optional=True + member cfs3: CondFeatureStruct3 optional=True +command test-features0 q_obj_test-features0-arg -> FeatureStruct1 gen=True success_response=True boxed=False oob=False preconfig=False command test-command-features1 None -> None gen=True success_response=True boxed=False oob=False preconfig=False @@ -440,6 +440,8 @@ command test-command-cond-features3 None -> None gen=True success_response=True boxed=False oob=False preconfig=False feature feature1 if ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)'] +event TEST-EVENT-FEATURES0 FeatureStruct1 + boxed=False event TEST-EVENT-FEATURES1 None boxed=False feature deprecated diff --git a/tests/qemu-iotests/172 b/tests/qemu-iotests/172 index 0ac942a6c5..ff269ca7b5 100755 --- a/tests/qemu-iotests/172 +++ b/tests/qemu-iotests/172 @@ -125,15 +125,6 @@ check_floppy_qtree -drive if=floppy,file="$TEST_IMG" -drive if=floppy,file="$TES echo echo -echo === Using -drive if=none and -global === - -check_floppy_qtree -drive if=none,file="$TEST_IMG" -global isa-fdc.driveA=none0 -check_floppy_qtree -drive if=none,file="$TEST_IMG" -global isa-fdc.driveB=none0 -check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \ - -global isa-fdc.driveA=none0 -global isa-fdc.driveB=none1 - -echo -echo echo === Using -drive if=none and -device === check_floppy_qtree -drive if=none,file="$TEST_IMG" -device floppy,drive=none0 @@ -145,13 +136,6 @@ echo echo echo === Mixing -fdX and -global === -# Working -check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global isa-fdc.driveB=none0 -check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global isa-fdc.driveA=none0 - -# Conflicting -check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global isa-fdc.driveA=none0 -check_floppy_qtree -fdb "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global isa-fdc.driveB=none0 # Conflicting, -fdX wins check_floppy_qtree -fda "$TEST_IMG" -drive if=none,file="$TEST_IMG.2" -global floppy.drive=none0 @@ -186,24 +170,11 @@ echo echo === Mixing -global and -device === # Working -check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \ - -global isa-fdc.driveA=none0 -device floppy,drive=none1 -check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \ - -global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=1 - -check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \ - -global isa-fdc.driveB=none0 -device floppy,drive=none1 -check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \ - -global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=0 check_floppy_qtree -drive if=none,file="$TEST_IMG" \ -global floppy.drive=none0 -device floppy,unit=0 # Conflicting check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \ - -global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=0 -check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \ - -global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=1 -check_floppy_qtree -drive if=none,file="$TEST_IMG" -drive if=none,file="$TEST_IMG.2" \ -global floppy.drive=none0 -device floppy,drive=none1,unit=0 echo @@ -227,7 +198,7 @@ echo === Too many floppy drives === check_floppy_qtree -drive if=floppy,file="$TEST_IMG" \ -drive if=none,file="$TEST_IMG.2" \ -drive if=none,file="$TEST_IMG.3" \ - -global isa-fdc.driveB=none0 \ + -device floppy,drive=none0 \ -device floppy,drive=none1 echo diff --git a/tests/qemu-iotests/172.out b/tests/qemu-iotests/172.out index 349ae51d6c..d53f61d0de 100644 --- a/tests/qemu-iotests/172.out +++ b/tests/qemu-iotests/172.out @@ -12,8 +12,6 @@ Testing: iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -41,8 +39,6 @@ Testing: -fda TEST_DIR/t.qcow2 iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -80,8 +76,6 @@ Testing: -fdb TEST_DIR/t.qcow2 iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -134,8 +128,6 @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2 iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -189,8 +181,6 @@ Testing: -fdb iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -229,8 +219,6 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -268,8 +256,6 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1 iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -322,8 +308,6 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -372,150 +356,6 @@ sd0: [not inserted] -=== Using -drive if=none and -global === - -Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveA=none0 -QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated -Use -device floppy,unit=0,drive=... instead. - - dev: isa-fdc, id "" - iobase = 1008 (0x3f0) - irq = 6 (0x6) - dma = 2 (0x2) - driveA = "" - driveB = "" - fdtypeA = "auto" - fdtypeB = "auto" - fallback = "288" - isa irq 6 - bus: floppy-bus.0 - type floppy-bus - dev: floppy, id "" - unit = 0 (0x0) - drive = "none0" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" -none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -ide1-cd0: [not inserted] - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - -sd0: [not inserted] - Removable device: not locked, tray closed -(qemu) quit - - -Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global isa-fdc.driveB=none0 -QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated -Use -device floppy,unit=1,drive=... instead. - - dev: isa-fdc, id "" - iobase = 1008 (0x3f0) - irq = 6 (0x6) - dma = 2 (0x2) - driveA = "" - driveB = "" - fdtypeA = "auto" - fdtypeB = "auto" - fallback = "288" - isa irq 6 - bus: floppy-bus.0 - type floppy-bus - dev: floppy, id "" - unit = 1 (0x1) - drive = "none0" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" -none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -ide1-cd0: [not inserted] - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - -sd0: [not inserted] - Removable device: not locked, tray closed -(qemu) quit - - -Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -global isa-fdc.driveB=none1 -QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated -Use -device floppy,unit=0,drive=... instead. -QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated -Use -device floppy,unit=1,drive=... instead. - - dev: isa-fdc, id "" - iobase = 1008 (0x3f0) - irq = 6 (0x6) - dma = 2 (0x2) - driveA = "" - driveB = "" - fdtypeA = "auto" - fdtypeB = "auto" - fallback = "288" - isa irq 6 - bus: floppy-bus.0 - type floppy-bus - dev: floppy, id "" - unit = 1 (0x1) - drive = "none1" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" - dev: floppy, id "" - unit = 0 (0x0) - drive = "none0" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" -none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -ide1-cd0: [not inserted] - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - -sd0: [not inserted] - Removable device: not locked, tray closed -(qemu) quit - - - === Using -drive if=none and -device === Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0 @@ -524,8 +364,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0 iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -563,8 +401,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1 iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -602,8 +438,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -654,130 +488,6 @@ sd0: [not inserted] === Mixing -fdX and -global === -Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 -QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated -Use -device floppy,unit=1,drive=... instead. - - dev: isa-fdc, id "" - iobase = 1008 (0x3f0) - irq = 6 (0x6) - dma = 2 (0x2) - driveA = "" - driveB = "" - fdtypeA = "auto" - fdtypeB = "auto" - fallback = "288" - isa irq 6 - bus: floppy-bus.0 - type floppy-bus - dev: floppy, id "" - unit = 0 (0x0) - drive = "floppy0" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" - dev: floppy, id "" - unit = 1 (0x1) - drive = "none0" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" -floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -ide1-cd0: [not inserted] - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - -sd0: [not inserted] - Removable device: not locked, tray closed -(qemu) quit - - -Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated -Use -device floppy,unit=0,drive=... instead. - - dev: isa-fdc, id "" - iobase = 1008 (0x3f0) - irq = 6 (0x6) - dma = 2 (0x2) - driveA = "" - driveB = "" - fdtypeA = "auto" - fdtypeB = "auto" - fallback = "288" - isa irq 6 - bus: floppy-bus.0 - type floppy-bus - dev: floppy, id "" - unit = 1 (0x1) - drive = "floppy1" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" - dev: floppy, id "" - unit = 0 (0x0) - drive = "none0" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" -floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -ide1-cd0: [not inserted] - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - -sd0: [not inserted] - Removable device: not locked, tray closed -(qemu) quit - - -Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated -Use -device floppy,unit=0,drive=... instead. -QEMU_PROG: Floppy unit 0 is in use - -Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 -QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated -Use -device floppy,unit=1,drive=... instead. -QEMU_PROG: Floppy unit 1 is in use - Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global floppy.drive=none0 QEMU_PROG: -global floppy.drive=... conflicts with drive=floppy0 @@ -790,8 +500,6 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -845,8 +553,6 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -900,8 +606,6 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -955,8 +659,6 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -1019,8 +721,6 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -1074,8 +774,6 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -1129,242 +827,12 @@ QEMU_PROG: -device floppy,drive=none0,unit=0: Floppy unit 0 is in use === Mixing -global and -device === -Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -device floppy,drive=none1 -QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated -Use -device floppy,unit=0,drive=... instead. - - dev: isa-fdc, id "" - iobase = 1008 (0x3f0) - irq = 6 (0x6) - dma = 2 (0x2) - driveA = "" - driveB = "" - fdtypeA = "auto" - fdtypeB = "auto" - fallback = "288" - isa irq 6 - bus: floppy-bus.0 - type floppy-bus - dev: floppy, id "" - unit = 1 (0x1) - drive = "none1" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" - dev: floppy, id "" - unit = 0 (0x0) - drive = "none0" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" -none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) - Attached to: /machine/peripheral-anon/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -ide1-cd0: [not inserted] - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - -sd0: [not inserted] - Removable device: not locked, tray closed -(qemu) quit - - -Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=1 -QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated -Use -device floppy,unit=0,drive=... instead. - - dev: isa-fdc, id "" - iobase = 1008 (0x3f0) - irq = 6 (0x6) - dma = 2 (0x2) - driveA = "" - driveB = "" - fdtypeA = "auto" - fdtypeB = "auto" - fallback = "288" - isa irq 6 - bus: floppy-bus.0 - type floppy-bus - dev: floppy, id "" - unit = 1 (0x1) - drive = "none1" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" - dev: floppy, id "" - unit = 0 (0x0) - drive = "none0" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" -none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) - Attached to: /machine/peripheral-anon/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -ide1-cd0: [not inserted] - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - -sd0: [not inserted] - Removable device: not locked, tray closed -(qemu) quit - - -Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 -device floppy,drive=none1 -QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated -Use -device floppy,unit=1,drive=... instead. - - dev: isa-fdc, id "" - iobase = 1008 (0x3f0) - irq = 6 (0x6) - dma = 2 (0x2) - driveA = "" - driveB = "" - fdtypeA = "auto" - fdtypeB = "auto" - fallback = "288" - isa irq 6 - bus: floppy-bus.0 - type floppy-bus - dev: floppy, id "" - unit = 0 (0x0) - drive = "none1" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" - dev: floppy, id "" - unit = 1 (0x1) - drive = "none0" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" -none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) - Attached to: /machine/peripheral-anon/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -ide1-cd0: [not inserted] - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - -sd0: [not inserted] - Removable device: not locked, tray closed -(qemu) quit - - -Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=0 -QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated -Use -device floppy,unit=1,drive=... instead. - - dev: isa-fdc, id "" - iobase = 1008 (0x3f0) - irq = 6 (0x6) - dma = 2 (0x2) - driveA = "" - driveB = "" - fdtypeA = "auto" - fdtypeB = "auto" - fallback = "288" - isa irq 6 - bus: floppy-bus.0 - type floppy-bus - dev: floppy, id "" - unit = 0 (0x0) - drive = "none1" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" - dev: floppy, id "" - unit = 1 (0x1) - drive = "none0" - logical_block_size = 512 (512 B) - physical_block_size = 512 (512 B) - min_io_size = 0 (0 B) - opt_io_size = 0 (0 B) - discard_granularity = 4294967295 (4 GiB) - write-cache = "auto" - share-rw = false - drive-type = "144" -none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2) - Attached to: /machine/peripheral-anon/device[N] - Removable device: not locked, tray closed - Cache mode: writeback - -ide1-cd0: [not inserted] - Attached to: /machine/unattached/device[N] - Removable device: not locked, tray closed - -sd0: [not inserted] - Removable device: not locked, tray closed -(qemu) quit - - Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global floppy.drive=none0 -device floppy,unit=0 dev: isa-fdc, id "" iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -1396,16 +864,6 @@ sd0: [not inserted] (qemu) quit -Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveA=none0 -device floppy,drive=none1,unit=0 -QEMU_PROG: warning: warning: property isa-fdc.driveA is deprecated -Use -device floppy,unit=0,drive=... instead. -QEMU_PROG: -device floppy,drive=none1,unit=0: Floppy unit 0 is in use - -Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global isa-fdc.driveB=none0 -device floppy,drive=none1,unit=1 -QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated -Use -device floppy,unit=1,drive=... instead. -QEMU_PROG: -device floppy,drive=none1,unit=1: Floppy unit 1 is in use - Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -global floppy.drive=none0 -device floppy,drive=none1,unit=0 QEMU_PROG: -device floppy,drive=none1,unit=0: -global floppy.drive=... conflicts with drive=none1 @@ -1430,9 +888,7 @@ QEMU_PROG: -device floppy,drive=floppy0: Property 'floppy.drive' can't find valu === Too many floppy drives === -Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -drive if=none,file=TEST_DIR/t.qcow2.3 -global isa-fdc.driveB=none0 -device floppy,drive=none1 -QEMU_PROG: warning: warning: property isa-fdc.driveB is deprecated -Use -device floppy,unit=1,drive=... instead. +Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -drive if=none,file=TEST_DIR/t.qcow2.3 -device floppy,drive=none0 -device floppy,drive=none1 QEMU_PROG: -device floppy,drive=none1: Can't create floppy unit 2, bus supports only 2 units @@ -1444,8 +900,6 @@ Testing: -device floppy iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -1470,8 +924,6 @@ Testing: -device floppy,drive-type=120 iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -1496,8 +948,6 @@ Testing: -device floppy,drive-type=144 iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -1522,8 +972,6 @@ Testing: -device floppy,drive-type=288 iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -1551,8 +999,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -1590,8 +1036,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -1632,8 +1076,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,logical iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" @@ -1671,8 +1113,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physica iobase = 1008 (0x3f0) irq = 6 (0x6) dma = 2 (0x2) - driveA = "" - driveB = "" fdtypeA = "auto" fdtypeB = "auto" fallback = "288" diff --git a/tests/qemu-iotests/tests/qsd-jobs b/tests/qemu-iotests/tests/qsd-jobs new file mode 100755 index 0000000000..972b6b3898 --- /dev/null +++ b/tests/qemu-iotests/tests/qsd-jobs @@ -0,0 +1,86 @@ +#!/usr/bin/env bash +# group: rw auto quick qsd +# +# Job tests related specifically to qemu-storage-daemon +# +# Copyright (C) 2021 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=kwolf@redhat.com + +seq="$(basename $0)" +echo "QA output created by $seq" + +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img + rm -f "$SOCK_DIR/nbd.sock" +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +cd .. +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto generic + +size=128M + +TEST_IMG="$TEST_IMG.base" _make_test_img $size +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT + +echo +echo "=== Job still present at shutdown ===" +echo + +# Just make sure that this doesn't crash +$QSD --chardev stdio,id=stdio --monitor chardev=stdio \ + --blockdev node-name=file0,driver=file,filename="$TEST_IMG" \ + --blockdev node-name=fmt0,driver=qcow2,file=file0 <<EOF | _filter_qmp +{"execute":"qmp_capabilities"} +{"execute": "block-commit", "arguments": {"device": "fmt0", "job-id": "job0"}} +{"execute": "quit"} +EOF + +echo +echo "=== Streaming can't get permission on base node ===" +echo + +# Just make sure that this doesn't crash +$QSD --chardev stdio,id=stdio --monitor chardev=stdio \ + --blockdev node-name=file_base,driver=file,filename="$TEST_IMG.base" \ + --blockdev node-name=fmt_base,driver=qcow2,file=file_base \ + --blockdev node-name=file_overlay,driver=file,filename="$TEST_IMG" \ + --blockdev node-name=fmt_overlay,driver=qcow2,file=file_overlay,backing=fmt_base \ + --nbd-server addr.type=unix,addr.path="$SOCK_DIR/nbd.sock" \ + --export type=nbd,id=export1,node-name=fmt_base,writable=on,name=export1 \ + <<EOF | _filter_qmp +{"execute": "qmp_capabilities"} +{"execute": "block-stream", + "arguments": {"device": "fmt_overlay", "job-id": "job0"}} +{"execute": "quit"} +EOF + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 + diff --git a/tests/qemu-iotests/tests/qsd-jobs.out b/tests/qemu-iotests/tests/qsd-jobs.out new file mode 100644 index 0000000000..05e1165e80 --- /dev/null +++ b/tests/qemu-iotests/tests/qsd-jobs.out @@ -0,0 +1,32 @@ +QA output created by qsd-jobs +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT + +=== Job still present at shutdown === + +QMP_VERSION +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} + +=== Streaming can't get permission on base node === + +QMP_VERSION +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} +{"error": {"class": "GenericError", "desc": "Conflicts with use by a block device as 'root', which uses 'write' on fmt_base"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export1"}} +*** done diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h index 8b8c7ac553..004c701915 100644 --- a/tests/qtest/fuzz/generic_fuzz_configs.h +++ b/tests/qtest/fuzz/generic_fuzz_configs.h @@ -182,7 +182,7 @@ const generic_fuzz_config predefined_configs[] = { .name = "sdhci-v3", .args = "-nodefaults -device sdhci-pci,sd-spec-version=3 " "-device sd-card,drive=mydrive " - "-drive if=sd,index=0,file=null-co://,format=raw,id=mydrive -nographic", + "-drive if=none,index=0,file=null-co://,format=raw,id=mydrive -nographic", .objects = "sd*" },{ .name = "ehci", diff --git a/tests/qtest/qmp-cmd-test.c b/tests/qtest/qmp-cmd-test.c index 1c7186e53c..c98b78d033 100644 --- a/tests/qtest/qmp-cmd-test.c +++ b/tests/qtest/qmp-cmd-test.c @@ -230,14 +230,14 @@ static void test_object_add_failure_modes(void) /* attempt to create 2 objects with duplicate id */ resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," - " 'props': {'size': 1048576 } } }"); + " 'size': 1048576 } }"); g_assert_nonnull(resp); g_assert(qdict_haskey(resp, "return")); qobject_unref(resp); resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," - " 'props': {'size': 1048576 } } }"); + " 'size': 1048576 } }"); g_assert_nonnull(resp); qmp_expect_error_and_unref(resp, "GenericError"); @@ -251,14 +251,14 @@ static void test_object_add_failure_modes(void) /* attempt to create an object with a property of a wrong type */ resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," - " 'props': {'size': '1048576' } } }"); + " 'size': '1048576' } }"); g_assert_nonnull(resp); /* now do it right */ qmp_expect_error_and_unref(resp, "GenericError"); resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," - " 'props': {'size': 1048576 } } }"); + " 'size': 1048576 } }"); g_assert_nonnull(resp); g_assert(qdict_haskey(resp, "return")); qobject_unref(resp); @@ -273,14 +273,14 @@ static void test_object_add_failure_modes(void) /* attempt to create an object without the id */ resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" " {'qom-type': 'memory-backend-ram'," - " 'props': {'size': 1048576 } } }"); + " 'size': 1048576 } }"); g_assert_nonnull(resp); qmp_expect_error_and_unref(resp, "GenericError"); /* now do it right */ resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," - " 'props': {'size': 1048576 } } }"); + " 'size': 1048576 } }"); g_assert_nonnull(resp); g_assert(qdict_haskey(resp, "return")); qobject_unref(resp); @@ -295,14 +295,14 @@ static void test_object_add_failure_modes(void) /* attempt to set a non existing property */ resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," - " 'props': {'sized': 1048576 } } }"); + " 'sized': 1048576 } }"); g_assert_nonnull(resp); qmp_expect_error_and_unref(resp, "GenericError"); /* now do it right */ resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':" " {'qom-type': 'memory-backend-ram', 'id': 'ram1'," - " 'props': {'size': 1048576 } } }"); + " 'size': 1048576 } }"); g_assert_nonnull(resp); g_assert(qdict_haskey(resp, "return")); qobject_unref(resp); diff --git a/tests/qtest/test-netfilter.c b/tests/qtest/test-netfilter.c index 22927ee6ab..785b6f3226 100644 --- a/tests/qtest/test-netfilter.c +++ b/tests/qtest/test-netfilter.c @@ -21,11 +21,10 @@ static void add_one_netfilter(void) " 'arguments': {" " 'qom-type': 'filter-buffer'," " 'id': 'qtest-f0'," - " 'props': {" - " 'netdev': 'qtest-bn0'," - " 'queue': 'rx'," - " 'interval': 1000" - "}}}"); + " 'netdev': 'qtest-bn0'," + " 'queue': 'rx'," + " 'interval': 1000" + "}}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); @@ -49,11 +48,10 @@ static void remove_netdev_with_one_netfilter(void) " 'arguments': {" " 'qom-type': 'filter-buffer'," " 'id': 'qtest-f0'," - " 'props': {" - " 'netdev': 'qtest-bn0'," - " 'queue': 'rx'," - " 'interval': 1000" - "}}}"); + " 'netdev': 'qtest-bn0'," + " 'queue': 'rx'," + " 'interval': 1000" + "}}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); @@ -87,11 +85,10 @@ static void add_multi_netfilter(void) " 'arguments': {" " 'qom-type': 'filter-buffer'," " 'id': 'qtest-f0'," - " 'props': {" - " 'netdev': 'qtest-bn0'," - " 'queue': 'rx'," - " 'interval': 1000" - "}}}"); + " 'netdev': 'qtest-bn0'," + " 'queue': 'rx'," + " 'interval': 1000" + "}}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); @@ -101,11 +98,10 @@ static void add_multi_netfilter(void) " 'arguments': {" " 'qom-type': 'filter-buffer'," " 'id': 'qtest-f1'," - " 'props': {" - " 'netdev': 'qtest-bn0'," - " 'queue': 'rx'," - " 'interval': 1000" - "}}}"); + " 'netdev': 'qtest-bn0'," + " 'queue': 'rx'," + " 'interval': 1000" + "}}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); @@ -137,11 +133,10 @@ static void remove_netdev_with_multi_netfilter(void) " 'arguments': {" " 'qom-type': 'filter-buffer'," " 'id': 'qtest-f0'," - " 'props': {" - " 'netdev': 'qtest-bn0'," - " 'queue': 'rx'," - " 'interval': 1000" - "}}}"); + " 'netdev': 'qtest-bn0'," + " 'queue': 'rx'," + " 'interval': 1000" + "}}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); @@ -151,11 +146,10 @@ static void remove_netdev_with_multi_netfilter(void) " 'arguments': {" " 'qom-type': 'filter-buffer'," " 'id': 'qtest-f1'," - " 'props': {" - " 'netdev': 'qtest-bn0'," - " 'queue': 'rx'," - " 'interval': 1000" - "}}}"); + " 'netdev': 'qtest-bn0'," + " 'queue': 'rx'," + " 'interval': 1000" + "}}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); diff --git a/tests/unit/check-qom-proplist.c b/tests/unit/check-qom-proplist.c index 1b76581980..48503e0dff 100644 --- a/tests/unit/check-qom-proplist.c +++ b/tests/unit/check-qom-proplist.c @@ -21,6 +21,9 @@ #include "qemu/osdep.h" #include "qapi/error.h" +#include "qapi/qobject-input-visitor.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qobject.h" #include "qom/object.h" #include "qemu/module.h" #include "qemu/option.h" @@ -398,44 +401,74 @@ static void test_dummy_createlist(void) object_unparent(OBJECT(dobj)); } +static bool test_create_obj(QDict *qdict, Error **errp) +{ + Visitor *v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); + Object *obj = user_creatable_add_type(TYPE_DUMMY, "dev0", qdict, v, errp); + + visit_free(v); + object_unref(obj); + return !!obj; +} + static void test_dummy_createcmdl(void) { - QemuOpts *opts; + QDict *qdict; DummyObject *dobj; Error *err = NULL; - const char *params = TYPE_DUMMY \ - ",id=dev0," \ - "bv=yes,sv=Hiss hiss hiss,av=platypus"; + bool created, help; + const char *params = "bv=yes,sv=Hiss hiss hiss,av=platypus"; + /* Needed for user_creatable_del. */ qemu_add_opts(&qemu_object_opts); - opts = qemu_opts_parse(&qemu_object_opts, params, true, &err); + + qdict = keyval_parse(params, "qom-type", &help, &err); g_assert(err == NULL); - g_assert(opts); + g_assert(qdict); + g_assert(!help); - dobj = DUMMY_OBJECT(user_creatable_add_opts(opts, &err)); + created = test_create_obj(qdict, &err); + g_assert(created); g_assert(err == NULL); + qobject_unref(qdict); + + dobj = DUMMY_OBJECT(object_resolve_path_component(object_get_objects_root(), + "dev0")); g_assert(dobj); g_assert_cmpstr(dobj->sv, ==, "Hiss hiss hiss"); g_assert(dobj->bv == true); g_assert(dobj->av == DUMMY_PLATYPUS); + qdict = keyval_parse(params, "qom-type", &help, &err); + created = test_create_obj(qdict, &err); + g_assert(!created); + g_assert(err); + g_assert(object_resolve_path_component(object_get_objects_root(), "dev0") + == OBJECT(dobj)); + qobject_unref(qdict); + error_free(err); + err = NULL; + + qdict = keyval_parse(params, "qom-type", &help, &err); user_creatable_del("dev0", &error_abort); + g_assert(object_resolve_path_component(object_get_objects_root(), "dev0") + == NULL); - object_unref(OBJECT(dobj)); - - /* - * cmdline-parsing via qemu_opts_parse() results in a QemuOpts entry - * corresponding to the Object's ID to be added to the QemuOptsList - * for objects. To avoid having this entry conflict with future - * Objects using the same ID (which can happen in cases where - * qemu_opts_parse() is used to parse the object params, such as - * with hmp_object_add() at the time of this comment), we need to - * check for this in user_creatable_del() and remove the QemuOpts if - * it is present. - * - * The below check ensures this works as expected. - */ - g_assert_null(qemu_opts_find(&qemu_object_opts, "dev0")); + created = test_create_obj(qdict, &err); + g_assert(created); + g_assert(err == NULL); + qobject_unref(qdict); + + dobj = DUMMY_OBJECT(object_resolve_path_component(object_get_objects_root(), + "dev0")); + g_assert(dobj); + g_assert_cmpstr(dobj->sv, ==, "Hiss hiss hiss"); + g_assert(dobj->bv == true); + g_assert(dobj->av == DUMMY_PLATYPUS); + g_assert(object_resolve_path_component(object_get_objects_root(), "dev0") + == OBJECT(dobj)); + + object_unparent(OBJECT(dobj)); } static void test_dummy_badenum(void) diff --git a/tests/unit/test-char.c b/tests/unit/test-char.c index 755d54c15e..5b3b48ebac 100644 --- a/tests/unit/test-char.c +++ b/tests/unit/test-char.c @@ -1199,12 +1199,6 @@ static void char_serial_test(void) /* TODO: add more tests with a pty */ object_unparent(OBJECT(chr)); - /* test tty alias */ - qemu_opt_set(opts, "backend", "tty", &error_abort); - chr = qemu_chr_new_from_opts(opts, NULL, &error_abort); - g_assert_nonnull(chr); - object_unparent(OBJECT(chr)); - qemu_opts_del(opts); } #endif diff --git a/tests/unit/test-qmp-cmds.c b/tests/unit/test-qmp-cmds.c index d3413bfef0..266db074b4 100644 --- a/tests/unit/test-qmp-cmds.c +++ b/tests/unit/test-qmp-cmds.c @@ -1,4 +1,5 @@ #include "qemu/osdep.h" +#include "qapi/compat-policy.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qjson.h" #include "qapi/qmp/qnum.h" @@ -49,12 +50,17 @@ void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp) { } -void qmp_test_features0(FeatureStruct0 *fs0, FeatureStruct1 *fs1, - FeatureStruct2 *fs2, FeatureStruct3 *fs3, - FeatureStruct4 *fs4, CondFeatureStruct1 *cfs1, - CondFeatureStruct2 *cfs2, CondFeatureStruct3 *cfs3, - Error **errp) +FeatureStruct1 *qmp_test_features0(bool has_fs0, FeatureStruct0 *fs0, + bool has_fs1, FeatureStruct1 *fs1, + bool has_fs2, FeatureStruct2 *fs2, + bool has_fs3, FeatureStruct3 *fs3, + bool has_fs4, FeatureStruct4 *fs4, + bool has_cfs1, CondFeatureStruct1 *cfs1, + bool has_cfs2, CondFeatureStruct2 *cfs2, + bool has_cfs3, CondFeatureStruct3 *cfs3, + Error **errp) { + return g_new0(FeatureStruct1, 1); } void qmp_test_command_features1(Error **errp) @@ -275,6 +281,75 @@ static void test_dispatch_cmd_io(void) qobject_unref(ret3); } +static void test_dispatch_cmd_deprecated(void) +{ + const char *cmd = "{ 'execute': 'test-command-features1' }"; + QDict *ret; + + memset(&compat_policy, 0, sizeof(compat_policy)); + + /* accept */ + ret = qobject_to(QDict, do_qmp_dispatch(false, cmd)); + assert(ret && qdict_size(ret) == 0); + qobject_unref(ret); + + compat_policy.has_deprecated_input = true; + compat_policy.deprecated_input = COMPAT_POLICY_INPUT_ACCEPT; + ret = qobject_to(QDict, do_qmp_dispatch(false, cmd)); + assert(ret && qdict_size(ret) == 0); + qobject_unref(ret); + + compat_policy.deprecated_input = COMPAT_POLICY_INPUT_REJECT; + do_qmp_dispatch_error(false, ERROR_CLASS_COMMAND_NOT_FOUND, cmd); +} + +static void test_dispatch_cmd_arg_deprecated(void) +{ + const char *cmd = "{ 'execute': 'test-features0'," + " 'arguments': { 'fs1': { 'foo': 42 } } }"; + QDict *ret; + + memset(&compat_policy, 0, sizeof(compat_policy)); + + /* accept */ + ret = qobject_to(QDict, do_qmp_dispatch(false, cmd)); + assert(ret && qdict_size(ret) == 1); + qobject_unref(ret); + + compat_policy.has_deprecated_input = true; + compat_policy.deprecated_input = COMPAT_POLICY_INPUT_ACCEPT; + ret = qobject_to(QDict, do_qmp_dispatch(false, cmd)); + assert(ret && qdict_size(ret) == 1); + qobject_unref(ret); + + compat_policy.deprecated_input = COMPAT_POLICY_INPUT_REJECT; + do_qmp_dispatch_error(false, ERROR_CLASS_GENERIC_ERROR, cmd); +} + +static void test_dispatch_cmd_ret_deprecated(void) +{ + const char *cmd = "{ 'execute': 'test-features0' }"; + QDict *ret; + + memset(&compat_policy, 0, sizeof(compat_policy)); + + /* default accept */ + ret = qobject_to(QDict, do_qmp_dispatch(false, cmd)); + assert(ret && qdict_size(ret) == 1); + qobject_unref(ret); + + compat_policy.has_deprecated_output = true; + compat_policy.deprecated_output = COMPAT_POLICY_OUTPUT_ACCEPT; + ret = qobject_to(QDict, do_qmp_dispatch(false, cmd)); + assert(ret && qdict_size(ret) == 1); + qobject_unref(ret); + + compat_policy.deprecated_output = COMPAT_POLICY_OUTPUT_HIDE; + ret = qobject_to(QDict, do_qmp_dispatch(false, cmd)); + assert(ret && qdict_size(ret) == 0); + qobject_unref(ret); +} + /* test generated dealloc functions for generated types */ static void test_dealloc_types(void) { @@ -349,6 +424,12 @@ int main(int argc, char **argv) g_test_add_func("/qmp/dispatch_cmd_io", test_dispatch_cmd_io); g_test_add_func("/qmp/dispatch_cmd_success_response", test_dispatch_cmd_success_response); + g_test_add_func("/qmp/dispatch_cmd_deprecated", + test_dispatch_cmd_deprecated); + g_test_add_func("/qmp/dispatch_cmd_arg_deprecated", + test_dispatch_cmd_arg_deprecated); + g_test_add_func("/qmp/dispatch_cmd_ret_deprecated", + test_dispatch_cmd_ret_deprecated); g_test_add_func("/qmp/dealloc_types", test_dealloc_types); g_test_add_func("/qmp/dealloc_partial", test_dealloc_partial); diff --git a/tests/unit/test-qmp-event.c b/tests/unit/test-qmp-event.c index 7dd0053190..047f44ff9a 100644 --- a/tests/unit/test-qmp-event.c +++ b/tests/unit/test-qmp-event.c @@ -14,6 +14,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qapi/compat-policy.h" #include "qapi/error.h" #include "qapi/qmp/qbool.h" #include "qapi/qmp/qdict.h" @@ -140,6 +141,44 @@ static void test_event_d(TestEventData *data, qobject_unref(data->expect); } +static void test_event_deprecated(TestEventData *data, const void *unused) +{ + data->expect = qdict_from_jsonf_nofail("{ 'event': 'TEST-EVENT-FEATURES1' }"); + + memset(&compat_policy, 0, sizeof(compat_policy)); + + qapi_event_send_test_event_features1(); + g_assert(data->emitted); + + compat_policy.has_deprecated_output = true; + compat_policy.deprecated_output = COMPAT_POLICY_OUTPUT_HIDE; + data->emitted = false; + qapi_event_send_test_event_features1(); + g_assert(!data->emitted); + + qobject_unref(data->expect); +} + +static void test_event_deprecated_data(TestEventData *data, const void *unused) +{ + memset(&compat_policy, 0, sizeof(compat_policy)); + + data->expect = qdict_from_jsonf_nofail("{ 'event': 'TEST-EVENT-FEATURES0'," + " 'data': { 'foo': 42 } }"); + qapi_event_send_test_event_features0(42); + g_assert(data->emitted); + + qobject_unref(data->expect); + + compat_policy.has_deprecated_output = true; + compat_policy.deprecated_output = COMPAT_POLICY_OUTPUT_HIDE; + data->expect = qdict_from_jsonf_nofail("{ 'event': 'TEST-EVENT-FEATURES0' }"); + qapi_event_send_test_event_features0(42); + g_assert(data->emitted); + + qobject_unref(data->expect); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -148,6 +187,8 @@ int main(int argc, char **argv) event_test_add("/event/event_b", test_event_b); event_test_add("/event/event_c", test_event_c); event_test_add("/event/event_d", test_event_d); + event_test_add("/event/deprecated", test_event_deprecated); + event_test_add("/event/deprecated_data", test_event_deprecated_data); g_test_run(); return 0; diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c index 67486055ed..72b9246529 100644 --- a/tests/unit/test-util-sockets.c +++ b/tests/unit/test-util-sockets.c @@ -73,6 +73,7 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp) * otherwise we get duplicate syms at link time. */ Monitor *monitor_cur(void) { return cur_mon; } +Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); } int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); } #ifndef _WIN32 diff --git a/tests/vmstate-static-checker-data/dump1.json b/tests/vmstate-static-checker-data/dump1.json index 786ca0b484..334ec07963 100644 --- a/tests/vmstate-static-checker-data/dump1.json +++ b/tests/vmstate-static-checker-data/dump1.json @@ -823,8 +823,8 @@ ] } }, - "SUNW,fdtwo": { - "Name": "SUNW,fdtwo", + "sun-fdtwo": { + "Name": "sun-fdtwo", "version_id": 2, "minimum_version_id": 2, "Description": { diff --git a/tests/vmstate-static-checker-data/dump2.json b/tests/vmstate-static-checker-data/dump2.json index 75719f5ec9..7184e9ccbb 100644 --- a/tests/vmstate-static-checker-data/dump2.json +++ b/tests/vmstate-static-checker-data/dump2.json @@ -628,8 +628,8 @@ ] } }, - "SUNW,fdtwo": { - "Name": "SUNW,fdtwo", + "sun-fdtwo": { + "Name": "sun-fdtwo", "version_id": 2, "minimum_version_id": 2, "Description": { |