diff options
72 files changed, 1228 insertions, 1196 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 36d0c68..d881ba7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1920,6 +1920,7 @@ Block QAPI, monitor, command line M: Markus Armbruster <armbru@redhat.com> S: Supported F: blockdev.c +F: blockdev-hmp-cmds.c F: block/qapi.c F: qapi/block*.json F: qapi/transaction.json @@ -15,9 +15,6 @@ UNCHECKED_GOALS := %clean TAGS cscope ctags dist \ help check-help print-% \ docker docker-% vm-help vm-test vm-build-% -print-%: - @echo '$*=$($*)' - # All following code might depend on configuration variables ifneq ($(wildcard config-host.mak),) # Put the all: rule here so that config-host.mak can contain dependencies. diff --git a/Makefile.objs b/Makefile.objs index e288663..40d3a16 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -48,7 +48,7 @@ common-obj-y += dump/ common-obj-y += job-qmp.o common-obj-y += monitor/ common-obj-y += net/ -common-obj-y += qdev-monitor.o device-hotplug.o +common-obj-y += qdev-monitor.o common-obj-$(CONFIG_WIN32) += os-win32.o common-obj-$(CONFIG_POSIX) += os-posix.o diff --git a/block/Makefile.objs b/block/Makefile.objs index cb36ae2..3635b6b 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -45,6 +45,7 @@ block-obj-y += crypto.o block-obj-y += aio_task.o block-obj-y += backup-top.o block-obj-y += filter-compress.o +common-obj-y += monitor/ block-obj-y += stream.o diff --git a/block/file-posix.c b/block/file-posix.c index 6345477..0f77447 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -888,7 +888,6 @@ static int raw_handle_perm_lock(BlockDriverState *bs, "Is another process using the image [%s]?\n", bs->filename); } - op = RAW_PL_ABORT; /* fall through to unlock bytes. */ case RAW_PL_ABORT: raw_apply_lock_bytes(s, s->fd, s->perm, ~s->shared_perm, diff --git a/block/monitor/Makefile.objs b/block/monitor/Makefile.objs new file mode 100644 index 0000000..0a74f9a --- /dev/null +++ b/block/monitor/Makefile.objs @@ -0,0 +1 @@ +common-obj-y += block-hmp-cmds.o diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c new file mode 100644 index 0000000..c3a6368 --- /dev/null +++ b/block/monitor/block-hmp-cmds.c @@ -0,0 +1,1015 @@ +/* + * Blockdev HMP commands + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * This work is licensed under the terms of the GNU GPL, version 2. + * See the COPYING file in the top-level directory. + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/boards.h" +#include "sysemu/block-backend.h" +#include "sysemu/blockdev.h" +#include "qapi/qapi-commands-block.h" +#include "qapi/qmp/qdict.h" +#include "qapi/error.h" +#include "qapi/qmp/qerror.h" +#include "qemu/config-file.h" +#include "qemu/option.h" +#include "qemu/sockets.h" +#include "qemu/cutils.h" +#include "sysemu/sysemu.h" +#include "monitor/monitor.h" +#include "monitor/hmp.h" +#include "block/nbd.h" +#include "block/qapi.h" +#include "block/block_int.h" +#include "block/block-hmp-cmds.h" +#include "qemu-io.h" + +static void hmp_drive_add_node(Monitor *mon, const char *optstr) +{ + QemuOpts *opts; + QDict *qdict; + Error *local_err = NULL; + + opts = qemu_opts_parse_noisily(&qemu_drive_opts, optstr, false); + if (!opts) { + return; + } + + qdict = qemu_opts_to_qdict(opts, NULL); + + if (!qdict_get_try_str(qdict, "node-name")) { + qobject_unref(qdict); + error_report("'node-name' needs to be specified"); + goto out; + } + + BlockDriverState *bs = bds_tree_init(qdict, &local_err); + if (!bs) { + error_report_err(local_err); + goto out; + } + + bdrv_set_monitor_owned(bs); +out: + qemu_opts_del(opts); +} + +void hmp_drive_add(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + DriveInfo *dinfo; + QemuOpts *opts; + MachineClass *mc; + const char *optstr = qdict_get_str(qdict, "opts"); + bool node = qdict_get_try_bool(qdict, "node", false); + + if (node) { + hmp_drive_add_node(mon, optstr); + return; + } + + opts = drive_def(optstr); + if (!opts) + return; + + mc = MACHINE_GET_CLASS(current_machine); + dinfo = drive_new(opts, mc->block_default_type, &err); + if (err) { + error_report_err(err); + qemu_opts_del(opts); + goto err; + } + + if (!dinfo) { + return; + } + + switch (dinfo->type) { + case IF_NONE: + monitor_printf(mon, "OK\n"); + break; + default: + monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type); + goto err; + } + return; + +err: + if (dinfo) { + BlockBackend *blk = blk_by_legacy_dinfo(dinfo); + monitor_remove_blk(blk); + blk_unref(blk); + } +} + +void hmp_drive_del(Monitor *mon, const QDict *qdict) +{ + const char *id = qdict_get_str(qdict, "id"); + BlockBackend *blk; + BlockDriverState *bs; + AioContext *aio_context; + Error *local_err = NULL; + + bs = bdrv_find_node(id); + if (bs) { + qmp_blockdev_del(id, &local_err); + if (local_err) { + error_report_err(local_err); + } + return; + } + + blk = blk_by_name(id); + if (!blk) { + error_report("Device '%s' not found", id); + return; + } + + if (!blk_legacy_dinfo(blk)) { + error_report("Deleting device added with blockdev-add" + " is not supported"); + return; + } + + aio_context = blk_get_aio_context(blk); + aio_context_acquire(aio_context); + + bs = blk_bs(blk); + if (bs) { + if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) { + error_report_err(local_err); + aio_context_release(aio_context); + return; + } + + blk_remove_bs(blk); + } + + /* Make the BlockBackend and the attached BlockDriverState anonymous */ + monitor_remove_blk(blk); + + /* + * If this BlockBackend has a device attached to it, its refcount will be + * decremented when the device is removed; otherwise we have to do so here. + */ + if (blk_get_attached_dev(blk)) { + /* Further I/O must not pause the guest */ + blk_set_on_error(blk, BLOCKDEV_ON_ERROR_REPORT, + BLOCKDEV_ON_ERROR_REPORT); + } else { + blk_unref(blk); + } + + aio_context_release(aio_context); +} + +void hmp_commit(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + BlockBackend *blk; + int ret; + + if (!strcmp(device, "all")) { + ret = blk_commit_all(); + } else { + BlockDriverState *bs; + AioContext *aio_context; + + blk = blk_by_name(device); + if (!blk) { + error_report("Device '%s' not found", device); + return; + } + if (!blk_is_available(blk)) { + error_report("Device '%s' has no medium", device); + return; + } + + bs = blk_bs(blk); + aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(aio_context); + + ret = bdrv_commit(bs); + + aio_context_release(aio_context); + } + if (ret < 0) { + error_report("'commit' error for '%s': %s", device, strerror(-ret)); + } +} + +void hmp_drive_mirror(Monitor *mon, const QDict *qdict) +{ + const char *filename = qdict_get_str(qdict, "target"); + const char *format = qdict_get_try_str(qdict, "format"); + bool reuse = qdict_get_try_bool(qdict, "reuse", false); + bool full = qdict_get_try_bool(qdict, "full", false); + Error *err = NULL; + DriveMirror mirror = { + .device = (char *)qdict_get_str(qdict, "device"), + .target = (char *)filename, + .has_format = !!format, + .format = (char *)format, + .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP, + .has_mode = true, + .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS, + .unmap = true, + }; + + if (!filename) { + error_setg(&err, QERR_MISSING_PARAMETER, "target"); + hmp_handle_error(mon, err); + return; + } + qmp_drive_mirror(&mirror, &err); + hmp_handle_error(mon, err); +} + +void hmp_drive_backup(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *filename = qdict_get_str(qdict, "target"); + const char *format = qdict_get_try_str(qdict, "format"); + bool reuse = qdict_get_try_bool(qdict, "reuse", false); + bool full = qdict_get_try_bool(qdict, "full", false); + bool compress = qdict_get_try_bool(qdict, "compress", false); + Error *err = NULL; + DriveBackup backup = { + .device = (char *)device, + .target = (char *)filename, + .has_format = !!format, + .format = (char *)format, + .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP, + .has_mode = true, + .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS, + .has_compress = !!compress, + .compress = compress, + }; + + if (!filename) { + error_setg(&err, QERR_MISSING_PARAMETER, "target"); + hmp_handle_error(mon, err); + return; + } + + qmp_drive_backup(&backup, &err); + hmp_handle_error(mon, err); +} + +void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict) +{ + Error *error = NULL; + const char *device = qdict_get_str(qdict, "device"); + int64_t value = qdict_get_int(qdict, "speed"); + + qmp_block_job_set_speed(device, value, &error); + + hmp_handle_error(mon, error); +} + +void hmp_block_job_cancel(Monitor *mon, const QDict *qdict) +{ + Error *error = NULL; + const char *device = qdict_get_str(qdict, "device"); + bool force = qdict_get_try_bool(qdict, "force", false); + + qmp_block_job_cancel(device, true, force, &error); + + hmp_handle_error(mon, error); +} + +void hmp_block_job_pause(Monitor *mon, const QDict *qdict) +{ + Error *error = NULL; + const char *device = qdict_get_str(qdict, "device"); + + qmp_block_job_pause(device, &error); + + hmp_handle_error(mon, error); +} + +void hmp_block_job_resume(Monitor *mon, const QDict *qdict) +{ + Error *error = NULL; + const char *device = qdict_get_str(qdict, "device"); + + qmp_block_job_resume(device, &error); + + hmp_handle_error(mon, error); +} + +void hmp_block_job_complete(Monitor *mon, const QDict *qdict) +{ + Error *error = NULL; + const char *device = qdict_get_str(qdict, "device"); + + qmp_block_job_complete(device, &error); + + hmp_handle_error(mon, error); +} + +void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *filename = qdict_get_try_str(qdict, "snapshot-file"); + const char *format = qdict_get_try_str(qdict, "format"); + bool reuse = qdict_get_try_bool(qdict, "reuse", false); + enum NewImageMode mode; + Error *err = NULL; + + if (!filename) { + /* + * In the future, if 'snapshot-file' is not specified, the snapshot + * will be taken internally. Today it's actually required. + */ + error_setg(&err, QERR_MISSING_PARAMETER, "snapshot-file"); + hmp_handle_error(mon, err); + return; + } + + mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS; + qmp_blockdev_snapshot_sync(true, device, false, NULL, + filename, false, NULL, + !!format, format, + true, mode, &err); + hmp_handle_error(mon, err); +} + +void hmp_snapshot_blkdev_internal(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *name = qdict_get_str(qdict, "name"); + Error *err = NULL; + + qmp_blockdev_snapshot_internal_sync(device, name, &err); + hmp_handle_error(mon, err); +} + +void hmp_snapshot_delete_blkdev_internal(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *name = qdict_get_str(qdict, "name"); + const char *id = qdict_get_try_str(qdict, "id"); + Error *err = NULL; + + qmp_blockdev_snapshot_delete_internal_sync(device, !!id, id, + true, name, &err); + hmp_handle_error(mon, err); +} + +void hmp_nbd_server_start(Monitor *mon, const QDict *qdict) +{ + const char *uri = qdict_get_str(qdict, "uri"); + bool writable = qdict_get_try_bool(qdict, "writable", false); + bool all = qdict_get_try_bool(qdict, "all", false); + Error *local_err = NULL; + BlockInfoList *block_list, *info; + SocketAddress *addr; + BlockExportNbd export; + + if (writable && !all) { + error_setg(&local_err, "-w only valid together with -a"); + goto exit; + } + + /* First check if the address is valid and start the server. */ + addr = socket_parse(uri, &local_err); + if (local_err != NULL) { + goto exit; + } + + nbd_server_start(addr, NULL, NULL, &local_err); + qapi_free_SocketAddress(addr); + if (local_err != NULL) { + goto exit; + } + + if (!all) { + return; + } + + /* Then try adding all block devices. If one fails, close all and + * exit. + */ + block_list = qmp_query_block(NULL); + + for (info = block_list; info; info = info->next) { + if (!info->value->has_inserted) { + continue; + } + + export = (BlockExportNbd) { + .device = info->value->device, + .has_writable = true, + .writable = writable, + }; + + qmp_nbd_server_add(&export, &local_err); + + if (local_err != NULL) { + qmp_nbd_server_stop(NULL); + break; + } + } + + qapi_free_BlockInfoList(block_list); + +exit: + hmp_handle_error(mon, local_err); +} + +void hmp_nbd_server_add(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *name = qdict_get_try_str(qdict, "name"); + bool writable = qdict_get_try_bool(qdict, "writable", false); + Error *local_err = NULL; + + BlockExportNbd export = { + .device = (char *) device, + .has_name = !!name, + .name = (char *) name, + .has_writable = true, + .writable = writable, + }; + + qmp_nbd_server_add(&export, &local_err); + hmp_handle_error(mon, local_err); +} + +void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict) +{ + const char *name = qdict_get_str(qdict, "name"); + bool force = qdict_get_try_bool(qdict, "force", false); + Error *err = NULL; + + /* Rely on NBD_SERVER_REMOVE_MODE_SAFE being the default */ + qmp_nbd_server_remove(name, force, NBD_SERVER_REMOVE_MODE_HARD, &err); + hmp_handle_error(mon, err); +} + +void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + + qmp_nbd_server_stop(&err); + hmp_handle_error(mon, err); +} + +void hmp_block_resize(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + int64_t size = qdict_get_int(qdict, "size"); + Error *err = NULL; + + qmp_block_resize(true, device, false, NULL, size, &err); + hmp_handle_error(mon, err); +} + +void hmp_block_stream(Monitor *mon, const QDict *qdict) +{ + Error *error = NULL; + const char *device = qdict_get_str(qdict, "device"); + const char *base = qdict_get_try_str(qdict, "base"); + int64_t speed = qdict_get_try_int(qdict, "speed", 0); + + qmp_block_stream(true, device, device, base != NULL, base, false, NULL, + false, NULL, qdict_haskey(qdict, "speed"), speed, true, + BLOCKDEV_ON_ERROR_REPORT, false, false, false, false, + &error); + + hmp_handle_error(mon, error); +} + +void hmp_block_passwd(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *password = qdict_get_str(qdict, "password"); + Error *err = NULL; + + qmp_block_passwd(true, device, false, NULL, password, &err); + hmp_handle_error(mon, err); +} + +void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + char *device = (char *) qdict_get_str(qdict, "device"); + BlockIOThrottle throttle = { + .bps = qdict_get_int(qdict, "bps"), + .bps_rd = qdict_get_int(qdict, "bps_rd"), + .bps_wr = qdict_get_int(qdict, "bps_wr"), + .iops = qdict_get_int(qdict, "iops"), + .iops_rd = qdict_get_int(qdict, "iops_rd"), + .iops_wr = qdict_get_int(qdict, "iops_wr"), + }; + + /* + * qmp_block_set_io_throttle has separate parameters for the + * (deprecated) block device name and the qdev ID but the HMP + * version has only one, so we must decide which one to pass. + */ + if (blk_by_name(device)) { + throttle.has_device = true; + throttle.device = device; + } else { + throttle.has_id = true; + throttle.id = device; + } + + qmp_block_set_io_throttle(&throttle, &err); + hmp_handle_error(mon, err); +} + +void hmp_eject(Monitor *mon, const QDict *qdict) +{ + bool force = qdict_get_try_bool(qdict, "force", false); + const char *device = qdict_get_str(qdict, "device"); + Error *err = NULL; + + qmp_eject(true, device, false, NULL, true, force, &err); + hmp_handle_error(mon, err); +} + +void hmp_qemu_io(Monitor *mon, const QDict *qdict) +{ + BlockBackend *blk; + BlockBackend *local_blk = NULL; + bool qdev = qdict_get_try_bool(qdict, "qdev", false); + const char *device = qdict_get_str(qdict, "device"); + const char *command = qdict_get_str(qdict, "command"); + Error *err = NULL; + int ret; + + if (qdev) { + blk = blk_by_qdev_id(device, &err); + if (!blk) { + goto fail; + } + } else { + blk = blk_by_name(device); + if (!blk) { + BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err); + if (bs) { + blk = local_blk = blk_new(bdrv_get_aio_context(bs), + 0, BLK_PERM_ALL); + ret = blk_insert_bs(blk, bs, &err); + if (ret < 0) { + goto fail; + } + } else { + goto fail; + } + } + } + + /* + * Notably absent: Proper permission management. This is sad, but it seems + * almost impossible to achieve without changing the semantics and thereby + * limiting the use cases of the qemu-io HMP command. + * + * In an ideal world we would unconditionally create a new BlockBackend for + * qemuio_command(), but we have commands like 'reopen' and want them to + * take effect on the exact BlockBackend whose name the user passed instead + * of just on a temporary copy of it. + * + * Another problem is that deleting the temporary BlockBackend involves + * draining all requests on it first, but some qemu-iotests cases want to + * issue multiple aio_read/write requests and expect them to complete in + * the background while the monitor has already returned. + * + * This is also what prevents us from saving the original permissions and + * restoring them later: We can't revoke permissions until all requests + * have completed, and we don't know when that is nor can we really let + * anything else run before we have revoken them to avoid race conditions. + * + * What happens now is that command() in qemu-io-cmds.c can extend the + * permissions if necessary for the qemu-io command. And they simply stay + * extended, possibly resulting in a read-only guest device keeping write + * permissions. Ugly, but it appears to be the lesser evil. + */ + qemuio_command(blk, command); + +fail: + blk_unref(local_blk); + hmp_handle_error(mon, err); +} + +static void print_block_info(Monitor *mon, BlockInfo *info, + BlockDeviceInfo *inserted, bool verbose) +{ + ImageInfo *image_info; + + assert(!info || !info->has_inserted || info->inserted == inserted); + + if (info && *info->device) { + monitor_printf(mon, "%s", info->device); + if (inserted && inserted->has_node_name) { + monitor_printf(mon, " (%s)", inserted->node_name); + } + } else { + assert(info || inserted); + monitor_printf(mon, "%s", + inserted && inserted->has_node_name ? inserted->node_name + : info && info->has_qdev ? info->qdev + : "<anonymous>"); + } + + if (inserted) { + monitor_printf(mon, ": %s (%s%s%s)\n", + inserted->file, + inserted->drv, + inserted->ro ? ", read-only" : "", + inserted->encrypted ? ", encrypted" : ""); + } else { + monitor_printf(mon, ": [not inserted]\n"); + } + + if (info) { + if (info->has_qdev) { + monitor_printf(mon, " Attached to: %s\n", info->qdev); + } + if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) { + monitor_printf(mon, " I/O status: %s\n", + BlockDeviceIoStatus_str(info->io_status)); + } + + if (info->removable) { + monitor_printf(mon, " Removable device: %slocked, tray %s\n", + info->locked ? "" : "not ", + info->tray_open ? "open" : "closed"); + } + } + + + if (!inserted) { + return; + } + + monitor_printf(mon, " Cache mode: %s%s%s\n", + inserted->cache->writeback ? "writeback" : "writethrough", + inserted->cache->direct ? ", direct" : "", + inserted->cache->no_flush ? ", ignore flushes" : ""); + + if (inserted->has_backing_file) { + monitor_printf(mon, + " Backing file: %s " + "(chain depth: %" PRId64 ")\n", + inserted->backing_file, + inserted->backing_file_depth); + } + + if (inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) { + monitor_printf(mon, " Detect zeroes: %s\n", + BlockdevDetectZeroesOptions_str(inserted->detect_zeroes)); + } + + if (inserted->bps || inserted->bps_rd || inserted->bps_wr || + inserted->iops || inserted->iops_rd || inserted->iops_wr) + { + monitor_printf(mon, " I/O throttling: bps=%" PRId64 + " bps_rd=%" PRId64 " bps_wr=%" PRId64 + " bps_max=%" PRId64 + " bps_rd_max=%" PRId64 + " bps_wr_max=%" PRId64 + " iops=%" PRId64 " iops_rd=%" PRId64 + " iops_wr=%" PRId64 + " iops_max=%" PRId64 + " iops_rd_max=%" PRId64 + " iops_wr_max=%" PRId64 + " iops_size=%" PRId64 + " group=%s\n", + inserted->bps, + inserted->bps_rd, + inserted->bps_wr, + inserted->bps_max, + inserted->bps_rd_max, + inserted->bps_wr_max, + inserted->iops, + inserted->iops_rd, + inserted->iops_wr, + inserted->iops_max, + inserted->iops_rd_max, + inserted->iops_wr_max, + inserted->iops_size, + inserted->group); + } + + if (verbose) { + monitor_printf(mon, "\nImages:\n"); + image_info = inserted->image; + while (1) { + bdrv_image_info_dump(image_info); + if (image_info->has_backing_image) { + image_info = image_info->backing_image; + } else { + break; + } + } + } +} + +void hmp_info_block(Monitor *mon, const QDict *qdict) +{ + BlockInfoList *block_list, *info; + BlockDeviceInfoList *blockdev_list, *blockdev; + const char *device = qdict_get_try_str(qdict, "device"); + bool verbose = qdict_get_try_bool(qdict, "verbose", false); + bool nodes = qdict_get_try_bool(qdict, "nodes", false); + bool printed = false; + + /* Print BlockBackend information */ + if (!nodes) { + block_list = qmp_query_block(NULL); + } else { + block_list = NULL; + } + + for (info = block_list; info; info = info->next) { + if (device && strcmp(device, info->value->device)) { + continue; + } + + if (info != block_list) { + monitor_printf(mon, "\n"); + } + + print_block_info(mon, info->value, info->value->has_inserted + ? info->value->inserted : NULL, + verbose); + printed = true; + } + + qapi_free_BlockInfoList(block_list); + + if ((!device && !nodes) || printed) { + return; + } + + /* Print node information */ + blockdev_list = qmp_query_named_block_nodes(false, false, NULL); + for (blockdev = blockdev_list; blockdev; blockdev = blockdev->next) { + assert(blockdev->value->has_node_name); + if (device && strcmp(device, blockdev->value->node_name)) { + continue; + } + + if (blockdev != blockdev_list) { + monitor_printf(mon, "\n"); + } + + print_block_info(mon, NULL, blockdev->value, verbose); + } + qapi_free_BlockDeviceInfoList(blockdev_list); +} + +void hmp_info_blockstats(Monitor *mon, const QDict *qdict) +{ + BlockStatsList *stats_list, *stats; + + stats_list = qmp_query_blockstats(false, false, NULL); + + for (stats = stats_list; stats; stats = stats->next) { + if (!stats->value->has_device) { + continue; + } + + monitor_printf(mon, "%s:", stats->value->device); + monitor_printf(mon, " rd_bytes=%" PRId64 + " wr_bytes=%" PRId64 + " rd_operations=%" PRId64 + " wr_operations=%" PRId64 + " flush_operations=%" PRId64 + " wr_total_time_ns=%" PRId64 + " rd_total_time_ns=%" PRId64 + " flush_total_time_ns=%" PRId64 + " rd_merged=%" PRId64 + " wr_merged=%" PRId64 + " idle_time_ns=%" PRId64 + "\n", + stats->value->stats->rd_bytes, + stats->value->stats->wr_bytes, + stats->value->stats->rd_operations, + stats->value->stats->wr_operations, + stats->value->stats->flush_operations, + stats->value->stats->wr_total_time_ns, + stats->value->stats->rd_total_time_ns, + stats->value->stats->flush_total_time_ns, + stats->value->stats->rd_merged, + stats->value->stats->wr_merged, + stats->value->stats->idle_time_ns); + } + + qapi_free_BlockStatsList(stats_list); +} + +void hmp_info_block_jobs(Monitor *mon, const QDict *qdict) +{ + BlockJobInfoList *list; + Error *err = NULL; + + list = qmp_query_block_jobs(&err); + assert(!err); + + if (!list) { + monitor_printf(mon, "No active jobs\n"); + return; + } + + while (list) { + if (strcmp(list->value->type, "stream") == 0) { + monitor_printf(mon, "Streaming device %s: Completed %" PRId64 + " of %" PRId64 " bytes, speed limit %" PRId64 + " bytes/s\n", + list->value->device, + list->value->offset, + list->value->len, + list->value->speed); + } else { + monitor_printf(mon, "Type %s, device %s: Completed %" PRId64 + " of %" PRId64 " bytes, speed limit %" PRId64 + " bytes/s\n", + list->value->type, + list->value->device, + list->value->offset, + list->value->len, + list->value->speed); + } + list = list->next; + } + + qapi_free_BlockJobInfoList(list); +} + +void hmp_info_snapshots(Monitor *mon, const QDict *qdict) +{ + BlockDriverState *bs, *bs1; + BdrvNextIterator it1; + QEMUSnapshotInfo *sn_tab, *sn; + bool no_snapshot = true; + int nb_sns, i; + int total; + int *global_snapshots; + AioContext *aio_context; + + typedef struct SnapshotEntry { + QEMUSnapshotInfo sn; + QTAILQ_ENTRY(SnapshotEntry) next; + } SnapshotEntry; + + typedef struct ImageEntry { + const char *imagename; + QTAILQ_ENTRY(ImageEntry) next; + QTAILQ_HEAD(, SnapshotEntry) snapshots; + } ImageEntry; + + QTAILQ_HEAD(, ImageEntry) image_list = + QTAILQ_HEAD_INITIALIZER(image_list); + + ImageEntry *image_entry, *next_ie; + SnapshotEntry *snapshot_entry; + + bs = bdrv_all_find_vmstate_bs(); + if (!bs) { + monitor_printf(mon, "No available block device supports snapshots\n"); + return; + } + aio_context = bdrv_get_aio_context(bs); + + aio_context_acquire(aio_context); + nb_sns = bdrv_snapshot_list(bs, &sn_tab); + aio_context_release(aio_context); + + if (nb_sns < 0) { + monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns); + return; + } + + for (bs1 = bdrv_first(&it1); bs1; bs1 = bdrv_next(&it1)) { + int bs1_nb_sns = 0; + ImageEntry *ie; + SnapshotEntry *se; + AioContext *ctx = bdrv_get_aio_context(bs1); + + aio_context_acquire(ctx); + if (bdrv_can_snapshot(bs1)) { + sn = NULL; + bs1_nb_sns = bdrv_snapshot_list(bs1, &sn); + if (bs1_nb_sns > 0) { + no_snapshot = false; + ie = g_new0(ImageEntry, 1); + ie->imagename = bdrv_get_device_name(bs1); + QTAILQ_INIT(&ie->snapshots); + QTAILQ_INSERT_TAIL(&image_list, ie, next); + for (i = 0; i < bs1_nb_sns; i++) { + se = g_new0(SnapshotEntry, 1); + se->sn = sn[i]; + QTAILQ_INSERT_TAIL(&ie->snapshots, se, next); + } + } + g_free(sn); + } + aio_context_release(ctx); + } + + if (no_snapshot) { + monitor_printf(mon, "There is no snapshot available.\n"); + return; + } + + global_snapshots = g_new0(int, nb_sns); + total = 0; + for (i = 0; i < nb_sns; i++) { + SnapshotEntry *next_sn; + if (bdrv_all_find_snapshot(sn_tab[i].name, &bs1) == 0) { + global_snapshots[total] = i; + total++; + QTAILQ_FOREACH(image_entry, &image_list, next) { + QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots, + next, next_sn) { + if (!strcmp(sn_tab[i].name, snapshot_entry->sn.name)) { + QTAILQ_REMOVE(&image_entry->snapshots, snapshot_entry, + next); + g_free(snapshot_entry); + } + } + } + } + } + monitor_printf(mon, "List of snapshots present on all disks:\n"); + + if (total > 0) { + bdrv_snapshot_dump(NULL); + monitor_printf(mon, "\n"); + for (i = 0; i < total; i++) { + sn = &sn_tab[global_snapshots[i]]; + /* + * The ID is not guaranteed to be the same on all images, so + * overwrite it. + */ + pstrcpy(sn->id_str, sizeof(sn->id_str), "--"); + bdrv_snapshot_dump(sn); + monitor_printf(mon, "\n"); + } + } else { + monitor_printf(mon, "None\n"); + } + + QTAILQ_FOREACH(image_entry, &image_list, next) { + if (QTAILQ_EMPTY(&image_entry->snapshots)) { + continue; + } + monitor_printf(mon, + "\nList of partial (non-loadable) snapshots on '%s':\n", + image_entry->imagename); + bdrv_snapshot_dump(NULL); + monitor_printf(mon, "\n"); + QTAILQ_FOREACH(snapshot_entry, &image_entry->snapshots, next) { + bdrv_snapshot_dump(&snapshot_entry->sn); + monitor_printf(mon, "\n"); + } + } + + QTAILQ_FOREACH_SAFE(image_entry, &image_list, next, next_ie) { + SnapshotEntry *next_sn; + QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots, next, + next_sn) { + g_free(snapshot_entry); + } + g_free(image_entry); + } + g_free(sn_tab); + g_free(global_snapshots); +} diff --git a/block/stream.c b/block/stream.c index 5562ccb..aa2e7af 100644 --- a/block/stream.c +++ b/block/stream.c @@ -114,7 +114,6 @@ static int coroutine_fn stream_run(Job *job, Error **errp) int64_t offset = 0; uint64_t delay_ns = 0; int error = 0; - int ret = 0; int64_t n = 0; /* bytes */ if (bs == s->bottom) { @@ -139,6 +138,7 @@ static int coroutine_fn stream_run(Job *job, Error **errp) for ( ; offset < len; offset += n) { bool copy; + int ret; /* Note that even when no rate limit is applied we need to yield * with no pending I/O here so that bdrv_drain_all() returns. @@ -183,7 +183,6 @@ static int coroutine_fn stream_run(Job *job, Error **errp) break; } } - ret = 0; /* Publish progress */ job_progress_update(&s->common.job, n); @@ -64,9 +64,14 @@ #include "qemu/main-loop.h" #include "qemu/throttle-options.h" -static QTAILQ_HEAD(, BlockDriverState) monitor_bdrv_states = +QTAILQ_HEAD(, BlockDriverState) monitor_bdrv_states = QTAILQ_HEAD_INITIALIZER(monitor_bdrv_states); +void bdrv_set_monitor_owned(BlockDriverState *bs) +{ + QTAILQ_INSERT_TAIL(&monitor_bdrv_states, bs, monitor_list); +} + static const char *const if_name[IF_COUNT] = { [IF_NONE] = "none", [IF_IDE] = "ide", @@ -640,7 +645,7 @@ err_no_opts: } /* Takes the ownership of bs_opts */ -static BlockDriverState *bds_tree_init(QDict *bs_opts, Error **errp) +BlockDriverState *bds_tree_init(QDict *bs_opts, Error **errp) { int bdrv_flags = 0; @@ -1039,41 +1044,6 @@ static BlockDriverState *qmp_get_root_bs(const char *name, Error **errp) return bs; } -void hmp_commit(Monitor *mon, const QDict *qdict) -{ - const char *device = qdict_get_str(qdict, "device"); - BlockBackend *blk; - int ret; - - if (!strcmp(device, "all")) { - ret = blk_commit_all(); - } else { - BlockDriverState *bs; - AioContext *aio_context; - - blk = blk_by_name(device); - if (!blk) { - error_report("Device '%s' not found", device); - return; - } - if (!blk_is_available(blk)) { - error_report("Device '%s' has no medium", device); - return; - } - - bs = blk_bs(blk); - aio_context = bdrv_get_aio_context(bs); - aio_context_acquire(aio_context); - - ret = bdrv_commit(bs); - - aio_context_release(aio_context); - } - if (ret < 0) { - error_report("'commit' error for '%s': %s", device, strerror(-ret)); - } -} - static void blockdev_do_action(TransactionAction *action, Error **errp) { TransactionActionList list; @@ -2747,66 +2717,6 @@ BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node, return ret; } -void hmp_drive_del(Monitor *mon, const QDict *qdict) -{ - const char *id = qdict_get_str(qdict, "id"); - BlockBackend *blk; - BlockDriverState *bs; - AioContext *aio_context; - Error *local_err = NULL; - - bs = bdrv_find_node(id); - if (bs) { - qmp_blockdev_del(id, &local_err); - if (local_err) { - error_report_err(local_err); - } - return; - } - - blk = blk_by_name(id); - if (!blk) { - error_report("Device '%s' not found", id); - return; - } - - if (!blk_legacy_dinfo(blk)) { - error_report("Deleting device added with blockdev-add" - " is not supported"); - return; - } - - aio_context = blk_get_aio_context(blk); - aio_context_acquire(aio_context); - - bs = blk_bs(blk); - if (bs) { - if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) { - error_report_err(local_err); - aio_context_release(aio_context); - return; - } - - blk_remove_bs(blk); - } - - /* Make the BlockBackend and the attached BlockDriverState anonymous */ - monitor_remove_blk(blk); - - /* If this BlockBackend has a device attached to it, its refcount will be - * decremented when the device is removed; otherwise we have to do so here. - */ - if (blk_get_attached_dev(blk)) { - /* Further I/O must not pause the guest */ - blk_set_on_error(blk, BLOCKDEV_ON_ERROR_REPORT, - BLOCKDEV_ON_ERROR_REPORT); - } else { - blk_unref(blk); - } - - aio_context_release(aio_context); -} - void qmp_block_resize(bool has_device, const char *device, bool has_node_name, const char *node_name, int64_t size, Error **errp) @@ -3814,37 +3724,6 @@ out: aio_context_release(aio_context); } -void hmp_drive_add_node(Monitor *mon, const char *optstr) -{ - QemuOpts *opts; - QDict *qdict; - Error *local_err = NULL; - - opts = qemu_opts_parse_noisily(&qemu_drive_opts, optstr, false); - if (!opts) { - return; - } - - qdict = qemu_opts_to_qdict(opts, NULL); - - if (!qdict_get_try_str(qdict, "node-name")) { - qobject_unref(qdict); - error_report("'node-name' needs to be specified"); - goto out; - } - - BlockDriverState *bs = bds_tree_init(qdict, &local_err); - if (!bs) { - error_report_err(local_err); - goto out; - } - - QTAILQ_INSERT_TAIL(&monitor_bdrv_states, bs, monitor_list); - -out: - qemu_opts_del(opts); -} - void qmp_blockdev_add(BlockdevOptions *options, Error **errp) { BlockDriverState *bs; @@ -3874,7 +3753,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) goto fail; } - QTAILQ_INSERT_TAIL(&monitor_bdrv_states, bs, monitor_list); + bdrv_set_monitor_owned(bs); fail: visit_free(v); diff --git a/chardev/char-pipe.c b/chardev/char-pipe.c index 94d714f..fd12c9e 100644 --- a/chardev/char-pipe.c +++ b/chardev/char-pipe.c @@ -70,7 +70,7 @@ static int win_chr_pipe_init(Chardev *chr, const char *filename, MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL); g_free(openname); if (s->file == INVALID_HANDLE_VALUE) { - error_setg(errp, "Failed CreateNamedPipe (%lu)", GetLastError()); + error_setg_win32(errp, GetLastError(), "Failed CreateNamedPipe"); s->file = NULL; goto fail; } diff --git a/chardev/char-win.c b/chardev/char-win.c index 34825f6..d4fb44c 100644 --- a/chardev/char-win.c +++ b/chardev/char-win.c @@ -96,7 +96,7 @@ int win_chr_serial_init(Chardev *chr, const char *filename, Error **errp) s->file = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if (s->file == INVALID_HANDLE_VALUE) { - error_setg(errp, "Failed CreateFile (%lu)", GetLastError()); + error_setg_win32(errp, GetLastError(), "Failed CreateFile"); s->file = NULL; goto fail; } diff --git a/device-hotplug.c b/device-hotplug.c deleted file mode 100644 index f01d537..0000000 --- a/device-hotplug.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * QEMU device hotplug helpers - * - * Copyright (c) 2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "qemu/osdep.h" -#include "hw/boards.h" -#include "sysemu/block-backend.h" -#include "sysemu/blockdev.h" -#include "qapi/qmp/qdict.h" -#include "qapi/error.h" -#include "qemu/config-file.h" -#include "qemu/option.h" -#include "sysemu/sysemu.h" -#include "monitor/monitor.h" -#include "block/block_int.h" - -static DriveInfo *add_init_drive(const char *optstr) -{ - Error *err = NULL; - DriveInfo *dinfo; - QemuOpts *opts; - MachineClass *mc; - - opts = drive_def(optstr); - if (!opts) - return NULL; - - mc = MACHINE_GET_CLASS(current_machine); - dinfo = drive_new(opts, mc->block_default_type, &err); - if (err) { - error_report_err(err); - qemu_opts_del(opts); - return NULL; - } - - return dinfo; -} - -void hmp_drive_add(Monitor *mon, const QDict *qdict) -{ - DriveInfo *dinfo = NULL; - const char *opts = qdict_get_str(qdict, "opts"); - bool node = qdict_get_try_bool(qdict, "node", false); - - if (node) { - hmp_drive_add_node(mon, opts); - return; - } - - dinfo = add_init_drive(opts); - if (!dinfo) { - goto err; - } - - switch (dinfo->type) { - case IF_NONE: - monitor_printf(mon, "OK\n"); - break; - default: - monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type); - goto err; - } - return; - -err: - if (dinfo) { - BlockBackend *blk = blk_by_legacy_dinfo(dinfo); - monitor_remove_blk(blk); - blk_unref(blk); - } -} diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index 6c1d903..0838338 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -248,12 +248,6 @@ the 'wait' field, which is only applicable to sockets in server mode Human Monitor Protocol (HMP) commands ------------------------------------- -The ``hub_id`` parameter of ``hostfwd_add`` / ``hostfwd_remove`` (since 3.1) -'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -The ``[hub_id name]`` parameter tuple of the 'hostfwd_add' and -'hostfwd_remove' HMP commands has been replaced by ``netdev_id``. - ``cpu-add`` (since 4.0) ''''''''''''''''''''''' @@ -430,6 +424,15 @@ QEMU Machine Protocol (QMP) commands The "autoload" parameter has been ignored since 2.12.0. All bitmaps are automatically loaded from qcow2 images. +Human Monitor Protocol (HMP) commands +------------------------------------- + +The ``hub_id`` parameter of ``hostfwd_add`` / ``hostfwd_remove`` (removed in 5.0) +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The ``[hub_id name]`` parameter tuple of the 'hostfwd_add' and +'hostfwd_remove' HMP commands has been replaced by ``netdev_id``. + Related binaries ---------------- diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c index aa1ab25..de061a8 100644 --- a/fsdev/virtfs-proxy-helper.c +++ b/fsdev/virtfs-proxy-helper.c @@ -43,7 +43,7 @@ #define BTRFS_SUPER_MAGIC 0x9123683E #endif -static struct option helper_opts[] = { +static const struct option helper_opts[] = { {"fd", required_argument, NULL, 'f'}, {"path", required_argument, NULL, 'p'}, {"nodaemon", no_argument, NULL, 'n'}, diff --git a/hmp-commands.hx b/hmp-commands.hx index eb3d160..f12263e 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1369,8 +1369,8 @@ ERST #ifdef CONFIG_SLIRP { .name = "hostfwd_add", - .args_type = "arg1:s,arg2:s?,arg3:s?", - .params = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport", + .args_type = "arg1:s,arg2:s?", + .params = "[netdev_id] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport", .help = "redirect TCP or UDP connections from host to guest (requires -net user)", .cmd = hmp_hostfwd_add, }, @@ -1383,8 +1383,8 @@ ERST #ifdef CONFIG_SLIRP { .name = "hostfwd_remove", - .args_type = "arg1:s,arg2:s?,arg3:s?", - .params = "[hub_id name]|[netdev_id] [tcp|udp]:[hostaddr]:hostport", + .args_type = "arg1:s,arg2:s?", + .params = "[netdev_id] [tcp|udp]:[hostaddr]:hostport", .help = "remove host-to-guest TCP or UDP redirection", .cmd = hmp_hostfwd_remove, }, diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c index 9c3bcc8..3e687d2 100644 --- a/hw/acpi/cpu_hotplug.c +++ b/hw/acpi/cpu_hotplug.c @@ -14,6 +14,7 @@ #include "qapi/error.h" #include "hw/core/cpu.h" #include "hw/i386/pc.h" +#include "hw/pci/pci.h" #include "qemu/error-report.h" #define CPU_EJECT_METHOD "CPEJ" diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index 2034dd7..4e74284 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -27,7 +27,6 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qapi/visitor.h" -#include "hw/i386/pc.h" #include "hw/pci/pci.h" #include "migration/vmstate.h" #include "qemu/timer.h" @@ -40,6 +39,7 @@ #include "hw/i386/ich9.h" #include "hw/mem/pc-dimm.h" +#include "hw/mem/nvdimm.h" //#define DEBUG diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 6d621c3..b84dbba 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -38,6 +38,7 @@ #include "hw/acpi/cpu.h" #include "hw/hotplug.h" #include "hw/mem/pc-dimm.h" +#include "hw/mem/nvdimm.h" #include "hw/acpi/memory_hotplug.h" #include "hw/acpi/acpi_dev_interface.h" #include "hw/xen/xen.h" diff --git a/hw/alpha/alpha_sys.h b/hw/alpha/alpha_sys.h index bc0a286..e2c02e2 100644 --- a/hw/alpha/alpha_sys.h +++ b/hw/alpha/alpha_sys.h @@ -6,7 +6,6 @@ #include "target/alpha/cpu-qom.h" #include "hw/pci/pci.h" #include "hw/pci/pci_host.h" -#include "hw/ide.h" #include "hw/boards.h" #include "hw/intc/i8259.h" diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c index d28f571..e5350a2 100644 --- a/hw/alpha/dp264.c +++ b/hw/alpha/dp264.c @@ -21,6 +21,7 @@ #include "hw/dma/i8257.h" #include "net/net.h" #include "qemu/cutils.h" +#include "net/net.h" #define MAX_IDE_BUS 2 diff --git a/hw/audio/fmopl.c b/hw/audio/fmopl.c index 9f50a89..173a752 100644 --- a/hw/audio/fmopl.c +++ b/hw/audio/fmopl.c @@ -1066,7 +1066,7 @@ static void OPLResetChip(FM_OPL *OPL) } } -/* ---------- Create one of vietual YM3812 ---------- */ +/* ---------- Create one of virtual YM3812 ---------- */ /* 'rate' is sampling rate and 'bufsiz' is the size of the */ FM_OPL *OPLCreate(int clock, int rate) { @@ -1115,7 +1115,7 @@ FM_OPL *OPLCreate(int clock, int rate) return OPL; } -/* ---------- Destroy one of vietual YM3812 ---------- */ +/* ---------- Destroy one of virtual YM3812 ---------- */ void OPLDestroy(FM_OPL *OPL) { #ifdef OPL_OUTPUT_LOG diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 3937d1e..85f062d 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -557,7 +557,7 @@ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n) { - char *propname = g_strdup_printf("%s[%d]", + g_autofree char *propname = g_strdup_printf("%s[%d]", name ? name : "unnamed-gpio-out", n); qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname, diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c index ec67766..1c0266c 100644 --- a/hw/display/exynos4210_fimd.c +++ b/hw/display/exynos4210_fimd.c @@ -1311,7 +1311,6 @@ static void exynos4210_fimd_update(void *opaque) } host_fb_addr += inc_size; fb_line_addr += inc_size; - is_dirty = false; } g_free(snap); blend = true; diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c index 05f5f84..464e931 100644 --- a/hw/display/pxa2xx_lcd.c +++ b/hw/display/pxa2xx_lcd.c @@ -593,7 +593,6 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp) n = 256; break; default: - format = 0; return; } diff --git a/hw/dma/xlnx-zdma.c b/hw/dma/xlnx-zdma.c index 1c1b142..2d9c0a0 100644 --- a/hw/dma/xlnx-zdma.c +++ b/hw/dma/xlnx-zdma.c @@ -372,7 +372,7 @@ static uint64_t zdma_update_descr_addr(XlnxZDMA *s, bool type, static void zdma_write_dst(XlnxZDMA *s, uint8_t *buf, uint32_t len) { uint32_t dst_size, dlen; - bool dst_intr, dst_type; + bool dst_intr; unsigned int ptype = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, POINT_TYPE); unsigned int rw_mode = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_CTRL0, MODE); unsigned int burst_type = ARRAY_FIELD_EX32(s->regs, ZDMA_CH_DATA_ATTR, @@ -386,17 +386,17 @@ static void zdma_write_dst(XlnxZDMA *s, uint8_t *buf, uint32_t len) while (len) { dst_size = FIELD_EX32(s->dsc_dst.words[2], ZDMA_CH_DST_DSCR_WORD2, SIZE); - dst_type = FIELD_EX32(s->dsc_dst.words[3], ZDMA_CH_DST_DSCR_WORD3, - TYPE); if (dst_size == 0 && ptype == PT_MEM) { uint64_t next; + bool dst_type = FIELD_EX32(s->dsc_dst.words[3], + ZDMA_CH_DST_DSCR_WORD3, + TYPE); + next = zdma_update_descr_addr(s, dst_type, R_ZDMA_CH_DST_CUR_DSCR_LSB); zdma_load_descriptor(s, next, &s->dsc_dst); dst_size = FIELD_EX32(s->dsc_dst.words[2], ZDMA_CH_DST_DSCR_WORD2, SIZE); - dst_type = FIELD_EX32(s->dsc_dst.words[3], ZDMA_CH_DST_DSCR_WORD3, - TYPE); } /* Match what hardware does by ignoring the dst_size and only using diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index bf18767..9175f4b 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -22,6 +22,7 @@ #include "qapi/error.h" #include "net/net.h" #include "qemu/log.h" +#include "net/net.h" #define MAX_IDE_BUS 2 diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c index fd50fb8..48f1ff4 100644 --- a/hw/i2c/smbus_ich9.c +++ b/hw/i2c/smbus_ich9.c @@ -21,6 +21,7 @@ */ #include "qemu/osdep.h" +#include "qemu/range.h" #include "hw/i2c/pm_smbus.h" #include "hw/pci/pci.h" #include "migration/vmstate.h" diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 26777f8..9a19c14 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -47,6 +47,7 @@ #include "hw/rtc/mc146818rtc_regs.h" #include "migration/vmstate.h" #include "hw/mem/memory-device.h" +#include "hw/mem/nvdimm.h" #include "sysemu/numa.h" #include "sysemu/reset.h" diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 6258c58..204b684 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -987,24 +987,26 @@ static bool vtd_slpte_nonzero_rsvd(uint64_t slpte, uint32_t level) static VTDBus *vtd_find_as_from_bus_num(IntelIOMMUState *s, uint8_t bus_num) { VTDBus *vtd_bus = s->vtd_as_by_bus_num[bus_num]; - if (!vtd_bus) { - /* - * Iterate over the registered buses to find the one which - * currently hold this bus number, and update the bus_num - * lookup table: - */ - GHashTableIter iter; + GHashTableIter iter; - g_hash_table_iter_init(&iter, s->vtd_as_by_busptr); - while (g_hash_table_iter_next(&iter, NULL, (void **)&vtd_bus)) { - if (pci_bus_num(vtd_bus->bus) == bus_num) { - s->vtd_as_by_bus_num[bus_num] = vtd_bus; - return vtd_bus; - } + if (vtd_bus) { + return vtd_bus; + } + + /* + * Iterate over the registered buses to find the one which + * currently holds this bus number and update the bus_num + * lookup table. + */ + g_hash_table_iter_init(&iter, s->vtd_as_by_busptr); + while (g_hash_table_iter_next(&iter, NULL, (void **)&vtd_bus)) { + if (pci_bus_num(vtd_bus->bus) == bus_num) { + s->vtd_as_by_bus_num[bus_num] = vtd_bus; + return vtd_bus; } - vtd_bus = NULL; } - return vtd_bus; + + return NULL; } /* Given the @iova, get relevant @slptep. @slpte_level will be the last level diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 6ab4acb..362eb2a 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -76,6 +76,7 @@ #include "hw/boards.h" #include "acpi-build.h" #include "hw/mem/pc-dimm.h" +#include "hw/mem/nvdimm.h" #include "qapi/error.h" #include "qapi/qapi-visit-common.h" #include "qapi/visitor.h" diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 9088db8..e2d9824 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -60,6 +60,7 @@ #include "migration/global_state.h" #include "migration/misc.h" #include "sysemu/numa.h" +#include "hw/mem/nvdimm.h" #define MAX_IDE_BUS 2 diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 84cf925..d37c425 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -53,6 +53,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "sysemu/numa.h" +#include "hw/mem/nvdimm.h" /* ICH9 AHCI has 6 ports */ #define MAX_SATA_PORTS 6 diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index f85b484..cb79616 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -37,7 +37,6 @@ #include "migration/vmstate.h" #include "hw/irq.h" #include "hw/isa/apm.h" -#include "hw/i386/ioapic.h" #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" #include "hw/i386/ich9.h" diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index 8a3504d..81fc13e 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -525,8 +525,8 @@ static void dp8393x_do_transmit_packets(dp8393xState *s) * (4 + 3 * s->regs[SONIC_TFC]), MEMTXATTRS_UNSPECIFIED, s->data, size); - s->regs[SONIC_CTDA] = dp8393x_get(s, width, 0) & ~0x1; - if (dp8393x_get(s, width, 0) & SONIC_DESC_EOL) { + s->regs[SONIC_CTDA] = dp8393x_get(s, width, 0); + if (s->regs[SONIC_CTDA] & SONIC_DESC_EOL) { /* EOL detected */ break; } diff --git a/hw/net/e1000.c b/hw/net/e1000.c index 0b833d5..9233248 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -1150,7 +1150,8 @@ set_ims(E1000State *s, int index, uint32_t val) } #define getreg(x) [x] = mac_readreg -static uint32_t (*macreg_readops[])(E1000State *, int) = { +typedef uint32_t (*readops)(E1000State *, int); +static const readops macreg_readops[] = { getreg(PBA), getreg(RCTL), getreg(TDH), getreg(TXDCTL), getreg(WUFC), getreg(TDT), getreg(CTRL), getreg(LEDCTL), getreg(MANC), getreg(MDIC), getreg(SWSM), getreg(STATUS), @@ -1205,7 +1206,8 @@ static uint32_t (*macreg_readops[])(E1000State *, int) = { enum { NREADOPS = ARRAY_SIZE(macreg_readops) }; #define putreg(x) [x] = mac_writereg -static void (*macreg_writeops[])(E1000State *, int, uint32_t) = { +typedef void (*writeops)(E1000State *, int, uint32_t); +static const writeops macreg_writeops[] = { putreg(PBA), putreg(EERD), putreg(SWSM), putreg(WUFC), putreg(TDBAL), putreg(TDBAH), putreg(TXDCTL), putreg(RDBAH), putreg(RDBAL), putreg(LEDCTL), putreg(VET), putreg(FCRUC), diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c index 94ea34d..df957e0 100644 --- a/hw/net/e1000e_core.c +++ b/hw/net/e1000e_core.c @@ -2855,7 +2855,8 @@ e1000e_set_gcr(E1000ECore *core, int index, uint32_t val) } #define e1000e_getreg(x) [x] = e1000e_mac_readreg -static uint32_t (*e1000e_macreg_readops[])(E1000ECore *, int) = { +typedef uint32_t (*readops)(E1000ECore *, int); +static const readops e1000e_macreg_readops[] = { e1000e_getreg(PBA), e1000e_getreg(WUFC), e1000e_getreg(MANC), @@ -3061,7 +3062,8 @@ static uint32_t (*e1000e_macreg_readops[])(E1000ECore *, int) = { enum { E1000E_NREADOPS = ARRAY_SIZE(e1000e_macreg_readops) }; #define e1000e_putreg(x) [x] = e1000e_mac_writereg -static void (*e1000e_macreg_writeops[])(E1000ECore *, int, uint32_t) = { +typedef void (*writeops)(E1000ECore *, int, uint32_t); +static const writeops e1000e_macreg_writeops[] = { e1000e_putreg(PBA), e1000e_putreg(SWSM), e1000e_putreg(WUFC), diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c index 0ba4e4d..f1cfe9d 100644 --- a/hw/pci-bridge/pcie_root_port.c +++ b/hw/pci-bridge/pcie_root_port.c @@ -94,7 +94,7 @@ static void rp_realize(PCIDevice *d, Error **errp) pcie_cap_arifwd_init(d); pcie_cap_deverr_init(d); - pcie_cap_slot_init(d, s->slot); + pcie_cap_slot_init(d, s); pcie_cap_root_init(d); pcie_chassis_create(s->chassis); diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c index 153a4ac..04aae72 100644 --- a/hw/pci-bridge/xio3130_downstream.c +++ b/hw/pci-bridge/xio3130_downstream.c @@ -94,7 +94,7 @@ static void xio3130_downstream_realize(PCIDevice *d, Error **errp) } pcie_cap_flr_init(d); pcie_cap_deverr_init(d); - pcie_cap_slot_init(d, s->slot); + pcie_cap_slot_init(d, s); pcie_cap_arifwd_init(d); pcie_chassis_create(s->chassis); diff --git a/hw/pci-host/i440fx.c b/hw/pci-host/i440fx.c index 11050a0..d980c97 100644 --- a/hw/pci-host/i440fx.c +++ b/hw/pci-host/i440fx.c @@ -23,6 +23,7 @@ */ #include "qemu/osdep.h" +#include "qemu/range.h" #include "hw/i386/pc.h" #include "hw/pci/pci.h" #include "hw/pci/pci_host.h" diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index a9b9ccc..993f467 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -29,6 +29,7 @@ */ #include "qemu/osdep.h" +#include "hw/i386/pc.h" #include "hw/pci-host/q35.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 0871818..0eb3a2a 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -495,7 +495,7 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, /* pci express slot for pci express root/downstream port PCI express capability slot registers */ -void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot) +void pcie_cap_slot_init(PCIDevice *dev, PCIESlot *s) { uint32_t pos = dev->exp.exp_cap; @@ -505,13 +505,16 @@ void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot) pci_long_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCAP, ~PCI_EXP_SLTCAP_PSN); pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP, - (slot << PCI_EXP_SLTCAP_PSN_SHIFT) | + (s->slot << PCI_EXP_SLTCAP_PSN_SHIFT) | PCI_EXP_SLTCAP_EIP | - PCI_EXP_SLTCAP_HPS | - PCI_EXP_SLTCAP_HPC | PCI_EXP_SLTCAP_PIP | PCI_EXP_SLTCAP_AIP | PCI_EXP_SLTCAP_ABP); + if (s->hotplug) { + pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP, + PCI_EXP_SLTCAP_HPS | + PCI_EXP_SLTCAP_HPC); + } if (dev->cap_present & QEMU_PCIE_SLTCAP_PCP) { pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP, diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c index f8263cb..eb563ad 100644 --- a/hw/pci/pcie_port.c +++ b/hw/pci/pcie_port.c @@ -147,6 +147,7 @@ static const TypeInfo pcie_port_type_info = { static Property pcie_slot_props[] = { DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0), DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0), + DEFINE_PROP_BOOL("hotplug", PCIESlot, hotplug, true), DEFINE_PROP_END_OF_LIST() }; diff --git a/hw/rtc/twl92230.c b/hw/rtc/twl92230.c index 63bd13d..d0011be 100644 --- a/hw/rtc/twl92230.c +++ b/hw/rtc/twl92230.c @@ -27,7 +27,6 @@ #include "migration/qemu-file-types.h" #include "migration/vmstate.h" #include "sysemu/sysemu.h" -#include "ui/console.h" #include "qemu/bcd.h" #include "qemu/module.h" diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 10d0794..1c0cb63 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -1915,7 +1915,6 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) r->iov.iov_base = blk_blockalign(s->qdev.conf.blk, r->buflen); } - buflen = req->cmd.xfer; outbuf = r->iov.iov_base; memset(outbuf, 0, r->buflen); switch (req->cmd.buf[0]) { diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index 8dbcbdc..380acfa 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -27,7 +27,6 @@ #include "qemu/osdep.h" #include "hw/i386/pc.h" #include "hw/irq.h" -#include "ui/console.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/timer.h" @@ -37,6 +36,7 @@ #include "hw/rtc/mc146818rtc_regs.h" #include "migration/vmstate.h" #include "hw/timer/i8254.h" +#include "exec/address-spaces.h" //#define HPET_DEBUG #ifdef HPET_DEBUG diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 90da008..5c4b57b 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -17,9 +17,7 @@ #include "desc.h" #include "hw/qdev-properties.h" #include "hw/scsi/scsi.h" -#include "ui/console.h" #include "migration/vmstate.h" -#include "monitor/monitor.h" #include "sysemu/sysemu.h" #include "sysemu/block-backend.h" #include "qapi/visitor.h" diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c index 66da965..9f9093e 100644 --- a/hw/virtio/vhost-vsock.c +++ b/hw/virtio/vhost-vsock.c @@ -325,7 +325,7 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) } else { vhostfd = open("/dev/vhost-vsock", O_RDWR); if (vhostfd < 0) { - error_setg_errno(errp, -errno, + error_setg_errno(errp, errno, "vhost-vsock: failed to open vhost device"); return; } diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 0d226da..01ebe12 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -290,7 +290,14 @@ static int vhost_dev_has_iommu(struct vhost_dev *dev) { VirtIODevice *vdev = dev->vdev; - return virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); + /* + * For vhost, VIRTIO_F_IOMMU_PLATFORM means the backend support + * incremental memory mapping API via IOTLB API. For platform that + * does not have IOMMU, there's no need to enable this feature + * which may cause unnecessary IOTLB miss/update trnasactions. + */ + return vdev->dma_as != &address_space_memory && + virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); } static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr, @@ -765,6 +772,9 @@ static int vhost_dev_set_features(struct vhost_dev *dev, if (enable_log) { features |= 0x1ULL << VHOST_F_LOG_ALL; } + if (!vhost_dev_has_iommu(dev)) { + features &= ~(0x1ULL << VIRTIO_F_IOMMU_PLATFORM); + } r = dev->vhost_ops->vhost_set_features(dev, features); if (r < 0) { VHOST_OPS_DEBUG("vhost_set_features failed"); diff --git a/include/block/block-hmp-cmds.h b/include/block/block-hmp-cmds.h new file mode 100644 index 0000000..3412e10 --- /dev/null +++ b/include/block/block-hmp-cmds.h @@ -0,0 +1,54 @@ +/* + * HMP commands related to the block layer + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2020 Red Hat, Inc. + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#ifndef BLOCK_HMP_COMMANDS_H +#define BLOCK_HMP_COMMANDS_H + +void hmp_drive_add(Monitor *mon, const QDict *qdict); + +void hmp_commit(Monitor *mon, const QDict *qdict); +void hmp_drive_del(Monitor *mon, const QDict *qdict); + +void hmp_drive_mirror(Monitor *mon, const QDict *qdict); +void hmp_drive_backup(Monitor *mon, const QDict *qdict); + +void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict); +void hmp_block_job_cancel(Monitor *mon, const QDict *qdict); +void hmp_block_job_pause(Monitor *mon, const QDict *qdict); +void hmp_block_job_resume(Monitor *mon, const QDict *qdict); +void hmp_block_job_complete(Monitor *mon, const QDict *qdict); + +void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict); +void hmp_snapshot_blkdev_internal(Monitor *mon, const QDict *qdict); +void hmp_snapshot_delete_blkdev_internal(Monitor *mon, const QDict *qdict); + +void hmp_nbd_server_start(Monitor *mon, const QDict *qdict); +void hmp_nbd_server_add(Monitor *mon, const QDict *qdict); +void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict); +void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict); + +void hmp_block_resize(Monitor *mon, const QDict *qdict); +void hmp_block_stream(Monitor *mon, const QDict *qdict); +void hmp_block_passwd(Monitor *mon, const QDict *qdict); +void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict); +void hmp_eject(Monitor *mon, const QDict *qdict); + +void hmp_qemu_io(Monitor *mon, const QDict *qdict); + +void hmp_info_block(Monitor *mon, const QDict *qdict); +void hmp_info_blockstats(Monitor *mon, const QDict *qdict); +void hmp_info_block_jobs(Monitor *mon, const QDict *qdict); +void hmp_info_snapshots(Monitor *mon, const QDict *qdict); + +#endif diff --git a/include/block/block_int.h b/include/block/block_int.h index f422c0b..3f70a98 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -1216,8 +1216,6 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, BlockCompletionFunc *cb, void *opaque, JobTxn *txn, Error **errp); -void hmp_drive_add_node(Monitor *mon, const char *optstr); - BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, const char *child_name, const BdrvChildRole *child_role, @@ -1322,4 +1320,7 @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, uint64_t src_offset, int refresh_total_sectors(BlockDriverState *bs, int64_t hint); +void bdrv_set_monitor_owned(BlockDriverState *bs); +BlockDriverState *bds_tree_init(QDict *bs_opts, Error **errp); + #endif /* BLOCK_INT_H */ diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h index 72e803f..a98d10b 100644 --- a/include/hw/i386/ich9.h +++ b/include/hw/i386/ich9.h @@ -5,7 +5,6 @@ #include "hw/sysbus.h" #include "hw/i386/pc.h" #include "hw/isa/apm.h" -#include "hw/i386/ioapic.h" #include "hw/pci/pci.h" #include "hw/pci/pcie_host.h" #include "hw/pci/pci_bridge.h" diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index 66b931e..a1c4afc 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -22,11 +22,7 @@ #ifndef INTEL_IOMMU_H #define INTEL_IOMMU_H -#include "sysemu/dma.h" #include "hw/i386/x86-iommu.h" -#include "hw/i386/ioapic.h" -#include "hw/pci/msi.h" -#include "hw/sysbus.h" #include "qemu/iova-tree.h" #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu" diff --git a/include/hw/i386/ioapic_internal.h b/include/hw/i386/ioapic_internal.h index d46c87c..fe06938 100644 --- a/include/hw/i386/ioapic_internal.h +++ b/include/hw/i386/ioapic_internal.h @@ -23,7 +23,6 @@ #define QEMU_IOAPIC_INTERNAL_H #include "exec/memory.h" -#include "hw/i386/ioapic.h" #include "hw/sysbus.h" #include "qemu/notify.h" diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index d5ac76d..6ab6eda 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -1,20 +1,15 @@ #ifndef HW_PC_H #define HW_PC_H -#include "exec/memory.h" +#include "qemu/notify.h" +#include "qapi/qapi-types-common.h" #include "hw/boards.h" #include "hw/block/fdc.h" #include "hw/block/flash.h" -#include "net/net.h" #include "hw/i386/x86.h" -#include "qemu/range.h" -#include "qemu/bitmap.h" -#include "qemu/module.h" -#include "hw/pci/pci.h" -#include "hw/mem/pc-dimm.h" -#include "hw/mem/nvdimm.h" #include "hw/acpi/acpi_dev_interface.h" +#include "hw/hotplug.h" #define HPET_INTCAP "hpet-intcap" diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h index 976fbae..070305f 100644 --- a/include/hw/pci-host/q35.h +++ b/include/hw/pci-host/q35.h @@ -22,17 +22,11 @@ #ifndef HW_Q35_H #define HW_Q35_H -#include "hw/isa/isa.h" -#include "hw/sysbus.h" -#include "hw/i386/pc.h" -#include "hw/isa/apm.h" #include "hw/pci/pci.h" #include "hw/pci/pcie_host.h" -#include "hw/acpi/acpi.h" -#include "hw/acpi/ich9.h" #include "hw/pci-host/pam.h" -#include "hw/i386/intel_iommu.h" #include "qemu/units.h" +#include "qemu/range.h" #define TYPE_Q35_HOST_DEVICE "q35-pcihost" #define Q35_HOST_DEVICE(obj) \ diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h index 7064875..14c58eb 100644 --- a/include/hw/pci/pcie.h +++ b/include/hw/pci/pcie.h @@ -104,7 +104,7 @@ void pcie_cap_deverr_reset(PCIDevice *dev); void pcie_cap_lnkctl_init(PCIDevice *dev); void pcie_cap_lnkctl_reset(PCIDevice *dev); -void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot); +void pcie_cap_slot_init(PCIDevice *dev, PCIESlot *s); void pcie_cap_slot_reset(PCIDevice *dev); void pcie_cap_slot_get(PCIDevice *dev, uint16_t *slt_ctl, uint16_t *slt_sta); void pcie_cap_slot_write_config(PCIDevice *dev, diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h index 4b3d254..caae575 100644 --- a/include/hw/pci/pcie_port.h +++ b/include/hw/pci/pcie_port.h @@ -55,6 +55,9 @@ struct PCIESlot { /* Disable ACS (really for a pcie_root_port) */ bool disable_acs; + + /* Indicates whether hot-plug is enabled on the slot */ + bool hotplug; QLIST_ENTRY(PCIESlot) next; }; diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h index 3d32985..e33ca5a 100644 --- a/include/monitor/hmp.h +++ b/include/monitor/hmp.h @@ -30,8 +30,6 @@ void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict); void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict); void hmp_info_migrate_cache_size(Monitor *mon, const QDict *qdict); void hmp_info_cpus(Monitor *mon, const QDict *qdict); -void hmp_info_block(Monitor *mon, const QDict *qdict); -void hmp_info_blockstats(Monitor *mon, const QDict *qdict); void hmp_info_vnc(Monitor *mon, const QDict *qdict); void hmp_info_spice(Monitor *mon, const QDict *qdict); void hmp_info_balloon(Monitor *mon, const QDict *qdict); @@ -39,7 +37,6 @@ void hmp_info_irq(Monitor *mon, const QDict *qdict); void hmp_info_pic(Monitor *mon, const QDict *qdict); void hmp_info_rdma(Monitor *mon, const QDict *qdict); void hmp_info_pci(Monitor *mon, const QDict *qdict); -void hmp_info_block_jobs(Monitor *mon, const QDict *qdict); void hmp_info_tpm(Monitor *mon, const QDict *qdict); void hmp_info_iothreads(Monitor *mon, const QDict *qdict); void hmp_quit(Monitor *mon, const QDict *qdict); @@ -58,18 +55,10 @@ void hmp_cont(Monitor *mon, const QDict *qdict); void hmp_system_wakeup(Monitor *mon, const QDict *qdict); void hmp_nmi(Monitor *mon, const QDict *qdict); void hmp_set_link(Monitor *mon, const QDict *qdict); -void hmp_block_passwd(Monitor *mon, const QDict *qdict); void hmp_balloon(Monitor *mon, const QDict *qdict); -void hmp_block_resize(Monitor *mon, const QDict *qdict); -void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict); -void hmp_snapshot_blkdev_internal(Monitor *mon, const QDict *qdict); -void hmp_snapshot_delete_blkdev_internal(Monitor *mon, const QDict *qdict); -void hmp_drive_mirror(Monitor *mon, const QDict *qdict); -void hmp_drive_backup(Monitor *mon, const QDict *qdict); void hmp_loadvm(Monitor *mon, const QDict *qdict); void hmp_savevm(Monitor *mon, const QDict *qdict); void hmp_delvm(Monitor *mon, const QDict *qdict); -void hmp_info_snapshots(Monitor *mon, const QDict *qdict); void hmp_migrate_cancel(Monitor *mon, const QDict *qdict); void hmp_migrate_continue(Monitor *mon, const QDict *qdict); void hmp_migrate_incoming(Monitor *mon, const QDict *qdict); @@ -85,15 +74,7 @@ void hmp_migrate_start_postcopy(Monitor *mon, const QDict *qdict); void hmp_x_colo_lost_heartbeat(Monitor *mon, const QDict *qdict); void hmp_set_password(Monitor *mon, const QDict *qdict); void hmp_expire_password(Monitor *mon, const QDict *qdict); -void hmp_eject(Monitor *mon, const QDict *qdict); void hmp_change(Monitor *mon, const QDict *qdict); -void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict); -void hmp_block_stream(Monitor *mon, const QDict *qdict); -void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict); -void hmp_block_job_cancel(Monitor *mon, const QDict *qdict); -void hmp_block_job_pause(Monitor *mon, const QDict *qdict); -void hmp_block_job_resume(Monitor *mon, const QDict *qdict); -void hmp_block_job_complete(Monitor *mon, const QDict *qdict); void hmp_migrate(Monitor *mon, const QDict *qdict); void hmp_device_add(Monitor *mon, const QDict *qdict); void hmp_device_del(Monitor *mon, const QDict *qdict); @@ -104,15 +85,10 @@ void hmp_getfd(Monitor *mon, const QDict *qdict); void hmp_closefd(Monitor *mon, const QDict *qdict); void hmp_sendkey(Monitor *mon, const QDict *qdict); void hmp_screendump(Monitor *mon, const QDict *qdict); -void hmp_nbd_server_start(Monitor *mon, const QDict *qdict); -void hmp_nbd_server_add(Monitor *mon, const QDict *qdict); -void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict); -void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict); void hmp_chardev_add(Monitor *mon, const QDict *qdict); void hmp_chardev_change(Monitor *mon, const QDict *qdict); void hmp_chardev_remove(Monitor *mon, const QDict *qdict); void hmp_chardev_send_break(Monitor *mon, const QDict *qdict); -void hmp_qemu_io(Monitor *mon, const QDict *qdict); void hmp_cpu_add(Monitor *mon, const QDict *qdict); void hmp_object_add(Monitor *mon, const QDict *qdict); void hmp_object_del(Monitor *mon, const QDict *qdict); diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index d34c492..a86d99b 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -57,8 +57,4 @@ QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file, DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type, Error **errp); -/* device-hotplug */ - -void hmp_commit(Monitor *mon, const QDict *qdict); -void hmp_drive_del(Monitor *mon, const QDict *qdict); #endif diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 479d90b..ef81302 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -63,9 +63,6 @@ extern int nb_option_roms; extern const char *prom_envs[MAX_PROM_ENVS]; extern unsigned int nb_prom_envs; -/* generic hotplug */ -void hmp_drive_add(Monitor *mon, const QDict *qdict); - /* pcie aer error injection */ void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict); diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index fb4c2fd..1c69d51 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -47,9 +47,6 @@ #include "qapi/string-output-visitor.h" #include "qom/object_interfaces.h" #include "ui/console.h" -#include "block/nbd.h" -#include "block/qapi.h" -#include "qemu-io.h" #include "qemu/cutils.h" #include "qemu/error-report.h" #include "exec/ramlist.h" @@ -472,213 +469,6 @@ void hmp_info_migrate_cache_size(Monitor *mon, const QDict *qdict) qmp_query_migrate_cache_size(NULL) >> 10); } -static void print_block_info(Monitor *mon, BlockInfo *info, - BlockDeviceInfo *inserted, bool verbose) -{ - ImageInfo *image_info; - - assert(!info || !info->has_inserted || info->inserted == inserted); - - if (info && *info->device) { - monitor_printf(mon, "%s", info->device); - if (inserted && inserted->has_node_name) { - monitor_printf(mon, " (%s)", inserted->node_name); - } - } else { - assert(info || inserted); - monitor_printf(mon, "%s", - inserted && inserted->has_node_name ? inserted->node_name - : info && info->has_qdev ? info->qdev - : "<anonymous>"); - } - - if (inserted) { - monitor_printf(mon, ": %s (%s%s%s)\n", - inserted->file, - inserted->drv, - inserted->ro ? ", read-only" : "", - inserted->encrypted ? ", encrypted" : ""); - } else { - monitor_printf(mon, ": [not inserted]\n"); - } - - if (info) { - if (info->has_qdev) { - monitor_printf(mon, " Attached to: %s\n", info->qdev); - } - if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) { - monitor_printf(mon, " I/O status: %s\n", - BlockDeviceIoStatus_str(info->io_status)); - } - - if (info->removable) { - monitor_printf(mon, " Removable device: %slocked, tray %s\n", - info->locked ? "" : "not ", - info->tray_open ? "open" : "closed"); - } - } - - - if (!inserted) { - return; - } - - monitor_printf(mon, " Cache mode: %s%s%s\n", - inserted->cache->writeback ? "writeback" : "writethrough", - inserted->cache->direct ? ", direct" : "", - inserted->cache->no_flush ? ", ignore flushes" : ""); - - if (inserted->has_backing_file) { - monitor_printf(mon, - " Backing file: %s " - "(chain depth: %" PRId64 ")\n", - inserted->backing_file, - inserted->backing_file_depth); - } - - if (inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) { - monitor_printf(mon, " Detect zeroes: %s\n", - BlockdevDetectZeroesOptions_str(inserted->detect_zeroes)); - } - - if (inserted->bps || inserted->bps_rd || inserted->bps_wr || - inserted->iops || inserted->iops_rd || inserted->iops_wr) - { - monitor_printf(mon, " I/O throttling: bps=%" PRId64 - " bps_rd=%" PRId64 " bps_wr=%" PRId64 - " bps_max=%" PRId64 - " bps_rd_max=%" PRId64 - " bps_wr_max=%" PRId64 - " iops=%" PRId64 " iops_rd=%" PRId64 - " iops_wr=%" PRId64 - " iops_max=%" PRId64 - " iops_rd_max=%" PRId64 - " iops_wr_max=%" PRId64 - " iops_size=%" PRId64 - " group=%s\n", - inserted->bps, - inserted->bps_rd, - inserted->bps_wr, - inserted->bps_max, - inserted->bps_rd_max, - inserted->bps_wr_max, - inserted->iops, - inserted->iops_rd, - inserted->iops_wr, - inserted->iops_max, - inserted->iops_rd_max, - inserted->iops_wr_max, - inserted->iops_size, - inserted->group); - } - - if (verbose) { - monitor_printf(mon, "\nImages:\n"); - image_info = inserted->image; - while (1) { - bdrv_image_info_dump(image_info); - if (image_info->has_backing_image) { - image_info = image_info->backing_image; - } else { - break; - } - } - } -} - -void hmp_info_block(Monitor *mon, const QDict *qdict) -{ - BlockInfoList *block_list, *info; - BlockDeviceInfoList *blockdev_list, *blockdev; - const char *device = qdict_get_try_str(qdict, "device"); - bool verbose = qdict_get_try_bool(qdict, "verbose", false); - bool nodes = qdict_get_try_bool(qdict, "nodes", false); - bool printed = false; - - /* Print BlockBackend information */ - if (!nodes) { - block_list = qmp_query_block(NULL); - } else { - block_list = NULL; - } - - for (info = block_list; info; info = info->next) { - if (device && strcmp(device, info->value->device)) { - continue; - } - - if (info != block_list) { - monitor_printf(mon, "\n"); - } - - print_block_info(mon, info->value, info->value->has_inserted - ? info->value->inserted : NULL, - verbose); - printed = true; - } - - qapi_free_BlockInfoList(block_list); - - if ((!device && !nodes) || printed) { - return; - } - - /* Print node information */ - blockdev_list = qmp_query_named_block_nodes(false, false, NULL); - for (blockdev = blockdev_list; blockdev; blockdev = blockdev->next) { - assert(blockdev->value->has_node_name); - if (device && strcmp(device, blockdev->value->node_name)) { - continue; - } - - if (blockdev != blockdev_list) { - monitor_printf(mon, "\n"); - } - - print_block_info(mon, NULL, blockdev->value, verbose); - } - qapi_free_BlockDeviceInfoList(blockdev_list); -} - -void hmp_info_blockstats(Monitor *mon, const QDict *qdict) -{ - BlockStatsList *stats_list, *stats; - - stats_list = qmp_query_blockstats(false, false, NULL); - - for (stats = stats_list; stats; stats = stats->next) { - if (!stats->value->has_device) { - continue; - } - - monitor_printf(mon, "%s:", stats->value->device); - monitor_printf(mon, " rd_bytes=%" PRId64 - " wr_bytes=%" PRId64 - " rd_operations=%" PRId64 - " wr_operations=%" PRId64 - " flush_operations=%" PRId64 - " wr_total_time_ns=%" PRId64 - " rd_total_time_ns=%" PRId64 - " flush_total_time_ns=%" PRId64 - " rd_merged=%" PRId64 - " wr_merged=%" PRId64 - " idle_time_ns=%" PRId64 - "\n", - stats->value->stats->rd_bytes, - stats->value->stats->wr_bytes, - stats->value->stats->rd_operations, - stats->value->stats->wr_operations, - stats->value->stats->flush_operations, - stats->value->stats->wr_total_time_ns, - stats->value->stats->rd_total_time_ns, - stats->value->stats->flush_total_time_ns, - stats->value->stats->rd_merged, - stats->value->stats->wr_merged, - stats->value->stats->idle_time_ns); - } - - qapi_free_BlockStatsList(stats_list); -} #ifdef CONFIG_VNC /* Helper for hmp_info_vnc_clients, _servers */ @@ -1058,44 +848,6 @@ void hmp_info_pci(Monitor *mon, const QDict *qdict) qapi_free_PciInfoList(info_list); } -void hmp_info_block_jobs(Monitor *mon, const QDict *qdict) -{ - BlockJobInfoList *list; - Error *err = NULL; - - list = qmp_query_block_jobs(&err); - assert(!err); - - if (!list) { - monitor_printf(mon, "No active jobs\n"); - return; - } - - while (list) { - if (strcmp(list->value->type, "stream") == 0) { - monitor_printf(mon, "Streaming device %s: Completed %" PRId64 - " of %" PRId64 " bytes, speed limit %" PRId64 - " bytes/s\n", - list->value->device, - list->value->offset, - list->value->len, - list->value->speed); - } else { - monitor_printf(mon, "Type %s, device %s: Completed %" PRId64 - " of %" PRId64 " bytes, speed limit %" PRId64 - " bytes/s\n", - list->value->type, - list->value->device, - list->value->offset, - list->value->len, - list->value->speed); - } - list = list->next; - } - - qapi_free_BlockJobInfoList(list); -} - void hmp_info_tpm(Monitor *mon, const QDict *qdict) { TPMInfoList *info_list, *info; @@ -1313,16 +1065,6 @@ void hmp_set_link(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, err); } -void hmp_block_passwd(Monitor *mon, const QDict *qdict) -{ - const char *device = qdict_get_str(qdict, "device"); - const char *password = qdict_get_str(qdict, "password"); - Error *err = NULL; - - qmp_block_passwd(true, device, false, NULL, password, &err); - hmp_handle_error(mon, err); -} - void hmp_balloon(Monitor *mon, const QDict *qdict) { int64_t value = qdict_get_int(qdict, "value"); @@ -1332,121 +1074,6 @@ void hmp_balloon(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, err); } -void hmp_block_resize(Monitor *mon, const QDict *qdict) -{ - const char *device = qdict_get_str(qdict, "device"); - int64_t size = qdict_get_int(qdict, "size"); - Error *err = NULL; - - qmp_block_resize(true, device, false, NULL, size, &err); - hmp_handle_error(mon, err); -} - -void hmp_drive_mirror(Monitor *mon, const QDict *qdict) -{ - const char *filename = qdict_get_str(qdict, "target"); - const char *format = qdict_get_try_str(qdict, "format"); - bool reuse = qdict_get_try_bool(qdict, "reuse", false); - bool full = qdict_get_try_bool(qdict, "full", false); - Error *err = NULL; - DriveMirror mirror = { - .device = (char *)qdict_get_str(qdict, "device"), - .target = (char *)filename, - .has_format = !!format, - .format = (char *)format, - .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP, - .has_mode = true, - .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS, - .unmap = true, - }; - - if (!filename) { - error_setg(&err, QERR_MISSING_PARAMETER, "target"); - hmp_handle_error(mon, err); - return; - } - qmp_drive_mirror(&mirror, &err); - hmp_handle_error(mon, err); -} - -void hmp_drive_backup(Monitor *mon, const QDict *qdict) -{ - const char *device = qdict_get_str(qdict, "device"); - const char *filename = qdict_get_str(qdict, "target"); - const char *format = qdict_get_try_str(qdict, "format"); - bool reuse = qdict_get_try_bool(qdict, "reuse", false); - bool full = qdict_get_try_bool(qdict, "full", false); - bool compress = qdict_get_try_bool(qdict, "compress", false); - Error *err = NULL; - DriveBackup backup = { - .device = (char *)device, - .target = (char *)filename, - .has_format = !!format, - .format = (char *)format, - .sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP, - .has_mode = true, - .mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS, - .has_compress = !!compress, - .compress = compress, - }; - - if (!filename) { - error_setg(&err, QERR_MISSING_PARAMETER, "target"); - hmp_handle_error(mon, err); - return; - } - - qmp_drive_backup(&backup, &err); - hmp_handle_error(mon, err); -} - -void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict) -{ - const char *device = qdict_get_str(qdict, "device"); - const char *filename = qdict_get_try_str(qdict, "snapshot-file"); - const char *format = qdict_get_try_str(qdict, "format"); - bool reuse = qdict_get_try_bool(qdict, "reuse", false); - enum NewImageMode mode; - Error *err = NULL; - - if (!filename) { - /* In the future, if 'snapshot-file' is not specified, the snapshot - will be taken internally. Today it's actually required. */ - error_setg(&err, QERR_MISSING_PARAMETER, "snapshot-file"); - hmp_handle_error(mon, err); - return; - } - - mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS; - qmp_blockdev_snapshot_sync(true, device, false, NULL, - filename, false, NULL, - !!format, format, - true, mode, &err); - hmp_handle_error(mon, err); -} - -void hmp_snapshot_blkdev_internal(Monitor *mon, const QDict *qdict) -{ - const char *device = qdict_get_str(qdict, "device"); - const char *name = qdict_get_str(qdict, "name"); - Error *err = NULL; - - qmp_blockdev_snapshot_internal_sync(device, name, &err); - hmp_handle_error(mon, err); -} - -void hmp_snapshot_delete_blkdev_internal(Monitor *mon, const QDict *qdict) -{ - const char *device = qdict_get_str(qdict, "device"); - const char *name = qdict_get_str(qdict, "name"); - const char *id = qdict_get_try_str(qdict, "id"); - Error *err = NULL; - - qmp_blockdev_snapshot_delete_internal_sync(device, !!id, id, - true, name, &err); - hmp_handle_error(mon, err); -} - void hmp_loadvm(Monitor *mon, const QDict *qdict) { int saved_vm_running = runstate_is_running(); @@ -1483,148 +1110,6 @@ void hmp_delvm(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, err); } -void hmp_info_snapshots(Monitor *mon, const QDict *qdict) -{ - BlockDriverState *bs, *bs1; - BdrvNextIterator it1; - QEMUSnapshotInfo *sn_tab, *sn; - bool no_snapshot = true; - int nb_sns, i; - int total; - int *global_snapshots; - AioContext *aio_context; - - typedef struct SnapshotEntry { - QEMUSnapshotInfo sn; - QTAILQ_ENTRY(SnapshotEntry) next; - } SnapshotEntry; - - typedef struct ImageEntry { - const char *imagename; - QTAILQ_ENTRY(ImageEntry) next; - QTAILQ_HEAD(, SnapshotEntry) snapshots; - } ImageEntry; - - QTAILQ_HEAD(, ImageEntry) image_list = - QTAILQ_HEAD_INITIALIZER(image_list); - - ImageEntry *image_entry, *next_ie; - SnapshotEntry *snapshot_entry; - - bs = bdrv_all_find_vmstate_bs(); - if (!bs) { - monitor_printf(mon, "No available block device supports snapshots\n"); - return; - } - aio_context = bdrv_get_aio_context(bs); - - aio_context_acquire(aio_context); - nb_sns = bdrv_snapshot_list(bs, &sn_tab); - aio_context_release(aio_context); - - if (nb_sns < 0) { - monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns); - return; - } - - for (bs1 = bdrv_first(&it1); bs1; bs1 = bdrv_next(&it1)) { - int bs1_nb_sns = 0; - ImageEntry *ie; - SnapshotEntry *se; - AioContext *ctx = bdrv_get_aio_context(bs1); - - aio_context_acquire(ctx); - if (bdrv_can_snapshot(bs1)) { - sn = NULL; - bs1_nb_sns = bdrv_snapshot_list(bs1, &sn); - if (bs1_nb_sns > 0) { - no_snapshot = false; - ie = g_new0(ImageEntry, 1); - ie->imagename = bdrv_get_device_name(bs1); - QTAILQ_INIT(&ie->snapshots); - QTAILQ_INSERT_TAIL(&image_list, ie, next); - for (i = 0; i < bs1_nb_sns; i++) { - se = g_new0(SnapshotEntry, 1); - se->sn = sn[i]; - QTAILQ_INSERT_TAIL(&ie->snapshots, se, next); - } - } - g_free(sn); - } - aio_context_release(ctx); - } - - if (no_snapshot) { - monitor_printf(mon, "There is no snapshot available.\n"); - return; - } - - global_snapshots = g_new0(int, nb_sns); - total = 0; - for (i = 0; i < nb_sns; i++) { - SnapshotEntry *next_sn; - if (bdrv_all_find_snapshot(sn_tab[i].name, &bs1) == 0) { - global_snapshots[total] = i; - total++; - QTAILQ_FOREACH(image_entry, &image_list, next) { - QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots, - next, next_sn) { - if (!strcmp(sn_tab[i].name, snapshot_entry->sn.name)) { - QTAILQ_REMOVE(&image_entry->snapshots, snapshot_entry, - next); - g_free(snapshot_entry); - } - } - } - } - } - - monitor_printf(mon, "List of snapshots present on all disks:\n"); - - if (total > 0) { - bdrv_snapshot_dump(NULL); - monitor_printf(mon, "\n"); - for (i = 0; i < total; i++) { - sn = &sn_tab[global_snapshots[i]]; - /* The ID is not guaranteed to be the same on all images, so - * overwrite it. - */ - pstrcpy(sn->id_str, sizeof(sn->id_str), "--"); - bdrv_snapshot_dump(sn); - monitor_printf(mon, "\n"); - } - } else { - monitor_printf(mon, "None\n"); - } - - QTAILQ_FOREACH(image_entry, &image_list, next) { - if (QTAILQ_EMPTY(&image_entry->snapshots)) { - continue; - } - monitor_printf(mon, - "\nList of partial (non-loadable) snapshots on '%s':\n", - image_entry->imagename); - bdrv_snapshot_dump(NULL); - monitor_printf(mon, "\n"); - QTAILQ_FOREACH(snapshot_entry, &image_entry->snapshots, next) { - bdrv_snapshot_dump(&snapshot_entry->sn); - monitor_printf(mon, "\n"); - } - } - - QTAILQ_FOREACH_SAFE(image_entry, &image_list, next, next_ie) { - SnapshotEntry *next_sn; - QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots, next, - next_sn) { - g_free(snapshot_entry); - } - g_free(image_entry); - } - g_free(sn_tab); - g_free(global_snapshots); - -} - void hmp_announce_self(Monitor *mon, const QDict *qdict) { const char *interfaces_str = qdict_get_try_str(qdict, "interfaces"); @@ -1946,15 +1431,6 @@ void hmp_expire_password(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, err); } -void hmp_eject(Monitor *mon, const QDict *qdict) -{ - bool force = qdict_get_try_bool(qdict, "force", false); - const char *device = qdict_get_str(qdict, "device"); - Error *err = NULL; - - qmp_eject(true, device, false, NULL, true, force, &err); - hmp_handle_error(mon, err); -} #ifdef CONFIG_VNC static void hmp_change_read_arg(void *opaque, const char *password, @@ -2012,101 +1488,6 @@ void hmp_change(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, err); } -void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict) -{ - Error *err = NULL; - char *device = (char *) qdict_get_str(qdict, "device"); - BlockIOThrottle throttle = { - .bps = qdict_get_int(qdict, "bps"), - .bps_rd = qdict_get_int(qdict, "bps_rd"), - .bps_wr = qdict_get_int(qdict, "bps_wr"), - .iops = qdict_get_int(qdict, "iops"), - .iops_rd = qdict_get_int(qdict, "iops_rd"), - .iops_wr = qdict_get_int(qdict, "iops_wr"), - }; - - /* qmp_block_set_io_throttle has separate parameters for the - * (deprecated) block device name and the qdev ID but the HMP - * version has only one, so we must decide which one to pass. */ - if (blk_by_name(device)) { - throttle.has_device = true; - throttle.device = device; - } else { - throttle.has_id = true; - throttle.id = device; - } - - qmp_block_set_io_throttle(&throttle, &err); - hmp_handle_error(mon, err); -} - -void hmp_block_stream(Monitor *mon, const QDict *qdict) -{ - Error *error = NULL; - const char *device = qdict_get_str(qdict, "device"); - const char *base = qdict_get_try_str(qdict, "base"); - int64_t speed = qdict_get_try_int(qdict, "speed", 0); - - qmp_block_stream(true, device, device, base != NULL, base, false, NULL, - false, NULL, qdict_haskey(qdict, "speed"), speed, true, - BLOCKDEV_ON_ERROR_REPORT, false, false, false, false, - &error); - - hmp_handle_error(mon, error); -} - -void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict) -{ - Error *error = NULL; - const char *device = qdict_get_str(qdict, "device"); - int64_t value = qdict_get_int(qdict, "speed"); - - qmp_block_job_set_speed(device, value, &error); - - hmp_handle_error(mon, error); -} - -void hmp_block_job_cancel(Monitor *mon, const QDict *qdict) -{ - Error *error = NULL; - const char *device = qdict_get_str(qdict, "device"); - bool force = qdict_get_try_bool(qdict, "force", false); - - qmp_block_job_cancel(device, true, force, &error); - - hmp_handle_error(mon, error); -} - -void hmp_block_job_pause(Monitor *mon, const QDict *qdict) -{ - Error *error = NULL; - const char *device = qdict_get_str(qdict, "device"); - - qmp_block_job_pause(device, &error); - - hmp_handle_error(mon, error); -} - -void hmp_block_job_resume(Monitor *mon, const QDict *qdict) -{ - Error *error = NULL; - const char *device = qdict_get_str(qdict, "device"); - - qmp_block_job_resume(device, &error); - - hmp_handle_error(mon, error); -} - -void hmp_block_job_complete(Monitor *mon, const QDict *qdict) -{ - Error *error = NULL; - const char *device = qdict_get_str(qdict, "device"); - - qmp_block_job_complete(device, &error); - - hmp_handle_error(mon, error); -} - typedef struct HMPMigrationStatus { QEMUTimer *timer; @@ -2333,105 +1714,6 @@ void hmp_screendump(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, err); } -void hmp_nbd_server_start(Monitor *mon, const QDict *qdict) -{ - const char *uri = qdict_get_str(qdict, "uri"); - bool writable = qdict_get_try_bool(qdict, "writable", false); - bool all = qdict_get_try_bool(qdict, "all", false); - Error *local_err = NULL; - BlockInfoList *block_list, *info; - SocketAddress *addr; - BlockExportNbd export; - - if (writable && !all) { - error_setg(&local_err, "-w only valid together with -a"); - goto exit; - } - - /* First check if the address is valid and start the server. */ - addr = socket_parse(uri, &local_err); - if (local_err != NULL) { - goto exit; - } - - nbd_server_start(addr, NULL, NULL, &local_err); - qapi_free_SocketAddress(addr); - if (local_err != NULL) { - goto exit; - } - - if (!all) { - return; - } - - /* Then try adding all block devices. If one fails, close all and - * exit. - */ - block_list = qmp_query_block(NULL); - - for (info = block_list; info; info = info->next) { - if (!info->value->has_inserted) { - continue; - } - - export = (BlockExportNbd) { - .device = info->value->device, - .has_writable = true, - .writable = writable, - }; - - qmp_nbd_server_add(&export, &local_err); - - if (local_err != NULL) { - qmp_nbd_server_stop(NULL); - break; - } - } - - qapi_free_BlockInfoList(block_list); - -exit: - hmp_handle_error(mon, local_err); -} - -void hmp_nbd_server_add(Monitor *mon, const QDict *qdict) -{ - const char *device = qdict_get_str(qdict, "device"); - const char *name = qdict_get_try_str(qdict, "name"); - bool writable = qdict_get_try_bool(qdict, "writable", false); - Error *local_err = NULL; - - BlockExportNbd export = { - .device = (char *) device, - .has_name = !!name, - .name = (char *) name, - .has_writable = true, - .writable = writable, - }; - - qmp_nbd_server_add(&export, &local_err); - hmp_handle_error(mon, local_err); -} - -void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict) -{ - const char *name = qdict_get_str(qdict, "name"); - bool force = qdict_get_try_bool(qdict, "force", false); - Error *err = NULL; - - /* Rely on NBD_SERVER_REMOVE_MODE_SAFE being the default */ - qmp_nbd_server_remove(name, force, NBD_SERVER_REMOVE_MODE_HARD, &err); - hmp_handle_error(mon, err); -} - -void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict) -{ - Error *err = NULL; - - qmp_nbd_server_stop(&err); - hmp_handle_error(mon, err); -} - void hmp_chardev_add(Monitor *mon, const QDict *qdict) { const char *args = qdict_get_str(qdict, "args"); @@ -2498,70 +1780,6 @@ void hmp_chardev_send_break(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, local_err); } -void hmp_qemu_io(Monitor *mon, const QDict *qdict) -{ - BlockBackend *blk; - BlockBackend *local_blk = NULL; - bool qdev = qdict_get_try_bool(qdict, "qdev", false); - const char* device = qdict_get_str(qdict, "device"); - const char* command = qdict_get_str(qdict, "command"); - Error *err = NULL; - int ret; - - if (qdev) { - blk = blk_by_qdev_id(device, &err); - if (!blk) { - goto fail; - } - } else { - blk = blk_by_name(device); - if (!blk) { - BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err); - if (bs) { - blk = local_blk = blk_new(bdrv_get_aio_context(bs), - 0, BLK_PERM_ALL); - ret = blk_insert_bs(blk, bs, &err); - if (ret < 0) { - goto fail; - } - } else { - goto fail; - } - } - } - - /* - * Notably absent: Proper permission management. This is sad, but it seems - * almost impossible to achieve without changing the semantics and thereby - * limiting the use cases of the qemu-io HMP command. - * - * In an ideal world we would unconditionally create a new BlockBackend for - * qemuio_command(), but we have commands like 'reopen' and want them to - * take effect on the exact BlockBackend whose name the user passed instead - * of just on a temporary copy of it. - * - * Another problem is that deleting the temporary BlockBackend involves - * draining all requests on it first, but some qemu-iotests cases want to - * issue multiple aio_read/write requests and expect them to complete in - * the background while the monitor has already returned. - * - * This is also what prevents us from saving the original permissions and - * restoring them later: We can't revoke permissions until all requests - * have completed, and we don't know when that is nor can we really let - * anything else run before we have revoken them to avoid race conditions. - * - * What happens now is that command() in qemu-io-cmds.c can extend the - * permissions if necessary for the qemu-io command. And they simply stay - * extended, possibly resulting in a read-only guest device keeping write - * permissions. Ugly, but it appears to be the lesser evil. - */ - qemuio_command(blk, command); - -fail: - blk_unref(local_blk); - hmp_handle_error(mon, err); -} - void hmp_object_del(Monitor *mon, const QDict *qdict) { const char *id = qdict_get_str(qdict, "id"); @@ -2842,7 +2060,6 @@ void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict) const char *name = qdict_get_str(qdict, "name"); uint8_t type = qdict_get_try_int(qdict, "type", 9); Error *err = NULL; - bool set = false; list = qmp_query_rocker_of_dpa_groups(name, type != 9, type, &err); if (err != NULL) { @@ -2854,6 +2071,7 @@ void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict) for (g = list; g; g = g->next) { RockerOfDpaGroup *group = g->value; + bool set = false; monitor_printf(mon, "0x%08x", group->id); @@ -2898,14 +2116,11 @@ void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict) if (group->has_set_eth_dst) { if (!set) { - set = true; monitor_printf(mon, " set"); } monitor_printf(mon, " dst %s", group->set_eth_dst); } - set = false; - if (group->has_ttl_check && group->ttl_check) { monitor_printf(mon, " check TTL"); } diff --git a/monitor/misc.c b/monitor/misc.c index 1748ab3..c3bc34c 100644 --- a/monitor/misc.c +++ b/monitor/misc.c @@ -66,6 +66,7 @@ #include "qemu/option.h" #include "qemu/thread.h" #include "block/qapi.h" +#include "block/block-hmp-cmds.h" #include "qapi/qapi-commands-char.h" #include "qapi/qapi-commands-control.h" #include "qapi/qapi-commands-migration.h" @@ -194,29 +194,6 @@ NetClientState *net_hub_add_port(int hub_id, const char *name, } /** - * Find a specific client on a hub - */ -NetClientState *net_hub_find_client_by_name(int hub_id, const char *name) -{ - NetHub *hub; - NetHubPort *port; - NetClientState *peer; - - QLIST_FOREACH(hub, &hubs, next) { - if (hub->id == hub_id) { - QLIST_FOREACH(port, &hub->ports, next) { - peer = port->nc.peer; - - if (peer && strcmp(peer->name, name) == 0) { - return peer; - } - } - } - } - return NULL; -} - -/** * Find a available port on a hub; otherwise create one new port */ NetClientState *net_hub_port_find(int hub_id) @@ -15,10 +15,8 @@ #ifndef NET_HUB_H #define NET_HUB_H - NetClientState *net_hub_add_port(int hub_id, const char *name, NetClientState *hubpeer); -NetClientState *net_hub_find_client_by_name(int hub_id, const char *name); void net_hub_info(Monitor *mon); void net_hub_check_clients(void); bool net_hub_flush(NetClientState *nc); diff --git a/net/slirp.c b/net/slirp.c index c4334ee..77042e6 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -610,25 +610,13 @@ error: return -1; } -static SlirpState *slirp_lookup(Monitor *mon, const char *hub_id, - const char *name) +static SlirpState *slirp_lookup(Monitor *mon, const char *id) { - if (name) { - NetClientState *nc; - if (hub_id) { - nc = net_hub_find_client_by_name(strtol(hub_id, NULL, 0), name); - if (!nc) { - monitor_printf(mon, "unrecognized (hub-id, stackname) pair\n"); - return NULL; - } - warn_report("Using 'hub-id' is deprecated, specify the netdev id " - "directly instead"); - } else { - nc = qemu_find_netdev(name); - if (!nc) { - monitor_printf(mon, "unrecognized netdev id '%s'\n", name); - return NULL; - } + if (id) { + NetClientState *nc = qemu_find_netdev(id); + if (!nc) { + monitor_printf(mon, "unrecognized netdev id '%s'\n", id); + return NULL; } if (strcmp(nc->model, "user")) { monitor_printf(mon, "invalid device specified\n"); @@ -655,16 +643,12 @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict) int err; const char *arg1 = qdict_get_str(qdict, "arg1"); const char *arg2 = qdict_get_try_str(qdict, "arg2"); - const char *arg3 = qdict_get_try_str(qdict, "arg3"); - if (arg3) { - s = slirp_lookup(mon, arg1, arg2); - src_str = arg3; - } else if (arg2) { - s = slirp_lookup(mon, NULL, arg1); + if (arg2) { + s = slirp_lookup(mon, arg1); src_str = arg2; } else { - s = slirp_lookup(mon, NULL, NULL); + s = slirp_lookup(mon, NULL); src_str = arg1; } if (!s) { @@ -784,16 +768,12 @@ void hmp_hostfwd_add(Monitor *mon, const QDict *qdict) SlirpState *s; const char *arg1 = qdict_get_str(qdict, "arg1"); const char *arg2 = qdict_get_try_str(qdict, "arg2"); - const char *arg3 = qdict_get_try_str(qdict, "arg3"); - if (arg3) { - s = slirp_lookup(mon, arg1, arg2); - redir_str = arg3; - } else if (arg2) { - s = slirp_lookup(mon, NULL, arg1); + if (arg2) { + s = slirp_lookup(mon, arg1); redir_str = arg2; } else { - s = slirp_lookup(mon, NULL, NULL); + s = slirp_lookup(mon, NULL); redir_str = arg1; } if (s) { @@ -177,9 +177,20 @@ SectionEnd !ifdef CONFIG_DOCUMENTATION Section "Documentation" SectionDoc SetOutPath "$INSTDIR" - File "${BINDIR}\qemu-doc.html" + File "${BINDIR}\index.html" + SetOutPath "$INSTDIR\interop" + FILE /r "${BINDIR}\interop\*.*" + SetOutPath "$INSTDIR\specs" + FILE /r "${BINDIR}\specs\*.*" + SetOutPath "$INSTDIR\system" + FILE /r "${BINDIR}\system\*.*" + SetOutPath "$INSTDIR\tools" + FILE /r "${BINDIR}\tools\*.*" + SetOutPath "$INSTDIR\user" + FILE /r "${BINDIR}\user\*.*" + SetOutPath "$INSTDIR" CreateDirectory "$SMPROGRAMS\${PRODUCT}" - CreateShortCut "$SMPROGRAMS\${PRODUCT}\User Documentation.lnk" "$INSTDIR\qemu-doc.html" "" "$INSTDIR\qemu-doc.html" 0 + CreateShortCut "$SMPROGRAMS\${PRODUCT}\User Documentation.lnk" "$INSTDIR\index.html" "" "$INSTDIR\index.html" 0 SectionEnd !endif @@ -227,7 +238,12 @@ Section "Uninstall" Delete "$INSTDIR\qemu-io.exe" Delete "$INSTDIR\qemu.exe" Delete "$INSTDIR\qemu-system-*.exe" - Delete "$INSTDIR\qemu-doc.html" + Delete "$INSTDIR\index.html" + RMDir /r "$INSTDIR\interop" + RMDir /r "$INSTDIR\specs" + RMDir /r "$INSTDIR\system" + RMDir /r "$INSTDIR\tools" + RMDir /r "$INSTDIR\user" RMDir /r "$INSTDIR\keymaps" RMDir /r "$INSTDIR\share" ; Remove generated files diff --git a/qga/channel-win32.c b/qga/channel-win32.c index c86f438..4f04868 100644 --- a/qga/channel-win32.c +++ b/qga/channel-win32.c @@ -302,13 +302,14 @@ static gboolean ga_channel_open(GAChannel *c, GAChannelMethod method, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL); if (c->handle == INVALID_HANDLE_VALUE) { - g_critical("error opening path %s: %s", newpath, - g_win32_error_message(GetLastError())); + g_autofree gchar *emsg = g_win32_error_message(GetLastError()); + g_critical("error opening path %s: %s", newpath, emsg); return false; } if (method == GA_CHANNEL_ISA_SERIAL && !SetCommTimeouts(c->handle,&comTimeOut)) { - g_critical("error setting timeout for com port: %lu",GetLastError()); + g_autofree gchar *emsg = g_win32_error_message(GetLastError()); + g_critical("error setting timeout for com port: %s", emsg); CloseHandle(c->handle); return false; } diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 2461fd1..9c744d6 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -315,8 +315,9 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **errp) } if (!ExitWindowsEx(shutdown_flag, SHTDN_REASON_FLAG_PLANNED)) { - slog("guest-shutdown failed: %lu", GetLastError()); - error_setg(errp, QERR_UNDEFINED_ERROR); + g_autofree gchar *emsg = g_win32_error_message(GetLastError()); + slog("guest-shutdown failed: %s", emsg); + error_setg_win32(errp, GetLastError(), "guest-shutdown failed"); } } @@ -1319,7 +1320,8 @@ static DWORD WINAPI do_suspend(LPVOID opaque) DWORD ret = 0; if (!SetSuspendState(*mode == GUEST_SUSPEND_MODE_DISK, TRUE, TRUE)) { - slog("failed to suspend guest, %lu", GetLastError()); + g_autofree gchar *emsg = g_win32_error_message(GetLastError()); + slog("failed to suspend guest: %s", emsg); ret = -1; } g_free(mode); @@ -435,3 +435,6 @@ sentinel = .$(subst $(SPACE),_,$(subst /,_,$1)).sentinel. atomic = $(eval $1: $(call sentinel,$1) ; @:) \ $(call sentinel,$1) : $2 ; @touch $$@ \ $(foreach t,$1,$(if $(wildcard $t),,$(shell rm -f $(call sentinel,$1)))) + +print-%: + @echo '$*=$($*)' diff --git a/scripts/git.orderfile b/scripts/git.orderfile index 7cf22e0..73fd818 100644 --- a/scripts/git.orderfile +++ b/scripts/git.orderfile @@ -11,6 +11,7 @@ # Documentation docs/* +*.rst *.texi # build system diff --git a/softmmu/vl.c b/softmmu/vl.c index 5549f4b..ff2685d 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "qemu/units.h" +#include "hw/boards.h" #include "hw/qdev-properties.h" #include "qapi/error.h" #include "qemu-version.h" diff --git a/util/osdep.c b/util/osdep.c index f7d0605..4829c07 100644 --- a/util/osdep.c +++ b/util/osdep.c @@ -82,8 +82,8 @@ static int qemu_mprotect__osdep(void *addr, size_t size, int prot) DWORD old_protect; if (!VirtualProtect(addr, size, prot, &old_protect)) { - error_report("%s: VirtualProtect failed with error code %ld", - __func__, GetLastError()); + g_autofree gchar *emsg = g_win32_error_message(GetLastError()); + error_report("%s: VirtualProtect failed: %s", __func__, emsg); return -1; } return 0; |