summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS9
-rw-r--r--accel/tcg/user-exec.c3
-rw-r--r--block.c208
-rw-r--r--block/file-posix.c2
-rw-r--r--block/gluster.c4
-rw-r--r--block/io.c130
-rw-r--r--block/meson.build1
-rw-r--r--block/nfs.c2
-rw-r--r--block/nvme.c24
-rw-r--r--block/preallocate.c559
-rw-r--r--block/qapi.c7
-rw-r--r--block/quorum.c88
-rw-r--r--block/rbd.c2
-rw-r--r--block/vpc.c146
-rw-r--r--bsd-user/main.c1
-rw-r--r--chardev/char.c20
-rwxr-xr-xconfigure1
-rw-r--r--contrib/rdmacm-mux/main.c2
-rw-r--r--disas/libvixl/vixl/a64/disasm-a64.cc4
-rw-r--r--disas/libvixl/vixl/globals.h6
-rw-r--r--docs/devel/migration.rst11
-rw-r--r--docs/devel/writing-qmp-commands.txt12
-rw-r--r--docs/interop/conf.py2
-rw-r--r--docs/interop/index.rst1
-rw-r--r--docs/interop/qemu-storage-daemon-qmp-ref.rst13
-rw-r--r--docs/meson.build1
-rw-r--r--docs/system/qemu-block-drivers.rst.inc26
-rw-r--r--docs/tools/conf.py2
-rw-r--r--docs/tools/index.rst1
-rw-r--r--docs/tools/qemu-storage-daemon.rst148
-rw-r--r--docs/user/main.rst99
-rw-r--r--hmp-commands.hx12
-rw-r--r--hw/block/nand.c12
-rw-r--r--hw/core/machine-qmp-cmds.c6
-rw-r--r--hw/core/machine.c11
-rw-r--r--hw/core/register.c16
-rw-r--r--hw/display/virtio-gpu.c2
-rw-r--r--hw/intc/arm_gicv3_kvm.c8
-rw-r--r--hw/intc/ibex_plic.c13
-rw-r--r--hw/intc/s390_flic_kvm.c2
-rw-r--r--hw/net/rocker/rocker.c8
-rw-r--r--hw/net/rocker/rocker_fp.c17
-rw-r--r--hw/net/rocker/rocker_fp.h2
-rw-r--r--hw/net/rocker/rocker_of_dpa.c20
-rw-r--r--hw/net/virtio-net.c21
-rw-r--r--hw/nvram/eeprom93xx.c2
-rw-r--r--hw/nvram/fw_cfg.c2
-rw-r--r--hw/pci/msix.c2
-rw-r--r--hw/pci/pci.c4
-rw-r--r--hw/pci/shpc.c2
-rw-r--r--hw/rdma/rdma_backend.c10
-rw-r--r--hw/rdma/rdma_backend_defs.h2
-rw-r--r--hw/rdma/rdma_utils.c29
-rw-r--r--hw/rdma/rdma_utils.h15
-rw-r--r--hw/riscv/boot.c70
-rw-r--r--hw/riscv/microchip_pfsoc.c21
-rw-r--r--hw/riscv/opentitan.c81
-rw-r--r--hw/riscv/sifive_u.c74
-rw-r--r--hw/riscv/spike.c52
-rw-r--r--hw/riscv/virt.c39
-rw-r--r--hw/rtc/twl92230.c46
-rw-r--r--hw/scsi/scsi-bus.c2
-rw-r--r--hw/timer/renesas_tmr.c1
-rw-r--r--hw/usb/redirect.c7
-rw-r--r--hw/virtio/virtio.c4
-rw-r--r--include/block/block.h20
-rw-r--r--include/block/block_int.h3
-rw-r--r--include/hw/riscv/boot.h14
-rw-r--r--include/hw/riscv/microchip_pfsoc.h3
-rw-r--r--include/hw/riscv/opentitan.h23
-rw-r--r--include/hw/riscv/spike.h6
-rw-r--r--include/hw/riscv/virt.h6
-rw-r--r--include/migration/vmstate.h7
-rw-r--r--include/qapi/qmp/json-writer.h35
-rw-r--r--include/qapi/qmp/qbool.h2
-rw-r--r--include/qapi/qmp/qdict.h2
-rw-r--r--include/qapi/qmp/qjson.h4
-rw-r--r--include/qapi/qmp/qlist.h2
-rw-r--r--include/qapi/qmp/qnull.h2
-rw-r--r--include/qapi/qmp/qnum.h3
-rw-r--r--include/qapi/qmp/qobject.h9
-rw-r--r--include/qapi/qmp/qstring.h14
-rw-r--r--include/qemu/compiler.h11
-rw-r--r--include/qemu/typedefs.h4
-rw-r--r--linux-user/elfload.c43
-rw-r--r--linux-user/ioctls.h46
-rw-r--r--linux-user/mmap.c21
-rw-r--r--linux-user/sparc/signal.c87
-rw-r--r--linux-user/syscall.c79
-rw-r--r--linux-user/syscall_defs.h32
-rw-r--r--migration/meson.build1
-rw-r--r--migration/migration.c35
-rw-r--r--migration/postcopy-ram.c7
-rw-r--r--migration/qjson.c114
-rw-r--r--migration/qjson.h29
-rw-r--r--migration/savevm.c64
-rw-r--r--migration/vmstate-types.c38
-rw-r--r--migration/vmstate.c52
-rw-r--r--monitor/hmp-cmds.c16
-rw-r--r--monitor/misc.c47
-rw-r--r--monitor/monitor-internal.h2
-rw-r--r--monitor/monitor.c20
-rw-r--r--monitor/qmp-cmds-control.c10
-rw-r--r--monitor/qmp.c46
-rw-r--r--qapi/block-core.json20
-rw-r--r--qapi/string-output-visitor.c2
-rw-r--r--qemu-img.c38
-rw-r--r--qemu-io-cmds.c46
-rw-r--r--qga/commands-posix-ssh.c7
-rw-r--r--qga/commands-posix.c47
-rw-r--r--qga/commands-win32.c32
-rw-r--r--qga/commands.c6
-rw-r--r--qga/main.c22
-rw-r--r--qobject/json-parser.c30
-rw-r--r--qobject/json-writer.c247
-rw-r--r--qobject/meson.build5
-rw-r--r--qobject/qbool.c1
-rw-r--r--qobject/qdict.c1
-rw-r--r--qobject/qjson.c146
-rw-r--r--qobject/qlist.c1
-rw-r--r--qobject/qnull.c1
-rw-r--r--qobject/qnum.c28
-rw-r--r--qobject/qobject-internal.h39
-rw-r--r--qobject/qobject.c1
-rw-r--r--qobject/qstring.c113
-rw-r--r--qom/object.c9
-rw-r--r--qom/object_interfaces.c4
-rw-r--r--qom/qom-hmp-cmds.c7
-rw-r--r--qom/qom-qmp-cmds.c29
-rw-r--r--scripts/simplebench/bench-example.py3
-rwxr-xr-xscripts/simplebench/bench_prealloc.py132
-rwxr-xr-xscripts/simplebench/bench_write_req.py3
-rwxr-xr-xscripts/simplebench/results_to_text.py126
-rw-r--r--scripts/simplebench/simplebench.py66
-rw-r--r--storage-daemon/qapi/qapi-schema.json3
-rw-r--r--target/alpha/machine.c2
-rw-r--r--target/arm/helper.c6
-rw-r--r--target/arm/machine.c6
-rw-r--r--target/arm/monitor.c13
-rw-r--r--target/avr/machine.c4
-rw-r--r--target/hppa/machine.c4
-rw-r--r--target/i386/cpu.c6
-rw-r--r--target/i386/tcg/translate.c7
-rw-r--r--target/microblaze/machine.c2
-rw-r--r--target/mips/cpu.c6
-rw-r--r--target/mips/cpu.h1
-rw-r--r--target/mips/machine.c4
-rw-r--r--target/openrisc/machine.c2
-rw-r--r--target/ppc/machine.c10
-rw-r--r--target/ppc/translate_init.c.inc12
-rw-r--r--target/riscv/cpu.c84
-rw-r--r--target/riscv/cpu.h8
-rw-r--r--target/riscv/cpu_bits.h8
-rw-r--r--target/riscv/cpu_helper.c15
-rw-r--r--target/riscv/csr.c176
-rw-r--r--target/riscv/fpu_helper.c8
-rw-r--r--target/riscv/helper.h24
-rw-r--r--target/s390x/cpu_models.c12
-rw-r--r--target/sparc/cpu.h28
-rw-r--r--target/sparc/int64_helper.c5
-rw-r--r--target/sparc/machine.c2
-rw-r--r--target/sparc/translate.c2
-rw-r--r--target/sparc/win_helper.c2
-rw-r--r--target/unicore32/translate.c2
-rw-r--r--tcg/optimize.c4
-rw-r--r--tests/check-qjson.c195
-rw-r--r--tests/check-qnum.c8
-rw-r--r--tests/check-qobject.c3
-rw-r--r--tests/check-qstring.c16
-rw-r--r--tests/fp/meson.build2
-rw-r--r--tests/qemu-iotests/085.out167
-rw-r--r--tests/qemu-iotests/094.out10
-rw-r--r--tests/qemu-iotests/095.out4
-rwxr-xr-xtests/qemu-iotests/1022
-rw-r--r--tests/qemu-iotests/102.out2
-rw-r--r--tests/qemu-iotests/109.out88
-rw-r--r--tests/qemu-iotests/117.out13
-rw-r--r--tests/qemu-iotests/127.out12
-rw-r--r--tests/qemu-iotests/140.out10
-rw-r--r--tests/qemu-iotests/141.out128
-rw-r--r--tests/qemu-iotests/143.out4
-rw-r--r--tests/qemu-iotests/144.out28
-rw-r--r--tests/qemu-iotests/153.out18
-rw-r--r--tests/qemu-iotests/156.out39
-rw-r--r--tests/qemu-iotests/161.out18
-rwxr-xr-xtests/qemu-iotests/1722
-rw-r--r--tests/qemu-iotests/172.out152
-rw-r--r--tests/qemu-iotests/173.out25
-rw-r--r--tests/qemu-iotests/182.out42
-rw-r--r--tests/qemu-iotests/183.out19
-rw-r--r--tests/qemu-iotests/185.out45
-rw-r--r--tests/qemu-iotests/186.out56
-rw-r--r--tests/qemu-iotests/191.out12
-rw-r--r--tests/qemu-iotests/210.out2
-rw-r--r--tests/qemu-iotests/223.out92
-rw-r--r--tests/qemu-iotests/229.out13
-rw-r--r--tests/qemu-iotests/249.out16
-rw-r--r--tests/qemu-iotests/298186
-rw-r--r--tests/qemu-iotests/298.out5
-rw-r--r--tests/qemu-iotests/308.out103
-rwxr-xr-xtests/qemu-iotests/312159
-rw-r--r--tests/qemu-iotests/312.out81
-rw-r--r--tests/qemu-iotests/common.filter2
-rw-r--r--tests/qemu-iotests/common.qemu11
-rw-r--r--tests/qemu-iotests/group2
-rw-r--r--tests/qemu-iotests/iotests.py16
-rw-r--r--tests/qtest/libqtest.c20
-rw-r--r--tests/test-clone-visitor.c7
-rw-r--r--tests/test-qobject-output-visitor.c48
-rw-r--r--tests/test-string-output-visitor.c4
-rw-r--r--tests/test-visitor-serialization.c181
-rw-r--r--tools/virtiofsd/fuse_lowlevel.c98
-rw-r--r--tools/virtiofsd/fuse_virtio.c36
-rw-r--r--tools/virtiofsd/passthrough_ll.c91
-rw-r--r--trace/qmp.c22
-rw-r--r--ui/input.c16
-rw-r--r--ui/vnc.c21
-rw-r--r--util/keyval.c11
-rw-r--r--util/qemu-config.c14
219 files changed, 4655 insertions, 2511 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 1e7c8f0488..0e139d9612 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2165,6 +2165,15 @@ F: qobject/block-qdict.c
F: tests/check-block-qdict.c
T: git https://repo.or.cz/qemu/kevin.git block
+Storage daemon
+M: Kevin Wolf <kwolf@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: storage-daemon/
+F: docs/interop/qemu-storage-daemon-qmp-ref.rst
+F: docs/tools/qemu-storage-daemon.rst
+T: git https://repo.or.cz/qemu/kevin.git block
+
Block I/O path
M: Stefan Hajnoczi <stefanha@redhat.com>
M: Fam Zheng <fam@euphon.net>
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 4ebe25461a..293ee86ea4 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -49,7 +49,8 @@ __thread uintptr_t helper_retaddr;
/* exit the current TB from a signal handler. The host registers are
restored in a state compatible with the CPU emulator
*/
-static void cpu_exit_tb_from_sighandler(CPUState *cpu, sigset_t *old_set)
+static void QEMU_NORETURN cpu_exit_tb_from_sighandler(CPUState *cpu,
+ sigset_t *old_set)
{
/* XXX: use siglongjmp ? */
sigprocmask(SIG_SETMASK, old_set, NULL);
diff --git a/block.c b/block.c
index 8f177504d4..8b9d457546 100644
--- a/block.c
+++ b/block.c
@@ -217,7 +217,7 @@ void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
/* Stripping the explicit protocol prefix may result in a protocol
* prefix being (wrongly) detected (if the filename contains a colon) */
if (path_has_protocol(filename)) {
- QString *fat_filename;
+ GString *fat_filename;
/* This means there is some colon before the first slash; therefore,
* this cannot be an absolute path */
@@ -225,12 +225,13 @@ void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
/* And we can thus fix the protocol detection issue by prefixing it
* by "./" */
- fat_filename = qstring_from_str("./");
- qstring_append(fat_filename, filename);
+ fat_filename = g_string_new("./");
+ g_string_append(fat_filename, filename);
- assert(!path_has_protocol(qstring_get_str(fat_filename)));
+ assert(!path_has_protocol(fat_filename->str));
- qdict_put(options, "filename", fat_filename);
+ qdict_put(options, "filename",
+ qstring_from_gstring(fat_filename));
} else {
/* If no protocol prefix was detected, we can use the shortened
* filename as-is */
@@ -1900,10 +1901,9 @@ static int bdrv_fill_options(QDict **options, const char *filename,
static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
uint64_t perm, uint64_t shared,
- GSList *ignore_children,
- bool *tighten_restrictions, Error **errp);
+ GSList *ignore_children, Error **errp);
static void bdrv_child_abort_perm_update(BdrvChild *c);
-static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared);
+static void bdrv_child_set_perm(BdrvChild *c);
typedef struct BlockReopenQueueEntry {
bool prepared;
@@ -1974,43 +1974,18 @@ static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
* permissions of all its parents. This involves checking whether all necessary
* permission changes to child nodes can be performed.
*
- * Will set *tighten_restrictions to true if and only if new permissions have to
- * be taken or currently shared permissions are to be unshared. Otherwise,
- * errors are not fatal as long as the caller accepts that the restrictions
- * remain tighter than they need to be. The caller still has to abort the
- * transaction.
- * @tighten_restrictions cannot be used together with @q: When reopening, we may
- * encounter fatal errors even though no restrictions are to be tightened. For
- * example, changing a node from RW to RO will fail if the WRITE permission is
- * to be kept.
- *
* A call to this function must always be followed by a call to bdrv_set_perm()
* or bdrv_abort_perm_update().
*/
static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
uint64_t cumulative_perms,
uint64_t cumulative_shared_perms,
- GSList *ignore_children,
- bool *tighten_restrictions, Error **errp)
+ GSList *ignore_children, Error **errp)
{
BlockDriver *drv = bs->drv;
BdrvChild *c;
int ret;
- assert(!q || !tighten_restrictions);
-
- if (tighten_restrictions) {
- uint64_t current_perms, current_shared;
- uint64_t added_perms, removed_shared_perms;
-
- bdrv_get_cumulative_perm(bs, &current_perms, &current_shared);
-
- added_perms = cumulative_perms & ~current_perms;
- removed_shared_perms = current_shared & ~cumulative_shared_perms;
-
- *tighten_restrictions = added_perms || removed_shared_perms;
- }
-
/* Write permissions never work with read-only images */
if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) &&
!bdrv_is_writable_after_reopen(bs, q))
@@ -2054,8 +2029,11 @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
}
if (drv->bdrv_check_perm) {
- return drv->bdrv_check_perm(bs, cumulative_perms,
- cumulative_shared_perms, errp);
+ ret = drv->bdrv_check_perm(bs, cumulative_perms,
+ cumulative_shared_perms, errp);
+ if (ret < 0) {
+ return ret;
+ }
}
/* Drivers that never have children can omit .bdrv_child_perm() */
@@ -2067,18 +2045,12 @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
/* Check all children */
QLIST_FOREACH(c, &bs->children, next) {
uint64_t cur_perm, cur_shared;
- bool child_tighten_restr;
bdrv_child_perm(bs, c->bs, c, c->role, q,
cumulative_perms, cumulative_shared_perms,
&cur_perm, &cur_shared);
ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children,
- tighten_restrictions ? &child_tighten_restr
- : NULL,
errp);
- if (tighten_restrictions) {
- *tighten_restrictions |= child_tighten_restr;
- }
if (ret < 0) {
return ret;
}
@@ -2112,9 +2084,9 @@ static void bdrv_abort_perm_update(BlockDriverState *bs)
}
}
-static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
- uint64_t cumulative_shared_perms)
+static void bdrv_set_perm(BlockDriverState *bs)
{
+ uint64_t cumulative_perms, cumulative_shared_perms;
BlockDriver *drv = bs->drv;
BdrvChild *c;
@@ -2122,6 +2094,8 @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
return;
}
+ bdrv_get_cumulative_perm(bs, &cumulative_perms, &cumulative_shared_perms);
+
/* Update this node */
if (drv->bdrv_set_perm) {
drv->bdrv_set_perm(bs, cumulative_perms, cumulative_shared_perms);
@@ -2135,11 +2109,7 @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
/* Update all children */
QLIST_FOREACH(c, &bs->children, next) {
- uint64_t cur_perm, cur_shared;
- bdrv_child_perm(bs, c->bs, c, c->role, NULL,
- cumulative_perms, cumulative_shared_perms,
- &cur_perm, &cur_shared);
- bdrv_child_set_perm(c, cur_perm, cur_shared);
+ bdrv_child_set_perm(c);
}
}
@@ -2203,22 +2173,18 @@ char *bdrv_perm_names(uint64_t perm)
* set, the BdrvChild objects in this list are ignored in the calculations;
* this allows checking permission updates for an existing reference.
*
- * See bdrv_check_perm() for the semantics of @tighten_restrictions.
- *
* Needs to be followed by a call to either bdrv_set_perm() or
* bdrv_abort_perm_update(). */
static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
uint64_t new_used_perm,
uint64_t new_shared_perm,
GSList *ignore_children,
- bool *tighten_restrictions,
Error **errp)
{
BdrvChild *c;
uint64_t cumulative_perms = new_used_perm;
uint64_t cumulative_shared_perms = new_shared_perm;
- assert(!q || !tighten_restrictions);
/* There is no reason why anyone couldn't tolerate write_unchanged */
assert(new_shared_perm & BLK_PERM_WRITE_UNCHANGED);
@@ -2232,10 +2198,6 @@ static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
char *user = bdrv_child_user_desc(c);
char *perm_names = bdrv_perm_names(new_used_perm & ~c->shared_perm);
- if (tighten_restrictions) {
- *tighten_restrictions = true;
- }
-
error_setg(errp, "Conflicts with use by %s as '%s', which does not "
"allow '%s' on %s",
user, c->name, perm_names, bdrv_get_node_name(c->bs));
@@ -2248,10 +2210,6 @@ static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
char *user = bdrv_child_user_desc(c);
char *perm_names = bdrv_perm_names(c->perm & ~new_shared_perm);
- if (tighten_restrictions) {
- *tighten_restrictions = true;
- }
-
error_setg(errp, "Conflicts with use by %s as '%s', which uses "
"'%s' on %s",
user, c->name, perm_names, bdrv_get_node_name(c->bs));
@@ -2265,21 +2223,19 @@ static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
}
return bdrv_check_perm(bs, q, cumulative_perms, cumulative_shared_perms,
- ignore_children, tighten_restrictions, errp);
+ ignore_children, errp);
}
/* Needs to be followed by a call to either bdrv_child_set_perm() or
* bdrv_child_abort_perm_update(). */
static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
uint64_t perm, uint64_t shared,
- GSList *ignore_children,
- bool *tighten_restrictions, Error **errp)
+ GSList *ignore_children, Error **errp)
{
int ret;
ignore_children = g_slist_prepend(g_slist_copy(ignore_children), c);
- ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children,
- tighten_restrictions, errp);
+ ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children, errp);
g_slist_free(ignore_children);
if (ret < 0) {
@@ -2302,18 +2258,11 @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
return 0;
}
-static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared)
+static void bdrv_child_set_perm(BdrvChild *c)
{
- uint64_t cumulative_perms, cumulative_shared_perms;
-
c->has_backup_perm = false;
- c->perm = perm;
- c->shared_perm = shared;
-
- bdrv_get_cumulative_perm(c->bs, &cumulative_perms,
- &cumulative_shared_perms);
- bdrv_set_perm(c->bs, cumulative_perms, cumulative_shared_perms);
+ bdrv_set_perm(c->bs);
}
static void bdrv_child_abort_perm_update(BdrvChild *c)
@@ -2327,18 +2276,33 @@ static void bdrv_child_abort_perm_update(BdrvChild *c)
bdrv_abort_perm_update(c->bs);
}
+static int bdrv_refresh_perms(BlockDriverState *bs, Error **errp)
+{
+ int ret;
+ uint64_t perm, shared_perm;
+
+ bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
+ ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, errp);
+ if (ret < 0) {
+ bdrv_abort_perm_update(bs);
+ return ret;
+ }
+ bdrv_set_perm(bs);
+
+ return 0;
+}
+
int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
Error **errp)
{
Error *local_err = NULL;
int ret;
- bool tighten_restrictions;
- ret = bdrv_child_check_perm(c, NULL, perm, shared, NULL,
- &tighten_restrictions, &local_err);
+ ret = bdrv_child_check_perm(c, NULL, perm, shared, NULL, &local_err);
if (ret < 0) {
bdrv_child_abort_perm_update(c);
- if (tighten_restrictions) {
+ if ((perm & ~c->perm) || (c->shared_perm & ~shared)) {
+ /* tighten permissions */
error_propagate(errp, local_err);
} else {
/*
@@ -2353,7 +2317,7 @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
return ret;
}
- bdrv_child_set_perm(c, perm, shared);
+ bdrv_child_set_perm(c);
return 0;
}
@@ -2623,7 +2587,6 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
{
BlockDriverState *old_bs = child->bs;
- uint64_t perm, shared_perm;
/* Asserts that child->frozen == false */
bdrv_replace_child_noperm(child, new_bs);
@@ -2637,27 +2600,16 @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
* restrictions.
*/
if (new_bs) {
- bdrv_get_cumulative_perm(new_bs, &perm, &shared_perm);
- bdrv_set_perm(new_bs, perm, shared_perm);
+ bdrv_set_perm(new_bs);
}
if (old_bs) {
- /* Update permissions for old node. This is guaranteed to succeed
- * because we're just taking a parent away, so we're loosening
- * restrictions. */
- bool tighten_restrictions;
- int ret;
-
- bdrv_get_cumulative_perm(old_bs, &perm, &shared_perm);
- ret = bdrv_check_perm(old_bs, NULL, perm, shared_perm, NULL,
- &tighten_restrictions, NULL);
- assert(tighten_restrictions == false);
- if (ret < 0) {
- /* We only tried to loosen restrictions, so errors are not fatal */
- bdrv_abort_perm_update(old_bs);
- } else {
- bdrv_set_perm(old_bs, perm, shared_perm);
- }
+ /*
+ * Update permissions for old node. We're just taking a parent away, so
+ * we're loosening restrictions. Errors of permission update are not
+ * fatal in this case, ignore them.
+ */
+ bdrv_refresh_perms(old_bs, NULL);
/* When the parent requiring a non-default AioContext is removed, the
* node moves back to the main AioContext */
@@ -2687,8 +2639,7 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
Error *local_err = NULL;
int ret;
- ret = bdrv_check_update_perm(child_bs, NULL, perm, shared_perm, NULL, NULL,
- errp);
+ ret = bdrv_check_update_perm(child_bs, NULL, perm, shared_perm, NULL, errp);
if (ret < 0) {
bdrv_abort_perm_update(child_bs);
bdrv_unref(child_bs);
@@ -3820,7 +3771,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
QTAILQ_FOREACH(bs_entry, bs_queue, entry) {
BDRVReopenState *state = &bs_entry->state;
ret = bdrv_check_perm(state->bs, bs_queue, state->perm,
- state->shared_perm, NULL, NULL, errp);
+ state->shared_perm, NULL, errp);
if (ret < 0) {
goto cleanup_perm;
}
@@ -3832,7 +3783,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
bs_queue, state->perm, state->shared_perm,
&nperm, &nshared);
ret = bdrv_check_update_perm(state->new_backing_bs, NULL,
- nperm, nshared, NULL, NULL, errp);
+ nperm, nshared, NULL, errp);
if (ret < 0) {
goto cleanup_perm;
}
@@ -3863,7 +3814,13 @@ cleanup_perm:
}
if (ret == 0) {
- bdrv_set_perm(state->bs, state->perm, state->shared_perm);
+ uint64_t perm, shared;
+
+ bdrv_get_cumulative_perm(state->bs, &perm, &shared);
+ assert(perm == state->perm);
+ assert(shared == state->shared_perm);
+
+ bdrv_set_perm(state->bs);
} else {
bdrv_abort_perm_update(state->bs);
if (state->replace_backing_bs && state->new_backing_bs) {
@@ -4021,7 +3978,7 @@ static int bdrv_reopen_parse_backing(BDRVReopenState *reopen_state,
new_backing_bs = NULL;
break;
case QTYPE_QSTRING:
- str = qobject_get_try_str(value);
+ str = qstring_get_str(qobject_to(QString, value));
new_backing_bs = bdrv_lookup_bs(NULL, str, errp);
if (new_backing_bs == NULL) {
return -EINVAL;
@@ -4284,8 +4241,8 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
}
if (child) {
- const char *str = qobject_get_try_str(new);
- if (!strcmp(child->bs->node_name, str)) {
+ if (!strcmp(child->bs->node_name,
+ qstring_get_str(qobject_to(QString, new)))) {
continue; /* Found child with this name, skip option */
}
}
@@ -4616,7 +4573,7 @@ static void bdrv_replace_node_common(BlockDriverState *from,
/* Check whether the required permissions can be granted on @to, ignoring
* all BdrvChild in @list so that they can't block themselves. */
- ret = bdrv_check_update_perm(to, NULL, perm, shared, list, NULL, errp);
+ ret = bdrv_check_update_perm(to, NULL, perm, shared, list, errp);
if (ret < 0) {
bdrv_abort_perm_update(to);
goto out;
@@ -4633,8 +4590,7 @@ static void bdrv_replace_node_common(BlockDriverState *from,
bdrv_unref(from);
}
- bdrv_get_cumulative_perm(to, &perm, &shared);
- bdrv_set_perm(to, perm, shared);
+ bdrv_set_perm(to);
out:
g_slist_free(list);
@@ -5781,7 +5737,6 @@ void bdrv_init_with_whitelist(void)
int coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp)
{
BdrvChild *child, *parent;
- uint64_t perm, shared_perm;
Error *local_err = NULL;
int ret;
BdrvDirtyBitmap *bm;
@@ -5813,14 +5768,11 @@ int coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp)
*/
if (bs->open_flags & BDRV_O_INACTIVE) {
bs->open_flags &= ~BDRV_O_INACTIVE;
- bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
- ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, NULL, errp);
+ ret = bdrv_refresh_perms(bs, errp);
if (ret < 0) {
- bdrv_abort_perm_update(bs);
bs->open_flags |= BDRV_O_INACTIVE;
return ret;
}
- bdrv_set_perm(bs, perm, shared_perm);
if (bs->drv->bdrv_co_invalidate_cache) {
bs->drv->bdrv_co_invalidate_cache(bs, &local_err);
@@ -5895,8 +5847,6 @@ static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
static int bdrv_inactivate_recurse(BlockDriverState *bs)
{
BdrvChild *child, *parent;
- bool tighten_restrictions;
- uint64_t perm, shared_perm;
int ret;
if (!bs->drv) {
@@ -5930,18 +5880,12 @@ static int bdrv_inactivate_recurse(BlockDriverState *bs)
bs->open_flags |= BDRV_O_INACTIVE;
- /* Update permissions, they may differ for inactive nodes */
- bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
- ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL,
- &tighten_restrictions, NULL);
- assert(tighten_restrictions == false);
- if (ret < 0) {
- /* We only tried to loosen restrictions, so errors are not fatal */
- bdrv_abort_perm_update(bs);
- } else {
- bdrv_set_perm(bs, perm, shared_perm);
- }
-
+ /*
+ * Update permissions, they may differ for inactive nodes.
+ * We only tried to loosen restrictions, so errors are not fatal, ignore
+ * them.
+ */
+ bdrv_refresh_perms(bs, NULL);
/* Recursively inactivate children */
QLIST_FOREACH(child, &bs->children, next) {
@@ -6995,13 +6939,13 @@ void bdrv_refresh_filename(BlockDriverState *bs)
if (bs->exact_filename[0]) {
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
} else {
- QString *json = qobject_to_json(QOBJECT(bs->full_open_options));
+ GString *json = qobject_to_json(QOBJECT(bs->full_open_options));
if (snprintf(bs->filename, sizeof(bs->filename), "json:%s",
- qstring_get_str(json)) >= sizeof(bs->filename)) {
+ json->str) >= sizeof(bs->filename)) {
/* Give user a hint if we truncated things. */
strcpy(bs->filename + sizeof(bs->filename) - 4, "...");
}
- qobject_unref(json);
+ g_string_free(json, true);
}
}
diff --git a/block/file-posix.c b/block/file-posix.c
index 9804681d5c..00cdaaa2d4 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -2953,7 +2953,7 @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int bytes,
assert(bdrv_check_request(req->offset, req->bytes) == 0);
- bdrv_mark_request_serialising(req, bs->bl.request_alignment);
+ bdrv_make_request_serialising(req, bs->bl.request_alignment);
}
#endif
diff --git a/block/gluster.c b/block/gluster.c
index 4f1448e2bc..1f8699b938 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -359,8 +359,8 @@ static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
return -EINVAL;
}
- gconf->server = g_new0(SocketAddressList, 1);
- gconf->server->value = gsconf = g_new0(SocketAddress, 1);
+ gsconf = g_new0(SocketAddress, 1);
+ QAPI_LIST_PREPEND(gconf->server, gsconf);
/* transport */
if (!uri->scheme || !strcmp(uri->scheme, "gluster")) {
diff --git a/block/io.c b/block/io.c
index 24205f5168..95b1c56c06 100644
--- a/block/io.c
+++ b/block/io.c
@@ -754,55 +754,65 @@ static bool tracked_request_overlaps(BdrvTrackedRequest *req,
return true;
}
-static bool coroutine_fn
-bdrv_wait_serialising_requests_locked(BlockDriverState *bs,
- BdrvTrackedRequest *self)
+/* Called with self->bs->reqs_lock held */
+static BdrvTrackedRequest *
+bdrv_find_conflicting_request(BdrvTrackedRequest *self)
{
BdrvTrackedRequest *req;
- bool retry;
- bool waited = false;
- do {
- retry = false;
- QLIST_FOREACH(req, &bs->tracked_requests, list) {
- if (req == self || (!req->serialising && !self->serialising)) {
- continue;
- }
- if (tracked_request_overlaps(req, self->overlap_offset,
- self->overlap_bytes))
- {
- /* Hitting this means there was a reentrant request, for
- * example, a block driver issuing nested requests. This must
- * never happen since it means deadlock.
- */
- assert(qemu_coroutine_self() != req->co);
-
- /* If the request is already (indirectly) waiting for us, or
- * will wait for us as soon as it wakes up, then just go on
- * (instead of producing a deadlock in the former case). */
- if (!req->waiting_for) {
- self->waiting_for = req;
- qemu_co_queue_wait(&req->wait_queue, &bs->reqs_lock);
- self->waiting_for = NULL;
- retry = true;
- waited = true;
- break;
- }
+ QLIST_FOREACH(req, &self->bs->tracked_requests, list) {
+ if (req == self || (!req->serialising && !self->serialising)) {
+ continue;
+ }
+ if (tracked_request_overlaps(req, self->overlap_offset,
+ self->overlap_bytes))
+ {
+ /*
+ * Hitting this means there was a reentrant request, for
+ * example, a block driver issuing nested requests. This must
+ * never happen since it means deadlock.
+ */
+ assert(qemu_coroutine_self() != req->co);
+
+ /*
+ * If the request is already (indirectly) waiting for us, or
+ * will wait for us as soon as it wakes up, then just go on
+ * (instead of producing a deadlock in the former case).
+ */
+ if (!req->waiting_for) {
+ return req;
}
}
- } while (retry);
+ }
+
+ return NULL;
+}
+
+/* Called with self->bs->reqs_lock held */
+static bool coroutine_fn
+bdrv_wait_serialising_requests_locked(BdrvTrackedRequest *self)
+{
+ BdrvTrackedRequest *req;
+ bool waited = false;
+
+ while ((req = bdrv_find_conflicting_request(self))) {
+ self->waiting_for = req;
+ qemu_co_queue_wait(&req->wait_queue, &self->bs->reqs_lock);
+ self->waiting_for = NULL;
+ waited = true;
+ }
+
return waited;
}
-bool bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
+/* Called with req->bs->reqs_lock held */
+static void tracked_request_set_serialising(BdrvTrackedRequest *req,
+ uint64_t align)
{
- BlockDriverState *bs = req->bs;
int64_t overlap_offset = req->offset & ~(align - 1);
uint64_t overlap_bytes = ROUND_UP(req->offset + req->bytes, align)
- overlap_offset;
- bool waited;
- qemu_co_mutex_lock(&bs->reqs_lock);
if (!req->serialising) {
qatomic_inc(&req->bs->serialising_in_flight);
req->serialising = true;
@@ -810,9 +820,6 @@ bool bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
req->overlap_offset = MIN(req->overlap_offset, overlap_offset);
req->overlap_bytes = MAX(req->overlap_bytes, overlap_bytes);
- waited = bdrv_wait_serialising_requests_locked(bs, req);
- qemu_co_mutex_unlock(&bs->reqs_lock);
- return waited;
}
/**
@@ -892,12 +899,27 @@ static bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self
}
qemu_co_mutex_lock(&bs->reqs_lock);
- waited = bdrv_wait_serialising_requests_locked(bs, self);
+ waited = bdrv_wait_serialising_requests_locked(self);
qemu_co_mutex_unlock(&bs->reqs_lock);
return waited;
}
+bool coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req,
+ uint64_t align)
+{
+ bool waited;
+
+ qemu_co_mutex_lock(&req->bs->reqs_lock);
+
+ tracked_request_set_serialising(req, align);
+ waited = bdrv_wait_serialising_requests_locked(req);
+
+ qemu_co_mutex_unlock(&req->bs->reqs_lock);
+
+ return waited;
+}
+
int bdrv_check_request(int64_t offset, int64_t bytes)
{
if (offset < 0 || bytes < 0) {
@@ -1423,7 +1445,7 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
* with each other for the same cluster. For example, in copy-on-read
* it ensures that the CoR read and write operations are atomic and
* guest writes cannot interleave between them. */
- bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs));
+ bdrv_make_request_serialising(req, bdrv_get_cluster_size(bs));
} else {
bdrv_wait_serialising_requests(req);
}
@@ -1827,7 +1849,6 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
BdrvTrackedRequest *req, int flags)
{
BlockDriverState *bs = child->bs;
- bool waited;
int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
if (bs->read_only) {
@@ -1837,17 +1858,18 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
assert(!(bs->open_flags & BDRV_O_INACTIVE));
assert((bs->open_flags & BDRV_O_NO_IO) == 0);
assert(!(flags & ~BDRV_REQ_MASK));
+ assert(!((flags & BDRV_REQ_NO_WAIT) && !(flags & BDRV_REQ_SERIALISING)));
if (flags & BDRV_REQ_SERIALISING) {
- waited = bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs));
- /*
- * For a misaligned request we should have already waited earlier,
- * because we come after bdrv_padding_rmw_read which must be called
- * with the request already marked as serialising.
- */
- assert(!waited ||
- (req->offset == req->overlap_offset &&
- req->bytes == req->overlap_bytes));
+ QEMU_LOCK_GUARD(&bs->reqs_lock);
+
+ tracked_request_set_serialising(req, bdrv_get_cluster_size(bs));
+
+ if ((flags & BDRV_REQ_NO_WAIT) && bdrv_find_conflicting_request(req)) {
+ return -EBUSY;
+ }
+
+ bdrv_wait_serialising_requests_locked(req);
} else {
bdrv_wait_serialising_requests(req);
}
@@ -2013,7 +2035,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
padding = bdrv_init_padding(bs, offset, bytes, &pad);
if (padding) {
- bdrv_mark_request_serialising(req, align);
+ bdrv_make_request_serialising(req, align);
bdrv_padding_rmw_read(child, req, &pad, true);
@@ -2127,7 +2149,7 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
}
if (bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad)) {
- bdrv_mark_request_serialising(&req, align);
+ bdrv_make_request_serialising(&req, align);
bdrv_padding_rmw_read(child, &req, &pad, false);
}
@@ -3248,7 +3270,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
* new area, we need to make sure that no write requests are made to it
* concurrently or they might be overwritten by preallocation. */
if (new_bytes) {
- bdrv_mark_request_serialising(&req, 1);
+ bdrv_make_request_serialising(&req, 1);
}
if (bs->read_only) {
error_setg(errp, "Image is read-only");
diff --git a/block/meson.build b/block/meson.build
index 5dcc1e5cce..7595d86c41 100644
--- a/block/meson.build
+++ b/block/meson.build
@@ -12,6 +12,7 @@ block_ss.add(files(
'block-copy.c',
'commit.c',
'copy-on-read.c',
+ 'preallocate.c',
'create.c',
'crypto.c',
'dirty-bitmap.c',
diff --git a/block/nfs.c b/block/nfs.c
index 77905f516d..8c1968bb41 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -592,7 +592,7 @@ static int64_t nfs_client_open_qdict(NFSClient *client, QDict *options,
int flags, int open_flags, Error **errp)
{
BlockdevOptionsNfs *opts;
- int ret;
+ int64_t ret;
opts = nfs_options_qdict_to_qapi(options, errp);
if (opts == NULL) {
diff --git a/block/nvme.c b/block/nvme.c
index a06a188d53..5a6fbacf4a 100644
--- a/block/nvme.c
+++ b/block/nvme.c
@@ -1389,6 +1389,29 @@ out:
}
+static int coroutine_fn nvme_co_truncate(BlockDriverState *bs, int64_t offset,
+ bool exact, PreallocMode prealloc,
+ BdrvRequestFlags flags, Error **errp)
+{
+ int64_t cur_length;
+
+ if (prealloc != PREALLOC_MODE_OFF) {
+ error_setg(errp, "Unsupported preallocation mode '%s'",
+ PreallocMode_str(prealloc));
+ return -ENOTSUP;
+ }
+
+ cur_length = nvme_getlength(bs);
+ if (offset != cur_length && exact) {
+ error_setg(errp, "Cannot resize NVMe devices");
+ return -ENOTSUP;
+ } else if (offset > cur_length) {
+ error_setg(errp, "Cannot grow NVMe devices");
+ return -EINVAL;
+ }
+
+ return 0;
+}
static int nvme_reopen_prepare(BDRVReopenState *reopen_state,
BlockReopenQueue *queue, Error **errp)
@@ -1523,6 +1546,7 @@ static BlockDriver bdrv_nvme = {
.bdrv_close = nvme_close,
.bdrv_getlength = nvme_getlength,
.bdrv_probe_blocksizes = nvme_probe_blocksizes,
+ .bdrv_co_truncate = nvme_co_truncate,
.bdrv_co_preadv = nvme_co_preadv,
.bdrv_co_pwritev = nvme_co_pwritev,
diff --git a/block/preallocate.c b/block/preallocate.c
new file mode 100644
index 0000000000..b619206304
--- /dev/null
+++ b/block/preallocate.c
@@ -0,0 +1,559 @@
+/*
+ * preallocate filter driver
+ *
+ * The driver performs preallocate operation: it is injected above
+ * some node, and before each write over EOF it does additional preallocating
+ * write-zeroes request.
+ *
+ * Copyright (c) 2020 Virtuozzo International GmbH.
+ *
+ * Author:
+ * Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "qemu/option.h"
+#include "qemu/units.h"
+#include "block/block_int.h"
+
+
+typedef struct PreallocateOpts {
+ int64_t prealloc_size;
+ int64_t prealloc_align;
+} PreallocateOpts;
+
+typedef struct BDRVPreallocateState {
+ PreallocateOpts opts;
+
+ /*
+ * Track real data end, to crop preallocation on close. If < 0 the status is
+ * unknown.
+ *
+ * @data_end is a maximum of file size on open (or when we get write/resize
+ * permissions) and all write request ends after it. So it's safe to
+ * truncate to data_end if it is valid.
+ */
+ int64_t data_end;
+
+ /*
+ * Start of trailing preallocated area which reads as zero. May be smaller
+ * than data_end, if user does over-EOF write zero operation. If < 0 the
+ * status is unknown.
+ *
+ * If both @zero_start and @file_end are valid, the region
+ * [@zero_start, @file_end) is known to be preallocated zeroes. If @file_end
+ * is not valid, @zero_start doesn't make much sense.
+ */
+ int64_t zero_start;
+
+ /*
+ * Real end of file. Actually the cache for bdrv_getlength(bs->file->bs),
+ * to avoid extra lseek() calls on each write operation. If < 0 the status
+ * is unknown.
+ */
+ int64_t file_end;
+
+ /*
+ * All three states @data_end, @zero_start and @file_end are guaranteed to
+ * be invalid (< 0) when we don't have both exclusive BLK_PERM_RESIZE and
+ * BLK_PERM_WRITE permissions on file child.
+ */
+} BDRVPreallocateState;
+
+#define PREALLOCATE_OPT_PREALLOC_ALIGN "prealloc-align"
+#define PREALLOCATE_OPT_PREALLOC_SIZE "prealloc-size"
+static QemuOptsList runtime_opts = {
+ .name = "preallocate",
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
+ .desc = {
+ {
+ .name = PREALLOCATE_OPT_PREALLOC_ALIGN,
+ .type = QEMU_OPT_SIZE,
+ .help = "on preallocation, align file length to this number, "
+ "default 1M",
+ },
+ {
+ .name = PREALLOCATE_OPT_PREALLOC_SIZE,
+ .type = QEMU_OPT_SIZE,
+ .help = "how much to preallocate, default 128M",
+ },
+ { /* end of list */ }
+ },
+};
+
+static bool preallocate_absorb_opts(PreallocateOpts *dest, QDict *options,
+ BlockDriverState *child_bs, Error **errp)
+{
+ QemuOpts *opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
+
+ if (!qemu_opts_absorb_qdict(opts, options, errp)) {
+ return false;
+ }
+
+ dest->prealloc_align =
+ qemu_opt_get_size(opts, PREALLOCATE_OPT_PREALLOC_ALIGN, 1 * MiB);
+ dest->prealloc_size =
+ qemu_opt_get_size(opts, PREALLOCATE_OPT_PREALLOC_SIZE, 128 * MiB);
+
+ qemu_opts_del(opts);
+
+ if (!QEMU_IS_ALIGNED(dest->prealloc_align, BDRV_SECTOR_SIZE)) {
+ error_setg(errp, "prealloc-align parameter of preallocate filter "
+ "is not aligned to %llu", BDRV_SECTOR_SIZE);
+ return false;
+ }
+
+ if (!QEMU_IS_ALIGNED(dest->prealloc_align,
+ child_bs->bl.request_alignment)) {
+ error_setg(errp, "prealloc-align parameter of preallocate filter "
+ "is not aligned to underlying node request alignment "
+ "(%" PRIi32 ")", child_bs->bl.request_alignment);
+ return false;
+ }
+
+ return true;
+}
+
+static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
+ Error **errp)
+{
+ BDRVPreallocateState *s = bs->opaque;
+
+ /*
+ * s->data_end and friends should be initialized on permission update.
+ * For this to work, mark them invalid.
+ */
+ s->file_end = s->zero_start = s->data_end = -EINVAL;
+
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
+ false, errp);
+ if (!bs->file) {
+ return -EINVAL;
+ }
+
+ if (!preallocate_absorb_opts(&s->opts, options, bs->file->bs, errp)) {
+ return -EINVAL;
+ }
+
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
+ (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
+
+ bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
+ ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
+ bs->file->bs->supported_zero_flags);
+
+ return 0;
+}
+
+static void preallocate_close(BlockDriverState *bs)
+{
+ int ret;
+ BDRVPreallocateState *s = bs->opaque;
+
+ if (s->data_end < 0) {
+ return;
+ }
+
+ if (s->file_end < 0) {
+ s->file_end = bdrv_getlength(bs->file->bs);
+ if (s->file_end < 0) {
+ return;
+ }
+ }
+
+ if (s->data_end < s->file_end) {
+ ret = bdrv_truncate(bs->file, s->data_end, true, PREALLOC_MODE_OFF, 0,
+ NULL);
+ s->file_end = ret < 0 ? ret : s->data_end;
+ }
+}
+
+
+/*
+ * Handle reopen.
+ *
+ * We must implement reopen handlers, otherwise reopen just don't work. Handle
+ * new options and don't care about preallocation state, as it is handled in
+ * set/check permission handlers.
+ */
+
+static int preallocate_reopen_prepare(BDRVReopenState *reopen_state,
+ BlockReopenQueue *queue, Error **errp)
+{
+ PreallocateOpts *opts = g_new0(PreallocateOpts, 1);
+
+ if (!preallocate_absorb_opts(opts, reopen_state->options,
+ reopen_state->bs->file->bs, errp)) {
+ g_free(opts);
+ return -EINVAL;
+ }
+
+ reopen_state->opaque = opts;
+
+ return 0;
+}
+
+static void preallocate_reopen_commit(BDRVReopenState *state)
+{
+ BDRVPreallocateState *s = state->bs->opaque;
+
+ s->opts = *(PreallocateOpts *)state->opaque;
+
+ g_free(state->opaque);
+ state->opaque = NULL;
+}
+
+static void preallocate_reopen_abort(BDRVReopenState *state)
+{
+ g_free(state->opaque);
+ state->opaque = NULL;
+}
+
+static coroutine_fn int preallocate_co_preadv_part(
+ BlockDriverState *bs, uint64_t offset, uint64_t bytes,
+ QEMUIOVector *qiov, size_t qiov_offset, int flags)
+{
+ return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
+ flags);
+}
+
+static int coroutine_fn preallocate_co_pdiscard(BlockDriverState *bs,
+ int64_t offset, int bytes)
+{
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
+}
+
+static bool can_write_resize(uint64_t perm)
+{
+ return (perm & BLK_PERM_WRITE) && (perm & BLK_PERM_RESIZE);
+}
+
+static bool has_prealloc_perms(BlockDriverState *bs)
+{
+ BDRVPreallocateState *s = bs->opaque;
+
+ if (can_write_resize(bs->file->perm)) {
+ assert(!(bs->file->shared_perm & BLK_PERM_WRITE));
+ assert(!(bs->file->shared_perm & BLK_PERM_RESIZE));
+ return true;
+ }
+
+ assert(s->data_end < 0);
+ assert(s->zero_start < 0);
+ assert(s->file_end < 0);
+ return false;
+}
+
+/*
+ * Call on each write. Returns true if @want_merge_zero is true and the region
+ * [offset, offset + bytes) is zeroed (as a result of this call or earlier
+ * preallocation).
+ *
+ * want_merge_zero is used to merge write-zero request with preallocation in
+ * one bdrv_co_pwrite_zeroes() call.
+ */
+static bool coroutine_fn handle_write(BlockDriverState *bs, int64_t offset,
+ int64_t bytes, bool want_merge_zero)
+{
+ BDRVPreallocateState *s = bs->opaque;
+ int64_t end = offset + bytes;
+ int64_t prealloc_start, prealloc_end;
+ int ret;
+
+ if (!has_prealloc_perms(bs)) {
+ /* We don't have state neither should try to recover it */
+ return false;
+ }
+
+ if (s->data_end < 0) {
+ s->data_end = bdrv_getlength(bs->file->bs);
+ if (s->data_end < 0) {
+ return false;
+ }
+
+ if (s->file_end < 0) {
+ s->file_end = s->data_end;
+ }
+ }
+
+ if (end <= s->data_end) {
+ return false;
+ }
+
+ /* We have valid s->data_end, and request writes beyond it. */
+
+ s->data_end = end;
+ if (s->zero_start < 0 || !want_merge_zero) {
+ s->zero_start = end;
+ }
+
+ if (s->file_end < 0) {
+ s->file_end = bdrv_getlength(bs->file->bs);
+ if (s->file_end < 0) {
+ return false;
+ }
+ }
+
+ /* Now s->data_end, s->zero_start and s->file_end are valid. */
+
+ if (end <= s->file_end) {
+ /* No preallocation needed. */
+ return want_merge_zero && offset >= s->zero_start;
+ }
+
+ /* Now we want new preallocation, as request writes beyond s->file_end. */
+
+ prealloc_start = want_merge_zero ? MIN(offset, s->file_end) : s->file_end;
+ prealloc_end = QEMU_ALIGN_UP(end + s->opts.prealloc_size,
+ s->opts.prealloc_align);
+
+ ret = bdrv_co_pwrite_zeroes(
+ bs->file, prealloc_start, prealloc_end - prealloc_start,
+ BDRV_REQ_NO_FALLBACK | BDRV_REQ_SERIALISING | BDRV_REQ_NO_WAIT);
+ if (ret < 0) {
+ s->file_end = ret;
+ return false;
+ }
+
+ s->file_end = prealloc_end;
+ return want_merge_zero;
+}
+
+static int coroutine_fn preallocate_co_pwrite_zeroes(BlockDriverState *bs,
+ int64_t offset, int bytes, BdrvRequestFlags flags)
+{
+ bool want_merge_zero =
+ !(flags & ~(BDRV_REQ_ZERO_WRITE | BDRV_REQ_NO_FALLBACK));
+ if (handle_write(bs, offset, bytes, want_merge_zero)) {
+ return 0;
+ }
+
+ return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
+}
+
+static coroutine_fn int preallocate_co_pwritev_part(BlockDriverState *bs,
+ uint64_t offset,
+ uint64_t bytes,
+ QEMUIOVector *qiov,
+ size_t qiov_offset,
+ int flags)
+{
+ handle_write(bs, offset, bytes, false);
+
+ return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
+ flags);
+}
+
+static int coroutine_fn
+preallocate_co_truncate(BlockDriverState *bs, int64_t offset,
+ bool exact, PreallocMode prealloc,
+ BdrvRequestFlags flags, Error **errp)
+{
+ ERRP_GUARD();
+ BDRVPreallocateState *s = bs->opaque;
+ int ret;
+
+ if (s->data_end >= 0 && offset > s->data_end) {
+ if (s->file_end < 0) {
+ s->file_end = bdrv_getlength(bs->file->bs);
+ if (s->file_end < 0) {
+ error_setg(errp, "failed to get file length");
+ return s->file_end;
+ }
+ }
+
+ if (prealloc == PREALLOC_MODE_FALLOC) {
+ /*
+ * If offset <= s->file_end, the task is already done, just
+ * update s->data_end, to move part of "filter preallocation"
+ * to "preallocation requested by user".
+ * Otherwise just proceed to preallocate missing part.
+ */
+ if (offset <= s->file_end) {
+ s->data_end = offset;
+ return 0;
+ }
+ } else {
+ /*
+ * We have to drop our preallocation, to
+ * - avoid "Cannot use preallocation for shrinking files" in
+ * case of offset < file_end
+ * - give PREALLOC_MODE_OFF a chance to keep small disk
+ * usage
+ * - give PREALLOC_MODE_FULL a chance to actually write the
+ * whole region as user expects
+ */
+ if (s->file_end > s->data_end) {
+ ret = bdrv_co_truncate(bs->file, s->data_end, true,
+ PREALLOC_MODE_OFF, 0, errp);
+ if (ret < 0) {
+ s->file_end = ret;
+ error_prepend(errp, "preallocate-filter: failed to drop "
+ "write-zero preallocation: ");
+ return ret;
+ }
+ s->file_end = s->data_end;
+ }
+ }
+
+ s->data_end = offset;
+ }
+
+ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
+ if (ret < 0) {
+ s->file_end = s->zero_start = s->data_end = ret;
+ return ret;
+ }
+
+ if (has_prealloc_perms(bs)) {
+ s->file_end = s->zero_start = s->data_end = offset;
+ }
+ return 0;
+}
+
+static int coroutine_fn preallocate_co_flush(BlockDriverState *bs)
+{
+ return bdrv_co_flush(bs->file->bs);
+}
+
+static int64_t preallocate_getlength(BlockDriverState *bs)
+{
+ int64_t ret;
+ BDRVPreallocateState *s = bs->opaque;
+
+ if (s->data_end >= 0) {
+ return s->data_end;
+ }
+
+ ret = bdrv_getlength(bs->file->bs);
+
+ if (has_prealloc_perms(bs)) {
+ s->file_end = s->zero_start = s->data_end = ret;
+ }
+
+ return ret;
+}
+
+static int preallocate_check_perm(BlockDriverState *bs,
+ uint64_t perm, uint64_t shared, Error **errp)
+{
+ BDRVPreallocateState *s = bs->opaque;
+
+ if (s->data_end >= 0 && !can_write_resize(perm)) {
+ /*
+ * Lose permissions.
+ * We should truncate in check_perm, as in set_perm bs->file->perm will
+ * be already changed, and we should not violate it.
+ */
+ if (s->file_end < 0) {
+ s->file_end = bdrv_getlength(bs->file->bs);
+ if (s->file_end < 0) {
+ error_setg(errp, "Failed to get file length");
+ return s->file_end;
+ }
+ }
+
+ if (s->data_end < s->file_end) {
+ int ret = bdrv_truncate(bs->file, s->data_end, true,
+ PREALLOC_MODE_OFF, 0, NULL);
+ if (ret < 0) {
+ error_setg(errp, "Failed to drop preallocation");
+ s->file_end = ret;
+ return ret;
+ }
+ s->file_end = s->data_end;
+ }
+ }
+
+ return 0;
+}
+
+static void preallocate_set_perm(BlockDriverState *bs,
+ uint64_t perm, uint64_t shared)
+{
+ BDRVPreallocateState *s = bs->opaque;
+
+ if (can_write_resize(perm)) {
+ if (s->data_end < 0) {
+ s->data_end = s->file_end = s->zero_start =
+ bdrv_getlength(bs->file->bs);
+ }
+ } else {
+ /*
+ * We drop our permissions, as well as allow shared
+ * permissions (see preallocate_child_perm), anyone will be able to
+ * change the child, so mark all states invalid. We'll regain control if
+ * get good permissions back.
+ */
+ s->data_end = s->file_end = s->zero_start = -EINVAL;
+ }
+}
+
+static void preallocate_child_perm(BlockDriverState *bs, BdrvChild *c,
+ BdrvChildRole role, BlockReopenQueue *reopen_queue,
+ uint64_t perm, uint64_t shared, uint64_t *nperm, uint64_t *nshared)
+{
+ bdrv_default_perms(bs, c, role, reopen_queue, perm, shared, nperm, nshared);
+
+ if (can_write_resize(perm)) {
+ /* This should come by default, but let's enforce: */
+ *nperm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
+
+ /*
+ * Don't share, to keep our states s->file_end, s->data_end and
+ * s->zero_start valid.
+ */
+ *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
+ }
+}
+
+BlockDriver bdrv_preallocate_filter = {
+ .format_name = "preallocate",
+ .instance_size = sizeof(BDRVPreallocateState),
+
+ .bdrv_getlength = preallocate_getlength,
+ .bdrv_open = preallocate_open,
+ .bdrv_close = preallocate_close,
+
+ .bdrv_reopen_prepare = preallocate_reopen_prepare,
+ .bdrv_reopen_commit = preallocate_reopen_commit,
+ .bdrv_reopen_abort = preallocate_reopen_abort,
+
+ .bdrv_co_preadv_part = preallocate_co_preadv_part,
+ .bdrv_co_pwritev_part = preallocate_co_pwritev_part,
+ .bdrv_co_pwrite_zeroes = preallocate_co_pwrite_zeroes,
+ .bdrv_co_pdiscard = preallocate_co_pdiscard,
+ .bdrv_co_flush = preallocate_co_flush,
+ .bdrv_co_truncate = preallocate_co_truncate,
+
+ .bdrv_check_perm = preallocate_check_perm,
+ .bdrv_set_perm = preallocate_set_perm,
+ .bdrv_child_perm = preallocate_child_perm,
+
+ .has_variable_length = true,
+ .is_filter = true,
+};
+
+static void bdrv_preallocate_init(void)
+{
+ bdrv_register(&bdrv_preallocate_filter);
+}
+
+block_init(bdrv_preallocate_init);
diff --git a/block/qapi.c b/block/qapi.c
index 036da085ee..0ca206f559 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -486,12 +486,7 @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
ds->account_failed = stats->account_failed;
while ((ts = block_acct_interval_next(stats, ts))) {
- BlockDeviceTimedStatsList *timed_stats =
- g_malloc0(sizeof(*timed_stats));
BlockDeviceTimedStats *dev_stats = g_malloc0(sizeof(*dev_stats));
- timed_stats->next = ds->timed_stats;
- timed_stats->value = dev_stats;
- ds->timed_stats = timed_stats;
TimedAverage *rd = &ts->latency[BLOCK_ACCT_READ];
TimedAverage *wr = &ts->latency[BLOCK_ACCT_WRITE];
@@ -515,6 +510,8 @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
block_acct_queue_depth(ts, BLOCK_ACCT_READ);
dev_stats->avg_wr_queue_depth =
block_acct_queue_depth(ts, BLOCK_ACCT_WRITE);
+
+ QAPI_LIST_PREPEND(ds->timed_stats, dev_stats);
}
bdrv_latency_histogram_stats(&stats->latency_histogram[BLOCK_ACCT_READ],
diff --git a/block/quorum.c b/block/quorum.c
index 4b08a199b7..0bd75450de 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -18,6 +18,7 @@
#include "qemu/module.h"
#include "qemu/option.h"
#include "block/block_int.h"
+#include "block/coroutines.h"
#include "block/qdict.h"
#include "qapi/error.h"
#include "qapi/qapi-events-block.h"
@@ -691,8 +692,13 @@ static void write_quorum_entry(void *opaque)
QuorumChildRequest *sacb = &acb->qcrs[i];
sacb->bs = s->children[i]->bs;
- sacb->ret = bdrv_co_pwritev(s->children[i], acb->offset, acb->bytes,
- acb->qiov, acb->flags);
+ if (acb->flags & BDRV_REQ_ZERO_WRITE) {
+ sacb->ret = bdrv_co_pwrite_zeroes(s->children[i], acb->offset,
+ acb->bytes, acb->flags);
+ } else {
+ sacb->ret = bdrv_co_pwritev(s->children[i], acb->offset, acb->bytes,
+ acb->qiov, acb->flags);
+ }
if (sacb->ret == 0) {
acb->success_count++;
} else {
@@ -738,6 +744,14 @@ static int quorum_co_pwritev(BlockDriverState *bs, uint64_t offset,
return ret;
}
+static int quorum_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
+ int bytes, BdrvRequestFlags flags)
+
+{
+ return quorum_co_pwritev(bs, offset, bytes, NULL,
+ flags | BDRV_REQ_ZERO_WRITE);
+}
+
static int64_t quorum_getlength(BlockDriverState *bs)
{
BDRVQuorumState *s = bs->opaque;
@@ -896,6 +910,21 @@ static QemuOptsList quorum_runtime_opts = {
},
};
+static void quorum_refresh_flags(BlockDriverState *bs)
+{
+ BDRVQuorumState *s = bs->opaque;
+ int i;
+
+ bs->supported_zero_flags =
+ BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
+
+ for (i = 0; i < s->num_children; i++) {
+ bs->supported_zero_flags &= s->children[i]->bs->supported_zero_flags;
+ }
+
+ bs->supported_zero_flags |= BDRV_REQ_WRITE_UNCHANGED;
+}
+
static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
@@ -990,6 +1019,7 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
s->next_child_index = s->num_children;
bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
+ quorum_refresh_flags(bs);
g_free(opened);
goto exit;
@@ -1061,6 +1091,7 @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
}
s->children = g_renew(BdrvChild *, s->children, s->num_children + 1);
s->children[s->num_children++] = child;
+ quorum_refresh_flags(bs);
out:
bdrv_drained_end(bs);
@@ -1105,6 +1136,7 @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
s->children = g_renew(BdrvChild *, s->children, --s->num_children);
bdrv_unref_child(bs, child);
+ quorum_refresh_flags(bs);
bdrv_drained_end(bs);
}
@@ -1179,6 +1211,56 @@ static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c,
| DEFAULT_PERM_UNCHANGED;
}
+/*
+ * Each one of the children can report different status flags even
+ * when they contain the same data, so what this function does is
+ * return BDRV_BLOCK_ZERO if *all* children agree that a certain
+ * region contains zeroes, and BDRV_BLOCK_DATA otherwise.
+ */
+static int coroutine_fn quorum_co_block_status(BlockDriverState *bs,
+ bool want_zero,
+ int64_t offset, int64_t count,
+ int64_t *pnum, int64_t *map,
+ BlockDriverState **file)
+{
+ BDRVQuorumState *s = bs->opaque;
+ int i, ret;
+ int64_t pnum_zero = count;
+ int64_t pnum_data = 0;
+
+ for (i = 0; i < s->num_children; i++) {
+ int64_t bytes;
+ ret = bdrv_co_common_block_status_above(s->children[i]->bs, NULL, false,
+ want_zero, offset, count,
+ &bytes, NULL, NULL, NULL);
+ if (ret < 0) {
+ quorum_report_bad(QUORUM_OP_TYPE_READ, offset, count,
+ s->children[i]->bs->node_name, ret);
+ pnum_data = count;
+ break;
+ }
+ /*
+ * Even if all children agree about whether there are zeroes
+ * or not at @offset they might disagree on the size, so use
+ * the smallest when reporting BDRV_BLOCK_ZERO and the largest
+ * when reporting BDRV_BLOCK_DATA.
+ */
+ if (ret & BDRV_BLOCK_ZERO) {
+ pnum_zero = MIN(pnum_zero, bytes);
+ } else {
+ pnum_data = MAX(pnum_data, bytes);
+ }
+ }
+
+ if (pnum_data) {
+ *pnum = pnum_data;
+ return BDRV_BLOCK_DATA;
+ } else {
+ *pnum = pnum_zero;
+ return BDRV_BLOCK_ZERO;
+ }
+}
+
static const char *const quorum_strong_runtime_opts[] = {
QUORUM_OPT_VOTE_THRESHOLD,
QUORUM_OPT_BLKVERIFY,
@@ -1197,6 +1279,7 @@ static BlockDriver bdrv_quorum = {
.bdrv_close = quorum_close,
.bdrv_gather_child_options = quorum_gather_child_options,
.bdrv_dirname = quorum_dirname,
+ .bdrv_co_block_status = quorum_co_block_status,
.bdrv_co_flush_to_disk = quorum_co_flush,
@@ -1204,6 +1287,7 @@ static BlockDriver bdrv_quorum = {
.bdrv_co_preadv = quorum_co_preadv,
.bdrv_co_pwritev = quorum_co_pwritev,
+ .bdrv_co_pwrite_zeroes = quorum_co_pwrite_zeroes,
.bdrv_add_child = quorum_add_child,
.bdrv_del_child = quorum_del_child,
diff --git a/block/rbd.c b/block/rbd.c
index 9bd2bce716..9071a00e3f 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -232,7 +232,7 @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options,
if (keypairs) {
qdict_put(options, "=keyvalue-pairs",
- qobject_to_json(QOBJECT(keypairs)));
+ qstring_from_gstring(qobject_to_json(QOBJECT(keypairs))));
}
done:
diff --git a/block/vpc.c b/block/vpc.c
index 1ab55f9287..17a705b482 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -39,8 +39,6 @@
/**************************************************************/
-#define HEADER_SIZE 512
-
//#define CACHE
enum vhd_type {
@@ -95,8 +93,11 @@ typedef struct vhd_footer {
QemuUUID uuid;
uint8_t in_saved_state;
+ uint8_t reserved[427];
} QEMU_PACKED VHDFooter;
+QEMU_BUILD_BUG_ON(sizeof(VHDFooter) != 512);
+
typedef struct vhd_dyndisk_header {
char magic[8]; /* "cxsparse" */
@@ -127,11 +128,14 @@ typedef struct vhd_dyndisk_header {
uint32_t reserved;
uint64_t data_offset;
} parent_locator[8];
+ uint8_t reserved2[256];
} QEMU_PACKED VHDDynDiskHeader;
+QEMU_BUILD_BUG_ON(sizeof(VHDDynDiskHeader) != 1024);
+
typedef struct BDRVVPCState {
CoMutex lock;
- uint8_t footer_buf[HEADER_SIZE];
+ VHDFooter footer;
uint64_t free_data_block_offset;
int max_table_entries;
uint32_t *pagetable;
@@ -172,8 +176,9 @@ static QemuOptsList vpc_runtime_opts = {
static QemuOptsList vpc_create_opts;
-static uint32_t vpc_checksum(uint8_t *buf, size_t size)
+static uint32_t vpc_checksum(void *p, size_t size)
{
+ uint8_t *buf = p;
uint32_t res = 0;
int i;
@@ -216,11 +221,10 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
BDRVVPCState *s = bs->opaque;
int i;
VHDFooter *footer;
- VHDDynDiskHeader *dyndisk_header;
QemuOpts *opts = NULL;
Error *local_err = NULL;
bool use_chs;
- uint8_t buf[HEADER_SIZE];
+ VHDDynDiskHeader dyndisk_header;
uint32_t checksum;
uint64_t computed_size;
uint64_t pagetable_size;
@@ -247,28 +251,28 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
goto fail;
}
- ret = bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE);
+ ret = bdrv_pread(bs->file, 0, &s->footer, sizeof(s->footer));
if (ret < 0) {
error_setg(errp, "Unable to read VHD header");
goto fail;
}
- footer = (VHDFooter *) s->footer_buf;
+ footer = &s->footer;
if (strncmp(footer->creator, "conectix", 8)) {
int64_t offset = bdrv_getlength(bs->file->bs);
if (offset < 0) {
ret = offset;
error_setg(errp, "Invalid file size");
goto fail;
- } else if (offset < HEADER_SIZE) {
+ } else if (offset < sizeof(*footer)) {
ret = -EINVAL;
error_setg(errp, "File too small for a VHD header");
goto fail;
}
/* If a fixed disk, the footer is found only at the end of the file */
- ret = bdrv_pread(bs->file, offset-HEADER_SIZE, s->footer_buf,
- HEADER_SIZE);
+ ret = bdrv_pread(bs->file, offset - sizeof(*footer),
+ footer, sizeof(*footer));
if (ret < 0) {
goto fail;
}
@@ -282,7 +286,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
checksum = be32_to_cpu(footer->checksum);
footer->checksum = 0;
- if (vpc_checksum(s->footer_buf, HEADER_SIZE) != checksum) {
+ if (vpc_checksum(footer, sizeof(*footer)) != checksum) {
error_setg(errp, "Incorrect header checksum");
ret = -EINVAL;
goto fail;
@@ -340,22 +344,20 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
}
if (disk_type == VHD_DYNAMIC) {
- ret = bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf,
- HEADER_SIZE);
+ ret = bdrv_pread(bs->file, be64_to_cpu(footer->data_offset),
+ &dyndisk_header, sizeof(dyndisk_header));
if (ret < 0) {
error_setg(errp, "Error reading dynamic VHD header");
goto fail;
}
- dyndisk_header = (VHDDynDiskHeader *) buf;
-
- if (strncmp(dyndisk_header->magic, "cxsparse", 8)) {
+ if (strncmp(dyndisk_header.magic, "cxsparse", 8)) {
error_setg(errp, "Invalid header magic");
ret = -EINVAL;
goto fail;
}
- s->block_size = be32_to_cpu(dyndisk_header->block_size);
+ s->block_size = be32_to_cpu(dyndisk_header.block_size);
if (!is_power_of_2(s->block_size) || s->block_size < BDRV_SECTOR_SIZE) {
error_setg(errp, "Invalid block size %" PRIu32, s->block_size);
ret = -EINVAL;
@@ -363,7 +365,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
}
s->bitmap_size = ((s->block_size / (8 * 512)) + 511) & ~511;
- s->max_table_entries = be32_to_cpu(dyndisk_header->max_table_entries);
+ s->max_table_entries = be32_to_cpu(dyndisk_header.max_table_entries);
if ((bs->total_sectors * 512) / s->block_size > 0xffffffffU) {
error_setg(errp, "Too many blocks");
@@ -395,7 +397,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
goto fail;
}
- s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
+ s->bat_offset = be64_to_cpu(dyndisk_header.table_offset);
ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable,
pagetable_size);
@@ -534,7 +536,7 @@ static int rewrite_footer(BlockDriverState *bs)
BDRVVPCState *s = bs->opaque;
int64_t offset = s->free_data_block_offset;
- ret = bdrv_pwrite_sync(bs->file, offset, s->footer_buf, HEADER_SIZE);
+ ret = bdrv_pwrite_sync(bs->file, offset, &s->footer, sizeof(s->footer));
if (ret < 0)
return ret;
@@ -597,9 +599,8 @@ fail:
static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{
BDRVVPCState *s = (BDRVVPCState *)bs->opaque;
- VHDFooter *footer = (VHDFooter *) s->footer_buf;
- if (be32_to_cpu(footer->type) != VHD_FIXED) {
+ if (be32_to_cpu(s->footer.type) != VHD_FIXED) {
bdi->cluster_size = s->block_size;
}
@@ -615,10 +616,9 @@ vpc_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
int64_t image_offset;
int64_t n_bytes;
int64_t bytes_done = 0;
- VHDFooter *footer = (VHDFooter *) s->footer_buf;
QEMUIOVector local_qiov;
- if (be32_to_cpu(footer->type) == VHD_FIXED) {
+ if (be32_to_cpu(s->footer.type) == VHD_FIXED) {
return bdrv_co_preadv(bs->file, offset, bytes, qiov, 0);
}
@@ -666,10 +666,9 @@ vpc_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
int64_t n_bytes;
int64_t bytes_done = 0;
int ret = 0;
- VHDFooter *footer = (VHDFooter *) s->footer_buf;
QEMUIOVector local_qiov;
- if (be32_to_cpu(footer->type) == VHD_FIXED) {
+ if (be32_to_cpu(s->footer.type) == VHD_FIXED) {
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, 0);
}
@@ -723,13 +722,12 @@ static int coroutine_fn vpc_co_block_status(BlockDriverState *bs,
BlockDriverState **file)
{
BDRVVPCState *s = bs->opaque;
- VHDFooter *footer = (VHDFooter*) s->footer_buf;
int64_t image_offset;
bool allocated;
int ret;
int64_t n;
- if (be32_to_cpu(footer->type) == VHD_FIXED) {
+ if (be32_to_cpu(s->footer.type) == VHD_FIXED) {
*pnum = bytes;
*map = offset;
*file = bs->file->bs;
@@ -819,11 +817,11 @@ static int calculate_geometry(int64_t total_sectors, uint16_t *cyls,
return 0;
}
-static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf,
+static int create_dynamic_disk(BlockBackend *blk, VHDFooter *footer,
int64_t total_sectors)
{
- VHDDynDiskHeader *dyndisk_header =
- (VHDDynDiskHeader *) buf;
+ VHDDynDiskHeader dyndisk_header;
+ uint8_t bat_sector[512];
size_t block_size, num_bat_entries;
int i;
int ret;
@@ -833,13 +831,13 @@ static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf,
block_size = 0x200000;
num_bat_entries = DIV_ROUND_UP(total_sectors, block_size / 512);
- ret = blk_pwrite(blk, offset, buf, HEADER_SIZE, 0);
+ ret = blk_pwrite(blk, offset, footer, sizeof(*footer), 0);
if (ret < 0) {
goto fail;
}
offset = 1536 + ((num_bat_entries * 4 + 511) & ~511);
- ret = blk_pwrite(blk, offset, buf, HEADER_SIZE, 0);
+ ret = blk_pwrite(blk, offset, footer, sizeof(*footer), 0);
if (ret < 0) {
goto fail;
}
@@ -847,9 +845,9 @@ static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf,
/* Write the initial BAT */
offset = 3 * 512;
- memset(buf, 0xFF, 512);
+ memset(bat_sector, 0xFF, 512);
for (i = 0; i < DIV_ROUND_UP(num_bat_entries * 4, 512); i++) {
- ret = blk_pwrite(blk, offset, buf, 512, 0);
+ ret = blk_pwrite(blk, offset, bat_sector, 512, 0);
if (ret < 0) {
goto fail;
}
@@ -857,26 +855,27 @@ static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf,
}
/* Prepare the Dynamic Disk Header */
- memset(buf, 0, 1024);
+ memset(&dyndisk_header, 0, sizeof(dyndisk_header));
- memcpy(dyndisk_header->magic, "cxsparse", 8);
+ memcpy(dyndisk_header.magic, "cxsparse", 8);
/*
* Note: The spec is actually wrong here for data_offset, it says
* 0xFFFFFFFF, but MS tools expect all 64 bits to be set.
*/
- dyndisk_header->data_offset = cpu_to_be64(0xFFFFFFFFFFFFFFFFULL);
- dyndisk_header->table_offset = cpu_to_be64(3 * 512);
- dyndisk_header->version = cpu_to_be32(0x00010000);
- dyndisk_header->block_size = cpu_to_be32(block_size);
- dyndisk_header->max_table_entries = cpu_to_be32(num_bat_entries);
+ dyndisk_header.data_offset = cpu_to_be64(0xFFFFFFFFFFFFFFFFULL);
+ dyndisk_header.table_offset = cpu_to_be64(3 * 512);
+ dyndisk_header.version = cpu_to_be32(0x00010000);
+ dyndisk_header.block_size = cpu_to_be32(block_size);
+ dyndisk_header.max_table_entries = cpu_to_be32(num_bat_entries);
- dyndisk_header->checksum = cpu_to_be32(vpc_checksum(buf, 1024));
+ dyndisk_header.checksum = cpu_to_be32(
+ vpc_checksum(&dyndisk_header, sizeof(dyndisk_header)));
/* Write the header */
offset = 512;
- ret = blk_pwrite(blk, offset, buf, 1024, 0);
+ ret = blk_pwrite(blk, offset, &dyndisk_header, sizeof(dyndisk_header), 0);
if (ret < 0) {
goto fail;
}
@@ -886,20 +885,21 @@ static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf,
return ret;
}
-static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
+static int create_fixed_disk(BlockBackend *blk, VHDFooter *footer,
int64_t total_size, Error **errp)
{
int ret;
/* Add footer to total size */
- total_size += HEADER_SIZE;
+ total_size += sizeof(*footer);
ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp);
if (ret < 0) {
return ret;
}
- ret = blk_pwrite(blk, total_size - HEADER_SIZE, buf, HEADER_SIZE, 0);
+ ret = blk_pwrite(blk, total_size - sizeof(*footer),
+ footer, sizeof(*footer), 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "Unable to write VHD header");
return ret;
@@ -971,8 +971,7 @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
BlockBackend *blk = NULL;
BlockDriverState *bs = NULL;
- uint8_t buf[1024];
- VHDFooter *footer = (VHDFooter *) buf;
+ VHDFooter footer;
uint16_t cyls = 0;
uint8_t heads = 0;
uint8_t secs_per_cyl = 0;
@@ -1035,48 +1034,48 @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
}
/* Prepare the Hard Disk Footer */
- memset(buf, 0, 1024);
+ memset(&footer, 0, sizeof(footer));
- memcpy(footer->creator, "conectix", 8);
+ memcpy(footer.creator, "conectix", 8);
if (vpc_opts->force_size) {
- memcpy(footer->creator_app, "qem2", 4);
+ memcpy(footer.creator_app, "qem2", 4);
} else {
- memcpy(footer->creator_app, "qemu", 4);
+ memcpy(footer.creator_app, "qemu", 4);
}
- memcpy(footer->creator_os, "Wi2k", 4);
+ memcpy(footer.creator_os, "Wi2k", 4);
- footer->features = cpu_to_be32(0x02);
- footer->version = cpu_to_be32(0x00010000);
+ footer.features = cpu_to_be32(0x02);
+ footer.version = cpu_to_be32(0x00010000);
if (disk_type == VHD_DYNAMIC) {
- footer->data_offset = cpu_to_be64(HEADER_SIZE);
+ footer.data_offset = cpu_to_be64(sizeof(footer));
} else {
- footer->data_offset = cpu_to_be64(0xFFFFFFFFFFFFFFFFULL);
+ footer.data_offset = cpu_to_be64(0xFFFFFFFFFFFFFFFFULL);
}
- footer->timestamp = cpu_to_be32(time(NULL) - VHD_TIMESTAMP_BASE);
+ footer.timestamp = cpu_to_be32(time(NULL) - VHD_TIMESTAMP_BASE);
/* Version of Virtual PC 2007 */
- footer->major = cpu_to_be16(0x0005);
- footer->minor = cpu_to_be16(0x0003);
- footer->orig_size = cpu_to_be64(total_size);
- footer->current_size = cpu_to_be64(total_size);
- footer->cyls = cpu_to_be16(cyls);
- footer->heads = heads;
- footer->secs_per_cyl = secs_per_cyl;
+ footer.major = cpu_to_be16(0x0005);
+ footer.minor = cpu_to_be16(0x0003);
+ footer.orig_size = cpu_to_be64(total_size);
+ footer.current_size = cpu_to_be64(total_size);
+ footer.cyls = cpu_to_be16(cyls);
+ footer.heads = heads;
+ footer.secs_per_cyl = secs_per_cyl;
- footer->type = cpu_to_be32(disk_type);
+ footer.type = cpu_to_be32(disk_type);
qemu_uuid_generate(&uuid);
- footer->uuid = uuid;
+ footer.uuid = uuid;
- footer->checksum = cpu_to_be32(vpc_checksum(buf, HEADER_SIZE));
+ footer.checksum = cpu_to_be32(vpc_checksum(&footer, sizeof(footer)));
if (disk_type == VHD_DYNAMIC) {
- ret = create_dynamic_disk(blk, buf, total_sectors);
+ ret = create_dynamic_disk(blk, &footer, total_sectors);
if (ret < 0) {
error_setg(errp, "Unable to create or write VHD header");
}
} else {
- ret = create_fixed_disk(blk, buf, total_size, errp);
+ ret = create_fixed_disk(blk, &footer, total_size, errp);
}
out:
@@ -1170,9 +1169,8 @@ fail:
static int vpc_has_zero_init(BlockDriverState *bs)
{
BDRVVPCState *s = bs->opaque;
- VHDFooter *footer = (VHDFooter *) s->footer_buf;
- if (be32_to_cpu(footer->type) == VHD_FIXED) {
+ if (be32_to_cpu(s->footer.type) == VHD_FIXED) {
return bdrv_has_zero_init(bs->file->bs);
} else {
return 1;
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 0a918e8f74..9c700c6234 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -512,6 +512,7 @@ void cpu_loop(CPUSPARCState *env)
case 0x141:
if (bsd_type != target_freebsd)
goto badtrap;
+ /* fallthrough */
case 0x100:
#endif
syscall_nr = env->gregs[1];
diff --git a/chardev/char.c b/chardev/char.c
index a9b8c5a9aa..288efebd12 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -776,15 +776,13 @@ static int qmp_query_chardev_foreach(Object *obj, void *data)
{
Chardev *chr = CHARDEV(obj);
ChardevInfoList **list = data;
- ChardevInfoList *info = g_malloc0(sizeof(*info));
+ ChardevInfo *value = g_malloc0(sizeof(*value));
- info->value = g_malloc0(sizeof(*info->value));
- info->value->label = g_strdup(chr->label);
- info->value->filename = g_strdup(chr->filename);
- info->value->frontend_open = chr->be && chr->be->fe_open;
+ value->label = g_strdup(chr->label);
+ value->filename = g_strdup(chr->filename);
+ value->frontend_open = chr->be && chr->be->fe_open;
- info->next = *list;
- *list = info;
+ QAPI_LIST_PREPEND(*list, value);
return 0;
}
@@ -803,12 +801,10 @@ static void
qmp_prepend_backend(const char *name, void *opaque)
{
ChardevBackendInfoList **list = opaque;
- ChardevBackendInfoList *info = g_malloc0(sizeof(*info));
+ ChardevBackendInfo *value = g_new0(ChardevBackendInfo, 1);
- info->value = g_malloc0(sizeof(*info->value));
- info->value->name = g_strdup(name);
- info->next = *list;
- *list = info;
+ value->name = g_strdup(name);
+ QAPI_LIST_PREPEND(*list, value);
}
ChardevBackendInfoList *qmp_query_chardev_backends(Error **errp)
diff --git a/configure b/configure
index c228f7c21e..881af4b6be 100755
--- a/configure
+++ b/configure
@@ -2023,6 +2023,7 @@ add_to warn_flags -Wempty-body
add_to warn_flags -Wnested-externs
add_to warn_flags -Wendif-labels
add_to warn_flags -Wexpansion-to-defined
+add_to warn_flags -Wimplicit-fallthrough=2
nowarn_flags=
add_to nowarn_flags -Wno-initializer-overrides
diff --git a/contrib/rdmacm-mux/main.c b/contrib/rdmacm-mux/main.c
index bd82abbad3..771ca01e03 100644
--- a/contrib/rdmacm-mux/main.c
+++ b/contrib/rdmacm-mux/main.c
@@ -186,7 +186,7 @@ static int hash_tbl_search_fd_by_ifid(int *fd, __be64 *gid_ifid)
*fd = _hash_tbl_search_fd_by_ifid(gid_ifid);
pthread_rwlock_unlock(&server.lock);
- if (!fd) {
+ if (!*fd) {
syslog(LOG_WARNING, "Can't find matching for ifid 0x%llx\n", *gid_ifid);
return -ENOENT;
}
diff --git a/disas/libvixl/vixl/a64/disasm-a64.cc b/disas/libvixl/vixl/a64/disasm-a64.cc
index 7a58a5c087..f34d1d68da 100644
--- a/disas/libvixl/vixl/a64/disasm-a64.cc
+++ b/disas/libvixl/vixl/a64/disasm-a64.cc
@@ -2985,6 +2985,10 @@ int Disassembler::SubstituteImmediateField(const Instruction* instr,
}
return 3;
}
+ default: {
+ VIXL_UNIMPLEMENTED();
+ return 0;
+ }
}
}
case 'C': { // ICondB - Immediate Conditional Branch.
diff --git a/disas/libvixl/vixl/globals.h b/disas/libvixl/vixl/globals.h
index 61dc9f7f7e..7099aa599f 100644
--- a/disas/libvixl/vixl/globals.h
+++ b/disas/libvixl/vixl/globals.h
@@ -108,10 +108,12 @@ inline void USE(T1, T2, T3, T4) {}
#define __has_warning(x) 0
#endif
-// Note: This option is only available for Clang. And will only be enabled for
-// C++11(201103L).
+// Fallthrough annotation for Clang and C++11(201103L).
#if __has_warning("-Wimplicit-fallthrough") && __cplusplus >= 201103L
#define VIXL_FALLTHROUGH() [[clang::fallthrough]] //NOLINT
+// Fallthrough annotation for GCC >= 7.
+#elif __GNUC__ >= 7
+ #define VIXL_FALLTHROUGH() __attribute__((fallthrough))
#else
#define VIXL_FALLTHROUGH() do {} while (0)
#endif
diff --git a/docs/devel/migration.rst b/docs/devel/migration.rst
index 49112bb27a..ad381b89b2 100644
--- a/docs/devel/migration.rst
+++ b/docs/devel/migration.rst
@@ -53,22 +53,23 @@ savevm/loadvm functionality.
Debugging
=========
-The migration stream can be analyzed thanks to `scripts/analyze_migration.py`.
+The migration stream can be analyzed thanks to `scripts/analyze-migration.py`.
Example usage:
.. code-block:: shell
- $ qemu-system-x86_64
- (qemu) migrate "exec:cat > mig"
- $ ./scripts/analyze_migration.py -f mig
+ $ qemu-system-x86_64 -display none -monitor stdio
+ (qemu) migrate "exec:cat > mig"
+ (qemu) q
+ $ ./scripts/analyze-migration.py -f mig
{
"ram (3)": {
"section sizes": {
"pc.ram": "0x0000000008000000",
...
-See also ``analyze_migration.py -h`` help for more options.
+See also ``analyze-migration.py -h`` help for more options.
Common infrastructure
=====================
diff --git a/docs/devel/writing-qmp-commands.txt b/docs/devel/writing-qmp-commands.txt
index 28984686c9..258e63bff5 100644
--- a/docs/devel/writing-qmp-commands.txt
+++ b/docs/devel/writing-qmp-commands.txt
@@ -531,15 +531,11 @@ TimerAlarmMethodList *qmp_query_alarm_methods(Error **errp)
bool current = true;
for (p = alarm_timers; p->name; p++) {
- TimerAlarmMethodList *info = g_malloc0(sizeof(*info));
- info->value = g_malloc0(sizeof(*info->value));
- info->value->method_name = g_strdup(p->name);
- info->value->current = current;
-
+ TimerAlarmMethod *value = g_malloc0(*value);
+ value->method_name = g_strdup(p->name);
+ value->current = current;
+ QAPI_LIST_PREPEND(method_list, value);
current = false;
-
- info->next = method_list;
- method_list = info;
}
return method_list;
diff --git a/docs/interop/conf.py b/docs/interop/conf.py
index 2634ca3410..f4370aaa13 100644
--- a/docs/interop/conf.py
+++ b/docs/interop/conf.py
@@ -23,4 +23,6 @@ man_pages = [
[], 7),
('qemu-qmp-ref', 'qemu-qmp-ref', 'QEMU QMP Reference Manual',
[], 7),
+ ('qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
+ 'QEMU Storage Daemon QMP Reference Manual', [], 7),
]
diff --git a/docs/interop/index.rst b/docs/interop/index.rst
index cd78d679d8..95d56495f6 100644
--- a/docs/interop/index.rst
+++ b/docs/interop/index.rst
@@ -20,6 +20,7 @@ Contents:
qemu-ga
qemu-ga-ref
qemu-qmp-ref
+ qemu-storage-daemon-qmp-ref
vhost-user
vhost-user-gpu
vhost-vdpa
diff --git a/docs/interop/qemu-storage-daemon-qmp-ref.rst b/docs/interop/qemu-storage-daemon-qmp-ref.rst
new file mode 100644
index 0000000000..caf9dad23a
--- /dev/null
+++ b/docs/interop/qemu-storage-daemon-qmp-ref.rst
@@ -0,0 +1,13 @@
+QEMU Storage Daemon QMP Reference Manual
+========================================
+
+..
+ TODO: the old Texinfo manual used to note that this manual
+ is GPL-v2-or-later. We should make that reader-visible
+ both here and in our Sphinx manuals more generally.
+
+..
+ TODO: display the QEMU version, both here and in our Sphinx manuals
+ more generally.
+
+.. qapi-doc:: storage-daemon/qapi/qapi-schema.json
diff --git a/docs/meson.build b/docs/meson.build
index bb8fe4c9e4..71641b4fe0 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -56,6 +56,7 @@ if build_docs
'qemu-ga.8': (have_tools ? 'man8' : ''),
'qemu-ga-ref.7': 'man7',
'qemu-qmp-ref.7': 'man7',
+ 'qemu-storage-daemon-qmp-ref.7': (have_tools ? 'man7' : ''),
},
'tools': {
'qemu-img.1': (have_tools ? 'man1' : ''),
diff --git a/docs/system/qemu-block-drivers.rst.inc b/docs/system/qemu-block-drivers.rst.inc
index b052a6d14e..60a064b232 100644
--- a/docs/system/qemu-block-drivers.rst.inc
+++ b/docs/system/qemu-block-drivers.rst.inc
@@ -952,3 +952,29 @@ on host and see if there are locks held by the QEMU process on the image file.
More than one byte could be locked by the QEMU instance, each byte of which
reflects a particular permission that is acquired or protected by the running
block driver.
+
+Filter drivers
+~~~~~~~~~~~~~~
+
+QEMU supports several filter drivers, which don't store any data, but perform
+some additional tasks, hooking io requests.
+
+.. program:: filter-drivers
+.. option:: preallocate
+
+ The preallocate filter driver is intended to be inserted between format
+ and protocol nodes and preallocates some additional space
+ (expanding the protocol file) when writing past the file’s end. This can be
+ useful for file-systems with slow allocation.
+
+ Supported options:
+
+ .. program:: preallocate
+ .. option:: prealloc-align
+
+ On preallocation, align the file length to this value (in bytes), default 1M.
+
+ .. program:: preallocate
+ .. option:: prealloc-size
+
+ How much to preallocate (in bytes), default 128M.
diff --git a/docs/tools/conf.py b/docs/tools/conf.py
index 4760d36ff2..7072d99324 100644
--- a/docs/tools/conf.py
+++ b/docs/tools/conf.py
@@ -20,6 +20,8 @@ html_theme_options['description'] = \
man_pages = [
('qemu-img', 'qemu-img', u'QEMU disk image utility',
['Fabrice Bellard'], 1),
+ ('qemu-storage-daemon', 'qemu-storage-daemon', u'QEMU storage daemon',
+ [], 1),
('qemu-nbd', 'qemu-nbd', u'QEMU Disk Network Block Device Server',
['Anthony Liguori <anthony@codemonkey.ws>'], 8),
('qemu-pr-helper', 'qemu-pr-helper', 'QEMU persistent reservation helper',
diff --git a/docs/tools/index.rst b/docs/tools/index.rst
index b99f86c7c6..3a5829c17a 100644
--- a/docs/tools/index.rst
+++ b/docs/tools/index.rst
@@ -11,6 +11,7 @@ Contents:
:maxdepth: 2
qemu-img
+ qemu-storage-daemon
qemu-nbd
qemu-pr-helper
qemu-trace-stap
diff --git a/docs/tools/qemu-storage-daemon.rst b/docs/tools/qemu-storage-daemon.rst
new file mode 100644
index 0000000000..f63627eaf6
--- /dev/null
+++ b/docs/tools/qemu-storage-daemon.rst
@@ -0,0 +1,148 @@
+QEMU Storage Daemon
+===================
+
+Synopsis
+--------
+
+**qemu-storage-daemon** [options]
+
+Description
+-----------
+
+qemu-storage-daemon provides disk image functionality from QEMU, qemu-img, and
+qemu-nbd in a long-running process controlled via QMP commands without running
+a virtual machine. It can export disk images, run block job operations, and
+perform other disk-related operations. The daemon is controlled via a QMP
+monitor and initial configuration from the command-line.
+
+The daemon offers the following subset of QEMU features:
+
+* Block nodes
+* Block jobs
+* Block exports
+* Throttle groups
+* Character devices
+* Crypto and secrets
+* QMP
+* IOThreads
+
+Commands can be sent over a QEMU Monitor Protocol (QMP) connection. See the
+:manpage:`qemu-storage-daemon-qmp-ref(7)` manual page for a description of the
+commands.
+
+The daemon runs until it is stopped using the ``quit`` QMP command or
+SIGINT/SIGHUP/SIGTERM.
+
+**Warning:** Never modify images in use by a running virtual machine or any
+other process; this may destroy the image. Also, be aware that querying an
+image that is being modified by another process may encounter inconsistent
+state.
+
+Options
+-------
+
+.. program:: qemu-storage-daemon
+
+Standard options:
+
+.. option:: -h, --help
+
+ Display help and exit
+
+.. option:: -V, --version
+
+ Display version information and exit
+
+.. option:: -T, --trace [[enable=]PATTERN][,events=FILE][,file=FILE]
+
+ .. include:: ../qemu-option-trace.rst.inc
+
+.. option:: --blockdev BLOCKDEVDEF
+
+ is a block node definition. See the :manpage:`qemu(1)` manual page for a
+ description of block node properties and the :manpage:`qemu-block-drivers(7)`
+ manual page for a description of driver-specific parameters.
+
+.. option:: --chardev CHARDEVDEF
+
+ is a character device definition. See the :manpage:`qemu(1)` manual page for
+ a description of character device properties. A common character device
+ definition configures a UNIX domain socket::
+
+ --chardev socket,id=char1,path=/tmp/qmp.sock,server,nowait
+
+.. option:: --export [type=]nbd,id=<id>,node-name=<node-name>[,name=<export-name>][,writable=on|off][,bitmap=<name>]
+ --export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,addr.type=unix,addr.path=<socket-path>[,writable=on|off][,logical-block-size=<block-size>][,num-queues=<num-queues>]
+ --export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,addr.type=fd,addr.str=<fd>[,writable=on|off][,logical-block-size=<block-size>][,num-queues=<num-queues>]
+
+ is a block export definition. ``node-name`` is the block node that should be
+ exported. ``writable`` determines whether or not the export allows write
+ requests for modifying data (the default is off).
+
+ The ``nbd`` export type requires ``--nbd-server`` (see below). ``name`` is
+ the NBD export name. ``bitmap`` is the name of a dirty bitmap reachable from
+ the block node, so the NBD client can use NBD_OPT_SET_META_CONTEXT with the
+ metadata context name "qemu:dirty-bitmap:BITMAP" to inspect the bitmap.
+
+ The ``vhost-user-blk`` export type takes a vhost-user socket address on which
+ it accept incoming connections. Both
+ ``addr.type=unix,addr.path=<socket-path>`` for UNIX domain sockets and
+ ``addr.type=fd,addr.str=<fd>`` for file descriptor passing are supported.
+ ``logical-block-size`` sets the logical block size in bytes (the default is
+ 512). ``num-queues`` sets the number of virtqueues (the default is 1).
+
+.. option:: --monitor MONITORDEF
+
+ is a QMP monitor definition. See the :manpage:`qemu(1)` manual page for
+ a description of QMP monitor properties. A common QMP monitor definition
+ configures a monitor on character device ``char1``::
+
+ --monitor chardev=char1
+
+.. option:: --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>[,tls-creds=<id>][,tls-authz=<id>][,max-connections=<n>]
+ --nbd-server addr.type=unix,addr.path=<path>[,tls-creds=<id>][,tls-authz=<id>][,max-connections=<n>]
+
+ is a server for NBD exports. Both TCP and UNIX domain sockets are supported.
+ TLS encryption can be configured using ``--object`` tls-creds-* and authz-*
+ secrets (see below).
+
+ To configure an NBD server on UNIX domain socket path ``/tmp/nbd.sock``::
+
+ --nbd-server addr.type=unix,addr.path=/tmp/nbd.sock
+
+.. option:: --object help
+ --object <type>,help
+ --object <type>[,<property>=<value>...]
+
+ is a QEMU user creatable object definition. List object types with ``help``.
+ List object properties with ``<type>,help``. See the :manpage:`qemu(1)`
+ manual page for a description of the object properties.
+
+Examples
+--------
+Launch the daemon with QMP monitor socket ``qmp.sock`` so clients can execute
+QMP commands::
+
+ $ qemu-storage-daemon \
+ --chardev socket,path=qmp.sock,server,nowait,id=char1 \
+ --monitor chardev=char1
+
+Export raw image file ``disk.img`` over NBD UNIX domain socket ``nbd.sock``::
+
+ $ qemu-storage-daemon \
+ --blockdev driver=file,node-name=disk,filename=disk.img \
+ --nbd-server addr.type=unix,addr.path=nbd.sock \
+ --export type=nbd,id=export,node-name=disk,writable=on
+
+Export a qcow2 image file ``disk.qcow2`` as a vhosts-user-blk device over UNIX
+domain socket ``vhost-user-blk.sock``::
+
+ $ qemu-storage-daemon \
+ --blockdev driver=file,node-name=file,filename=disk.qcow2 \
+ --blockdev driver=qcow2,node-name=qcow2,file=file \
+ --export type=vhost-user-blk,id=export,addr.type=unix,addr.path=vhost-user-blk.sock,node-name=qcow2
+
+See also
+--------
+
+:manpage:`qemu(1)`, :manpage:`qemu-block-drivers(7)`, :manpage:`qemu-storage-daemon-qmp-ref(7)`
diff --git a/docs/user/main.rst b/docs/user/main.rst
index bd99b0fdbe..8dfe232a3a 100644
--- a/docs/user/main.rst
+++ b/docs/user/main.rst
@@ -170,68 +170,81 @@ QEMU_STRACE
Other binaries
~~~~~~~~~~~~~~
-user mode (Alpha)
-``qemu-alpha`` TODO.
+- user mode (Alpha)
-user mode (Arm)
-``qemu-armeb`` TODO.
+ * ``qemu-alpha`` TODO.
-user mode (Arm)
-``qemu-arm`` is also capable of running Arm \"Angel\" semihosted ELF
-binaries (as implemented by the arm-elf and arm-eabi Newlib/GDB
-configurations), and arm-uclinux bFLT format binaries.
+- user mode (Arm)
-user mode (ColdFire)
-user mode (M68K)
-``qemu-m68k`` is capable of running semihosted binaries using the BDM
-(m5xxx-ram-hosted.ld) or m68k-sim (sim.ld) syscall interfaces, and
-coldfire uClinux bFLT format binaries.
+ * ``qemu-armeb`` TODO.
-The binary format is detected automatically.
+ * ``qemu-arm`` is also capable of running Arm \"Angel\" semihosted ELF
+ binaries (as implemented by the arm-elf and arm-eabi Newlib/GDB
+ configurations), and arm-uclinux bFLT format binaries.
-user mode (Cris)
-``qemu-cris`` TODO.
+- user mode (ColdFire)
-user mode (i386)
-``qemu-i386`` TODO. ``qemu-x86_64`` TODO.
+- user mode (M68K)
-user mode (Microblaze)
-``qemu-microblaze`` TODO.
+ * ``qemu-m68k`` is capable of running semihosted binaries using the BDM
+ (m5xxx-ram-hosted.ld) or m68k-sim (sim.ld) syscall interfaces, and
+ coldfire uClinux bFLT format binaries.
-user mode (MIPS)
-``qemu-mips`` executes 32-bit big endian MIPS binaries (MIPS O32 ABI).
+ The binary format is detected automatically.
-``qemu-mipsel`` executes 32-bit little endian MIPS binaries (MIPS O32
-ABI).
+- user mode (Cris)
-``qemu-mips64`` executes 64-bit big endian MIPS binaries (MIPS N64 ABI).
+ * ``qemu-cris`` TODO.
-``qemu-mips64el`` executes 64-bit little endian MIPS binaries (MIPS N64
-ABI).
+- user mode (i386)
-``qemu-mipsn32`` executes 32-bit big endian MIPS binaries (MIPS N32
-ABI).
+ * ``qemu-i386`` TODO.
+ * ``qemu-x86_64`` TODO.
-``qemu-mipsn32el`` executes 32-bit little endian MIPS binaries (MIPS N32
-ABI).
+- user mode (Microblaze)
-user mode (NiosII)
-``qemu-nios2`` TODO.
+ * ``qemu-microblaze`` TODO.
-user mode (PowerPC)
-``qemu-ppc64abi32`` TODO. ``qemu-ppc64`` TODO. ``qemu-ppc`` TODO.
+- user mode (MIPS)
-user mode (SH4)
-``qemu-sh4eb`` TODO. ``qemu-sh4`` TODO.
+ * ``qemu-mips`` executes 32-bit big endian MIPS binaries (MIPS O32 ABI).
-user mode (SPARC)
-``qemu-sparc`` can execute Sparc32 binaries (Sparc32 CPU, 32 bit ABI).
+ * ``qemu-mipsel`` executes 32-bit little endian MIPS binaries (MIPS O32 ABI).
-``qemu-sparc32plus`` can execute Sparc32 and SPARC32PLUS binaries
-(Sparc64 CPU, 32 bit ABI).
+ * ``qemu-mips64`` executes 64-bit big endian MIPS binaries (MIPS N64 ABI).
-``qemu-sparc64`` can execute some Sparc64 (Sparc64 CPU, 64 bit ABI) and
-SPARC32PLUS binaries (Sparc64 CPU, 32 bit ABI).
+ * ``qemu-mips64el`` executes 64-bit little endian MIPS binaries (MIPS N64
+ ABI).
+
+ * ``qemu-mipsn32`` executes 32-bit big endian MIPS binaries (MIPS N32 ABI).
+
+ * ``qemu-mipsn32el`` executes 32-bit little endian MIPS binaries (MIPS N32
+ ABI).
+
+- user mode (NiosII)
+
+ * ``qemu-nios2`` TODO.
+
+- user mode (PowerPC)
+
+ * ``qemu-ppc64abi32`` TODO.
+ * ``qemu-ppc64`` TODO.
+ * ``qemu-ppc`` TODO.
+
+- user mode (SH4)
+
+ * ``qemu-sh4eb`` TODO.
+ * ``qemu-sh4`` TODO.
+
+- user mode (SPARC)
+
+ * ``qemu-sparc`` can execute Sparc32 binaries (Sparc32 CPU, 32 bit ABI).
+
+ * ``qemu-sparc32plus`` can execute Sparc32 and SPARC32PLUS binaries
+ (Sparc64 CPU, 32 bit ABI).
+
+ * ``qemu-sparc64`` can execute some Sparc64 (Sparc64 CPU, 64 bit ABI) and
+ SPARC32PLUS binaries (Sparc64 CPU, 32 bit ABI).
BSD User space emulator
-----------------------
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 470a420c2d..73e0832ea1 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -40,7 +40,7 @@ SRST
ERST
{
- .name = "q|quit",
+ .name = "quit|q",
.args_type = "",
.params = "",
.help = "quit the emulator",
@@ -49,7 +49,7 @@ ERST
},
SRST
-``q`` or ``quit``
+``quit`` or ``q``
Quit the emulator.
ERST
@@ -401,7 +401,7 @@ SRST
ERST
{
- .name = "c|cont",
+ .name = "cont|c",
.args_type = "",
.params = "",
.help = "resume emulation",
@@ -409,7 +409,7 @@ ERST
},
SRST
-``c`` or ``cont``
+``cont`` or ``c``
Resume emulation.
ERST
@@ -554,7 +554,7 @@ SRST
ERST
{
- .name = "p|print",
+ .name = "print|p",
.args_type = "fmt:/,val:l",
.params = "/fmt expr",
.help = "print expression value (use $reg for CPU register access)",
@@ -562,7 +562,7 @@ ERST
},
SRST
-``p`` or ``print/``\ *fmt* *expr*
+``print`` or ``p/``\ *fmt* *expr*
Print expression value. Only the *format* part of *fmt* is
used.
ERST
diff --git a/hw/block/nand.c b/hw/block/nand.c
index 1d7a48a2ec..9ed54a0a92 100644
--- a/hw/block/nand.c
+++ b/hw/block/nand.c
@@ -137,7 +137,7 @@ static void mem_and(uint8_t *dest, const uint8_t *src, size_t n)
# define ADDR_SHIFT 16
# include "nand.c"
-/* Information based on Linux drivers/mtd/nand/nand_ids.c */
+/* Information based on Linux drivers/mtd/nand/raw/nand_ids.c */
static const struct {
int size;
int width;
@@ -147,21 +147,11 @@ static const struct {
} nand_flash_ids[0x100] = {
[0 ... 0xff] = { 0 },
- [0x6e] = { 1, 8, 8, 4, 0 },
- [0x64] = { 2, 8, 8, 4, 0 },
[0x6b] = { 4, 8, 9, 4, 0 },
- [0xe8] = { 1, 8, 8, 4, 0 },
- [0xec] = { 1, 8, 8, 4, 0 },
- [0xea] = { 2, 8, 8, 4, 0 },
- [0xd5] = { 4, 8, 9, 4, 0 },
[0xe3] = { 4, 8, 9, 4, 0 },
[0xe5] = { 4, 8, 9, 4, 0 },
[0xd6] = { 8, 8, 9, 4, 0 },
-
- [0x39] = { 8, 8, 9, 4, 0 },
[0xe6] = { 8, 8, 9, 4, 0 },
- [0x49] = { 8, 16, 9, 4, NAND_BUSWIDTH_16 },
- [0x59] = { 8, 16, 9, 4, NAND_BUSWIDTH_16 },
[0x33] = { 16, 8, 9, 5, 0 },
[0x73] = { 16, 8, 9, 5, 0 },
diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
index 87f14140a3..affffe0c4a 100644
--- a/hw/core/machine-qmp-cmds.c
+++ b/hw/core/machine-qmp-cmds.c
@@ -215,7 +215,6 @@ MachineInfoList *qmp_query_machines(Error **errp)
for (el = machines; el; el = el->next) {
MachineClass *mc = el->data;
- MachineInfoList *entry;
MachineInfo *info;
info = g_malloc0(sizeof(*info));
@@ -243,10 +242,7 @@ MachineInfoList *qmp_query_machines(Error **errp)
info->has_default_ram_id = true;
}
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = mach_list;
- mach_list = entry;
+ QAPI_LIST_PREPEND(mach_list, info);
}
g_slist_free(machines);
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 05dcaf09c9..de3b8f1b31 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -504,11 +504,7 @@ static void machine_set_nvdimm_persistence(Object *obj, const char *value,
void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type)
{
- strList *item = g_new0(strList, 1);
-
- item->value = g_strdup(type);
- item->next = mc->allowed_dynamic_sysbus_devices;
- mc->allowed_dynamic_sysbus_devices = item;
+ QAPI_LIST_PREPEND(mc->allowed_dynamic_sysbus_devices, g_strdup(type));
}
static void validate_sysbus_device(SysBusDevice *sbdev, void *opaque)
@@ -569,7 +565,6 @@ HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine)
for (i = 0; i < machine->possible_cpus->len; i++) {
Object *cpu;
- HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1);
HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1);
cpu_item->type = g_strdup(machine->possible_cpus->cpus[i].type);
@@ -582,9 +577,7 @@ HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine)
cpu_item->has_qom_path = true;
cpu_item->qom_path = object_get_canonical_path(cpu);
}
- list_item->value = cpu_item;
- list_item->next = head;
- head = list_item;
+ QAPI_LIST_PREPEND(head, cpu_item);
}
return head;
}
diff --git a/hw/core/register.c b/hw/core/register.c
index 3600ef5bde..d6f8c20816 100644
--- a/hw/core/register.c
+++ b/hw/core/register.c
@@ -80,7 +80,7 @@ void register_write(RegisterInfo *reg, uint64_t val, uint64_t we,
if (!ac || !ac->name) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state "
- "(written value: %#" PRIx64 ")\n", prefix, val);
+ "(written value: 0x%" PRIx64 ")\n", prefix, val);
return;
}
@@ -89,14 +89,14 @@ void register_write(RegisterInfo *reg, uint64_t val, uint64_t we,
test = (old_val ^ val) & ac->rsvd;
if (test) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: change of value in reserved bit"
- "fields: %#" PRIx64 ")\n", prefix, test);
+ "fields: 0x%" PRIx64 ")\n", prefix, test);
}
test = val & ac->unimp;
if (test) {
qemu_log_mask(LOG_UNIMP,
- "%s:%s writing %#" PRIx64 " to unimplemented bits:" \
- " %#" PRIx64 "\n",
+ "%s:%s writing 0x%" PRIx64 " to unimplemented bits:" \
+ " 0x%" PRIx64 "\n",
prefix, reg->access->name, val, ac->unimp);
}
@@ -112,7 +112,7 @@ void register_write(RegisterInfo *reg, uint64_t val, uint64_t we,
}
if (debug) {
- qemu_log("%s:%s: write of value %#" PRIx64 "\n", prefix, ac->name,
+ qemu_log("%s:%s: write of value 0x%" PRIx64 "\n", prefix, ac->name,
new_val);
}
@@ -150,7 +150,7 @@ uint64_t register_read(RegisterInfo *reg, uint64_t re, const char* prefix,
}
if (debug) {
- qemu_log("%s:%s: read of value %#" PRIx64 "\n", prefix,
+ qemu_log("%s:%s: read of value 0x%" PRIx64 "\n", prefix,
ac->name, ret);
}
@@ -193,7 +193,7 @@ void register_write_memory(void *opaque, hwaddr addr,
if (!reg) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: write to unimplemented register " \
- "at address: %#" PRIx64 "\n", reg_array->prefix, addr);
+ "at address: 0x%" PRIx64 "\n", reg_array->prefix, addr);
return;
}
@@ -222,7 +222,7 @@ uint64_t register_read_memory(void *opaque, hwaddr addr,
if (!reg) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: read to unimplemented register " \
- "at address: %#" PRIx64 "\n", reg_array->prefix, addr);
+ "at address: 0x%" PRIx64 "\n", reg_array->prefix, addr);
return 0;
}
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index f3b71fa9c7..0e833a462b 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -970,7 +970,7 @@ static const VMStateDescription vmstate_virtio_gpu_scanouts = {
};
static int virtio_gpu_save(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
VirtIOGPU *g = opaque;
struct virtio_gpu_simple_resource *res;
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index 187eb054e0..d040a5d1e9 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -478,9 +478,11 @@ static void kvm_arm_gicv3_put(GICv3State *s)
kvm_gicc_access(s, ICC_AP0R_EL1(3), ncpu, &reg64, true);
reg64 = c->icc_apr[GICV3_G0][2];
kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, &reg64, true);
+ /* fall through */
case 6:
reg64 = c->icc_apr[GICV3_G0][1];
kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, &reg64, true);
+ /* fall through */
default:
reg64 = c->icc_apr[GICV3_G0][0];
kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, &reg64, true);
@@ -492,9 +494,11 @@ static void kvm_arm_gicv3_put(GICv3State *s)
kvm_gicc_access(s, ICC_AP1R_EL1(3), ncpu, &reg64, true);
reg64 = c->icc_apr[GICV3_G1NS][2];
kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, &reg64, true);
+ /* fall through */
case 6:
reg64 = c->icc_apr[GICV3_G1NS][1];
kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, &reg64, true);
+ /* fall through */
default:
reg64 = c->icc_apr[GICV3_G1NS][0];
kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, &reg64, true);
@@ -631,9 +635,11 @@ static void kvm_arm_gicv3_get(GICv3State *s)
c->icc_apr[GICV3_G0][3] = reg64;
kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, &reg64, false);
c->icc_apr[GICV3_G0][2] = reg64;
+ /* fall through */
case 6:
kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, &reg64, false);
c->icc_apr[GICV3_G0][1] = reg64;
+ /* fall through */
default:
kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, &reg64, false);
c->icc_apr[GICV3_G0][0] = reg64;
@@ -645,9 +651,11 @@ static void kvm_arm_gicv3_get(GICv3State *s)
c->icc_apr[GICV3_G1NS][3] = reg64;
kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, &reg64, false);
c->icc_apr[GICV3_G1NS][2] = reg64;
+ /* fall through */
case 6:
kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, &reg64, false);
c->icc_apr[GICV3_G1NS][1] = reg64;
+ /* fall through */
default:
kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, &reg64, false);
c->icc_apr[GICV3_G1NS][0] = reg64;
diff --git a/hw/intc/ibex_plic.c b/hw/intc/ibex_plic.c
index 341c9db405..c1b72fcab0 100644
--- a/hw/intc/ibex_plic.c
+++ b/hw/intc/ibex_plic.c
@@ -43,16 +43,23 @@ static void ibex_plic_irqs_set_pending(IbexPlicState *s, int irq, bool level)
{
int pending_num = irq / 32;
+ if (!level) {
+ /*
+ * If the level is low make sure we clear the hidden_pending.
+ */
+ s->hidden_pending[pending_num] &= ~(1 << (irq % 32));
+ }
+
if (s->claimed[pending_num] & 1 << (irq % 32)) {
/*
* The interrupt has been claimed, but not completed.
* The pending bit can't be set.
+ * Save the pending level for after the interrupt is completed.
*/
s->hidden_pending[pending_num] |= level << (irq % 32);
- return;
+ } else {
+ s->pending[pending_num] |= level << (irq % 32);
}
-
- s->pending[pending_num] |= level << (irq % 32);
}
static bool ibex_plic_irqs_pending(IbexPlicState *s, uint32_t context)
diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
index 35d91afa55..b3fb9f8395 100644
--- a/hw/intc/s390_flic_kvm.c
+++ b/hw/intc/s390_flic_kvm.c
@@ -386,7 +386,7 @@ static void kvm_s390_release_adapter_routes(S390FLICState *fs,
* reached
*/
static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
KVMS390FLICState *flic = opaque;
int len = FLIC_SAVE_INITIAL_SIZE;
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
index 1af1e6fa2f..c53a02315e 100644
--- a/hw/net/rocker/rocker.c
+++ b/hw/net/rocker/rocker.c
@@ -127,13 +127,7 @@ RockerPortList *qmp_query_rocker_ports(const char *name, Error **errp)
}
for (i = r->fp_ports - 1; i >= 0; i--) {
- RockerPortList *info = g_malloc0(sizeof(*info));
- info->value = g_malloc0(sizeof(*info->value));
- struct fp_port *port = r->fp_port[i];
-
- fp_port_get_info(port, info);
- info->next = list;
- list = info;
+ QAPI_LIST_PREPEND(list, fp_port_get_info(r->fp_port[i]));
}
return list;
diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c
index 4aa7da79b8..cbeed65bd5 100644
--- a/hw/net/rocker/rocker_fp.c
+++ b/hw/net/rocker/rocker_fp.c
@@ -51,14 +51,17 @@ bool fp_port_get_link_up(FpPort *port)
return !qemu_get_queue(port->nic)->link_down;
}
-void fp_port_get_info(FpPort *port, RockerPortList *info)
+RockerPort *fp_port_get_info(FpPort *port)
{
- info->value->name = g_strdup(port->name);
- info->value->enabled = port->enabled;
- info->value->link_up = fp_port_get_link_up(port);
- info->value->speed = port->speed;
- info->value->duplex = port->duplex;
- info->value->autoneg = port->autoneg;
+ RockerPort *value = g_malloc0(sizeof(*value));
+
+ value->name = g_strdup(port->name);
+ value->enabled = port->enabled;
+ value->link_up = fp_port_get_link_up(port);
+ value->speed = port->speed;
+ value->duplex = port->duplex;
+ value->autoneg = port->autoneg;
+ return value;
}
void fp_port_get_macaddr(FpPort *port, MACAddr *macaddr)
diff --git a/hw/net/rocker/rocker_fp.h b/hw/net/rocker/rocker_fp.h
index dbe1dd329a..7ff57aac01 100644
--- a/hw/net/rocker/rocker_fp.h
+++ b/hw/net/rocker/rocker_fp.h
@@ -28,7 +28,7 @@ int fp_port_eg(FpPort *port, const struct iovec *iov, int iovcnt);
char *fp_port_get_name(FpPort *port);
bool fp_port_get_link_up(FpPort *port);
-void fp_port_get_info(FpPort *port, RockerPortList *info);
+RockerPort *fp_port_get_info(FpPort *port);
void fp_port_get_macaddr(FpPort *port, MACAddr *macaddr);
void fp_port_set_macaddr(FpPort *port, MACAddr *macaddr);
uint8_t fp_port_get_learning(FpPort *port);
diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c
index 8e347d1ee4..b3b8c5bb6d 100644
--- a/hw/net/rocker/rocker_of_dpa.c
+++ b/hw/net/rocker/rocker_of_dpa.c
@@ -2296,7 +2296,6 @@ static void of_dpa_flow_fill(void *cookie, void *value, void *user_data)
struct of_dpa_flow_key *key = &flow->key;
struct of_dpa_flow_key *mask = &flow->mask;
struct of_dpa_flow_fill_context *flow_context = user_data;
- RockerOfDpaFlowList *new;
RockerOfDpaFlow *nflow;
RockerOfDpaFlowKey *nkey;
RockerOfDpaFlowMask *nmask;
@@ -2307,8 +2306,7 @@ static void of_dpa_flow_fill(void *cookie, void *value, void *user_data)
return;
}
- new = g_malloc0(sizeof(*new));
- nflow = new->value = g_malloc0(sizeof(*nflow));
+ nflow = g_malloc0(sizeof(*nflow));
nkey = nflow->key = g_malloc0(sizeof(*nkey));
nmask = nflow->mask = g_malloc0(sizeof(*nmask));
naction = nflow->action = g_malloc0(sizeof(*naction));
@@ -2424,8 +2422,7 @@ static void of_dpa_flow_fill(void *cookie, void *value, void *user_data)
naction->new_vlan_id = flow->action.apply.new_vlan_id;
}
- new->next = flow_context->list;
- flow_context->list = new;
+ QAPI_LIST_PREPEND(flow_context->list, nflow);
}
RockerOfDpaFlowList *qmp_query_rocker_of_dpa_flows(const char *name,
@@ -2469,9 +2466,7 @@ static void of_dpa_group_fill(void *key, void *value, void *user_data)
{
struct of_dpa_group *group = value;
struct of_dpa_group_fill_context *flow_context = user_data;
- RockerOfDpaGroupList *new;
RockerOfDpaGroup *ngroup;
- struct uint32List *id;
int i;
if (flow_context->type != 9 &&
@@ -2479,8 +2474,7 @@ static void of_dpa_group_fill(void *key, void *value, void *user_data)
return;
}
- new = g_malloc0(sizeof(*new));
- ngroup = new->value = g_malloc0(sizeof(*ngroup));
+ ngroup = g_malloc0(sizeof(*ngroup));
ngroup->id = group->id;
@@ -2525,10 +2519,7 @@ static void of_dpa_group_fill(void *key, void *value, void *user_data)
ngroup->index = ROCKER_GROUP_INDEX_GET(group->id);
for (i = 0; i < group->l2_flood.group_count; i++) {
ngroup->has_group_ids = true;
- id = g_malloc0(sizeof(*id));
- id->value = group->l2_flood.group_ids[i];
- id->next = ngroup->group_ids;
- ngroup->group_ids = id;
+ QAPI_LIST_PREPEND(ngroup->group_ids, group->l2_flood.group_ids[i]);
}
break;
case ROCKER_OF_DPA_GROUP_TYPE_L3_UCAST:
@@ -2557,8 +2548,7 @@ static void of_dpa_group_fill(void *key, void *value, void *user_data)
break;
}
- new->next = flow_context->list;
- flow_context->list = new;
+ QAPI_LIST_PREPEND(flow_context->list, ngroup);
}
RockerOfDpaGroupList *qmp_query_rocker_of_dpa_groups(const char *name,
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 044ac95f6f..8356eeec13 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -437,17 +437,14 @@ static void rxfilter_notify(NetClientState *nc)
static intList *get_vlan_table(VirtIONet *n)
{
- intList *list, *entry;
+ intList *list;
int i, j;
list = NULL;
for (i = 0; i < MAX_VLAN >> 5; i++) {
for (j = 0; n->vlans[i] && j <= 0x1f; j++) {
if (n->vlans[i] & (1U << j)) {
- entry = g_malloc0(sizeof(*entry));
- entry->value = (i << 5) + j;
- entry->next = list;
- list = entry;
+ QAPI_LIST_PREPEND(list, (i << 5) + j);
}
}
}
@@ -460,7 +457,7 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
VirtIONet *n = qemu_get_nic_opaque(nc);
VirtIODevice *vdev = VIRTIO_DEVICE(n);
RxFilterInfo *info;
- strList *str_list, *entry;
+ strList *str_list;
int i;
info = g_malloc0(sizeof(*info));
@@ -491,19 +488,15 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
str_list = NULL;
for (i = 0; i < n->mac_table.first_multi; i++) {
- entry = g_malloc0(sizeof(*entry));
- entry->value = qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN);
- entry->next = str_list;
- str_list = entry;
+ QAPI_LIST_PREPEND(str_list,
+ qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN));
}
info->unicast_table = str_list;
str_list = NULL;
for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) {
- entry = g_malloc0(sizeof(*entry));
- entry->value = qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN);
- entry->next = str_list;
- str_list = entry;
+ QAPI_LIST_PREPEND(str_list,
+ qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN));
}
info->multicast_table = str_list;
info->vlan_table = get_vlan_table(n);
diff --git a/hw/nvram/eeprom93xx.c b/hw/nvram/eeprom93xx.c
index ca6f591c84..a1b9c78844 100644
--- a/hw/nvram/eeprom93xx.c
+++ b/hw/nvram/eeprom93xx.c
@@ -104,7 +104,7 @@ static int get_uint16_from_uint8(QEMUFile *f, void *pv, size_t size,
}
static int put_unused(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
fprintf(stderr, "uint16_from_uint8 is used only for backwards compatibility.\n");
fprintf(stderr, "Never should be used to write a new state.\n");
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 44cb274a32..9b8dcca4ea 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -583,7 +583,7 @@ static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size,
}
static int put_unused(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n");
fprintf(stderr, "This functions shouldn't be called.\n");
diff --git a/hw/pci/msix.c b/hw/pci/msix.c
index 36491ee52b..ae9331cd0b 100644
--- a/hw/pci/msix.c
+++ b/hw/pci/msix.c
@@ -634,7 +634,7 @@ void msix_unset_vector_notifiers(PCIDevice *dev)
}
static int put_msix_state(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
msix_save(pv, f);
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index d4349ea577..dd589cd7c7 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -559,7 +559,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size,
/* just put buffer */
static int put_pci_config_device(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
const uint8_t **v = pv;
assert(size == pci_config_size(container_of(pv, PCIDevice, config)));
@@ -597,7 +597,7 @@ static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size,
}
static int put_pci_irq_state(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
int i;
PCIDevice *s = container_of(pv, PCIDevice, irq_state);
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index b00dce629c..4786a44996 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -699,7 +699,7 @@ void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
}
static int shpc_save(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
PCIDevice *d = container_of(pv, PCIDevice, shpc);
qemu_put_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
diff --git a/hw/rdma/rdma_backend.c b/hw/rdma/rdma_backend.c
index 5de010b1fa..6dcdfbbbe2 100644
--- a/hw/rdma/rdma_backend.c
+++ b/hw/rdma/rdma_backend.c
@@ -78,7 +78,7 @@ static void clean_recv_mads(RdmaBackendDev *backend_dev)
unsigned long cqe_ctx_id;
do {
- cqe_ctx_id = rdma_protected_qlist_pop_int64(&backend_dev->
+ cqe_ctx_id = rdma_protected_gqueue_pop_int64(&backend_dev->
recv_mads_list);
if (cqe_ctx_id != -ENOENT) {
qatomic_inc(&backend_dev->rdma_dev_res->stats.missing_cqe);
@@ -597,7 +597,7 @@ static unsigned int save_mad_recv_buffer(RdmaBackendDev *backend_dev,
bctx->up_ctx = ctx;
bctx->sge = *sge;
- rdma_protected_qlist_append_int64(&backend_dev->recv_mads_list, bctx_id);
+ rdma_protected_gqueue_append_int64(&backend_dev->recv_mads_list, bctx_id);
return 0;
}
@@ -1111,7 +1111,7 @@ static void process_incoming_mad_req(RdmaBackendDev *backend_dev,
trace_mad_message("recv", msg->umad.mad, msg->umad_len);
- cqe_ctx_id = rdma_protected_qlist_pop_int64(&backend_dev->recv_mads_list);
+ cqe_ctx_id = rdma_protected_gqueue_pop_int64(&backend_dev->recv_mads_list);
if (cqe_ctx_id == -ENOENT) {
rdma_warn_report("No more free MADs buffers, waiting for a while");
sleep(THR_POLL_TO);
@@ -1185,7 +1185,7 @@ static int mad_init(RdmaBackendDev *backend_dev, CharBackend *mad_chr_be)
return -EIO;
}
- rdma_protected_qlist_init(&backend_dev->recv_mads_list);
+ rdma_protected_gqueue_init(&backend_dev->recv_mads_list);
enable_rdmacm_mux_async(backend_dev);
@@ -1205,7 +1205,7 @@ static void mad_fini(RdmaBackendDev *backend_dev)
{
disable_rdmacm_mux_async(backend_dev);
qemu_chr_fe_disconnect(backend_dev->rdmacm_mux.chr_be);
- rdma_protected_qlist_destroy(&backend_dev->recv_mads_list);
+ rdma_protected_gqueue_destroy(&backend_dev->recv_mads_list);
}
int rdma_backend_get_gid_index(RdmaBackendDev *backend_dev,
diff --git a/hw/rdma/rdma_backend_defs.h b/hw/rdma/rdma_backend_defs.h
index 0b55be3503..4e6c0ad695 100644
--- a/hw/rdma/rdma_backend_defs.h
+++ b/hw/rdma/rdma_backend_defs.h
@@ -43,7 +43,7 @@ typedef struct RdmaBackendDev {
struct ibv_context *context;
struct ibv_comp_channel *channel;
uint8_t port_num;
- RdmaProtectedQList recv_mads_list;
+ RdmaProtectedGQueue recv_mads_list;
RdmaCmMux rdmacm_mux;
} RdmaBackendDev;
diff --git a/hw/rdma/rdma_utils.c b/hw/rdma/rdma_utils.c
index 698ed4716c..98df58f689 100644
--- a/hw/rdma/rdma_utils.c
+++ b/hw/rdma/rdma_utils.c
@@ -14,8 +14,6 @@
*/
#include "qemu/osdep.h"
-#include "qapi/qmp/qlist.h"
-#include "qapi/qmp/qnum.h"
#include "trace.h"
#include "rdma_utils.h"
@@ -54,41 +52,46 @@ void rdma_pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len)
}
}
-void rdma_protected_qlist_init(RdmaProtectedQList *list)
+void rdma_protected_gqueue_init(RdmaProtectedGQueue *list)
{
qemu_mutex_init(&list->lock);
- list->list = qlist_new();
+ list->list = g_queue_new();
}
-void rdma_protected_qlist_destroy(RdmaProtectedQList *list)
+void rdma_protected_gqueue_destroy(RdmaProtectedGQueue *list)
{
if (list->list) {
- qlist_destroy_obj(QOBJECT(list->list));
+ g_queue_free_full(list->list, g_free);
qemu_mutex_destroy(&list->lock);
list->list = NULL;
}
}
-void rdma_protected_qlist_append_int64(RdmaProtectedQList *list, int64_t value)
+void rdma_protected_gqueue_append_int64(RdmaProtectedGQueue *list,
+ int64_t value)
{
qemu_mutex_lock(&list->lock);
- qlist_append_int(list->list, value);
+ g_queue_push_tail(list->list, g_memdup(&value, sizeof(value)));
qemu_mutex_unlock(&list->lock);
}
-int64_t rdma_protected_qlist_pop_int64(RdmaProtectedQList *list)
+int64_t rdma_protected_gqueue_pop_int64(RdmaProtectedGQueue *list)
{
- QObject *obj;
+ int64_t *valp;
+ int64_t val;
qemu_mutex_lock(&list->lock);
- obj = qlist_pop(list->list);
+
+ valp = g_queue_pop_head(list->list);
qemu_mutex_unlock(&list->lock);
- if (!obj) {
+ if (!valp) {
return -ENOENT;
}
- return qnum_get_uint(qobject_to(QNum, obj));
+ val = *valp;
+ g_free(valp);
+ return val;
}
void rdma_protected_gslist_init(RdmaProtectedGSList *list)
diff --git a/hw/rdma/rdma_utils.h b/hw/rdma/rdma_utils.h
index e7babe96cb..9fd0efd940 100644
--- a/hw/rdma/rdma_utils.h
+++ b/hw/rdma/rdma_utils.h
@@ -28,10 +28,10 @@
#define rdma_info_report(fmt, ...) \
info_report("%s: " fmt, "rdma", ## __VA_ARGS__)
-typedef struct RdmaProtectedQList {
+typedef struct RdmaProtectedGQueue {
QemuMutex lock;
- QList *list;
-} RdmaProtectedQList;
+ GQueue *list;
+} RdmaProtectedGQueue;
typedef struct RdmaProtectedGSList {
QemuMutex lock;
@@ -40,10 +40,11 @@ typedef struct RdmaProtectedGSList {
void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t plen);
void rdma_pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len);
-void rdma_protected_qlist_init(RdmaProtectedQList *list);
-void rdma_protected_qlist_destroy(RdmaProtectedQList *list);
-void rdma_protected_qlist_append_int64(RdmaProtectedQList *list, int64_t value);
-int64_t rdma_protected_qlist_pop_int64(RdmaProtectedQList *list);
+void rdma_protected_gqueue_init(RdmaProtectedGQueue *list);
+void rdma_protected_gqueue_destroy(RdmaProtectedGQueue *list);
+void rdma_protected_gqueue_append_int64(RdmaProtectedGQueue *list,
+ int64_t value);
+int64_t rdma_protected_gqueue_pop_int64(RdmaProtectedGQueue *list);
void rdma_protected_gslist_init(RdmaProtectedGSList *list);
void rdma_protected_gslist_destroy(RdmaProtectedGSList *list);
void rdma_protected_gslist_append_int32(RdmaProtectedGSList *list,
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index d62f3dc758..83586aef41 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -33,24 +33,16 @@
#include <libfdt.h>
-#if defined(TARGET_RISCV32)
-#define fw_dynamic_info_data(__val) cpu_to_le32(__val)
-#else
-#define fw_dynamic_info_data(__val) cpu_to_le64(__val)
-#endif
-
-bool riscv_is_32_bit(MachineState *machine)
+bool riscv_is_32bit(RISCVHartArrayState harts)
{
- if (!strncmp(machine->cpu_type, "rv32", 4)) {
- return true;
- } else {
- return false;
- }
+ RISCVCPU hart = harts.harts[0];
+
+ return riscv_cpu_is_32bit(&hart.env);
}
-target_ulong riscv_calc_kernel_start_addr(MachineState *machine,
+target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState harts,
target_ulong firmware_end_addr) {
- if (riscv_is_32_bit(machine)) {
+ if (riscv_is_32bit(harts)) {
return QEMU_ALIGN_UP(firmware_end_addr, 4 * MiB);
} else {
return QEMU_ALIGN_UP(firmware_end_addr, 2 * MiB);
@@ -218,16 +210,24 @@ uint32_t riscv_load_fdt(hwaddr dram_base, uint64_t mem_size, void *fdt)
return fdt_addr;
}
-void riscv_rom_copy_firmware_info(hwaddr rom_base, hwaddr rom_size,
- uint32_t reset_vec_size, uint64_t kernel_entry)
+void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
+ hwaddr rom_size, uint32_t reset_vec_size,
+ uint64_t kernel_entry)
{
struct fw_dynamic_info dinfo;
size_t dinfo_len;
- dinfo.magic = fw_dynamic_info_data(FW_DYNAMIC_INFO_MAGIC_VALUE);
- dinfo.version = fw_dynamic_info_data(FW_DYNAMIC_INFO_VERSION);
- dinfo.next_mode = fw_dynamic_info_data(FW_DYNAMIC_INFO_NEXT_MODE_S);
- dinfo.next_addr = fw_dynamic_info_data(kernel_entry);
+ if (sizeof(dinfo.magic) == 4) {
+ dinfo.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
+ dinfo.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
+ dinfo.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
+ dinfo.next_addr = cpu_to_le32(kernel_entry);
+ } else {
+ dinfo.magic = cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
+ dinfo.version = cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
+ dinfo.next_mode = cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
+ dinfo.next_addr = cpu_to_le64(kernel_entry);
+ }
dinfo.options = 0;
dinfo.boot_hart = 0;
dinfo_len = sizeof(dinfo);
@@ -247,28 +247,25 @@ void riscv_rom_copy_firmware_info(hwaddr rom_base, hwaddr rom_size,
&address_space_memory);
}
-void riscv_setup_rom_reset_vec(hwaddr start_addr, hwaddr rom_base,
- hwaddr rom_size, uint64_t kernel_entry,
+void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState harts,
+ hwaddr start_addr,
+ hwaddr rom_base, hwaddr rom_size,
+ uint64_t kernel_entry,
uint32_t fdt_load_addr, void *fdt)
{
int i;
uint32_t start_addr_hi32 = 0x00000000;
- #if defined(TARGET_RISCV64)
- start_addr_hi32 = start_addr >> 32;
- #endif
+ if (!riscv_is_32bit(harts)) {
+ start_addr_hi32 = start_addr >> 32;
+ }
/* reset vector */
uint32_t reset_vec[10] = {
0x00000297, /* 1: auipc t0, %pcrel_hi(fw_dyn) */
0x02828613, /* addi a2, t0, %pcrel_lo(1b) */
0xf1402573, /* csrr a0, mhartid */
-#if defined(TARGET_RISCV32)
- 0x0202a583, /* lw a1, 32(t0) */
- 0x0182a283, /* lw t0, 24(t0) */
-#elif defined(TARGET_RISCV64)
- 0x0202b583, /* ld a1, 32(t0) */
- 0x0182b283, /* ld t0, 24(t0) */
-#endif
+ 0,
+ 0,
0x00028067, /* jr t0 */
start_addr, /* start: .dword */
start_addr_hi32,
@@ -276,6 +273,13 @@ void riscv_setup_rom_reset_vec(hwaddr start_addr, hwaddr rom_base,
0x00000000,
/* fw_dyn: */
};
+ if (riscv_is_32bit(harts)) {
+ reset_vec[3] = 0x0202a583; /* lw a1, 32(t0) */
+ reset_vec[4] = 0x0182a283; /* lw t0, 24(t0) */
+ } else {
+ reset_vec[3] = 0x0202b583; /* ld a1, 32(t0) */
+ reset_vec[4] = 0x0182b283; /* ld t0, 24(t0) */
+ }
/* copy in the reset vector in little_endian byte order */
for (i = 0; i < ARRAY_SIZE(reset_vec); i++) {
@@ -283,7 +287,7 @@ void riscv_setup_rom_reset_vec(hwaddr start_addr, hwaddr rom_base,
}
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
rom_base, &address_space_memory);
- riscv_rom_copy_firmware_info(rom_base, rom_size, sizeof(reset_vec),
+ riscv_rom_copy_firmware_info(machine, rom_base, rom_size, sizeof(reset_vec),
kernel_entry);
return;
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index 37ac46a1af..e952b49e8c 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -113,6 +113,8 @@ static const struct MemmapEntry {
[MICROCHIP_PFSOC_MMUART2] = { 0x20102000, 0x1000 },
[MICROCHIP_PFSOC_MMUART3] = { 0x20104000, 0x1000 },
[MICROCHIP_PFSOC_MMUART4] = { 0x20106000, 0x1000 },
+ [MICROCHIP_PFSOC_SPI0] = { 0x20108000, 0x1000 },
+ [MICROCHIP_PFSOC_SPI1] = { 0x20109000, 0x1000 },
[MICROCHIP_PFSOC_I2C1] = { 0x2010b000, 0x1000 },
[MICROCHIP_PFSOC_GEM0] = { 0x20110000, 0x2000 },
[MICROCHIP_PFSOC_GEM1] = { 0x20112000, 0x2000 },
@@ -121,6 +123,7 @@ static const struct MemmapEntry {
[MICROCHIP_PFSOC_GPIO2] = { 0x20122000, 0x1000 },
[MICROCHIP_PFSOC_ENVM_CFG] = { 0x20200000, 0x1000 },
[MICROCHIP_PFSOC_ENVM_DATA] = { 0x20220000, 0x20000 },
+ [MICROCHIP_PFSOC_QSPI_XIP] = { 0x21000000, 0x1000000 },
[MICROCHIP_PFSOC_IOSCB] = { 0x30000000, 0x10000000 },
[MICROCHIP_PFSOC_DRAM_LO] = { 0x80000000, 0x40000000 },
[MICROCHIP_PFSOC_DRAM_LO_ALIAS] = { 0xc0000000, 0x40000000 },
@@ -185,6 +188,7 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
MemoryRegion *e51_dtim_mem = g_new(MemoryRegion, 1);
MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1);
MemoryRegion *envm_data = g_new(MemoryRegion, 1);
+ MemoryRegion *qspi_xip_mem = g_new(MemoryRegion, 1);
char *plic_hart_config;
size_t plic_hart_config_len;
NICInfo *nd;
@@ -344,6 +348,14 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART4_IRQ),
serial_hd(4));
+ /* SPI */
+ create_unimplemented_device("microchip.pfsoc.spi0",
+ memmap[MICROCHIP_PFSOC_SPI0].base,
+ memmap[MICROCHIP_PFSOC_SPI0].size);
+ create_unimplemented_device("microchip.pfsoc.spi1",
+ memmap[MICROCHIP_PFSOC_SPI1].base,
+ memmap[MICROCHIP_PFSOC_SPI1].size);
+
/* I2C1 */
create_unimplemented_device("microchip.pfsoc.i2c1",
memmap[MICROCHIP_PFSOC_I2C1].base,
@@ -401,6 +413,15 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
sysbus_realize(SYS_BUS_DEVICE(&s->ioscb), errp);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ioscb), 0,
memmap[MICROCHIP_PFSOC_IOSCB].base);
+
+ /* QSPI Flash */
+ memory_region_init_rom(qspi_xip_mem, OBJECT(dev),
+ "microchip.pfsoc.qspi_xip",
+ memmap[MICROCHIP_PFSOC_QSPI_XIP].size,
+ &error_fatal);
+ memory_region_add_subregion(system_memory,
+ memmap[MICROCHIP_PFSOC_QSPI_XIP].base,
+ qspi_xip_mem);
}
static void microchip_pfsoc_soc_class_init(ObjectClass *oc, void *data)
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index cc758b78b8..af3456932f 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -35,22 +35,33 @@ static const struct MemmapEntry {
[IBEX_DEV_ROM] = { 0x00008000, 16 * KiB },
[IBEX_DEV_RAM] = { 0x10000000, 0x10000 },
[IBEX_DEV_FLASH] = { 0x20000000, 0x80000 },
- [IBEX_DEV_UART] = { 0x40000000, 0x10000 },
- [IBEX_DEV_GPIO] = { 0x40010000, 0x10000 },
- [IBEX_DEV_SPI] = { 0x40020000, 0x10000 },
- [IBEX_DEV_FLASH_CTRL] = { 0x40030000, 0x10000 },
- [IBEX_DEV_PINMUX] = { 0x40070000, 0x10000 },
- [IBEX_DEV_RV_TIMER] = { 0x40080000, 0x10000 },
- [IBEX_DEV_PLIC] = { 0x40090000, 0x10000 },
- [IBEX_DEV_PWRMGR] = { 0x400A0000, 0x10000 },
- [IBEX_DEV_RSTMGR] = { 0x400B0000, 0x10000 },
- [IBEX_DEV_CLKMGR] = { 0x400C0000, 0x10000 },
- [IBEX_DEV_AES] = { 0x40110000, 0x10000 },
- [IBEX_DEV_HMAC] = { 0x40120000, 0x10000 },
- [IBEX_DEV_ALERT_HANDLER] = { 0x40130000, 0x10000 },
- [IBEX_DEV_NMI_GEN] = { 0x40140000, 0x10000 },
- [IBEX_DEV_USBDEV] = { 0x40150000, 0x10000 },
- [IBEX_DEV_PADCTRL] = { 0x40160000, 0x10000 }
+ [IBEX_DEV_UART] = { 0x40000000, 0x1000 },
+ [IBEX_DEV_GPIO] = { 0x40040000, 0x1000 },
+ [IBEX_DEV_SPI] = { 0x40050000, 0x1000 },
+ [IBEX_DEV_I2C] = { 0x40080000, 0x1000 },
+ [IBEX_DEV_PATTGEN] = { 0x400e0000, 0x1000 },
+ [IBEX_DEV_RV_TIMER] = { 0x40100000, 0x1000 },
+ [IBEX_DEV_SENSOR_CTRL] = { 0x40110000, 0x1000 },
+ [IBEX_DEV_OTP_CTRL] = { 0x40130000, 0x4000 },
+ [IBEX_DEV_PWRMGR] = { 0x40400000, 0x1000 },
+ [IBEX_DEV_RSTMGR] = { 0x40410000, 0x1000 },
+ [IBEX_DEV_CLKMGR] = { 0x40420000, 0x1000 },
+ [IBEX_DEV_PINMUX] = { 0x40460000, 0x1000 },
+ [IBEX_DEV_PADCTRL] = { 0x40470000, 0x1000 },
+ [IBEX_DEV_USBDEV] = { 0x40500000, 0x1000 },
+ [IBEX_DEV_FLASH_CTRL] = { 0x41000000, 0x1000 },
+ [IBEX_DEV_PLIC] = { 0x41010000, 0x1000 },
+ [IBEX_DEV_AES] = { 0x41100000, 0x1000 },
+ [IBEX_DEV_HMAC] = { 0x41110000, 0x1000 },
+ [IBEX_DEV_KMAC] = { 0x41120000, 0x1000 },
+ [IBEX_DEV_KEYMGR] = { 0x41130000, 0x1000 },
+ [IBEX_DEV_CSRNG] = { 0x41150000, 0x1000 },
+ [IBEX_DEV_ENTROPY] = { 0x41160000, 0x1000 },
+ [IBEX_DEV_EDNO] = { 0x41170000, 0x1000 },
+ [IBEX_DEV_EDN1] = { 0x41180000, 0x1000 },
+ [IBEX_DEV_ALERT_HANDLER] = { 0x411b0000, 0x1000 },
+ [IBEX_DEV_NMI_GEN] = { 0x411c0000, 0x1000 },
+ [IBEX_DEV_OTBN] = { 0x411d0000, 0x10000 },
};
static void opentitan_board_init(MachineState *machine)
@@ -156,30 +167,52 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
memmap[IBEX_DEV_GPIO].base, memmap[IBEX_DEV_GPIO].size);
create_unimplemented_device("riscv.lowrisc.ibex.spi",
memmap[IBEX_DEV_SPI].base, memmap[IBEX_DEV_SPI].size);
- create_unimplemented_device("riscv.lowrisc.ibex.flash_ctrl",
- memmap[IBEX_DEV_FLASH_CTRL].base, memmap[IBEX_DEV_FLASH_CTRL].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.i2c",
+ memmap[IBEX_DEV_I2C].base, memmap[IBEX_DEV_I2C].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.pattgen",
+ memmap[IBEX_DEV_PATTGEN].base, memmap[IBEX_DEV_PATTGEN].size);
create_unimplemented_device("riscv.lowrisc.ibex.rv_timer",
memmap[IBEX_DEV_RV_TIMER].base, memmap[IBEX_DEV_RV_TIMER].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.sensor_ctrl",
+ memmap[IBEX_DEV_SENSOR_CTRL].base, memmap[IBEX_DEV_SENSOR_CTRL].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.otp_ctrl",
+ memmap[IBEX_DEV_OTP_CTRL].base, memmap[IBEX_DEV_OTP_CTRL].size);
create_unimplemented_device("riscv.lowrisc.ibex.pwrmgr",
memmap[IBEX_DEV_PWRMGR].base, memmap[IBEX_DEV_PWRMGR].size);
create_unimplemented_device("riscv.lowrisc.ibex.rstmgr",
memmap[IBEX_DEV_RSTMGR].base, memmap[IBEX_DEV_RSTMGR].size);
create_unimplemented_device("riscv.lowrisc.ibex.clkmgr",
memmap[IBEX_DEV_CLKMGR].base, memmap[IBEX_DEV_CLKMGR].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.pinmux",
+ memmap[IBEX_DEV_PINMUX].base, memmap[IBEX_DEV_PINMUX].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.padctrl",
+ memmap[IBEX_DEV_PADCTRL].base, memmap[IBEX_DEV_PADCTRL].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.usbdev",
+ memmap[IBEX_DEV_USBDEV].base, memmap[IBEX_DEV_USBDEV].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.flash_ctrl",
+ memmap[IBEX_DEV_FLASH_CTRL].base, memmap[IBEX_DEV_FLASH_CTRL].size);
create_unimplemented_device("riscv.lowrisc.ibex.aes",
memmap[IBEX_DEV_AES].base, memmap[IBEX_DEV_AES].size);
create_unimplemented_device("riscv.lowrisc.ibex.hmac",
memmap[IBEX_DEV_HMAC].base, memmap[IBEX_DEV_HMAC].size);
- create_unimplemented_device("riscv.lowrisc.ibex.pinmux",
- memmap[IBEX_DEV_PINMUX].base, memmap[IBEX_DEV_PINMUX].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.kmac",
+ memmap[IBEX_DEV_KMAC].base, memmap[IBEX_DEV_KMAC].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.keymgr",
+ memmap[IBEX_DEV_KEYMGR].base, memmap[IBEX_DEV_KEYMGR].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.csrng",
+ memmap[IBEX_DEV_CSRNG].base, memmap[IBEX_DEV_CSRNG].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.entropy",
+ memmap[IBEX_DEV_ENTROPY].base, memmap[IBEX_DEV_ENTROPY].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.edn0",
+ memmap[IBEX_DEV_EDNO].base, memmap[IBEX_DEV_EDNO].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.edn1",
+ memmap[IBEX_DEV_EDN1].base, memmap[IBEX_DEV_EDN1].size);
create_unimplemented_device("riscv.lowrisc.ibex.alert_handler",
memmap[IBEX_DEV_ALERT_HANDLER].base, memmap[IBEX_DEV_ALERT_HANDLER].size);
create_unimplemented_device("riscv.lowrisc.ibex.nmi_gen",
memmap[IBEX_DEV_NMI_GEN].base, memmap[IBEX_DEV_NMI_GEN].size);
- create_unimplemented_device("riscv.lowrisc.ibex.usbdev",
- memmap[IBEX_DEV_USBDEV].base, memmap[IBEX_DEV_USBDEV].size);
- create_unimplemented_device("riscv.lowrisc.ibex.padctrl",
- memmap[IBEX_DEV_PADCTRL].base, memmap[IBEX_DEV_PADCTRL].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.otbn",
+ memmap[IBEX_DEV_OTBN].base, memmap[IBEX_DEV_OTBN].size);
}
static void lowrisc_ibex_soc_class_init(ObjectClass *oc, void *data)
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index e7f6dc5fb3..f5c400dd44 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -60,12 +60,6 @@
#include <libfdt.h>
-#if defined(TARGET_RISCV32)
-# define BIOS_FILENAME "opensbi-riscv32-generic-fw_dynamic.bin"
-#else
-# define BIOS_FILENAME "opensbi-riscv64-generic-fw_dynamic.bin"
-#endif
-
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
@@ -93,7 +87,7 @@ static const struct MemmapEntry {
#define GEM_REVISION 0x10070109
static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
- uint64_t mem_size, const char *cmdline)
+ uint64_t mem_size, const char *cmdline, bool is_32_bit)
{
MachineState *ms = MACHINE(qdev_get_machine());
void *fdt;
@@ -176,11 +170,11 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
qemu_fdt_add_subnode(fdt, nodename);
/* cpu 0 is the management hart that does not have mmu */
if (cpu != 0) {
-#if defined(TARGET_RISCV32)
- qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32");
-#else
- qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
-#endif
+ if (is_32_bit) {
+ qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32");
+ } else {
+ qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
+ }
isa = riscv_isa_string(&s->soc.u_cpus.harts[cpu - 1]);
} else {
isa = riscv_isa_string(&s->soc.e_cpus.harts[0]);
@@ -386,6 +380,21 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
g_free(nodename);
nodename = g_strdup_printf("/soc/serial@%lx",
+ (long)memmap[SIFIVE_U_DEV_UART1].base);
+ qemu_fdt_add_subnode(fdt, nodename);
+ qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,uart0");
+ qemu_fdt_setprop_cells(fdt, nodename, "reg",
+ 0x0, memmap[SIFIVE_U_DEV_UART1].base,
+ 0x0, memmap[SIFIVE_U_DEV_UART1].size);
+ qemu_fdt_setprop_cells(fdt, nodename, "clocks",
+ prci_phandle, PRCI_CLK_TLCLK);
+ qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
+ qemu_fdt_setprop_cell(fdt, nodename, "interrupts", SIFIVE_U_UART1_IRQ);
+
+ qemu_fdt_setprop_string(fdt, "/aliases", "serial1", nodename);
+ g_free(nodename);
+
+ nodename = g_strdup_printf("/soc/serial@%lx",
(long)memmap[SIFIVE_U_DEV_UART0].base);
qemu_fdt_add_subnode(fdt, nodename);
qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,uart0");
@@ -456,7 +465,8 @@ static void sifive_u_machine_init(MachineState *machine)
qemu_allocate_irq(sifive_u_machine_reset, NULL, 0));
/* create device tree */
- create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
+ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
+ riscv_is_32bit(s->soc.u_cpus));
if (s->start_in_flash) {
/*
@@ -485,11 +495,18 @@ static void sifive_u_machine_init(MachineState *machine)
break;
}
- firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
- start_addr, NULL);
+ if (riscv_is_32bit(s->soc.u_cpus)) {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ "opensbi-riscv32-generic-fw_dynamic.bin",
+ start_addr, NULL);
+ } else {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ "opensbi-riscv64-generic-fw_dynamic.bin",
+ start_addr, NULL);
+ }
if (machine->kernel_filename) {
- kernel_start_addr = riscv_calc_kernel_start_addr(machine,
+ kernel_start_addr = riscv_calc_kernel_start_addr(s->soc.u_cpus,
firmware_end_addr);
kernel_entry = riscv_load_kernel(machine->kernel_filename,
@@ -516,9 +533,9 @@ static void sifive_u_machine_init(MachineState *machine)
/* Compute the fdt load address in dram */
fdt_load_addr = riscv_load_fdt(memmap[SIFIVE_U_DEV_DRAM].base,
machine->ram_size, s->fdt);
- #if defined(TARGET_RISCV64)
- start_addr_hi32 = start_addr >> 32;
- #endif
+ if (!riscv_is_32bit(s->soc.u_cpus)) {
+ start_addr_hi32 = (uint64_t)start_addr >> 32;
+ }
/* reset vector */
uint32_t reset_vec[11] = {
@@ -526,13 +543,8 @@ static void sifive_u_machine_init(MachineState *machine)
0x00000297, /* 1: auipc t0, %pcrel_hi(fw_dyn) */
0x02828613, /* addi a2, t0, %pcrel_lo(1b) */
0xf1402573, /* csrr a0, mhartid */
-#if defined(TARGET_RISCV32)
- 0x0202a583, /* lw a1, 32(t0) */
- 0x0182a283, /* lw t0, 24(t0) */
-#elif defined(TARGET_RISCV64)
- 0x0202b583, /* ld a1, 32(t0) */
- 0x0182b283, /* ld t0, 24(t0) */
-#endif
+ 0,
+ 0,
0x00028067, /* jr t0 */
start_addr, /* start: .dword */
start_addr_hi32,
@@ -540,6 +552,14 @@ static void sifive_u_machine_init(MachineState *machine)
0x00000000,
/* fw_dyn: */
};
+ if (riscv_is_32bit(s->soc.u_cpus)) {
+ reset_vec[4] = 0x0202a583; /* lw a1, 32(t0) */
+ reset_vec[5] = 0x0182a283; /* lw t0, 24(t0) */
+ } else {
+ reset_vec[4] = 0x0202b583; /* ld a1, 32(t0) */
+ reset_vec[5] = 0x0182b283; /* ld t0, 24(t0) */
+ }
+
/* copy in the reset vector in little_endian byte order */
for (i = 0; i < ARRAY_SIZE(reset_vec); i++) {
@@ -548,7 +568,7 @@ static void sifive_u_machine_init(MachineState *machine)
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
memmap[SIFIVE_U_DEV_MROM].base, &address_space_memory);
- riscv_rom_copy_firmware_info(memmap[SIFIVE_U_DEV_MROM].base,
+ riscv_rom_copy_firmware_info(machine, memmap[SIFIVE_U_DEV_MROM].base,
memmap[SIFIVE_U_DEV_MROM].size,
sizeof(reset_vec), kernel_entry);
}
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index facac6e7d2..e723ca0ac9 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -43,17 +43,6 @@
#include "sysemu/qtest.h"
#include "sysemu/sysemu.h"
-/*
- * Not like other RISC-V machines that use plain binary bios images,
- * keeping ELF files here was intentional because BIN files don't work
- * for the Spike machine as HTIF emulation depends on ELF parsing.
- */
-#if defined(TARGET_RISCV32)
-# define BIOS_FILENAME "opensbi-riscv32-generic-fw_dynamic.elf"
-#else
-# define BIOS_FILENAME "opensbi-riscv64-generic-fw_dynamic.elf"
-#endif
-
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
@@ -64,7 +53,7 @@ static const struct MemmapEntry {
};
static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap,
- uint64_t mem_size, const char *cmdline)
+ uint64_t mem_size, const char *cmdline, bool is_32_bit)
{
void *fdt;
uint64_t addr, size;
@@ -115,11 +104,11 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap,
cpu_name = g_strdup_printf("/cpus/cpu@%d",
s->soc[socket].hartid_base + cpu);
qemu_fdt_add_subnode(fdt, cpu_name);
-#if defined(TARGET_RISCV32)
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv32");
-#else
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv48");
-#endif
+ if (is_32_bit) {
+ qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv32");
+ } else {
+ qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv48");
+ }
name = riscv_isa_string(&s->soc[socket].harts[cpu]);
qemu_fdt_setprop_string(fdt, cpu_name, "riscv,isa", name);
g_free(name);
@@ -254,7 +243,8 @@ static void spike_board_init(MachineState *machine)
main_mem);
/* create device tree */
- create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
+ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
+ riscv_is_32bit(s->soc[0]));
/* boot rom */
memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
@@ -262,12 +252,25 @@ static void spike_board_init(MachineState *machine)
memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
mask_rom);
- firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
- memmap[SPIKE_DRAM].base,
- htif_symbol_callback);
+ /*
+ * Not like other RISC-V machines that use plain binary bios images,
+ * keeping ELF files here was intentional because BIN files don't work
+ * for the Spike machine as HTIF emulation depends on ELF parsing.
+ */
+ if (riscv_is_32bit(s->soc[0])) {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ "opensbi-riscv32-generic-fw_dynamic.elf",
+ memmap[SPIKE_DRAM].base,
+ htif_symbol_callback);
+ } else {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ "opensbi-riscv64-generic-fw_dynamic.elf",
+ memmap[SPIKE_DRAM].base,
+ htif_symbol_callback);
+ }
if (machine->kernel_filename) {
- kernel_start_addr = riscv_calc_kernel_start_addr(machine,
+ kernel_start_addr = riscv_calc_kernel_start_addr(s->soc[0],
firmware_end_addr);
kernel_entry = riscv_load_kernel(machine->kernel_filename,
@@ -296,7 +299,8 @@ static void spike_board_init(MachineState *machine)
fdt_load_addr = riscv_load_fdt(memmap[SPIKE_DRAM].base,
machine->ram_size, s->fdt);
/* load the reset vector */
- riscv_setup_rom_reset_vec(memmap[SPIKE_DRAM].base, memmap[SPIKE_MROM].base,
+ riscv_setup_rom_reset_vec(machine, s->soc[0], memmap[SPIKE_DRAM].base,
+ memmap[SPIKE_MROM].base,
memmap[SPIKE_MROM].size, kernel_entry,
fdt_load_addr, s->fdt);
@@ -317,7 +321,7 @@ static void spike_machine_class_init(ObjectClass *oc, void *data)
mc->init = spike_board_init;
mc->max_cpus = SPIKE_CPUS_MAX;
mc->is_default = true;
- mc->default_cpu_type = SPIKE_V1_10_0_CPU;
+ mc->default_cpu_type = TYPE_RISCV_CPU_BASE;
mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids;
mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 3cc18a76e7..8de4c35c9d 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -43,12 +43,6 @@
#include "hw/pci/pci.h"
#include "hw/pci-host/gpex.h"
-#if defined(TARGET_RISCV32)
-# define BIOS_FILENAME "opensbi-riscv32-generic-fw_dynamic.bin"
-#else
-# define BIOS_FILENAME "opensbi-riscv64-generic-fw_dynamic.bin"
-#endif
-
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
@@ -177,7 +171,7 @@ static void create_pcie_irq_map(void *fdt, char *nodename,
}
static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
- uint64_t mem_size, const char *cmdline)
+ uint64_t mem_size, const char *cmdline, bool is_32_bit)
{
void *fdt;
int i, cpu, socket;
@@ -240,11 +234,11 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
cpu_name = g_strdup_printf("/cpus/cpu@%d",
s->soc[socket].hartid_base + cpu);
qemu_fdt_add_subnode(fdt, cpu_name);
-#if defined(TARGET_RISCV32)
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv32");
-#else
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv48");
-#endif
+ if (is_32_bit) {
+ qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv32");
+ } else {
+ qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv48");
+ }
name = riscv_isa_string(&s->soc[socket].harts[cpu]);
qemu_fdt_setprop_string(fdt, cpu_name, "riscv,isa", name);
g_free(name);
@@ -606,7 +600,8 @@ static void virt_machine_init(MachineState *machine)
main_mem);
/* create device tree */
- create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
+ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
+ riscv_is_32bit(s->soc[0]));
/* boot rom */
memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom",
@@ -614,11 +609,18 @@ static void virt_machine_init(MachineState *machine)
memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
mask_rom);
- firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
- start_addr, NULL);
+ if (riscv_is_32bit(s->soc[0])) {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ "opensbi-riscv32-generic-fw_dynamic.bin",
+ start_addr, NULL);
+ } else {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ "opensbi-riscv64-generic-fw_dynamic.bin",
+ start_addr, NULL);
+ }
if (machine->kernel_filename) {
- kernel_start_addr = riscv_calc_kernel_start_addr(machine,
+ kernel_start_addr = riscv_calc_kernel_start_addr(s->soc[0],
firmware_end_addr);
kernel_entry = riscv_load_kernel(machine->kernel_filename,
@@ -654,7 +656,8 @@ static void virt_machine_init(MachineState *machine)
fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base,
machine->ram_size, s->fdt);
/* load the reset vector */
- riscv_setup_rom_reset_vec(start_addr, virt_memmap[VIRT_MROM].base,
+ riscv_setup_rom_reset_vec(machine, s->soc[0], start_addr,
+ virt_memmap[VIRT_MROM].base,
virt_memmap[VIRT_MROM].size, kernel_entry,
fdt_load_addr, s->fdt);
@@ -704,7 +707,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
mc->desc = "RISC-V VirtIO board";
mc->init = virt_machine_init;
mc->max_cpus = VIRT_CPUS_MAX;
- mc->default_cpu_type = VIRT_CPU;
+ mc->default_cpu_type = TYPE_RISCV_CPU_BASE;
mc->pci_allow_0_address = true;
mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids;
mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
diff --git a/hw/rtc/twl92230.c b/hw/rtc/twl92230.c
index f838913b37..0922df5ad3 100644
--- a/hw/rtc/twl92230.c
+++ b/hw/rtc/twl92230.c
@@ -271,37 +271,23 @@ static void menelaus_gpio_set(void *opaque, int line, int level)
static uint8_t menelaus_read(void *opaque, uint8_t addr)
{
MenelausState *s = (MenelausState *) opaque;
- int reg = 0;
switch (addr) {
case MENELAUS_REV:
return 0x22;
- case MENELAUS_VCORE_CTRL5: reg ++;
- case MENELAUS_VCORE_CTRL4: reg ++;
- case MENELAUS_VCORE_CTRL3: reg ++;
- case MENELAUS_VCORE_CTRL2: reg ++;
- case MENELAUS_VCORE_CTRL1:
- return s->vcore[reg];
+ case MENELAUS_VCORE_CTRL1 ... MENELAUS_VCORE_CTRL5:
+ return s->vcore[addr - MENELAUS_VCORE_CTRL1];
- case MENELAUS_DCDC_CTRL3: reg ++;
- case MENELAUS_DCDC_CTRL2: reg ++;
- case MENELAUS_DCDC_CTRL1:
- return s->dcdc[reg];
-
- case MENELAUS_LDO_CTRL8: reg ++;
- case MENELAUS_LDO_CTRL7: reg ++;
- case MENELAUS_LDO_CTRL6: reg ++;
- case MENELAUS_LDO_CTRL5: reg ++;
- case MENELAUS_LDO_CTRL4: reg ++;
- case MENELAUS_LDO_CTRL3: reg ++;
- case MENELAUS_LDO_CTRL2: reg ++;
- case MENELAUS_LDO_CTRL1:
- return s->ldo[reg];
+ case MENELAUS_DCDC_CTRL1 ... MENELAUS_DCDC_CTRL3:
+ return s->dcdc[addr - MENELAUS_DCDC_CTRL1];
+
+ case MENELAUS_LDO_CTRL1 ... MENELAUS_LDO_CTRL8:
+ return s->ldo[addr - MENELAUS_LDO_CTRL1];
- case MENELAUS_SLEEP_CTRL2: reg ++;
case MENELAUS_SLEEP_CTRL1:
- return s->sleep[reg];
+ case MENELAUS_SLEEP_CTRL2:
+ return s->sleep[addr - MENELAUS_SLEEP_CTRL1];
case MENELAUS_DEVICE_OFF:
return 0;
@@ -395,10 +381,8 @@ static uint8_t menelaus_read(void *opaque, uint8_t addr)
case MENELAUS_S2_PULL_DIR:
return s->pull[3];
- case MENELAUS_MCT_CTRL3: reg ++;
- case MENELAUS_MCT_CTRL2: reg ++;
- case MENELAUS_MCT_CTRL1:
- return s->mmc_ctrl[reg];
+ case MENELAUS_MCT_CTRL1 ... MENELAUS_MCT_CTRL3:
+ return s->mmc_ctrl[addr - MENELAUS_MCT_CTRL1];
case MENELAUS_MCT_PIN_ST:
/* TODO: return the real Card Detect */
return 0;
@@ -418,7 +402,6 @@ static void menelaus_write(void *opaque, uint8_t addr, uint8_t value)
{
MenelausState *s = (MenelausState *) opaque;
int line;
- int reg = 0;
struct tm tm;
switch (addr) {
@@ -496,9 +479,9 @@ static void menelaus_write(void *opaque, uint8_t addr, uint8_t value)
s->ldo[7] = value & 3;
break;
- case MENELAUS_SLEEP_CTRL2: reg ++;
case MENELAUS_SLEEP_CTRL1:
- s->sleep[reg] = value;
+ case MENELAUS_SLEEP_CTRL2:
+ s->sleep[addr - MENELAUS_SLEEP_CTRL1] = value;
break;
case MENELAUS_DEVICE_OFF:
@@ -714,6 +697,7 @@ static void menelaus_write(void *opaque, uint8_t addr, uint8_t value)
#ifdef VERBOSE
printf("%s: unknown register %02x\n", __func__, addr);
#endif
+ break;
}
}
@@ -762,7 +746,7 @@ static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size,
}
static int put_int32_as_uint16(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
int *v = pv;
qemu_put_be16(f, *v);
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index edb5c3492a..c349fb7f2d 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -1638,7 +1638,7 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
/* SCSI request list. For simplicity, pv points to the whole device */
static int put_scsi_requests(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
SCSIDevice *s = pv;
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c
index 446f2eacdd..e03a8155b2 100644
--- a/hw/timer/renesas_tmr.c
+++ b/hw/timer/renesas_tmr.c
@@ -221,6 +221,7 @@ static uint64_t tmr_read(void *opaque, hwaddr addr, unsigned size)
} else if (ch == 0) {
return concat_reg(tmr->tcora);
}
+ /* fall through */
case A_TCORB:
if (size == 1) {
return tmr->tcorb[ch];
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 3238de6bb8..4ca7d47ef7 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -2227,7 +2227,7 @@ static int usbredir_post_load(void *priv, int version_id)
/* For usbredirparser migration */
static int usbredir_put_parser(QEMUFile *f, void *priv, size_t unused,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
USBRedirDevice *dev = priv;
uint8_t *data;
@@ -2294,7 +2294,7 @@ static const VMStateInfo usbredir_parser_vmstate_info = {
/* For buffered packets (iso/irq) queue migration */
static int usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
struct endp_data *endp = priv;
USBRedirDevice *dev = endp->dev;
@@ -2421,7 +2421,8 @@ static const VMStateDescription usbredir_ep_vmstate = {
/* For PacketIdQueue migration */
static int usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field,
+ JSONWriter *vmdesc)
{
struct PacketIdQueue *q = priv;
USBRedirDevice *dev = q->dev;
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index eff35fab7c..b308026596 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2745,7 +2745,7 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size,
}
static int put_extra_state(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
VirtIODevice *vdev = pv;
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
@@ -2919,7 +2919,7 @@ int virtio_save(VirtIODevice *vdev, QEMUFile *f)
/* A wrapper for use as a VMState .put function */
static int virtio_device_put(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
return virtio_save(VIRTIO_DEVICE(opaque), f);
}
diff --git a/include/block/block.h b/include/block/block.h
index 5b81e33e94..a193545b6a 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -63,16 +63,7 @@ typedef enum {
* content. */
BDRV_REQ_WRITE_UNCHANGED = 0x40,
- /*
- * BDRV_REQ_SERIALISING forces request serialisation for writes.
- * It is used to ensure that writes to the backing file of a backup process
- * target cannot race with a read of the backup target that defers to the
- * backing file.
- *
- * Note, that BDRV_REQ_SERIALISING is _not_ opposite in meaning to
- * BDRV_REQ_NO_SERIALISING. A more descriptive name for the latter might be
- * _DO_NOT_WAIT_FOR_SERIALISING, except that is too long.
- */
+ /* Forces request serialisation. Use only with write requests. */
BDRV_REQ_SERIALISING = 0x80,
/* Execute the request only if the operation can be offloaded or otherwise
@@ -86,8 +77,15 @@ typedef enum {
* written to qiov parameter which may be NULL.
*/
BDRV_REQ_PREFETCH = 0x200,
+
+ /*
+ * If we need to wait for other requests, just fail immediately. Used
+ * only together with BDRV_REQ_SERIALISING.
+ */
+ BDRV_REQ_NO_WAIT = 0x400,
+
/* Mask of valid flags */
- BDRV_REQ_MASK = 0x3ff,
+ BDRV_REQ_MASK = 0x7ff,
} BdrvRequestFlags;
typedef struct BlockSizes {
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 1eeafc118c..b9ef61fe4d 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -1060,7 +1060,8 @@ extern unsigned int bdrv_drain_all_count;
void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent);
void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent);
-bool coroutine_fn bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align);
+bool coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req,
+ uint64_t align);
BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs);
int get_tmp_filename(char *filename, int size);
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index 0b01988727..20ff5fe5e5 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -22,10 +22,11 @@
#include "exec/cpu-defs.h"
#include "hw/loader.h"
+#include "hw/riscv/riscv_hart.h"
-bool riscv_is_32_bit(MachineState *machine);
+bool riscv_is_32bit(RISCVHartArrayState harts);
-target_ulong riscv_calc_kernel_start_addr(MachineState *machine,
+target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState harts,
target_ulong firmware_end_addr);
target_ulong riscv_find_and_load_firmware(MachineState *machine,
const char *default_machine_firmware,
@@ -41,10 +42,13 @@ target_ulong riscv_load_kernel(const char *kernel_filename,
hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,
uint64_t kernel_entry, hwaddr *start);
uint32_t riscv_load_fdt(hwaddr dram_start, uint64_t dram_size, void *fdt);
-void riscv_setup_rom_reset_vec(hwaddr saddr, hwaddr rom_base,
- hwaddr rom_size, uint64_t kernel_entry,
+void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState harts,
+ hwaddr saddr,
+ hwaddr rom_base, hwaddr rom_size,
+ uint64_t kernel_entry,
uint32_t fdt_load_addr, void *fdt);
-void riscv_rom_copy_firmware_info(hwaddr rom_base, hwaddr rom_size,
+void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
+ hwaddr rom_size,
uint32_t reset_vec_size,
uint64_t kernel_entry);
diff --git a/include/hw/riscv/microchip_pfsoc.h b/include/hw/riscv/microchip_pfsoc.h
index 51d44637db..d0c666aae0 100644
--- a/include/hw/riscv/microchip_pfsoc.h
+++ b/include/hw/riscv/microchip_pfsoc.h
@@ -97,6 +97,8 @@ enum {
MICROCHIP_PFSOC_MMUART2,
MICROCHIP_PFSOC_MMUART3,
MICROCHIP_PFSOC_MMUART4,
+ MICROCHIP_PFSOC_SPI0,
+ MICROCHIP_PFSOC_SPI1,
MICROCHIP_PFSOC_I2C1,
MICROCHIP_PFSOC_GEM0,
MICROCHIP_PFSOC_GEM1,
@@ -105,6 +107,7 @@ enum {
MICROCHIP_PFSOC_GPIO2,
MICROCHIP_PFSOC_ENVM_CFG,
MICROCHIP_PFSOC_ENVM_DATA,
+ MICROCHIP_PFSOC_QSPI_XIP,
MICROCHIP_PFSOC_IOSCB,
MICROCHIP_PFSOC_DRAM_LO,
MICROCHIP_PFSOC_DRAM_LO_ALIAS,
diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h
index 5ff0c0f85e..a5ea3a5e4e 100644
--- a/include/hw/riscv/opentitan.h
+++ b/include/hw/riscv/opentitan.h
@@ -55,19 +55,30 @@ enum {
IBEX_DEV_UART,
IBEX_DEV_GPIO,
IBEX_DEV_SPI,
- IBEX_DEV_FLASH_CTRL,
+ IBEX_DEV_I2C,
+ IBEX_DEV_PATTGEN,
IBEX_DEV_RV_TIMER,
- IBEX_DEV_AES,
- IBEX_DEV_HMAC,
- IBEX_DEV_PLIC,
+ IBEX_DEV_SENSOR_CTRL,
+ IBEX_DEV_OTP_CTRL,
IBEX_DEV_PWRMGR,
IBEX_DEV_RSTMGR,
IBEX_DEV_CLKMGR,
IBEX_DEV_PINMUX,
+ IBEX_DEV_PADCTRL,
+ IBEX_DEV_USBDEV,
+ IBEX_DEV_FLASH_CTRL,
+ IBEX_DEV_PLIC,
+ IBEX_DEV_AES,
+ IBEX_DEV_HMAC,
+ IBEX_DEV_KMAC,
+ IBEX_DEV_KEYMGR,
+ IBEX_DEV_CSRNG,
+ IBEX_DEV_ENTROPY,
+ IBEX_DEV_EDNO,
+ IBEX_DEV_EDN1,
IBEX_DEV_ALERT_HANDLER,
IBEX_DEV_NMI_GEN,
- IBEX_DEV_USBDEV,
- IBEX_DEV_PADCTRL,
+ IBEX_DEV_OTBN,
};
enum {
diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h
index cddeca2e77..cdd1a13011 100644
--- a/include/hw/riscv/spike.h
+++ b/include/hw/riscv/spike.h
@@ -47,10 +47,4 @@ enum {
SPIKE_DRAM
};
-#if defined(TARGET_RISCV32)
-#define SPIKE_V1_10_0_CPU TYPE_RISCV_CPU_BASE32
-#elif defined(TARGET_RISCV64)
-#define SPIKE_V1_10_0_CPU TYPE_RISCV_CPU_BASE64
-#endif
-
#endif
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index b4ed9a32eb..84b7a3848f 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -89,10 +89,4 @@ enum {
#define FDT_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + 1 + \
FDT_PLIC_ADDR_CELLS + FDT_PLIC_INT_CELLS)
-#if defined(TARGET_RISCV32)
-#define VIRT_CPU TYPE_RISCV_CPU_BASE32
-#elif defined(TARGET_RISCV64)
-#define VIRT_CPU TYPE_RISCV_CPU_BASE64
-#endif
-
#endif
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 4d71dc8fba..075ee80096 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -43,7 +43,7 @@ struct VMStateInfo {
const char *name;
int (*get)(QEMUFile *f, void *pv, size_t size, const VMStateField *field);
int (*put)(QEMUFile *f, void *pv, size_t size, const VMStateField *field,
- QJSON *vmdesc);
+ JSONWriter *vmdesc);
};
enum VMStateFlags {
@@ -1169,9 +1169,10 @@ extern const VMStateInfo vmstate_info_qlist;
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, int version_id);
int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
- void *opaque, QJSON *vmdesc);
+ void *opaque, JSONWriter *vmdesc);
int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
- void *opaque, QJSON *vmdesc, int version_id);
+ void *opaque, JSONWriter *vmdesc,
+ int version_id);
bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque);
diff --git a/include/qapi/qmp/json-writer.h b/include/qapi/qmp/json-writer.h
new file mode 100644
index 0000000000..b70ba64077
--- /dev/null
+++ b/include/qapi/qmp/json-writer.h
@@ -0,0 +1,35 @@
+/*
+ * JSON Writer
+ *
+ * Copyright (c) 2020 Red Hat Inc.
+ *
+ * Authors:
+ * Markus Armbruster <armbru@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef JSON_WRITER_H
+#define JSON_WRITER_H
+
+JSONWriter *json_writer_new(bool pretty);
+const char *json_writer_get(JSONWriter *);
+GString *json_writer_get_and_free(JSONWriter *);
+void json_writer_free(JSONWriter *);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(JSONWriter, json_writer_free)
+
+void json_writer_start_object(JSONWriter *, const char *name);
+void json_writer_end_object(JSONWriter *);
+void json_writer_start_array(JSONWriter *, const char *name);
+void json_writer_end_array(JSONWriter *);
+void json_writer_bool(JSONWriter *, const char *name, bool val);
+void json_writer_null(JSONWriter *, const char *name);
+void json_writer_int64(JSONWriter *, const char *name, int64_t val);
+void json_writer_uint64(JSONWriter *, const char *name, uint64_t val);
+void json_writer_double(JSONWriter *, const char *name, double val);
+void json_writer_str(JSONWriter *, const char *name, const char *str);
+
+#endif
diff --git a/include/qapi/qmp/qbool.h b/include/qapi/qmp/qbool.h
index 5f61e38e64..2f888d1057 100644
--- a/include/qapi/qmp/qbool.h
+++ b/include/qapi/qmp/qbool.h
@@ -23,7 +23,5 @@ struct QBool {
QBool *qbool_from_bool(bool value);
bool qbool_get_bool(const QBool *qb);
-bool qbool_is_equal(const QObject *x, const QObject *y);
-void qbool_destroy_obj(QObject *obj);
#endif /* QBOOL_H */
diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index da942347a7..9934539c1b 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -39,10 +39,8 @@ void qdict_put_obj(QDict *qdict, const char *key, QObject *value);
void qdict_del(QDict *qdict, const char *key);
int qdict_haskey(const QDict *qdict, const char *key);
QObject *qdict_get(const QDict *qdict, const char *key);
-bool qdict_is_equal(const QObject *x, const QObject *y);
const QDictEntry *qdict_first(const QDict *qdict);
const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry);
-void qdict_destroy_obj(QObject *obj);
/* Helper to qdict_put_obj(), accepts any object */
#define qdict_put(qdict, key, obj) \
diff --git a/include/qapi/qmp/qjson.h b/include/qapi/qmp/qjson.h
index 5ebbe5a118..593b40b4e0 100644
--- a/include/qapi/qmp/qjson.h
+++ b/include/qapi/qmp/qjson.h
@@ -25,7 +25,7 @@ QDict *qdict_from_vjsonf_nofail(const char *string, va_list ap)
QDict *qdict_from_jsonf_nofail(const char *string, ...)
GCC_FMT_ATTR(1, 2);
-QString *qobject_to_json(const QObject *obj);
-QString *qobject_to_json_pretty(const QObject *obj);
+GString *qobject_to_json(const QObject *obj);
+GString *qobject_to_json_pretty(const QObject *obj, bool pretty);
#endif /* QJSON_H */
diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h
index 595b7943e1..06e98ad5f4 100644
--- a/include/qapi/qmp/qlist.h
+++ b/include/qapi/qmp/qlist.h
@@ -51,8 +51,6 @@ QObject *qlist_pop(QList *qlist);
QObject *qlist_peek(QList *qlist);
int qlist_empty(const QList *qlist);
size_t qlist_size(const QList *qlist);
-bool qlist_is_equal(const QObject *x, const QObject *y);
-void qlist_destroy_obj(QObject *obj);
static inline const QListEntry *qlist_first(const QList *qlist)
{
diff --git a/include/qapi/qmp/qnull.h b/include/qapi/qmp/qnull.h
index c1426882c5..e84ecceedb 100644
--- a/include/qapi/qmp/qnull.h
+++ b/include/qapi/qmp/qnull.h
@@ -26,6 +26,4 @@ static inline QNull *qnull(void)
return qobject_ref(&qnull_);
}
-bool qnull_is_equal(const QObject *x, const QObject *y);
-
#endif /* QNULL_H */
diff --git a/include/qapi/qmp/qnum.h b/include/qapi/qmp/qnum.h
index bbae0a5ec8..7f84e20bfb 100644
--- a/include/qapi/qmp/qnum.h
+++ b/include/qapi/qmp/qnum.h
@@ -68,7 +68,4 @@ double qnum_get_double(QNum *qn);
char *qnum_to_string(QNum *qn);
-bool qnum_is_equal(const QObject *x, const QObject *y);
-void qnum_destroy_obj(QObject *obj);
-
#endif /* QNUM_H */
diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h
index fcfd549220..9003b71fd3 100644
--- a/include/qapi/qmp/qobject.h
+++ b/include/qapi/qmp/qobject.h
@@ -64,14 +64,6 @@ QEMU_BUILD_BUG_MSG(QTYPE__MAX != 7,
#define qobject_to(type, obj) \
((type *)qobject_check_type(obj, glue(QTYPE_CAST_TO_, type)))
-/* Initialize an object to default values */
-static inline void qobject_init(QObject *obj, QType type)
-{
- assert(QTYPE_NONE < type && type < QTYPE__MAX);
- obj->base.refcnt = 1;
- obj->base.type = type;
-}
-
static inline void qobject_ref_impl(QObject *obj)
{
if (obj) {
@@ -90,6 +82,7 @@ bool qobject_is_equal(const QObject *x, const QObject *y);
/**
* qobject_destroy(): Free resources used by the object
+ * For use via qobject_unref() only!
*/
void qobject_destroy(QObject *obj);
diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h
index e2e356e5e7..1d8ba46936 100644
--- a/include/qapi/qmp/qstring.h
+++ b/include/qapi/qmp/qstring.h
@@ -17,23 +17,13 @@
struct QString {
struct QObjectBase_ base;
- char *string;
- size_t length;
- size_t capacity;
+ const char *string;
};
QString *qstring_new(void);
QString *qstring_from_str(const char *str);
QString *qstring_from_substr(const char *str, size_t start, size_t end);
-size_t qstring_get_length(const QString *qstring);
+QString *qstring_from_gstring(GString *gstr);
const char *qstring_get_str(const QString *qstring);
-const char *qstring_get_try_str(const QString *qstring);
-const char *qobject_get_try_str(const QObject *qstring);
-void qstring_append_int(QString *qstring, int64_t value);
-void qstring_append(QString *qstring, const char *str);
-void qstring_append_chr(QString *qstring, int c);
-bool qstring_is_equal(const QObject *x, const QObject *y);
-char *qstring_free(QString *qstring, bool return_str);
-void qstring_destroy_obj(QObject *obj);
#endif /* QSTRING_H */
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
index 1b9e58e82b..df9ec08f8a 100644
--- a/include/qemu/compiler.h
+++ b/include/qemu/compiler.h
@@ -222,4 +222,15 @@ extern void QEMU_NORETURN QEMU_ERROR("code path is reachable")
#define qemu_build_not_reached() g_assert_not_reached()
#endif
+/**
+ * In most cases, normal "fallthrough" comments are good enough for
+ * switch-case statements, but sometimes the compiler has problems
+ * with those. In that case you can use QEMU_FALLTHROUGH instead.
+ */
+#if __has_attribute(fallthrough)
+# define QEMU_FALLTHROUGH __attribute__((fallthrough))
+#else
+# define QEMU_FALLTHROUGH do {} while (0) /* fallthrough */
+#endif
+
#endif /* COMPILER_H */
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 6281eae3b5..976b529dfb 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -57,8 +57,8 @@ typedef struct IOMMUMemoryRegion IOMMUMemoryRegion;
typedef struct ISABus ISABus;
typedef struct ISADevice ISADevice;
typedef struct IsaDma IsaDma;
+typedef struct JSONWriter JSONWriter;
typedef struct MACAddr MACAddr;
-typedef struct ReservedRegion ReservedRegion;
typedef struct MachineClass MachineClass;
typedef struct MachineState MachineState;
typedef struct MemoryListener MemoryListener;
@@ -107,7 +107,6 @@ typedef struct QEMUSGList QEMUSGList;
typedef struct QemuSpin QemuSpin;
typedef struct QEMUTimer QEMUTimer;
typedef struct QEMUTimerListGroup QEMUTimerListGroup;
-typedef struct QJSON QJSON;
typedef struct QList QList;
typedef struct QNull QNull;
typedef struct QNum QNum;
@@ -115,6 +114,7 @@ typedef struct QObject QObject;
typedef struct QString QString;
typedef struct RAMBlock RAMBlock;
typedef struct Range Range;
+typedef struct ReservedRegion ReservedRegion;
typedef struct SavedIOTLB SavedIOTLB;
typedef struct SHPCDevice SHPCDevice;
typedef struct SSIBus SSIBus;
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 0b02a92602..a64050713f 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -7,6 +7,7 @@
#include "qemu.h"
#include "disas/disas.h"
+#include "qemu/bitops.h"
#include "qemu/path.h"
#include "qemu/queue.h"
#include "qemu/guest-random.h"
@@ -985,26 +986,54 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMIPSState *e
enum {
HWCAP_MIPS_R6 = (1 << 0),
HWCAP_MIPS_MSA = (1 << 1),
+ HWCAP_MIPS_CRC32 = (1 << 2),
+ HWCAP_MIPS_MIPS16 = (1 << 3),
+ HWCAP_MIPS_MDMX = (1 << 4),
+ HWCAP_MIPS_MIPS3D = (1 << 5),
+ HWCAP_MIPS_SMARTMIPS = (1 << 6),
+ HWCAP_MIPS_DSP = (1 << 7),
+ HWCAP_MIPS_DSP2 = (1 << 8),
+ HWCAP_MIPS_DSP3 = (1 << 9),
+ HWCAP_MIPS_MIPS16E2 = (1 << 10),
+ HWCAP_LOONGSON_MMI = (1 << 11),
+ HWCAP_LOONGSON_EXT = (1 << 12),
+ HWCAP_LOONGSON_EXT2 = (1 << 13),
+ HWCAP_LOONGSON_CPUCFG = (1 << 14),
};
#define ELF_HWCAP get_elf_hwcap()
+#define GET_FEATURE_INSN(_flag, _hwcap) \
+ do { if (cpu->env.insn_flags & (_flag)) { hwcaps |= _hwcap; } } while (0)
+
+#define GET_FEATURE_REG_SET(_reg, _mask, _hwcap) \
+ do { if (cpu->env._reg & (_mask)) { hwcaps |= _hwcap; } } while (0)
+
+#define GET_FEATURE_REG_EQU(_reg, _start, _length, _val, _hwcap) \
+ do { \
+ if (extract32(cpu->env._reg, (_start), (_length)) == (_val)) { \
+ hwcaps |= _hwcap; \
+ } \
+ } while (0)
+
static uint32_t get_elf_hwcap(void)
{
MIPSCPU *cpu = MIPS_CPU(thread_cpu);
uint32_t hwcaps = 0;
-#define GET_FEATURE(flag, hwcap) \
- do { if (cpu->env.insn_flags & (flag)) { hwcaps |= hwcap; } } while (0)
-
- GET_FEATURE(ISA_MIPS32R6 | ISA_MIPS64R6, HWCAP_MIPS_R6);
- GET_FEATURE(ASE_MSA, HWCAP_MIPS_MSA);
-
-#undef GET_FEATURE
+ GET_FEATURE_REG_EQU(CP0_Config0, CP0C0_AR, CP0C0_AR_LENGTH,
+ 2, HWCAP_MIPS_R6);
+ GET_FEATURE_REG_SET(CP0_Config3, 1 << CP0C3_MSAP, HWCAP_MIPS_MSA);
+ GET_FEATURE_INSN(ASE_LMMI, HWCAP_LOONGSON_MMI);
+ GET_FEATURE_INSN(ASE_LEXT, HWCAP_LOONGSON_EXT);
return hwcaps;
}
+#undef GET_FEATURE_REG_EQU
+#undef GET_FEATURE_REG_SET
+#undef GET_FEATURE_INSN
+
#endif /* TARGET_MIPS */
#ifdef TARGET_MICROBLAZE
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 8efb4d38c0..661b5daa9f 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -720,3 +720,49 @@
IOCTL(KCOV_DISABLE, 0, TYPE_NULL)
IOCTL(KCOV_INIT_TRACE, IOC_R, TYPE_ULONG)
#endif
+
+ IOCTL(TUNSETDEBUG, IOC_W, TYPE_INT)
+ IOCTL(TUNSETIFF, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
+ IOCTL(TUNSETPERSIST, IOC_W, TYPE_INT)
+ IOCTL(TUNSETOWNER, IOC_W, TYPE_INT)
+ IOCTL(TUNSETLINK, IOC_W, TYPE_INT)
+ IOCTL(TUNSETGROUP, IOC_W, TYPE_INT)
+ IOCTL(TUNGETFEATURES, IOC_R, MK_PTR(TYPE_INT))
+ IOCTL(TUNSETOFFLOAD, IOC_W, TYPE_LONG)
+ IOCTL_SPECIAL(TUNSETTXFILTER, IOC_W, do_ioctl_TUNSETTXFILTER,
+ /*
+ * We can't represent `struct tun_filter` in thunk so leaving
+ * it uninterpreted. do_ioctl_TUNSETTXFILTER will do the
+ * conversion.
+ */
+ TYPE_PTRVOID)
+ IOCTL(TUNGETIFF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
+ IOCTL(TUNGETSNDBUF, IOC_R, MK_PTR(TYPE_INT))
+ IOCTL(TUNSETSNDBUF, IOC_W, MK_PTR(TYPE_INT))
+ /*
+ * TUNATTACHFILTER and TUNDETACHFILTER are not supported. Linux kernel keeps a
+ * user pointer in TUNATTACHFILTER, which we are not able to correctly handle.
+ */
+ IOCTL(TUNGETVNETHDRSZ, IOC_R, MK_PTR(TYPE_INT))
+ IOCTL(TUNSETVNETHDRSZ, IOC_W, MK_PTR(TYPE_INT))
+ IOCTL(TUNSETQUEUE, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
+ IOCTL(TUNSETIFINDEX , IOC_W, MK_PTR(TYPE_INT))
+ /* TUNGETFILTER is not supported: see TUNATTACHFILTER. */
+ IOCTL(TUNSETVNETLE, IOC_W, MK_PTR(TYPE_INT))
+ IOCTL(TUNGETVNETLE, IOC_R, MK_PTR(TYPE_INT))
+#ifdef TUNSETVNETBE
+ IOCTL(TUNSETVNETBE, IOC_W, MK_PTR(TYPE_INT))
+ IOCTL(TUNGETVNETBE, IOC_R, MK_PTR(TYPE_INT))
+#endif
+#ifdef TUNSETSTEERINGEBPF
+ IOCTL(TUNSETSTEERINGEBPF, IOC_W, MK_PTR(TYPE_INT))
+#endif
+#ifdef TUNSETFILTEREBPF
+ IOCTL(TUNSETFILTEREBPF, IOC_W, MK_PTR(TYPE_INT))
+#endif
+#ifdef TUNSETCARRIER
+ IOCTL(TUNSETCARRIER, IOC_W, MK_PTR(TYPE_INT))
+#endif
+#ifdef TUNGETDEVNETNS
+ IOCTL(TUNGETDEVNETNS, IOC_R, TYPE_NULL)
+#endif
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 00c05e6a0f..810653c503 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -767,20 +767,23 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
}
if (prot == 0) {
host_addr = mremap(g2h(old_addr), old_size, new_size, flags);
- if (host_addr != MAP_FAILED && reserved_va && old_size > new_size) {
- mmap_reserve(old_addr + old_size, old_size - new_size);
+
+ if (host_addr != MAP_FAILED) {
+ /* Check if address fits target address space */
+ if (!guest_range_valid(h2g(host_addr), new_size)) {
+ /* Revert mremap() changes */
+ host_addr = mremap(g2h(old_addr), new_size, old_size,
+ flags);
+ errno = ENOMEM;
+ host_addr = MAP_FAILED;
+ } else if (reserved_va && old_size > new_size) {
+ mmap_reserve(old_addr + old_size, old_size - new_size);
+ }
}
} else {
errno = ENOMEM;
host_addr = MAP_FAILED;
}
- /* Check if address fits target address space */
- if ((unsigned long)host_addr + new_size > (abi_ulong)-1) {
- /* Revert mremap() changes */
- host_addr = mremap(g2h(old_addr), new_size, old_size, flags);
- errno = ENOMEM;
- host_addr = MAP_FAILED;
- }
}
if (host_addr == MAP_FAILED) {
diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c
index d12adc8e6f..d27b7a3af7 100644
--- a/linux-user/sparc/signal.c
+++ b/linux-user/sparc/signal.c
@@ -402,8 +402,10 @@ void sparc64_set_context(CPUSPARCState *env)
abi_ulong ucp_addr;
struct target_ucontext *ucp;
target_mc_gregset_t *grp;
+ target_mc_fpu_t *fpup;
abi_ulong pc, npc, tstate;
unsigned int i;
+ unsigned char fenab;
ucp_addr = env->regwptr[WREG_O0];
if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
@@ -436,16 +438,16 @@ void sparc64_set_context(CPUSPARCState *env)
env->npc = npc;
__get_user(env->y, &((*grp)[SPARC_MC_Y]));
__get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
+ /* Honour TSTATE_ASI, TSTATE_ICC and TSTATE_XCC only */
env->asi = (tstate >> 24) & 0xff;
- cpu_put_ccr(env, tstate >> 32);
- cpu_put_cwp64(env, tstate & 0x1f);
+ cpu_put_ccr(env, (tstate >> 32) & 0xff);
__get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
__get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
__get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
__get_user(env->gregs[4], (&(*grp)[SPARC_MC_G4]));
__get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
__get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
- __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
+ /* Skip g7 as that's the thread register in userspace */
/*
* Note that unlike the kernel, we didn't need to mess with the
@@ -467,26 +469,42 @@ void sparc64_set_context(CPUSPARCState *env)
__get_user(env->regwptr[WREG_FP], &(ucp->tuc_mcontext.mc_fp));
__get_user(env->regwptr[WREG_I7], &(ucp->tuc_mcontext.mc_i7));
- /* FIXME this does not match how the kernel handles the FPU in
- * its sparc64_set_context implementation. In particular the FPU
- * is only restored if fenab is non-zero in:
- * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
- */
- __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
- {
- uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
- for (i = 0; i < 64; i++, src++) {
- if (i & 1) {
- __get_user(env->fpr[i/2].l.lower, src);
- } else {
- __get_user(env->fpr[i/2].l.upper, src);
+ fpup = &ucp->tuc_mcontext.mc_fpregs;
+
+ __get_user(fenab, &(fpup->mcfpu_enab));
+ if (fenab) {
+ abi_ulong fprs;
+
+ /*
+ * We use the FPRS from the guest only in deciding whether
+ * to restore the upper, lower, or both banks of the FPU regs.
+ * The kernel here writes the FPU register data into the
+ * process's current_thread_info state and unconditionally
+ * clears FPRS and TSTATE_PEF: this disables the FPU so that the
+ * next FPU-disabled trap will copy the data out of
+ * current_thread_info and into the real FPU registers.
+ * QEMU doesn't need to handle lazy-FPU-state-restoring like that,
+ * so we always load the data directly into the FPU registers
+ * and leave FPRS and TSTATE_PEF alone (so the FPU stays enabled).
+ * Note that because we (and the kernel) always write zeroes for
+ * the fenab and fprs in sparc64_get_context() none of this code
+ * will execute unless the guest manually constructed or changed
+ * the context structure.
+ */
+ __get_user(fprs, &(fpup->mcfpu_fprs));
+ if (fprs & FPRS_DL) {
+ for (i = 0; i < 16; i++) {
+ __get_user(env->fpr[i].ll, &(fpup->mcfpu_fregs.dregs[i]));
+ }
+ }
+ if (fprs & FPRS_DU) {
+ for (i = 16; i < 32; i++) {
+ __get_user(env->fpr[i].ll, &(fpup->mcfpu_fregs.dregs[i]));
}
}
+ __get_user(env->fsr, &(fpup->mcfpu_fsr));
+ __get_user(env->gsr, &(fpup->mcfpu_gsr));
}
- __get_user(env->fsr,
- &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
- __get_user(env->gsr,
- &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
unlock_user_struct(ucp, ucp_addr, 0);
return;
do_sigsegv:
@@ -509,7 +527,9 @@ void sparc64_get_context(CPUSPARCState *env)
if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
goto do_sigsegv;
}
-
+
+ memset(ucp, 0, sizeof(*ucp));
+
mcp = &ucp->tuc_mcontext;
grp = &mcp->mc_gregs;
@@ -535,12 +555,9 @@ void sparc64_get_context(CPUSPARCState *env)
for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
__put_user(*src, dst);
}
- if (err)
- goto do_sigsegv;
}
- /* XXX: tstate must be saved properly */
- // __put_user(env->tstate, &((*grp)[SPARC_MC_TSTATE]));
+ __put_user(sparc64_tstate(env), &((*grp)[SPARC_MC_TSTATE]));
__put_user(env->pc, &((*grp)[SPARC_MC_PC]));
__put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
__put_user(env->y, &((*grp)[SPARC_MC_Y]));
@@ -572,22 +589,12 @@ void sparc64_get_context(CPUSPARCState *env)
__put_user(env->regwptr[WREG_FP], &(mcp->mc_fp));
__put_user(env->regwptr[WREG_I7], &(mcp->mc_i7));
- {
- uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
- for (i = 0; i < 64; i++, dst++) {
- if (i & 1) {
- __put_user(env->fpr[i/2].l.lower, dst);
- } else {
- __put_user(env->fpr[i/2].l.upper, dst);
- }
- }
- }
- __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
- __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
- __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
+ /*
+ * We don't write out the FPU state. This matches the kernel's
+ * implementation (which has the code for doing this but
+ * hidden behind an "if (fenab)" where fenab is always 0).
+ */
- if (err)
- goto do_sigsegv;
unlock_user_struct(ucp, ucp_addr, 1);
return;
do_sigsegv:
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 7bf99beb18..d182890ff0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -56,6 +56,7 @@
#include <linux/wireless.h>
#include <linux/icmp.h>
#include <linux/icmpv6.h>
+#include <linux/if_tun.h>
#include <linux/errqueue.h>
#include <linux/random.h>
#ifdef CONFIG_TIMERFD
@@ -813,6 +814,12 @@ safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
size_t, len, unsigned *, prio, const struct timespec *, timeout)
#endif
+#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
+safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff,
+ int, outfd, loff_t *, poutoff, size_t, length,
+ unsigned int, flags)
+#endif
+
/* We do ioctl like this rather than via safe_syscall3 to preserve the
* "third argument might be integer or pointer or not present" behaviour of
* the libc function.
@@ -5703,6 +5710,42 @@ static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
#endif
+static abi_long do_ioctl_TUNSETTXFILTER(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, int cmd, abi_long arg)
+{
+ struct tun_filter *filter = (struct tun_filter *)buf_temp;
+ struct tun_filter *target_filter;
+ char *target_addr;
+
+ assert(ie->access == IOC_W);
+
+ target_filter = lock_user(VERIFY_READ, arg, sizeof(*target_filter), 1);
+ if (!target_filter) {
+ return -TARGET_EFAULT;
+ }
+ filter->flags = tswap16(target_filter->flags);
+ filter->count = tswap16(target_filter->count);
+ unlock_user(target_filter, arg, 0);
+
+ if (filter->count) {
+ if (offsetof(struct tun_filter, addr) + filter->count * ETH_ALEN >
+ MAX_STRUCT_SIZE) {
+ return -TARGET_EFAULT;
+ }
+
+ target_addr = lock_user(VERIFY_READ,
+ arg + offsetof(struct tun_filter, addr),
+ filter->count * ETH_ALEN, 1);
+ if (!target_addr) {
+ return -TARGET_EFAULT;
+ }
+ memcpy(filter->addr, target_addr, filter->count * ETH_ALEN);
+ unlock_user(target_addr, arg + offsetof(struct tun_filter, addr), 0);
+ }
+
+ return get_errno(safe_ioctl(fd, ie->host_cmd, filter));
+}
+
IOCTLEntry ioctl_entries[] = {
#define IOCTL(cmd, access, ...) \
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
@@ -13065,6 +13108,42 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
return get_errno(membarrier(arg1, arg2));
#endif
+#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
+ case TARGET_NR_copy_file_range:
+ {
+ loff_t inoff, outoff;
+ loff_t *pinoff = NULL, *poutoff = NULL;
+
+ if (arg2) {
+ if (get_user_u64(inoff, arg2)) {
+ return -TARGET_EFAULT;
+ }
+ pinoff = &inoff;
+ }
+ if (arg4) {
+ if (get_user_u64(outoff, arg4)) {
+ return -TARGET_EFAULT;
+ }
+ poutoff = &outoff;
+ }
+ ret = get_errno(safe_copy_file_range(arg1, pinoff, arg3, poutoff,
+ arg5, arg6));
+ if (!is_error(ret) && ret > 0) {
+ if (arg2) {
+ if (put_user_u64(inoff, arg2)) {
+ return -TARGET_EFAULT;
+ }
+ }
+ if (arg4) {
+ if (put_user_u64(outoff, arg4)) {
+ return -TARGET_EFAULT;
+ }
+ }
+ }
+ }
+ return ret;
+#endif
+
default:
qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
return -TARGET_ENOSYS;
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index b934d0b606..a00bfc2647 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -929,6 +929,38 @@ struct target_rtc_pll_info {
#define TARGET_SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
+/* From <linux/if_tun.h> */
+
+#define TARGET_TUNSETDEBUG TARGET_IOW('T', 201, int)
+#define TARGET_TUNSETIFF TARGET_IOW('T', 202, int)
+#define TARGET_TUNSETPERSIST TARGET_IOW('T', 203, int)
+#define TARGET_TUNSETOWNER TARGET_IOW('T', 204, int)
+#define TARGET_TUNSETLINK TARGET_IOW('T', 205, int)
+#define TARGET_TUNSETGROUP TARGET_IOW('T', 206, int)
+#define TARGET_TUNGETFEATURES TARGET_IOR('T', 207, unsigned int)
+#define TARGET_TUNSETOFFLOAD TARGET_IOW('T', 208, unsigned int)
+#define TARGET_TUNSETTXFILTER TARGET_IOW('T', 209, unsigned int)
+#define TARGET_TUNGETIFF TARGET_IOR('T', 210, unsigned int)
+#define TARGET_TUNGETSNDBUF TARGET_IOR('T', 211, int)
+#define TARGET_TUNSETSNDBUF TARGET_IOW('T', 212, int)
+/*
+ * TUNATTACHFILTER and TUNDETACHFILTER are not supported. Linux kernel keeps a
+ * user pointer in TUNATTACHFILTER, which we are not able to correctly handle.
+ */
+#define TARGET_TUNGETVNETHDRSZ TARGET_IOR('T', 215, int)
+#define TARGET_TUNSETVNETHDRSZ TARGET_IOW('T', 216, int)
+#define TARGET_TUNSETQUEUE TARGET_IOW('T', 217, int)
+#define TARGET_TUNSETIFINDEX TARGET_IOW('T', 218, unsigned int)
+/* TUNGETFILTER is not supported: see TUNATTACHFILTER. */
+#define TARGET_TUNSETVNETLE TARGET_IOW('T', 220, int)
+#define TARGET_TUNGETVNETLE TARGET_IOR('T', 221, int)
+#define TARGET_TUNSETVNETBE TARGET_IOW('T', 222, int)
+#define TARGET_TUNGETVNETBE TARGET_IOR('T', 223, int)
+#define TARGET_TUNSETSTEERINGEBPF TARGET_IOR('T', 224, int)
+#define TARGET_TUNSETFILTEREBPF TARGET_IOR('T', 225, int)
+#define TARGET_TUNSETCARRIER TARGET_IOW('T', 226, int)
+#define TARGET_TUNGETDEVNETNS TARGET_IO('T', 227)
+
/* From <linux/random.h> */
#define TARGET_RNDGETENTCNT TARGET_IOR('R', 0x00, int)
diff --git a/migration/meson.build b/migration/meson.build
index 980e37865c..291adc1337 100644
--- a/migration/meson.build
+++ b/migration/meson.build
@@ -6,7 +6,6 @@ migration_files = files(
'vmstate.c',
'qemu-file-channel.c',
'qemu-file.c',
- 'qjson.c',
)
softmmu_ss.add(migration_files)
diff --git a/migration/migration.c b/migration/migration.c
index e0dbde4091..9c7ed12cec 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -406,12 +406,9 @@ int migration_incoming_enable_colo(void)
void migrate_add_address(SocketAddress *address)
{
MigrationIncomingState *mis = migration_incoming_get_current();
- SocketAddressList *addrs;
- addrs = g_new0(SocketAddressList, 1);
- addrs->next = mis->socket_address_list;
- mis->socket_address_list = addrs;
- addrs->value = QAPI_CLONE(SocketAddress, address);
+ QAPI_LIST_PREPEND(mis->socket_address_list,
+ QAPI_CLONE(SocketAddress, address));
}
static void qemu_start_incoming_migration(const char *uri, Error **errp)
@@ -1654,27 +1651,23 @@ void migrate_set_state(int *state, int old_state, int new_state)
}
}
-static MigrationCapabilityStatusList *migrate_cap_add(
- MigrationCapabilityStatusList *list,
- MigrationCapability index,
- bool state)
+static MigrationCapabilityStatus *migrate_cap_add(MigrationCapability index,
+ bool state)
{
- MigrationCapabilityStatusList *cap;
+ MigrationCapabilityStatus *cap;
- cap = g_new0(MigrationCapabilityStatusList, 1);
- cap->value = g_new0(MigrationCapabilityStatus, 1);
- cap->value->capability = index;
- cap->value->state = state;
- cap->next = list;
+ cap = g_new0(MigrationCapabilityStatus, 1);
+ cap->capability = index;
+ cap->state = state;
return cap;
}
void migrate_set_block_enabled(bool value, Error **errp)
{
- MigrationCapabilityStatusList *cap;
+ MigrationCapabilityStatusList *cap = NULL;
- cap = migrate_cap_add(NULL, MIGRATION_CAPABILITY_BLOCK, value);
+ QAPI_LIST_PREPEND(cap, migrate_cap_add(MIGRATION_CAPABILITY_BLOCK, value));
qmp_migrate_set_capabilities(cap, errp);
qapi_free_MigrationCapabilityStatusList(cap);
}
@@ -2102,6 +2095,12 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc,
return false;
}
+ if (runstate_check(RUN_STATE_POSTMIGRATE)) {
+ error_setg(errp, "Can't migrate the vm that was paused due to "
+ "previous migration");
+ return false;
+ }
+
if (migration_is_blocked(errp)) {
return false;
}
@@ -3863,7 +3862,7 @@ static bool migration_object_check(MigrationState *ms, Error **errp)
for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
if (ms->enabled_capabilities[i]) {
- head = migrate_cap_add(head, i, true);
+ QAPI_LIST_PREPEND(head, migrate_cap_add(i, true));
}
}
diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
index d99842eb1b..ab482adef1 100644
--- a/migration/postcopy-ram.c
+++ b/migration/postcopy-ram.c
@@ -145,14 +145,11 @@ static struct PostcopyBlocktimeContext *blocktime_context_new(void)
static uint32List *get_vcpu_blocktime_list(PostcopyBlocktimeContext *ctx)
{
MachineState *ms = MACHINE(qdev_get_machine());
- uint32List *list = NULL, *entry = NULL;
+ uint32List *list = NULL;
int i;
for (i = ms->smp.cpus - 1; i >= 0; i--) {
- entry = g_new0(uint32List, 1);
- entry->value = ctx->vcpu_blocktime[i];
- entry->next = list;
- list = entry;
+ QAPI_LIST_PREPEND(list, ctx->vcpu_blocktime[i]);
}
return list;
diff --git a/migration/qjson.c b/migration/qjson.c
deleted file mode 100644
index e9889bdcb0..0000000000
--- a/migration/qjson.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * A simple JSON writer
- *
- * Copyright Alexander Graf
- *
- * Authors:
- * Alexander Graf <agraf@suse.de>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-
-/*
- * Type QJSON lets you build JSON text. Its interface mirrors (a
- * subset of) abstract JSON syntax.
- *
- * It does *not* detect incorrect use. It happily produces invalid
- * JSON then. This is what migration wants.
- *
- * QAPI output visitors also produce JSON text. However, they do
- * assert their preconditions and invariants, and therefore abort on
- * incorrect use.
- */
-
-#include "qemu/osdep.h"
-#include "qapi/qmp/qstring.h"
-#include "qjson.h"
-
-struct QJSON {
- QString *str;
- bool omit_comma;
-};
-
-static void json_emit_element(QJSON *json, const char *name)
-{
- /* Check whether we need to print a , before an element */
- if (json->omit_comma) {
- json->omit_comma = false;
- } else {
- qstring_append(json->str, ", ");
- }
-
- if (name) {
- qstring_append(json->str, "\"");
- qstring_append(json->str, name);
- qstring_append(json->str, "\" : ");
- }
-}
-
-void json_start_object(QJSON *json, const char *name)
-{
- json_emit_element(json, name);
- qstring_append(json->str, "{ ");
- json->omit_comma = true;
-}
-
-void json_end_object(QJSON *json)
-{
- qstring_append(json->str, " }");
- json->omit_comma = false;
-}
-
-void json_start_array(QJSON *json, const char *name)
-{
- json_emit_element(json, name);
- qstring_append(json->str, "[ ");
- json->omit_comma = true;
-}
-
-void json_end_array(QJSON *json)
-{
- qstring_append(json->str, " ]");
- json->omit_comma = false;
-}
-
-void json_prop_int(QJSON *json, const char *name, int64_t val)
-{
- json_emit_element(json, name);
- qstring_append_int(json->str, val);
-}
-
-void json_prop_str(QJSON *json, const char *name, const char *str)
-{
- json_emit_element(json, name);
- qstring_append_chr(json->str, '"');
- qstring_append(json->str, str);
- qstring_append_chr(json->str, '"');
-}
-
-const char *qjson_get_str(QJSON *json)
-{
- return qstring_get_str(json->str);
-}
-
-QJSON *qjson_new(void)
-{
- QJSON *json = g_new0(QJSON, 1);
-
- json->str = qstring_from_str("{ ");
- json->omit_comma = true;
- return json;
-}
-
-void qjson_finish(QJSON *json)
-{
- json_end_object(json);
-}
-
-void qjson_destroy(QJSON *json)
-{
- qobject_unref(json->str);
- g_free(json);
-}
diff --git a/migration/qjson.h b/migration/qjson.h
deleted file mode 100644
index 1786bb5864..0000000000
--- a/migration/qjson.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * QEMU JSON writer
- *
- * Copyright Alexander Graf
- *
- * Authors:
- * Alexander Graf <agraf@suse.de>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-#ifndef QEMU_QJSON_H
-#define QEMU_QJSON_H
-
-QJSON *qjson_new(void);
-void qjson_destroy(QJSON *json);
-void json_prop_str(QJSON *json, const char *name, const char *str);
-void json_prop_int(QJSON *json, const char *name, int64_t val);
-void json_end_array(QJSON *json);
-void json_start_array(QJSON *json, const char *name);
-void json_end_object(QJSON *json);
-void json_start_object(QJSON *json, const char *name);
-const char *qjson_get_str(QJSON *json);
-void qjson_finish(QJSON *json);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(QJSON, qjson_destroy)
-
-#endif /* QEMU_QJSON_H */
diff --git a/migration/savevm.c b/migration/savevm.c
index 5f937a2762..27e842812e 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -42,6 +42,7 @@
#include "postcopy-ram.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-migration.h"
+#include "qapi/qmp/json-writer.h"
#include "qapi/qmp/qerror.h"
#include "qemu/error-report.h"
#include "sysemu/cpus.h"
@@ -58,7 +59,6 @@
#include "sysemu/runstate.h"
#include "sysemu/sysemu.h"
#include "sysemu/xen.h"
-#include "qjson.h"
#include "migration/colo.h"
#include "qemu/bitmap.h"
#include "net/announce.h"
@@ -209,7 +209,7 @@ static int get_timer(QEMUFile *f, void *pv, size_t size,
}
static int put_timer(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
QEMUTimer *v = pv;
timer_put(f, v);
@@ -406,7 +406,7 @@ static int get_capability(QEMUFile *f, void *pv, size_t size,
}
static int put_capability(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
MigrationCapability *capability = pv;
const char *capability_str = MigrationCapability_str(*capability);
@@ -884,7 +884,8 @@ static int vmstate_load(QEMUFile *f, SaveStateEntry *se)
return vmstate_load_state(f, se->vmsd, se->opaque, se->load_version_id);
}
-static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se, QJSON *vmdesc)
+static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se,
+ JSONWriter *vmdesc)
{
int64_t old_offset, size;
@@ -893,18 +894,19 @@ static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se, QJSON *vmdes
size = qemu_ftell_fast(f) - old_offset;
if (vmdesc) {
- json_prop_int(vmdesc, "size", size);
- json_start_array(vmdesc, "fields");
- json_start_object(vmdesc, NULL);
- json_prop_str(vmdesc, "name", "data");
- json_prop_int(vmdesc, "size", size);
- json_prop_str(vmdesc, "type", "buffer");
- json_end_object(vmdesc);
- json_end_array(vmdesc);
+ json_writer_int64(vmdesc, "size", size);
+ json_writer_start_array(vmdesc, "fields");
+ json_writer_start_object(vmdesc, NULL);
+ json_writer_str(vmdesc, "name", "data");
+ json_writer_int64(vmdesc, "size", size);
+ json_writer_str(vmdesc, "type", "buffer");
+ json_writer_end_object(vmdesc);
+ json_writer_end_array(vmdesc);
}
}
-static int vmstate_save(QEMUFile *f, SaveStateEntry *se, QJSON *vmdesc)
+static int vmstate_save(QEMUFile *f, SaveStateEntry *se,
+ JSONWriter *vmdesc)
{
trace_vmstate_save(se->idstr, se->vmsd ? se->vmsd->name : "(old)");
if (!se->vmsd) {
@@ -1357,14 +1359,15 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
bool in_postcopy,
bool inactivate_disks)
{
- g_autoptr(QJSON) vmdesc = NULL;
+ g_autoptr(JSONWriter) vmdesc = NULL;
int vmdesc_len;
SaveStateEntry *se;
int ret;
- vmdesc = qjson_new();
- json_prop_int(vmdesc, "page_size", qemu_target_page_size());
- json_start_array(vmdesc, "devices");
+ vmdesc = json_writer_new(false);
+ json_writer_start_object(vmdesc, NULL);
+ json_writer_int64(vmdesc, "page_size", qemu_target_page_size());
+ json_writer_start_array(vmdesc, "devices");
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if ((!se->ops || !se->ops->save_state) && !se->vmsd) {
@@ -1377,9 +1380,9 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
trace_savevm_section_start(se->idstr, se->section_id);
- json_start_object(vmdesc, NULL);
- json_prop_str(vmdesc, "name", se->idstr);
- json_prop_int(vmdesc, "instance_id", se->instance_id);
+ json_writer_start_object(vmdesc, NULL);
+ json_writer_str(vmdesc, "name", se->idstr);
+ json_writer_int64(vmdesc, "instance_id", se->instance_id);
save_section_header(f, se, QEMU_VM_SECTION_FULL);
ret = vmstate_save(f, se, vmdesc);
@@ -1390,7 +1393,7 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
trace_savevm_section_end(se->idstr, se->section_id, 0);
save_section_footer(f, se);
- json_end_object(vmdesc);
+ json_writer_end_object(vmdesc);
}
if (inactivate_disks) {
@@ -1409,14 +1412,14 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
qemu_put_byte(f, QEMU_VM_EOF);
}
- json_end_array(vmdesc);
- qjson_finish(vmdesc);
- vmdesc_len = strlen(qjson_get_str(vmdesc));
+ json_writer_end_array(vmdesc);
+ json_writer_end_object(vmdesc);
+ vmdesc_len = strlen(json_writer_get(vmdesc));
if (should_send_vmdesc()) {
qemu_put_byte(f, QEMU_VM_VMDESCRIPTION);
qemu_put_be32(f, vmdesc_len);
- qemu_put_buffer(f, (uint8_t *)qjson_get_str(vmdesc), vmdesc_len);
+ qemu_put_buffer(f, (uint8_t *)json_writer_get(vmdesc), vmdesc_len);
}
return 0;
@@ -2728,7 +2731,7 @@ int qemu_load_device_state(QEMUFile *f)
int save_snapshot(const char *name, Error **errp)
{
BlockDriverState *bs, *bs1;
- QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
+ QEMUSnapshotInfo sn1, *sn = &sn1;
int ret = -1, ret2;
QEMUFile *f;
int saved_vm_running;
@@ -2797,13 +2800,7 @@ int save_snapshot(const char *name, Error **errp)
}
if (name) {
- ret = bdrv_snapshot_find(bs, old_sn, name);
- if (ret >= 0) {
- pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
- pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
- } else {
- pstrcpy(sn->name, sizeof(sn->name), name);
- }
+ pstrcpy(sn->name, sizeof(sn->name), name);
} else {
/* cast below needed for OpenBSD where tv_sec is still 'long' */
localtime_r((const time_t *)&tv.tv_sec, &tm);
@@ -2839,6 +2836,7 @@ int save_snapshot(const char *name, Error **errp)
if (ret < 0) {
error_setg(errp, "Error while creating snapshot on '%s'",
bdrv_get_device_or_node_name(bs));
+ bdrv_all_delete_snapshot(sn->name, &bs, NULL);
goto the_end;
}
diff --git a/migration/vmstate-types.c b/migration/vmstate-types.c
index e22d41d73d..bf4d440308 100644
--- a/migration/vmstate-types.c
+++ b/migration/vmstate-types.c
@@ -29,7 +29,7 @@ static int get_bool(QEMUFile *f, void *pv, size_t size,
}
static int put_bool(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
bool *v = pv;
qemu_put_byte(f, *v);
@@ -53,7 +53,7 @@ static int get_int8(QEMUFile *f, void *pv, size_t size,
}
static int put_int8(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
int8_t *v = pv;
qemu_put_s8s(f, v);
@@ -77,7 +77,7 @@ static int get_int16(QEMUFile *f, void *pv, size_t size,
}
static int put_int16(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
int16_t *v = pv;
qemu_put_sbe16s(f, v);
@@ -101,7 +101,7 @@ static int get_int32(QEMUFile *f, void *pv, size_t size,
}
static int put_int32(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
int32_t *v = pv;
qemu_put_sbe32s(f, v);
@@ -178,7 +178,7 @@ static int get_int64(QEMUFile *f, void *pv, size_t size,
}
static int put_int64(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
int64_t *v = pv;
qemu_put_sbe64s(f, v);
@@ -202,7 +202,7 @@ static int get_uint8(QEMUFile *f, void *pv, size_t size,
}
static int put_uint8(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
uint8_t *v = pv;
qemu_put_8s(f, v);
@@ -226,7 +226,7 @@ static int get_uint16(QEMUFile *f, void *pv, size_t size,
}
static int put_uint16(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
uint16_t *v = pv;
qemu_put_be16s(f, v);
@@ -250,7 +250,7 @@ static int get_uint32(QEMUFile *f, void *pv, size_t size,
}
static int put_uint32(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
uint32_t *v = pv;
qemu_put_be32s(f, v);
@@ -300,7 +300,7 @@ static int get_uint64(QEMUFile *f, void *pv, size_t size,
}
static int put_uint64(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
uint64_t *v = pv;
qemu_put_be64s(f, v);
@@ -325,7 +325,7 @@ static int get_nullptr(QEMUFile *f, void *pv, size_t size,
}
static int put_nullptr(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
if (pv == NULL) {
@@ -432,7 +432,7 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size,
}
static int put_cpudouble(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
CPU_DoubleU *v = pv;
qemu_put_be32s(f, &v->l.upper);
@@ -457,7 +457,7 @@ static int get_buffer(QEMUFile *f, void *pv, size_t size,
}
static int put_buffer(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
uint8_t *v = pv;
qemu_put_buffer(f, v, size);
@@ -488,7 +488,7 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size,
}
static int put_unused_buffer(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
static const uint8_t buf[1024];
int block_len;
@@ -530,7 +530,7 @@ static int get_tmp(QEMUFile *f, void *pv, size_t size,
}
static int put_tmp(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
const VMStateDescription *vmsd = field->vmsd;
void *tmp = g_malloc(size);
@@ -573,7 +573,7 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size,
}
static int put_bitmap(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
unsigned long *bmp = pv;
int i, idx = 0;
@@ -637,7 +637,7 @@ static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
/* put for QTAILQ */
static int put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
const VMStateDescription *vmsd = field->vmsd;
/* offset of the QTAILQ entry in a QTAILQ element*/
@@ -670,7 +670,7 @@ struct put_gtree_data {
QEMUFile *f;
const VMStateDescription *key_vmsd;
const VMStateDescription *val_vmsd;
- QJSON *vmdesc;
+ JSONWriter *vmdesc;
int ret;
};
@@ -703,7 +703,7 @@ static gboolean put_gtree_elem(gpointer key, gpointer value, gpointer data)
}
static int put_gtree(QEMUFile *f, void *pv, size_t unused_size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
bool direct_key = (!field->start);
const VMStateDescription *key_vmsd = direct_key ? NULL : &field->vmsd[1];
@@ -819,7 +819,7 @@ const VMStateInfo vmstate_info_gtree = {
};
static int put_qlist(QEMUFile *f, void *pv, size_t unused_size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
const VMStateDescription *vmsd = field->vmsd;
/* offset of the QTAILQ entry in a QTAILQ element*/
diff --git a/migration/vmstate.c b/migration/vmstate.c
index e9d2aef66b..05f87cdddc 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -14,14 +14,14 @@
#include "migration.h"
#include "migration/vmstate.h"
#include "savevm.h"
+#include "qapi/qmp/json-writer.h"
#include "qemu-file.h"
#include "qemu/bitops.h"
#include "qemu/error-report.h"
#include "trace.h"
-#include "qjson.h"
static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
- void *opaque, QJSON *vmdesc);
+ void *opaque, JSONWriter *vmdesc);
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque);
@@ -249,7 +249,8 @@ static bool vmsd_can_compress(const VMStateField *field)
return true;
}
-static void vmsd_desc_field_start(const VMStateDescription *vmsd, QJSON *vmdesc,
+static void vmsd_desc_field_start(const VMStateDescription *vmsd,
+ JSONWriter *vmdesc,
const VMStateField *field, int i, int max)
{
char *name, *old_name;
@@ -270,25 +271,26 @@ static void vmsd_desc_field_start(const VMStateDescription *vmsd, QJSON *vmdesc,
g_free(old_name);
}
- json_start_object(vmdesc, NULL);
- json_prop_str(vmdesc, "name", name);
+ json_writer_start_object(vmdesc, NULL);
+ json_writer_str(vmdesc, "name", name);
if (is_array) {
if (can_compress) {
- json_prop_int(vmdesc, "array_len", max);
+ json_writer_int64(vmdesc, "array_len", max);
} else {
- json_prop_int(vmdesc, "index", i);
+ json_writer_int64(vmdesc, "index", i);
}
}
- json_prop_str(vmdesc, "type", vmfield_get_type_name(field));
+ json_writer_str(vmdesc, "type", vmfield_get_type_name(field));
if (field->flags & VMS_STRUCT) {
- json_start_object(vmdesc, "struct");
+ json_writer_start_object(vmdesc, "struct");
}
g_free(name);
}
-static void vmsd_desc_field_end(const VMStateDescription *vmsd, QJSON *vmdesc,
+static void vmsd_desc_field_end(const VMStateDescription *vmsd,
+ JSONWriter *vmdesc,
const VMStateField *field, size_t size, int i)
{
if (!vmdesc) {
@@ -297,11 +299,11 @@ static void vmsd_desc_field_end(const VMStateDescription *vmsd, QJSON *vmdesc,
if (field->flags & VMS_STRUCT) {
/* We printed a struct in between, close its child object */
- json_end_object(vmdesc);
+ json_writer_end_object(vmdesc);
}
- json_prop_int(vmdesc, "size", size);
- json_end_object(vmdesc);
+ json_writer_int64(vmdesc, "size", size);
+ json_writer_end_object(vmdesc);
}
@@ -316,13 +318,13 @@ bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque)
int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
- void *opaque, QJSON *vmdesc_id)
+ void *opaque, JSONWriter *vmdesc_id)
{
return vmstate_save_state_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id);
}
int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
- void *opaque, QJSON *vmdesc, int version_id)
+ void *opaque, JSONWriter *vmdesc, int version_id)
{
int ret = 0;
const VMStateField *field = vmsd->fields;
@@ -339,9 +341,9 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
}
if (vmdesc) {
- json_prop_str(vmdesc, "vmsd_name", vmsd->name);
- json_prop_int(vmdesc, "version", version_id);
- json_start_array(vmdesc, "fields");
+ json_writer_str(vmdesc, "vmsd_name", vmsd->name);
+ json_writer_int64(vmdesc, "version", version_id);
+ json_writer_start_array(vmdesc, "fields");
}
while (field->name) {
@@ -353,7 +355,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
int i, n_elems = vmstate_n_elems(opaque, field);
int size = vmstate_size(opaque, field);
int64_t old_offset, written_bytes;
- QJSON *vmdesc_loop = vmdesc;
+ JSONWriter *vmdesc_loop = vmdesc;
trace_vmstate_save_state_loop(vmsd->name, field->name, n_elems);
if (field->flags & VMS_POINTER) {
@@ -413,7 +415,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
}
if (vmdesc) {
- json_end_array(vmdesc);
+ json_writer_end_array(vmdesc);
}
ret = vmstate_subsection_save(f, vmsd, opaque, vmdesc);
@@ -491,7 +493,7 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
}
static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
- void *opaque, QJSON *vmdesc)
+ void *opaque, JSONWriter *vmdesc)
{
const VMStateDescription **sub = vmsd->subsections;
bool vmdesc_has_subsections = false;
@@ -507,11 +509,11 @@ static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
if (vmdesc) {
/* Only create subsection array when we have any */
if (!vmdesc_has_subsections) {
- json_start_array(vmdesc, "subsections");
+ json_writer_start_array(vmdesc, "subsections");
vmdesc_has_subsections = true;
}
- json_start_object(vmdesc, NULL);
+ json_writer_start_object(vmdesc, NULL);
}
qemu_put_byte(f, QEMU_VM_SUBSECTION);
@@ -525,14 +527,14 @@ static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
}
if (vmdesc) {
- json_end_object(vmdesc);
+ json_writer_end_object(vmdesc);
}
}
sub++;
}
if (vmdesc_has_subsections) {
- json_end_array(vmdesc);
+ json_writer_end_array(vmdesc);
}
return ret;
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 65d8ff4849..0dd594f92b 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -1255,7 +1255,8 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
const char *cap = qdict_get_str(qdict, "capability");
bool state = qdict_get_bool(qdict, "state");
Error *err = NULL;
- MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps));
+ MigrationCapabilityStatusList *caps = NULL;
+ MigrationCapabilityStatus *value;
int val;
val = qapi_enum_parse(&MigrationCapability_lookup, cap, -1, &err);
@@ -1263,14 +1264,14 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
goto end;
}
- caps->value = g_malloc0(sizeof(*caps->value));
- caps->value->capability = val;
- caps->value->state = state;
- caps->next = NULL;
+ value = g_malloc0(sizeof(*value));
+ value->capability = val;
+ value->state = state;
+ QAPI_LIST_PREPEND(caps, value);
qmp_migrate_set_capabilities(caps, &err);
+ qapi_free_MigrationCapabilityStatusList(caps);
end:
- qapi_free_MigrationCapabilityStatusList(caps);
hmp_handle_error(mon, err);
}
@@ -1549,8 +1550,7 @@ end:
hmp_handle_error(mon, err);
}
-typedef struct HMPMigrationStatus
-{
+typedef struct HMPMigrationStatus {
QEMUTimer *timer;
Monitor *mon;
bool is_block_migration;
diff --git a/monitor/misc.c b/monitor/misc.c
index fde6e36a0b..a5d4d4e4f4 100644
--- a/monitor/misc.c
+++ b/monitor/misc.c
@@ -136,11 +136,7 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
handle_hmp_command(&hmp, command_line);
WITH_QEMU_LOCK_GUARD(&hmp.common.mon_lock) {
- if (qstring_get_length(hmp.common.outbuf) > 0) {
- output = g_strdup(qstring_get_str(hmp.common.outbuf));
- } else {
- output = g_strdup("");
- }
+ output = g_strdup(hmp.common.outbuf->str);
}
out:
@@ -492,8 +488,10 @@ static void hmp_singlestep(Monitor *mon, const QDict *qdict)
static void hmp_gdbserver(Monitor *mon, const QDict *qdict)
{
const char *device = qdict_get_try_str(qdict, "device");
- if (!device)
+ if (!device) {
device = "tcp::" DEFAULT_GDBSTUB_PORT;
+ }
+
if (gdbserver_start(device) < 0) {
monitor_printf(mon, "Could not open gdbserver on device '%s'\n",
device);
@@ -559,10 +557,11 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
}
len = wsize * count;
- if (wsize == 1)
+ if (wsize == 1) {
line_size = 8;
- else
+ } else {
line_size = 16;
+ }
max_digits = 0;
switch(format) {
@@ -583,10 +582,11 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
}
while (len > 0) {
- if (is_physical)
+ if (is_physical) {
monitor_printf(mon, TARGET_FMT_plx ":", addr);
- else
+ } else {
monitor_printf(mon, TARGET_FMT_lx ":", (target_ulong)addr);
+ }
l = len;
if (l > line_size)
l = line_size;
@@ -915,7 +915,7 @@ static void hmp_ioport_read(Monitor *mon, const QDict *qdict)
suffix = 'l';
break;
}
- monitor_printf(mon, "port%c[0x%04x] = %#0*x\n",
+ monitor_printf(mon, "port%c[0x%04x] = 0x%0*x\n",
suffix, addr, size * 2, val);
}
@@ -1430,33 +1430,26 @@ FdsetInfoList *qmp_query_fdsets(Error **errp)
QEMU_LOCK_GUARD(&mon_fdsets_lock);
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
- FdsetInfoList *fdset_info = g_malloc0(sizeof(*fdset_info));
- FdsetFdInfoList *fdsetfd_list = NULL;
+ FdsetInfo *fdset_info = g_malloc0(sizeof(*fdset_info));
- fdset_info->value = g_malloc0(sizeof(*fdset_info->value));
- fdset_info->value->fdset_id = mon_fdset->id;
+ fdset_info->fdset_id = mon_fdset->id;
QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
- FdsetFdInfoList *fdsetfd_info;
+ FdsetFdInfo *fdsetfd_info;
fdsetfd_info = g_malloc0(sizeof(*fdsetfd_info));
- fdsetfd_info->value = g_malloc0(sizeof(*fdsetfd_info->value));
- fdsetfd_info->value->fd = mon_fdset_fd->fd;
+ fdsetfd_info->fd = mon_fdset_fd->fd;
if (mon_fdset_fd->opaque) {
- fdsetfd_info->value->has_opaque = true;
- fdsetfd_info->value->opaque = g_strdup(mon_fdset_fd->opaque);
+ fdsetfd_info->has_opaque = true;
+ fdsetfd_info->opaque = g_strdup(mon_fdset_fd->opaque);
} else {
- fdsetfd_info->value->has_opaque = false;
+ fdsetfd_info->has_opaque = false;
}
- fdsetfd_info->next = fdsetfd_list;
- fdsetfd_list = fdsetfd_info;
+ QAPI_LIST_PREPEND(fdset_info->fds, fdsetfd_info);
}
- fdset_info->value->fds = fdsetfd_list;
-
- fdset_info->next = fdset_list;
- fdset_list = fdset_info;
+ QAPI_LIST_PREPEND(fdset_list, fdset_info);
}
return fdset_list;
diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h
index a6131554da..40903d6386 100644
--- a/monitor/monitor-internal.h
+++ b/monitor/monitor-internal.h
@@ -105,7 +105,7 @@ struct Monitor {
* Members that are protected by the per-monitor lock
*/
QLIST_HEAD(, mon_fd_t) fds;
- QString *outbuf;
+ GString *outbuf;
guint out_watch;
/* Read under either BQL or mon_lock, written with BQL+mon_lock. */
int mux_out;
diff --git a/monitor/monitor.c b/monitor/monitor.c
index 84222cd130..1e4a6b3f20 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -29,7 +29,6 @@
#include "qapi/qapi-emit-events.h"
#include "qapi/qapi-visit-control.h"
#include "qapi/qmp/qdict.h"
-#include "qapi/qmp/qstring.h"
#include "qemu/error-report.h"
#include "qemu/option.h"
#include "sysemu/qtest.h"
@@ -181,22 +180,19 @@ static void monitor_flush_locked(Monitor *mon)
return;
}
- buf = qstring_get_str(mon->outbuf);
- len = qstring_get_length(mon->outbuf);
+ buf = mon->outbuf->str;
+ len = mon->outbuf->len;
if (len && !mon->mux_out) {
rc = qemu_chr_fe_write(&mon->chr, (const uint8_t *) buf, len);
if ((rc < 0 && errno != EAGAIN) || (rc == len)) {
/* all flushed or error */
- qobject_unref(mon->outbuf);
- mon->outbuf = qstring_new();
+ g_string_truncate(mon->outbuf, 0);
return;
}
if (rc > 0) {
/* partial write */
- QString *tmp = qstring_from_str(buf + rc);
- qobject_unref(mon->outbuf);
- mon->outbuf = tmp;
+ g_string_erase(mon->outbuf, 0, rc);
}
if (mon->out_watch == 0) {
mon->out_watch =
@@ -223,9 +219,9 @@ int monitor_puts(Monitor *mon, const char *str)
for (i = 0; str[i]; i++) {
c = str[i];
if (c == '\n') {
- qstring_append_chr(mon->outbuf, '\r');
+ g_string_append_c(mon->outbuf, '\r');
}
- qstring_append_chr(mon->outbuf, c);
+ g_string_append_c(mon->outbuf, c);
if (c == '\n') {
monitor_flush_locked(mon);
}
@@ -602,7 +598,7 @@ void monitor_data_init(Monitor *mon, bool is_qmp, bool skip_flush,
}
qemu_mutex_init(&mon->mon_lock);
mon->is_qmp = is_qmp;
- mon->outbuf = qstring_new();
+ mon->outbuf = g_string_new(NULL);
mon->skip_flush = skip_flush;
mon->use_io_thread = use_io_thread;
}
@@ -616,7 +612,7 @@ void monitor_data_destroy(Monitor *mon)
} else {
readline_free(container_of(mon, MonitorHMP, common)->rs);
}
- qobject_unref(mon->outbuf);
+ g_string_free(mon->outbuf, true);
qemu_mutex_destroy(&mon->mon_lock);
}
diff --git a/monitor/qmp-cmds-control.c b/monitor/qmp-cmds-control.c
index a456762f6a..17514f4959 100644
--- a/monitor/qmp-cmds-control.c
+++ b/monitor/qmp-cmds-control.c
@@ -138,18 +138,18 @@ EventInfoList *qmp_query_events(Error **errp)
* QAPIEvent_str() and QAPIEvent_lookup[]. When the command goes,
* they should go, too.
*/
- EventInfoList *info, *ev_list = NULL;
+ EventInfoList *ev_list = NULL;
QAPIEvent e;
for (e = 0 ; e < QAPI_EVENT__MAX ; e++) {
const char *event_name = QAPIEvent_str(e);
+ EventInfo *info;
+
assert(event_name != NULL);
info = g_malloc0(sizeof(*info));
- info->value = g_malloc0(sizeof(*info->value));
- info->value->name = g_strdup(event_name);
+ info->name = g_strdup(event_name);
- info->next = ev_list;
- ev_list = info;
+ QAPI_LIST_PREPEND(ev_list, info);
}
return ev_list;
diff --git a/monitor/qmp.c b/monitor/qmp.c
index b42f8c6af3..8f91af32be 100644
--- a/monitor/qmp.c
+++ b/monitor/qmp.c
@@ -31,7 +31,6 @@
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qjson.h"
#include "qapi/qmp/qlist.h"
-#include "qapi/qmp/qstring.h"
#include "trace.h"
struct QMPRequest {
@@ -110,15 +109,15 @@ static void monitor_qmp_cleanup_queue_and_resume(MonitorQMP *mon)
void qmp_send_response(MonitorQMP *mon, const QDict *rsp)
{
const QObject *data = QOBJECT(rsp);
- QString *json;
+ GString *json;
- json = mon->pretty ? qobject_to_json_pretty(data) : qobject_to_json(data);
+ json = qobject_to_json_pretty(data, mon->pretty);
assert(json != NULL);
- qstring_append_chr(json, '\n');
- monitor_puts(&mon->common, qstring_get_str(json));
+ g_string_append_c(json, '\n');
+ monitor_puts(&mon->common, json->str);
- qobject_unref(json);
+ g_string_free(json, true);
}
/*
@@ -276,9 +275,15 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data)
mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1;
qemu_mutex_unlock(&mon->qmp_queue_lock);
if (req_obj->req) {
- QDict *qdict = qobject_to(QDict, req_obj->req);
- QObject *id = qdict ? qdict_get(qdict, "id") : NULL;
- trace_monitor_qmp_cmd_in_band(qobject_get_try_str(id) ?: "");
+ if (trace_event_get_state(TRACE_MONITOR_QMP_CMD_IN_BAND)) {
+ QDict *qdict = qobject_to(QDict, req_obj->req);
+ QObject *id = qdict ? qdict_get(qdict, "id") : NULL;
+ GString *id_json;
+
+ id_json = id ? qobject_to_json(id) : g_string_new(NULL);
+ trace_monitor_qmp_cmd_in_band(id_json->str);
+ g_string_free(id_json, true);
+ }
monitor_qmp_dispatch(mon, req_obj->req);
} else {
assert(req_obj->err);
@@ -308,26 +313,27 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data)
static void handle_qmp_command(void *opaque, QObject *req, Error *err)
{
MonitorQMP *mon = opaque;
- QObject *id = NULL;
- QDict *qdict;
+ QDict *qdict = qobject_to(QDict, req);
QMPRequest *req_obj;
assert(!req != !err);
- qdict = qobject_to(QDict, req);
- if (qdict) {
- id = qdict_get(qdict, "id");
- } /* else will fail qmp_dispatch() */
-
if (req && trace_event_get_state_backends(TRACE_HANDLE_QMP_COMMAND)) {
- QString *req_json = qobject_to_json(req);
- trace_handle_qmp_command(mon, qstring_get_str(req_json));
- qobject_unref(req_json);
+ GString *req_json = qobject_to_json(req);
+ trace_handle_qmp_command(mon, req_json->str);
+ g_string_free(req_json, true);
}
if (qdict && qmp_is_oob(qdict)) {
/* OOB commands are executed immediately */
- trace_monitor_qmp_cmd_out_of_band(qobject_get_try_str(id) ?: "");
+ if (trace_event_get_state(TRACE_MONITOR_QMP_CMD_OUT_OF_BAND)) {
+ QObject *id = qdict_get(qdict, "id");
+ GString *id_json;
+
+ id_json = id ? qobject_to_json(id) : g_string_new(NULL);
+ trace_monitor_qmp_cmd_out_of_band(id_json->str);
+ g_string_free(id_json, true);
+ }
monitor_qmp_dispatch(mon, req);
qobject_unref(req);
return;
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 04c5196e59..3484986d1c 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2829,7 +2829,7 @@
'cloop', 'compress', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps',
'gluster', 'host_cdrom', 'host_device', 'http', 'https', 'iscsi',
'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels',
- 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
+ 'preallocate', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
{ 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
'sheepdog',
'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
@@ -3099,6 +3099,23 @@
'luks': 'QCryptoBlockOptionsLUKS'} }
##
+# @BlockdevOptionsPreallocate:
+#
+# Filter driver intended to be inserted between format and protocol node
+# and do preallocation in protocol node on write.
+#
+# @prealloc-align: on preallocation, align file length to this number,
+# default 1048576 (1M)
+#
+# @prealloc-size: how much to preallocate, default 134217728 (128M)
+#
+# Since: 6.0
+##
+{ 'struct': 'BlockdevOptionsPreallocate',
+ 'base': 'BlockdevOptionsGenericFormat',
+ 'data': { '*prealloc-align': 'int', '*prealloc-size': 'int' } }
+
+##
# @BlockdevOptionsQcow2:
#
# Driver specific block device options for qcow2.
@@ -4006,6 +4023,7 @@
'null-co': 'BlockdevOptionsNull',
'nvme': 'BlockdevOptionsNVMe',
'parallels': 'BlockdevOptionsGenericFormat',
+ 'preallocate':'BlockdevOptionsPreallocate',
'qcow2': 'BlockdevOptionsQcow2',
'qcow': 'BlockdevOptionsQcow',
'qed': 'BlockdevOptionsGenericCOWFormat',
diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c
index b74aa4d44c..5506c933de 100644
--- a/qapi/string-output-visitor.c
+++ b/qapi/string-output-visitor.c
@@ -258,7 +258,7 @@ static bool print_type_number(Visitor *v, const char *name, double *obj,
Error **errp)
{
StringOutputVisitor *sov = to_sov(v);
- string_output_set(sov, g_strdup_printf("%f", *obj));
+ string_output_set(sov, g_strdup_printf("%.17g", *obj));
return true;
}
diff --git a/qemu-img.c b/qemu-img.c
index 8bdea40b58..8597d069af 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -33,7 +33,6 @@
#include "qapi/qobject-output-visitor.h"
#include "qapi/qmp/qjson.h"
#include "qapi/qmp/qdict.h"
-#include "qapi/qmp/qstring.h"
#include "qemu/cutils.h"
#include "qemu/config-file.h"
#include "qemu/option.h"
@@ -627,18 +626,18 @@ fail:
static void dump_json_image_check(ImageCheck *check, bool quiet)
{
- QString *str;
+ GString *str;
QObject *obj;
Visitor *v = qobject_output_visitor_new(&obj);
visit_type_ImageCheck(v, NULL, &check, &error_abort);
visit_complete(v, &obj);
- str = qobject_to_json_pretty(obj);
+ str = qobject_to_json_pretty(obj, true);
assert(str != NULL);
- qprintf(quiet, "%s\n", qstring_get_str(str));
+ qprintf(quiet, "%s\n", str->str);
qobject_unref(obj);
visit_free(v);
- qobject_unref(str);
+ g_string_free(str, true);
}
static void dump_human_image_check(ImageCheck *check, bool quiet)
@@ -1652,14 +1651,13 @@ static void do_dirty_bitmap_merge(const char *dst_node, const char *dst_name,
Error **errp)
{
BlockDirtyBitmapMergeSource *merge_src;
- BlockDirtyBitmapMergeSourceList *list;
+ BlockDirtyBitmapMergeSourceList *list = NULL;
merge_src = g_new0(BlockDirtyBitmapMergeSource, 1);
merge_src->type = QTYPE_QDICT;
merge_src->u.external.node = g_strdup(src_node);
merge_src->u.external.name = g_strdup(src_name);
- list = g_new0(BlockDirtyBitmapMergeSourceList, 1);
- list->value = merge_src;
+ QAPI_LIST_PREPEND(list, merge_src);
qmp_block_dirty_bitmap_merge(dst_node, dst_name, list, errp);
qapi_free_BlockDirtyBitmapMergeSourceList(list);
}
@@ -2790,34 +2788,34 @@ static void dump_snapshots(BlockDriverState *bs)
static void dump_json_image_info_list(ImageInfoList *list)
{
- QString *str;
+ GString *str;
QObject *obj;
Visitor *v = qobject_output_visitor_new(&obj);
visit_type_ImageInfoList(v, NULL, &list, &error_abort);
visit_complete(v, &obj);
- str = qobject_to_json_pretty(obj);
+ str = qobject_to_json_pretty(obj, true);
assert(str != NULL);
- printf("%s\n", qstring_get_str(str));
+ printf("%s\n", str->str);
qobject_unref(obj);
visit_free(v);
- qobject_unref(str);
+ g_string_free(str, true);
}
static void dump_json_image_info(ImageInfo *info)
{
- QString *str;
+ GString *str;
QObject *obj;
Visitor *v = qobject_output_visitor_new(&obj);
visit_type_ImageInfo(v, NULL, &info, &error_abort);
visit_complete(v, &obj);
- str = qobject_to_json_pretty(obj);
+ str = qobject_to_json_pretty(obj, true);
assert(str != NULL);
- printf("%s\n", qstring_get_str(str));
+ printf("%s\n", str->str);
qobject_unref(obj);
visit_free(v);
- qobject_unref(str);
+ g_string_free(str, true);
}
static void dump_human_image_info_list(ImageInfoList *list)
@@ -5237,18 +5235,18 @@ out:
static void dump_json_block_measure_info(BlockMeasureInfo *info)
{
- QString *str;
+ GString *str;
QObject *obj;
Visitor *v = qobject_output_visitor_new(&obj);
visit_type_BlockMeasureInfo(v, NULL, &info, &error_abort);
visit_complete(v, &obj);
- str = qobject_to_json_pretty(obj);
+ str = qobject_to_json_pretty(obj, true);
assert(str != NULL);
- printf("%s\n", qstring_get_str(str));
+ printf("%s\n", str->str);
qobject_unref(obj);
visit_free(v);
- qobject_unref(str);
+ g_string_free(str, true);
}
static int img_measure(int argc, char **argv)
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 4153f1c0b0..97611969cb 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -1698,13 +1698,42 @@ static const cmdinfo_t flush_cmd = {
.oneline = "flush all in-core file state to disk",
};
+static int truncate_f(BlockBackend *blk, int argc, char **argv);
+static const cmdinfo_t truncate_cmd = {
+ .name = "truncate",
+ .altname = "t",
+ .cfunc = truncate_f,
+ .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE,
+ .argmin = 1,
+ .argmax = 3,
+ .args = "[-m prealloc_mode] off",
+ .oneline = "truncates the current file at the given offset",
+};
+
static int truncate_f(BlockBackend *blk, int argc, char **argv)
{
Error *local_err = NULL;
int64_t offset;
- int ret;
+ int c, ret;
+ PreallocMode prealloc = PREALLOC_MODE_OFF;
- offset = cvtnum(argv[1]);
+ while ((c = getopt(argc, argv, "m:")) != -1) {
+ switch (c) {
+ case 'm':
+ prealloc = qapi_enum_parse(&PreallocMode_lookup, optarg,
+ PREALLOC_MODE__MAX, NULL);
+ if (prealloc == PREALLOC_MODE__MAX) {
+ error_report("Invalid preallocation mode '%s'", optarg);
+ return -EINVAL;
+ }
+ break;
+ default:
+ qemuio_command_usage(&truncate_cmd);
+ return -EINVAL;
+ }
+ }
+
+ offset = cvtnum(argv[optind]);
if (offset < 0) {
print_cvtnum_err(offset, argv[1]);
return offset;
@@ -1715,7 +1744,7 @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
* exact=true. It is better to err on the "emit more errors" side
* than to be overly permissive.
*/
- ret = blk_truncate(blk, offset, false, PREALLOC_MODE_OFF, 0, &local_err);
+ ret = blk_truncate(blk, offset, false, prealloc, 0, &local_err);
if (ret < 0) {
error_report_err(local_err);
return ret;
@@ -1724,17 +1753,6 @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
return 0;
}
-static const cmdinfo_t truncate_cmd = {
- .name = "truncate",
- .altname = "t",
- .cfunc = truncate_f,
- .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE,
- .argmin = 1,
- .argmax = 1,
- .args = "off",
- .oneline = "truncates the current file at the given offset",
-};
-
static int length_f(BlockBackend *blk, int argc, char **argv)
{
int64_t size;
diff --git a/qga/commands-posix-ssh.c b/qga/commands-posix-ssh.c
index 749167e82d..2dda136d64 100644
--- a/qga/commands-posix-ssh.c
+++ b/qga/commands-posix-ssh.c
@@ -293,17 +293,12 @@ qmp_guest_ssh_get_authorized_keys(const char *username, Error **errp)
ret = g_new0(GuestAuthorizedKeys, 1);
for (i = 0; authkeys[i] != NULL; i++) {
- strList *new;
-
g_strstrip(authkeys[i]);
if (!authkeys[i][0] || authkeys[i][0] == '#') {
continue;
}
- new = g_new0(strList, 1);
- new->value = g_strdup(authkeys[i]);
- new->next = ret->keys;
- ret->keys = new;
+ QAPI_LIST_PREPEND(ret->keys, g_strdup(authkeys[i]));
}
return g_steal_pointer(&ret);
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index c089e38120..849923b260 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -1036,7 +1036,6 @@ static void build_guest_fsinfo_for_real_device(char const *syspath,
{
GuestDiskAddress *disk;
GuestPCIAddress *pciaddr;
- GuestDiskAddressList *list = NULL;
bool has_hwinf;
#ifdef CONFIG_LIBUDEV
struct udev *udev = NULL;
@@ -1053,9 +1052,6 @@ static void build_guest_fsinfo_for_real_device(char const *syspath,
disk->pci_controller = pciaddr;
disk->bus_type = GUEST_DISK_BUS_TYPE_UNKNOWN;
- list = g_new0(GuestDiskAddressList, 1);
- list->value = disk;
-
#ifdef CONFIG_LIBUDEV
udev = udev_new();
udevice = udev_device_new_from_syspath(udev, syspath);
@@ -1089,10 +1085,9 @@ static void build_guest_fsinfo_for_real_device(char const *syspath,
}
if (has_hwinf || disk->has_dev || disk->has_serial) {
- list->next = fs->disk;
- fs->disk = list;
+ QAPI_LIST_PREPEND(fs->disk, disk);
} else {
- qapi_free_GuestDiskAddressList(list);
+ qapi_free_GuestDiskAddress(disk);
}
}
@@ -1288,7 +1283,6 @@ static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk)
disk->has_dependencies = true;
while ((dep = g_dir_read_name(dp_deps)) != NULL) {
g_autofree char *dep_dir = NULL;
- strList *dep_item = NULL;
char *dev_name;
/* Add dependent disks */
@@ -1296,10 +1290,7 @@ static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk)
dev_name = get_device_for_syspath(dep_dir);
if (dev_name != NULL) {
g_debug(" adding dependent device: %s", dev_name);
- dep_item = g_new0(strList, 1);
- dep_item->value = dev_name;
- dep_item->next = disk->dependencies;
- disk->dependencies = dep_item;
+ QAPI_LIST_PREPEND(disk->dependencies, dev_name);
}
}
g_dir_close(dp_deps);
@@ -1318,7 +1309,7 @@ static GuestDiskInfoList *get_disk_partitions(
const char *disk_name, const char *disk_dir,
const char *disk_dev)
{
- GuestDiskInfoList *item, *ret = list;
+ GuestDiskInfoList *ret = list;
struct dirent *de_disk;
DIR *dp_disk = NULL;
size_t len = strlen(disk_name);
@@ -1352,15 +1343,9 @@ static GuestDiskInfoList *get_disk_partitions(
partition->name = dev_name;
partition->partition = true;
/* Add parent disk as dependent for easier tracking of hierarchy */
- partition->dependencies = g_new0(strList, 1);
- partition->dependencies->value = g_strdup(disk_dev);
- partition->has_dependencies = true;
-
- item = g_new0(GuestDiskInfoList, 1);
- item->value = partition;
- item->next = ret;
- ret = item;
+ QAPI_LIST_PREPEND(partition->dependencies, g_strdup(disk_dev));
+ QAPI_LIST_PREPEND(ret, partition);
}
closedir(dp_disk);
@@ -1369,7 +1354,7 @@ static GuestDiskInfoList *get_disk_partitions(
GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
{
- GuestDiskInfoList *item, *ret = NULL;
+ GuestDiskInfoList *ret = NULL;
GuestDiskInfo *disk;
DIR *dp = NULL;
struct dirent *de = NULL;
@@ -1415,10 +1400,7 @@ GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
disk->partition = false;
disk->alias = get_alias_for_syspath(disk_dir);
disk->has_alias = (disk->alias != NULL);
- item = g_new0(GuestDiskInfoList, 1);
- item->value = disk;
- item->next = ret;
- ret = item;
+ QAPI_LIST_PREPEND(ret, disk);
/* Get address for non-virtual devices */
bool is_virtual = is_disk_virtual(disk_dir, &local_err);
@@ -1495,7 +1477,7 @@ GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
{
FsMountList mounts;
struct FsMount *mount;
- GuestFilesystemInfoList *new, *ret = NULL;
+ GuestFilesystemInfoList *ret = NULL;
Error *local_err = NULL;
QTAILQ_INIT(&mounts);
@@ -1508,10 +1490,7 @@ GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
QTAILQ_FOREACH(mount, &mounts, next) {
g_debug("Building guest fsinfo for '%s'", mount->dirname);
- new = g_malloc0(sizeof(*ret));
- new->value = build_guest_fsinfo(mount, &local_err);
- new->next = ret;
- ret = new;
+ QAPI_LIST_PREPEND(ret, build_guest_fsinfo(mount, &local_err));
if (local_err) {
error_propagate(errp, local_err);
qapi_free_GuestFilesystemInfoList(ret);
@@ -1777,7 +1756,6 @@ GuestFilesystemTrimResponse *
qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
{
GuestFilesystemTrimResponse *response;
- GuestFilesystemTrimResultList *list;
GuestFilesystemTrimResult *result;
int ret = 0;
FsMountList mounts;
@@ -1801,10 +1779,7 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
result = g_malloc0(sizeof(*result));
result->path = g_strdup(mount->dirname);
- list = g_malloc0(sizeof(*list));
- list->value = result;
- list->next = response->paths;
- response->paths = list;
+ QAPI_LIST_PREPEND(response->paths, result);
fd = qemu_open_old(mount->dirname, O_RDONLY);
if (fd == -1) {
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index ba1fd07d06..684639bd13 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -874,7 +874,7 @@ err_close:
static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
{
Error *local_err = NULL;
- GuestDiskAddressList *list = NULL, *cur_item = NULL;
+ GuestDiskAddressList *list = NULL;
GuestDiskAddress *disk = NULL;
int i;
HANDLE vol_h;
@@ -926,10 +926,8 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
error_free(local_err);
goto out;
}
- list = g_malloc0(sizeof(*list));
- list->value = disk;
+ QAPI_LIST_PREPEND(list, disk);
disk = NULL;
- list->next = NULL;
goto out;
} else {
error_setg_win32(errp, GetLastError(),
@@ -960,11 +958,8 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
error_propagate(errp, local_err);
goto out;
}
- cur_item = g_malloc0(sizeof(*list));
- cur_item->value = disk;
+ QAPI_LIST_PREPEND(list, disk);
disk = NULL;
- cur_item->next = list;
- list = cur_item;
}
@@ -982,7 +977,7 @@ out:
GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
{
ERRP_GUARD();
- GuestDiskInfoList *new = NULL, *ret = NULL;
+ GuestDiskInfoList *ret = NULL;
HDEVINFO dev_info;
SP_DEVICE_INTERFACE_DATA dev_iface_data;
int i;
@@ -1064,10 +1059,7 @@ GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
disk->has_address = true;
}
- new = g_malloc0(sizeof(GuestDiskInfoList));
- new->value = disk;
- new->next = ret;
- ret = new;
+ QAPI_LIST_PREPEND(ret, disk);
}
SetupDiDestroyDeviceInfoList(dev_info);
@@ -1165,7 +1157,7 @@ free:
GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
{
HANDLE vol_h;
- GuestFilesystemInfoList *new, *ret = NULL;
+ GuestFilesystemInfoList *ret = NULL;
char guid[256];
vol_h = FindFirstVolume(guid, sizeof(guid));
@@ -1183,10 +1175,7 @@ GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
error_free(local_err);
continue;
}
- new = g_malloc(sizeof(*ret));
- new->value = info;
- new->next = ret;
- ret = new;
+ QAPI_LIST_PREPEND(ret, info);
} while (FindNextVolume(vol_h, guid, sizeof(guid)));
if (GetLastError() != ERROR_NO_MORE_FILES) {
@@ -1330,7 +1319,6 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
do {
GuestFilesystemTrimResult *res;
- GuestFilesystemTrimResultList *list;
PWCHAR uc_path;
DWORD char_count = 0;
char *path, *out;
@@ -1369,11 +1357,7 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
res->path = path;
- list = g_new0(GuestFilesystemTrimResultList, 1);
- list->value = res;
- list->next = resp->paths;
-
- resp->paths = list;
+ QAPI_LIST_PREPEND(resp->paths, res);
memset(argv, 0, sizeof(argv));
argv[0] = (gchar *)"defrag.exe";
diff --git a/qga/commands.c b/qga/commands.c
index 3dcd5fbe5c..e866fc7081 100644
--- a/qga/commands.c
+++ b/qga/commands.c
@@ -66,17 +66,13 @@ static void qmp_command_info(const QmpCommand *cmd, void *opaque)
{
GuestAgentInfo *info = opaque;
GuestAgentCommandInfo *cmd_info;
- GuestAgentCommandInfoList *cmd_info_list;
cmd_info = g_new0(GuestAgentCommandInfo, 1);
cmd_info->name = g_strdup(qmp_command_name(cmd));
cmd_info->enabled = qmp_command_is_enabled(cmd);
cmd_info->success_response = qmp_has_success_response(cmd);
- cmd_info_list = g_new0(GuestAgentCommandInfoList, 1);
- cmd_info_list->value = cmd_info;
- cmd_info_list->next = info->supported_commands;
- info->supported_commands = cmd_info_list;
+ QAPI_LIST_PREPEND(info->supported_commands, cmd_info);
}
struct GuestAgentInfo *qmp_guest_info(Error **errp)
diff --git a/qga/main.c b/qga/main.c
index dea6a3aa64..e7f8f3b161 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -22,7 +22,6 @@
#include "qapi/qmp/json-parser.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qjson.h"
-#include "qapi/qmp/qstring.h"
#include "guest-agent-core.h"
#include "qga-qapi-init-commands.h"
#include "qapi/qmp/qerror.h"
@@ -528,8 +527,7 @@ fail:
static int send_response(GAState *s, const QDict *rsp)
{
- const char *buf;
- QString *payload_qstr, *response_qstr;
+ GString *response;
GIOStatus status;
g_assert(s->channel);
@@ -538,25 +536,19 @@ static int send_response(GAState *s, const QDict *rsp)
return 0;
}
- payload_qstr = qobject_to_json(QOBJECT(rsp));
- if (!payload_qstr) {
+ response = qobject_to_json(QOBJECT(rsp));
+ if (!response) {
return -EINVAL;
}
if (s->delimit_response) {
s->delimit_response = false;
- response_qstr = qstring_new();
- qstring_append_chr(response_qstr, QGA_SENTINEL_BYTE);
- qstring_append(response_qstr, qstring_get_str(payload_qstr));
- qobject_unref(payload_qstr);
- } else {
- response_qstr = payload_qstr;
+ g_string_prepend_c(response, QGA_SENTINEL_BYTE);
}
- qstring_append_chr(response_qstr, '\n');
- buf = qstring_get_str(response_qstr);
- status = ga_channel_write_all(s->channel, buf, strlen(buf));
- qobject_unref(response_qstr);
+ g_string_append_c(response, '\n');
+ status = ga_channel_write_all(s->channel, response->str, response->len);
+ g_string_free(response, true);
if (status != G_IO_STATUS_NORMAL) {
return -EIO;
}
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
index c0f521b56b..d351039b10 100644
--- a/qobject/json-parser.c
+++ b/qobject/json-parser.c
@@ -130,7 +130,7 @@ static int cvt4hex(const char *s)
static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
{
const char *ptr = token->str;
- QString *str;
+ GString *str;
char quote;
const char *beg;
int cp, trailing;
@@ -140,7 +140,7 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
assert(*ptr == '"' || *ptr == '\'');
quote = *ptr++;
- str = qstring_new();
+ str = g_string_new(NULL);
while (*ptr != quote) {
assert(*ptr);
@@ -149,31 +149,31 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
beg = ptr++;
switch (*ptr++) {
case '"':
- qstring_append_chr(str, '"');
+ g_string_append_c(str, '"');
break;
case '\'':
- qstring_append_chr(str, '\'');
+ g_string_append_c(str, '\'');
break;
case '\\':
- qstring_append_chr(str, '\\');
+ g_string_append_c(str, '\\');
break;
case '/':
- qstring_append_chr(str, '/');
+ g_string_append_c(str, '/');
break;
case 'b':
- qstring_append_chr(str, '\b');
+ g_string_append_c(str, '\b');
break;
case 'f':
- qstring_append_chr(str, '\f');
+ g_string_append_c(str, '\f');
break;
case 'n':
- qstring_append_chr(str, '\n');
+ g_string_append_c(str, '\n');
break;
case 'r':
- qstring_append_chr(str, '\r');
+ g_string_append_c(str, '\r');
break;
case 't':
- qstring_append_chr(str, '\t');
+ g_string_append_c(str, '\t');
break;
case 'u':
cp = cvt4hex(ptr);
@@ -200,7 +200,7 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
(int)(ptr - beg), beg);
goto out;
}
- qstring_append(str, utf8_buf);
+ g_string_append(str, utf8_buf);
break;
default:
parse_error(ctxt, token, "invalid escape sequence in string");
@@ -225,14 +225,14 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
ptr = end;
len = mod_utf8_encode(utf8_buf, sizeof(utf8_buf), cp);
assert(len >= 0);
- qstring_append(str, utf8_buf);
+ g_string_append(str, utf8_buf);
}
}
- return str;
+ return qstring_from_gstring(str);
out:
- qobject_unref(str);
+ g_string_free(str, true);
return NULL;
}
diff --git a/qobject/json-writer.c b/qobject/json-writer.c
new file mode 100644
index 0000000000..309a31d57a
--- /dev/null
+++ b/qobject/json-writer.c
@@ -0,0 +1,247 @@
+/*
+ * JSON Writer
+ *
+ * Copyright IBM, Corp. 2009
+ * Copyright (c) 2010-2020 Red Hat Inc.
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ * Markus Armbruster <armbru@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/qmp/json-writer.h"
+#include "qemu/unicode.h"
+
+struct JSONWriter {
+ bool pretty;
+ bool need_comma;
+ GString *contents;
+ GByteArray *container_is_array;
+};
+
+JSONWriter *json_writer_new(bool pretty)
+{
+ JSONWriter *writer = g_new(JSONWriter, 1);
+
+ writer->pretty = pretty;
+ writer->need_comma = false;
+ writer->contents = g_string_new(NULL);
+ writer->container_is_array = g_byte_array_new();
+ return writer;
+}
+
+const char *json_writer_get(JSONWriter *writer)
+{
+ g_assert(!writer->container_is_array->len);
+ return writer->contents->str;
+}
+
+GString *json_writer_get_and_free(JSONWriter *writer)
+{
+ GString *contents = writer->contents;
+
+ writer->contents = NULL;
+ g_byte_array_free(writer->container_is_array, true);
+ g_free(writer);
+ return contents;
+}
+
+void json_writer_free(JSONWriter *writer)
+{
+ if (writer) {
+ g_string_free(json_writer_get_and_free(writer), true);
+ }
+}
+
+static void enter_container(JSONWriter *writer, bool is_array)
+{
+ unsigned depth = writer->container_is_array->len;
+
+ g_byte_array_set_size(writer->container_is_array, depth + 1);
+ writer->container_is_array->data[depth] = is_array;
+ writer->need_comma = false;
+}
+
+static void leave_container(JSONWriter *writer, bool is_array)
+{
+ unsigned depth = writer->container_is_array->len;
+
+ assert(depth);
+ assert(writer->container_is_array->data[depth - 1] == is_array);
+ g_byte_array_set_size(writer->container_is_array, depth - 1);
+ writer->need_comma = true;
+}
+
+static bool in_object(JSONWriter *writer)
+{
+ unsigned depth = writer->container_is_array->len;
+
+ return depth && !writer->container_is_array->data[depth - 1];
+}
+
+static void pretty_newline(JSONWriter *writer)
+{
+ if (writer->pretty) {
+ g_string_append_printf(writer->contents, "\n%*s",
+ writer->container_is_array->len * 4, "");
+ }
+}
+
+static void pretty_newline_or_space(JSONWriter *writer)
+{
+ if (writer->pretty) {
+ g_string_append_printf(writer->contents, "\n%*s",
+ writer->container_is_array->len * 4, "");
+ } else {
+ g_string_append_c(writer->contents, ' ');
+ }
+}
+
+static void quoted_str(JSONWriter *writer, const char *str)
+{
+ const char *ptr;
+ char *end;
+ int cp;
+
+ g_string_append_c(writer->contents, '"');
+
+ for (ptr = str; *ptr; ptr = end) {
+ cp = mod_utf8_codepoint(ptr, 6, &end);
+ switch (cp) {
+ case '\"':
+ g_string_append(writer->contents, "\\\"");
+ break;
+ case '\\':
+ g_string_append(writer->contents, "\\\\");
+ break;
+ case '\b':
+ g_string_append(writer->contents, "\\b");
+ break;
+ case '\f':
+ g_string_append(writer->contents, "\\f");
+ break;
+ case '\n':
+ g_string_append(writer->contents, "\\n");
+ break;
+ case '\r':
+ g_string_append(writer->contents, "\\r");
+ break;
+ case '\t':
+ g_string_append(writer->contents, "\\t");
+ break;
+ default:
+ if (cp < 0) {
+ cp = 0xFFFD; /* replacement character */
+ }
+ if (cp > 0xFFFF) {
+ /* beyond BMP; need a surrogate pair */
+ g_string_append_printf(writer->contents, "\\u%04X\\u%04X",
+ 0xD800 + ((cp - 0x10000) >> 10),
+ 0xDC00 + ((cp - 0x10000) & 0x3FF));
+ } else if (cp < 0x20 || cp >= 0x7F) {
+ g_string_append_printf(writer->contents, "\\u%04X", cp);
+ } else {
+ g_string_append_c(writer->contents, cp);
+ }
+ }
+ };
+
+ g_string_append_c(writer->contents, '"');
+}
+
+static void maybe_comma_name(JSONWriter *writer, const char *name)
+{
+ if (writer->need_comma) {
+ g_string_append_c(writer->contents, ',');
+ pretty_newline_or_space(writer);
+ } else {
+ if (writer->contents->len) {
+ pretty_newline(writer);
+ }
+ writer->need_comma = true;
+ }
+
+ if (in_object(writer)) {
+ quoted_str(writer, name);
+ g_string_append(writer->contents, ": ");
+ }
+}
+
+void json_writer_start_object(JSONWriter *writer, const char *name)
+{
+ maybe_comma_name(writer, name);
+ g_string_append_c(writer->contents, '{');
+ enter_container(writer, false);
+}
+
+void json_writer_end_object(JSONWriter *writer)
+{
+ leave_container(writer, false);
+ pretty_newline(writer);
+ g_string_append_c(writer->contents, '}');
+}
+
+void json_writer_start_array(JSONWriter *writer, const char *name)
+{
+ maybe_comma_name(writer, name);
+ g_string_append_c(writer->contents, '[');
+ enter_container(writer, true);
+}
+
+void json_writer_end_array(JSONWriter *writer)
+{
+ leave_container(writer, true);
+ pretty_newline(writer);
+ g_string_append_c(writer->contents, ']');
+}
+
+void json_writer_bool(JSONWriter *writer, const char *name, bool val)
+{
+ maybe_comma_name(writer, name);
+ g_string_append(writer->contents, val ? "true" : "false");
+}
+
+void json_writer_null(JSONWriter *writer, const char *name)
+{
+ maybe_comma_name(writer, name);
+ g_string_append(writer->contents, "null");
+}
+
+void json_writer_int64(JSONWriter *writer, const char *name, int64_t val)
+{
+ maybe_comma_name(writer, name);
+ g_string_append_printf(writer->contents, "%" PRId64, val);
+}
+
+void json_writer_uint64(JSONWriter *writer, const char *name, uint64_t val)
+{
+ maybe_comma_name(writer, name);
+ g_string_append_printf(writer->contents, "%" PRIu64, val);
+}
+
+void json_writer_double(JSONWriter *writer, const char *name, double val)
+{
+ maybe_comma_name(writer, name);
+
+ /*
+ * FIXME: g_string_append_printf() is locale dependent; but JSON
+ * requires numbers to be formatted as if in the C locale.
+ * Dependence on C locale is a pervasive issue in QEMU.
+ */
+ /*
+ * FIXME: This risks printing Inf or NaN, which are not valid
+ * JSON values.
+ */
+ g_string_append_printf(writer->contents, "%.17g", val);
+}
+
+void json_writer_str(JSONWriter *writer, const char *name, const char *str)
+{
+ maybe_comma_name(writer, name);
+ quoted_str(writer, str);
+}
diff --git a/qobject/meson.build b/qobject/meson.build
index bb63c06b63..4683a852a2 100644
--- a/qobject/meson.build
+++ b/qobject/meson.build
@@ -1,3 +1,4 @@
-util_ss.add(files('qnull.c', 'qnum.c', 'qstring.c', 'qdict.c', 'qlist.c', 'qbool.c',
- 'qlit.c', 'qjson.c', 'qobject.c', 'json-lexer.c', 'json-streamer.c', 'json-parser.c',
+util_ss.add(files('qnull.c', 'qnum.c', 'qstring.c', 'qdict.c',
+ 'qlist.c', 'qbool.c', 'qlit.c', 'qjson.c', 'qobject.c',
+ 'json-writer.c', 'json-lexer.c', 'json-streamer.c', 'json-parser.c',
'block-qdict.c'))
diff --git a/qobject/qbool.c b/qobject/qbool.c
index 06dfc43498..16a600abb9 100644
--- a/qobject/qbool.c
+++ b/qobject/qbool.c
@@ -13,6 +13,7 @@
#include "qemu/osdep.h"
#include "qapi/qmp/qbool.h"
+#include "qobject-internal.h"
/**
* qbool_from_bool(): Create a new QBool from a bool
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 1079bd3f6f..d84443391e 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -16,6 +16,7 @@
#include "qapi/qmp/qbool.h"
#include "qapi/qmp/qnull.h"
#include "qapi/qmp/qstring.h"
+#include "qobject-internal.h"
/**
* qdict_new(): Create a new QDict
diff --git a/qobject/qjson.c b/qobject/qjson.c
index f1f2c69704..bcc376e626 100644
--- a/qobject/qjson.c
+++ b/qobject/qjson.c
@@ -14,13 +14,13 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qapi/qmp/json-parser.h"
+#include "qapi/qmp/json-writer.h"
#include "qapi/qmp/qjson.h"
#include "qapi/qmp/qbool.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qnum.h"
#include "qapi/qmp/qstring.h"
-#include "qemu/unicode.h"
typedef struct JSONParsingState
{
@@ -149,144 +149,69 @@ QDict *qdict_from_jsonf_nofail(const char *string, ...)
return qdict;
}
-static void to_json(const QObject *obj, QString *str, int pretty, int indent);
-
-static void json_pretty_newline(QString *str, bool pretty, int indent)
-{
- int i;
-
- if (pretty) {
- qstring_append(str, "\n");
- for (i = 0; i < indent; i++) {
- qstring_append(str, " ");
- }
- }
-}
-
-static void to_json(const QObject *obj, QString *str, int pretty, int indent)
+static void to_json(JSONWriter *writer, const char *name,
+ const QObject *obj)
{
switch (qobject_type(obj)) {
case QTYPE_QNULL:
- qstring_append(str, "null");
+ json_writer_null(writer, name);
break;
case QTYPE_QNUM: {
QNum *val = qobject_to(QNum, obj);
- char *buffer = qnum_to_string(val);
- qstring_append(str, buffer);
- g_free(buffer);
+
+ switch (val->kind) {
+ case QNUM_I64:
+ json_writer_int64(writer, name, val->u.i64);
+ break;
+ case QNUM_U64:
+ json_writer_uint64(writer, name, val->u.u64);
+ break;
+ case QNUM_DOUBLE:
+ json_writer_double(writer, name, val->u.dbl);
+ break;
+ default:
+ abort();
+ }
break;
}
case QTYPE_QSTRING: {
QString *val = qobject_to(QString, obj);
- const char *ptr;
- int cp;
- char buf[16];
- char *end;
-
- ptr = qstring_get_str(val);
- qstring_append(str, "\"");
-
- for (; *ptr; ptr = end) {
- cp = mod_utf8_codepoint(ptr, 6, &end);
- switch (cp) {
- case '\"':
- qstring_append(str, "\\\"");
- break;
- case '\\':
- qstring_append(str, "\\\\");
- break;
- case '\b':
- qstring_append(str, "\\b");
- break;
- case '\f':
- qstring_append(str, "\\f");
- break;
- case '\n':
- qstring_append(str, "\\n");
- break;
- case '\r':
- qstring_append(str, "\\r");
- break;
- case '\t':
- qstring_append(str, "\\t");
- break;
- default:
- if (cp < 0) {
- cp = 0xFFFD; /* replacement character */
- }
- if (cp > 0xFFFF) {
- /* beyond BMP; need a surrogate pair */
- snprintf(buf, sizeof(buf), "\\u%04X\\u%04X",
- 0xD800 + ((cp - 0x10000) >> 10),
- 0xDC00 + ((cp - 0x10000) & 0x3FF));
- } else if (cp < 0x20 || cp >= 0x7F) {
- snprintf(buf, sizeof(buf), "\\u%04X", cp);
- } else {
- buf[0] = cp;
- buf[1] = 0;
- }
- qstring_append(str, buf);
- }
- };
-
- qstring_append(str, "\"");
+
+ json_writer_str(writer, name, qstring_get_str(val));
break;
}
case QTYPE_QDICT: {
QDict *val = qobject_to(QDict, obj);
- const char *comma = pretty ? "," : ", ";
- const char *sep = "";
const QDictEntry *entry;
- QString *qkey;
- qstring_append(str, "{");
+ json_writer_start_object(writer, name);
for (entry = qdict_first(val);
entry;
entry = qdict_next(val, entry)) {
- qstring_append(str, sep);
- json_pretty_newline(str, pretty, indent + 1);
-
- qkey = qstring_from_str(qdict_entry_key(entry));
- to_json(QOBJECT(qkey), str, pretty, indent + 1);
- qobject_unref(qkey);
-
- qstring_append(str, ": ");
- to_json(qdict_entry_value(entry), str, pretty, indent + 1);
- sep = comma;
+ to_json(writer, qdict_entry_key(entry), qdict_entry_value(entry));
}
- json_pretty_newline(str, pretty, indent);
- qstring_append(str, "}");
+ json_writer_end_object(writer);
break;
}
case QTYPE_QLIST: {
QList *val = qobject_to(QList, obj);
- const char *comma = pretty ? "," : ", ";
- const char *sep = "";
QListEntry *entry;
- qstring_append(str, "[");
+ json_writer_start_array(writer, name);
QLIST_FOREACH_ENTRY(val, entry) {
- qstring_append(str, sep);
- json_pretty_newline(str, pretty, indent + 1);
- to_json(qlist_entry_obj(entry), str, pretty, indent + 1);
- sep = comma;
+ to_json(writer, NULL, qlist_entry_obj(entry));
}
- json_pretty_newline(str, pretty, indent);
- qstring_append(str, "]");
+ json_writer_end_array(writer);
break;
}
case QTYPE_QBOOL: {
QBool *val = qobject_to(QBool, obj);
- if (qbool_get_bool(val)) {
- qstring_append(str, "true");
- } else {
- qstring_append(str, "false");
- }
+ json_writer_bool(writer, name, qbool_get_bool(val));
break;
}
default:
@@ -294,20 +219,15 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
}
}
-QString *qobject_to_json(const QObject *obj)
+GString *qobject_to_json_pretty(const QObject *obj, bool pretty)
{
- QString *str = qstring_new();
-
- to_json(obj, str, 0, 0);
+ JSONWriter *writer = json_writer_new(pretty);
- return str;
+ to_json(writer, NULL, obj);
+ return json_writer_get_and_free(writer);
}
-QString *qobject_to_json_pretty(const QObject *obj)
+GString *qobject_to_json(const QObject *obj)
{
- QString *str = qstring_new();
-
- to_json(obj, str, 1, 0);
-
- return str;
+ return qobject_to_json_pretty(obj, false);
}
diff --git a/qobject/qlist.c b/qobject/qlist.c
index 1be95367d1..60562a1f52 100644
--- a/qobject/qlist.c
+++ b/qobject/qlist.c
@@ -17,6 +17,7 @@
#include "qapi/qmp/qnum.h"
#include "qapi/qmp/qstring.h"
#include "qemu/queue.h"
+#include "qobject-internal.h"
/**
* qlist_new(): Create a new QList
diff --git a/qobject/qnull.c b/qobject/qnull.c
index 00870a1824..b26b368219 100644
--- a/qobject/qnull.c
+++ b/qobject/qnull.c
@@ -12,6 +12,7 @@
#include "qemu/osdep.h"
#include "qapi/qmp/qnull.h"
+#include "qobject-internal.h"
QNull qnull_ = {
.base = {
diff --git a/qobject/qnum.c b/qobject/qnum.c
index 7012fc57f2..5dd66938dd 100644
--- a/qobject/qnum.c
+++ b/qobject/qnum.c
@@ -14,6 +14,7 @@
#include "qemu/osdep.h"
#include "qapi/qmp/qnum.h"
+#include "qobject-internal.h"
/**
* qnum_from_int(): Create a new QNum from an int64_t
@@ -161,37 +162,14 @@ double qnum_get_double(QNum *qn)
char *qnum_to_string(QNum *qn)
{
- char *buffer;
- int len;
-
switch (qn->kind) {
case QNUM_I64:
return g_strdup_printf("%" PRId64, qn->u.i64);
case QNUM_U64:
return g_strdup_printf("%" PRIu64, qn->u.u64);
case QNUM_DOUBLE:
- /* FIXME: snprintf() is locale dependent; but JSON requires
- * numbers to be formatted as if in the C locale. Dependence
- * on C locale is a pervasive issue in QEMU. */
- /* FIXME: This risks printing Inf or NaN, which are not valid
- * JSON values. */
- /* FIXME: the default precision of 6 for %f often causes
- * rounding errors; we should be using DBL_DECIMAL_DIG (17),
- * and only rounding to a shorter number if the result would
- * still produce the same floating point value. */
- buffer = g_strdup_printf("%f" , qn->u.dbl);
- len = strlen(buffer);
- while (len > 0 && buffer[len - 1] == '0') {
- len--;
- }
-
- if (len && buffer[len - 1] == '.') {
- buffer[len - 1] = 0;
- } else {
- buffer[len] = 0;
- }
-
- return buffer;
+ /* 17 digits suffice for IEEE double */
+ return g_strdup_printf("%.17g", qn->u.dbl);
}
assert(0);
diff --git a/qobject/qobject-internal.h b/qobject/qobject-internal.h
new file mode 100644
index 0000000000..b310c8e1b5
--- /dev/null
+++ b/qobject/qobject-internal.h
@@ -0,0 +1,39 @@
+/*
+ * QObject internals
+ *
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1
+ * or later. See the COPYING.LIB file in the top-level directory.
+ */
+
+#ifndef QOBJECT_INTERNAL_H
+#define QOBJECT_INTERNAL_H
+
+#include "qapi/qmp/qobject.h"
+
+static inline void qobject_init(QObject *obj, QType type)
+{
+ assert(QTYPE_NONE < type && type < QTYPE__MAX);
+ obj->base.refcnt = 1;
+ obj->base.type = type;
+}
+
+void qbool_destroy_obj(QObject *obj);
+bool qbool_is_equal(const QObject *x, const QObject *y);
+
+void qdict_destroy_obj(QObject *obj);
+bool qdict_is_equal(const QObject *x, const QObject *y);
+
+void qlist_destroy_obj(QObject *obj);
+bool qlist_is_equal(const QObject *x, const QObject *y);
+
+bool qnull_is_equal(const QObject *x, const QObject *y);
+
+void qnum_destroy_obj(QObject *obj);
+bool qnum_is_equal(const QObject *x, const QObject *y);
+
+void qstring_destroy_obj(QObject *obj);
+bool qstring_is_equal(const QObject *x, const QObject *y);
+
+#endif
diff --git a/qobject/qobject.c b/qobject/qobject.c
index 878dd76e79..d7077b8f2a 100644
--- a/qobject/qobject.c
+++ b/qobject/qobject.c
@@ -14,6 +14,7 @@
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qstring.h"
+#include "qobject-internal.h"
QEMU_BUILD_BUG_MSG(
offsetof(QNull, base) != 0 ||
diff --git a/qobject/qstring.c b/qobject/qstring.c
index b66a2c35f2..b4613899b9 100644
--- a/qobject/qstring.c
+++ b/qobject/qstring.c
@@ -12,6 +12,7 @@
#include "qemu/osdep.h"
#include "qapi/qmp/qstring.h"
+#include "qobject-internal.h"
/**
* qstring_new(): Create a new empty QString
@@ -24,14 +25,6 @@ QString *qstring_new(void)
}
/**
- * qstring_get_length(): Get the length of a QString
- */
-size_t qstring_get_length(const QString *qstring)
-{
- return qstring->length;
-}
-
-/**
* qstring_from_substr(): Create a new QString from a C string substring
*
* Return string reference
@@ -41,18 +34,9 @@ QString *qstring_from_substr(const char *str, size_t start, size_t end)
QString *qstring;
assert(start <= end);
-
qstring = g_malloc(sizeof(*qstring));
qobject_init(QOBJECT(qstring), QTYPE_QSTRING);
-
- qstring->length = end - start;
- qstring->capacity = qstring->length;
-
- assert(qstring->capacity < SIZE_MAX);
- qstring->string = g_malloc(qstring->capacity + 1);
- memcpy(qstring->string, str + start, qstring->length);
- qstring->string[qstring->length] = 0;
-
+ qstring->string = g_strndup(str + start, end - start);
return qstring;
}
@@ -66,47 +50,22 @@ QString *qstring_from_str(const char *str)
return qstring_from_substr(str, 0, strlen(str));
}
-static void capacity_increase(QString *qstring, size_t len)
-{
- if (qstring->capacity < (qstring->length + len)) {
- assert(len <= SIZE_MAX - qstring->capacity);
- qstring->capacity += len;
- assert(qstring->capacity <= SIZE_MAX / 2);
- qstring->capacity *= 2; /* use exponential growth */
-
- qstring->string = g_realloc(qstring->string, qstring->capacity + 1);
- }
-}
-
-/* qstring_append(): Append a C string to a QString
+/**
+ * qstring_from_gstring(): Convert a GString to a QString
+ *
+ * Return strong reference.
*/
-void qstring_append(QString *qstring, const char *str)
-{
- size_t len = strlen(str);
-
- capacity_increase(qstring, len);
- memcpy(qstring->string + qstring->length, str, len);
- qstring->length += len;
- qstring->string[qstring->length] = 0;
-}
-void qstring_append_int(QString *qstring, int64_t value)
+QString *qstring_from_gstring(GString *gstr)
{
- char num[32];
+ QString *qstring;
- snprintf(num, sizeof(num), "%" PRId64, value);
- qstring_append(qstring, num);
+ qstring = g_malloc(sizeof(*qstring));
+ qobject_init(QOBJECT(qstring), QTYPE_QSTRING);
+ qstring->string = g_string_free(gstr, false);
+ return qstring;
}
-/**
- * qstring_append_chr(): Append a C char to a QString
- */
-void qstring_append_chr(QString *qstring, int c)
-{
- capacity_increase(qstring, 1);
- qstring->string[qstring->length++] = c;
- qstring->string[qstring->length] = 0;
-}
/**
* qstring_get_str(): Return a pointer to the stored string
@@ -120,27 +79,6 @@ const char *qstring_get_str(const QString *qstring)
}
/**
- * qstring_get_try_str(): Return a pointer to the stored string
- *
- * NOTE: will return NULL if qstring is not provided.
- */
-const char *qstring_get_try_str(const QString *qstring)
-{
- return qstring ? qstring_get_str(qstring) : NULL;
-}
-
-/**
- * qobject_get_try_str(): Return a pointer to the corresponding string
- *
- * NOTE: the string will only be returned if the object is valid, and
- * its type is QString, otherwise NULL is returned.
- */
-const char *qobject_get_try_str(const QObject *qstring)
-{
- return qstring_get_try_str(qobject_to(QString, qstring));
-}
-
-/**
* qstring_is_equal(): Test whether the two QStrings are equal
*/
bool qstring_is_equal(const QObject *x, const QObject *y)
@@ -150,32 +88,15 @@ bool qstring_is_equal(const QObject *x, const QObject *y)
}
/**
- * qstring_free(): Free the memory allocated by a QString object
- *
- * Return: if @return_str, return the underlying string, to be
- * g_free(), otherwise NULL is returned.
- */
-char *qstring_free(QString *qstring, bool return_str)
-{
- char *rv = NULL;
-
- if (return_str) {
- rv = qstring->string;
- } else {
- g_free(qstring->string);
- }
-
- g_free(qstring);
-
- return rv;
-}
-
-/**
* qstring_destroy_obj(): Free all memory allocated by a QString
* object
*/
void qstring_destroy_obj(QObject *obj)
{
+ QString *qs;
+
assert(obj != NULL);
- qstring_free(qobject_to(QString, obj), FALSE);
+ qs = qobject_to(QString, obj);
+ g_free((char *)qs->string);
+ g_free(qs);
}
diff --git a/qom/object.c b/qom/object.c
index f2ae6e6b2a..5cd43fe366 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1415,15 +1415,18 @@ char *object_property_get_str(Object *obj, const char *name,
Error **errp)
{
QObject *ret = object_property_get_qobject(obj, name, errp);
+ QString *qstring;
char *retval;
if (!ret) {
return NULL;
}
-
- retval = g_strdup(qobject_get_try_str(ret));
- if (!retval) {
+ qstring = qobject_to(QString, ret);
+ if (!qstring) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
+ retval = NULL;
+ } else {
+ retval = g_strdup(qstring_get_str(qstring));
}
qobject_unref(ret);
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index ed896fe764..1e9ad6f08a 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -5,7 +5,6 @@
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qmp/qjson.h"
-#include "qapi/qmp/qstring.h"
#include "qapi/qobject-input-visitor.h"
#include "qom/object_interfaces.h"
#include "qemu/help_option.h"
@@ -207,7 +206,8 @@ char *object_property_help(const char *name, const char *type,
g_string_append(str, description);
}
if (defval) {
- g_autofree char *def_json = qstring_free(qobject_to_json(defval), TRUE);
+ g_autofree char *def_json = g_string_free(qobject_to_json(defval),
+ true);
g_string_append_printf(str, " (default: %s)", def_json);
}
diff --git a/qom/qom-hmp-cmds.c b/qom/qom-hmp-cmds.c
index 8861a109d5..453fbfeabc 100644
--- a/qom/qom-hmp-cmds.c
+++ b/qom/qom-hmp-cmds.c
@@ -13,7 +13,6 @@
#include "qapi/qapi-commands-qom.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qjson.h"
-#include "qapi/qmp/qstring.h"
#include "qom/object.h"
void hmp_qom_list(Monitor *mon, const QDict *qdict)
@@ -78,9 +77,9 @@ void hmp_qom_get(Monitor *mon, const QDict *qdict)
QObject *obj = qmp_qom_get(path, property, &err);
if (err == NULL) {
- QString *str = qobject_to_json_pretty(obj);
- monitor_printf(mon, "%s\n", qstring_get_str(str));
- qobject_unref(str);
+ GString *str = qobject_to_json_pretty(obj, true);
+ monitor_printf(mon, "%s\n", str->str);
+ g_string_free(str, true);
}
qobject_unref(obj);
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
index 2dd233f293..b40ac39f30 100644
--- a/qom/qom-qmp-cmds.c
+++ b/qom/qom-qmp-cmds.c
@@ -46,14 +46,12 @@ ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
object_property_iter_init(&iter, obj);
while ((prop = object_property_iter_next(&iter))) {
- ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry));
+ ObjectPropertyInfo *value = g_malloc0(sizeof(ObjectPropertyInfo));
- entry->value = g_malloc0(sizeof(ObjectPropertyInfo));
- entry->next = props;
- props = entry;
+ QAPI_LIST_PREPEND(props, value);
- entry->value->name = g_strdup(prop->name);
- entry->value->type = g_strdup(prop->type);
+ value->name = g_strdup(prop->name);
+ value->type = g_strdup(prop->type);
}
return props;
@@ -90,7 +88,7 @@ QObject *qmp_qom_get(const char *path, const char *property, Error **errp)
static void qom_list_types_tramp(ObjectClass *klass, void *data)
{
- ObjectTypeInfoList *e, **pret = data;
+ ObjectTypeInfoList **pret = data;
ObjectTypeInfo *info;
ObjectClass *parent = object_class_get_parent(klass);
@@ -102,10 +100,7 @@ static void qom_list_types_tramp(ObjectClass *klass, void *data)
info->parent = g_strdup(object_class_get_name(parent));
}
- e = g_malloc0(sizeof(*e));
- e->value = info;
- e->next = *pret;
- *pret = e;
+ QAPI_LIST_PREPEND(*pret, info);
}
ObjectTypeInfoList *qmp_qom_list_types(bool has_implements,
@@ -150,7 +145,6 @@ ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
object_property_iter_init(&iter, obj);
while ((prop = object_property_iter_next(&iter))) {
ObjectPropertyInfo *info;
- ObjectPropertyInfoList *entry;
/* Skip Object and DeviceState properties */
if (strcmp(prop->name, "type") == 0 ||
@@ -176,10 +170,7 @@ ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
info->default_value = qobject_ref(prop->defval);
info->has_default_value = !!info->default_value;
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = prop_list;
- prop_list = entry;
+ QAPI_LIST_PREPEND(prop_list, info);
}
object_unref(obj);
@@ -217,7 +208,6 @@ ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
}
while ((prop = object_property_iter_next(&iter))) {
ObjectPropertyInfo *info;
- ObjectPropertyInfoList *entry;
info = g_malloc0(sizeof(*info));
info->name = g_strdup(prop->name);
@@ -225,10 +215,7 @@ ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
info->has_description = !!prop->description;
info->description = g_strdup(prop->description);
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = prop_list;
- prop_list = entry;
+ QAPI_LIST_PREPEND(prop_list, info);
}
object_unref(obj);
diff --git a/scripts/simplebench/bench-example.py b/scripts/simplebench/bench-example.py
index c642a5b891..d9c7f7bc17 100644
--- a/scripts/simplebench/bench-example.py
+++ b/scripts/simplebench/bench-example.py
@@ -19,6 +19,7 @@
#
import simplebench
+from results_to_text import results_to_text
from bench_block_job import bench_block_copy, drv_file, drv_nbd
@@ -77,4 +78,4 @@ test_envs = [
]
result = simplebench.bench(bench_func, test_envs, test_cases, count=3)
-print(simplebench.ascii(result))
+print(results_to_text(result))
diff --git a/scripts/simplebench/bench_prealloc.py b/scripts/simplebench/bench_prealloc.py
new file mode 100755
index 0000000000..85f588c597
--- /dev/null
+++ b/scripts/simplebench/bench_prealloc.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python3
+#
+# Benchmark preallocate filter
+#
+# Copyright (c) 2020 Virtuozzo International GmbH.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+
+import sys
+import os
+import subprocess
+import re
+import json
+
+import simplebench
+from results_to_text import results_to_text
+
+
+def qemu_img_bench(args):
+ p = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ universal_newlines=True)
+
+ if p.returncode == 0:
+ try:
+ m = re.search(r'Run completed in (\d+.\d+) seconds.', p.stdout)
+ return {'seconds': float(m.group(1))}
+ except Exception:
+ return {'error': f'failed to parse qemu-img output: {p.stdout}'}
+ else:
+ return {'error': f'qemu-img failed: {p.returncode}: {p.stdout}'}
+
+
+def bench_func(env, case):
+ fname = f"{case['dir']}/prealloc-test.qcow2"
+ try:
+ os.remove(fname)
+ except OSError:
+ pass
+
+ subprocess.run([env['qemu-img-binary'], 'create', '-f', 'qcow2', fname,
+ '16G'], stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL, check=True)
+
+ args = [env['qemu-img-binary'], 'bench', '-c', str(case['count']),
+ '-d', '64', '-s', case['block-size'], '-t', 'none', '-n', '-w']
+ if env['prealloc']:
+ args += ['--image-opts',
+ 'driver=qcow2,file.driver=preallocate,file.file.driver=file,'
+ f'file.file.filename={fname}']
+ else:
+ args += ['-f', 'qcow2', fname]
+
+ return qemu_img_bench(args)
+
+
+def auto_count_bench_func(env, case):
+ case['count'] = 100
+ while True:
+ res = bench_func(env, case)
+ if 'error' in res:
+ return res
+
+ if res['seconds'] >= 1:
+ break
+
+ case['count'] *= 10
+
+ if res['seconds'] < 5:
+ case['count'] = round(case['count'] * 5 / res['seconds'])
+ res = bench_func(env, case)
+ if 'error' in res:
+ return res
+
+ res['iops'] = case['count'] / res['seconds']
+ return res
+
+
+if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ print(f'USAGE: {sys.argv[0]} <qemu-img binary> '
+ 'DISK_NAME:DIR_PATH ...')
+ exit(1)
+
+ qemu_img = sys.argv[1]
+
+ envs = [
+ {
+ 'id': 'no-prealloc',
+ 'qemu-img-binary': qemu_img,
+ 'prealloc': False
+ },
+ {
+ 'id': 'prealloc',
+ 'qemu-img-binary': qemu_img,
+ 'prealloc': True
+ }
+ ]
+
+ aligned_cases = []
+ unaligned_cases = []
+
+ for disk in sys.argv[2:]:
+ name, path = disk.split(':')
+ aligned_cases.append({
+ 'id': f'{name}, aligned sequential 16k',
+ 'block-size': '16k',
+ 'dir': path
+ })
+ unaligned_cases.append({
+ 'id': f'{name}, unaligned sequential 64k',
+ 'block-size': '16k',
+ 'dir': path
+ })
+
+ result = simplebench.bench(auto_count_bench_func, envs,
+ aligned_cases + unaligned_cases, count=5)
+ print(results_to_text(result))
+ with open('results.json', 'w') as f:
+ json.dump(result, f, indent=4)
diff --git a/scripts/simplebench/bench_write_req.py b/scripts/simplebench/bench_write_req.py
index ca1178fd68..da601ea2fe 100755
--- a/scripts/simplebench/bench_write_req.py
+++ b/scripts/simplebench/bench_write_req.py
@@ -26,6 +26,7 @@ import sys
import os
import subprocess
import simplebench
+from results_to_text import results_to_text
def bench_func(env, case):
@@ -167,4 +168,4 @@ if __name__ == '__main__':
result = simplebench.bench(bench_func, test_envs, test_cases, count=3,
initial_run=False)
- print(simplebench.ascii(result))
+ print(results_to_text(result))
diff --git a/scripts/simplebench/results_to_text.py b/scripts/simplebench/results_to_text.py
new file mode 100755
index 0000000000..d561e5e2db
--- /dev/null
+++ b/scripts/simplebench/results_to_text.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python3
+#
+# Simple benchmarking framework
+#
+# Copyright (c) 2019 Virtuozzo International GmbH.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import math
+import tabulate
+
+# We want leading whitespace for difference row cells (see below)
+tabulate.PRESERVE_WHITESPACE = True
+
+
+def format_value(x, stdev):
+ stdev_pr = stdev / x * 100
+ if stdev_pr < 1.5:
+ # don't care too much
+ return f'{x:.2g}'
+ else:
+ return f'{x:.2g} ± {math.ceil(stdev_pr)}%'
+
+
+def result_to_text(result):
+ """Return text representation of bench_one() returned dict."""
+ if 'average' in result:
+ s = format_value(result['average'], result['stdev'])
+ if 'n-failed' in result:
+ s += '\n({} failed)'.format(result['n-failed'])
+ return s
+ else:
+ return 'FAILED'
+
+
+def results_dimension(results):
+ dim = None
+ for case in results['cases']:
+ for env in results['envs']:
+ res = results['tab'][case['id']][env['id']]
+ if dim is None:
+ dim = res['dimension']
+ else:
+ assert dim == res['dimension']
+
+ assert dim in ('iops', 'seconds')
+
+ return dim
+
+
+def results_to_text(results):
+ """Return text representation of bench() returned dict."""
+ n_columns = len(results['envs'])
+ named_columns = n_columns > 2
+ dim = results_dimension(results)
+ tab = []
+
+ if named_columns:
+ # Environment columns are named A, B, ...
+ tab.append([''] + [chr(ord('A') + i) for i in range(n_columns)])
+
+ tab.append([''] + [c['id'] for c in results['envs']])
+
+ for case in results['cases']:
+ row = [case['id']]
+ case_results = results['tab'][case['id']]
+ for env in results['envs']:
+ res = case_results[env['id']]
+ row.append(result_to_text(res))
+ tab.append(row)
+
+ # Add row of difference between columns. For each column starting from
+ # B we calculate difference with all previous columns.
+ row = ['', ''] # case name and first column
+ for i in range(1, n_columns):
+ cell = ''
+ env = results['envs'][i]
+ res = case_results[env['id']]
+
+ if 'average' not in res:
+ # Failed result
+ row.append(cell)
+ continue
+
+ for j in range(0, i):
+ env_j = results['envs'][j]
+ res_j = case_results[env_j['id']]
+ cell += ' '
+
+ if 'average' not in res_j:
+ # Failed result
+ cell += '--'
+ continue
+
+ col_j = tab[0][j + 1] if named_columns else ''
+ diff_pr = round((res['average'] - res_j['average']) /
+ res_j['average'] * 100)
+ cell += f' {col_j}{diff_pr:+}%'
+ row.append(cell)
+ tab.append(row)
+
+ return f'All results are in {dim}\n\n' + tabulate.tabulate(tab)
+
+
+if __name__ == '__main__':
+ import sys
+ import json
+
+ if len(sys.argv) < 2:
+ print(f'USAGE: {sys.argv[0]} results.json')
+ exit(1)
+
+ with open(sys.argv[1]) as f:
+ print(results_to_text(json.load(f)))
diff --git a/scripts/simplebench/simplebench.py b/scripts/simplebench/simplebench.py
index 59e7314ff6..f61513af90 100644
--- a/scripts/simplebench/simplebench.py
+++ b/scripts/simplebench/simplebench.py
@@ -18,15 +18,20 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+import statistics
+
def bench_one(test_func, test_env, test_case, count=5, initial_run=True):
"""Benchmark one test-case
test_func -- benchmarking function with prototype
test_func(env, case), which takes test_env and test_case
- arguments and returns {'seconds': int} (which is benchmark
- result) on success and {'error': str} on error. Returned
- dict may contain any other additional fields.
+ arguments and on success returns dict with 'seconds' or
+ 'iops' (or both) fields, specifying the benchmark result.
+ If both 'iops' and 'seconds' provided, the 'iops' is
+ considered the main, and 'seconds' is just an additional
+ info. On failure test_func should return {'error': str}.
+ Returned dict may contain any other additional fields.
test_env -- test environment - opaque first argument for test_func
test_case -- test case - opaque second argument for test_func
count -- how many times to call test_func, to calculate average
@@ -34,9 +39,10 @@ def bench_one(test_func, test_env, test_case, count=5, initial_run=True):
Returns dict with the following fields:
'runs': list of test_func results
- 'average': average seconds per run (exists only if at least one run
- succeeded)
- 'delta': maximum delta between test_func result and the average
+ 'dimension': dimension of results, may be 'seconds' or 'iops'
+ 'average': average value (iops or seconds) per run (exists only if at
+ least one run succeeded)
+ 'stdev': standard deviation of results
(exists only if at least one run succeeded)
'n-failed': number of failed runs (exists only if at least one run
failed)
@@ -54,29 +60,25 @@ def bench_one(test_func, test_env, test_case, count=5, initial_run=True):
result = {'runs': runs}
- successed = [r for r in runs if ('seconds' in r)]
- if successed:
- avg = sum(r['seconds'] for r in successed) / len(successed)
- result['average'] = avg
- result['delta'] = max(abs(r['seconds'] - avg) for r in successed)
-
- if len(successed) < count:
- result['n-failed'] = count - len(successed)
+ succeeded = [r for r in runs if ('seconds' in r or 'iops' in r)]
+ if succeeded:
+ if 'iops' in succeeded[0]:
+ assert all('iops' in r for r in succeeded)
+ dim = 'iops'
+ else:
+ assert all('seconds' in r for r in succeeded)
+ assert all('iops' not in r for r in succeeded)
+ dim = 'seconds'
+ result['dimension'] = dim
+ result['average'] = statistics.mean(r[dim] for r in succeeded)
+ result['stdev'] = statistics.stdev(r[dim] for r in succeeded)
+
+ if len(succeeded) < count:
+ result['n-failed'] = count - len(succeeded)
return result
-def ascii_one(result):
- """Return ASCII representation of bench_one() returned dict."""
- if 'average' in result:
- s = '{:.2f} +- {:.2f}'.format(result['average'], result['delta'])
- if 'n-failed' in result:
- s += '\n({} failed)'.format(result['n-failed'])
- return s
- else:
- return 'FAILED'
-
-
def bench(test_func, test_envs, test_cases, *args, **vargs):
"""Fill benchmark table
@@ -112,17 +114,3 @@ def bench(test_func, test_envs, test_cases, *args, **vargs):
print('Done')
return results
-
-
-def ascii(results):
- """Return ASCII representation of bench() returned dict."""
- from tabulate import tabulate
-
- tab = [[""] + [c['id'] for c in results['envs']]]
- for case in results['cases']:
- row = [case['id']]
- for env in results['envs']:
- row.append(ascii_one(results['tab'][case['id']][env['id']]))
- tab.append(row)
-
- return tabulate(tab)
diff --git a/storage-daemon/qapi/qapi-schema.json b/storage-daemon/qapi/qapi-schema.json
index c6ad5ae1e3..28117c3aac 100644
--- a/storage-daemon/qapi/qapi-schema.json
+++ b/storage-daemon/qapi/qapi-schema.json
@@ -15,6 +15,9 @@
{ 'include': '../../qapi/pragma.json' }
+##
+# = Block devices
+##
{ 'include': '../../qapi/block-core.json' }
{ 'include': '../../qapi/block-export.json' }
{ 'include': '../../qapi/char.json' }
diff --git a/target/alpha/machine.c b/target/alpha/machine.c
index 9d20169d4f..2b7c8148ff 100644
--- a/target/alpha/machine.c
+++ b/target/alpha/machine.c
@@ -11,7 +11,7 @@ static int get_fpcr(QEMUFile *f, void *opaque, size_t size,
}
static int put_fpcr(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
CPUAlphaState *env = opaque;
qemu_put_be64(f, cpu_alpha_load_fpcr(env));
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 7b8bcd6903..2d0d4cd1e1 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8283,7 +8283,6 @@ static void arm_cpu_add_definition(gpointer data, gpointer user_data)
{
ObjectClass *oc = data;
CpuDefinitionInfoList **cpu_list = user_data;
- CpuDefinitionInfoList *entry;
CpuDefinitionInfo *info;
const char *typename;
@@ -8293,10 +8292,7 @@ static void arm_cpu_add_definition(gpointer data, gpointer user_data)
strlen(typename) - strlen("-" TYPE_ARM_CPU));
info->q_typename = g_strdup(typename);
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = *cpu_list;
- *cpu_list = entry;
+ QAPI_LIST_PREPEND(*cpu_list, info);
}
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
diff --git a/target/arm/machine.c b/target/arm/machine.c
index c5a2114f51..581852bc53 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -27,7 +27,7 @@ static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
}
static int put_fpscr(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
ARMCPU *cpu = opaque;
CPUARMState *env = &cpu->env;
@@ -573,7 +573,7 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
}
static int put_cpsr(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
ARMCPU *cpu = opaque;
CPUARMState *env = &cpu->env;
@@ -608,7 +608,7 @@ static int get_power(QEMUFile *f, void *opaque, size_t size,
}
static int put_power(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
ARMCPU *cpu = opaque;
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
index 169d8a64b6..198b14e95e 100644
--- a/target/arm/monitor.c
+++ b/target/arm/monitor.c
@@ -42,15 +42,6 @@ static GICCapability *gic_cap_new(int version)
return cap;
}
-static GICCapabilityList *gic_cap_list_add(GICCapabilityList *head,
- GICCapability *cap)
-{
- GICCapabilityList *item = g_new0(GICCapabilityList, 1);
- item->value = cap;
- item->next = head;
- return item;
-}
-
static inline void gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3)
{
#ifdef CONFIG_KVM
@@ -84,8 +75,8 @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
gic_cap_kvm_probe(v2, v3);
- head = gic_cap_list_add(head, v2);
- head = gic_cap_list_add(head, v3);
+ QAPI_LIST_PREPEND(head, v2);
+ QAPI_LIST_PREPEND(head, v3);
return head;
}
diff --git a/target/avr/machine.c b/target/avr/machine.c
index e315442787..de264f57c3 100644
--- a/target/avr/machine.c
+++ b/target/avr/machine.c
@@ -34,7 +34,7 @@ static int get_sreg(QEMUFile *f, void *opaque, size_t size,
}
static int put_sreg(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
CPUAVRState *env = opaque;
uint8_t sreg = cpu_get_sreg(env);
@@ -61,7 +61,7 @@ static int get_segment(QEMUFile *f, void *opaque, size_t size,
}
static int put_segment(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
uint32_t *ramp = opaque;
uint8_t temp = *ramp >> 16;
diff --git a/target/hppa/machine.c b/target/hppa/machine.c
index b60b654efb..905991d7f9 100644
--- a/target/hppa/machine.c
+++ b/target/hppa/machine.c
@@ -52,7 +52,7 @@ static int get_psw(QEMUFile *f, void *opaque, size_t size,
}
static int put_psw(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
CPUHPPAState *env = opaque;
qemu_put_betr(f, cpu_hppa_get_psw(env));
@@ -93,7 +93,7 @@ static int get_tlb(QEMUFile *f, void *opaque, size_t size,
}
static int put_tlb(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
hppa_tlb_entry *ent = opaque;
uint32_t val = 0;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 0d20e156f2..35459a38bb 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -5014,7 +5014,6 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data)
ObjectClass *oc = data;
X86CPUClass *cc = X86_CPU_CLASS(oc);
CpuDefinitionInfoList **cpu_list = user_data;
- CpuDefinitionInfoList *entry;
CpuDefinitionInfo *info;
info = g_malloc0(sizeof(*info));
@@ -5039,10 +5038,7 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data)
info->has_alias_of = !!info->alias_of;
}
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = *cpu_list;
- *cpu_list = entry;
+ QAPI_LIST_PREPEND(*cpu_list, info);
}
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 750f75c257..11db2f3c8d 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -1778,9 +1778,12 @@ static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, int op1,
} else {
tcg_gen_deposit_tl(s->T1, s->T0, s->T1, 16, 16);
}
- /* FALLTHRU */
-#ifdef TARGET_X86_64
+ /*
+ * If TARGET_X86_64 defined then fall through into MO_32 case,
+ * otherwise fall through default case.
+ */
case MO_32:
+#ifdef TARGET_X86_64
/* Concatenate the two 32-bit values and use a 64-bit shift. */
tcg_gen_subi_tl(s->tmp0, count, 1);
if (is_right) {
diff --git a/target/microblaze/machine.c b/target/microblaze/machine.c
index c2074bbdfe..d24def3992 100644
--- a/target/microblaze/machine.c
+++ b/target/microblaze/machine.c
@@ -46,7 +46,7 @@ static int get_msr(QEMUFile *f, void *opaque, size_t size,
}
static int put_msr(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
CPUMBState *env = container_of(opaque, CPUMBState, msr);
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index aadc6f8e74..b2cd69ff7f 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -543,7 +543,6 @@ static void mips_cpu_add_definition(gpointer data, gpointer user_data)
{
ObjectClass *oc = data;
CpuDefinitionInfoList **cpu_list = user_data;
- CpuDefinitionInfoList *entry;
CpuDefinitionInfo *info;
const char *typename;
@@ -553,10 +552,7 @@ static void mips_cpu_add_definition(gpointer data, gpointer user_data)
strlen(typename) - strlen("-" TYPE_MIPS_CPU));
info->q_typename = g_strdup(typename);
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = *cpu_list;
- *cpu_list = entry;
+ QAPI_LIST_PREPEND(*cpu_list, info);
}
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 3ac21d0e9c..4cbc31c3e8 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -844,6 +844,7 @@ struct CPUMIPSState {
#define CP0C0_MT 7 /* 9..7 */
#define CP0C0_VI 3
#define CP0C0_K0 0 /* 2..0 */
+#define CP0C0_AR_LENGTH 3
int32_t CP0_Config1;
#define CP0C1_M 31
#define CP0C1_MMU 25 /* 30..25 */
diff --git a/target/mips/machine.c b/target/mips/machine.c
index 5b23e3e912..77afe654e9 100644
--- a/target/mips/machine.c
+++ b/target/mips/machine.c
@@ -31,7 +31,7 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size,
}
static int put_fpr(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
int i;
fpr_t *v = pv;
@@ -156,7 +156,7 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size,
}
static int put_tlb(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
r4k_tlb_t *v = pv;
diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c
index b92985d99b..6239725c4f 100644
--- a/target/openrisc/machine.c
+++ b/target/openrisc/machine.c
@@ -55,7 +55,7 @@ static int get_sr(QEMUFile *f, void *opaque, size_t size,
}
static int put_sr(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
CPUOpenRISCState *env = opaque;
qemu_put_be32(f, cpu_get_sr(env));
diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index d9d911b9b1..283db1d28a 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -134,7 +134,7 @@ static int get_avr(QEMUFile *f, void *pv, size_t size,
}
static int put_avr(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
ppc_avr_t *v = pv;
@@ -166,7 +166,7 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size,
}
static int put_fpr(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
ppc_vsr_t *v = pv;
@@ -197,7 +197,7 @@ static int get_vsr(QEMUFile *f, void *pv, size_t size,
}
static int put_vsr(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
ppc_vsr_t *v = pv;
@@ -455,7 +455,7 @@ static int get_vscr(QEMUFile *f, void *opaque, size_t size,
}
static int put_vscr(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
PowerPCCPU *cpu = opaque;
qemu_put_be32(f, helper_mfvscr(&cpu->env));
@@ -580,7 +580,7 @@ static int get_slbe(QEMUFile *f, void *pv, size_t size,
}
static int put_slbe(QEMUFile *f, void *pv, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
ppc_slb_t *v = pv;
diff --git a/target/ppc/translate_init.c.inc b/target/ppc/translate_init.c.inc
index a4d0038828..3c05a17343 100644
--- a/target/ppc/translate_init.c.inc
+++ b/target/ppc/translate_init.c.inc
@@ -10566,7 +10566,6 @@ static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
ObjectClass *oc = data;
CpuDefinitionInfoList **first = user_data;
const char *typename;
- CpuDefinitionInfoList *entry;
CpuDefinitionInfo *info;
typename = object_class_get_name(oc);
@@ -10574,10 +10573,7 @@ static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
info->name = g_strndup(typename,
strlen(typename) - strlen(POWERPC_CPU_TYPE_SUFFIX));
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = *first;
- *first = entry;
+ QAPI_LIST_PREPEND(*first, info);
}
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
@@ -10593,7 +10589,6 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) {
PowerPCCPUAlias *alias = &ppc_cpu_aliases[i];
ObjectClass *oc;
- CpuDefinitionInfoList *entry;
CpuDefinitionInfo *info;
oc = ppc_cpu_class_by_name(alias->model);
@@ -10605,10 +10600,7 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
info->name = g_strdup(alias->alias);
info->q_typename = g_strdup(object_class_get_name(oc));
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = cpu_list;
- cpu_list = entry;
+ QAPI_LIST_PREPEND(cpu_list, info);
}
return cpu_list;
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 6a0264fc6b..254cd83f8b 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -108,6 +108,15 @@ const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
}
}
+bool riscv_cpu_is_32bit(CPURISCVState *env)
+{
+ if (env->misa & RV64) {
+ return false;
+ }
+
+ return true;
+}
+
static void set_misa(CPURISCVState *env, target_ulong misa)
{
env->misa_mask = env->misa = misa;
@@ -142,29 +151,50 @@ static void riscv_any_cpu_init(Object *obj)
set_priv_version(env, PRIV_VERSION_1_11_0);
}
-static void riscv_base_cpu_init(Object *obj)
+#if defined(TARGET_RISCV64)
+static void rv64_base_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
/* We set this in the realise function */
- set_misa(env, 0);
+ set_misa(env, RV64);
}
-static void rvxx_sifive_u_cpu_init(Object *obj)
+static void rv64_sifive_u_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
- set_misa(env, RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+ set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
}
-static void rvxx_sifive_e_cpu_init(Object *obj)
+static void rv64_sifive_e_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
- set_misa(env, RVXLEN | RVI | RVM | RVA | RVC | RVU);
+ set_misa(env, RV64 | RVI | RVM | RVA | RVC | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
}
+#else
+static void rv32_base_cpu_init(Object *obj)
+{
+ CPURISCVState *env = &RISCV_CPU(obj)->env;
+ /* We set this in the realise function */
+ set_misa(env, RV32);
+}
-#if defined(TARGET_RISCV32)
+static void rv32_sifive_u_cpu_init(Object *obj)
+{
+ CPURISCVState *env = &RISCV_CPU(obj)->env;
+ set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+ set_priv_version(env, PRIV_VERSION_1_10_0);
+}
+
+static void rv32_sifive_e_cpu_init(Object *obj)
+{
+ CPURISCVState *env = &RISCV_CPU(obj)->env;
+ set_misa(env, RV32 | RVI | RVM | RVA | RVC | RVU);
+ set_priv_version(env, PRIV_VERSION_1_10_0);
+ qdev_prop_set_bit(DEVICE(obj), "mmu", false);
+}
static void rv32_ibex_cpu_init(Object *obj)
{
@@ -182,7 +212,6 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj)
set_resetvec(env, DEFAULT_RSTVEC);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
}
-
#endif
static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model)
@@ -218,10 +247,10 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
#ifndef CONFIG_USER_ONLY
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", (target_ulong)env->mstatus);
-#ifdef TARGET_RISCV32
- qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ",
- (target_ulong)(env->mstatus >> 32));
-#endif
+ if (riscv_cpu_is_32bit(env)) {
+ qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ",
+ (target_ulong)(env->mstatus >> 32));
+ }
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ",
@@ -334,11 +363,12 @@ static void riscv_cpu_reset(DeviceState *dev)
static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
{
-#if defined(TARGET_RISCV32)
- info->print_insn = print_insn_riscv32;
-#elif defined(TARGET_RISCV64)
- info->print_insn = print_insn_riscv64;
-#endif
+ RISCVCPU *cpu = RISCV_CPU(s);
+ if (riscv_cpu_is_32bit(&cpu->env)) {
+ info->print_insn = print_insn_riscv32;
+ } else {
+ info->print_insn = print_insn_riscv64;
+ }
}
static void riscv_cpu_realize(DeviceState *dev, Error **errp)
@@ -349,7 +379,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
int priv_version = PRIV_VERSION_1_11_0;
int vext_version = VEXT_VERSION_0_07_1;
- target_ulong target_misa = 0;
+ target_ulong target_misa = env->misa;
Error *local_err = NULL;
cpu_exec_realizefn(cs, &local_err);
@@ -384,8 +414,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
set_resetvec(env, cpu->cfg.resetvec);
- /* If misa isn't set (rv32 and rv64 machines) set it here */
- if (!env->misa) {
+ /* If only XLEN is set for misa, then set misa from properties */
+ if (env->misa == RV32 || env->misa == RV64) {
/* Do some ISA extension error checking */
if (cpu->cfg.ext_i && cpu->cfg.ext_e) {
error_setg(errp,
@@ -481,7 +511,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
set_vext_version(env, vext_version);
}
- set_misa(env, RVXLEN | target_misa);
+ set_misa(env, target_misa);
}
riscv_cpu_register_gdb_regs_for_features(cs);
@@ -632,15 +662,15 @@ static const TypeInfo riscv_cpu_type_infos[] = {
},
DEFINE_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init),
#if defined(TARGET_RISCV32)
- DEFINE_CPU(TYPE_RISCV_CPU_BASE32, riscv_base_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_BASE32, rv32_base_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_IBEX, rv32_ibex_cpu_init),
- DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rvxx_sifive_e_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32_sifive_e_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32_imafcu_nommu_cpu_init),
- DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rvxx_sifive_u_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32_sifive_u_cpu_init),
#elif defined(TARGET_RISCV64)
- DEFINE_CPU(TYPE_RISCV_CPU_BASE64, riscv_base_cpu_init),
- DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rvxx_sifive_e_cpu_init),
- DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rvxx_sifive_u_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_BASE64, rv64_base_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64_sifive_e_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64_sifive_u_cpu_init),
#endif
};
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index c0a326c843..6339e84819 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -44,6 +44,12 @@
#define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34")
#define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54")
+#if defined(TARGET_RISCV32)
+# define TYPE_RISCV_CPU_BASE TYPE_RISCV_CPU_BASE32
+#elif defined(TARGET_RISCV64)
+# define TYPE_RISCV_CPU_BASE TYPE_RISCV_CPU_BASE64
+#endif
+
#define RV32 ((target_ulong)1 << (TARGET_LONG_BITS - 2))
#define RV64 ((target_ulong)2 << (TARGET_LONG_BITS - 2))
@@ -378,6 +384,8 @@ FIELD(TB_FLAGS, VILL, 8, 1)
/* Is a Hypervisor instruction load/store allowed? */
FIELD(TB_FLAGS, HLSX, 9, 1)
+bool riscv_cpu_is_32bit(CPURISCVState *env);
+
/*
* A simplification for VLMAX
* = (1 << LMUL) * VLEN / (8 * (1 << SEW))
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 24b24c69c5..b41e8836c3 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -379,8 +379,8 @@
#define MSTATUS_MXR 0x00080000
#define MSTATUS_VM 0x1F000000 /* until: priv-1.9.1 */
#define MSTATUS_TVM 0x00100000 /* since: priv-1.10 */
-#define MSTATUS_TW 0x20000000 /* since: priv-1.10 */
-#define MSTATUS_TSR 0x40000000 /* since: priv-1.10 */
+#define MSTATUS_TW 0x00200000 /* since: priv-1.10 */
+#define MSTATUS_TSR 0x00400000 /* since: priv-1.10 */
#define MSTATUS_GVA 0x4000000000ULL
#define MSTATUS_MPV 0x8000000000ULL
@@ -437,9 +437,7 @@
#define HSTATUS_VGEIN 0x0003F000
#define HSTATUS_VTVM 0x00100000
#define HSTATUS_VTSR 0x00400000
-#if defined(TARGET_RISCV64)
-#define HSTATUS_VSXL 0x300000000
-#endif
+#define HSTATUS_VSXL 0x300000000
#define HSTATUS32_WPRI 0xFF8FF87E
#define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index a2787b1d48..a2afb95fa1 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -367,7 +367,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
vm = get_field(env->hgatp, HGATP_MODE);
widened = 2;
}
- sum = get_field(env->mstatus, MSTATUS_SUM);
+ /* status.SUM will be ignored if execute on background */
+ sum = get_field(env->mstatus, MSTATUS_SUM) || use_background;
switch (vm) {
case VM_1_10_SV32:
levels = 2; ptidxbits = 10; ptesize = 4; break;
@@ -446,11 +447,13 @@ restart:
return TRANSLATE_PMP_FAIL;
}
-#if defined(TARGET_RISCV32)
- target_ulong pte = address_space_ldl(cs->as, pte_addr, attrs, &res);
-#elif defined(TARGET_RISCV64)
- target_ulong pte = address_space_ldq(cs->as, pte_addr, attrs, &res);
-#endif
+ target_ulong pte;
+ if (riscv_cpu_is_32bit(env)) {
+ pte = address_space_ldl(cs->as, pte_addr, attrs, &res);
+ } else {
+ pte = address_space_ldq(cs->as, pte_addr, attrs, &res);
+ }
+
if (res != MEMTX_OK) {
return TRANSLATE_FAIL;
}
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 93263f8e06..10ab82ed1f 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -102,44 +102,65 @@ static int ctr(CPURISCVState *env, int csrno)
return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
}
break;
-#if defined(TARGET_RISCV32)
- case CSR_CYCLEH:
- if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
- get_field(env->mcounteren, HCOUNTEREN_CY)) {
- return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
- }
- break;
- case CSR_TIMEH:
- if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
- get_field(env->mcounteren, HCOUNTEREN_TM)) {
- return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
- }
- break;
- case CSR_INSTRETH:
- if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
- get_field(env->mcounteren, HCOUNTEREN_IR)) {
- return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
- }
- break;
- case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
- if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3H)) &&
- get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3H))) {
- return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ if (riscv_cpu_is_32bit(env)) {
+ switch (csrno) {
+ case CSR_CYCLEH:
+ if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
+ get_field(env->mcounteren, HCOUNTEREN_CY)) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+ case CSR_TIMEH:
+ if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
+ get_field(env->mcounteren, HCOUNTEREN_TM)) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+ case CSR_INSTRETH:
+ if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
+ get_field(env->mcounteren, HCOUNTEREN_IR)) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+ case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
+ if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3H)) &&
+ get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3H))) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
}
- break;
-#endif
}
}
#endif
return 0;
}
+static int ctr32(CPURISCVState *env, int csrno)
+{
+ if (!riscv_cpu_is_32bit(env)) {
+ return -RISCV_EXCP_ILLEGAL_INST;
+ }
+
+ return ctr(env, csrno);
+}
+
#if !defined(CONFIG_USER_ONLY)
static int any(CPURISCVState *env, int csrno)
{
return 0;
}
+static int any32(CPURISCVState *env, int csrno)
+{
+ if (!riscv_cpu_is_32bit(env)) {
+ return -RISCV_EXCP_ILLEGAL_INST;
+ }
+
+ return any(env, csrno);
+
+}
+
static int smode(CPURISCVState *env, int csrno)
{
return -!riscv_has_ext(env, RVS);
@@ -161,6 +182,16 @@ static int hmode(CPURISCVState *env, int csrno)
return -RISCV_EXCP_ILLEGAL_INST;
}
+static int hmode32(CPURISCVState *env, int csrno)
+{
+ if (!riscv_cpu_is_32bit(env)) {
+ return 0;
+ }
+
+ return hmode(env, csrno);
+
+}
+
static int pmp(CPURISCVState *env, int csrno)
{
return -!riscv_feature(env, RISCV_FEATURE_PMP);
@@ -310,7 +341,6 @@ static int read_instret(CPURISCVState *env, int csrno, target_ulong *val)
return 0;
}
-#if defined(TARGET_RISCV32)
static int read_instreth(CPURISCVState *env, int csrno, target_ulong *val)
{
#if !defined(CONFIG_USER_ONLY)
@@ -324,7 +354,6 @@ static int read_instreth(CPURISCVState *env, int csrno, target_ulong *val)
#endif
return 0;
}
-#endif /* TARGET_RISCV32 */
#if defined(CONFIG_USER_ONLY)
static int read_time(CPURISCVState *env, int csrno, target_ulong *val)
@@ -333,13 +362,11 @@ static int read_time(CPURISCVState *env, int csrno, target_ulong *val)
return 0;
}
-#if defined(TARGET_RISCV32)
static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = cpu_get_host_ticks() >> 32;
return 0;
}
-#endif
#else /* CONFIG_USER_ONLY */
@@ -355,7 +382,6 @@ static int read_time(CPURISCVState *env, int csrno, target_ulong *val)
return 0;
}
-#if defined(TARGET_RISCV32)
static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val)
{
uint64_t delta = riscv_cpu_virt_enabled(env) ? env->htimedelta : 0;
@@ -367,7 +393,6 @@ static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val)
*val = (env->rdtime_fn(env->rdtime_fn_arg) + delta) >> 32;
return 0;
}
-#endif
/* Machine constants */
@@ -406,19 +431,17 @@ static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
static const target_ulong hip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
static const target_ulong vsip_writable_mask = MIP_VSSIP;
-#if defined(TARGET_RISCV32)
-static const char valid_vm_1_10[16] = {
+static const char valid_vm_1_10_32[16] = {
[VM_1_10_MBARE] = 1,
[VM_1_10_SV32] = 1
};
-#elif defined(TARGET_RISCV64)
-static const char valid_vm_1_10[16] = {
+
+static const char valid_vm_1_10_64[16] = {
[VM_1_10_MBARE] = 1,
[VM_1_10_SV39] = 1,
[VM_1_10_SV48] = 1,
[VM_1_10_SV57] = 1
};
-#endif /* CONFIG_USER_ONLY */
/* Machine Information Registers */
static int read_zero(CPURISCVState *env, int csrno, target_ulong *val)
@@ -441,7 +464,11 @@ static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val)
static int validate_vm(CPURISCVState *env, target_ulong vm)
{
- return valid_vm_1_10[vm & 0xf];
+ if (riscv_cpu_is_32bit(env)) {
+ return valid_vm_1_10_32[vm & 0xf];
+ } else {
+ return valid_vm_1_10_64[vm & 0xf];
+ }
}
static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
@@ -459,13 +486,14 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
MSTATUS_TW;
-#if defined(TARGET_RISCV64)
- /*
- * RV32: MPV and GVA are not in mstatus. The current plan is to
- * add them to mstatush. For now, we just don't support it.
- */
- mask |= MSTATUS_MPV | MSTATUS_GVA;
-#endif
+
+ if (!riscv_cpu_is_32bit(env)) {
+ /*
+ * RV32: MPV and GVA are not in mstatus. The current plan is to
+ * add them to mstatush. For now, we just don't support it.
+ */
+ mask |= MSTATUS_MPV | MSTATUS_GVA;
+ }
mstatus = (mstatus & ~mask) | (val & mask);
@@ -477,7 +505,6 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
return 0;
}
-#ifdef TARGET_RISCV32
static int read_mstatush(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->mstatus >> 32;
@@ -497,7 +524,6 @@ static int write_mstatush(CPURISCVState *env, int csrno, target_ulong val)
return 0;
}
-#endif
static int read_misa(CPURISCVState *env, int csrno, target_ulong *val)
{
@@ -895,10 +921,10 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
static int read_hstatus(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->hstatus;
-#ifdef TARGET_RISCV64
- /* We only support 64-bit VSXL */
- *val = set_field(*val, HSTATUS_VSXL, 2);
-#endif
+ if (!riscv_cpu_is_32bit(env)) {
+ /* We only support 64-bit VSXL */
+ *val = set_field(*val, HSTATUS_VSXL, 2);
+ }
/* We only support little endian */
*val = set_field(*val, HSTATUS_VSBE, 0);
return 0;
@@ -907,11 +933,9 @@ static int read_hstatus(CPURISCVState *env, int csrno, target_ulong *val)
static int write_hstatus(CPURISCVState *env, int csrno, target_ulong val)
{
env->hstatus = val;
-#ifdef TARGET_RISCV64
- if (get_field(val, HSTATUS_VSXL) != 2) {
+ if (!riscv_cpu_is_32bit(env) && get_field(val, HSTATUS_VSXL) != 2) {
qemu_log_mask(LOG_UNIMP, "QEMU does not support mixed HSXLEN options.");
}
-#endif
if (get_field(val, HSTATUS_VSBE) != 0) {
qemu_log_mask(LOG_UNIMP, "QEMU does not support big endian guests.");
}
@@ -1053,11 +1077,7 @@ static int read_htimedelta(CPURISCVState *env, int csrno, target_ulong *val)
return -RISCV_EXCP_ILLEGAL_INST;
}
-#if defined(TARGET_RISCV32)
- *val = env->htimedelta & 0xffffffff;
-#else
*val = env->htimedelta;
-#endif
return 0;
}
@@ -1067,15 +1087,14 @@ static int write_htimedelta(CPURISCVState *env, int csrno, target_ulong val)
return -RISCV_EXCP_ILLEGAL_INST;
}
-#if defined(TARGET_RISCV32)
- env->htimedelta = deposit64(env->htimedelta, 0, 32, (uint64_t)val);
-#else
- env->htimedelta = val;
-#endif
+ if (riscv_cpu_is_32bit(env)) {
+ env->htimedelta = deposit64(env->htimedelta, 0, 32, (uint64_t)val);
+ } else {
+ env->htimedelta = val;
+ }
return 0;
}
-#if defined(TARGET_RISCV32)
static int read_htimedeltah(CPURISCVState *env, int csrno, target_ulong *val)
{
if (!env->rdtime_fn) {
@@ -1095,7 +1114,6 @@ static int write_htimedeltah(CPURISCVState *env, int csrno, target_ulong val)
env->htimedelta = deposit64(env->htimedelta, 32, 32, (uint64_t)val);
return 0;
}
-#endif
/* Virtual CSR Registers */
static int read_vsstatus(CPURISCVState *env, int csrno, target_ulong *val)
@@ -1374,26 +1392,20 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
/* User Timers and Counters */
[CSR_CYCLE] = { ctr, read_instret },
[CSR_INSTRET] = { ctr, read_instret },
-#if defined(TARGET_RISCV32)
- [CSR_CYCLEH] = { ctr, read_instreth },
- [CSR_INSTRETH] = { ctr, read_instreth },
-#endif
+ [CSR_CYCLEH] = { ctr32, read_instreth },
+ [CSR_INSTRETH] = { ctr32, read_instreth },
/* In privileged mode, the monitor will have to emulate TIME CSRs only if
* rdtime callback is not provided by machine/platform emulation */
[CSR_TIME] = { ctr, read_time },
-#if defined(TARGET_RISCV32)
- [CSR_TIMEH] = { ctr, read_timeh },
-#endif
+ [CSR_TIMEH] = { ctr32, read_timeh },
#if !defined(CONFIG_USER_ONLY)
/* Machine Timers and Counters */
[CSR_MCYCLE] = { any, read_instret },
[CSR_MINSTRET] = { any, read_instret },
-#if defined(TARGET_RISCV32)
- [CSR_MCYCLEH] = { any, read_instreth },
- [CSR_MINSTRETH] = { any, read_instreth },
-#endif
+ [CSR_MCYCLEH] = { any32, read_instreth },
+ [CSR_MINSTRETH] = { any32, read_instreth },
/* Machine Information Registers */
[CSR_MVENDORID] = { any, read_zero },
@@ -1410,9 +1422,7 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_MTVEC] = { any, read_mtvec, write_mtvec },
[CSR_MCOUNTEREN] = { any, read_mcounteren, write_mcounteren },
-#if defined(TARGET_RISCV32)
- [CSR_MSTATUSH] = { any, read_mstatush, write_mstatush },
-#endif
+ [CSR_MSTATUSH] = { any32, read_mstatush, write_mstatush },
[CSR_MSCOUNTEREN] = { any, read_mscounteren, write_mscounteren },
@@ -1452,9 +1462,7 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_HGEIP] = { hmode, read_hgeip, write_hgeip },
[CSR_HGATP] = { hmode, read_hgatp, write_hgatp },
[CSR_HTIMEDELTA] = { hmode, read_htimedelta, write_htimedelta },
-#if defined(TARGET_RISCV32)
- [CSR_HTIMEDELTAH] = { hmode, read_htimedeltah, write_htimedeltah},
-#endif
+ [CSR_HTIMEDELTAH] = { hmode32, read_htimedeltah, write_htimedeltah},
[CSR_VSSTATUS] = { hmode, read_vsstatus, write_vsstatus },
[CSR_VSIP] = { hmode, NULL, NULL, rmw_vsip },
@@ -1477,9 +1485,7 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_HPMCOUNTER3 ... CSR_HPMCOUNTER31] = { ctr, read_zero },
[CSR_MHPMCOUNTER3 ... CSR_MHPMCOUNTER31] = { any, read_zero },
[CSR_MHPMEVENT3 ... CSR_MHPMEVENT31] = { any, read_zero },
-#if defined(TARGET_RISCV32)
- [CSR_HPMCOUNTER3H ... CSR_HPMCOUNTER31H] = { ctr, read_zero },
- [CSR_MHPMCOUNTER3H ... CSR_MHPMCOUNTER31H] = { any, read_zero },
-#endif
+ [CSR_HPMCOUNTER3H ... CSR_HPMCOUNTER31H] = { ctr32, read_zero },
+ [CSR_MHPMCOUNTER3H ... CSR_MHPMCOUNTER31H] = { any32, read_zero },
#endif /* !CONFIG_USER_ONLY */
};
diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
index bb346a8249..7c4ab92ecb 100644
--- a/target/riscv/fpu_helper.c
+++ b/target/riscv/fpu_helper.c
@@ -223,7 +223,6 @@ target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t rs1)
return (int32_t)float32_to_uint32(frs1, &env->fp_status);
}
-#if defined(TARGET_RISCV64)
uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1)
{
float32 frs1 = check_nanbox_s(rs1);
@@ -235,7 +234,6 @@ uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1)
float32 frs1 = check_nanbox_s(rs1);
return float32_to_uint64(frs1, &env->fp_status);
}
-#endif
uint64_t helper_fcvt_s_w(CPURISCVState *env, target_ulong rs1)
{
@@ -247,7 +245,6 @@ uint64_t helper_fcvt_s_wu(CPURISCVState *env, target_ulong rs1)
return nanbox_s(uint32_to_float32((uint32_t)rs1, &env->fp_status));
}
-#if defined(TARGET_RISCV64)
uint64_t helper_fcvt_s_l(CPURISCVState *env, uint64_t rs1)
{
return nanbox_s(int64_to_float32(rs1, &env->fp_status));
@@ -257,7 +254,6 @@ uint64_t helper_fcvt_s_lu(CPURISCVState *env, uint64_t rs1)
{
return nanbox_s(uint64_to_float32(rs1, &env->fp_status));
}
-#endif
target_ulong helper_fclass_s(uint64_t rs1)
{
@@ -336,7 +332,6 @@ target_ulong helper_fcvt_wu_d(CPURISCVState *env, uint64_t frs1)
return (int32_t)float64_to_uint32(frs1, &env->fp_status);
}
-#if defined(TARGET_RISCV64)
uint64_t helper_fcvt_l_d(CPURISCVState *env, uint64_t frs1)
{
return float64_to_int64(frs1, &env->fp_status);
@@ -346,7 +341,6 @@ uint64_t helper_fcvt_lu_d(CPURISCVState *env, uint64_t frs1)
{
return float64_to_uint64(frs1, &env->fp_status);
}
-#endif
uint64_t helper_fcvt_d_w(CPURISCVState *env, target_ulong rs1)
{
@@ -358,7 +352,6 @@ uint64_t helper_fcvt_d_wu(CPURISCVState *env, target_ulong rs1)
return uint32_to_float64((uint32_t)rs1, &env->fp_status);
}
-#if defined(TARGET_RISCV64)
uint64_t helper_fcvt_d_l(CPURISCVState *env, uint64_t rs1)
{
return int64_to_float64(rs1, &env->fp_status);
@@ -368,7 +361,6 @@ uint64_t helper_fcvt_d_lu(CPURISCVState *env, uint64_t rs1)
{
return uint64_to_float64(rs1, &env->fp_status);
}
-#endif
target_ulong helper_fclass_d(uint64_t frs1)
{
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 939731c345..e3f3f41e89 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -27,16 +27,12 @@ DEF_HELPER_FLAGS_3(flt_s, TCG_CALL_NO_RWG, tl, env, i64, i64)
DEF_HELPER_FLAGS_3(feq_s, TCG_CALL_NO_RWG, tl, env, i64, i64)
DEF_HELPER_FLAGS_2(fcvt_w_s, TCG_CALL_NO_RWG, tl, env, i64)
DEF_HELPER_FLAGS_2(fcvt_wu_s, TCG_CALL_NO_RWG, tl, env, i64)
-#if defined(TARGET_RISCV64)
-DEF_HELPER_FLAGS_2(fcvt_l_s, TCG_CALL_NO_RWG, tl, env, i64)
-DEF_HELPER_FLAGS_2(fcvt_lu_s, TCG_CALL_NO_RWG, tl, env, i64)
-#endif
+DEF_HELPER_FLAGS_2(fcvt_l_s, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_lu_s, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_2(fcvt_s_w, TCG_CALL_NO_RWG, i64, env, tl)
DEF_HELPER_FLAGS_2(fcvt_s_wu, TCG_CALL_NO_RWG, i64, env, tl)
-#if defined(TARGET_RISCV64)
-DEF_HELPER_FLAGS_2(fcvt_s_l, TCG_CALL_NO_RWG, i64, env, tl)
-DEF_HELPER_FLAGS_2(fcvt_s_lu, TCG_CALL_NO_RWG, i64, env, tl)
-#endif
+DEF_HELPER_FLAGS_2(fcvt_s_l, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_s_lu, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_1(fclass_s, TCG_CALL_NO_RWG_SE, tl, i64)
/* Floating Point - Double Precision */
@@ -54,16 +50,12 @@ DEF_HELPER_FLAGS_3(flt_d, TCG_CALL_NO_RWG, tl, env, i64, i64)
DEF_HELPER_FLAGS_3(feq_d, TCG_CALL_NO_RWG, tl, env, i64, i64)
DEF_HELPER_FLAGS_2(fcvt_w_d, TCG_CALL_NO_RWG, tl, env, i64)
DEF_HELPER_FLAGS_2(fcvt_wu_d, TCG_CALL_NO_RWG, tl, env, i64)
-#if defined(TARGET_RISCV64)
-DEF_HELPER_FLAGS_2(fcvt_l_d, TCG_CALL_NO_RWG, tl, env, i64)
-DEF_HELPER_FLAGS_2(fcvt_lu_d, TCG_CALL_NO_RWG, tl, env, i64)
-#endif
+DEF_HELPER_FLAGS_2(fcvt_l_d, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_lu_d, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_2(fcvt_d_w, TCG_CALL_NO_RWG, i64, env, tl)
DEF_HELPER_FLAGS_2(fcvt_d_wu, TCG_CALL_NO_RWG, i64, env, tl)
-#if defined(TARGET_RISCV64)
-DEF_HELPER_FLAGS_2(fcvt_d_l, TCG_CALL_NO_RWG, i64, env, tl)
-DEF_HELPER_FLAGS_2(fcvt_d_lu, TCG_CALL_NO_RWG, i64, env, tl)
-#endif
+DEF_HELPER_FLAGS_2(fcvt_d_l, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_d_lu, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_1(fclass_d, TCG_CALL_NO_RWG_SE, tl, i64)
/* Special functions */
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index b5abff8bef..a23fd3e32b 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -427,7 +427,6 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque)
{
struct CpuDefinitionInfoListData *cpu_list_data = opaque;
CpuDefinitionInfoList **cpu_list = &cpu_list_data->list;
- CpuDefinitionInfoList *entry;
CpuDefinitionInfo *info;
char *name = g_strdup(object_class_get_name(klass));
S390CPUClass *scc = S390_CPU_CLASS(klass);
@@ -454,10 +453,7 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque)
object_unref(obj);
}
- entry = g_new0(CpuDefinitionInfoList, 1);
- entry->value = info;
- entry->next = *cpu_list;
- *cpu_list = entry;
+ QAPI_LIST_PREPEND(*cpu_list, info);
}
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
@@ -624,12 +620,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
static void list_add_feat(const char *name, void *opaque)
{
strList **last = (strList **) opaque;
- strList *entry;
- entry = g_new0(strList, 1);
- entry->value = g_strdup(name);
- entry->next = *last;
- *last = entry;
+ QAPI_LIST_PREPEND(*last, g_strdup(name));
}
CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *infoa,
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index b9369398f2..4b2290650b 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -156,7 +156,9 @@ enum {
#define PS_IE (1<<1)
#define PS_AG (1<<0) /* v9, zero on UA2007 */
-#define FPRS_FEF (1<<2)
+#define FPRS_DL (1 << 0)
+#define FPRS_DU (1 << 1)
+#define FPRS_FEF (1 << 2)
#define HS_PRIV (1<<2)
#endif
@@ -606,10 +608,6 @@ target_ulong cpu_get_psr(CPUSPARCState *env1);
void cpu_put_psr(CPUSPARCState *env1, target_ulong val);
void cpu_put_psr_raw(CPUSPARCState *env1, target_ulong val);
#ifdef TARGET_SPARC64
-target_ulong cpu_get_ccr(CPUSPARCState *env1);
-void cpu_put_ccr(CPUSPARCState *env1, target_ulong val);
-target_ulong cpu_get_cwp64(CPUSPARCState *env1);
-void cpu_put_cwp64(CPUSPARCState *env1, int cwp);
void cpu_change_pstate(CPUSPARCState *env1, uint32_t new_pstate);
void cpu_gl_switch_gregs(CPUSPARCState *env, uint32_t new_gl);
#endif
@@ -827,4 +825,24 @@ static inline bool tb_am_enabled(int tb_flags)
#endif
}
+#ifdef TARGET_SPARC64
+/* win_helper.c */
+target_ulong cpu_get_ccr(CPUSPARCState *env1);
+void cpu_put_ccr(CPUSPARCState *env1, target_ulong val);
+target_ulong cpu_get_cwp64(CPUSPARCState *env1);
+void cpu_put_cwp64(CPUSPARCState *env1, int cwp);
+
+static inline uint64_t sparc64_tstate(CPUSPARCState *env)
+{
+ uint64_t tstate = (cpu_get_ccr(env) << 32) |
+ ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
+ cpu_get_cwp64(env);
+
+ if (env->def.features & CPU_FEATURE_GL) {
+ tstate |= (env->gl & 7ULL) << 40;
+ }
+ return tstate;
+}
+#endif
+
#endif
diff --git a/target/sparc/int64_helper.c b/target/sparc/int64_helper.c
index ba95bf228c..7fb8ab211c 100644
--- a/target/sparc/int64_helper.c
+++ b/target/sparc/int64_helper.c
@@ -131,9 +131,7 @@ void sparc_cpu_do_interrupt(CPUState *cs)
}
tsptr = cpu_tsptr(env);
- tsptr->tstate = (cpu_get_ccr(env) << 32) |
- ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
- cpu_get_cwp64(env);
+ tsptr->tstate = sparc64_tstate(env);
tsptr->tpc = env->pc;
tsptr->tnpc = env->npc;
tsptr->tt = intno;
@@ -148,7 +146,6 @@ void sparc_cpu_do_interrupt(CPUState *cs)
}
if (env->def.features & CPU_FEATURE_GL) {
- tsptr->tstate |= (env->gl & 7ULL) << 40;
cpu_gl_switch_gregs(env, env->gl + 1);
env->gl++;
}
diff --git a/target/sparc/machine.c b/target/sparc/machine.c
index f38cf229af..917375c3a1 100644
--- a/target/sparc/machine.c
+++ b/target/sparc/machine.c
@@ -68,7 +68,7 @@ static int get_psr(QEMUFile *f, void *opaque, size_t size,
}
static int put_psr(QEMUFile *f, void *opaque, size_t size,
- const VMStateField *field, QJSON *vmdesc)
+ const VMStateField *field, JSONWriter *vmdesc)
{
SPARCCPU *cpu = opaque;
CPUSPARCState *env = &cpu->env;
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 30c73f8d2e..4bfa3179f8 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -2324,8 +2324,8 @@ static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,
}
/* in OpenSPARC T1+ CPUs TWINX ASIs in store instructions
* are ST_BLKINIT_ ASIs */
- /* fall through */
#endif
+ /* fall through */
case GET_ASI_DIRECT:
gen_address_mask(dc, addr);
tcg_gen_qemu_st_tl(src, addr, da.mem_idx, da.memop);
diff --git a/target/sparc/win_helper.c b/target/sparc/win_helper.c
index 5b57892a10..3a7c0ff943 100644
--- a/target/sparc/win_helper.c
+++ b/target/sparc/win_helper.c
@@ -302,7 +302,7 @@ static inline uint64_t *get_gregset(CPUSPARCState *env, uint32_t pstate)
switch (pstate) {
default:
trace_win_helper_gregset_error(pstate);
- /* pass through to normal set of global registers */
+ /* fall through to normal set of global registers */
case 0:
return env->bgregs;
case PS_AG:
diff --git a/target/unicore32/translate.c b/target/unicore32/translate.c
index d4b06df672..962f9877a0 100644
--- a/target/unicore32/translate.c
+++ b/target/unicore32/translate.c
@@ -1801,6 +1801,7 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
do_misc(env, s, insn);
break;
}
+ /* fallthrough */
case 0x1:
if (((UCOP_OPCODES >> 2) == 2) && !UCOP_SET_S) {
do_misc(env, s, insn);
@@ -1817,6 +1818,7 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
if (UCOP_SET(8) || UCOP_SET(5)) {
ILLEGAL;
}
+ /* fallthrough */
case 0x3:
do_ldst_ir(env, s, insn);
break;
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 220f4601d5..7ca71de956 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -855,6 +855,7 @@ void tcg_optimize(TCGContext *s)
if ((arg_info(op->args[1])->mask & 0x80) != 0) {
break;
}
+ QEMU_FALLTHROUGH;
CASE_OP_32_64(ext8u):
mask = 0xff;
goto and_const;
@@ -862,6 +863,7 @@ void tcg_optimize(TCGContext *s)
if ((arg_info(op->args[1])->mask & 0x8000) != 0) {
break;
}
+ QEMU_FALLTHROUGH;
CASE_OP_32_64(ext16u):
mask = 0xffff;
goto and_const;
@@ -869,6 +871,7 @@ void tcg_optimize(TCGContext *s)
if ((arg_info(op->args[1])->mask & 0x80000000) != 0) {
break;
}
+ QEMU_FALLTHROUGH;
case INDEX_op_ext32u_i64:
mask = 0xffffffffU;
goto and_const;
@@ -886,6 +889,7 @@ void tcg_optimize(TCGContext *s)
if ((arg_info(op->args[1])->mask & 0x80000000) != 0) {
break;
}
+ QEMU_FALLTHROUGH;
case INDEX_op_extu_i32_i64:
/* We do not compute affected as it is a size changing op. */
mask = (uint32_t)arg_info(op->args[1])->mask;
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index 9a02079099..c845f91d43 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -35,17 +35,15 @@ static QString *from_json_str(const char *jstr, bool single, Error **errp)
static char *to_json_str(QString *str)
{
- QString *json = qobject_to_json(QOBJECT(str));
- char *jstr;
+ GString *json = qobject_to_json(QOBJECT(str));
if (!json) {
return NULL;
}
/* peel off double quotes */
- jstr = g_strndup(qstring_get_str(json) + 1,
- qstring_get_length(json) - 2);
- qobject_unref(json);
- return jstr;
+ g_string_truncate(json, json->len - 1);
+ g_string_erase(json, 0, 1);
+ return g_string_free(json, false);
}
static void escaped_string(void)
@@ -91,7 +89,7 @@ static void escaped_string(void)
for (j = 0; j < 2; j++) {
if (test_cases[i].utf8_out) {
cstr = from_json_str(test_cases[i].json_in, j, &error_abort);
- g_assert_cmpstr(qstring_get_try_str(cstr),
+ g_assert_cmpstr(qstring_get_str(cstr),
==, test_cases[i].utf8_out);
if (!test_cases[i].skip) {
jstr = to_json_str(cstr);
@@ -753,7 +751,7 @@ static void utf8_string(void)
/* Parse @json_in, expect @utf8_out */
if (utf8_out) {
str = from_json_str(json_in, j, &error_abort);
- g_assert_cmpstr(qstring_get_try_str(str), ==, utf8_out);
+ g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
qobject_unref(str);
} else {
str = from_json_str(json_in, j, NULL);
@@ -784,125 +782,129 @@ static void utf8_string(void)
/* Parse @json_out right back, unless it has replacements */
if (!strstr(json_out, "\\uFFFD")) {
str = from_json_str(json_out, j, &error_abort);
- g_assert_cmpstr(qstring_get_try_str(str), ==, utf8_in);
+ g_assert_cmpstr(qstring_get_str(str), ==, utf8_in);
qobject_unref(str);
}
}
}
}
-static void simple_number(void)
+static void int_number(void)
{
- int i;
struct {
const char *encoded;
int64_t decoded;
- int skip;
+ const char *reencoded;
} test_cases[] = {
{ "0", 0 },
{ "1234", 1234 },
{ "1", 1 },
{ "-32", -32 },
- { "-0", 0, .skip = 1 },
- { },
+ { "-0", 0, "0" },
+ {},
};
+ int i;
+ QNum *qnum;
+ int64_t ival;
+ uint64_t uval;
+ GString *str;
for (i = 0; test_cases[i].encoded; i++) {
- QNum *qnum;
- int64_t val;
-
qnum = qobject_to(QNum,
qobject_from_json(test_cases[i].encoded,
&error_abort));
g_assert(qnum);
- g_assert(qnum_get_try_int(qnum, &val));
- g_assert_cmpint(val, ==, test_cases[i].decoded);
- if (test_cases[i].skip == 0) {
- QString *str;
-
- str = qobject_to_json(QOBJECT(qnum));
- g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
- qobject_unref(str);
+ g_assert(qnum_get_try_int(qnum, &ival));
+ g_assert_cmpint(ival, ==, test_cases[i].decoded);
+ if (test_cases[i].decoded >= 0) {
+ g_assert(qnum_get_try_uint(qnum, &uval));
+ g_assert_cmpuint(uval, ==, (uint64_t)test_cases[i].decoded);
+ } else {
+ g_assert(!qnum_get_try_uint(qnum, &uval));
}
+ g_assert_cmpfloat(qnum_get_double(qnum), ==,
+ (double)test_cases[i].decoded);
+
+ str = qobject_to_json(QOBJECT(qnum));
+ g_assert_cmpstr(str->str, ==,
+ test_cases[i].reencoded ?: test_cases[i].encoded);
+ g_string_free(str, true);
qobject_unref(qnum);
}
}
-static void large_number(void)
+static void uint_number(void)
{
- const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
- const char *gtu64 = "18446744073709551616"; /* 2^64 */
- const char *lti64 = "-9223372036854775809"; /* -2^63 - 1 */
+ struct {
+ const char *encoded;
+ uint64_t decoded;
+ const char *reencoded;
+ } test_cases[] = {
+ { "9223372036854775808", (uint64_t)1 << 63 },
+ { "18446744073709551615", UINT64_MAX },
+ {},
+ };
+ int i;
QNum *qnum;
- QString *str;
- uint64_t val;
int64_t ival;
+ uint64_t uval;
+ GString *str;
- qnum = qobject_to(QNum, qobject_from_json(maxu64, &error_abort));
- g_assert(qnum);
- g_assert_cmpuint(qnum_get_uint(qnum), ==, 18446744073709551615U);
- g_assert(!qnum_get_try_int(qnum, &ival));
-
- str = qobject_to_json(QOBJECT(qnum));
- g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
- qobject_unref(str);
- qobject_unref(qnum);
-
- qnum = qobject_to(QNum, qobject_from_json(gtu64, &error_abort));
- g_assert(qnum);
- g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709552e3);
- g_assert(!qnum_get_try_uint(qnum, &val));
- g_assert(!qnum_get_try_int(qnum, &ival));
-
- str = qobject_to_json(QOBJECT(qnum));
- g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
- qobject_unref(str);
- qobject_unref(qnum);
+ for (i = 0; test_cases[i].encoded; i++) {
+ qnum = qobject_to(QNum,
+ qobject_from_json(test_cases[i].encoded,
+ &error_abort));
+ g_assert(qnum);
+ g_assert(qnum_get_try_uint(qnum, &uval));
+ g_assert_cmpuint(uval, ==, test_cases[i].decoded);
+ g_assert(!qnum_get_try_int(qnum, &ival));
+ g_assert_cmpfloat(qnum_get_double(qnum), ==,
+ (double)test_cases[i].decoded);
- qnum = qobject_to(QNum, qobject_from_json(lti64, &error_abort));
- g_assert(qnum);
- g_assert_cmpfloat(qnum_get_double(qnum), ==, -92233720368547758e2);
- g_assert(!qnum_get_try_uint(qnum, &val));
- g_assert(!qnum_get_try_int(qnum, &ival));
+ str = qobject_to_json(QOBJECT(qnum));
+ g_assert_cmpstr(str->str, ==,
+ test_cases[i].reencoded ?: test_cases[i].encoded);
+ g_string_free(str, true);
- str = qobject_to_json(QOBJECT(qnum));
- g_assert_cmpstr(qstring_get_str(str), ==, "-9223372036854775808");
- qobject_unref(str);
- qobject_unref(qnum);
+ qobject_unref(qnum);
+ }
}
static void float_number(void)
{
- int i;
struct {
const char *encoded;
double decoded;
- int skip;
+ const char *reencoded;
} test_cases[] = {
{ "32.43", 32.43 },
{ "0.222", 0.222 },
- { "-32.12313", -32.12313 },
- { "-32.20e-10", -32.20e-10, .skip = 1 },
- { },
+ { "-32.12313", -32.12313, "-32.123130000000003" },
+ { "-32.20e-10", -32.20e-10, "-3.22e-09" },
+ { "18446744073709551616", 0x1p64, "1.8446744073709552e+19" },
+ { "-9223372036854775809", -0x1p63, "-9.2233720368547758e+18" },
+ {},
};
+ int i;
+ QNum *qnum;
+ int64_t ival;
+ uint64_t uval;
+ GString *str;
for (i = 0; test_cases[i].encoded; i++) {
- QObject *obj;
- QNum *qnum;
-
- obj = qobject_from_json(test_cases[i].encoded, &error_abort);
- qnum = qobject_to(QNum, obj);
+ qnum = qobject_to(QNum,
+ qobject_from_json(test_cases[i].encoded,
+ &error_abort));
g_assert(qnum);
- g_assert(qnum_get_double(qnum) == test_cases[i].decoded);
+ g_assert_cmpfloat(qnum_get_double(qnum), ==, test_cases[i].decoded);
+ g_assert(!qnum_get_try_int(qnum, &ival));
+ g_assert(!qnum_get_try_uint(qnum, &uval));
- if (test_cases[i].skip == 0) {
- QString *str;
-
- str = qobject_to_json(obj);
- g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
- qobject_unref(str);
- }
+ str = qobject_to_json(QOBJECT(qnum));
+ g_assert_cmpstr(str->str, ==,
+ test_cases[i].reencoded ?: test_cases[i].encoded);
+ g_string_free(str, true);
qobject_unref(qnum);
}
@@ -913,7 +915,7 @@ static void keyword_literal(void)
QObject *obj;
QBool *qbool;
QNull *null;
- QString *str;
+ GString *str;
obj = qobject_from_json("true", &error_abort);
qbool = qobject_to(QBool, obj);
@@ -921,8 +923,8 @@ static void keyword_literal(void)
g_assert(qbool_get_bool(qbool) == true);
str = qobject_to_json(obj);
- g_assert(strcmp(qstring_get_str(str), "true") == 0);
- qobject_unref(str);
+ g_assert_cmpstr(str->str, ==, "true");
+ g_string_free(str, true);
qobject_unref(qbool);
@@ -932,8 +934,8 @@ static void keyword_literal(void)
g_assert(qbool_get_bool(qbool) == false);
str = qobject_to_json(obj);
- g_assert(strcmp(qstring_get_str(str), "false") == 0);
- qobject_unref(str);
+ g_assert_cmpstr(str->str, ==, "false");
+ g_string_free(str, true);
qobject_unref(qbool);
@@ -1019,9 +1021,8 @@ static void interpolation_valid(void)
/* string */
- qstr = qobject_to(QString,
- qobject_from_jsonf_nofail("%s", value_s));
- g_assert_cmpstr(qstring_get_try_str(qstr), ==, value_s);
+ qstr = qobject_to(QString, qobject_from_jsonf_nofail("%s", value_s));
+ g_assert_cmpstr(qstring_get_str(qstr), ==, value_s);
qobject_unref(qstr);
/* object */
@@ -1083,7 +1084,7 @@ static void simple_dict(void)
for (i = 0; test_cases[i].encoded; i++) {
QObject *obj;
- QString *str;
+ GString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
@@ -1091,10 +1092,10 @@ static void simple_dict(void)
str = qobject_to_json(obj);
qobject_unref(obj);
- obj = qobject_from_json(qstring_get_str(str), &error_abort);
+ obj = qobject_from_json(str->str, &error_abort);
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
qobject_unref(obj);
- qobject_unref(str);
+ g_string_free(str, true);
}
}
@@ -1192,7 +1193,7 @@ static void simple_list(void)
for (i = 0; test_cases[i].encoded; i++) {
QObject *obj;
- QString *str;
+ GString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
@@ -1200,10 +1201,10 @@ static void simple_list(void)
str = qobject_to_json(obj);
qobject_unref(obj);
- obj = qobject_from_json(qstring_get_str(str), &error_abort);
+ obj = qobject_from_json(str->str, &error_abort);
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
qobject_unref(obj);
- qobject_unref(str);
+ g_string_free(str, true);
}
}
@@ -1254,7 +1255,7 @@ static void simple_whitespace(void)
for (i = 0; test_cases[i].encoded; i++) {
QObject *obj;
- QString *str;
+ GString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
@@ -1262,11 +1263,11 @@ static void simple_whitespace(void)
str = qobject_to_json(obj);
qobject_unref(obj);
- obj = qobject_from_json(qstring_get_str(str), &error_abort);
+ obj = qobject_from_json(str->str, &error_abort);
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
qobject_unref(obj);
- qobject_unref(str);
+ g_string_free(str, true);
}
}
@@ -1479,8 +1480,8 @@ int main(int argc, char **argv)
g_test_add_func("/literals/string/quotes", string_with_quotes);
g_test_add_func("/literals/string/utf8", utf8_string);
- g_test_add_func("/literals/number/simple", simple_number);
- g_test_add_func("/literals/number/large", large_number);
+ g_test_add_func("/literals/number/int", int_number);
+ g_test_add_func("/literals/number/uint", uint_number);
g_test_add_func("/literals/number/float", float_number);
g_test_add_func("/literals/keyword", keyword_literal);
diff --git a/tests/check-qnum.c b/tests/check-qnum.c
index 4105015872..b85fca2302 100644
--- a/tests/check-qnum.c
+++ b/tests/check-qnum.c
@@ -147,7 +147,13 @@ static void qnum_to_string_test(void)
qn = qnum_from_double(0.42);
tmp = qnum_to_string(qn);
- g_assert_cmpstr(tmp, ==, "0.42");
+ g_assert_cmpstr(tmp, ==, "0.41999999999999998");
+ g_free(tmp);
+ qobject_unref(qn);
+
+ qn = qnum_from_double(2.718281828459045);
+ tmp = qnum_to_string(qn);
+ g_assert_cmpstr(tmp, ==, "2.7182818284590451");
g_free(tmp);
qobject_unref(qn);
}
diff --git a/tests/check-qobject.c b/tests/check-qobject.c
index 6b6deaeb8b..c1713d15af 100644
--- a/tests/check-qobject.c
+++ b/tests/check-qobject.c
@@ -155,8 +155,7 @@ static void qobject_is_equal_string_test(void)
str_case = qstring_from_str("Foo");
/* Should yield "foo" */
- str_built = qstring_from_substr("form", 0, 2);
- qstring_append_chr(str_built, 'o');
+ str_built = qstring_from_substr("buffoon", 3, 6);
check_unequal(str_base, str_whitespace_0, str_whitespace_1,
str_whitespace_2, str_whitespace_3, str_case);
diff --git a/tests/check-qstring.c b/tests/check-qstring.c
index 2d079921e3..4bf9772093 100644
--- a/tests/check-qstring.c
+++ b/tests/check-qstring.c
@@ -47,21 +47,6 @@ static void qstring_get_str_test(void)
qobject_unref(qstring);
}
-static void qstring_append_chr_test(void)
-{
- int i;
- QString *qstring;
- const char *str = "qstring append char unit-test";
-
- qstring = qstring_new();
-
- for (i = 0; str[i]; i++)
- qstring_append_chr(qstring, str[i]);
-
- g_assert(strcmp(str, qstring_get_str(qstring)) == 0);
- qobject_unref(qstring);
-}
-
static void qstring_from_substr_test(void)
{
QString *qs;
@@ -90,7 +75,6 @@ int main(int argc, char **argv)
g_test_add_func("/public/from_str", qstring_from_str_test);
g_test_add_func("/public/get_str", qstring_get_str_test);
- g_test_add_func("/public/append_chr", qstring_append_chr_test);
g_test_add_func("/public/from_substr", qstring_from_substr_test);
g_test_add_func("/public/to_qstring", qobject_to_qstring_test);
diff --git a/tests/fp/meson.build b/tests/fp/meson.build
index 3d4fb00f9d..8d739c4d59 100644
--- a/tests/fp/meson.build
+++ b/tests/fp/meson.build
@@ -27,6 +27,7 @@ tfdir = 'berkeley-testfloat-3/source'
sfinc = include_directories(sfdir / 'include', sfspedir)
tfcflags = [
+ '-Wno-implicit-fallthrough',
'-Wno-strict-prototypes',
'-Wno-unknown-pragmas',
'-Wno-uninitialized',
@@ -209,6 +210,7 @@ libtestfloat = static_library(
)
sfcflags = [
+ '-Wno-implicit-fallthrough',
'-Wno-missing-prototypes',
'-Wno-redundant-decls',
'-Wno-return-type',
diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out
index 7fc44b1c61..32a193f2c2 100644
--- a/tests/qemu-iotests/085.out
+++ b/tests/qemu-iotests/085.out
@@ -12,56 +12,135 @@ Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728
=== Create a single snapshot on virtio0 ===
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT', 'format': 'IMGFMT' } }
+{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': { 'device': 'virtio0',
+ 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT',
+ 'format': 'IMGFMT' } }
Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
=== Invalid command - missing device and nodename ===
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT', 'format': 'IMGFMT' } }
+{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': { 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT',
+ 'format': 'IMGFMT' } }
{"error": {"class": "GenericError", "desc": "Cannot find device= nor node_name="}}
=== Invalid command - missing snapshot-file ===
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'format': 'IMGFMT' } }
+{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': { 'device': 'virtio0',
+ 'format': 'IMGFMT' } }
{"error": {"class": "GenericError", "desc": "Parameter 'snapshot-file' is missing"}}
=== Create several transactional group snapshots ===
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/2-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/2-snapshot-v1.IMGFMT' } } ] } }
+{ 'execute': 'transaction', 'arguments':
+ {'actions': [
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio0',
+ 'snapshot-file': 'TEST_DIR/2-snapshot-v0.IMGFMT' } },
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio1',
+ 'snapshot-file': 'TEST_DIR/2-snapshot-v1.IMGFMT' } } ]
+ } }
Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/3-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/3-snapshot-v1.IMGFMT' } } ] } }
+{ 'execute': 'transaction', 'arguments':
+ {'actions': [
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio0',
+ 'snapshot-file': 'TEST_DIR/3-snapshot-v0.IMGFMT' } },
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio1',
+ 'snapshot-file': 'TEST_DIR/3-snapshot-v1.IMGFMT' } } ]
+ } }
Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/4-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/4-snapshot-v1.IMGFMT' } } ] } }
+{ 'execute': 'transaction', 'arguments':
+ {'actions': [
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio0',
+ 'snapshot-file': 'TEST_DIR/4-snapshot-v0.IMGFMT' } },
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio1',
+ 'snapshot-file': 'TEST_DIR/4-snapshot-v1.IMGFMT' } } ]
+ } }
Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/5-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/5-snapshot-v1.IMGFMT' } } ] } }
+{ 'execute': 'transaction', 'arguments':
+ {'actions': [
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio0',
+ 'snapshot-file': 'TEST_DIR/5-snapshot-v0.IMGFMT' } },
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio1',
+ 'snapshot-file': 'TEST_DIR/5-snapshot-v1.IMGFMT' } } ]
+ } }
Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/6-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/6-snapshot-v1.IMGFMT' } } ] } }
+{ 'execute': 'transaction', 'arguments':
+ {'actions': [
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio0',
+ 'snapshot-file': 'TEST_DIR/6-snapshot-v0.IMGFMT' } },
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio1',
+ 'snapshot-file': 'TEST_DIR/6-snapshot-v1.IMGFMT' } } ]
+ } }
Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/7-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/7-snapshot-v1.IMGFMT' } } ] } }
+{ 'execute': 'transaction', 'arguments':
+ {'actions': [
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio0',
+ 'snapshot-file': 'TEST_DIR/7-snapshot-v0.IMGFMT' } },
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio1',
+ 'snapshot-file': 'TEST_DIR/7-snapshot-v1.IMGFMT' } } ]
+ } }
Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/8-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/8-snapshot-v1.IMGFMT' } } ] } }
+{ 'execute': 'transaction', 'arguments':
+ {'actions': [
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio0',
+ 'snapshot-file': 'TEST_DIR/8-snapshot-v0.IMGFMT' } },
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio1',
+ 'snapshot-file': 'TEST_DIR/8-snapshot-v1.IMGFMT' } } ]
+ } }
Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/9-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/9-snapshot-v1.IMGFMT' } } ] } }
+{ 'execute': 'transaction', 'arguments':
+ {'actions': [
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio0',
+ 'snapshot-file': 'TEST_DIR/9-snapshot-v0.IMGFMT' } },
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio1',
+ 'snapshot-file': 'TEST_DIR/9-snapshot-v1.IMGFMT' } } ]
+ } }
Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
-{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/10-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/10-snapshot-v1.IMGFMT' } } ] } }
+{ 'execute': 'transaction', 'arguments':
+ {'actions': [
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio0',
+ 'snapshot-file': 'TEST_DIR/10-snapshot-v0.IMGFMT' } },
+ { 'type': 'blockdev-snapshot-sync', 'data' :
+ { 'device': 'virtio1',
+ 'snapshot-file': 'TEST_DIR/10-snapshot-v1.IMGFMT' } } ]
+ } }
Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
@@ -69,48 +148,84 @@ Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extende
=== Create a couple of snapshots using blockdev-snapshot ===
Formatting 'TEST_DIR/11-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/10-snapshot-v0.IMGFMT backing_fmt=IMGFMT
-{ 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_11', 'backing': null, 'file': { 'driver': 'file', 'filename': 'TEST_DIR/11-snapshot-v0.IMGFMT', 'node-name': 'file_11' } } }
+{ 'execute': 'blockdev-add', 'arguments':
+ { 'driver': 'IMGFMT', 'node-name': 'snap_11', 'backing': null,
+ 'file':
+ { 'driver': 'file', 'filename': 'TEST_DIR/11-snapshot-v0.IMGFMT',
+ 'node-name': 'file_11' } } }
{"return": {}}
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_11' } }
+{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node': 'virtio0',
+ 'overlay':'snap_11' } }
{"return": {}}
Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/11-snapshot-v0.IMGFMT backing_fmt=IMGFMT
-{ 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_12', 'backing': null, 'file': { 'driver': 'file', 'filename': 'TEST_DIR/12-snapshot-v0.IMGFMT', 'node-name': 'file_12' } } }
+{ 'execute': 'blockdev-add', 'arguments':
+ { 'driver': 'IMGFMT', 'node-name': 'snap_12', 'backing': null,
+ 'file':
+ { 'driver': 'file', 'filename': 'TEST_DIR/12-snapshot-v0.IMGFMT',
+ 'node-name': 'file_12' } } }
{"return": {}}
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_12' } }
+{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node': 'virtio0',
+ 'overlay':'snap_12' } }
{"return": {}}
=== Invalid command - cannot create a snapshot using a file BDS ===
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node':'virtio0', 'overlay':'file_12' } }
+{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node':'virtio0',
+ 'overlay':'file_12' }
+ }
{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}
=== Invalid command - snapshot node used as active layer ===
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_12' } }
+{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node': 'virtio0',
+ 'overlay':'snap_12' } }
{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node':'virtio0', 'overlay':'virtio0' } }
+{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node':'virtio0',
+ 'overlay':'virtio0' }
+ }
{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node':'virtio0', 'overlay':'virtio1' } }
+{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node':'virtio0',
+ 'overlay':'virtio1' }
+ }
{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}
=== Invalid command - snapshot node used as backing hd ===
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_11' } }
+{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node': 'virtio0',
+ 'overlay':'snap_11' } }
{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}
=== Invalid command - snapshot node has a backing image ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT
-{ 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_13', 'file': { 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'node-name': 'file_13' } } }
-{"return": {}}
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_13' } }
+{ 'execute': 'blockdev-add', 'arguments':
+ { 'driver': 'IMGFMT', 'node-name': 'snap_13',
+ 'file':
+ { 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT',
+ 'node-name': 'file_13' } } }
+{"return": {}}
+{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node': 'virtio0',
+ 'overlay':'snap_13' } }
{"error": {"class": "GenericError", "desc": "The overlay already has a backing image"}}
=== Invalid command - The node does not exist ===
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_14' } }
+{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node': 'virtio0',
+ 'overlay':'snap_14' } }
{"error": {"class": "GenericError", "desc": "Cannot find device=snap_14 nor node_name=snap_14"}}
-{ 'execute': 'blockdev-snapshot', 'arguments': { 'node':'nodevice', 'overlay':'snap_13' } }
+{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node':'nodevice',
+ 'overlay':'snap_13' }
+ }
{"error": {"class": "GenericError", "desc": "Cannot find device=nodevice nor node_name=nodevice"}}
*** done
diff --git a/tests/qemu-iotests/094.out b/tests/qemu-iotests/094.out
index 9b6c57b3e2..97f894cf8f 100644
--- a/tests/qemu-iotests/094.out
+++ b/tests/qemu-iotests/094.out
@@ -3,13 +3,19 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/source.IMGFMT', fmt=IMGFMT size=67108864
{'execute': 'qmp_capabilities'}
{"return": {}}
-{'execute': 'drive-mirror', 'arguments': {'device': 'src', 'target': 'nbd+unix:///?socket=SOCK_DIR/nbd', 'format': 'nbd', 'sync':'full', 'mode':'existing'}}
+{'execute': 'drive-mirror',
+ 'arguments': {'device': 'src',
+ 'target': 'nbd+unix:///?socket=SOCK_DIR/nbd',
+ 'format': 'nbd',
+ 'sync':'full',
+ 'mode':'existing'}}
{"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": 67108864, "offset": 67108864, "speed": 0, "type": "mirror"}}
-{'execute': 'block-job-complete', 'arguments': {'device': 'src'}}
+{'execute': 'block-job-complete',
+ 'arguments': {'device': 'src'}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
diff --git a/tests/qemu-iotests/095.out b/tests/qemu-iotests/095.out
index e66ced58f8..8257c5e1e6 100644
--- a/tests/qemu-iotests/095.out
+++ b/tests/qemu-iotests/095.out
@@ -12,7 +12,9 @@ virtual size: 5 MiB (5242880 bytes)
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'block-commit', 'arguments': { 'device': 'test', 'top': 'TEST_DIR/t.IMGFMT.snp1' } }
+{ 'execute': 'block-commit',
+ 'arguments': { 'device': 'test',
+ 'top': 'TEST_DIR/t.IMGFMT.snp1' } }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "test"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "test"}}
{"return": {}}
diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102
index 2cc3efd1ed..9d747c7bbf 100755
--- a/tests/qemu-iotests/102
+++ b/tests/qemu-iotests/102
@@ -68,7 +68,7 @@ $QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io
qemu_comm_method=monitor _launch_qemu -drive if=none,file="$TEST_IMG",id=drv0
# Wait for a prompt to appear (so we know qemu has opened the image)
-_send_qemu_cmd '' '(qemu)'
+_send_qemu_cmd $QEMU_HANDLE '' '(qemu)'
$QEMU_IMG resize --shrink --image-opts \
"driver=raw,file.driver=file,file.filename=$TEST_IMG,file.locking=off" \
diff --git a/tests/qemu-iotests/102.out b/tests/qemu-iotests/102.out
index cd2fdc7f96..320ed5a52b 100644
--- a/tests/qemu-iotests/102.out
+++ b/tests/qemu-iotests/102.out
@@ -16,8 +16,8 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
QEMU X.Y.Z monitor - type 'help' for more information
-Image resized.
(qemu)
+Image resized.
(qemu) qemu-io drv0 map
64 KiB (0x10000) bytes allocated at offset 0 bytes (0x0)
*** done
diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out
index ad739df46c..6e73406cdb 100644
--- a/tests/qemu-iotests/109.out
+++ b/tests/qemu-iotests/109.out
@@ -6,7 +6,9 @@ Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ '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.
Specify the 'raw' format explicitly to remove the restrictions.
@@ -27,7 +29,9 @@ 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' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
{"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": {}}
@@ -51,7 +55,9 @@ Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ '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.
Specify the 'raw' format explicitly to remove the restrictions.
@@ -72,7 +78,9 @@ 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' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
{"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": {}}
@@ -96,7 +104,9 @@ Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ '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.
Specify the 'raw' format explicitly to remove the restrictions.
@@ -117,7 +127,9 @@ 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' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
{"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": {}}
@@ -141,7 +153,9 @@ Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ '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.
Specify the 'raw' format explicitly to remove the restrictions.
@@ -162,7 +176,9 @@ 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' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
{"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": {}}
@@ -186,7 +202,9 @@ Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ '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.
Specify the 'raw' format explicitly to remove the restrictions.
@@ -207,7 +225,9 @@ 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' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
{"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": {}}
@@ -231,7 +251,9 @@ Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ '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.
Specify the 'raw' format explicitly to remove the restrictions.
@@ -252,7 +274,9 @@ 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' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
{"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": {}}
@@ -275,7 +299,9 @@ Images are identical.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ '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.
Specify the 'raw' format explicitly to remove the restrictions.
@@ -296,7 +322,9 @@ 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' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
{"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": {}}
@@ -319,7 +347,9 @@ Images are identical.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ '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.
Specify the 'raw' format explicitly to remove the restrictions.
@@ -340,7 +370,9 @@ 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' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
{"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": {}}
@@ -363,7 +395,9 @@ Images are identical.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ '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.
Specify the 'raw' format explicitly to remove the restrictions.
@@ -384,7 +418,9 @@ 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' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
{"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": {}}
@@ -407,7 +443,9 @@ Images are identical.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ '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.
Specify the 'raw' format explicitly to remove the restrictions.
@@ -428,7 +466,9 @@ 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' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
{"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": {}}
@@ -451,7 +491,9 @@ Images are identical.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ '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.
Specify the 'raw' format explicitly to remove the restrictions.
@@ -473,7 +515,9 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
Images are identical.
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
+{'execute':'drive-mirror', 'arguments':{
+ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT',
+ 'mode': 'existing', 'sync': 'full'}}
{"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": {}}
diff --git a/tests/qemu-iotests/117.out b/tests/qemu-iotests/117.out
index bb623dcc0a..735ffd25c6 100644
--- a/tests/qemu-iotests/117.out
+++ b/tests/qemu-iotests/117.out
@@ -2,11 +2,18 @@ QA output created by 117
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'blockdev-add', 'arguments': { 'node-name': 'protocol', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT' } }
+{ 'execute': 'blockdev-add',
+ 'arguments': { 'node-name': 'protocol',
+ 'driver': 'file',
+ 'filename': 'TEST_DIR/t.IMGFMT' } }
{"return": {}}
-{ 'execute': 'blockdev-add', 'arguments': { 'node-name': 'format', 'driver': 'IMGFMT', 'file': 'protocol' } }
+{ 'execute': 'blockdev-add',
+ 'arguments': { 'node-name': 'format',
+ 'driver': 'IMGFMT',
+ 'file': 'protocol' } }
{"return": {}}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io format "write -P 42 0 64k"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line': 'qemu-io format "write -P 42 0 64k"' } }
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
diff --git a/tests/qemu-iotests/127.out b/tests/qemu-iotests/127.out
index efd6cb327f..1685c4850a 100644
--- a/tests/qemu-iotests/127.out
+++ b/tests/qemu-iotests/127.out
@@ -6,13 +6,21 @@ wrote 42/42 bytes at offset 0
42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'drive-mirror', 'arguments': { 'job-id': 'mirror', 'device': 'source', 'target': 'TEST_DIR/t.IMGFMT.overlay1', 'mode': 'existing', 'sync': 'top' } }
+{ 'execute': 'drive-mirror',
+ 'arguments': {
+ 'job-id': 'mirror',
+ 'device': 'source',
+ 'target': 'TEST_DIR/t.IMGFMT.overlay1',
+ 'mode': 'existing',
+ 'sync': 'top'
+ } }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "mirror"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "mirror", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
-{ 'execute': 'block-job-complete', 'arguments': { 'device': 'mirror' } }
+{ 'execute': 'block-job-complete',
+ 'arguments': { 'device': 'mirror' } }
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "mirror"}}
diff --git a/tests/qemu-iotests/140.out b/tests/qemu-iotests/140.out
index 62d9c3ab3c..312f76d5da 100644
--- a/tests/qemu-iotests/140.out
+++ b/tests/qemu-iotests/140.out
@@ -4,13 +4,17 @@ wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'nbd-server-start', 'arguments': { 'addr': { 'type': 'unix', 'data': { 'path': 'SOCK_DIR/nbd' }}}}
+{ 'execute': 'nbd-server-start',
+ 'arguments': { 'addr': { 'type': 'unix',
+ 'data': { 'path': 'SOCK_DIR/nbd' }}}}
{"return": {}}
-{ 'execute': 'nbd-server-add', 'arguments': { 'device': 'drv' }}
+{ 'execute': 'nbd-server-add',
+ 'arguments': { 'device': 'drv' }}
{"return": {}}
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{ 'execute': 'eject', 'arguments': { 'device': 'drv' }}
+{ 'execute': 'eject',
+ 'arguments': { 'device': 'drv' }}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "drv"}}
qemu-io: can't open device nbd+unix:///drv?socket=SOCK_DIR/nbd: Requested export not available
server reported: export 'drv' not present
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
index 08e0aecd65..6d8652e22b 100644
--- a/tests/qemu-iotests/141.out
+++ b/tests/qemu-iotests/141.out
@@ -7,105 +7,173 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.
=== Testing drive-backup ===
-{'execute': 'blockdev-add', 'arguments': { 'node-name': 'drv0', 'driver': 'IMGFMT', 'file': { 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT' }}}
-{"return": {}}
-{'execute': 'drive-backup', 'arguments': {'job-id': 'job0', 'device': 'drv0', 'target': 'TEST_DIR/o.IMGFMT', 'format': 'IMGFMT', 'sync': 'none'}}
+{'execute': 'blockdev-add',
+ 'arguments': {
+ 'node-name': 'drv0',
+ 'driver': 'IMGFMT',
+ 'file': {
+ 'driver': 'file',
+ 'filename': 'TEST_DIR/t.IMGFMT'
+ }}}
+{"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': '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'}}
+{'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' }}}
-{"return": {}}
-{'execute': 'drive-mirror', 'arguments': {'job-id': 'job0', 'device': 'drv0', 'target': 'TEST_DIR/o.IMGFMT', 'format': 'IMGFMT', 'sync': 'none'}}
+{'execute': 'blockdev-add',
+ 'arguments': {
+ 'node-name': 'drv0',
+ 'driver': 'IMGFMT',
+ 'file': {
+ 'driver': 'file',
+ 'filename': 'TEST_DIR/t.IMGFMT'
+ }}}
+{"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': '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'}}
+{'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' }}}
-{"return": {}}
-{'execute': 'block-commit', 'arguments': {'job-id': 'job0', 'device': 'drv0'}}
+{'execute': 'blockdev-add',
+ 'arguments': {
+ 'node-name': 'drv0',
+ 'driver': 'IMGFMT',
+ 'file': {
+ 'driver': 'file',
+ 'filename': 'TEST_DIR/t.IMGFMT'
+ }}}
+{"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': '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'}}
+{'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' }}}
-{"return": {}}
-{'execute': 'block-commit', 'arguments': {'job-id': 'job0', 'device': 'drv0', 'top': 'TEST_DIR/m.IMGFMT', 'speed': 1}}
+{'execute': 'blockdev-add',
+ 'arguments': {
+ 'node-name': 'drv0',
+ 'driver': 'IMGFMT',
+ 'file': {
+ 'driver': 'file',
+ 'filename': 'TEST_DIR/t.IMGFMT'
+ }}}
+{"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': 'blockdev-del',
+ 'arguments': {'node-name': 'drv0'}}
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
-{'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'}}
+{'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' }}}
-{"return": {}}
-{'execute': 'block-stream', 'arguments': {'job-id': 'job0', 'device': 'drv0', 'speed': 1}}
+{'execute': 'blockdev-add',
+ 'arguments': {
+ 'node-name': 'drv0',
+ 'driver': 'IMGFMT',
+ 'file': {
+ 'driver': 'file',
+ 'filename': 'TEST_DIR/t.IMGFMT'
+ }}}
+{"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': 'blockdev-del',
+ 'arguments': {'node-name': 'drv0'}}
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
-{'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'}}
+{'execute': 'blockdev-del',
+ 'arguments': {'node-name': 'drv0'}}
{"return": {}}
*** done
diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out
index fc9c0a761f..9ec5888e0e 100644
--- a/tests/qemu-iotests/143.out
+++ b/tests/qemu-iotests/143.out
@@ -1,7 +1,9 @@
QA output created by 143
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'nbd-server-start', 'arguments': { 'addr': { 'type': 'unix', 'data': { 'path': 'SOCK_DIR/nbd' }}}}
+{ 'execute': 'nbd-server-start',
+ 'arguments': { 'addr': { 'type': 'unix',
+ 'data': { 'path': 'SOCK_DIR/nbd' }}}}
{"return": {}}
qemu-io: can't open device nbd+unix:///no_such_export?socket=SOCK_DIR/nbd: Requested export not available
server reported: export 'no_such_export' not present
diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out
index 13e0c4f5a7..b3b4812015 100644
--- a/tests/qemu-iotests/144.out
+++ b/tests/qemu-iotests/144.out
@@ -8,19 +8,33 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=536870912
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp.IMGFMT', 'format': 'IMGFMT' } }
+{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': {
+ 'device': 'virtio0',
+ 'snapshot-file':'TEST_DIR/tmp.IMGFMT',
+ 'format': 'IMGFMT'
+ }
+ }
Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
=== Performing block-commit on active layer ===
-{ 'execute': 'block-commit', 'arguments': { 'device': 'virtio0' } }
+{ 'execute': 'block-commit',
+ 'arguments': {
+ 'device': 'virtio0'
+ }
+ }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "virtio0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "virtio0"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "virtio0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
-{ 'execute': 'block-job-complete', 'arguments': { 'device': 'virtio0' } }
+{ 'execute': 'block-job-complete',
+ 'arguments': {
+ 'device': 'virtio0'
+ }
+ }
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "virtio0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "virtio0"}}
@@ -30,7 +44,13 @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off co
=== Performing Live Snapshot 2 ===
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp2.IMGFMT', 'format': 'IMGFMT' } }
+{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': {
+ 'device': 'virtio0',
+ 'snapshot-file':'TEST_DIR/tmp2.IMGFMT',
+ 'format': 'IMGFMT'
+ }
+ }
Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
*** done
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
index fcaa71aeee..ff8e55864a 100644
--- a/tests/qemu-iotests/153.out
+++ b/tests/qemu-iotests/153.out
@@ -425,7 +425,8 @@ _qemu_img_wrapper commit -b TEST_DIR/t.qcow2.b TEST_DIR/t.qcow2.c
{ 'execute': 'qmp_capabilities' }
{"return": {}}
Adding drive
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'drive_add 0 if=none,id=d0,file=TEST_DIR/t.IMGFMT' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line': 'drive_add 0 if=none,id=d0,file=TEST_DIR/t.IMGFMT' } }
{"return": "OKrn"}
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
@@ -435,25 +436,30 @@ Creating overlay with qemu-img when the guest is running should be allowed
_qemu_img_wrapper create -f qcow2 -b TEST_DIR/t.qcow2 -F qcow2 TEST_DIR/t.qcow2.overlay
== Closing an image should unlock it ==
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'drive_del d0' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line': 'drive_del d0' } }
{"return": ""}
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
Adding two and closing one
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'drive_add 0 if=none,id=d0,file=TEST_DIR/t.IMGFMT,readonly=on' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line': 'drive_add 0 if=none,id=d0,file=TEST_DIR/t.IMGFMT,readonly=on' } }
{"return": "OKrn"}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'drive_add 0 if=none,id=d1,file=TEST_DIR/t.IMGFMT,readonly=on' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line': 'drive_add 0 if=none,id=d1,file=TEST_DIR/t.IMGFMT,readonly=on' } }
{"return": "OKrn"}
_qemu_img_wrapper info TEST_DIR/t.qcow2
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'drive_del d0' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line': 'drive_del d0' } }
{"return": ""}
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
qemu-io: can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
Is another process using the image [TEST_DIR/t.qcow2]?
Closing the other
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'drive_del d1' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line': 'drive_del d1' } }
{"return": ""}
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
diff --git a/tests/qemu-iotests/156.out b/tests/qemu-iotests/156.out
index cce167b63f..4a22f0c41a 100644
--- a/tests/qemu-iotests/156.out
+++ b/tests/qemu-iotests/156.out
@@ -8,24 +8,37 @@ wrote 196608/196608 bytes at offset 65536
{ 'execute': 'qmp_capabilities' }
{"return": {}}
Formatting 'TEST_DIR/t.IMGFMT.overlay', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'source', 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay', 'format': 'IMGFMT', 'mode': 'existing' } }
+{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': { 'device': 'source',
+ 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay',
+ 'format': 'IMGFMT',
+ 'mode': 'existing' } }
{"return": {}}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io source "write -P 3 128k 128k"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io source "write -P 3 128k 128k"' } }
wrote 131072/131072 bytes at offset 131072
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
Formatting 'TEST_DIR/t.IMGFMT.target.overlay', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.target backing_fmt=IMGFMT
-{ 'execute': 'drive-mirror', 'arguments': { 'device': 'source', 'target': 'TEST_DIR/t.IMGFMT.target.overlay', 'mode': 'existing', 'sync': 'top' } }
+{ 'execute': 'drive-mirror',
+ 'arguments': { 'device': 'source',
+ 'target': 'TEST_DIR/t.IMGFMT.target.overlay',
+ 'mode': 'existing',
+ 'sync': 'top' } }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "source"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "source"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "source"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "source", "len": 131072, "offset": 131072, "speed": 0, "type": "mirror"}}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io source "write -P 4 192k 64k"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io source "write -P 4 192k 64k"' } }
wrote 65536/65536 bytes at offset 196608
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
-{ 'execute': 'block-job-complete', 'arguments': { 'device': 'source' } }
+{ 'execute': 'block-job-complete',
+ 'arguments': { 'device': 'source' } }
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "source"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "source"}}
@@ -33,19 +46,27 @@ wrote 65536/65536 bytes at offset 196608
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "source"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "source"}}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io source "read -P 1 0k 64k"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io source "read -P 1 0k 64k"' } }
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io source "read -P 2 64k 64k"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io source "read -P 2 64k 64k"' } }
read 65536/65536 bytes at offset 65536
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io source "read -P 3 128k 64k"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io source "read -P 3 128k 64k"' } }
read 65536/65536 bytes at offset 131072
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io source "read -P 4 192k 64k"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io source "read -P 4 192k 64k"' } }
read 65536/65536 bytes at offset 196608
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
diff --git a/tests/qemu-iotests/161.out b/tests/qemu-iotests/161.out
index 3d8d89a9da..6cc285afcf 100644
--- a/tests/qemu-iotests/161.out
+++ b/tests/qemu-iotests/161.out
@@ -7,18 +7,23 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
{"return": ""}
*** Stream and then change an option on the backing file
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'block-stream', 'arguments': { 'device': 'none0', 'base': 'TEST_DIR/t.IMGFMT.base' } }
+{ 'execute': 'block-stream', 'arguments': { 'device': 'none0',
+ 'base': 'TEST_DIR/t.IMGFMT.base' } }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "none0"}}
{"return": {}}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "none0", "len": 1048576, "offset": 1048576, "speed": 0, "type": "stream"}}
@@ -33,11 +38,14 @@ Formatting 'TEST_DIR/t.IMGFMT.int', fmt=IMGFMT size=1048576 backing_file=TEST_DI
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.int backing_fmt=IMGFMT
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'block-commit', 'arguments': { 'device': 'none0', 'top': 'TEST_DIR/t.IMGFMT.int' } }
+{ 'execute': 'block-commit', 'arguments': { 'device': 'none0',
+ 'top': 'TEST_DIR/t.IMGFMT.int' } }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "none0"}}
{"return": {}}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "none0", "len": 1048576, "offset": 1048576, "speed": 0, "type": "commit"}}
diff --git a/tests/qemu-iotests/172 b/tests/qemu-iotests/172
index 3abfa72948..b45782e8db 100755
--- a/tests/qemu-iotests/172
+++ b/tests/qemu-iotests/172
@@ -73,7 +73,7 @@ check_floppy_qtree()
(QEMU_OPTIONS="" do_run_qemu "$@" |
_filter_testdir |_filter_generated_node_ids | _filter_hmp |
sed -ne '/^ dev: isa-fdc/,/^ dev:/{x;p};/^[a-z][^ ]* (NODE_NAME):* /,/^(qemu)$/{p}') 2>&1 |
- _filter_win32 | _filter_qemu
+ _filter_win32 | _filter_qemu | _filter_qom_path
}
check_cache_mode()
diff --git a/tests/qemu-iotests/172.out b/tests/qemu-iotests/172.out
index cca2894af0..2cd4a8fd83 100644
--- a/tests/qemu-iotests/172.out
+++ b/tests/qemu-iotests/172.out
@@ -63,12 +63,12 @@ Testing: -fda TEST_DIR/t.qcow2
share-rw = false
drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -114,16 +114,16 @@ Testing: -fdb TEST_DIR/t.qcow2
share-rw = false
drive-type = "288"
floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[16]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[23]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
floppy0: [not inserted]
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -169,17 +169,17 @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2
share-rw = false
drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
floppy1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/unattached/device[16]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[23]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -255,12 +255,12 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2
share-rw = false
drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -306,16 +306,16 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1
share-rw = false
drive-type = "288"
floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[16]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[23]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
floppy0: [not inserted]
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -361,17 +361,17 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t
share-rw = false
drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
floppy1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/unattached/device[16]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[23]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -411,12 +411,12 @@ Use -device floppy,unit=0,drive=... instead.
share-rw = false
drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -453,12 +453,12 @@ Use -device floppy,unit=1,drive=... instead.
share-rw = false
drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -508,17 +508,17 @@ Use -device floppy,unit=1,drive=... instead.
share-rw = false
drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/unattached/device[16]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[23]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -556,12 +556,12 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0
share-rw = false
drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[21]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -596,12 +596,12 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1
share-rw = false
drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[21]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -647,17 +647,17 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
share-rw = false
drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/peripheral-anon/device[1]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[21]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -708,17 +708,17 @@ Use -device floppy,unit=1,drive=... instead.
share-rw = false
drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[16]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[23]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -766,17 +766,17 @@ Use -device floppy,unit=0,drive=... instead.
share-rw = false
drive-type = "144"
floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[16]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[23]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -838,17 +838,17 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
share-rw = false
drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -894,17 +894,17 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
share-rw = false
drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -950,17 +950,17 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
share-rw = false
drive-type = "144"
floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -1006,17 +1006,17 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
share-rw = false
drive-type = "144"
floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -1071,17 +1071,17 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
share-rw = false
drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -1127,17 +1127,17 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
share-rw = false
drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none0 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -1191,17 +1191,17 @@ Use -device floppy,unit=0,drive=... instead.
share-rw = false
drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -1249,17 +1249,17 @@ Use -device floppy,unit=0,drive=... instead.
share-rw = false
drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -1307,17 +1307,17 @@ Use -device floppy,unit=1,drive=... instead.
share-rw = false
drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -1365,17 +1365,17 @@ Use -device floppy,unit=1,drive=... instead.
share-rw = false
drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/unattached/device[15]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
none1 (NODE_NAME): TEST_DIR/t.qcow2.2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[22]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -1410,12 +1410,12 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global floppy.drive=none0 -device
share-rw = false
drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[21]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -1603,12 +1603,12 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t
share-rw = false
drive-type = "120"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[21]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -1643,12 +1643,12 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t
share-rw = false
drive-type = "288"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[21]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -1686,12 +1686,12 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,logical
share-rw = false
drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[21]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
@@ -1726,12 +1726,12 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physica
share-rw = false
drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
- Attached to: /machine/peripheral-anon/device[0]
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
ide1-cd0: [not inserted]
- Attached to: /machine/unattached/device[21]
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
sd0: [not inserted]
diff --git a/tests/qemu-iotests/173.out b/tests/qemu-iotests/173.out
index b5114b5c79..2d6490d680 100644
--- a/tests/qemu-iotests/173.out
+++ b/tests/qemu-iotests/173.out
@@ -6,11 +6,30 @@ Formatting 'TEST_DIR/image.snp1', fmt=IMGFMT size=104857600
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'arguments': { 'device': 'disk2', 'format': 'IMGFMT', 'mode': 'existing', 'snapshot-file': 'TEST_DIR/image.snp1', 'snapshot-node-name': 'snp1' }, 'execute': 'blockdev-snapshot-sync' }
+{ 'arguments': {
+ 'device': 'disk2',
+ 'format': 'IMGFMT',
+ 'mode': 'existing',
+ 'snapshot-file': 'TEST_DIR/image.snp1',
+ 'snapshot-node-name': 'snp1'
+ },
+ 'execute': 'blockdev-snapshot-sync'
+ }
{"return": {}}
-{ 'arguments': { 'backing-file': 'image.base', 'device': 'disk2', 'image-node-name': 'snp1' }, 'execute': 'change-backing-file' }
+{ 'arguments': {
+ 'backing-file': 'image.base',
+ 'device': 'disk2',
+ 'image-node-name': 'snp1'
+ },
+ 'execute': 'change-backing-file'
+ }
{"return": {}}
-{ 'arguments': { 'base': 'TEST_DIR/image.base', 'device': 'disk2' }, 'execute': 'block-stream' }
+{ 'arguments': {
+ 'base': 'TEST_DIR/image.base',
+ 'device': 'disk2'
+ },
+ 'execute': 'block-stream'
+ }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk2"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk2"}}
{"return": {}}
diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out
index ce23340670..57f7265458 100644
--- a/tests/qemu-iotests/182.out
+++ b/tests/qemu-iotests/182.out
@@ -10,16 +10,42 @@ Is another process using the image [TEST_DIR/t.qcow2]?
{'execute': 'qmp_capabilities'}
{"return": {}}
-{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node0', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
-{"return": {}}
-{'execute': 'blockdev-snapshot-sync', 'arguments': { 'node-name': 'node0', 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay', 'snapshot-node-name': 'node1' } }
+{'execute': 'blockdev-add',
+ 'arguments': {
+ 'node-name': 'node0',
+ 'driver': 'file',
+ 'filename': 'TEST_DIR/t.IMGFMT',
+ 'locking': 'on'
+ } }
+{"return": {}}
+{'execute': 'blockdev-snapshot-sync',
+ 'arguments': {
+ 'node-name': 'node0',
+ 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay',
+ 'snapshot-node-name': 'node1'
+ } }
Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file lazy_refcounts=off refcount_bits=16
{"return": {}}
-{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node1', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
-{"return": {}}
-{'execute': 'nbd-server-start', 'arguments': { 'addr': { 'type': 'unix', 'data': { 'path': 'SOCK_DIR/nbd.socket' } } } }
-{"return": {}}
-{'execute': 'nbd-server-add', 'arguments': { 'device': 'node1' } }
+{'execute': 'blockdev-add',
+ 'arguments': {
+ 'node-name': 'node1',
+ 'driver': 'file',
+ 'filename': 'TEST_DIR/t.IMGFMT',
+ 'locking': 'on'
+ } }
+{"return": {}}
+{'execute': 'nbd-server-start',
+ 'arguments': {
+ 'addr': {
+ 'type': 'unix',
+ 'data': {
+ 'path': 'SOCK_DIR/nbd.socket'
+ } } } }
+{"return": {}}
+{'execute': 'nbd-server-add',
+ 'arguments': {
+ 'device': 'node1'
+ } }
{"return": {}}
=== Testing failure to loosen restrictions ===
diff --git a/tests/qemu-iotests/183.out b/tests/qemu-iotests/183.out
index d4be2cb2de..fd9c2e52a5 100644
--- a/tests/qemu-iotests/183.out
+++ b/tests/qemu-iotests/183.out
@@ -11,18 +11,23 @@ Formatting 'TEST_DIR/t.IMGFMT.dest', fmt=IMGFMT size=67108864
=== Write something on the source ===
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "write -P 0x55 0 64k"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io disk "write -P 0x55 0 64k"' } }
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "read -P 0x55 0 64k"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io disk "read -P 0x55 0 64k"' } }
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
=== Do block migration to destination ===
-{ 'execute': 'migrate', 'arguments': { 'uri': 'unix:SOCK_DIR/migrate', 'blk': true } }
+{ 'execute': 'migrate',
+ 'arguments': { 'uri': 'unix:SOCK_DIR/migrate', 'blk': true } }
{"return": {}}
{ 'execute': 'query-status' }
{"return": {"status": "postmigrate", "singlestep": false, "running": false}}
@@ -32,11 +37,15 @@ read 65536/65536 bytes at offset 0
{ 'execute': 'query-status' }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "RESUME"}
{"return": {"status": "running", "singlestep": false, "running": true}}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "read -P 0x55 0 64k"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io disk "read -P 0x55 0 64k"' } }
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "write -P 0x66 1M 64k"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io disk "write -P 0x66 1M 64k"' } }
wrote 65536/65536 bytes at offset 1048576
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out
index 339438ac68..eab55d22bf 100644
--- a/tests/qemu-iotests/185.out
+++ b/tests/qemu-iotests/185.out
@@ -8,20 +8,34 @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
=== Creating backing chain ===
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT.mid', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
+{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': { 'device': 'disk',
+ 'snapshot-file': 'TEST_DIR/t.IMGFMT.mid',
+ 'format': 'IMGFMT',
+ 'mode': 'absolute-paths' } }
Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
-{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "write 0 4M"' } }
+{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io disk "write 0 4M"' } }
wrote 4194304/4194304 bytes at offset 0
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
-{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
+{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': { 'device': 'disk',
+ 'snapshot-file': 'TEST_DIR/t.IMGFMT',
+ 'format': 'IMGFMT',
+ 'mode': 'absolute-paths' } }
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
{"return": {}}
=== Start commit job and exit qemu ===
-{ 'execute': 'block-commit', 'arguments': { 'device': 'disk', 'base':'TEST_DIR/t.IMGFMT.base', 'top': 'TEST_DIR/t.IMGFMT.mid', 'speed': 65536 } }
+{ 'execute': 'block-commit',
+ 'arguments': { 'device': 'disk',
+ 'base':'TEST_DIR/t.IMGFMT.base',
+ 'top': 'TEST_DIR/t.IMGFMT.mid',
+ 'speed': 65536 } }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
{"return": {}}
@@ -34,7 +48,10 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off comp
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'block-commit', 'arguments': { 'device': 'disk', 'base':'TEST_DIR/t.IMGFMT.base', 'speed': 65536 } }
+{ 'execute': 'block-commit',
+ 'arguments': { 'device': 'disk',
+ 'base':'TEST_DIR/t.IMGFMT.base',
+ 'speed': 65536 } }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
{"return": {}}
@@ -47,7 +64,12 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off comp
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'drive-mirror', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
+{ 'execute': 'drive-mirror',
+ 'arguments': { 'device': 'disk',
+ 'target': 'TEST_DIR/t.IMGFMT.copy',
+ 'format': 'IMGFMT',
+ 'sync': 'full',
+ 'speed': 65536 } }
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
@@ -61,7 +83,12 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'drive-backup', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
+{ 'execute': 'drive-backup',
+ 'arguments': { 'device': 'disk',
+ 'target': 'TEST_DIR/t.IMGFMT.copy',
+ 'format': 'IMGFMT',
+ 'sync': 'full',
+ 'speed': 65536 } }
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
@@ -77,7 +104,9 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'block-stream', 'arguments': { 'device': 'disk', 'speed': 65536 } }
+{ 'execute': 'block-stream',
+ 'arguments': { 'device': 'disk',
+ 'speed': 65536 } }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
{"return": {}}
diff --git a/tests/qemu-iotests/186.out b/tests/qemu-iotests/186.out
index 5b3504042a..01530040e5 100644
--- a/tests/qemu-iotests/186.out
+++ b/tests/qemu-iotests/186.out
@@ -7,7 +7,7 @@ Testing: -device floppy
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
/machine/peripheral-anon/device[1]: [not inserted]
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
(qemu) quit
@@ -23,7 +23,7 @@ Testing: -device ide-cd
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
/machine/peripheral-anon/device[1]: [not inserted]
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
(qemu) quit
@@ -39,7 +39,7 @@ Testing: -device scsi-cd
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
/machine/peripheral-anon/device[1]: [not inserted]
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
(qemu) quit
@@ -58,7 +58,7 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device ide-hd,d
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Cache mode: writeback
(qemu) quit
@@ -74,7 +74,7 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device scsi-hd,
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Cache mode: writeback
(qemu) quit
@@ -90,7 +90,7 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]/virtio-backend
Cache mode: writeback
(qemu) quit
@@ -98,7 +98,7 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral/qdev_id/virtio-backend
Cache mode: writeback
(qemu) quit
@@ -106,7 +106,7 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device floppy,d
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
(qemu) quit
@@ -124,7 +124,7 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device ide-cd,d
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
(qemu) quit
@@ -142,7 +142,7 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device scsi-cd,
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
(qemu) quit
@@ -191,7 +191,7 @@ none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
Cache mode: writeback
null: json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral/qdev_id/virtio-backend
Cache mode: writeback
(qemu) quit
@@ -241,7 +241,7 @@ Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device ide
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Cache mode: writeback
(qemu) quit
@@ -257,7 +257,7 @@ Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device scs
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Cache mode: writeback
(qemu) quit
@@ -273,7 +273,7 @@ Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device vir
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]/virtio-backend
Cache mode: writeback
(qemu) quit
@@ -281,7 +281,7 @@ Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device vir
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral/qdev_id/virtio-backend
Cache mode: writeback
(qemu) quit
@@ -289,7 +289,7 @@ Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device flo
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
(qemu) quit
@@ -307,7 +307,7 @@ Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device ide
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
(qemu) quit
@@ -325,7 +325,7 @@ Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device scs
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
(qemu) quit
@@ -353,7 +353,7 @@ Testing: -drive if=none -device floppy,drive=none0
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
none0: [not inserted]
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
(qemu) quit
@@ -369,7 +369,7 @@ Testing: -drive if=none -device ide-cd,drive=none0
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
none0: [not inserted]
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
(qemu) quit
@@ -385,7 +385,7 @@ Testing: -drive if=none -device scsi-cd,drive=none0
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
none0: [not inserted]
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]
Removable device: not locked, tray closed
(qemu) quit
@@ -404,7 +404,7 @@ Testing: -drive if=floppy
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
floppy0: [not inserted]
- Attached to: PATH
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
(qemu) quit
@@ -412,7 +412,7 @@ Testing: -drive if=floppy,driver=null-co,read-zeroes=on
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
floppy0 (NODE_NAME): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
(qemu) quit
@@ -421,7 +421,7 @@ Testing: -drive if=ide,driver=null-co,read-zeroes=on
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
ide0-hd0 (NODE_NAME): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/unattached/device[N]
Cache mode: writeback
(qemu) quit
@@ -429,7 +429,7 @@ Testing: -drive if=ide,media=cdrom
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
ide0-cd0: [not inserted]
- Attached to: PATH
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
(qemu) quit
@@ -437,7 +437,7 @@ Testing: -drive if=ide,driver=null-co,read-zeroes=on,media=cdrom
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
ide0-cd0 (NODE_NAME): json:{"read-zeroes": "on", "driver": "null-co"} (null-co, read-only)
- Attached to: PATH
+ Attached to: /machine/unattached/device[N]
Removable device: not locked, tray closed
Cache mode: writeback
(qemu) quit
@@ -446,7 +446,7 @@ Testing: -drive if=virtio,driver=null-co,read-zeroes=on
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
virtio0 (NODE_NAME): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: PATH
+ Attached to: /machine/peripheral-anon/device[N]/virtio-backend
Cache mode: writeback
(qemu) quit
@@ -454,7 +454,7 @@ Testing: -drive if=pflash,driver=null-co,read-zeroes=on,size=1M
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
pflash0 (NODE_NAME): json:{"read-zeroes": "on", "driver": "null-co", "size": "1M"} (null-co)
- Attached to: PATH
+ Attached to: /machine/system.flash0
Cache mode: writeback
(qemu) quit
diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out
index 11aaf3b691..022021efab 100644
--- a/tests/qemu-iotests/191.out
+++ b/tests/qemu-iotests/191.out
@@ -16,7 +16,11 @@ wrote 65536/65536 bytes at offset 1048576
=== Perform commit job ===
-{ 'execute': 'block-commit', 'arguments': { 'job-id': 'commit0', 'device': 'top', 'base':'TEST_DIR/t.IMGFMT.base', 'top': 'TEST_DIR/t.IMGFMT.mid' } }
+{ 'execute': 'block-commit',
+ 'arguments': { 'job-id': 'commit0',
+ 'device': 'top',
+ 'base':'TEST_DIR/t.IMGFMT.base',
+ 'top': 'TEST_DIR/t.IMGFMT.mid' } }
{
"timestamp": {
"seconds": TIMESTAMP,
@@ -427,7 +431,11 @@ wrote 65536/65536 bytes at offset 1048576
=== Perform commit job ===
-{ 'execute': 'block-commit', 'arguments': { 'job-id': 'commit0', 'device': 'top', 'base':'TEST_DIR/t.IMGFMT.base', 'top': 'TEST_DIR/t.IMGFMT.mid' } }
+{ 'execute': 'block-commit',
+ 'arguments': { 'job-id': 'commit0',
+ 'device': 'top',
+ 'base':'TEST_DIR/t.IMGFMT.base',
+ 'top': 'TEST_DIR/t.IMGFMT.mid' } }
{
"timestamp": {
"seconds": TIMESTAMP,
diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out
index a5e88e2a82..dc1a3c9786 100644
--- a/tests/qemu-iotests/210.out
+++ b/tests/qemu-iotests/210.out
@@ -182,7 +182,7 @@ Job failed: The requested file size is too large
=== Resize image with invalid sizes ===
{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 9223372036854775296}}
-{"error": {"class": "GenericError", "desc": "The requested file size is too large"}}
+{"error": {"class": "GenericError", "desc": "Required too big image size, it must be not greater than 9223372035781033984"}}
{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 9223372036854775808}}
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}}
{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 18446744073709551104}}
diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out
index f6eac23f04..bbc85289e3 100644
--- a/tests/qemu-iotests/223.out
+++ b/tests/qemu-iotests/223.out
@@ -26,31 +26,48 @@ wrote 2097152/2097152 bytes at offset 2097152
{"execute":"qmp_capabilities"}
{"return": {}}
-{"execute":"blockdev-add", "arguments":{"driver":"IMGFMT", "node-name":"n", "file":{"driver":"file", "filename":"TEST_DIR/t.IMGFMT"}}}
+{"execute":"blockdev-add",
+ "arguments":{"driver":"IMGFMT", "node-name":"n",
+ "file":{"driver":"file", "filename":"TEST_DIR/t.IMGFMT"}}}
{"return": {}}
-{"execute":"block-dirty-bitmap-disable", "arguments":{"node":"n", "name":"b"}}
+{"execute":"block-dirty-bitmap-disable",
+ "arguments":{"node":"n", "name":"b"}}
{"return": {}}
=== Set up NBD with normal access ===
-{"execute":"nbd-server-add", "arguments":{"device":"n"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"n"}}
{"error": {"class": "GenericError", "desc": "NBD server not running"}}
-{"execute":"nbd-server-start", "arguments":{"addr":{"type":"unix", "data":{"path":"SOCK_DIR/nbd"}}}}
+{"execute":"nbd-server-start",
+ "arguments":{"addr":{"type":"unix",
+ "data":{"path":"SOCK_DIR/nbd"}}}}
{"return": {}}
-{"execute":"nbd-server-start", "arguments":{"addr":{"type":"unix", "data":{"path":"SOCK_DIR/nbd1"}}}}
+{"execute":"nbd-server-start",
+ "arguments":{"addr":{"type":"unix",
+ "data":{"path":"SOCK_DIR/nbd1"}}}}
{"error": {"class": "GenericError", "desc": "NBD server already running"}}
exports available: 0
-{"execute":"nbd-server-add", "arguments":{"device":"n", "bitmap":"b"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"n", "bitmap":"b"}}
{"return": {}}
-{"execute":"nbd-server-add", "arguments":{"device":"nosuch"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"nosuch"}}
{"error": {"class": "GenericError", "desc": "Cannot find device=nosuch nor node_name=nosuch"}}
-{"execute":"nbd-server-add", "arguments":{"device":"n"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"n"}}
{"error": {"class": "GenericError", "desc": "Block export id 'n' is already in use"}}
-{"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b2"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"n", "name":"n2",
+ "bitmap":"b2"}}
{"error": {"class": "GenericError", "desc": "Enabled bitmap 'b2' incompatible with readonly export"}}
-{"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b3"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"n", "name":"n2",
+ "bitmap":"b3"}}
{"error": {"class": "GenericError", "desc": "Bitmap 'b3' is not found"}}
-{"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "writable":true, "description":"some text", "bitmap":"b2"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"n", "name":"n2", "writable":true,
+ "description":"some text", "bitmap":"b2"}}
{"return": {}}
exports available: 2
export: 'n'
@@ -99,12 +116,15 @@ read 2097152/2097152 bytes at offset 2097152
=== End qemu NBD server ===
-{"execute":"nbd-server-remove", "arguments":{"name":"n"}}
+{"execute":"nbd-server-remove",
+ "arguments":{"name":"n"}}
{"return": {}}
-{"execute":"nbd-server-remove", "arguments":{"name":"n2"}}
+{"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"}}
+{"execute":"nbd-server-remove",
+ "arguments":{"name":"n2"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}}
{"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}}
{"execute":"nbd-server-stop"}
@@ -114,26 +134,41 @@ read 2097152/2097152 bytes at offset 2097152
=== Set up NBD with iothread access ===
-{"execute":"x-blockdev-set-iothread", "arguments":{"node-name":"n", "iothread":"io0"}}
+{"execute":"x-blockdev-set-iothread",
+ "arguments":{"node-name":"n", "iothread":"io0"}}
{"return": {}}
-{"execute":"nbd-server-add", "arguments":{"device":"n"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"n"}}
{"error": {"class": "GenericError", "desc": "NBD server not running"}}
-{"execute":"nbd-server-start", "arguments":{"addr":{"type":"unix", "data":{"path":"SOCK_DIR/nbd"}}}}
+{"execute":"nbd-server-start",
+ "arguments":{"addr":{"type":"unix",
+ "data":{"path":"SOCK_DIR/nbd"}}}}
{"return": {}}
-{"execute":"nbd-server-start", "arguments":{"addr":{"type":"unix", "data":{"path":"SOCK_DIR/nbd1"}}}}
+{"execute":"nbd-server-start",
+ "arguments":{"addr":{"type":"unix",
+ "data":{"path":"SOCK_DIR/nbd1"}}}}
{"error": {"class": "GenericError", "desc": "NBD server already running"}}
exports available: 0
-{"execute":"nbd-server-add", "arguments":{"device":"n", "bitmap":"b"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"n", "bitmap":"b"}}
{"return": {}}
-{"execute":"nbd-server-add", "arguments":{"device":"nosuch"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"nosuch"}}
{"error": {"class": "GenericError", "desc": "Cannot find device=nosuch nor node_name=nosuch"}}
-{"execute":"nbd-server-add", "arguments":{"device":"n"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"n"}}
{"error": {"class": "GenericError", "desc": "Block export id 'n' is already in use"}}
-{"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b2"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"n", "name":"n2",
+ "bitmap":"b2"}}
{"error": {"class": "GenericError", "desc": "Enabled bitmap 'b2' incompatible with readonly export"}}
-{"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "bitmap":"b3"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"n", "name":"n2",
+ "bitmap":"b3"}}
{"error": {"class": "GenericError", "desc": "Bitmap 'b3' is not found"}}
-{"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2", "writable":true, "description":"some text", "bitmap":"b2"}}
+{"execute":"nbd-server-add",
+ "arguments":{"device":"n", "name":"n2", "writable":true,
+ "description":"some text", "bitmap":"b2"}}
{"return": {}}
exports available: 2
export: 'n'
@@ -182,12 +217,15 @@ read 2097152/2097152 bytes at offset 2097152
=== End qemu NBD server ===
-{"execute":"nbd-server-remove", "arguments":{"name":"n"}}
+{"execute":"nbd-server-remove",
+ "arguments":{"name":"n"}}
{"return": {}}
-{"execute":"nbd-server-remove", "arguments":{"name":"n2"}}
+{"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"}}
+{"execute":"nbd-server-remove",
+ "arguments":{"name":"n2"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}}
{"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}}
{"execute":"nbd-server-stop"}
diff --git a/tests/qemu-iotests/229.out b/tests/qemu-iotests/229.out
index 7eed393013..7d2bfbfbe6 100644
--- a/tests/qemu-iotests/229.out
+++ b/tests/qemu-iotests/229.out
@@ -8,7 +8,14 @@ wrote 2097152/2097152 bytes at offset 0
=== Starting drive-mirror, causing error & stop ===
-{'execute': 'drive-mirror', 'arguments': {'device': 'testdisk', 'format': 'IMGFMT', 'target': 'blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT.dest', 'sync': 'full', 'mode': 'existing', 'on-source-error': 'stop', 'on-target-error': 'stop' }}
+{'execute': 'drive-mirror',
+ 'arguments': {'device': 'testdisk',
+ 'format': 'IMGFMT',
+ 'target': 'blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT.dest',
+ 'sync': 'full',
+ 'mode': 'existing',
+ 'on-source-error': 'stop',
+ 'on-target-error': 'stop' }}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "testdisk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
{"return": {}}
@@ -17,7 +24,9 @@ wrote 2097152/2097152 bytes at offset 0
=== Force cancel job paused in error state ===
-{'execute': 'block-job-cancel', 'arguments': { 'device': 'testdisk', 'force': true}}
+{'execute': 'block-job-cancel',
+ 'arguments': { 'device': 'testdisk',
+ 'force': true}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "testdisk"}}
diff --git a/tests/qemu-iotests/249.out b/tests/qemu-iotests/249.out
index 85acda4635..92ec81db03 100644
--- a/tests/qemu-iotests/249.out
+++ b/tests/qemu-iotests/249.out
@@ -7,24 +7,29 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
=== Send a write command to a drive opened in read-only mode (1)
-{ 'execute': 'human-monitor-command', 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
+{ 'execute': 'human-monitor-command',
+ 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
{"return": "Block node is read-onlyrn"}
=== Run block-commit on base using an invalid filter node name
-{ 'execute': 'block-commit', 'arguments': {'job-id': 'job0', 'device': 'none1', 'top-node': 'int', 'filter-node-name': '1234'}}
+{ 'execute': 'block-commit',
+ 'arguments': {'job-id': 'job0', 'device': 'none1', 'top-node': 'int',
+ 'filter-node-name': '1234'}}
{"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": "Invalid node name"}}
=== Send a write command to a drive opened in read-only mode (2)
-{ 'execute': 'human-monitor-command', 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
+{ 'execute': 'human-monitor-command',
+ 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
{"return": "Block node is read-onlyrn"}
=== Run block-commit on base using the default filter node name
-{ 'execute': 'block-commit', 'arguments': {'job-id': 'job0', 'device': 'none1', 'top-node': 'int'}}
+{ 'execute': 'block-commit',
+ 'arguments': {'job-id': 'job0', 'device': 'none1', 'top-node': 'int'}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
{"return": {}}
@@ -36,6 +41,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
=== Send a write command to a drive opened in read-only mode (3)
-{ 'execute': 'human-monitor-command', 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
+{ 'execute': 'human-monitor-command',
+ 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
{"return": "Block node is read-onlyrn"}
*** done
diff --git a/tests/qemu-iotests/298 b/tests/qemu-iotests/298
new file mode 100644
index 0000000000..d535946b5f
--- /dev/null
+++ b/tests/qemu-iotests/298
@@ -0,0 +1,186 @@
+#!/usr/bin/env python3
+#
+# Test for preallocate filter
+#
+# Copyright (c) 2020 Virtuozzo International GmbH.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import iotests
+
+MiB = 1024 * 1024
+disk = os.path.join(iotests.test_dir, 'disk')
+overlay = os.path.join(iotests.test_dir, 'overlay')
+refdisk = os.path.join(iotests.test_dir, 'refdisk')
+drive_opts = f'node-name=disk,driver={iotests.imgfmt},' \
+ f'file.node-name=filter,file.driver=preallocate,' \
+ f'file.file.node-name=file,file.file.filename={disk}'
+
+
+class TestPreallocateBase(iotests.QMPTestCase):
+ def setUp(self):
+ iotests.qemu_img_create('-f', iotests.imgfmt, disk, str(10 * MiB))
+
+ def tearDown(self):
+ try:
+ self.check_small()
+ check = iotests.qemu_img_check(disk)
+ self.assertFalse('leaks' in check)
+ self.assertFalse('corruptions' in check)
+ self.assertEqual(check['check-errors'], 0)
+ finally:
+ os.remove(disk)
+
+ def check_big(self):
+ self.assertTrue(os.path.getsize(disk) > 100 * MiB)
+
+ def check_small(self):
+ self.assertTrue(os.path.getsize(disk) < 10 * MiB)
+
+
+class TestQemuImg(TestPreallocateBase):
+ def test_qemu_img(self):
+ p = iotests.QemuIoInteractive('--image-opts', drive_opts)
+
+ p.cmd('write 0 1M')
+ p.cmd('flush')
+
+ self.check_big()
+
+ p.close()
+
+
+class TestPreallocateFilter(TestPreallocateBase):
+ def setUp(self):
+ super().setUp()
+ self.vm = iotests.VM().add_drive(path=None, opts=drive_opts)
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ super().tearDown()
+
+ def test_prealloc(self):
+ self.vm.hmp_qemu_io('drive0', 'write 0 1M')
+ self.check_big()
+
+ def test_external_snapshot(self):
+ self.test_prealloc()
+
+ result = self.vm.qmp('blockdev-snapshot-sync', node_name='disk',
+ snapshot_file=overlay,
+ snapshot_node_name='overlay')
+ self.assert_qmp(result, 'return', {})
+
+ # on reopen to r-o base preallocation should be dropped
+ self.check_small()
+
+ self.vm.hmp_qemu_io('drive0', 'write 1M 1M')
+
+ result = self.vm.qmp('block-commit', device='overlay')
+ self.assert_qmp(result, 'return', {})
+ self.complete_and_wait()
+
+ # commit of new megabyte should trigger preallocation
+ self.check_big()
+
+ def test_reopen_opts(self):
+ result = self.vm.qmp('x-blockdev-reopen', **{
+ 'node-name': 'disk',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'node-name': 'filter',
+ 'driver': 'preallocate',
+ 'prealloc-size': 20 * MiB,
+ 'prealloc-align': 5 * MiB,
+ 'file': {
+ 'node-name': 'file',
+ 'driver': 'file',
+ 'filename': disk
+ }
+ }
+ })
+ self.assert_qmp(result, 'return', {})
+
+ self.vm.hmp_qemu_io('drive0', 'write 0 1M')
+ self.assertTrue(os.path.getsize(disk) == 25 * MiB)
+
+
+class TestTruncate(iotests.QMPTestCase):
+ def setUp(self):
+ iotests.qemu_img_create('-f', iotests.imgfmt, disk, str(10 * MiB))
+ iotests.qemu_img_create('-f', iotests.imgfmt, refdisk, str(10 * MiB))
+
+ def tearDown(self):
+ os.remove(disk)
+ os.remove(refdisk)
+
+ def do_test(self, prealloc_mode, new_size):
+ ret = iotests.qemu_io_silent('--image-opts', '-c', 'write 0 10M', '-c',
+ f'truncate -m {prealloc_mode} {new_size}',
+ drive_opts)
+ self.assertEqual(ret, 0)
+
+ ret = iotests.qemu_io_silent('-f', iotests.imgfmt, '-c', 'write 0 10M',
+ '-c',
+ f'truncate -m {prealloc_mode} {new_size}',
+ refdisk)
+ self.assertEqual(ret, 0)
+
+ stat = os.stat(disk)
+ refstat = os.stat(refdisk)
+
+ # Probably we'll want preallocate filter to keep align to cluster when
+ # shrink preallocation, so, ignore small differece
+ self.assertLess(abs(stat.st_size - refstat.st_size), 64 * 1024)
+
+ # Preallocate filter may leak some internal clusters (for example, if
+ # guest write far over EOF, skipping some clusters - they will remain
+ # fallocated, preallocate filter don't care about such leaks, it drops
+ # only trailing preallocation.
+ self.assertLess(abs(stat.st_blocks - refstat.st_blocks) * 512,
+ 1024 * 1024)
+
+ def test_real_shrink(self):
+ self.do_test('off', '5M')
+
+ def test_truncate_inside_preallocated_area__falloc(self):
+ self.do_test('falloc', '50M')
+
+ def test_truncate_inside_preallocated_area__metadata(self):
+ self.do_test('metadata', '50M')
+
+ def test_truncate_inside_preallocated_area__full(self):
+ self.do_test('full', '50M')
+
+ def test_truncate_inside_preallocated_area__off(self):
+ self.do_test('off', '50M')
+
+ def test_truncate_over_preallocated_area__falloc(self):
+ self.do_test('falloc', '150M')
+
+ def test_truncate_over_preallocated_area__metadata(self):
+ self.do_test('metadata', '150M')
+
+ def test_truncate_over_preallocated_area__full(self):
+ self.do_test('full', '150M')
+
+ def test_truncate_over_preallocated_area__off(self):
+ self.do_test('off', '150M')
+
+
+if __name__ == '__main__':
+ iotests.main(supported_fmts=['qcow2'], required_fmts=['preallocate'])
diff --git a/tests/qemu-iotests/298.out b/tests/qemu-iotests/298.out
new file mode 100644
index 0000000000..fa16b5ccef
--- /dev/null
+++ b/tests/qemu-iotests/298.out
@@ -0,0 +1,5 @@
+.............
+----------------------------------------------------------------------
+Ran 13 tests
+
+OK
diff --git a/tests/qemu-iotests/308.out b/tests/qemu-iotests/308.out
index b93aceed2e..466e7e0267 100644
--- a/tests/qemu-iotests/308.out
+++ b/tests/qemu-iotests/308.out
@@ -5,42 +5,91 @@ wrote 67108864/67108864 bytes at offset 0
64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{'execute': 'qmp_capabilities'}
{"return": {}}
-{'execute': 'blockdev-add', 'arguments': { 'driver': 'file', 'node-name': 'node-protocol', 'filename': 'TEST_DIR/t.IMGFMT' } }
+{'execute': 'blockdev-add',
+ 'arguments': {
+ 'driver': 'file',
+ 'node-name': 'node-protocol',
+ 'filename': 'TEST_DIR/t.IMGFMT'
+ } }
{"return": {}}
-{'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'node-format', 'file': 'node-protocol' } }
+{'execute': 'blockdev-add',
+ 'arguments': {
+ 'driver': 'IMGFMT',
+ 'node-name': 'node-format',
+ 'file': 'node-protocol'
+ } }
{"return": {}}
=== Mountpoint not present ===
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-err', 'node-name': 'node-format', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse' } }
+{'execute': 'block-export-add',
+ 'arguments': {
+ 'type': 'fuse',
+ 'id': 'export-err',
+ 'node-name': 'node-format',
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse'
+ } }
{"error": {"class": "GenericError", "desc": "Failed to stat 'TEST_DIR/t.IMGFMT.fuse': No such file or directory"}}
=== Mountpoint is a directory ===
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-err', 'node-name': 'node-format', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse' } }
+{'execute': 'block-export-add',
+ 'arguments': {
+ 'type': 'fuse',
+ 'id': 'export-err',
+ 'node-name': 'node-format',
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse'
+ } }
{"error": {"class": "GenericError", "desc": "'TEST_DIR/t.IMGFMT.fuse' is not a regular file"}}
=== Mountpoint is a regular file ===
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-mp', 'node-name': 'node-format', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse' } }
+{'execute': 'block-export-add',
+ 'arguments': {
+ 'type': 'fuse',
+ 'id': 'export-mp',
+ 'node-name': 'node-format',
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse'
+ } }
{"return": {}}
Images are identical.
=== Mount over existing file ===
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-img', 'node-name': 'node-format', 'mountpoint': 'TEST_DIR/t.IMGFMT' } }
+{'execute': 'block-export-add',
+ 'arguments': {
+ 'type': 'fuse',
+ 'id': 'export-img',
+ 'node-name': 'node-format',
+ 'mountpoint': 'TEST_DIR/t.IMGFMT'
+ } }
{"return": {}}
Images are identical.
=== Double export ===
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-err', 'node-name': 'node-format', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse' } }
+{'execute': 'block-export-add',
+ 'arguments': {
+ 'type': 'fuse',
+ 'id': 'export-err',
+ 'node-name': 'node-format',
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse'
+ } }
{"error": {"class": "GenericError", "desc": "There already is a FUSE export on 'TEST_DIR/t.IMGFMT.fuse'"}}
=== Remove export ===
virtual size: 64 MiB (67108864 bytes)
-{'execute': 'block-export-del', 'arguments': { 'id': 'export-mp' } }
+{'execute': 'block-export-del',
+ 'arguments': {
+ 'id': 'export-mp'
+ } }
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export-mp"}}
virtual size: 0 B (0 bytes)
=== Writable export ===
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-mp', 'node-name': 'node-format', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true } }
+{'execute': 'block-export-add',
+ 'arguments': {
+ 'type': 'fuse',
+ 'id': 'export-mp',
+ 'node-name': 'node-format',
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true
+ } }
{"return": {}}
write failed: Permission denied
wrote 65536/65536 bytes at offset 1048576
@@ -49,15 +98,30 @@ wrote 65536/65536 bytes at offset 1048576
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== Resizing exports ===
-{'execute': 'block-export-del', 'arguments': { 'id': 'export-mp' } }
+{'execute': 'block-export-del',
+ 'arguments': {
+ 'id': 'export-mp'
+ } }
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export-mp"}}
-{'execute': 'block-export-del', 'arguments': { 'id': 'export-img' } }
+{'execute': 'block-export-del',
+ 'arguments': {
+ 'id': 'export-img'
+ } }
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export-img"}}
-{'execute': 'blockdev-del', 'arguments': { 'node-name': 'node-format' } }
+{'execute': 'blockdev-del',
+ 'arguments': {
+ 'node-name': 'node-format'
+ } }
{"return": {}}
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-mp', 'node-name': 'node-protocol', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true } }
+{'execute': 'block-export-add',
+ 'arguments': {
+ 'type': 'fuse',
+ 'id': 'export-mp',
+ 'node-name': 'node-protocol',
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true
+ } }
{"return": {}}
--- Try growing non-growable export ---
@@ -72,10 +136,19 @@ OK: Post-truncate image size is as expected
OK: Disk usage grew with fallocate
--- Try growing growable export ---
-{'execute': 'block-export-del', 'arguments': { 'id': 'export-mp' } }
+{'execute': 'block-export-del',
+ 'arguments': {
+ 'id': 'export-mp'
+ } }
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export-mp"}}
-{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': 'export-mp', 'node-name': 'node-protocol', 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true, 'growable': true } }
+{'execute': 'block-export-add',
+ 'arguments': {
+ 'type': 'fuse',
+ 'id': 'export-mp',
+ 'node-name': 'node-protocol',
+ 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true, 'growable': true
+ } }
{"return": {}}
65536+0 records in
65536+0 records out
diff --git a/tests/qemu-iotests/312 b/tests/qemu-iotests/312
new file mode 100755
index 0000000000..41340494b0
--- /dev/null
+++ b/tests/qemu-iotests/312
@@ -0,0 +1,159 @@
+#!/usr/bin/env bash
+#
+# Test drive-mirror with quorum
+#
+# The goal of this test is to check how the quorum driver reports
+# regions that are known to read as zeroes (BDRV_BLOCK_ZERO). The idea
+# is that drive-mirror will try the efficient representation of zeroes
+# in the destination image instead of writing actual zeroes.
+#
+# Copyright (C) 2020 Igalia, S.L.
+# Author: Alberto Garcia <berto@igalia.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=berto@igalia.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _rm_test_img "$TEST_IMG.0"
+ _rm_test_img "$TEST_IMG.1"
+ _rm_test_img "$TEST_IMG.2"
+ _rm_test_img "$TEST_IMG.3"
+ _cleanup_qemu
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+_unsupported_imgopts cluster_size data_file
+
+echo
+echo '### Create all images' # three source (quorum), one destination
+echo
+TEST_IMG="$TEST_IMG.0" _make_test_img -o cluster_size=64k 10M
+TEST_IMG="$TEST_IMG.1" _make_test_img -o cluster_size=64k 10M
+TEST_IMG="$TEST_IMG.2" _make_test_img -o cluster_size=64k 10M
+TEST_IMG="$TEST_IMG.3" _make_test_img -o cluster_size=64k 10M
+
+quorum="driver=raw,file.driver=quorum,file.vote-threshold=2"
+quorum="$quorum,file.children.0.file.filename=$TEST_IMG.0"
+quorum="$quorum,file.children.1.file.filename=$TEST_IMG.1"
+quorum="$quorum,file.children.2.file.filename=$TEST_IMG.2"
+quorum="$quorum,file.children.0.driver=$IMGFMT"
+quorum="$quorum,file.children.1.driver=$IMGFMT"
+quorum="$quorum,file.children.2.driver=$IMGFMT"
+
+echo
+echo '### Output of qemu-img map (empty quorum)'
+echo
+$QEMU_IMG map --image-opts $quorum | _filter_qemu_img_map
+
+# Now we write data to the quorum. All three images will read as
+# zeroes in all cases, but with different ways to represent them
+# (unallocated clusters, zero clusters, data clusters with zeroes)
+# that will have an effect on how the data will be mirrored and the
+# output of qemu-img map on the resulting image.
+echo
+echo '### Write data to the quorum'
+echo
+# Test 1: data regions surrounded by unallocated clusters.
+# Three data regions, the largest one (0x30000) will be picked, end result:
+# offset 0x10000, length 0x30000 -> data
+$QEMU_IO -c "write -P 0 $((0x10000)) $((0x10000))" "$TEST_IMG.0" | _filter_qemu_io
+$QEMU_IO -c "write -P 0 $((0x10000)) $((0x30000))" "$TEST_IMG.1" | _filter_qemu_io
+$QEMU_IO -c "write -P 0 $((0x10000)) $((0x20000))" "$TEST_IMG.2" | _filter_qemu_io
+
+# Test 2: zero regions surrounded by data clusters.
+# First we allocate the data clusters.
+$QEMU_IO -c "open -o $quorum" -c "write -P 0 $((0x100000)) $((0x40000))" | _filter_qemu_io
+
+# Three zero regions, the smallest one (0x10000) will be picked, end result:
+# offset 0x100000, length 0x10000 -> data
+# offset 0x110000, length 0x10000 -> zeroes
+# offset 0x120000, length 0x20000 -> data
+$QEMU_IO -c "write -z $((0x110000)) $((0x10000))" "$TEST_IMG.0" | _filter_qemu_io
+$QEMU_IO -c "write -z $((0x110000)) $((0x30000))" "$TEST_IMG.1" | _filter_qemu_io
+$QEMU_IO -c "write -z $((0x110000)) $((0x20000))" "$TEST_IMG.2" | _filter_qemu_io
+
+# Test 3: zero clusters surrounded by unallocated clusters.
+# Everything reads as zeroes, no effect on the end result.
+$QEMU_IO -c "write -z $((0x150000)) $((0x10000))" "$TEST_IMG.0" | _filter_qemu_io
+$QEMU_IO -c "write -z $((0x150000)) $((0x30000))" "$TEST_IMG.1" | _filter_qemu_io
+$QEMU_IO -c "write -z $((0x150000)) $((0x20000))" "$TEST_IMG.2" | _filter_qemu_io
+
+# Test 4: mix of data and zero clusters.
+# The zero region will be ignored in favor of the largest data region
+# (0x20000), end result:
+# offset 0x200000, length 0x20000 -> data
+$QEMU_IO -c "write -P 0 $((0x200000)) $((0x10000))" "$TEST_IMG.0" | _filter_qemu_io
+$QEMU_IO -c "write -z $((0x200000)) $((0x30000))" "$TEST_IMG.1" | _filter_qemu_io
+$QEMU_IO -c "write -P 0 $((0x200000)) $((0x20000))" "$TEST_IMG.2" | _filter_qemu_io
+
+# Test 5: write data to a region and then zeroize it, doing it
+# directly on the quorum device instead of the individual images.
+# This has no effect on the end result but proves that the quorum driver
+# supports 'write -z'.
+$QEMU_IO -c "open -o $quorum" -c "write -P 1 $((0x250000)) $((0x10000))" | _filter_qemu_io
+# Verify the data that we just wrote
+$QEMU_IO -c "open -o $quorum" -c "read -P 1 $((0x250000)) $((0x10000))" | _filter_qemu_io
+$QEMU_IO -c "open -o $quorum" -c "write -z $((0x250000)) $((0x10000))" | _filter_qemu_io
+# Now it should read back as zeroes
+$QEMU_IO -c "open -o $quorum" -c "read -P 0 $((0x250000)) $((0x10000))" | _filter_qemu_io
+
+echo
+echo '### Launch the drive-mirror job'
+echo
+qemu_comm_method="qmp" _launch_qemu -drive if=virtio,"$quorum"
+h=$QEMU_HANDLE
+_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" 'return'
+
+_send_qemu_cmd $h \
+ "{'execute': 'drive-mirror',
+ 'arguments': {'device': 'virtio0',
+ 'format': '$IMGFMT',
+ 'target': '$TEST_IMG.3',
+ 'sync': 'full',
+ 'mode': 'existing' }}" \
+ "BLOCK_JOB_READY.*virtio0"
+
+_send_qemu_cmd $h \
+ "{ 'execute': 'block-job-complete',
+ 'arguments': { 'device': 'virtio0' } }" \
+ 'BLOCK_JOB_COMPLETED'
+
+_send_qemu_cmd $h "{ 'execute': 'quit' }" ''
+
+echo
+echo '### Output of qemu-img map (destination image)'
+echo
+$QEMU_IMG map "$TEST_IMG.3" | _filter_qemu_img_map
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/312.out b/tests/qemu-iotests/312.out
new file mode 100644
index 0000000000..5615146b5c
--- /dev/null
+++ b/tests/qemu-iotests/312.out
@@ -0,0 +1,81 @@
+QA output created by 312
+
+### Create all images
+
+Formatting 'TEST_DIR/t.IMGFMT.0', fmt=IMGFMT size=10485760
+Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=10485760
+Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=10485760
+Formatting 'TEST_DIR/t.IMGFMT.3', fmt=IMGFMT size=10485760
+
+### Output of qemu-img map (empty quorum)
+
+Offset Length File
+
+### Write data to the quorum
+
+wrote 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 196608/196608 bytes at offset 65536
+192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 131072/131072 bytes at offset 65536
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 262144/262144 bytes at offset 1048576
+256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1114112
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 196608/196608 bytes at offset 1114112
+192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 131072/131072 bytes at offset 1114112
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1376256
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 196608/196608 bytes at offset 1376256
+192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 131072/131072 bytes at offset 1376256
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 2097152
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 196608/196608 bytes at offset 2097152
+192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 131072/131072 bytes at offset 2097152
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 2424832
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 65536/65536 bytes at offset 2424832
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 2424832
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 65536/65536 bytes at offset 2424832
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+### Launch the drive-mirror job
+
+{ 'execute': 'qmp_capabilities' }
+{"return": {}}
+{'execute': 'drive-mirror',
+ 'arguments': {'device': 'virtio0',
+ 'format': 'IMGFMT',
+ 'target': 'TEST_DIR/t.IMGFMT.3',
+ 'sync': 'full',
+ 'mode': 'existing' }}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "virtio0"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "virtio0"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "virtio0"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 10485760, "offset": 10485760, "speed": 0, "type": "mirror"}}
+{ 'execute': 'block-job-complete',
+ 'arguments': { 'device': 'virtio0' } }
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "virtio0"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "virtio0"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "virtio0", "len": 10485760, "offset": 10485760, "speed": 0, "type": "mirror"}}
+{ 'execute': 'quit' }
+
+### Output of qemu-img map (destination image)
+
+Offset Length File
+0x10000 0x30000 TEST_DIR/t.IMGFMT.3
+0x100000 0x10000 TEST_DIR/t.IMGFMT.3
+0x120000 0x20000 TEST_DIR/t.IMGFMT.3
+0x200000 0x20000 TEST_DIR/t.IMGFMT.3
+*** done
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index 172ea5752e..268b749e2f 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -37,7 +37,7 @@ _filter_generated_node_ids()
_filter_qom_path()
{
- $SED -e 's#\(Attached to: *\) /.*#\1 PATH#'
+ $SED -e '/Attached to:/s/\device[[0-9]\+\]/device[N]/g'
}
# replace occurrences of the actual TEST_DIR value with TEST_DIR
diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu
index de680cf1c7..ef105dfc39 100644
--- a/tests/qemu-iotests/common.qemu
+++ b/tests/qemu-iotests/common.qemu
@@ -146,14 +146,9 @@ _send_qemu_cmd()
count=${qemu_cmd_repeat}
use_error="no"
fi
- # This array element extraction is done to accommodate pathnames with spaces
- if [ -z "${success_or_failure}" ]; then
- cmd=${@: 1:${#@}-1}
- shift $(($# - 1))
- else
- cmd=${@: 1:${#@}-2}
- shift $(($# - 2))
- fi
+
+ cmd=$1
+ shift
# Display QMP being sent, but not HMP (since HMP already echoes its
# input back to output); decide based on leading '{'
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 9a8394b4cd..e4fb6327ae 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -307,6 +307,7 @@
295 rw
296 rw
297 meta
+298
299 auto quick
300 migration
301 backing quick
@@ -317,3 +318,4 @@
307 rw quick export
308 rw
309 rw auto quick
+312 rw auto quick
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index bcd4fe5b6f..dcdcd0387f 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -205,7 +205,12 @@ def qemu_io_log(*args):
def qemu_io_silent(*args):
'''Run qemu-io and return the exit code, suppressing stdout'''
- args = qemu_io_args + list(args)
+ if '-f' in args or '--image-opts' in args:
+ default_args = qemu_io_args_no_fmt
+ else:
+ default_args = qemu_io_args
+
+ args = default_args + list(args)
exitcode = subprocess.call(args, stdout=open('/dev/null', 'w'))
if exitcode < 0:
sys.stderr.write('qemu-io received signal %i: %s\n' %
@@ -1118,6 +1123,11 @@ def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()) -> None:
if supported_aio_modes and (aiomode not in supported_aio_modes):
notrun('not suitable for this aio mode: %s' % aiomode)
+def _verify_formats(required_formats: Sequence[str] = ()) -> None:
+ usf_list = list(set(required_formats) - set(supported_formats()))
+ if usf_list:
+ notrun(f'formats {usf_list} are not whitelisted')
+
def supports_quorum():
return 'quorum' in qemu_img_pipe('--help')
@@ -1275,7 +1285,8 @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
supported_aio_modes: Sequence[str] = (),
unsupported_fmts: Sequence[str] = (),
supported_protocols: Sequence[str] = (),
- unsupported_protocols: Sequence[str] = ()) -> bool:
+ unsupported_protocols: Sequence[str] = (),
+ required_fmts: Sequence[str] = ()) -> bool:
"""
Perform necessary setup for either script-style or unittest-style tests.
@@ -1301,6 +1312,7 @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
_verify_platform(supported=supported_platforms)
_verify_cache_mode(supported_cache_modes)
_verify_aio_mode(supported_aio_modes)
+ _verify_formats(required_fmts)
return debug
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index e49f3a1e45..8e93b0a707 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -652,27 +652,25 @@ void qmp_fd_vsend_fds(int fd, int *fds, size_t fds_num,
/* No need to send anything for an empty QObject. */
if (qobj) {
int log = getenv("QTEST_LOG") != NULL;
- QString *qstr = qobject_to_json(qobj);
- const char *str;
+ GString *str = qobject_to_json(qobj);
/*
* BUG: QMP doesn't react to input until it sees a newline, an
* object, or an array. Work-around: give it a newline.
*/
- qstring_append_chr(qstr, '\n');
- str = qstring_get_str(qstr);
+ g_string_append_c(str, '\n');
if (log) {
- fprintf(stderr, "%s", str);
+ fprintf(stderr, "%s", str->str);
}
/* Send QMP request */
if (fds && fds_num > 0) {
- socket_send_fds(fd, fds, fds_num, str, qstring_get_length(qstr));
+ socket_send_fds(fd, fds, fds_num, str->str, str->len);
} else {
- socket_send(fd, str, qstring_get_length(qstr));
+ socket_send(fd, str->str, str->len);
}
- qobject_unref(qstr);
+ g_string_free(str, true);
qobject_unref(qobj);
}
}
@@ -1197,9 +1195,9 @@ void qtest_qmp_assert_success(QTestState *qts, const char *fmt, ...)
g_assert(response);
if (!qdict_haskey(response, "return")) {
- QString *s = qobject_to_json_pretty(QOBJECT(response));
- g_test_message("%s", qstring_get_str(s));
- qobject_unref(s);
+ GString *s = qobject_to_json_pretty(QOBJECT(response), true);
+ g_test_message("%s", s->str);
+ g_string_free(s, true);
}
g_assert(qdict_haskey(response, "return"));
qobject_unref(response);
diff --git a/tests/test-clone-visitor.c b/tests/test-clone-visitor.c
index 5e1e8b2f5e..4944b3d857 100644
--- a/tests/test-clone-visitor.c
+++ b/tests/test-clone-visitor.c
@@ -65,16 +65,13 @@ static void test_clone_alternate(void)
static void test_clone_list_union(void)
{
- uint8List *src, *dst;
+ uint8List *src = NULL, *dst;
uint8List *tmp = NULL;
int i;
/* Build list in reverse */
for (i = 10; i; i--) {
- src = g_new0(uint8List, 1);
- src->next = tmp;
- src->value = i;
- tmp = src;
+ QAPI_LIST_PREPEND(src, i);
}
dst = QAPI_CLONE(uint8List, src);
diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
index 1c856d9bd2..b20ab8b29b 100644
--- a/tests/test-qobject-output-visitor.c
+++ b/tests/test-qobject-output-visitor.c
@@ -223,7 +223,8 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
const void *unused)
{
const char *value_str = "list value";
- TestStructList *p, *head = NULL;
+ TestStruct *value;
+ TestStructList *head = NULL;
const int max_items = 10;
bool value_bool = true;
int value_int = 10;
@@ -233,14 +234,12 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
/* Build the list in reverse order... */
for (i = 0; i < max_items; i++) {
- p = g_malloc0(sizeof(*p));
- p->value = g_malloc0(sizeof(*p->value));
- p->value->integer = value_int + (max_items - i - 1);
- p->value->boolean = value_bool;
- p->value->string = g_strdup(value_str);
-
- p->next = head;
- head = p;
+ value = g_malloc0(sizeof(*value));
+ value->integer = value_int + (max_items - i - 1);
+ value->boolean = value_bool;
+ value->string = g_strdup(value_str);
+
+ QAPI_LIST_PREPEND(head, value);
}
visit_type_TestStructList(data->ov, NULL, &head, &error_abort);
@@ -270,26 +269,25 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
const void *unused)
{
- UserDefTwoList *p, *head = NULL;
+ UserDefTwo *value;
+ UserDefTwoList *head = NULL;
const char string[] = "foo bar";
int i, max_count = 1024;
for (i = 0; i < max_count; i++) {
- p = g_malloc0(sizeof(*p));
- p->value = g_malloc0(sizeof(*p->value));
-
- p->value->string0 = g_strdup(string);
- p->value->dict1 = g_new0(UserDefTwoDict, 1);
- p->value->dict1->string1 = g_strdup(string);
- p->value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
- p->value->dict1->dict2->userdef = g_new0(UserDefOne, 1);
- p->value->dict1->dict2->userdef->string = g_strdup(string);
- p->value->dict1->dict2->userdef->integer = 42;
- p->value->dict1->dict2->string = g_strdup(string);
- p->value->dict1->has_dict3 = false;
-
- p->next = head;
- head = p;
+ value = g_malloc0(sizeof(*value));
+
+ value->string0 = g_strdup(string);
+ value->dict1 = g_new0(UserDefTwoDict, 1);
+ value->dict1->string1 = g_strdup(string);
+ value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
+ value->dict1->dict2->userdef = g_new0(UserDefOne, 1);
+ value->dict1->dict2->userdef->string = g_strdup(string);
+ value->dict1->dict2->userdef->integer = 42;
+ value->dict1->dict2->string = g_strdup(string);
+ value->dict1->has_dict3 = false;
+
+ QAPI_LIST_PREPEND(head, value);
}
qapi_free_UserDefTwoList(head);
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index 9f6581439a..0dae04b960 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -130,13 +130,13 @@ static void test_visitor_out_bool(TestOutputVisitorData *data,
static void test_visitor_out_number(TestOutputVisitorData *data,
const void *unused)
{
- double value = 3.14;
+ double value = 3.1415926535897932;
char *str;
visit_type_number(data->ov, NULL, &value, &error_abort);
str = visitor_get(data);
- g_assert_cmpstr(str, ==, "3.140000");
+ g_assert_cmpstr(str, ==, "3.1415926535897931");
}
static void test_visitor_out_string(TestOutputVisitorData *data,
diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
index 1c5a8b94ea..4629958647 100644
--- a/tests/test-visitor-serialization.c
+++ b/tests/test-visitor-serialization.c
@@ -55,7 +55,6 @@ typedef struct PrimitiveType {
int16_t s16;
int32_t s32;
int64_t s64;
- intmax_t max;
} value;
enum PrimitiveTypeKind type;
const char *description;
@@ -307,25 +306,46 @@ static void test_primitives(gconstpointer opaque)
&error_abort);
g_assert(pt_copy != NULL);
- if (pt->type == PTYPE_STRING) {
+ switch (pt->type) {
+ case PTYPE_STRING:
g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
g_free((char *)pt_copy->value.string);
- } else if (pt->type == PTYPE_NUMBER) {
- GString *double_expected = g_string_new("");
- GString *double_actual = g_string_new("");
- /* we serialize with %f for our reference visitors, so rather than fuzzy
- * floating math to test "equality", just compare the formatted values
- */
- g_string_printf(double_expected, "%.6f", pt->value.number);
- g_string_printf(double_actual, "%.6f", pt_copy->value.number);
- g_assert_cmpstr(double_actual->str, ==, double_expected->str);
-
- g_string_free(double_expected, true);
- g_string_free(double_actual, true);
- } else if (pt->type == PTYPE_BOOLEAN) {
- g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max);
- } else {
- g_assert_cmpint(pt->value.max, ==, pt_copy->value.max);
+ break;
+ case PTYPE_BOOLEAN:
+ g_assert_cmpint(pt->value.boolean, ==, pt->value.boolean);
+ break;
+ case PTYPE_NUMBER:
+ g_assert_cmpfloat(pt->value.number, ==, pt_copy->value.number);
+ break;
+ case PTYPE_INTEGER:
+ g_assert_cmpint(pt->value.integer, ==, pt_copy->value.integer);
+ break;
+ case PTYPE_U8:
+ g_assert_cmpuint(pt->value.u8, ==, pt_copy->value.u8);
+ break;
+ case PTYPE_U16:
+ g_assert_cmpuint(pt->value.u16, ==, pt_copy->value.u16);
+ break;
+ case PTYPE_U32:
+ g_assert_cmpuint(pt->value.u32, ==, pt_copy->value.u32);
+ break;
+ case PTYPE_U64:
+ g_assert_cmpuint(pt->value.u64, ==, pt_copy->value.u64);
+ break;
+ case PTYPE_S8:
+ g_assert_cmpint(pt->value.s8, ==, pt_copy->value.s8);
+ break;
+ case PTYPE_S16:
+ g_assert_cmpint(pt->value.s16, ==, pt_copy->value.s16);
+ break;
+ case PTYPE_S32:
+ g_assert_cmpint(pt->value.s32, ==, pt_copy->value.s32);
+ break;
+ case PTYPE_S64:
+ g_assert_cmpint(pt->value.s64, ==, pt_copy->value.s64);
+ break;
+ case PTYPE_EOL:
+ g_assert_not_reached();
}
ops->cleanup(serialize_data);
@@ -351,135 +371,51 @@ static void test_primitive_lists(gconstpointer opaque)
for (i = 0; i < 32; i++) {
switch (pl.type) {
case PTYPE_STRING: {
- strList *tmp = g_new0(strList, 1);
- tmp->value = g_strdup(pt->value.string);
- if (pl.value.strings == NULL) {
- pl.value.strings = tmp;
- } else {
- tmp->next = pl.value.strings;
- pl.value.strings = tmp;
- }
+ QAPI_LIST_PREPEND(pl.value.strings, g_strdup(pt->value.string));
break;
}
case PTYPE_INTEGER: {
- intList *tmp = g_new0(intList, 1);
- tmp->value = pt->value.integer;
- if (pl.value.integers == NULL) {
- pl.value.integers = tmp;
- } else {
- tmp->next = pl.value.integers;
- pl.value.integers = tmp;
- }
+ QAPI_LIST_PREPEND(pl.value.integers, pt->value.integer);
break;
}
case PTYPE_S8: {
- int8List *tmp = g_new0(int8List, 1);
- tmp->value = pt->value.s8;
- if (pl.value.s8_integers == NULL) {
- pl.value.s8_integers = tmp;
- } else {
- tmp->next = pl.value.s8_integers;
- pl.value.s8_integers = tmp;
- }
+ QAPI_LIST_PREPEND(pl.value.s8_integers, pt->value.s8);
break;
}
case PTYPE_S16: {
- int16List *tmp = g_new0(int16List, 1);
- tmp->value = pt->value.s16;
- if (pl.value.s16_integers == NULL) {
- pl.value.s16_integers = tmp;
- } else {
- tmp->next = pl.value.s16_integers;
- pl.value.s16_integers = tmp;
- }
+ QAPI_LIST_PREPEND(pl.value.s16_integers, pt->value.s16);
break;
}
case PTYPE_S32: {
- int32List *tmp = g_new0(int32List, 1);
- tmp->value = pt->value.s32;
- if (pl.value.s32_integers == NULL) {
- pl.value.s32_integers = tmp;
- } else {
- tmp->next = pl.value.s32_integers;
- pl.value.s32_integers = tmp;
- }
+ QAPI_LIST_PREPEND(pl.value.s32_integers, pt->value.s32);
break;
}
case PTYPE_S64: {
- int64List *tmp = g_new0(int64List, 1);
- tmp->value = pt->value.s64;
- if (pl.value.s64_integers == NULL) {
- pl.value.s64_integers = tmp;
- } else {
- tmp->next = pl.value.s64_integers;
- pl.value.s64_integers = tmp;
- }
+ QAPI_LIST_PREPEND(pl.value.s64_integers, pt->value.s64);
break;
}
case PTYPE_U8: {
- uint8List *tmp = g_new0(uint8List, 1);
- tmp->value = pt->value.u8;
- if (pl.value.u8_integers == NULL) {
- pl.value.u8_integers = tmp;
- } else {
- tmp->next = pl.value.u8_integers;
- pl.value.u8_integers = tmp;
- }
+ QAPI_LIST_PREPEND(pl.value.u8_integers, pt->value.u8);
break;
}
case PTYPE_U16: {
- uint16List *tmp = g_new0(uint16List, 1);
- tmp->value = pt->value.u16;
- if (pl.value.u16_integers == NULL) {
- pl.value.u16_integers = tmp;
- } else {
- tmp->next = pl.value.u16_integers;
- pl.value.u16_integers = tmp;
- }
+ QAPI_LIST_PREPEND(pl.value.u16_integers, pt->value.u16);
break;
}
case PTYPE_U32: {
- uint32List *tmp = g_new0(uint32List, 1);
- tmp->value = pt->value.u32;
- if (pl.value.u32_integers == NULL) {
- pl.value.u32_integers = tmp;
- } else {
- tmp->next = pl.value.u32_integers;
- pl.value.u32_integers = tmp;
- }
+ QAPI_LIST_PREPEND(pl.value.u32_integers, pt->value.u32);
break;
}
case PTYPE_U64: {
- uint64List *tmp = g_new0(uint64List, 1);
- tmp->value = pt->value.u64;
- if (pl.value.u64_integers == NULL) {
- pl.value.u64_integers = tmp;
- } else {
- tmp->next = pl.value.u64_integers;
- pl.value.u64_integers = tmp;
- }
+ QAPI_LIST_PREPEND(pl.value.u64_integers, pt->value.u64);
break;
}
case PTYPE_NUMBER: {
- numberList *tmp = g_new0(numberList, 1);
- tmp->value = pt->value.number;
- if (pl.value.numbers == NULL) {
- pl.value.numbers = tmp;
- } else {
- tmp->next = pl.value.numbers;
- pl.value.numbers = tmp;
- }
+ QAPI_LIST_PREPEND(pl.value.numbers, pt->value.number);
break;
}
case PTYPE_BOOLEAN: {
- boolList *tmp = g_new0(boolList, 1);
- tmp->value = pt->value.boolean;
- if (pl.value.booleans == NULL) {
- pl.value.booleans = tmp;
- } else {
- tmp->next = pl.value.booleans;
- pl.value.booleans = tmp;
- }
+ QAPI_LIST_PREPEND(pl.value.booleans, pt->value.boolean);
break;
}
default:
@@ -704,10 +640,7 @@ static void test_nested_struct_list(gconstpointer opaque)
int i = 0;
for (i = 0; i < 8; i++) {
- tmp = g_new0(UserDefTwoList, 1);
- tmp->value = nested_struct_create();
- tmp->next = listp;
- listp = tmp;
+ QAPI_LIST_PREPEND(listp, nested_struct_create());
}
ops->serialize(listp, &serialize_data, visit_nested_struct_list,
@@ -790,10 +723,6 @@ static PrimitiveType pt_values[] = {
.value.boolean = 0,
},
/* number tests (double) */
- /* note: we format these to %.6f before comparing, since that's how
- * we serialize them and it doesn't make sense to check precision
- * beyond that.
- */
{
.description = "number_sanity1",
.type = PTYPE_NUMBER,
@@ -802,7 +731,7 @@ static PrimitiveType pt_values[] = {
{
.description = "number_sanity2",
.type = PTYPE_NUMBER,
- .value.number = 3.14159265,
+ .value.number = 3.141593,
},
{
.description = "number_min",
@@ -1028,15 +957,15 @@ static void qmp_deserialize(void **native_out, void *datap,
VisitorFunc visit, Error **errp)
{
QmpSerializeData *d = datap;
- QString *output_json;
+ GString *output_json;
QObject *obj_orig, *obj;
visit_complete(d->qov, &d->obj);
obj_orig = d->obj;
output_json = qobject_to_json(obj_orig);
- obj = qobject_from_json(qstring_get_str(output_json), &error_abort);
+ obj = qobject_from_json(output_json->str, &error_abort);
- qobject_unref(output_json);
+ g_string_free(output_json, true);
d->qiv = qobject_input_visitor_new(obj);
qobject_unref(obj_orig);
qobject_unref(obj);
diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c
index d4119e92ab..e94b71110b 100644
--- a/tools/virtiofsd/fuse_lowlevel.c
+++ b/tools/virtiofsd/fuse_lowlevel.c
@@ -2143,104 +2143,6 @@ static void do_destroy(fuse_req_t req, fuse_ino_t nodeid,
send_reply_ok(req, NULL, 0);
}
-static int send_notify_iov(struct fuse_session *se, int notify_code,
- struct iovec *iov, int count)
-{
- struct fuse_out_header out = {
- .error = notify_code,
- };
-
- if (!se->got_init) {
- return -ENOTCONN;
- }
-
- iov[0].iov_base = &out;
- iov[0].iov_len = sizeof(struct fuse_out_header);
-
- return fuse_send_msg(se, NULL, iov, count);
-}
-
-int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
-{
- if (ph != NULL) {
- struct fuse_notify_poll_wakeup_out outarg = {
- .kh = ph->kh,
- };
- struct iovec iov[2];
-
- iov[1].iov_base = &outarg;
- iov[1].iov_len = sizeof(outarg);
-
- return send_notify_iov(ph->se, FUSE_NOTIFY_POLL, iov, 2);
- } else {
- return 0;
- }
-}
-
-int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, fuse_ino_t ino,
- off_t off, off_t len)
-{
- struct fuse_notify_inval_inode_out outarg = {
- .ino = ino,
- .off = off,
- .len = len,
- };
- struct iovec iov[2];
-
- if (!se) {
- return -EINVAL;
- }
-
- iov[1].iov_base = &outarg;
- iov[1].iov_len = sizeof(outarg);
-
- return send_notify_iov(se, FUSE_NOTIFY_INVAL_INODE, iov, 2);
-}
-
-int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t parent,
- const char *name, size_t namelen)
-{
- struct fuse_notify_inval_entry_out outarg = {
- .parent = parent,
- .namelen = namelen,
- };
- struct iovec iov[3];
-
- if (!se) {
- return -EINVAL;
- }
-
- iov[1].iov_base = &outarg;
- iov[1].iov_len = sizeof(outarg);
- iov[2].iov_base = (void *)name;
- iov[2].iov_len = namelen + 1;
-
- return send_notify_iov(se, FUSE_NOTIFY_INVAL_ENTRY, iov, 3);
-}
-
-int fuse_lowlevel_notify_delete(struct fuse_session *se, fuse_ino_t parent,
- fuse_ino_t child, const char *name,
- size_t namelen)
-{
- struct fuse_notify_delete_out outarg = {
- .parent = parent,
- .child = child,
- .namelen = namelen,
- };
- struct iovec iov[3];
-
- if (!se) {
- return -EINVAL;
- }
-
- iov[1].iov_base = &outarg;
- iov[1].iov_len = sizeof(outarg);
- iov[2].iov_base = (void *)name;
- iov[2].iov_len = namelen + 1;
-
- return send_notify_iov(se, FUSE_NOTIFY_DELETE, iov, 3);
-}
-
int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino,
off_t offset, struct fuse_bufvec *bufv)
{
diff --git a/tools/virtiofsd/fuse_virtio.c b/tools/virtiofsd/fuse_virtio.c
index b264dcbd18..ddcefee427 100644
--- a/tools/virtiofsd/fuse_virtio.c
+++ b/tools/virtiofsd/fuse_virtio.c
@@ -578,13 +578,18 @@ static void *fv_queue_thread(void *opaque)
struct VuDev *dev = &qi->virtio_dev->dev;
struct VuVirtq *q = vu_get_queue(dev, qi->qidx);
struct fuse_session *se = qi->virtio_dev->se;
- GThreadPool *pool;
-
- pool = g_thread_pool_new(fv_queue_worker, qi, se->thread_pool_size, FALSE,
- NULL);
- if (!pool) {
- fuse_log(FUSE_LOG_ERR, "%s: g_thread_pool_new failed\n", __func__);
- return NULL;
+ GThreadPool *pool = NULL;
+ GList *req_list = NULL;
+
+ if (se->thread_pool_size) {
+ fuse_log(FUSE_LOG_DEBUG, "%s: Creating thread pool for Queue %d\n",
+ __func__, qi->qidx);
+ pool = g_thread_pool_new(fv_queue_worker, qi, se->thread_pool_size,
+ FALSE, NULL);
+ if (!pool) {
+ fuse_log(FUSE_LOG_ERR, "%s: g_thread_pool_new failed\n", __func__);
+ return NULL;
+ }
}
fuse_log(FUSE_LOG_INFO, "%s: Start for queue %d kick_fd %d\n", __func__,
@@ -659,14 +664,27 @@ static void *fv_queue_thread(void *opaque)
req->reply_sent = false;
- g_thread_pool_push(pool, req, NULL);
+ if (!se->thread_pool_size) {
+ req_list = g_list_prepend(req_list, req);
+ } else {
+ g_thread_pool_push(pool, req, NULL);
+ }
}
pthread_mutex_unlock(&qi->vq_lock);
pthread_rwlock_unlock(&qi->virtio_dev->vu_dispatch_rwlock);
+
+ /* Process all the requests. */
+ if (!se->thread_pool_size && req_list != NULL) {
+ g_list_foreach(req_list, fv_queue_worker, qi);
+ g_list_free(req_list);
+ req_list = NULL;
+ }
}
- g_thread_pool_free(pool, FALSE, TRUE);
+ if (pool) {
+ g_thread_pool_free(pool, FALSE, TRUE);
+ }
return NULL;
}
diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index 12de321745..5fb36d9407 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -101,7 +101,7 @@ struct lo_inode {
* This counter keeps the inode alive during the FUSE session.
* Incremented when the FUSE inode number is sent in a reply
* (FUSE_LOOKUP, FUSE_READDIRPLUS, etc). Decremented when an inode is
- * released by requests like FUSE_FORGET, FUSE_RMDIR, FUSE_RENAME, etc.
+ * released by a FUSE_FORGET request.
*
* Note that this value is untrusted because the client can manipulate
* it arbitrarily using FUSE_FORGET requests.
@@ -902,10 +902,11 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
inode->key.ino = e->attr.st_ino;
inode->key.dev = e->attr.st_dev;
inode->key.mnt_id = mnt_id;
- pthread_mutex_init(&inode->plock_mutex, NULL);
- inode->posix_locks = g_hash_table_new_full(
- g_direct_hash, g_direct_equal, NULL, posix_locks_value_destroy);
-
+ if (lo->posix_lock) {
+ pthread_mutex_init(&inode->plock_mutex, NULL);
+ inode->posix_locks = g_hash_table_new_full(
+ g_direct_hash, g_direct_equal, NULL, posix_locks_value_destroy);
+ }
pthread_mutex_lock(&lo->mutex);
inode->fuse_ino = lo_add_inode_mapping(req, inode);
g_hash_table_insert(lo->inodes, &inode->key, inode);
@@ -1291,12 +1292,13 @@ static void unref_inode(struct lo_data *lo, struct lo_inode *inode, uint64_t n)
if (!inode->nlookup) {
lo_map_remove(&lo->ino_map, inode->fuse_ino);
g_hash_table_remove(lo->inodes, &inode->key);
- if (g_hash_table_size(inode->posix_locks)) {
- fuse_log(FUSE_LOG_WARNING, "Hash table is not empty\n");
+ if (lo->posix_lock) {
+ if (g_hash_table_size(inode->posix_locks)) {
+ fuse_log(FUSE_LOG_WARNING, "Hash table is not empty\n");
+ }
+ g_hash_table_destroy(inode->posix_locks);
+ pthread_mutex_destroy(&inode->plock_mutex);
}
- g_hash_table_destroy(inode->posix_locks);
- pthread_mutex_destroy(&inode->plock_mutex);
-
/* Drop our refcount from lo_do_lookup() */
lo_inode_put(lo, &inode);
}
@@ -1772,6 +1774,11 @@ static void lo_getlk(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi,
ino, fi->flags, fi->lock_owner, lock->l_type, lock->l_start,
lock->l_len);
+ if (!lo->posix_lock) {
+ fuse_reply_err(req, ENOSYS);
+ return;
+ }
+
inode = lo_inode(req, ino);
if (!inode) {
fuse_reply_err(req, EBADF);
@@ -1817,6 +1824,11 @@ static void lo_setlk(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi,
ino, fi->flags, lock->l_type, lock->l_pid, fi->lock_owner, sleep,
lock->l_whence, lock->l_start, lock->l_len);
+ if (!lo->posix_lock) {
+ fuse_reply_err(req, ENOSYS);
+ return;
+ }
+
if (sleep) {
fuse_reply_err(req, EOPNOTSUPP);
return;
@@ -1941,6 +1953,7 @@ static void lo_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
int res;
(void)ino;
struct lo_inode *inode;
+ struct lo_data *lo = lo_data(req);
inode = lo_inode(req, ino);
if (!inode) {
@@ -1948,13 +1961,21 @@ static void lo_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
return;
}
- /* An fd is going away. Cleanup associated posix locks */
- pthread_mutex_lock(&inode->plock_mutex);
- g_hash_table_remove(inode->posix_locks, GUINT_TO_POINTER(fi->lock_owner));
- pthread_mutex_unlock(&inode->plock_mutex);
+ if (!S_ISREG(inode->filetype)) {
+ lo_inode_put(lo, &inode);
+ fuse_reply_err(req, EBADF);
+ return;
+ }
+ /* An fd is going away. Cleanup associated posix locks */
+ if (lo->posix_lock) {
+ pthread_mutex_lock(&inode->plock_mutex);
+ g_hash_table_remove(inode->posix_locks,
+ GUINT_TO_POINTER(fi->lock_owner));
+ pthread_mutex_unlock(&inode->plock_mutex);
+ }
res = close(dup(lo_fi_fd(req, fi)));
- lo_inode_put(lo_data(req), &inode);
+ lo_inode_put(lo, &inode);
fuse_reply_err(req, res == -1 ? errno : 0);
}
@@ -3284,18 +3305,38 @@ static void setup_nofile_rlimit(unsigned long rlimit_nofile)
static void log_func(enum fuse_log_level level, const char *fmt, va_list ap)
{
g_autofree char *localfmt = NULL;
+ struct timespec ts;
+ struct tm tm;
+ char sec_fmt[sizeof "2020-12-07 18:17:54"];
+ char zone_fmt[sizeof "+0100"];
if (current_log_level < level) {
return;
}
if (current_log_level == FUSE_LOG_DEBUG) {
- if (!use_syslog) {
- localfmt = g_strdup_printf("[%" PRId64 "] [ID: %08ld] %s",
- get_clock(), syscall(__NR_gettid), fmt);
- } else {
+ if (use_syslog) {
+ /* no timestamp needed */
localfmt = g_strdup_printf("[ID: %08ld] %s", syscall(__NR_gettid),
fmt);
+ } else {
+ /* try formatting a broken-down timestamp */
+ if (clock_gettime(CLOCK_REALTIME, &ts) != -1 &&
+ localtime_r(&ts.tv_sec, &tm) != NULL &&
+ strftime(sec_fmt, sizeof sec_fmt, "%Y-%m-%d %H:%M:%S",
+ &tm) != 0 &&
+ strftime(zone_fmt, sizeof zone_fmt, "%z", &tm) != 0) {
+ localfmt = g_strdup_printf("[%s.%02ld%s] [ID: %08ld] %s",
+ sec_fmt,
+ ts.tv_nsec / (10L * 1000 * 1000),
+ zone_fmt, syscall(__NR_gettid),
+ fmt);
+ } else {
+ /* fall back to a flat timestamp */
+ localfmt = g_strdup_printf("[%" PRId64 "] [ID: %08ld] %s",
+ get_clock(), syscall(__NR_gettid),
+ fmt);
+ }
}
fmt = localfmt;
}
@@ -3360,6 +3401,11 @@ static void setup_root(struct lo_data *lo, struct lo_inode *root)
root->key.mnt_id = mnt_id;
root->nlookup = 2;
g_atomic_int_set(&root->refcount, 2);
+ if (lo->posix_lock) {
+ pthread_mutex_init(&root->plock_mutex, NULL);
+ root->posix_locks = g_hash_table_new_full(
+ g_direct_hash, g_direct_equal, NULL, posix_locks_value_destroy);
+ }
}
static guint lo_key_hash(gconstpointer key)
@@ -3382,6 +3428,10 @@ static void fuse_lo_data_cleanup(struct lo_data *lo)
if (lo->inodes) {
g_hash_table_destroy(lo->inodes);
}
+
+ if (lo->root.posix_locks) {
+ g_hash_table_destroy(lo->root.posix_locks);
+ }
lo_map_destroy(&lo->fd_map);
lo_map_destroy(&lo->dirp_map);
lo_map_destroy(&lo->ino_map);
@@ -3416,6 +3466,9 @@ int main(int argc, char *argv[])
struct lo_map_elem *reserve_elem;
int ret = -1;
+ /* Initialize time conversion information for localtime_r(). */
+ tzset();
+
/* Don't mask creation mode, kernel already did that */
umask(0);
diff --git a/trace/qmp.c b/trace/qmp.c
index 38246e1aa6..85f81e47cc 100644
--- a/trace/qmp.c
+++ b/trace/qmp.c
@@ -92,39 +92,37 @@ TraceEventInfoList *qmp_trace_event_get_state(const char *name,
/* Get states (all errors checked above) */
trace_event_iter_init(&iter, name);
while ((ev = trace_event_iter_next(&iter)) != NULL) {
- TraceEventInfoList *elem;
+ TraceEventInfo *value;
bool is_vcpu = trace_event_is_vcpu(ev);
if (has_vcpu && !is_vcpu) {
continue;
}
- elem = g_new(TraceEventInfoList, 1);
- elem->value = g_new(TraceEventInfo, 1);
- elem->value->vcpu = is_vcpu;
- elem->value->name = g_strdup(trace_event_get_name(ev));
+ value = g_new(TraceEventInfo, 1);
+ value->vcpu = is_vcpu;
+ value->name = g_strdup(trace_event_get_name(ev));
if (!trace_event_get_state_static(ev)) {
- elem->value->state = TRACE_EVENT_STATE_UNAVAILABLE;
+ value->state = TRACE_EVENT_STATE_UNAVAILABLE;
} else {
if (has_vcpu) {
if (is_vcpu) {
if (trace_event_get_vcpu_state_dynamic(cpu, ev)) {
- elem->value->state = TRACE_EVENT_STATE_ENABLED;
+ value->state = TRACE_EVENT_STATE_ENABLED;
} else {
- elem->value->state = TRACE_EVENT_STATE_DISABLED;
+ value->state = TRACE_EVENT_STATE_DISABLED;
}
}
/* else: already skipped above */
} else {
if (trace_event_get_state_dynamic(ev)) {
- elem->value->state = TRACE_EVENT_STATE_ENABLED;
+ value->state = TRACE_EVENT_STATE_ENABLED;
} else {
- elem->value->state = TRACE_EVENT_STATE_DISABLED;
+ value->state = TRACE_EVENT_STATE_DISABLED;
}
}
}
- elem->next = events;
- events = elem;
+ QAPI_LIST_PREPEND(events, value);
}
return events;
diff --git a/ui/input.c b/ui/input.c
index 4791b089c7..8ac407dec4 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -571,7 +571,7 @@ void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
MouseInfoList *qmp_query_mice(Error **errp)
{
MouseInfoList *mice_list = NULL;
- MouseInfoList *info;
+ MouseInfo *info;
QemuInputHandlerState *s;
bool current = true;
@@ -581,16 +581,14 @@ MouseInfoList *qmp_query_mice(Error **errp)
continue;
}
- info = g_new0(MouseInfoList, 1);
- info->value = g_new0(MouseInfo, 1);
- info->value->index = s->id;
- info->value->name = g_strdup(s->handler->name);
- info->value->absolute = s->handler->mask & INPUT_EVENT_MASK_ABS;
- info->value->current = current;
+ info = g_new0(MouseInfo, 1);
+ info->index = s->id;
+ info->name = g_strdup(s->handler->name);
+ info->absolute = s->handler->mask & INPUT_EVENT_MASK_ABS;
+ info->current = current;
current = false;
- info->next = mice_list;
- mice_list = info;
+ QAPI_LIST_PREPEND(mice_list, info);
}
return mice_list;
diff --git a/ui/vnc.c b/ui/vnc.c
index 34e6dc437c..7452ac7df2 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -365,14 +365,11 @@ static VncDisplay *vnc_display_find(const char *id)
static VncClientInfoList *qmp_query_client_list(VncDisplay *vd)
{
- VncClientInfoList *cinfo, *prev = NULL;
+ VncClientInfoList *prev = NULL;
VncState *client;
QTAILQ_FOREACH(client, &vd->clients, next) {
- cinfo = g_new0(VncClientInfoList, 1);
- cinfo->value = qmp_query_vnc_client(client);
- cinfo->next = prev;
- prev = cinfo;
+ QAPI_LIST_PREPEND(prev, qmp_query_vnc_client(client));
}
return prev;
}
@@ -453,7 +450,6 @@ static VncServerInfo2List *qmp_query_server_entry(QIOChannelSocket *ioc,
int subauth,
VncServerInfo2List *prev)
{
- VncServerInfo2List *list;
VncServerInfo2 *info;
Error *err = NULL;
SocketAddress *addr;
@@ -476,10 +472,8 @@ static VncServerInfo2List *qmp_query_server_entry(QIOChannelSocket *ioc,
qmp_query_auth(auth, subauth, &info->auth,
&info->vencrypt, &info->has_vencrypt);
- list = g_new0(VncServerInfo2List, 1);
- list->value = info;
- list->next = prev;
- return list;
+ QAPI_LIST_PREPEND(prev, info);
+ return prev;
}
static void qmp_query_auth(int auth, int subauth,
@@ -554,7 +548,7 @@ static void qmp_query_auth(int auth, int subauth,
VncInfo2List *qmp_query_vnc_servers(Error **errp)
{
- VncInfo2List *item, *prev = NULL;
+ VncInfo2List *prev = NULL;
VncInfo2 *info;
VncDisplay *vd;
DeviceState *dev;
@@ -583,10 +577,7 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp)
vd->ws_subauth, info->server);
}
- item = g_new0(VncInfo2List, 1);
- item->value = info;
- item->next = prev;
- prev = item;
+ QAPI_LIST_PREPEND(prev, info);
}
return prev;
}
diff --git a/util/keyval.c b/util/keyval.c
index 7f625ad33c..be34928813 100644
--- a/util/keyval.c
+++ b/util/keyval.c
@@ -189,7 +189,7 @@ static const char *keyval_parse_one(QDict *qdict, const char *params,
QDict *cur;
int ret;
QObject *next;
- QString *val;
+ GString *val;
key = params;
val_end = NULL;
@@ -263,7 +263,7 @@ static const char *keyval_parse_one(QDict *qdict, const char *params,
if (key == implied_key) {
assert(!*s);
- val = qstring_from_substr(params, 0, val_end - params);
+ val = g_string_new_len(params, val_end - params);
s = val_end;
if (*s == ',') {
s++;
@@ -276,7 +276,7 @@ static const char *keyval_parse_one(QDict *qdict, const char *params,
}
s++;
- val = qstring_new();
+ val = g_string_new(NULL);
for (;;) {
if (!*s) {
break;
@@ -286,11 +286,12 @@ static const char *keyval_parse_one(QDict *qdict, const char *params,
break;
}
}
- qstring_append_chr(val, *s++);
+ g_string_append_c(val, *s++);
}
}
- if (!keyval_parse_put(cur, key_in_cur, val, key, key_end, errp)) {
+ if (!keyval_parse_put(cur, key_in_cur, qstring_from_gstring(val),
+ key, key_end, errp)) {
return NULL;
}
return s;
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 725e3d7e4b..e2a700b284 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -55,7 +55,7 @@ QemuOpts *qemu_find_opts_singleton(const char *group)
static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc)
{
- CommandLineParameterInfoList *param_list = NULL, *entry;
+ CommandLineParameterInfoList *param_list = NULL;
CommandLineParameterInfo *info;
int i;
@@ -87,10 +87,7 @@ static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc)
info->q_default = g_strdup(desc[i].def_value_str);
}
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = param_list;
- param_list = entry;
+ QAPI_LIST_PREPEND(param_list, info);
}
return param_list;
@@ -246,7 +243,7 @@ CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option,
const char *option,
Error **errp)
{
- CommandLineOptionInfoList *conf_list = NULL, *entry;
+ CommandLineOptionInfoList *conf_list = NULL;
CommandLineOptionInfo *info;
int i;
@@ -262,10 +259,7 @@ CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option,
info->parameters =
query_option_descs(vm_config_groups[i]->desc);
}
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
- entry->next = conf_list;
- conf_list = entry;
+ QAPI_LIST_PREPEND(conf_list, info);
}
}