Merge tag 'pull-target-arm-20240126' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target-arm queue:
* Fix VNCR fault detection logic
* Fix A64 scalar SQSHRN and SQRSHRN
* Fix incorrect aa64_tidcp1 feature check
* hw/arm/virt.c: Remove newline from error_report() string
* hw/arm/musicpal: Convert to qemu_add_kbd_event_handler()
* hw/arm/allwinner-a10: Unconditionally map the USB Host controllers
* hw/arm/nseries: Unconditionally map the TUSB6010 USB Host controller
* hw/arm: Add EHCI/OHCI controllers to Allwinner R40 and Bananapi board
* hw/arm: Add AHCI/SATA controller to Allwinner R40 and Bananapi board
* hw/arm: Add watchdog timer to Allwinner H40 and Bananapi board
* arm: various include header cleanups
* cleanups to allow some files to be built only once
* fsl-imx6ul: Add various missing unimplemented devices
* docs/system/arm/virt.rst: Add note on CPU features off by default
* hw/char/imx_serial: Implement receive FIFO and ageing timer
* target/xtensa: fix OOB TLB entry access
* bswap.h: Fix const_le64() macro
* hw/arm: add PCIe to Freescale i.MX6
# -----BEGIN PGP SIGNATURE-----
#
# iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmWzwpsZHHBldGVyLm1h
# eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3oTVD/4jM7ttKlXxtWsJ/cKDL5Im
# uMmDECPrdK2qaNpONfV/YC3WadM6bSgB8OQd2YlI67DLgl3Hfaa+GnQsZhEgZ3lC
# VECOTg5OKwwJY+Ac86t1GJa483wDEQ6NL08oLN94n9Ub/9G0S3oWpmE4bgof7PzW
# rbLDDpKP+W5NfkqMfA5piV7N6mFHvg9wqFX//quqySIiu8NesKV9LmlP/FyNDU/s
# 8ZeSqo/tq/IHr9IeYUtOoxVwYUOPuNKwD+vwy1taiXgjvVtq2URrCrlc4+KCWJsj
# VUBSXdY2boqK31KFZ9NP9kJhIS5gmzgnK8YrHX6sgSbh+IybZUv+y/4eSO/LDYIi
# r2VQF6oTtkmcIxUqAI6ZAehzZUIrB22QItUN8rg0slKBM8e/xHYaEBY8APKCLcvE
# h59DLq1rPZG3Aie/h3/RjTfT2kI83PiE1mDGbhKf9G8UfXHEH8Eabd0g66UWfzlK
# 67o7bwwzwXgoGk2hgMY/yobB3pF5YCly/a3aN/aLEj387y8sNaT1ASR9LETj7TC3
# xOhn5f8G6OFKMVI3K8Sco8ILP15LELprAW2keL4jn+4y3Hfq5yC984yOSnlM0wug
# wWRvEr7U1ZiEbDaOvoa0beuYpeq1sm4OZ5yGJxGy3IuQ8pZpkHVTrBxw/NCNQnos
# fK5czVTGqvvmPXgPsQQm1A==
# =vYTy
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 26 Jan 2024 14:32:59 GMT
# gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg: issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# gpg: aka "Peter Maydell <peter@archaic.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE
* tag 'pull-target-arm-20240126' of https://git.linaro.org/people/pmaydell/qemu-arm: (36 commits)
hw/arm: add PCIe to Freescale i.MX6
target/arm: Fix incorrect aa64_tidcp1 feature check
bswap.h: Fix const_le64() macro
target/arm: Fix A64 scalar SQSHRN and SQRSHRN
hw/char/imx_serial: Implement receive FIFO and ageing timer
docs/system/arm/virt.rst: Add note on CPU features off by default
fsl-imx6ul: Add various missing unimplemented devices
hw/arm: Build various units only once
target/arm: Move GTimer definitions to new 'gtimer.h' header
target/arm: Move e2h_access() helper around
target/arm: Move ARM_CPU_IRQ/FIQ definitions to 'cpu-qom.h' header
hw/arm/armv7m: Make 'hw/intc/armv7m_nvic.h' a target agnostic header
target/arm: Expose M-profile register bank index definitions
hw/misc/xlnx-versal-crl: Build it only once
hw/misc/xlnx-versal-crl: Include generic 'cpu-qom.h' instead of 'cpu.h'
hw/cpu/a9mpcore: Build it only once
target/arm: Declare ARM_CPU_TYPE_NAME/SUFFIX in 'cpu-qom.h'
target/arm: Expose arm_cpu_mp_affinity() in 'multiprocessing.h' header
target/arm: Create arm_cpu_mp_affinity
target/arm: Rename arm_cpu_mp_affinity
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/block.c b/block.c
index a097772..30afdcb 100644
--- a/block.c
+++ b/block.c
@@ -1309,11 +1309,14 @@
}
static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
- const char *filename, Error **errp)
+ const char *filename,
+ bool backing_mask_protocol,
+ Error **errp)
{
BlockDriverState *parent = c->opaque;
bool read_only = bdrv_is_read_only(parent);
int ret;
+ const char *format_name;
GLOBAL_STATE_CODE();
if (read_only) {
@@ -1323,9 +1326,23 @@
}
}
- ret = bdrv_change_backing_file(parent, filename,
- base->drv ? base->drv->format_name : "",
- false);
+ if (base->drv) {
+ /*
+ * If the new base image doesn't have a format driver layer, which we
+ * detect by the fact that @base is a protocol driver, we record
+ * 'raw' as the format instead of putting the protocol name as the
+ * backing format
+ */
+ if (backing_mask_protocol && base->drv->protocol_name) {
+ format_name = "raw";
+ } else {
+ format_name = base->drv->format_name;
+ }
+ } else {
+ format_name = "";
+ }
+
+ ret = bdrv_change_backing_file(parent, filename, format_name, false);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not update backing file link");
}
@@ -1479,10 +1496,14 @@
}
static int bdrv_child_cb_update_filename(BdrvChild *c, BlockDriverState *base,
- const char *filename, Error **errp)
+ const char *filename,
+ bool backing_mask_protocol,
+ Error **errp)
{
if (c->role & BDRV_CHILD_COW) {
- return bdrv_backing_update_filename(c, base, filename, errp);
+ return bdrv_backing_update_filename(c, base, filename,
+ backing_mask_protocol,
+ errp);
}
return 0;
}
@@ -5803,7 +5824,8 @@
*
*/
int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
- const char *backing_file_str)
+ const char *backing_file_str,
+ bool backing_mask_protocol)
{
BlockDriverState *explicit_top = top;
bool update_inherits_from;
@@ -5869,6 +5891,7 @@
if (c->klass->update_filename) {
ret = c->klass->update_filename(c, base, backing_file_str,
+ backing_mask_protocol,
&local_err);
if (ret < 0) {
/*
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
index 7207b2e..ed38a93 100644
--- a/block/blklogwrites.c
+++ b/block/blklogwrites.c
@@ -3,7 +3,7 @@
*
* Copyright (c) 2017 Tuomas Tynkkynen <tuomas@tuxera.com>
* Copyright (c) 2018 Aapo Vienamo <aapo@tuxera.com>
- * Copyright (c) 2018 Ari Sundholm <ari@tuxera.com>
+ * Copyright (c) 2018-2024 Ari Sundholm <ari@tuxera.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
@@ -55,9 +55,34 @@
BdrvChild *log_file;
uint32_t sectorsize;
uint32_t sectorbits;
+ uint64_t update_interval;
+
+ /*
+ * The mutable state of the driver, consisting of the current log sector
+ * and the number of log entries.
+ *
+ * May be read and/or written from multiple threads, and the mutex must be
+ * held when accessing these fields.
+ */
uint64_t cur_log_sector;
uint64_t nr_entries;
- uint64_t update_interval;
+ QemuMutex mutex;
+
+ /*
+ * The super block sequence number. Non-zero if a super block update is in
+ * progress.
+ *
+ * The mutex must be held when accessing this field.
+ */
+ uint64_t super_update_seq;
+
+ /*
+ * A coroutine-aware queue to serialize super block updates.
+ *
+ * Used with the mutex to ensure that only one thread be updating the super
+ * block at a time.
+ */
+ CoQueue super_update_queue;
} BDRVBlkLogWritesState;
static QemuOptsList runtime_opts = {
@@ -169,6 +194,9 @@
goto fail;
}
+ qemu_mutex_init(&s->mutex);
+ qemu_co_queue_init(&s->super_update_queue);
+
log_append = qemu_opt_get_bool(opts, "log-append", false);
if (log_append) {
@@ -231,6 +259,8 @@
s->nr_entries = 0;
}
+ s->super_update_seq = 0;
+
if (!blk_log_writes_sector_size_valid(log_sector_size)) {
ret = -EINVAL;
error_setg(errp, "Invalid log sector size %"PRIu64, log_sector_size);
@@ -255,6 +285,7 @@
bdrv_unref_child(bs, s->log_file);
bdrv_graph_wrunlock();
s->log_file = NULL;
+ qemu_mutex_destroy(&s->mutex);
}
fail:
qemu_opts_del(opts);
@@ -269,6 +300,7 @@
bdrv_unref_child(bs, s->log_file);
s->log_file = NULL;
bdrv_graph_wrunlock();
+ qemu_mutex_destroy(&s->mutex);
}
static int64_t coroutine_fn GRAPH_RDLOCK
@@ -295,7 +327,7 @@
static void blk_log_writes_refresh_limits(BlockDriverState *bs, Error **errp)
{
- BDRVBlkLogWritesState *s = bs->opaque;
+ const BDRVBlkLogWritesState *s = bs->opaque;
bs->bl.request_alignment = s->sectorsize;
}
@@ -328,38 +360,85 @@
blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
{
BDRVBlkLogWritesState *s = lr->bs->opaque;
- uint64_t cur_log_offset = s->cur_log_sector << s->sectorbits;
- s->nr_entries++;
- s->cur_log_sector +=
- ROUND_UP(lr->qiov->size, s->sectorsize) >> s->sectorbits;
+ /*
+ * Determine the offsets and sizes of different parts of the entry, and
+ * update the state of the driver.
+ *
+ * This needs to be done in one go, before any actual I/O is done, as the
+ * log entry may have to be written in two parts, and the state of the
+ * driver may be modified by other driver operations while waiting for the
+ * I/O to complete.
+ */
+ qemu_mutex_lock(&s->mutex);
+ const uint64_t entry_start_sector = s->cur_log_sector;
+ const uint64_t entry_offset = entry_start_sector << s->sectorbits;
+ const uint64_t qiov_aligned_size = ROUND_UP(lr->qiov->size, s->sectorsize);
+ const uint64_t entry_aligned_size = qiov_aligned_size +
+ ROUND_UP(lr->zero_size, s->sectorsize);
+ const uint64_t entry_nr_sectors = entry_aligned_size >> s->sectorbits;
+ const uint64_t entry_seq = s->nr_entries + 1;
- lr->log_ret = bdrv_co_pwritev(s->log_file, cur_log_offset, lr->qiov->size,
+ s->nr_entries = entry_seq;
+ s->cur_log_sector += entry_nr_sectors;
+ qemu_mutex_unlock(&s->mutex);
+
+ /*
+ * Write the log entry. Note that if this is a "write zeroes" operation,
+ * only the entry header is written here, with the zeroing being done
+ * separately below.
+ */
+ lr->log_ret = bdrv_co_pwritev(s->log_file, entry_offset, lr->qiov->size,
lr->qiov, 0);
/* Logging for the "write zeroes" operation */
if (lr->log_ret == 0 && lr->zero_size) {
- cur_log_offset = s->cur_log_sector << s->sectorbits;
- s->cur_log_sector +=
- ROUND_UP(lr->zero_size, s->sectorsize) >> s->sectorbits;
+ const uint64_t zeroes_offset = entry_offset + qiov_aligned_size;
- lr->log_ret = bdrv_co_pwrite_zeroes(s->log_file, cur_log_offset,
+ lr->log_ret = bdrv_co_pwrite_zeroes(s->log_file, zeroes_offset,
lr->zero_size, 0);
}
/* Update super block on flush or every update interval */
if (lr->log_ret == 0 && ((lr->entry.flags & LOG_FLUSH_FLAG)
- || (s->nr_entries % s->update_interval == 0)))
+ || (entry_seq % s->update_interval == 0)))
{
struct log_write_super super = {
.magic = cpu_to_le64(WRITE_LOG_MAGIC),
.version = cpu_to_le64(WRITE_LOG_VERSION),
- .nr_entries = cpu_to_le64(s->nr_entries),
+ .nr_entries = 0, /* updated below */
.sectorsize = cpu_to_le32(s->sectorsize),
};
- void *zeroes = g_malloc0(s->sectorsize - sizeof(super));
+ void *zeroes;
QEMUIOVector qiov;
+ /*
+ * Wait if a super block update is already in progress.
+ * Bail out if a newer update got its turn before us.
+ */
+ WITH_QEMU_LOCK_GUARD(&s->mutex) {
+ CoQueueWaitFlags wait_flags = 0;
+ while (s->super_update_seq) {
+ if (entry_seq < s->super_update_seq) {
+ return;
+ }
+ qemu_co_queue_wait_flags(&s->super_update_queue,
+ &s->mutex, wait_flags);
+
+ /*
+ * In case the wait condition remains true after wakeup,
+ * to avoid starvation, make sure that this request is
+ * scheduled to rerun next by pushing it to the front of the
+ * queue.
+ */
+ wait_flags = CO_QUEUE_WAIT_FRONT;
+ }
+ s->super_update_seq = entry_seq;
+ super.nr_entries = cpu_to_le64(s->nr_entries);
+ }
+
+ zeroes = g_malloc0(s->sectorsize - sizeof(super));
+
qemu_iovec_init(&qiov, 2);
qemu_iovec_add(&qiov, &super, sizeof(super));
qemu_iovec_add(&qiov, zeroes, s->sectorsize - sizeof(super));
@@ -369,6 +448,13 @@
if (lr->log_ret == 0) {
lr->log_ret = bdrv_co_flush(s->log_file->bs);
}
+
+ /* The super block has been updated. Let another request have a go. */
+ qemu_mutex_lock(&s->mutex);
+ s->super_update_seq = 0;
+ (void) qemu_co_queue_next(&s->super_update_queue);
+ qemu_mutex_unlock(&s->mutex);
+
qemu_iovec_destroy(&qiov);
g_free(zeroes);
}
@@ -388,7 +474,7 @@
{
QEMUIOVector log_qiov;
size_t niov = qiov ? qiov->niov : 0;
- BDRVBlkLogWritesState *s = bs->opaque;
+ const BDRVBlkLogWritesState *s = bs->opaque;
BlkLogWritesFileReq fr = {
.bs = bs,
.offset = offset,
diff --git a/block/commit.c b/block/commit.c
index 1dd7a65..7c3fdcb 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -42,6 +42,7 @@
bool base_read_only;
bool chain_frozen;
char *backing_file_str;
+ bool backing_mask_protocol;
} CommitBlockJob;
static int commit_prepare(Job *job)
@@ -61,7 +62,8 @@
/* FIXME: bdrv_drop_intermediate treats total failures and partial failures
* identically. Further work is needed to disambiguate these cases. */
return bdrv_drop_intermediate(s->commit_top_bs, s->base_bs,
- s->backing_file_str);
+ s->backing_file_str,
+ s->backing_mask_protocol);
}
static void commit_abort(Job *job)
@@ -254,6 +256,7 @@
BlockDriverState *base, BlockDriverState *top,
int creation_flags, int64_t speed,
BlockdevOnError on_error, const char *backing_file_str,
+ bool backing_mask_protocol,
const char *filter_node_name, Error **errp)
{
CommitBlockJob *s;
@@ -408,6 +411,7 @@
blk_set_disable_request_queuing(s->top, true);
s->backing_file_str = g_strdup(backing_file_str);
+ s->backing_mask_protocol = backing_mask_protocol;
s->on_error = on_error;
trace_commit_start(bs, base, top, s);
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index bdbb5cb..d954bec 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -496,7 +496,7 @@
const char *base = qdict_get_try_str(qdict, "base");
int64_t speed = qdict_get_try_int(qdict, "speed", 0);
- qmp_block_stream(device, device, base, NULL, NULL, NULL,
+ qmp_block_stream(device, device, base, NULL, NULL, false, false, NULL,
qdict_haskey(qdict, "speed"), speed,
true, BLOCKDEV_ON_ERROR_REPORT, NULL,
false, false, false, false, &error);
diff --git a/block/stream.c b/block/stream.c
index 048c2d2..7031eef 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -39,6 +39,7 @@
BlockDriverState *target_bs;
BlockdevOnError on_error;
char *backing_file_str;
+ bool backing_mask_protocol;
bool bs_read_only;
} StreamBlockJob;
@@ -95,7 +96,12 @@
if (unfiltered_base) {
base_id = s->backing_file_str ?: unfiltered_base->filename;
if (unfiltered_base->drv) {
- base_fmt = unfiltered_base->drv->format_name;
+ if (s->backing_mask_protocol &&
+ unfiltered_base->drv->protocol_name) {
+ base_fmt = "raw";
+ } else {
+ base_fmt = unfiltered_base->drv->format_name;
+ }
}
}
@@ -247,6 +253,7 @@
void stream_start(const char *job_id, BlockDriverState *bs,
BlockDriverState *base, const char *backing_file_str,
+ bool backing_mask_protocol,
BlockDriverState *bottom,
int creation_flags, int64_t speed,
BlockdevOnError on_error,
@@ -398,6 +405,7 @@
s->base_overlay = base_overlay;
s->above_base = above_base;
s->backing_file_str = g_strdup(backing_file_str);
+ s->backing_mask_protocol = backing_mask_protocol;
s->cor_filter_bs = cor_filter_bs;
s->target_bs = bs;
s->bs_read_only = bs_read_only;
diff --git a/blockdev.c b/blockdev.c
index 3a5e722..f8bb093 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2278,6 +2278,8 @@
const char *base,
const char *base_node,
const char *backing_file,
+ bool has_backing_mask_protocol,
+ bool backing_mask_protocol,
const char *bottom,
bool has_speed, int64_t speed,
bool has_on_error, BlockdevOnError on_error,
@@ -2313,6 +2315,10 @@
return;
}
+ if (!has_backing_mask_protocol) {
+ backing_mask_protocol = false;
+ }
+
if (!has_on_error) {
on_error = BLOCKDEV_ON_ERROR_REPORT;
}
@@ -2400,6 +2406,7 @@
}
stream_start(job_id, bs, base_bs, backing_file,
+ backing_mask_protocol,
bottom_bs, job_flags, has_speed ? speed : 0, on_error,
filter_node_name, &local_err);
if (local_err) {
@@ -2420,6 +2427,8 @@
const char *top_node,
const char *top,
const char *backing_file,
+ bool has_backing_mask_protocol,
+ bool backing_mask_protocol,
bool has_speed, int64_t speed,
bool has_on_error, BlockdevOnError on_error,
const char *filter_node_name,
@@ -2450,6 +2459,9 @@
if (has_auto_dismiss && !auto_dismiss) {
job_flags |= JOB_MANUAL_DISMISS;
}
+ if (!has_backing_mask_protocol) {
+ backing_mask_protocol = false;
+ }
/* Important Note:
* libvirt relies on the DeviceNotFound error class in order to probe for
@@ -2591,6 +2603,7 @@
}
commit_start(job_id, bs, base_bs, top_bs, job_flags,
speed, on_error, backing_file,
+ backing_mask_protocol,
filter_node_name, &local_err);
}
if (local_err != NULL) {
diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst
index ea82285..76be722 100644
--- a/docs/devel/qapi-code-gen.rst
+++ b/docs/devel/qapi-code-gen.rst
@@ -737,9 +737,8 @@
generally speaking, type definitions should always use CamelCase for
user-defined type names, while built-in types are lowercase.
-Type names ending with ``Kind`` or ``List`` are reserved for the
-generator, which uses them for implicit union enums and array types,
-respectively.
+Type names ending with ``List`` are reserved for the generator, which
+uses them for array types.
Command names, member names within a type, and feature names should be
all lower case with words separated by a hyphen. However, some
@@ -990,8 +989,8 @@
# @feature: Description text
A tagged section starts with one of the following words:
-"Note:"/"Notes:", "Since:", "Example"/"Examples", "Returns:", "TODO:".
-The section ends with the start of a new section.
+"Note:"/"Notes:", "Since:", "Example:"/"Examples:", "Returns:",
+"TODO:". The section ends with the start of a new section.
The second and subsequent lines of sections other than
"Example"/"Examples" should be indented like this::
diff --git a/docs/devel/writing-monitor-commands.rst b/docs/devel/writing-monitor-commands.rst
index 2c11e71..b6ee4fa 100644
--- a/docs/devel/writing-monitor-commands.rst
+++ b/docs/devel/writing-monitor-commands.rst
@@ -8,8 +8,8 @@
into the QAPI framework implementation.
For an in-depth introduction to the QAPI framework, please refer to
-docs/devel/qapi-code-gen.txt. For documentation about the QMP protocol,
-start with docs/interop/qmp-intro.txt.
+:doc:`qapi-code-gen`. For the QMP protocol, see the
+:doc:`/interop/qmp-spec`.
New commands may be implemented in QMP only. New HMP commands should be
implemented on top of QMP. The typical HMP command wraps around an
diff --git a/docs/interop/bitmaps.rst b/docs/interop/bitmaps.rst
index 1de46fe..ddf8947 100644
--- a/docs/interop/bitmaps.rst
+++ b/docs/interop/bitmaps.rst
@@ -166,9 +166,9 @@
---------------
The primary interface to manipulating bitmap objects is via the QMP
-interface. If you are not familiar, see docs/interop/qmp-intro.txt for a broad
-overview, and `qemu-qmp-ref <qemu-qmp-ref.html>`_ for a full reference of all
-QMP commands.
+interface. If you are not familiar, see the :doc:`qmp-spec` for the
+protocol, and :doc:`qemu-qmp-ref` for a full reference of all QMP
+commands.
Supported Commands
~~~~~~~~~~~~~~~~~~
diff --git a/hw/block/dataplane/meson.build b/hw/block/dataplane/meson.build
index 025b3b0..11a5eba 100644
--- a/hw/block/dataplane/meson.build
+++ b/hw/block/dataplane/meson.build
@@ -1,2 +1 @@
-system_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c'))
specific_ss.add(when: 'CONFIG_XEN_BUS', if_true: files('xen-block.c'))
diff --git a/hw/block/dataplane/trace-events b/hw/block/dataplane/trace-events
deleted file mode 100644
index 38fc3e7..0000000
--- a/hw/block/dataplane/trace-events
+++ /dev/null
@@ -1,5 +0,0 @@
-# See docs/devel/tracing.rst for syntax documentation.
-
-# virtio-blk.c
-virtio_blk_data_plane_start(void *s) "dataplane %p"
-virtio_blk_data_plane_stop(void *s) "dataplane %p"
diff --git a/hw/block/dataplane/trace.h b/hw/block/dataplane/trace.h
deleted file mode 100644
index 240cc59..0000000
--- a/hw/block/dataplane/trace.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "trace/trace-hw_block_dataplane.h"
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
deleted file mode 100644
index ba22732..0000000
--- a/hw/block/dataplane/virtio-blk.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Dedicated thread for virtio-blk I/O processing
- *
- * Copyright 2012 IBM, Corp.
- * Copyright 2012 Red Hat, Inc. and/or its affiliates
- *
- * Authors:
- * Stefan Hajnoczi <stefanha@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "trace.h"
-#include "qemu/iov.h"
-#include "qemu/main-loop.h"
-#include "qemu/thread.h"
-#include "qemu/error-report.h"
-#include "hw/virtio/virtio-blk.h"
-#include "virtio-blk.h"
-#include "block/aio.h"
-#include "hw/virtio/virtio-bus.h"
-#include "qom/object_interfaces.h"
-
-struct VirtIOBlockDataPlane {
- bool starting;
- bool stopping;
-
- VirtIOBlkConf *conf;
- VirtIODevice *vdev;
-
- /*
- * The AioContext for each virtqueue. The BlockDriverState will use the
- * first element as its AioContext.
- */
- AioContext **vq_aio_context;
-};
-
-/* Raise an interrupt to signal guest, if necessary */
-void virtio_blk_data_plane_notify(VirtIOBlockDataPlane *s, VirtQueue *vq)
-{
- virtio_notify_irqfd(s->vdev, vq);
-}
-
-/* Generate vq:AioContext mappings from a validated iothread-vq-mapping list */
-static void
-apply_vq_mapping(IOThreadVirtQueueMappingList *iothread_vq_mapping_list,
- AioContext **vq_aio_context, uint16_t num_queues)
-{
- IOThreadVirtQueueMappingList *node;
- size_t num_iothreads = 0;
- size_t cur_iothread = 0;
-
- for (node = iothread_vq_mapping_list; node; node = node->next) {
- num_iothreads++;
- }
-
- for (node = iothread_vq_mapping_list; node; node = node->next) {
- IOThread *iothread = iothread_by_id(node->value->iothread);
- AioContext *ctx = iothread_get_aio_context(iothread);
-
- /* Released in virtio_blk_data_plane_destroy() */
- object_ref(OBJECT(iothread));
-
- if (node->value->vqs) {
- uint16List *vq;
-
- /* Explicit vq:IOThread assignment */
- for (vq = node->value->vqs; vq; vq = vq->next) {
- vq_aio_context[vq->value] = ctx;
- }
- } else {
- /* Round-robin vq:IOThread assignment */
- for (unsigned i = cur_iothread; i < num_queues;
- i += num_iothreads) {
- vq_aio_context[i] = ctx;
- }
- }
-
- cur_iothread++;
- }
-}
-
-/* Context: BQL held */
-bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
- VirtIOBlockDataPlane **dataplane,
- Error **errp)
-{
- VirtIOBlockDataPlane *s;
- BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
- VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-
- *dataplane = NULL;
-
- if (conf->iothread || conf->iothread_vq_mapping_list) {
- if (!k->set_guest_notifiers || !k->ioeventfd_assign) {
- error_setg(errp,
- "device is incompatible with iothread "
- "(transport does not support notifiers)");
- return false;
- }
- if (!virtio_device_ioeventfd_enabled(vdev)) {
- error_setg(errp, "ioeventfd is required for iothread");
- return false;
- }
-
- /* If dataplane is (re-)enabled while the guest is running there could
- * be block jobs that can conflict.
- */
- if (blk_op_is_blocked(conf->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
- error_prepend(errp, "cannot start virtio-blk dataplane: ");
- return false;
- }
- }
- /* Don't try if transport does not support notifiers. */
- if (!virtio_device_ioeventfd_enabled(vdev)) {
- return false;
- }
-
- s = g_new0(VirtIOBlockDataPlane, 1);
- s->vdev = vdev;
- s->conf = conf;
- s->vq_aio_context = g_new(AioContext *, conf->num_queues);
-
- if (conf->iothread_vq_mapping_list) {
- apply_vq_mapping(conf->iothread_vq_mapping_list, s->vq_aio_context,
- conf->num_queues);
- } else if (conf->iothread) {
- AioContext *ctx = iothread_get_aio_context(conf->iothread);
- for (unsigned i = 0; i < conf->num_queues; i++) {
- s->vq_aio_context[i] = ctx;
- }
-
- /* Released in virtio_blk_data_plane_destroy() */
- object_ref(OBJECT(conf->iothread));
- } else {
- AioContext *ctx = qemu_get_aio_context();
- for (unsigned i = 0; i < conf->num_queues; i++) {
- s->vq_aio_context[i] = ctx;
- }
- }
-
- *dataplane = s;
-
- return true;
-}
-
-/* Context: BQL held */
-void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
-{
- VirtIOBlock *vblk;
- VirtIOBlkConf *conf;
-
- if (!s) {
- return;
- }
-
- vblk = VIRTIO_BLK(s->vdev);
- assert(!vblk->dataplane_started);
- conf = s->conf;
-
- if (conf->iothread_vq_mapping_list) {
- IOThreadVirtQueueMappingList *node;
-
- for (node = conf->iothread_vq_mapping_list; node; node = node->next) {
- IOThread *iothread = iothread_by_id(node->value->iothread);
- object_unref(OBJECT(iothread));
- }
- }
-
- if (conf->iothread) {
- object_unref(OBJECT(conf->iothread));
- }
-
- g_free(s->vq_aio_context);
- g_free(s);
-}
-
-/* Context: BQL held */
-int virtio_blk_data_plane_start(VirtIODevice *vdev)
-{
- VirtIOBlock *vblk = VIRTIO_BLK(vdev);
- VirtIOBlockDataPlane *s = vblk->dataplane;
- BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vblk)));
- VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
- unsigned i;
- unsigned nvqs = s->conf->num_queues;
- Error *local_err = NULL;
- int r;
-
- if (vblk->dataplane_started || s->starting) {
- return 0;
- }
-
- s->starting = true;
-
- /* Set up guest notifier (irq) */
- r = k->set_guest_notifiers(qbus->parent, nvqs, true);
- if (r != 0) {
- error_report("virtio-blk failed to set guest notifier (%d), "
- "ensure -accel kvm is set.", r);
- goto fail_guest_notifiers;
- }
-
- /*
- * Batch all the host notifiers in a single transaction to avoid
- * quadratic time complexity in address_space_update_ioeventfds().
- */
- memory_region_transaction_begin();
-
- /* Set up virtqueue notify */
- for (i = 0; i < nvqs; i++) {
- r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, true);
- if (r != 0) {
- int j = i;
-
- fprintf(stderr, "virtio-blk failed to set host notifier (%d)\n", r);
- while (i--) {
- virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
- }
-
- /*
- * The transaction expects the ioeventfds to be open when it
- * commits. Do it now, before the cleanup loop.
- */
- memory_region_transaction_commit();
-
- while (j--) {
- virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), j);
- }
- goto fail_host_notifiers;
- }
- }
-
- memory_region_transaction_commit();
-
- trace_virtio_blk_data_plane_start(s);
-
- r = blk_set_aio_context(s->conf->conf.blk, s->vq_aio_context[0],
- &local_err);
- if (r < 0) {
- error_report_err(local_err);
- goto fail_aio_context;
- }
-
- /*
- * These fields must be visible to the IOThread when it processes the
- * virtqueue, otherwise it will think dataplane has not started yet.
- *
- * Make sure ->dataplane_started is false when blk_set_aio_context() is
- * called above so that draining does not cause the host notifier to be
- * detached/attached prematurely.
- */
- s->starting = false;
- vblk->dataplane_started = true;
- smp_wmb(); /* paired with aio_notify_accept() on the read side */
-
- /* Get this show started by hooking up our callbacks */
- if (!blk_in_drain(s->conf->conf.blk)) {
- for (i = 0; i < nvqs; i++) {
- VirtQueue *vq = virtio_get_queue(s->vdev, i);
- AioContext *ctx = s->vq_aio_context[i];
-
- /* Kick right away to begin processing requests already in vring */
- event_notifier_set(virtio_queue_get_host_notifier(vq));
-
- virtio_queue_aio_attach_host_notifier(vq, ctx);
- }
- }
- return 0;
-
- fail_aio_context:
- memory_region_transaction_begin();
-
- for (i = 0; i < nvqs; i++) {
- virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
- }
-
- memory_region_transaction_commit();
-
- for (i = 0; i < nvqs; i++) {
- virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
- }
- fail_host_notifiers:
- k->set_guest_notifiers(qbus->parent, nvqs, false);
- fail_guest_notifiers:
- vblk->dataplane_disabled = true;
- s->starting = false;
- return -ENOSYS;
-}
-
-/* Stop notifications for new requests from guest.
- *
- * Context: BH in IOThread
- */
-static void virtio_blk_data_plane_stop_vq_bh(void *opaque)
-{
- VirtQueue *vq = opaque;
- EventNotifier *host_notifier = virtio_queue_get_host_notifier(vq);
-
- virtio_queue_aio_detach_host_notifier(vq, qemu_get_current_aio_context());
-
- /*
- * Test and clear notifier after disabling event, in case poll callback
- * didn't have time to run.
- */
- virtio_queue_host_notifier_read(host_notifier);
-}
-
-/* Context: BQL held */
-void virtio_blk_data_plane_stop(VirtIODevice *vdev)
-{
- VirtIOBlock *vblk = VIRTIO_BLK(vdev);
- VirtIOBlockDataPlane *s = vblk->dataplane;
- BusState *qbus = qdev_get_parent_bus(DEVICE(vblk));
- VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
- unsigned i;
- unsigned nvqs = s->conf->num_queues;
-
- if (!vblk->dataplane_started || s->stopping) {
- return;
- }
-
- /* Better luck next time. */
- if (vblk->dataplane_disabled) {
- vblk->dataplane_disabled = false;
- vblk->dataplane_started = false;
- return;
- }
- s->stopping = true;
- trace_virtio_blk_data_plane_stop(s);
-
- if (!blk_in_drain(s->conf->conf.blk)) {
- for (i = 0; i < nvqs; i++) {
- VirtQueue *vq = virtio_get_queue(s->vdev, i);
- AioContext *ctx = s->vq_aio_context[i];
-
- aio_wait_bh_oneshot(ctx, virtio_blk_data_plane_stop_vq_bh, vq);
- }
- }
-
- /*
- * Batch all the host notifiers in a single transaction to avoid
- * quadratic time complexity in address_space_update_ioeventfds().
- */
- memory_region_transaction_begin();
-
- for (i = 0; i < nvqs; i++) {
- virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
- }
-
- /*
- * The transaction expects the ioeventfds to be open when it
- * commits. Do it now, before the cleanup loop.
- */
- memory_region_transaction_commit();
-
- for (i = 0; i < nvqs; i++) {
- virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
- }
-
- /*
- * Set ->dataplane_started to false before draining so that host notifiers
- * are not detached/attached anymore.
- */
- vblk->dataplane_started = false;
-
- /* Wait for virtio_blk_dma_restart_bh() and in flight I/O to complete */
- blk_drain(s->conf->conf.blk);
-
- /*
- * Try to switch bs back to the QEMU main loop. If other users keep the
- * BlockBackend in the iothread, that's ok
- */
- blk_set_aio_context(s->conf->conf.blk, qemu_get_aio_context(), NULL);
-
- /* Clean up guest notifier (irq) */
- k->set_guest_notifiers(qbus->parent, nvqs, false);
-
- s->stopping = false;
-}
-
-void virtio_blk_data_plane_detach(VirtIOBlockDataPlane *s)
-{
- VirtIODevice *vdev = VIRTIO_DEVICE(s->vdev);
-
- for (uint16_t i = 0; i < s->conf->num_queues; i++) {
- VirtQueue *vq = virtio_get_queue(vdev, i);
- virtio_queue_aio_detach_host_notifier(vq, s->vq_aio_context[i]);
- }
-}
-
-void virtio_blk_data_plane_attach(VirtIOBlockDataPlane *s)
-{
- VirtIODevice *vdev = VIRTIO_DEVICE(s->vdev);
-
- for (uint16_t i = 0; i < s->conf->num_queues; i++) {
- VirtQueue *vq = virtio_get_queue(vdev, i);
- virtio_queue_aio_attach_host_notifier(vq, s->vq_aio_context[i]);
- }
-}
diff --git a/hw/block/dataplane/virtio-blk.h b/hw/block/dataplane/virtio-blk.h
deleted file mode 100644
index 1a806fe..0000000
--- a/hw/block/dataplane/virtio-blk.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Dedicated thread for virtio-blk I/O processing
- *
- * Copyright 2012 IBM, Corp.
- * Copyright 2012 Red Hat, Inc. and/or its affiliates
- *
- * Authors:
- * Stefan Hajnoczi <stefanha@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#ifndef HW_DATAPLANE_VIRTIO_BLK_H
-#define HW_DATAPLANE_VIRTIO_BLK_H
-
-#include "hw/virtio/virtio.h"
-
-typedef struct VirtIOBlockDataPlane VirtIOBlockDataPlane;
-
-bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
- VirtIOBlockDataPlane **dataplane,
- Error **errp);
-void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s);
-void virtio_blk_data_plane_notify(VirtIOBlockDataPlane *s, VirtQueue *vq);
-
-int virtio_blk_data_plane_start(VirtIODevice *vdev);
-void virtio_blk_data_plane_stop(VirtIODevice *vdev);
-
-void virtio_blk_data_plane_detach(VirtIOBlockDataPlane *s);
-void virtio_blk_data_plane_attach(VirtIOBlockDataPlane *s);
-
-#endif /* HW_DATAPLANE_VIRTIO_BLK_H */
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index b7a344c..227d835 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -27,7 +27,6 @@
#include "sysemu/sysemu.h"
#include "sysemu/runstate.h"
#include "hw/virtio/virtio-blk.h"
-#include "dataplane/virtio-blk.h"
#include "scsi/constants.h"
#ifdef __linux__
# include <scsi/sg.h>
@@ -65,8 +64,8 @@
iov_discard_undo(&req->inhdr_undo);
iov_discard_undo(&req->outhdr_undo);
virtqueue_push(req->vq, &req->elem, req->in_len);
- if (s->dataplane_started && !s->dataplane_disabled) {
- virtio_blk_data_plane_notify(s->dataplane, req->vq);
+ if (s->ioeventfd_started && !s->ioeventfd_disabled) {
+ virtio_notify_irqfd(vdev, req->vq);
} else {
virtio_notify(vdev, req->vq);
}
@@ -1142,12 +1141,12 @@
{
VirtIOBlock *s = (VirtIOBlock *)vdev;
- if (s->dataplane && !s->dataplane_started) {
+ if (!s->ioeventfd_disabled && !s->ioeventfd_started) {
/* Some guests kick before setting VIRTIO_CONFIG_S_DRIVER_OK so start
- * dataplane here instead of waiting for .set_status().
+ * ioeventfd here instead of waiting for .set_status().
*/
virtio_device_start_ioeventfd(vdev);
- if (!s->dataplane_disabled) {
+ if (!s->ioeventfd_disabled) {
return;
}
}
@@ -1157,16 +1156,11 @@
static void virtio_blk_dma_restart_bh(void *opaque)
{
- VirtIOBlock *s = opaque;
+ VirtIOBlockReq *req = opaque;
+ VirtIOBlock *s = req->dev; /* we're called with at least one request */
- VirtIOBlockReq *req;
MultiReqBuffer mrb = {};
- WITH_QEMU_LOCK_GUARD(&s->rq_lock) {
- req = s->rq;
- s->rq = NULL;
- }
-
while (req) {
VirtIOBlockReq *next = req->next;
if (virtio_blk_handle_request(req, &mrb)) {
@@ -1196,16 +1190,43 @@
RunState state)
{
VirtIOBlock *s = opaque;
+ uint16_t num_queues = s->conf.num_queues;
if (!running) {
return;
}
- /* Paired with dec in virtio_blk_dma_restart_bh() */
- blk_inc_in_flight(s->conf.conf.blk);
+ /* Split the device-wide s->rq request list into per-vq request lists */
+ g_autofree VirtIOBlockReq **vq_rq = g_new0(VirtIOBlockReq *, num_queues);
+ VirtIOBlockReq *rq;
- aio_bh_schedule_oneshot(blk_get_aio_context(s->conf.conf.blk),
- virtio_blk_dma_restart_bh, s);
+ WITH_QEMU_LOCK_GUARD(&s->rq_lock) {
+ rq = s->rq;
+ s->rq = NULL;
+ }
+
+ while (rq) {
+ VirtIOBlockReq *next = rq->next;
+ uint16_t idx = virtio_get_queue_index(rq->vq);
+
+ rq->next = vq_rq[idx];
+ vq_rq[idx] = rq;
+ rq = next;
+ }
+
+ /* Schedule a BH to submit the requests in each vq's AioContext */
+ for (uint16_t i = 0; i < num_queues; i++) {
+ if (!vq_rq[i]) {
+ continue;
+ }
+
+ /* Paired with dec in virtio_blk_dma_restart_bh() */
+ blk_inc_in_flight(s->conf.conf.blk);
+
+ aio_bh_schedule_oneshot(s->vq_aio_context[i],
+ virtio_blk_dma_restart_bh,
+ vq_rq[i]);
+ }
}
static void virtio_blk_reset(VirtIODevice *vdev)
@@ -1214,7 +1235,7 @@
VirtIOBlockReq *req;
/* Dataplane has stopped... */
- assert(!s->dataplane_started);
+ assert(!s->ioeventfd_started);
/* ...but requests may still be in flight. */
blk_drain(s->blk);
@@ -1381,7 +1402,7 @@
VirtIOBlock *s = VIRTIO_BLK(vdev);
if (!(status & (VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK))) {
- assert(!s->dataplane_started);
+ assert(!s->ioeventfd_started);
}
if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
@@ -1546,16 +1567,34 @@
aio_bh_schedule_oneshot(qemu_get_aio_context(), virtio_resize_cb, vdev);
}
+static void virtio_blk_ioeventfd_detach(VirtIOBlock *s)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
+
+ for (uint16_t i = 0; i < s->conf.num_queues; i++) {
+ VirtQueue *vq = virtio_get_queue(vdev, i);
+ virtio_queue_aio_detach_host_notifier(vq, s->vq_aio_context[i]);
+ }
+}
+
+static void virtio_blk_ioeventfd_attach(VirtIOBlock *s)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
+
+ for (uint16_t i = 0; i < s->conf.num_queues; i++) {
+ VirtQueue *vq = virtio_get_queue(vdev, i);
+ virtio_queue_aio_attach_host_notifier(vq, s->vq_aio_context[i]);
+ }
+}
+
/* Suspend virtqueue ioeventfd processing during drain */
static void virtio_blk_drained_begin(void *opaque)
{
VirtIOBlock *s = opaque;
- if (!s->dataplane || !s->dataplane_started) {
- return;
+ if (s->ioeventfd_started) {
+ virtio_blk_ioeventfd_detach(s);
}
-
- virtio_blk_data_plane_detach(s->dataplane);
}
/* Resume virtqueue ioeventfd processing after drain */
@@ -1563,11 +1602,9 @@
{
VirtIOBlock *s = opaque;
- if (!s->dataplane || !s->dataplane_started) {
- return;
+ if (s->ioeventfd_started) {
+ virtio_blk_ioeventfd_attach(s);
}
-
- virtio_blk_data_plane_attach(s->dataplane);
}
static const BlockDevOps virtio_block_ops = {
@@ -1576,6 +1613,312 @@
.drained_end = virtio_blk_drained_end,
};
+/* Generate vq:AioContext mappings from a validated iothread-vq-mapping list */
+static void
+apply_vq_mapping(IOThreadVirtQueueMappingList *iothread_vq_mapping_list,
+ AioContext **vq_aio_context, uint16_t num_queues)
+{
+ IOThreadVirtQueueMappingList *node;
+ size_t num_iothreads = 0;
+ size_t cur_iothread = 0;
+
+ for (node = iothread_vq_mapping_list; node; node = node->next) {
+ num_iothreads++;
+ }
+
+ for (node = iothread_vq_mapping_list; node; node = node->next) {
+ IOThread *iothread = iothread_by_id(node->value->iothread);
+ AioContext *ctx = iothread_get_aio_context(iothread);
+
+ /* Released in virtio_blk_vq_aio_context_cleanup() */
+ object_ref(OBJECT(iothread));
+
+ if (node->value->vqs) {
+ uint16List *vq;
+
+ /* Explicit vq:IOThread assignment */
+ for (vq = node->value->vqs; vq; vq = vq->next) {
+ vq_aio_context[vq->value] = ctx;
+ }
+ } else {
+ /* Round-robin vq:IOThread assignment */
+ for (unsigned i = cur_iothread; i < num_queues;
+ i += num_iothreads) {
+ vq_aio_context[i] = ctx;
+ }
+ }
+
+ cur_iothread++;
+ }
+}
+
+/* Context: BQL held */
+static bool virtio_blk_vq_aio_context_init(VirtIOBlock *s, Error **errp)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
+ VirtIOBlkConf *conf = &s->conf;
+ BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+
+ if (conf->iothread || conf->iothread_vq_mapping_list) {
+ if (!k->set_guest_notifiers || !k->ioeventfd_assign) {
+ error_setg(errp,
+ "device is incompatible with iothread "
+ "(transport does not support notifiers)");
+ return false;
+ }
+ if (!virtio_device_ioeventfd_enabled(vdev)) {
+ error_setg(errp, "ioeventfd is required for iothread");
+ return false;
+ }
+
+ /*
+ * If ioeventfd is (re-)enabled while the guest is running there could
+ * be block jobs that can conflict.
+ */
+ if (blk_op_is_blocked(conf->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
+ error_prepend(errp, "cannot start virtio-blk ioeventfd: ");
+ return false;
+ }
+ }
+
+ s->vq_aio_context = g_new(AioContext *, conf->num_queues);
+
+ if (conf->iothread_vq_mapping_list) {
+ apply_vq_mapping(conf->iothread_vq_mapping_list, s->vq_aio_context,
+ conf->num_queues);
+ } else if (conf->iothread) {
+ AioContext *ctx = iothread_get_aio_context(conf->iothread);
+ for (unsigned i = 0; i < conf->num_queues; i++) {
+ s->vq_aio_context[i] = ctx;
+ }
+
+ /* Released in virtio_blk_vq_aio_context_cleanup() */
+ object_ref(OBJECT(conf->iothread));
+ } else {
+ AioContext *ctx = qemu_get_aio_context();
+ for (unsigned i = 0; i < conf->num_queues; i++) {
+ s->vq_aio_context[i] = ctx;
+ }
+ }
+
+ return true;
+}
+
+/* Context: BQL held */
+static void virtio_blk_vq_aio_context_cleanup(VirtIOBlock *s)
+{
+ VirtIOBlkConf *conf = &s->conf;
+
+ assert(!s->ioeventfd_started);
+
+ if (conf->iothread_vq_mapping_list) {
+ IOThreadVirtQueueMappingList *node;
+
+ for (node = conf->iothread_vq_mapping_list; node; node = node->next) {
+ IOThread *iothread = iothread_by_id(node->value->iothread);
+ object_unref(OBJECT(iothread));
+ }
+ }
+
+ if (conf->iothread) {
+ object_unref(OBJECT(conf->iothread));
+ }
+
+ g_free(s->vq_aio_context);
+ s->vq_aio_context = NULL;
+}
+
+/* Context: BQL held */
+static int virtio_blk_start_ioeventfd(VirtIODevice *vdev)
+{
+ VirtIOBlock *s = VIRTIO_BLK(vdev);
+ BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
+ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+ unsigned i;
+ unsigned nvqs = s->conf.num_queues;
+ Error *local_err = NULL;
+ int r;
+
+ if (s->ioeventfd_started || s->ioeventfd_starting) {
+ return 0;
+ }
+
+ s->ioeventfd_starting = true;
+
+ /* Set up guest notifier (irq) */
+ r = k->set_guest_notifiers(qbus->parent, nvqs, true);
+ if (r != 0) {
+ error_report("virtio-blk failed to set guest notifier (%d), "
+ "ensure -accel kvm is set.", r);
+ goto fail_guest_notifiers;
+ }
+
+ /*
+ * Batch all the host notifiers in a single transaction to avoid
+ * quadratic time complexity in address_space_update_ioeventfds().
+ */
+ memory_region_transaction_begin();
+
+ /* Set up virtqueue notify */
+ for (i = 0; i < nvqs; i++) {
+ r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, true);
+ if (r != 0) {
+ int j = i;
+
+ fprintf(stderr, "virtio-blk failed to set host notifier (%d)\n", r);
+ while (i--) {
+ virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
+ }
+
+ /*
+ * The transaction expects the ioeventfds to be open when it
+ * commits. Do it now, before the cleanup loop.
+ */
+ memory_region_transaction_commit();
+
+ while (j--) {
+ virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), j);
+ }
+ goto fail_host_notifiers;
+ }
+ }
+
+ memory_region_transaction_commit();
+
+ /*
+ * Try to change the AioContext so that block jobs and other operations can
+ * co-locate their activity in the same AioContext. If it fails, nevermind.
+ */
+ r = blk_set_aio_context(s->conf.conf.blk, s->vq_aio_context[0],
+ &local_err);
+ if (r < 0) {
+ warn_report_err(local_err);
+ }
+
+ /*
+ * These fields must be visible to the IOThread when it processes the
+ * virtqueue, otherwise it will think ioeventfd has not started yet.
+ *
+ * Make sure ->ioeventfd_started is false when blk_set_aio_context() is
+ * called above so that draining does not cause the host notifier to be
+ * detached/attached prematurely.
+ */
+ s->ioeventfd_starting = false;
+ s->ioeventfd_started = true;
+ smp_wmb(); /* paired with aio_notify_accept() on the read side */
+
+ /* Get this show started by hooking up our callbacks */
+ for (i = 0; i < nvqs; i++) {
+ VirtQueue *vq = virtio_get_queue(vdev, i);
+ AioContext *ctx = s->vq_aio_context[i];
+
+ /* Kick right away to begin processing requests already in vring */
+ event_notifier_set(virtio_queue_get_host_notifier(vq));
+
+ if (!blk_in_drain(s->conf.conf.blk)) {
+ virtio_queue_aio_attach_host_notifier(vq, ctx);
+ }
+ }
+ return 0;
+
+ fail_host_notifiers:
+ k->set_guest_notifiers(qbus->parent, nvqs, false);
+ fail_guest_notifiers:
+ s->ioeventfd_disabled = true;
+ s->ioeventfd_starting = false;
+ return -ENOSYS;
+}
+
+/* Stop notifications for new requests from guest.
+ *
+ * Context: BH in IOThread
+ */
+static void virtio_blk_ioeventfd_stop_vq_bh(void *opaque)
+{
+ VirtQueue *vq = opaque;
+ EventNotifier *host_notifier = virtio_queue_get_host_notifier(vq);
+
+ virtio_queue_aio_detach_host_notifier(vq, qemu_get_current_aio_context());
+
+ /*
+ * Test and clear notifier after disabling event, in case poll callback
+ * didn't have time to run.
+ */
+ virtio_queue_host_notifier_read(host_notifier);
+}
+
+/* Context: BQL held */
+static void virtio_blk_stop_ioeventfd(VirtIODevice *vdev)
+{
+ VirtIOBlock *s = VIRTIO_BLK(vdev);
+ BusState *qbus = qdev_get_parent_bus(DEVICE(s));
+ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+ unsigned i;
+ unsigned nvqs = s->conf.num_queues;
+
+ if (!s->ioeventfd_started || s->ioeventfd_stopping) {
+ return;
+ }
+
+ /* Better luck next time. */
+ if (s->ioeventfd_disabled) {
+ s->ioeventfd_disabled = false;
+ s->ioeventfd_started = false;
+ return;
+ }
+ s->ioeventfd_stopping = true;
+
+ if (!blk_in_drain(s->conf.conf.blk)) {
+ for (i = 0; i < nvqs; i++) {
+ VirtQueue *vq = virtio_get_queue(vdev, i);
+ AioContext *ctx = s->vq_aio_context[i];
+
+ aio_wait_bh_oneshot(ctx, virtio_blk_ioeventfd_stop_vq_bh, vq);
+ }
+ }
+
+ /*
+ * Batch all the host notifiers in a single transaction to avoid
+ * quadratic time complexity in address_space_update_ioeventfds().
+ */
+ memory_region_transaction_begin();
+
+ for (i = 0; i < nvqs; i++) {
+ virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
+ }
+
+ /*
+ * The transaction expects the ioeventfds to be open when it
+ * commits. Do it now, before the cleanup loop.
+ */
+ memory_region_transaction_commit();
+
+ for (i = 0; i < nvqs; i++) {
+ virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
+ }
+
+ /*
+ * Set ->ioeventfd_started to false before draining so that host notifiers
+ * are not detached/attached anymore.
+ */
+ s->ioeventfd_started = false;
+
+ /* Wait for virtio_blk_dma_restart_bh() and in flight I/O to complete */
+ blk_drain(s->conf.conf.blk);
+
+ /*
+ * Try to switch bs back to the QEMU main loop. If other users keep the
+ * BlockBackend in the iothread, that's ok
+ */
+ blk_set_aio_context(s->conf.conf.blk, qemu_get_aio_context(), NULL);
+
+ /* Clean up guest notifier (irq) */
+ k->set_guest_notifiers(qbus->parent, nvqs, false);
+
+ s->ioeventfd_stopping = false;
+}
+
static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
@@ -1680,7 +2023,13 @@
virtio_add_queue(vdev, conf->queue_size, virtio_blk_handle_output);
}
qemu_coroutine_inc_pool_size(conf->num_queues * conf->queue_size / 2);
- virtio_blk_data_plane_create(vdev, conf, &s->dataplane, &err);
+
+ /* Don't start ioeventfd if transport does not support notifiers. */
+ if (!virtio_device_ioeventfd_enabled(vdev)) {
+ s->ioeventfd_disabled = true;
+ }
+
+ virtio_blk_vq_aio_context_init(s, &err);
if (err != NULL) {
error_propagate(errp, err);
for (i = 0; i < conf->num_queues; i++) {
@@ -1717,8 +2066,7 @@
blk_drain(s->blk);
del_boot_device_lchs(dev, "/disk@0,0");
- virtio_blk_data_plane_destroy(s->dataplane);
- s->dataplane = NULL;
+ virtio_blk_vq_aio_context_cleanup(s);
for (i = 0; i < conf->num_queues; i++) {
virtio_del_queue(vdev, i);
}
@@ -1802,8 +2150,8 @@
vdc->reset = virtio_blk_reset;
vdc->save = virtio_blk_save_device;
vdc->load = virtio_blk_load_device;
- vdc->start_ioeventfd = virtio_blk_data_plane_start;
- vdc->stop_ioeventfd = virtio_blk_data_plane_stop;
+ vdc->start_ioeventfd = virtio_blk_start_ioeventfd;
+ vdc->stop_ioeventfd = virtio_blk_stop_ioeventfd;
}
static const TypeInfo virtio_blk_info = {
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 7a2846f..5a79bc3 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -674,6 +674,11 @@
n->mergeable_rx_bufs = mergeable_rx_bufs;
+ /*
+ * Note: when extending the vnet header, please make sure to
+ * change the vnet header copying logic in virtio_net_flush_tx()
+ * as well.
+ */
if (version_1) {
n->guest_hdr_len = hash_report ?
sizeof(struct virtio_net_hdr_v1_hash) :
@@ -2693,7 +2698,7 @@
ssize_t ret;
unsigned int out_num;
struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1], *out_sg;
- struct virtio_net_hdr_mrg_rxbuf mhdr;
+ struct virtio_net_hdr_v1_hash vhdr;
elem = virtqueue_pop(q->tx_vq, sizeof(VirtQueueElement));
if (!elem) {
@@ -2710,7 +2715,7 @@
}
if (n->has_vnet_hdr) {
- if (iov_to_buf(out_sg, out_num, 0, &mhdr, n->guest_hdr_len) <
+ if (iov_to_buf(out_sg, out_num, 0, &vhdr, n->guest_hdr_len) <
n->guest_hdr_len) {
virtio_error(vdev, "virtio-net header incorrect");
virtqueue_detach_element(q->tx_vq, elem, 0);
@@ -2718,8 +2723,8 @@
return -EINVAL;
}
if (n->needs_vnet_hdr_swap) {
- virtio_net_hdr_swap(vdev, (void *) &mhdr);
- sg2[0].iov_base = &mhdr;
+ virtio_net_hdr_swap(vdev, (void *) &vhdr);
+ sg2[0].iov_base = &vhdr;
sg2[0].iov_len = n->guest_hdr_len;
out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1,
out_sg, out_num,
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
index 4ec0b21..bd7cecd 100644
--- a/include/block/block-global-state.h
+++ b/include/block/block-global-state.h
@@ -144,7 +144,8 @@
void bdrv_register(BlockDriver *bdrv);
int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
- const char *backing_file_str);
+ const char *backing_file_str,
+ bool backing_mask_protocol);
BlockDriverState * GRAPH_RDLOCK
bdrv_find_overlay(BlockDriverState *active, BlockDriverState *bs);
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index 151279d..7612761 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -985,7 +985,9 @@
* can update its reference.
*/
int (*update_filename)(BdrvChild *child, BlockDriverState *new_base,
- const char *filename, Error **errp);
+ const char *filename,
+ bool backing_mask_protocol,
+ Error **errp);
bool (*change_aio_ctx)(BdrvChild *child, AioContext *ctx,
GHashTable *visited, Transaction *tran,
diff --git a/include/block/block_int-global-state.h b/include/block/block_int-global-state.h
index ef31c58..d2201e2 100644
--- a/include/block/block_int-global-state.h
+++ b/include/block/block_int-global-state.h
@@ -46,6 +46,8 @@
* flatten the whole backing file chain onto @bs.
* @backing_file_str: The file name that will be written to @bs as the
* the new backing file if the job completes. Ignored if @base is %NULL.
+ * @backing_mask_protocol: Replace potential protocol name with 'raw' in
+ * 'backing file format' header
* @creation_flags: Flags that control the behavior of the Job lifetime.
* See @BlockJobCreateFlags
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
@@ -64,6 +66,7 @@
*/
void stream_start(const char *job_id, BlockDriverState *bs,
BlockDriverState *base, const char *backing_file_str,
+ bool backing_mask_protocol,
BlockDriverState *bottom,
int creation_flags, int64_t speed,
BlockdevOnError on_error,
@@ -82,6 +85,8 @@
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
* @on_error: The action to take upon error.
* @backing_file_str: String to use as the backing file in @top's overlay
+ * @backing_mask_protocol: Replace potential protocol name with 'raw' in
+ * 'backing file format' header
* @filter_node_name: The node name that should be assigned to the filter
* driver that the commit job inserts into the graph above @top. NULL means
* that a node name should be autogenerated.
@@ -92,6 +97,7 @@
BlockDriverState *base, BlockDriverState *top,
int creation_flags, int64_t speed,
BlockdevOnError on_error, const char *backing_file_str,
+ bool backing_mask_protocol,
const char *filter_node_name, Error **errp);
/**
* commit_active_start:
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index 5e4091e..833a9a3 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -50,8 +50,6 @@
bool x_enable_wce_if_config_wce;
};
-struct VirtIOBlockDataPlane;
-
struct VirtIOBlockReq;
struct VirtIOBlock {
VirtIODevice parent_obj;
@@ -62,9 +60,17 @@
unsigned short sector_mask;
bool original_wce;
VMChangeStateEntry *change;
- bool dataplane_disabled;
- bool dataplane_started;
- struct VirtIOBlockDataPlane *dataplane;
+ bool ioeventfd_disabled;
+ bool ioeventfd_started;
+ bool ioeventfd_starting;
+ bool ioeventfd_stopping;
+
+ /*
+ * The AioContext for each virtqueue. The BlockDriverState will use the
+ * first element as its AioContext.
+ */
+ AioContext **vq_aio_context;
+
uint64_t host_features;
size_t config_size;
BlockRAMRegistrar blk_ram_registrar;
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index d53a84c..27b85d4 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -39,7 +39,7 @@
* limitations; see the documentation for each visitor for more
* details on what it supports. Also, see visitor-impl.h for the
* callback contracts implemented by each visitor, and
- * docs/devel/qapi-code-gen.txt for more about the QAPI code
+ * docs/devel/qapi-code-gen.rst for more about the QAPI code
* generator.
*
* All of the visitors are created via:
diff --git a/include/qemu/yank.h b/include/qemu/yank.h
index 1907150..3d88af6 100644
--- a/include/qemu/yank.h
+++ b/include/qemu/yank.h
@@ -45,7 +45,7 @@
* yank_register_function: Register a yank function
*
* This registers a yank function. All limitations of qmp oob commands apply
- * to the yank function as well. See docs/devel/qapi-code-gen.txt under
+ * to the yank function as well. See docs/devel/qapi-code-gen.rst under
* "An OOB-capable command handler must satisfy the following conditions".
*
* This function is thread-safe.
diff --git a/linux-headers/asm-loongarch/kvm.h b/linux-headers/asm-loongarch/kvm.h
index c6ad2ee..923d0bd 100644
--- a/linux-headers/asm-loongarch/kvm.h
+++ b/linux-headers/asm-loongarch/kvm.h
@@ -79,6 +79,7 @@
#define LOONGARCH_REG_64(TYPE, REG) (TYPE | KVM_REG_SIZE_U64 | (REG << LOONGARCH_REG_SHIFT))
#define KVM_IOC_CSRID(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CSR, REG)
#define KVM_IOC_CPUCFG(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CPUCFG, REG)
+#define KVM_LOONGARCH_VCPU_CPUCFG 0
struct kvm_debug_exit_arch {
};
diff --git a/meson.build b/meson.build
index d032996..5ffa8c9 100644
--- a/meson.build
+++ b/meson.build
@@ -3286,7 +3286,6 @@
'hw/arm',
'hw/audio',
'hw/block',
- 'hw/block/dataplane',
'hw/char',
'hw/display',
'hw/dma',
diff --git a/monitor/qmp.c b/monitor/qmp.c
index 6eee450..a239945 100644
--- a/monitor/qmp.c
+++ b/monitor/qmp.c
@@ -321,14 +321,6 @@
qemu_coroutine_yield();
}
- /*
- * Move the coroutine from iohandler_ctx to qemu_aio_context for
- * executing the command handler so that it can make progress if it
- * involves an AIO_WAIT_WHILE().
- */
- aio_co_schedule(qemu_get_aio_context(), qmp_dispatcher_co);
- qemu_coroutine_yield();
-
/* Process request */
if (req_obj->req) {
if (trace_event_get_state(TRACE_MONITOR_QMP_CMD_IN_BAND)) {
@@ -355,15 +347,6 @@
}
qmp_request_free(req_obj);
-
- /*
- * Yield and reschedule so the main loop stays responsive.
- *
- * Move back to iohandler_ctx so that nested event loops for
- * qemu_aio_context don't start new monitor commands.
- */
- aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co);
- qemu_coroutine_yield();
}
qatomic_set(&qmp_dispatcher_co, NULL);
}
diff --git a/qapi/block-core.json b/qapi/block-core.json
index ca390c5..48c181e 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1361,7 +1361,7 @@
# target, i.e. same data and new writes are done synchronously to
# both.
#
-# Since 8.2
+# Since: 8.2
##
{ 'struct': 'BlockJobInfoMirror',
'data': { 'actively-synced': 'bool' } }
@@ -1810,6 +1810,11 @@
# Care should be taken when specifying the string, to specify a
# valid filename or protocol. (Since 2.1)
#
+# @backing-mask-protocol: If true, replace any protocol mentioned in the
+# 'backing file format' with 'raw', rather than storing the protocol
+# name as the backing format. Can be used even when no image header
+# will be updated (default false; since 9.0).
+#
# @speed: the maximum speed, in bytes per second
#
# @on-error: the action to take on an error. 'ignore' means that the
@@ -1856,7 +1861,8 @@
'*base': { 'type': 'str', 'features': [ 'deprecated' ] },
'*top-node': 'str',
'*top': { 'type': 'str', 'features': [ 'deprecated' ] },
- '*backing-file': 'str', '*speed': 'int',
+ '*backing-file': 'str', '*backing-mask-protocol': 'bool',
+ '*speed': 'int',
'*on-error': 'BlockdevOnError',
'*filter-node-name': 'str',
'*auto-finalize': 'bool', '*auto-dismiss': 'bool' },
@@ -2820,6 +2826,11 @@
# Care should be taken when specifying the string, to specify a
# valid filename or protocol. (Since 2.1)
#
+# @backing-mask-protocol: If true, replace any protocol mentioned in the
+# 'backing file format' with 'raw', rather than storing the protocol
+# name as the backing format. Can be used even when no image header
+# will be updated (default false; since 9.0).
+#
# @speed: the maximum speed, in bytes per second
#
# @on-error: the action to take on an error (default report). 'stop'
@@ -2858,7 +2869,9 @@
##
{ 'command': 'block-stream',
'data': { '*job-id': 'str', 'device': 'str', '*base': 'str',
- '*base-node': 'str', '*backing-file': 'str', '*bottom': 'str',
+ '*base-node': 'str', '*backing-file': 'str',
+ '*backing-mask-protocol': 'bool',
+ '*bottom': 'str',
'*speed': 'int', '*on-error': 'BlockdevOnError',
'*filter-node-name': 'str',
'*auto-finalize': 'bool', '*auto-dismiss': 'bool' },
@@ -3080,7 +3093,7 @@
#
# @type: The job type
#
-# Since 8.2
+# Since: 8.2
##
{ 'union': 'BlockJobChangeOptions',
'base': { 'id': 'str', 'type': 'JobType' },
diff --git a/qapi/char.json b/qapi/char.json
index c1bab7b..6c6ad3b 100644
--- a/qapi/char.json
+++ b/qapi/char.json
@@ -391,8 +391,8 @@
# @rows: console height, in chars
#
# Note: the options are only effective when the VNC or SDL graphical
-# display backend is active. They are ignored with the GTK, Spice, VNC
-# and D-Bus display backends.
+# display backend is active. They are ignored with the GTK,
+# Spice, VNC and D-Bus display backends.
#
# Since: 1.5
##
diff --git a/qapi/introspect.json b/qapi/introspect.json
index 9173e60..8df1ce8 100644
--- a/qapi/introspect.json
+++ b/qapi/introspect.json
@@ -261,7 +261,7 @@
#
# @members: the alternate type's members, in no particular order. The
# members' wire encoding is distinct, see
-# docs/devel/qapi-code-gen.txt section Alternate types.
+# :doc:`/devel/qapi-code-gen` section Alternate types.
#
# On the wire, this can be any of the members.
#
diff --git a/qapi/machine.json b/qapi/machine.json
index b6d634b..aa99fa3 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -1059,10 +1059,10 @@
# From it we have: balloon_size = vm_ram_size - @value
#
# Returns:
-# - Nothing on success
-# - If the balloon driver is enabled but not functional because the
-# KVM kernel module cannot support it, KVMMissingCap
-# - If no balloon device is present, DeviceNotActive
+# - Nothing on success
+# - If the balloon driver is enabled but not functional because
+# the KVM kernel module cannot support it, KVMMissingCap
+# - If no balloon device is present, DeviceNotActive
#
# Notes: This command just issues a request to the guest. When it
# returns, the balloon size may not have changed. A guest can
@@ -1097,10 +1097,10 @@
# Return information about the balloon device.
#
# Returns:
-# - @BalloonInfo on success
-# - If the balloon driver is enabled but not functional because the
-# KVM kernel module cannot support it, KVMMissingCap
-# - If no balloon device is present, DeviceNotActive
+# - @BalloonInfo on success
+# - If the balloon driver is enabled but not functional because
+# the KVM kernel module cannot support it, KVMMissingCap
+# - If no balloon device is present, DeviceNotActive
#
# Since: 0.14
#
@@ -1161,10 +1161,10 @@
# message from the guest.
#
# Returns:
-# - @HvBalloonInfo on success
-# - If no hv-balloon device is present, guest memory status reporting
-# is not enabled or no guest memory status report received yet,
-# GenericError
+# - @HvBalloonInfo on success
+# - If no hv-balloon device is present, guest memory status
+# reporting is not enabled or no guest memory status report
+# received yet, GenericError
#
# Since: 8.2
#
diff --git a/qapi/migration.json b/qapi/migration.json
index eb2f883..489b591 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -1597,7 +1597,7 @@
#
# @file: Direct the migration stream to a file.
#
-# Since 8.2
+# Since: 8.2
##
{ 'enum': 'MigrationAddressType',
'data': [ 'socket', 'exec', 'rdma', 'file' ] }
@@ -1609,7 +1609,7 @@
#
# @offset: The file offset where the migration stream will start
#
-# Since 8.2
+# Since: 8.2
##
{ 'struct': 'FileMigrationArgs',
'data': { 'filename': 'str',
@@ -1620,7 +1620,7 @@
#
# @args: command (list head) and arguments to execute.
#
-# Since 8.2
+# Since: 8.2
##
{ 'struct': 'MigrationExecCommand',
'data': {'args': [ 'str' ] } }
@@ -1630,7 +1630,7 @@
#
# Migration endpoint configuration.
#
-# Since 8.2
+# Since: 8.2
##
{ 'union': 'MigrationAddress',
'base': { 'transport' : 'MigrationAddressType'},
@@ -1648,7 +1648,7 @@
#
# @main: Main outbound migration channel.
#
-# Since 8.1
+# Since: 8.1
##
{ 'enum': 'MigrationChannelType',
'data': [ 'main' ] }
@@ -1662,7 +1662,7 @@
#
# @addr: Migration endpoint configuration on destination interface.
#
-# Since 8.1
+# Since: 8.1
##
{ 'struct': 'MigrationChannel',
'data': {
@@ -2126,7 +2126,7 @@
#
# @millisecond: value is in milliseconds
#
-# Since 8.2
+# Since: 8.2
#
##
{ 'enum': 'TimeUnit',
diff --git a/qapi/misc-target.json b/qapi/misc-target.json
index 8829145..9195e7d 100644
--- a/qapi/misc-target.json
+++ b/qapi/misc-target.json
@@ -475,7 +475,7 @@
# @port: The port number
#
# Returns:
-# - Nothing on success.
+# - Nothing on success.
#
# Since: 8.0
#
diff --git a/qapi/misc.json b/qapi/misc.json
index 3622d98..2ca8c39 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -344,9 +344,9 @@
# @opaque: A free-form string that can be used to describe the fd.
#
# Returns:
-# - @AddfdInfo on success
-# - If file descriptor was not received, GenericError
-# - If @fdset-id is a negative value, GenericError
+# - @AddfdInfo on success
+# - If file descriptor was not received, GenericError
+# - If @fdset-id is a negative value, GenericError
#
# Notes: The list of fd sets is shared by all monitor connections.
#
@@ -374,8 +374,8 @@
# @fd: The file descriptor that is to be removed.
#
# Returns:
-# - Nothing on success
-# - If @fdset-id or @fd is not found, GenericError
+# - Nothing on success
+# - If @fdset-id or @fd is not found, GenericError
#
# Since: 1.2
#
diff --git a/qapi/net.json b/qapi/net.json
index 8095b68..68493d6 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -18,8 +18,9 @@
#
# @up: true to set the link status to be up
#
-# Returns: Nothing on success If @name is not a valid network device,
-# DeviceNotFound
+# Returns:
+# - Nothing on success
+# - If @name is not a valid network device, DeviceNotFound
#
# Since: 0.14
#
@@ -44,8 +45,9 @@
#
# Since: 0.14
#
-# Returns: Nothing on success If @type is not a valid network backend,
-# DeviceNotFound
+# Returns:
+# - Nothing on success
+# - If @type is not a valid network backend, DeviceNotFound
#
# Example:
#
@@ -64,8 +66,9 @@
#
# @id: the name of the network backend to remove
#
-# Returns: Nothing on success If @id is not a valid network backend,
-# DeviceNotFound
+# Returns:
+# - Nothing on success
+# - If @id is not a valid network backend, DeviceNotFound
#
# Since: 0.14
#
diff --git a/qapi/qapi-util.c b/qapi/qapi-util.c
index 63596e1..65a7d18 100644
--- a/qapi/qapi-util.c
+++ b/qapi/qapi-util.c
@@ -112,7 +112,7 @@
* It may be prefixed by __RFQDN_ (downstream extension), where RFQDN
* may contain only letters, digits, hyphen and period.
* The special exception for enumeration names is not implemented.
- * See docs/devel/qapi-code-gen.txt for more on QAPI naming rules.
+ * See docs/devel/qapi-code-gen.rst for more on QAPI naming rules.
* Keep this consistent with scripts/qapi-gen.py!
* If @complete, the parse fails unless it consumes @str completely.
* Return its length on success, -1 on failure.
diff --git a/qapi/qdev.json b/qapi/qdev.json
index 6bc5a73..25bac5e 100644
--- a/qapi/qdev.json
+++ b/qapi/qdev.json
@@ -89,8 +89,9 @@
#
# @id: the device's ID or QOM path
#
-# Returns: Nothing on success If @id is not a valid device,
-# DeviceNotFound
+# Returns:
+# - Nothing on success
+# - If @id is not a valid device, DeviceNotFound
#
# Notes: When this command completes, the device may not be removed
# from the guest. Hot removal is an operation that requires guest
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 555528b..176b549 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -206,9 +206,31 @@
assert(!(oob && qemu_in_coroutine()));
assert(monitor_cur() == NULL);
if (!!(cmd->options & QCO_COROUTINE) == qemu_in_coroutine()) {
+ if (qemu_in_coroutine()) {
+ /*
+ * Move the coroutine from iohandler_ctx to qemu_aio_context for
+ * executing the command handler so that it can make progress if it
+ * involves an AIO_WAIT_WHILE().
+ */
+ aio_co_schedule(qemu_get_aio_context(), qemu_coroutine_self());
+ qemu_coroutine_yield();
+ }
+
monitor_set_cur(qemu_coroutine_self(), cur_mon);
cmd->fn(args, &ret, &err);
monitor_set_cur(qemu_coroutine_self(), NULL);
+
+ if (qemu_in_coroutine()) {
+ /*
+ * Yield and reschedule so the main loop stays responsive.
+ *
+ * Move back to iohandler_ctx so that nested event loops for
+ * qemu_aio_context don't start new monitor commands.
+ */
+ aio_co_schedule(iohandler_get_aio_context(),
+ qemu_coroutine_self());
+ qemu_coroutine_yield();
+ }
} else {
/*
* Actual context doesn't match the one the command needs.
@@ -232,7 +254,7 @@
.errp = &err,
.co = qemu_coroutine_self(),
};
- aio_bh_schedule_oneshot(qemu_get_aio_context(), do_qmp_dispatch_bh,
+ aio_bh_schedule_oneshot(iohandler_get_aio_context(), do_qmp_dispatch_bh,
&data);
qemu_coroutine_yield();
}
diff --git a/qapi/qom.json b/qapi/qom.json
index 95516ba..84af23f 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -1056,8 +1056,9 @@
#
# Create a QOM object.
#
-# Returns: Nothing on success Error if @qom-type is not a valid class
-# name
+# Returns:
+# - Nothing on success
+# - Error if @qom-type is not a valid class name
#
# Since: 2.0
#
@@ -1078,8 +1079,9 @@
#
# @id: the name of the QOM object to remove
#
-# Returns: Nothing on success Error if @id is not a valid id for a QOM
-# object
+# Returns:
+# - Nothing on success
+# - Error if @id is not a valid id for a QOM object
#
# Since: 2.0
#
diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c
index f0c1dea..5115536 100644
--- a/qapi/string-output-visitor.c
+++ b/qapi/string-output-visitor.c
@@ -65,6 +65,7 @@
} range_start, range_end;
GList *ranges;
void *list; /* Only needed for sanity checking the caller */
+ unsigned int struct_nesting;
};
static StringOutputVisitor *to_sov(Visitor *v)
@@ -144,6 +145,10 @@
StringOutputVisitor *sov = to_sov(v);
GList *l;
+ if (sov->struct_nesting) {
+ return true;
+ }
+
switch (sov->list_mode) {
case LM_NONE:
string_output_append(sov, *obj);
@@ -231,6 +236,10 @@
uint64_t val;
char *out, *psize;
+ if (sov->struct_nesting) {
+ return true;
+ }
+
if (!sov->human) {
out = g_strdup_printf("%"PRIu64, *obj);
string_output_set(sov, out);
@@ -250,6 +259,11 @@
Error **errp)
{
StringOutputVisitor *sov = to_sov(v);
+
+ if (sov->struct_nesting) {
+ return true;
+ }
+
string_output_set(sov, g_strdup(*obj ? "true" : "false"));
return true;
}
@@ -260,6 +274,10 @@
StringOutputVisitor *sov = to_sov(v);
char *out;
+ if (sov->struct_nesting) {
+ return true;
+ }
+
if (sov->human) {
out = *obj ? g_strdup_printf("\"%s\"", *obj) : g_strdup("<null>");
} else {
@@ -273,6 +291,11 @@
Error **errp)
{
StringOutputVisitor *sov = to_sov(v);
+
+ if (sov->struct_nesting) {
+ return true;
+ }
+
string_output_set(sov, g_strdup_printf("%.17g", *obj));
return true;
}
@@ -283,6 +306,10 @@
StringOutputVisitor *sov = to_sov(v);
char *out;
+ if (sov->struct_nesting) {
+ return true;
+ }
+
if (sov->human) {
out = g_strdup("<null>");
} else {
@@ -295,6 +322,9 @@
static bool start_struct(Visitor *v, const char *name, void **obj,
size_t size, Error **errp)
{
+ StringOutputVisitor *sov = to_sov(v);
+
+ sov->struct_nesting++;
return true;
}
@@ -302,6 +332,10 @@
{
StringOutputVisitor *sov = to_sov(v);
+ if (--sov->struct_nesting) {
+ return;
+ }
+
/* TODO actually print struct fields */
string_output_set(sov, g_strdup("<omitted>"));
}
@@ -312,6 +346,10 @@
{
StringOutputVisitor *sov = to_sov(v);
+ if (sov->struct_nesting) {
+ return true;
+ }
+
/* we can't traverse a list in a list */
assert(sov->list_mode == LM_NONE);
/* We don't support visits without a list */
@@ -329,6 +367,10 @@
StringOutputVisitor *sov = to_sov(v);
GenericList *ret = tail->next;
+ if (sov->struct_nesting) {
+ return ret;
+ }
+
if (ret && !ret->next) {
sov->list_mode = LM_END;
}
@@ -339,6 +381,10 @@
{
StringOutputVisitor *sov = to_sov(v);
+ if (sov->struct_nesting) {
+ return;
+ }
+
assert(sov->list == obj);
assert(sov->list_mode == LM_STARTED ||
sov->list_mode == LM_END ||
diff --git a/qapi/yank.json b/qapi/yank.json
index 87ec7ca..60eda20 100644
--- a/qapi/yank.json
+++ b/qapi/yank.json
@@ -77,8 +77,8 @@
# Takes a list of @YankInstance as argument.
#
# Returns:
-# - Nothing on success
-# - @DeviceNotFound error, if any of the YankInstances doesn't exist
+# - Nothing on success
+# - @DeviceNotFound error, if any of the YankInstances doesn't exist
#
# Example:
#
diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index bf31018..48cd55a 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -71,7 +71,7 @@
Parse QAPI schema source.
Parse a JSON-esque schema file and process directives. See
- qapi-code-gen.txt section "Schema Syntax" for the exact syntax.
+ qapi-code-gen.rst section "Schema Syntax" for the exact syntax.
Grammatical validation is handled later by `expr.check_exprs()`.
:param fname: Source file name.
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 84bcdf5..c19978a 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -250,7 +250,7 @@
return ret;
}
-static int kvm_loongarch_put_csr(CPUState *cs)
+static int kvm_loongarch_put_csr(CPUState *cs, int level)
{
int ret = 0;
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
@@ -322,8 +322,11 @@
ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG),
&env->CSR_RVACFG);
- ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
+ /* CPUID is constant after poweron, it should be set only once */
+ if (level >= KVM_PUT_FULL_STATE) {
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
&env->CSR_CPUID);
+ }
ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1),
&env->CSR_PRCFG1);
@@ -537,6 +540,38 @@
return ret;
}
+static int kvm_check_cpucfg2(CPUState *cs)
+{
+ int ret;
+ uint64_t val;
+ struct kvm_device_attr attr = {
+ .group = KVM_LOONGARCH_VCPU_CPUCFG,
+ .attr = 2,
+ .addr = (uint64_t)&val,
+ };
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
+
+ if (!ret) {
+ kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
+ env->cpucfg[2] &= val;
+
+ if (FIELD_EX32(env->cpucfg[2], CPUCFG2, FP)) {
+ /* The FP minimal version is 1. */
+ env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, FP_VER, 1);
+ }
+
+ if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LLFTP)) {
+ /* The LLFTP minimal version is 1. */
+ env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LLFTP_VER, 1);
+ }
+ }
+
+ return ret;
+}
+
static int kvm_loongarch_put_cpucfg(CPUState *cs)
{
int i, ret = 0;
@@ -545,14 +580,13 @@
uint64_t val;
for (i = 0; i < 21; i++) {
+ if (i == 2) {
+ ret = kvm_check_cpucfg2(cs);
+ if (ret) {
+ return ret;
+ }
+ }
val = env->cpucfg[i];
- /* LSX and LASX and LBT are not supported in kvm now */
- if (i == 2) {
- val &= ~(BIT(R_CPUCFG2_LSX_SHIFT) | BIT(R_CPUCFG2_LASX_SHIFT));
- val &= ~(BIT(R_CPUCFG2_LBT_X86_SHIFT) |
- BIT(R_CPUCFG2_LBT_ARM_SHIFT) |
- BIT(R_CPUCFG2_LBT_MIPS_SHIFT));
- }
ret = kvm_set_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
if (ret < 0) {
trace_kvm_failed_put_cpucfg(strerror(errno));
@@ -598,7 +632,7 @@
return ret;
}
- ret = kvm_loongarch_put_csr(cs);
+ ret = kvm_loongarch_put_csr(cs, level);
if (ret) {
return ret;
}
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
index 329977d..a37bf44 100644
--- a/tests/qemu-iotests/060.out
+++ b/tests/qemu-iotests/060.out
@@ -421,8 +421,8 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_IMAGE_CORRUPTED", "data": {"device": "none0", "msg": "Preventing invalid write on metadata (overlaps with refcount table)", "offset": 65536, "node-name": "drive", "fatal": true, "size": 65536}}
write failed: Input/output error
{"return": ""}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
=== Testing incoming inactive corrupted image ===
@@ -432,8 +432,8 @@
qcow2: Image is corrupt: L2 table offset 0x2a2a2a00 unaligned (L1 index: 0); further non-fatal corruption events will be suppressed
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_IMAGE_CORRUPTED", "data": {"device": "", "msg": "L2 table offset 0x2a2a2a00 unaligned (L1 index: 0)", "node-name": "drive", "fatal": false}}
{"return": ""}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
corrupt: false
*** done
diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
index bca0c02..a2923b0 100644
--- a/tests/qemu-iotests/071.out
+++ b/tests/qemu-iotests/071.out
@@ -45,8 +45,8 @@
{"return": {}}
read failed: Input/output error
{"return": ""}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
=== Testing blkverify on existing block device ===
@@ -84,9 +84,9 @@
{"return": ""}
read failed: Input/output error
{"return": ""}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
QEMU_PROG: Failed to flush the L2 table cache: Input/output error
QEMU_PROG: Failed to flush the refcount block cache: Input/output error
+{"return": {}}
*** done
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
index 615c083..aba85ea 100644
--- a/tests/qemu-iotests/081.out
+++ b/tests/qemu-iotests/081.out
@@ -35,8 +35,8 @@
read 10485760/10485760 bytes at offset 0
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
== using quorum rewrite corrupted mode ==
@@ -67,8 +67,8 @@
read 10485760/10485760 bytes at offset 0
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
-- checking that the image has been corrected --
read 10485760/10485760 bytes at offset 0
@@ -106,8 +106,8 @@
{"return": {}}
{"return": {}}
{"return": {}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
Testing:
QMP_VERSION
@@ -115,8 +115,8 @@
{"return": {}}
{"return": {}}
{"error": {"class": "GenericError", "desc": "Cannot add a child to a quorum in blkverify mode"}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
== dynamically removing a child from a quorum ==
@@ -125,31 +125,31 @@
{"return": {}}
{"return": {}}
{"return": {}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
Testing:
QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "blkverify=on can only be set if there are exactly two files and vote-threshold is 2"}}
{"error": {"class": "GenericError", "desc": "Cannot find device='drive0-quorum' nor node-name='drive0-quorum'"}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
*** done
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
index e1c23a6..97b6d80 100644
--- a/tests/qemu-iotests/087.out
+++ b/tests/qemu-iotests/087.out
@@ -7,8 +7,8 @@
QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "'node-name' must be specified for the root node"}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
=== Duplicate ID ===
@@ -18,8 +18,8 @@
{"return": {}}
{"error": {"class": "GenericError", "desc": "node-name=disk is conflicting with a device id"}}
{"error": {"class": "GenericError", "desc": "Duplicate nodes with node-name='test-node'"}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
=== aio=native without O_DIRECT ===
@@ -28,8 +28,8 @@
QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "aio=native was specified, but it requires cache.direct=on, which was not specified."}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
=== Encrypted image QCow ===
@@ -40,8 +40,8 @@
{"return": {}}
{"return": {}}
{"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
=== Encrypted image LUKS ===
@@ -52,8 +52,8 @@
{"return": {}}
{"return": {}}
{"return": {}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
=== Missing driver ===
@@ -63,7 +63,7 @@
QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "Parameter 'driver' is missing"}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
*** done
diff --git a/tests/qemu-iotests/108.out b/tests/qemu-iotests/108.out
index b5401d7..b9c876b 100644
--- a/tests/qemu-iotests/108.out
+++ b/tests/qemu-iotests/108.out
@@ -173,8 +173,8 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "create"}}
{"return": {}}
{ "execute": "quit" }
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
index e207a55..0fb580f 100755
--- a/tests/qemu-iotests/109
+++ b/tests/qemu-iotests/109
@@ -57,13 +57,13 @@
_launch_qemu -drive file="${source_img}",format=raw,cache=${CACHEMODE},aio=${AIOMODE},id=src
_send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'qmp_capabilities' }" "return"
- _send_qemu_cmd $QEMU_HANDLE \
+ capture_events="$qmp_event" _send_qemu_cmd $QEMU_HANDLE \
"{'execute':'drive-mirror', 'arguments':{
'device': 'src', 'target': '$raw_img', $qmp_format
'mode': 'existing', 'sync': 'full'}}" \
"return"
- _send_qemu_cmd $QEMU_HANDLE '' "$qmp_event"
+ capture_events="$qmp_event JOB_STATUS_CHANGE" _wait_event $QEMU_HANDLE "$qmp_event"
if test "$qmp_event" = BLOCK_JOB_ERROR; then
_send_qemu_cmd $QEMU_HANDLE '' '"status": "null"'
fi
diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out
index 965c9a6..3ae8552 100644
--- a/tests/qemu-iotests/109.out
+++ b/tests/qemu-iotests/109.out
@@ -7,7 +7,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{
- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
'mode': 'existing', 'sync': 'full'}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -23,8 +23,8 @@
{"execute":"query-block-jobs"}
{"return": []}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
@@ -35,12 +35,10 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
{"execute":"query-block-jobs"}
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 1024, "offset": 1024, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
@@ -50,6 +48,7 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
+{"return": {}}
Images are identical.
=== Writing a qcow2 header into raw ===
@@ -59,7 +58,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{
- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
'mode': 'existing', 'sync': 'full'}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -75,8 +74,8 @@
{"execute":"query-block-jobs"}
{"return": []}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
@@ -87,12 +86,10 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}}
{"execute":"query-block-jobs"}
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 197120, "offset": 197120, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
@@ -102,6 +99,7 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
+{"return": {}}
Images are identical.
=== Writing a qed header into raw ===
@@ -111,7 +109,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{
- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
'mode': 'existing', 'sync': 'full'}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -127,8 +125,8 @@
{"execute":"query-block-jobs"}
{"return": []}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
@@ -139,12 +137,10 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
{"execute":"query-block-jobs"}
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 327680, "offset": 327680, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
@@ -154,6 +150,7 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
+{"return": {}}
Images are identical.
=== Writing a vdi header into raw ===
@@ -163,7 +160,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{
- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
'mode': 'existing', 'sync': 'full'}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -179,8 +176,8 @@
{"execute":"query-block-jobs"}
{"return": []}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
@@ -191,12 +188,10 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
{"execute":"query-block-jobs"}
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 1024, "offset": 1024, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
@@ -206,6 +201,7 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
+{"return": {}}
Images are identical.
=== Writing a vmdk header into raw ===
@@ -215,7 +211,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{
- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
'mode': 'existing', 'sync': 'full'}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -231,8 +227,8 @@
{"execute":"query-block-jobs"}
{"return": []}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
@@ -243,12 +239,10 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
{"execute":"query-block-jobs"}
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 65536, "offset": 65536, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
@@ -258,6 +252,7 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
+{"return": {}}
Images are identical.
=== Writing a vpc header into raw ===
@@ -267,7 +262,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{
- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
'mode': 'existing', 'sync': 'full'}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -283,8 +278,8 @@
{"execute":"query-block-jobs"}
{"return": []}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
@@ -295,12 +290,10 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
{"execute":"query-block-jobs"}
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2560, "offset": 2560, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
@@ -310,6 +303,7 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
+{"return": {}}
Images are identical.
=== Copying sample image empty.bochs into raw ===
@@ -318,7 +312,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{
- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
'mode': 'existing', 'sync': 'full'}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -334,8 +328,8 @@
{"execute":"query-block-jobs"}
{"return": []}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
@@ -346,12 +340,10 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
{"execute":"query-block-jobs"}
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2560, "offset": 2560, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
@@ -361,6 +353,7 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
+{"return": {}}
Images are identical.
=== Copying sample image iotest-dirtylog-10G-4M.vhdx into raw ===
@@ -369,7 +362,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{
- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
'mode': 'existing', 'sync': 'full'}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -385,8 +378,8 @@
{"execute":"query-block-jobs"}
{"return": []}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
@@ -397,12 +390,10 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}}
{"execute":"query-block-jobs"}
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 31457280, "offset": 31457280, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
@@ -412,6 +403,7 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
+{"return": {}}
Images are identical.
=== Copying sample image parallels-v1 into raw ===
@@ -420,7 +412,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{
- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
'mode': 'existing', 'sync': 'full'}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -436,8 +428,8 @@
{"execute":"query-block-jobs"}
{"return": []}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
@@ -448,12 +440,10 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
{"execute":"query-block-jobs"}
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 327680, "offset": 327680, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
@@ -463,6 +453,7 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
+{"return": {}}
Images are identical.
=== Copying sample image simple-pattern.cloop into raw ===
@@ -471,7 +462,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{
- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
'mode': 'existing', 'sync': 'full'}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -487,8 +478,8 @@
{"execute":"query-block-jobs"}
{"return": []}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
@@ -499,12 +490,10 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
{"execute":"query-block-jobs"}
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2048, "offset": 2048, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
@@ -514,6 +503,7 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
+{"return": {}}
Images are identical.
=== Write legitimate MBR into raw ===
@@ -522,7 +512,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{
- 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT',
'mode': 'existing', 'sync': 'full'}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -530,12 +520,10 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
{"execute":"query-block-jobs"}
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 512, "offset": 512, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
@@ -545,6 +533,7 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
+{"return": {}}
Images are identical.
{ 'execute': 'qmp_capabilities' }
{"return": {}}
@@ -554,12 +543,10 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
{"execute":"query-block-jobs"}
{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 512, "offset": 512, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
@@ -569,5 +556,6 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
+{"return": {}}
Images are identical.
*** done
diff --git a/tests/qemu-iotests/117.out b/tests/qemu-iotests/117.out
index 735ffd2..1cea9e0 100644
--- a/tests/qemu-iotests/117.out
+++ b/tests/qemu-iotests/117.out
@@ -18,8 +18,8 @@
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
{ 'execute': 'quit' }
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
No errors were found on the image.
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/tests/qemu-iotests/120.out b/tests/qemu-iotests/120.out
index 0744c1f..35d84a5 100644
--- a/tests/qemu-iotests/120.out
+++ b/tests/qemu-iotests/120.out
@@ -5,8 +5,8 @@
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 65536/65536 bytes at offset 0
diff --git a/tests/qemu-iotests/127.out b/tests/qemu-iotests/127.out
index 1685c48..dd8c4a8 100644
--- a/tests/qemu-iotests/127.out
+++ b/tests/qemu-iotests/127.out
@@ -28,6 +28,6 @@
{ 'execute': 'quit' }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "mirror"}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
*** done
diff --git a/tests/qemu-iotests/140.out b/tests/qemu-iotests/140.out
index 312f76d..3286644 100644
--- a/tests/qemu-iotests/140.out
+++ b/tests/qemu-iotests/140.out
@@ -19,6 +19,6 @@
qemu-io: can't open device nbd+unix:///drv?socket=SOCK_DIR/nbd: Requested export not available
server reported: export 'drv' not present
{ 'execute': 'quit' }
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
*** done
diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
index a37030e..a7d3985 100755
--- a/tests/qemu-iotests/141
+++ b/tests/qemu-iotests/141
@@ -1,9 +1,12 @@
-#!/usr/bin/env bash
+#!/usr/bin/env python3
# group: rw auto quick
#
# Test case for ejecting BDSs with block jobs still running on them
#
-# Copyright (C) 2016 Red Hat, Inc.
+# Originally written in bash by Hanna Czenczek, ported to Python by Stefan
+# Hajnoczi.
+#
+# Copyright Red Hat
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -19,177 +22,129 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-# creator
-owner=hreitz@redhat.com
+import iotests
-seq="$(basename $0)"
-echo "QA output created by $seq"
-
-status=1 # failure is the default!
-
-_cleanup()
-{
- _cleanup_qemu
- _cleanup_test_img
- for img in "$TEST_DIR"/{b,m,o}.$IMGFMT; do
- _rm_test_img "$img"
- done
-}
-trap "_cleanup; exit \$status" 0 1 2 3 15
-
-# get standard environment, filters and checks
-. ./common.rc
-. ./common.filter
-. ./common.qemu
-
-# Needs backing file and backing format support
-_supported_fmt qcow2 qed
-_supported_proto file
-_supported_os Linux
+# Common filters to mask values that vary in the test output
+QMP_FILTERS = [iotests.filter_qmp_testfiles, \
+ iotests.filter_qmp_imgfmt]
-test_blockjob()
-{
- _send_qemu_cmd $QEMU_HANDLE \
- "{'execute': 'blockdev-add',
- 'arguments': {
- 'node-name': 'drv0',
- 'driver': '$IMGFMT',
- 'file': {
- 'driver': 'file',
- 'filename': '$TEST_IMG'
- }}}" \
- 'return'
+class TestCase:
+ def __init__(self, name, vm, image_path, cancel_event):
+ self.name = name
+ self.vm = vm
+ self.image_path = image_path
+ self.cancel_event = cancel_event
- # If "$2" is an event, we may or may not see it before the
- # {"return": {}}. Therefore, filter the {"return": {}} out both
- # here and in the next command. (Naturally, if we do not see it
- # here, we will see it before the next command can be executed,
- # so it will appear in the next _send_qemu_cmd's output.)
- _send_qemu_cmd $QEMU_HANDLE \
- "$1" \
- "$2" \
- | _filter_img_create | _filter_qmp_empty_return
+ def __enter__(self):
+ iotests.log(f'=== Testing {self.name} ===')
+ self.vm.qmp_log('blockdev-add', \
+ node_name='drv0', \
+ driver=iotests.imgfmt, \
+ file={'driver': 'file', 'filename': self.image_path}, \
+ filters=QMP_FILTERS)
- # We want this to return an error because the block job is still running
- _send_qemu_cmd $QEMU_HANDLE \
- "{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}" \
- 'error' | _filter_generated_node_ids | _filter_qmp_empty_return
+ def __exit__(self, *exc_details):
+ # This is expected to fail because the job still exists
+ self.vm.qmp_log('blockdev-del', node_name='drv0', \
+ filters=[iotests.filter_qmp_generated_node_ids])
- _send_qemu_cmd $QEMU_HANDLE \
- "{'execute': 'block-job-cancel',
- 'arguments': {'device': 'job0'}}" \
- "$3"
+ self.vm.qmp_log('block-job-cancel', device='job0')
+ event = self.vm.event_wait(self.cancel_event)
+ iotests.log(event, filters=[iotests.filter_qmp_event])
- _send_qemu_cmd $QEMU_HANDLE \
- "{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}" \
- 'return'
-}
+ # This time it succeeds
+ self.vm.qmp_log('blockdev-del', node_name='drv0')
+
+ # Separate test cases in output
+ iotests.log('')
-TEST_IMG="$TEST_DIR/b.$IMGFMT" _make_test_img 1M
-TEST_IMG="$TEST_DIR/m.$IMGFMT" _make_test_img -b "$TEST_DIR/b.$IMGFMT" -F $IMGFMT 1M
-_make_test_img -b "$TEST_DIR/m.$IMGFMT" 1M -F $IMGFMT
+def main() -> None:
+ with iotests.FilePath('bottom', 'middle', 'top', 'target') as \
+ (bottom_path, middle_path, top_path, target_path), \
+ iotests.VM() as vm:
-_launch_qemu -nodefaults
+ iotests.log('Creating bottom <- middle <- top backing file chain...')
+ IMAGE_SIZE='1M'
+ iotests.qemu_img_create('-f', iotests.imgfmt, bottom_path, IMAGE_SIZE)
+ iotests.qemu_img_create('-f', iotests.imgfmt, \
+ '-F', iotests.imgfmt, \
+ '-b', bottom_path, \
+ middle_path, \
+ IMAGE_SIZE)
+ iotests.qemu_img_create('-f', iotests.imgfmt, \
+ '-F', iotests.imgfmt, \
+ '-b', middle_path, \
+ top_path, \
+ IMAGE_SIZE)
-_send_qemu_cmd $QEMU_HANDLE \
- "{'execute': 'qmp_capabilities'}" \
- 'return'
+ iotests.log('Starting VM...')
+ vm.add_args('-nodefaults')
+ vm.launch()
-echo
-echo '=== Testing drive-backup ==='
-echo
+ # drive-backup will not send BLOCK_JOB_READY by itself, and cancelling
+ # the job will consequently result in BLOCK_JOB_CANCELLED being
+ # emitted.
+ with TestCase('drive-backup', vm, top_path, 'BLOCK_JOB_CANCELLED'):
+ vm.qmp_log('drive-backup', \
+ job_id='job0', \
+ device='drv0', \
+ target=target_path, \
+ format=iotests.imgfmt, \
+ sync='none', \
+ filters=QMP_FILTERS)
-# drive-backup will not send BLOCK_JOB_READY by itself, and cancelling the job
-# will consequently result in BLOCK_JOB_CANCELLED being emitted.
+ # drive-mirror will send BLOCK_JOB_READY basically immediately, and
+ # cancelling the job will consequently result in BLOCK_JOB_COMPLETED
+ # being emitted.
+ with TestCase('drive-mirror', vm, top_path, 'BLOCK_JOB_COMPLETED'):
+ vm.qmp_log('drive-mirror', \
+ job_id='job0', \
+ device='drv0', \
+ target=target_path, \
+ format=iotests.imgfmt, \
+ sync='none', \
+ filters=QMP_FILTERS)
+ event = vm.event_wait('BLOCK_JOB_READY')
+ assert event is not None # silence mypy
+ iotests.log(event, filters=[iotests.filter_qmp_event])
-test_blockjob \
- "{'execute': 'drive-backup',
- 'arguments': {'job-id': 'job0',
- 'device': 'drv0',
- 'target': '$TEST_DIR/o.$IMGFMT',
- 'format': '$IMGFMT',
- 'sync': 'none'}}" \
- 'return' \
- '"status": "null"'
+ # An active block-commit will send BLOCK_JOB_READY basically
+ # immediately, and cancelling the job will consequently result in
+ # BLOCK_JOB_COMPLETED being emitted.
+ with TestCase('active block-commit', vm, top_path, \
+ 'BLOCK_JOB_COMPLETED'):
+ vm.qmp_log('block-commit', \
+ job_id='job0', \
+ device='drv0')
+ event = vm.event_wait('BLOCK_JOB_READY')
+ assert event is not None # silence mypy
+ iotests.log(event, filters=[iotests.filter_qmp_event])
-echo
-echo '=== Testing drive-mirror ==='
-echo
+ # Give block-commit something to work on, otherwise it would be done
+ # immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would
+ # work just fine without the block job still running.
+ iotests.qemu_io(middle_path, '-c', f'write 0 {IMAGE_SIZE}')
+ with TestCase('non-active block-commit', vm, top_path, \
+ 'BLOCK_JOB_CANCELLED'):
+ vm.qmp_log('block-commit', \
+ job_id='job0', \
+ device='drv0', \
+ top=middle_path, \
+ speed=1, \
+ filters=[iotests.filter_qmp_testfiles])
-# drive-mirror will send BLOCK_JOB_READY basically immediately, and cancelling
-# the job will consequently result in BLOCK_JOB_COMPLETED being emitted.
+ # Give block-stream something to work on, otherwise it would be done
+ # immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would
+ # work just fine without the block job still running.
+ iotests.qemu_io(bottom_path, '-c', f'write 0 {IMAGE_SIZE}')
+ with TestCase('block-stream', vm, top_path, 'BLOCK_JOB_CANCELLED'):
+ vm.qmp_log('block-stream', \
+ job_id='job0', \
+ device='drv0', \
+ speed=1)
-test_blockjob \
- "{'execute': 'drive-mirror',
- 'arguments': {'job-id': 'job0',
- 'device': 'drv0',
- 'target': '$TEST_DIR/o.$IMGFMT',
- 'format': '$IMGFMT',
- 'sync': 'none'}}" \
- 'BLOCK_JOB_READY' \
- '"status": "null"'
-
-echo
-echo '=== Testing active block-commit ==='
-echo
-
-# An active block-commit will send BLOCK_JOB_READY basically immediately, and
-# cancelling the job will consequently result in BLOCK_JOB_COMPLETED being
-# emitted.
-
-test_blockjob \
- "{'execute': 'block-commit',
- 'arguments': {'job-id': 'job0', 'device': 'drv0'}}" \
- 'BLOCK_JOB_READY' \
- '"status": "null"'
-
-echo
-echo '=== Testing non-active block-commit ==='
-echo
-
-# Give block-commit something to work on, otherwise it would be done
-# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just
-# fine without the block job still running.
-
-$QEMU_IO -c 'write 0 1M' "$TEST_DIR/m.$IMGFMT" | _filter_qemu_io
-
-test_blockjob \
- "{'execute': 'block-commit',
- 'arguments': {'job-id': 'job0',
- 'device': 'drv0',
- 'top': '$TEST_DIR/m.$IMGFMT',
- 'speed': 1}}" \
- 'return' \
- '"status": "null"'
-
-echo
-echo '=== Testing block-stream ==='
-echo
-
-# Give block-stream something to work on, otherwise it would be done
-# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just
-# fine without the block job still running.
-
-$QEMU_IO -c 'write 0 1M' "$TEST_DIR/b.$IMGFMT" | _filter_qemu_io
-
-# With some data to stream (and @speed set to 1), block-stream will not complete
-# until we send the block-job-cancel command.
-
-test_blockjob \
- "{'execute': 'block-stream',
- 'arguments': {'job-id': 'job0',
- 'device': 'drv0',
- 'speed': 1}}" \
- 'return' \
- '"status": "null"'
-
-_cleanup_qemu
-
-# success, all done
-echo "*** done"
-rm -f $seq.full
-status=0
+if __name__ == '__main__':
+ iotests.script_main(main, supported_fmts=['qcow2', 'qed'],
+ supported_protocols=['file'])
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
index 63203d9..91b7ba5 100644
--- a/tests/qemu-iotests/141.out
+++ b/tests/qemu-iotests/141.out
@@ -1,179 +1,69 @@
-QA output created by 141
-Formatting 'TEST_DIR/b.IMGFMT', fmt=IMGFMT size=1048576
-Formatting 'TEST_DIR/m.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/b.IMGFMT backing_fmt=IMGFMT
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.IMGFMT backing_fmt=IMGFMT
-{'execute': 'qmp_capabilities'}
-{"return": {}}
-
+Creating bottom <- middle <- top backing file chain...
+Starting VM...
=== Testing drive-backup ===
-
-{'execute': 'blockdev-add',
- 'arguments': {
- 'node-name': 'drv0',
- 'driver': 'IMGFMT',
- 'file': {
- 'driver': 'file',
- 'filename': 'TEST_DIR/t.IMGFMT'
- }}}
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
{"return": {}}
-{'execute': 'drive-backup',
-'arguments': {'job-id': 'job0',
-'device': 'drv0',
-'target': 'TEST_DIR/o.IMGFMT',
-'format': 'IMGFMT',
-'sync': 'none'}}
-Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"execute": "drive-backup", "arguments": {"device": "drv0", "format": "IMGFMT", "job-id": "job0", "sync": "none", "target": "TEST_DIR/PID-target"}}
+{"return": {}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'"}}
-{'execute': 'block-job-cancel',
- 'arguments': {'device': 'job0'}}
+{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"return": {}}
=== Testing drive-mirror ===
-
-{'execute': 'blockdev-add',
- 'arguments': {
- 'node-name': 'drv0',
- 'driver': 'IMGFMT',
- 'file': {
- 'driver': 'file',
- 'filename': 'TEST_DIR/t.IMGFMT'
- }}}
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
{"return": {}}
-{'execute': 'drive-mirror',
-'arguments': {'job-id': 'job0',
-'device': 'drv0',
-'target': 'TEST_DIR/o.IMGFMT',
-'format': 'IMGFMT',
-'sync': 'none'}}
-Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"execute": "drive-mirror", "arguments": {"device": "drv0", "format": "IMGFMT", "job-id": "job0", "sync": "none", "target": "TEST_DIR/PID-target"}}
+{"return": {}}
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}}
-{'execute': 'block-job-cancel',
- 'arguments': {'device': 'job0'}}
+{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"return": {}}
=== Testing active block-commit ===
-
-{'execute': 'blockdev-add',
- 'arguments': {
- 'node-name': 'drv0',
- 'driver': 'IMGFMT',
- 'file': {
- 'driver': 'file',
- 'filename': 'TEST_DIR/t.IMGFMT'
- }}}
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
{"return": {}}
-{'execute': 'block-commit',
-'arguments': {'job-id': 'job0', 'device': 'drv0'}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"execute": "block-commit", "arguments": {"device": "drv0", "job-id": "job0"}}
+{"return": {}}
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
-{'execute': 'block-job-cancel',
- 'arguments': {'device': 'job0'}}
+{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"return": {}}
=== Testing non-active block-commit ===
-
-wrote 1048576/1048576 bytes at offset 0
-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{'execute': 'blockdev-add',
- 'arguments': {
- 'node-name': 'drv0',
- 'driver': 'IMGFMT',
- 'file': {
- 'driver': 'file',
- 'filename': 'TEST_DIR/t.IMGFMT'
- }}}
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
{"return": {}}
-{'execute': 'block-commit',
-'arguments': {'job-id': 'job0',
-'device': 'drv0',
-'top': 'TEST_DIR/m.IMGFMT',
-'speed': 1}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"execute": "block-commit", "arguments": {"device": "drv0", "job-id": "job0", "speed": 1, "top": "TEST_DIR/PID-middle"}}
+{"return": {}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
-{'execute': 'block-job-cancel',
- 'arguments': {'device': 'job0'}}
+{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"return": {}}
=== Testing block-stream ===
-
-wrote 1048576/1048576 bytes at offset 0
-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{'execute': 'blockdev-add',
- 'arguments': {
- 'node-name': 'drv0',
- 'driver': 'IMGFMT',
- 'file': {
- 'driver': 'file',
- 'filename': 'TEST_DIR/t.IMGFMT'
- }}}
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
{"return": {}}
-{'execute': 'block-stream',
-'arguments': {'job-id': 'job0',
-'device': 'drv0',
-'speed': 1}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"execute": "block-stream", "arguments": {"device": "drv0", "job-id": "job0", "speed": 1}}
+{"return": {}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: stream"}}
-{'execute': 'block-job-cancel',
- 'arguments': {'device': 'job0'}}
+{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"return": {}}
-*** done
+
diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out
index 9ec5888..d6afa32 100644
--- a/tests/qemu-iotests/143.out
+++ b/tests/qemu-iotests/143.out
@@ -10,6 +10,6 @@
qemu-io: can't open device nbd+unix:///aa--aa1?socket=SOCK_DIR/nbd: Requested export not available
server reported: export 'aa--aa...' not present
{ 'execute': 'quit' }
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
*** done
diff --git a/tests/qemu-iotests/156.out b/tests/qemu-iotests/156.out
index 4a22f0c..07e5e83 100644
--- a/tests/qemu-iotests/156.out
+++ b/tests/qemu-iotests/156.out
@@ -72,8 +72,8 @@
{"return": ""}
{ 'execute': 'quit' }
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/tests/qemu-iotests/176.out b/tests/qemu-iotests/176.out
index 9d09b60..45e9153 100644
--- a/tests/qemu-iotests/176.out
+++ b/tests/qemu-iotests/176.out
@@ -169,8 +169,8 @@
{"return": {}}
{"return": {}}
{"return": {}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
wrote 196608/196608 bytes at offset 2147287040
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 131072/131072 bytes at offset 2147352576
@@ -206,8 +206,8 @@
{"return": {}}
{"return": {}}
{"return": {"sha256": HASH}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
=== Test pass bitmap.1 ===
@@ -218,8 +218,8 @@
{"return": {}}
{"return": {}}
{"return": {}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
wrote 196608/196608 bytes at offset 2147287040
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 131072/131072 bytes at offset 2147352576
@@ -256,8 +256,8 @@
{"return": {}}
{"return": {}}
{"return": {"sha256": HASH}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
=== Test pass bitmap.2 ===
@@ -268,8 +268,8 @@
{"return": {}}
{"return": {}}
{"return": {}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
wrote 196608/196608 bytes at offset 2147287040
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 131072/131072 bytes at offset 2147352576
@@ -306,8 +306,8 @@
{"return": {}}
{"return": {}}
{"return": {"sha256": HASH}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
=== Test pass bitmap.3 ===
@@ -318,8 +318,8 @@
{"return": {}}
{"return": {}}
{"return": {}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
wrote 196608/196608 bytes at offset 2147287040
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 131072/131072 bytes at offset 2147352576
@@ -353,6 +353,6 @@
{"return": {}}
{"return": {}}
{"return": {"sha256": HASH}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
*** done
diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out
index 57f7265..83fc1a4 100644
--- a/tests/qemu-iotests/182.out
+++ b/tests/qemu-iotests/182.out
@@ -53,6 +53,6 @@
{'execute': 'qmp_capabilities'}
{"return": {}}
{'execute': 'quit'}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
*** done
diff --git a/tests/qemu-iotests/183.out b/tests/qemu-iotests/183.out
index 9277643..8aef74a 100644
--- a/tests/qemu-iotests/183.out
+++ b/tests/qemu-iotests/183.out
@@ -53,11 +53,11 @@
=== Shut down and check image ===
{"execute":"quit"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"return": {}}
{"execute":"quit"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
No errors were found on the image.
No errors were found on the image.
wrote 65536/65536 bytes at offset 1048576
diff --git a/tests/qemu-iotests/184.out b/tests/qemu-iotests/184.out
index 77e5489..e8f631f 100644
--- a/tests/qemu-iotests/184.out
+++ b/tests/qemu-iotests/184.out
@@ -90,10 +90,6 @@
]
}
{
- "return": {
- }
-}
-{
"timestamp": {
"seconds": TIMESTAMP,
"microseconds": TIMESTAMP
@@ -104,6 +100,10 @@
"reason": "host-qmp-quit"
}
}
+{
+ "return": {
+ }
+}
== property changes in ThrottleGroup ==
@@ -170,10 +170,6 @@
}
}
{
- "return": {
- }
-}
-{
"timestamp": {
"seconds": TIMESTAMP,
"microseconds": TIMESTAMP
@@ -184,6 +180,10 @@
"reason": "host-qmp-quit"
}
}
+{
+ "return": {
+ }
+}
== object creation/set errors ==
@@ -212,10 +212,6 @@
}
}
{
- "return": {
- }
-}
-{
"timestamp": {
"seconds": TIMESTAMP,
"microseconds": TIMESTAMP
@@ -226,6 +222,10 @@
"reason": "host-qmp-quit"
}
}
+{
+ "return": {
+ }
+}
== don't specify group ==
@@ -248,10 +248,6 @@
}
}
{
- "return": {
- }
-}
-{
"timestamp": {
"seconds": TIMESTAMP,
"microseconds": TIMESTAMP
@@ -262,6 +258,10 @@
"reason": "host-qmp-quit"
}
}
+{
+ "return": {
+ }
+}
*** done
diff --git a/tests/qemu-iotests/185 b/tests/qemu-iotests/185
index 2ae0a85..17489fb 100755
--- a/tests/qemu-iotests/185
+++ b/tests/qemu-iotests/185
@@ -344,14 +344,14 @@
sleep 1
+ # List of expected events
+ capture_events='BLOCK_JOB_CANCELLED JOB_STATUS_CHANGE SHUTDOWN'
+
_send_qemu_cmd $h \
'{"execute": "quit"}' \
'return'
- # List of expected events
- capture_events='BLOCK_JOB_CANCELLED JOB_STATUS_CHANGE SHUTDOWN'
_wait_event $h 'SHUTDOWN'
- QEMU_EVENTS= # Ignore all JOB_STATUS_CHANGE events that came before SHUTDOWN
_wait_event $h 'JOB_STATUS_CHANGE' # standby
_wait_event $h 'JOB_STATUS_CHANGE' # ready
_wait_event $h 'JOB_STATUS_CHANGE' # standby
diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out
index 7292c26..6af0953 100644
--- a/tests/qemu-iotests/185.out
+++ b/tests/qemu-iotests/185.out
@@ -40,9 +40,16 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
{"return": {}}
{ 'execute': 'quit' }
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 524288, "speed": 65536, "type": "commit"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
+{"return": {}}
=== Start active commit job and exit qemu ===
@@ -56,9 +63,16 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
{"return": {}}
{ 'execute': 'quit' }
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "commit"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
+{"return": {}}
=== Start mirror job and exit qemu ===
@@ -75,9 +89,16 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
{"return": {}}
{ 'execute': 'quit' }
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "mirror"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
+{"return": {}}
=== Start backup job and exit qemu ===
@@ -97,9 +118,16 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
{"return": {}}
{ 'execute': 'quit' }
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 65536, "speed": 65536, "type": "backup"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
+{"return": {}}
=== Start streaming job and exit qemu ===
@@ -112,9 +140,16 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
{"return": {}}
{ 'execute': 'quit' }
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 524288, "speed": 65536, "type": "stream"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}}
+{"return": {}}
No errors were found on the image.
=== Start mirror to throttled QSD and exit qemu ===
diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out
index ea88777..c3309e4 100644
--- a/tests/qemu-iotests/191.out
+++ b/tests/qemu-iotests/191.out
@@ -379,10 +379,6 @@
}
{ 'execute': 'quit' }
{
- "return": {
- }
-}
-{
"timestamp": {
"seconds": TIMESTAMP,
"microseconds": TIMESTAMP
@@ -393,6 +389,10 @@
"reason": "host-qmp-quit"
}
}
+{
+ "return": {
+ }
+}
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 64 MiB (67108864 bytes)
@@ -797,10 +797,6 @@
}
{ 'execute': 'quit' }
{
- "return": {
- }
-}
-{
"timestamp": {
"seconds": TIMESTAMP,
"microseconds": TIMESTAMP
@@ -811,6 +807,10 @@
"reason": "host-qmp-quit"
}
}
+{
+ "return": {
+ }
+}
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 64 MiB (67108864 bytes)
diff --git a/tests/qemu-iotests/195.out b/tests/qemu-iotests/195.out
index ec84df5..91717d3 100644
--- a/tests/qemu-iotests/195.out
+++ b/tests/qemu-iotests/195.out
@@ -18,10 +18,6 @@
}
}
{
- "return": {
- }
-}
-{
"timestamp": {
"seconds": TIMESTAMP,
"microseconds": TIMESTAMP
@@ -32,6 +28,10 @@
"reason": "host-qmp-quit"
}
}
+{
+ "return": {
+ }
+}
image: TEST_DIR/t.IMGFMT.mid
file format: IMGFMT
@@ -56,10 +56,6 @@
}
}
{
- "return": {
- }
-}
-{
"timestamp": {
"seconds": TIMESTAMP,
"microseconds": TIMESTAMP
@@ -70,6 +66,10 @@
"reason": "host-qmp-quit"
}
}
+{
+ "return": {
+ }
+}
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out
index e5e7f42..5f5b42e 100644
--- a/tests/qemu-iotests/223.out
+++ b/tests/qemu-iotests/223.out
@@ -11,8 +11,8 @@
{"return": {}}
{"return": {}}
{"return": {}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
=== Write part of the file under active bitmap ===
@@ -145,14 +145,14 @@
{"execute":"nbd-server-remove",
"arguments":{"name":"n"}}
-{"return": {}}
-{"execute":"nbd-server-remove",
- "arguments":{"name":"n2"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}}
{"return": {}}
{"execute":"nbd-server-remove",
"arguments":{"name":"n2"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}}
+{"return": {}}
+{"execute":"nbd-server-remove",
+ "arguments":{"name":"n2"}}
{"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}}
{"execute":"nbd-server-stop"}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n3"}}
@@ -267,14 +267,14 @@
{"execute":"nbd-server-remove",
"arguments":{"name":"n"}}
-{"return": {}}
-{"execute":"nbd-server-remove",
- "arguments":{"name":"n2"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}}
{"return": {}}
{"execute":"nbd-server-remove",
"arguments":{"name":"n2"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}}
+{"return": {}}
+{"execute":"nbd-server-remove",
+ "arguments":{"name":"n2"}}
{"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}}
{"execute":"nbd-server-stop"}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n3"}}
@@ -282,8 +282,8 @@
{"execute":"nbd-server-stop"}
{"error": {"class": "GenericError", "desc": "NBD server not running"}}
{"execute":"quit"}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
=== Use qemu-nbd as server ===
diff --git a/tests/qemu-iotests/227.out b/tests/qemu-iotests/227.out
index a947b1a..d6a1d4e 100644
--- a/tests/qemu-iotests/227.out
+++ b/tests/qemu-iotests/227.out
@@ -55,10 +55,6 @@
]
}
{
- "return": {
- }
-}
-{
"timestamp": {
"seconds": TIMESTAMP,
"microseconds": TIMESTAMP
@@ -69,6 +65,10 @@
"reason": "host-qmp-quit"
}
}
+{
+ "return": {
+ }
+}
=== blockstats with -drive if=none ===
@@ -125,10 +125,6 @@
]
}
{
- "return": {
- }
-}
-{
"timestamp": {
"seconds": TIMESTAMP,
"microseconds": TIMESTAMP
@@ -139,6 +135,10 @@
"reason": "host-qmp-quit"
}
}
+{
+ "return": {
+ }
+}
=== blockstats with -blockdev ===
@@ -156,10 +156,6 @@
]
}
{
- "return": {
- }
-}
-{
"timestamp": {
"seconds": TIMESTAMP,
"microseconds": TIMESTAMP
@@ -170,6 +166,10 @@
"reason": "host-qmp-quit"
}
}
+{
+ "return": {
+ }
+}
=== blockstats with -blockdev and -device ===
@@ -227,10 +227,6 @@
]
}
{
- "return": {
- }
-}
-{
"timestamp": {
"seconds": TIMESTAMP,
"microseconds": TIMESTAMP
@@ -241,5 +237,9 @@
"reason": "host-qmp-quit"
}
}
+{
+ "return": {
+ }
+}
*** done
diff --git a/tests/qemu-iotests/247.out b/tests/qemu-iotests/247.out
index e909e83..7d252e7 100644
--- a/tests/qemu-iotests/247.out
+++ b/tests/qemu-iotests/247.out
@@ -17,6 +17,6 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
*** done
diff --git a/tests/qemu-iotests/264 b/tests/qemu-iotests/264
index c532ccd..c6ba275 100755
--- a/tests/qemu-iotests/264
+++ b/tests/qemu-iotests/264
@@ -25,7 +25,8 @@
import iotests
from iotests import qemu_img_create, file_path, qemu_nbd_popen
-disk_a, disk_b, nbd_sock = file_path('disk_a', 'disk_b', 'nbd-sock')
+disk_a, disk_b = file_path('disk_a', 'disk_b')
+nbd_sock = file_path('nbd-sock', base_dir=iotests.sock_dir)
nbd_uri = 'nbd+unix:///?socket=' + nbd_sock
wait_limit = 3.0
wait_step = 0.2
diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out
index 6a74a81..71843f0 100644
--- a/tests/qemu-iotests/273.out
+++ b/tests/qemu-iotests/273.out
@@ -283,10 +283,6 @@
}
}
{
- "return": {
- }
-}
-{
"timestamp": {
"seconds": TIMESTAMP,
"microseconds": TIMESTAMP
@@ -297,5 +293,9 @@
"reason": "host-qmp-quit"
}
}
+{
+ "return": {
+ }
+}
*** done
diff --git a/tests/qemu-iotests/277 b/tests/qemu-iotests/277
index 24833e7..4224202 100755
--- a/tests/qemu-iotests/277
+++ b/tests/qemu-iotests/277
@@ -27,7 +27,8 @@
iotests.script_initialize()
-nbd_sock, conf_file = file_path('nbd-sock', 'nbd-fault-injector.conf')
+conf_file = file_path('nbd-fault-injector.conf')
+nbd_sock = file_path('nbd-sock', base_dir=iotests.sock_dir)
def make_conf_file(event):
diff --git a/tests/qemu-iotests/308 b/tests/qemu-iotests/308
index de12b2b..ea81dc4 100755
--- a/tests/qemu-iotests/308
+++ b/tests/qemu-iotests/308
@@ -77,6 +77,7 @@
# $1: Export ID
fuse_export_del()
{
+ capture_events="BLOCK_EXPORT_DELETED" \
_send_qemu_cmd $QEMU_HANDLE \
"{'execute': 'block-export-del',
'arguments': {
@@ -84,8 +85,7 @@
} }" \
'return'
- _send_qemu_cmd $QEMU_HANDLE \
- '' \
+ _wait_event $QEMU_HANDLE \
'BLOCK_EXPORT_DELETED'
}
diff --git a/tests/qemu-iotests/308.out b/tests/qemu-iotests/308.out
index d576713..e5e2336 100644
--- a/tests/qemu-iotests/308.out
+++ b/tests/qemu-iotests/308.out
@@ -165,9 +165,9 @@
=== Tear down ===
{'execute': 'quit'}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export-mp"}}
+{"return": {}}
=== Compare copy with original ===
Images are identical.
@@ -201,9 +201,9 @@
read 67108864/67108864 bytes at offset 0
64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{'execute': 'quit'}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export"}}
+{"return": {}}
read 67108864/67108864 bytes at offset 0
64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
*** done
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index e5c5798..ea48af4 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -651,6 +651,13 @@
def filter_generated_node_ids(msg):
return re.sub("#block[0-9]+", "NODE_NAME", msg)
+def filter_qmp_generated_node_ids(qmsg):
+ def _filter(_key, value):
+ if is_str(value):
+ return filter_generated_node_ids(value)
+ return value
+ return filter_qmp(qmsg, _filter)
+
def filter_img_info(output: str, filename: str,
drop_child_info: bool = True) -> str:
lines = []
diff --git a/tests/qemu-iotests/tests/file-io-error b/tests/qemu-iotests/tests/file-io-error
index 88ee5f6..fb8db73 100755
--- a/tests/qemu-iotests/tests/file-io-error
+++ b/tests/qemu-iotests/tests/file-io-error
@@ -99,13 +99,12 @@
$QEMU_IO -f file -c 'write 0 64M' "$TEST_DIR/fuse-export" | _filter_qemu_io
echo
-_send_qemu_cmd $QEMU_HANDLE \
+capture_events=BLOCK_EXPORT_DELETED _send_qemu_cmd $QEMU_HANDLE \
"{'execute': 'block-export-del',
'arguments': {'id': 'exp0'}}" \
'return'
-_send_qemu_cmd $QEMU_HANDLE \
- '' \
+_wait_event $QEMU_HANDLE \
'BLOCK_EXPORT_DELETED'
_send_qemu_cmd $QEMU_HANDLE \
diff --git a/tests/qemu-iotests/tests/iothreads-resize.out b/tests/qemu-iotests/tests/iothreads-resize.out
index 2ca5a9d..2967ac8 100644
--- a/tests/qemu-iotests/tests/iothreads-resize.out
+++ b/tests/qemu-iotests/tests/iothreads-resize.out
@@ -3,8 +3,8 @@
QMP_VERSION
{"return": {}}
{"return": {}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 128 MiB (134217728 bytes)
diff --git a/tests/qemu-iotests/tests/iothreads-stream b/tests/qemu-iotests/tests/iothreads-stream
index 503f221..231195b 100755
--- a/tests/qemu-iotests/tests/iothreads-stream
+++ b/tests/qemu-iotests/tests/iothreads-stream
@@ -18,6 +18,7 @@
#
# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
+import asyncio
import iotests
iotests.script_initialize(supported_fmts=['qcow2'],
@@ -69,6 +70,6 @@
# The test is done once both jobs are gone
if finished == 2:
break
- except TimeoutError:
+ except asyncio.TimeoutError:
pass
vm.cmd('query-jobs')
diff --git a/tests/qemu-iotests/tests/qsd-jobs.out b/tests/qemu-iotests/tests/qsd-jobs.out
index c1bc9b8..aa6b6d1 100644
--- a/tests/qemu-iotests/tests/qsd-jobs.out
+++ b/tests/qemu-iotests/tests/qsd-jobs.out
@@ -7,8 +7,8 @@
QMP_VERSION
{"return": {}}
{"return": {}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+{"return": {}}
=== Streaming can't get permission on base node ===
@@ -17,6 +17,6 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
{"error": {"class": "GenericError", "desc": "Permission conflict on node 'fmt_base': permissions 'write' are both required by an unnamed block device (uses node 'fmt_base' as 'root' child) and unshared by stream job 'job0' (uses node 'fmt_base' as 'intermediate node' child)."}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export1"}}
+{"return": {}}
*** done
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index 0659532..cae925c 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -175,7 +175,8 @@
'test-aio-multithread' : 120,
'test-crypto-block' : 300,
'test-crypto-tlscredsx509': 45,
- 'test-crypto-tlssession': 45
+ 'test-crypto-tlssession': 45,
+ 'test-replication': 60,
}
foreach test_name, extra: tests
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
index 17830a6..6668804 100644
--- a/tests/unit/test-bdrv-drain.c
+++ b/tests/unit/test-bdrv-drain.c
@@ -1591,6 +1591,7 @@
static int drop_intermediate_poll_update_filename(BdrvChild *child,
BlockDriverState *new_base,
const char *filename,
+ bool backing_mask_protocol,
Error **errp)
{
/*
@@ -1702,7 +1703,7 @@
job->should_complete = true;
g_assert(!job_has_completed);
- ret = bdrv_drop_intermediate(chain[1], chain[0], NULL);
+ ret = bdrv_drop_intermediate(chain[1], chain[0], NULL, false);
aio_poll(qemu_get_aio_context(), false);
g_assert(ret == 0);
g_assert(job_has_completed);
diff --git a/util/yank.c b/util/yank.c
index abf47c3..eaac505 100644
--- a/util/yank.c
+++ b/util/yank.c
@@ -35,7 +35,7 @@
/*
* This lock protects the yank_instance_list below. Because it's taken by
* OOB-capable commands, it must be "fast", i.e. it may only be held for a
- * bounded, short time. See docs/devel/qapi-code-gen.txt for additional
+ * bounded, short time. See docs/devel/qapi-code-gen.rst for additional
* information.
*/
static QemuMutex yank_lock;