summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorSeokYeon Hwang <syeon.hwang@samsung.com>2016-11-30 14:11:48 +0900
committerSeokYeon Hwang <syeon.hwang@samsung.com>2016-11-30 14:11:58 +0900
commit2371603ef207b015cc29728296b21cb1722d8ae6 (patch)
tree25cbb62daf29066fa874b9a4b8f754bc18187806 /tests
parentd5df306aedcc13cf5a2463ddf858c8d718a788d5 (diff)
parentd4dcb59384ab4433702f015fdddda1eff8e3927f (diff)
downloadqemu-2371603ef207b015cc29728296b21cb1722d8ae6.tar.gz
qemu-2371603ef207b015cc29728296b21cb1722d8ae6.tar.bz2
qemu-2371603ef207b015cc29728296b21cb1722d8ae6.zip
Merge branch 'develop_qemu_2.7' into develop
Change-Id: Ibae70e3c0d1d88632903f98be114f47af9ca7502 Signed-off-by: SeokYeon Hwang <syeon.hwang@samsung.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitignore6
-rw-r--r--tests/Makefile.include (renamed from tests/Makefile)75
-rw-r--r--tests/ac97-test.c1
-rw-r--r--tests/acpi-test-data/pc/APIC.cphpbin0 -> 160 bytes
-rw-r--r--tests/acpi-test-data/pc/DSDTbin5587 -> 6008 bytes
-rw-r--r--tests/acpi-test-data/pc/DSDT.bridgebin7446 -> 7867 bytes
-rw-r--r--tests/acpi-test-data/pc/DSDT.cphpbin0 -> 6435 bytes
-rw-r--r--tests/acpi-test-data/pc/DSDT.ipmikcsbin0 -> 6080 bytes
-rw-r--r--tests/acpi-test-data/q35/APIC.cphpbin0 -> 160 bytes
-rw-r--r--tests/acpi-test-data/q35/DSDTbin8357 -> 8770 bytes
-rw-r--r--tests/acpi-test-data/q35/DSDT.bridgebin8374 -> 8787 bytes
-rw-r--r--tests/acpi-test-data/q35/DSDT.cphpbin0 -> 9197 bytes
-rw-r--r--tests/acpi-test-data/q35/DSDT.ipmibtbin0 -> 8845 bytes
-rw-r--r--tests/ahci-test.c35
-rw-r--r--tests/bios-tables-test.c107
-rw-r--r--tests/boot-order-test.c1
-rw-r--r--tests/boot-sector.h6
-rw-r--r--tests/check-qdict.c1
-rw-r--r--tests/check-qfloat.c1
-rw-r--r--tests/check-qint.c1
-rw-r--r--tests/check-qjson.c11
-rw-r--r--tests/check-qlist.c1
-rw-r--r--tests/check-qnull.c73
-rw-r--r--tests/check-qom-interface.c1
-rw-r--r--tests/check-qom-proplist.c1
-rw-r--r--tests/check-qstring.c1
-rw-r--r--tests/data/test-qga-config8
-rw-r--r--tests/device-introspect-test.c1
-rw-r--r--tests/display-vga-test.c7
-rw-r--r--tests/docker/Makefile.include128
-rwxr-xr-xtests/docker/common.rc33
-rwxr-xr-xtests/docker/docker.py335
-rw-r--r--tests/docker/dockerfiles/centos6.docker6
-rw-r--r--tests/docker/dockerfiles/debian-bootstrap.docker21
-rwxr-xr-xtests/docker/dockerfiles/debian-bootstrap.pre87
-rw-r--r--tests/docker/dockerfiles/fedora.docker7
-rw-r--r--tests/docker/dockerfiles/ubuntu.docker11
-rwxr-xr-xtests/docker/run68
-rwxr-xr-xtests/docker/test-clang24
-rwxr-xr-xtests/docker/test-full17
-rwxr-xr-xtests/docker/test-mingw34
-rwxr-xr-xtests/docker/test-quick19
-rwxr-xr-xtests/docker/travis21
-rwxr-xr-xtests/docker/travis.py48
-rw-r--r--tests/drive_del-test.c4
-rw-r--r--tests/ds1338-test.c2
-rw-r--r--tests/e1000-test.c1
-rw-r--r--tests/e1000e-test.c478
-rw-r--r--tests/eepro100-test.c1
-rw-r--r--tests/endianness-test.c6
-rw-r--r--tests/es1370-test.c1
-rw-r--r--tests/fdc-test.c1
-rw-r--r--tests/fw_cfg-test.c1
-rw-r--r--tests/hd-geo-test.c1
-rw-r--r--tests/i440fx-test.c6
-rw-r--r--tests/i82801b11-test.c1
-rw-r--r--tests/ide-test.c45
-rw-r--r--tests/intel-hda-test.c7
-rw-r--r--tests/ioh3420-test.c1
-rw-r--r--tests/ipmi-bt-test.c1
-rw-r--r--tests/ipmi-kcs-test.c1
-rw-r--r--tests/ipoctal232-test.c1
-rw-r--r--tests/ivshmem-test.c2
-rw-r--r--tests/libqos/ahci.c1
-rw-r--r--tests/libqos/ahci.h4
-rw-r--r--tests/libqos/fw_cfg.c1
-rw-r--r--tests/libqos/i2c-imx.c1
-rw-r--r--tests/libqos/i2c-omap.c1
-rw-r--r--tests/libqos/libqos-pc.h4
-rw-r--r--tests/libqos/libqos.c1
-rw-r--r--tests/libqos/libqos.h4
-rw-r--r--tests/libqos/malloc-generic.c1
-rw-r--r--tests/libqos/malloc-pc.c1
-rw-r--r--tests/libqos/malloc.c2
-rw-r--r--tests/libqos/pci-pc.c1
-rw-r--r--tests/libqos/pci.c1
-rw-r--r--tests/libqos/usb.c1
-rw-r--r--tests/libqos/virtio-mmio.c14
-rw-r--r--tests/libqos/virtio-pci.c61
-rw-r--r--tests/libqos/virtio-pci.h17
-rw-r--r--tests/libqos/virtio.c49
-rw-r--r--tests/libqos/virtio.h78
-rw-r--r--tests/libqtest.c3
-rw-r--r--tests/m48t59-test.c1
-rw-r--r--tests/migration/.gitignore2
-rwxr-xr-xtests/migration/guestperf-batch.py26
-rwxr-xr-xtests/migration/guestperf-plot.py26
-rwxr-xr-xtests/migration/guestperf.py27
-rw-r--r--tests/migration/guestperf/__init__.py0
-rw-r--r--tests/migration/guestperf/comparison.py124
-rw-r--r--tests/migration/guestperf/engine.py439
-rw-r--r--tests/migration/guestperf/hardware.py62
-rw-r--r--tests/migration/guestperf/plot.py623
-rw-r--r--tests/migration/guestperf/progress.py117
-rw-r--r--tests/migration/guestperf/report.py98
-rw-r--r--tests/migration/guestperf/scenario.py95
-rw-r--r--tests/migration/guestperf/shell.py255
-rw-r--r--tests/migration/guestperf/timings.py55
-rw-r--r--tests/migration/stress.c367
-rw-r--r--tests/ne2000-test.c1
-rw-r--r--tests/nvme-test.c1
-rw-r--r--tests/pc-cpu-test.c1
-rw-r--r--tests/pcnet-test.c1
-rw-r--r--tests/postcopy-test.c530
-rw-r--r--tests/prom-env-test.c90
-rw-r--r--tests/pvpanic-test.c1
-rw-r--r--tests/pxe-test.c1
-rw-r--r--tests/q35-test.c1
-rw-r--r--tests/qapi-schema/args-bad-boxed.err1
-rw-r--r--tests/qapi-schema/args-bad-boxed.exit1
-rw-r--r--tests/qapi-schema/args-bad-boxed.json2
-rw-r--r--tests/qapi-schema/args-bad-boxed.out0
-rw-r--r--tests/qapi-schema/args-boxed-anon.err1
-rw-r--r--tests/qapi-schema/args-boxed-anon.exit1
-rw-r--r--tests/qapi-schema/args-boxed-anon.json2
-rw-r--r--tests/qapi-schema/args-boxed-anon.out0
-rw-r--r--tests/qapi-schema/args-boxed-empty.err1
-rw-r--r--tests/qapi-schema/args-boxed-empty.exit1
-rw-r--r--tests/qapi-schema/args-boxed-empty.json3
-rw-r--r--tests/qapi-schema/args-boxed-empty.out0
-rw-r--r--tests/qapi-schema/args-boxed-string.err1
-rw-r--r--tests/qapi-schema/args-boxed-string.exit1
-rw-r--r--tests/qapi-schema/args-boxed-string.json2
-rw-r--r--tests/qapi-schema/args-boxed-string.out0
-rw-r--r--tests/qapi-schema/args-union.err2
-rw-r--r--tests/qapi-schema/args-union.json3
-rw-r--r--tests/qapi-schema/event-boxed-empty.err1
-rw-r--r--tests/qapi-schema/event-boxed-empty.exit1
-rw-r--r--tests/qapi-schema/event-boxed-empty.json2
-rw-r--r--tests/qapi-schema/event-boxed-empty.out0
-rw-r--r--tests/qapi-schema/event-case.out1
-rw-r--r--tests/qapi-schema/flat-union-incomplete-branch.err1
-rw-r--r--tests/qapi-schema/flat-union-incomplete-branch.exit1
-rw-r--r--tests/qapi-schema/flat-union-incomplete-branch.json9
-rw-r--r--tests/qapi-schema/flat-union-incomplete-branch.out0
-rw-r--r--tests/qapi-schema/ident-with-escape.out2
-rw-r--r--tests/qapi-schema/indented-expr.out4
-rw-r--r--tests/qapi-schema/qapi-schema-test.json4
-rw-r--r--tests/qapi-schema/qapi-schema-test.out37
-rw-r--r--tests/qapi-schema/test-qapi.py11
-rwxr-xr-xtests/qemu-iotests/0042
-rwxr-xr-xtests/qemu-iotests/0125
-rw-r--r--tests/qemu-iotests/023.out2160
-rw-r--r--tests/qemu-iotests/026.out50
-rw-r--r--tests/qemu-iotests/026.out.nocache50
-rwxr-xr-xtests/qemu-iotests/0342
-rw-r--r--tests/qemu-iotests/039.out20
-rwxr-xr-xtests/qemu-iotests/04157
-rwxr-xr-xtests/qemu-iotests/04826
-rw-r--r--tests/qemu-iotests/048.out6
-rwxr-xr-xtests/qemu-iotests/0524
-rw-r--r--tests/qemu-iotests/052.out4
-rw-r--r--tests/qemu-iotests/061.out8
-rw-r--r--tests/qemu-iotests/071.out8
-rwxr-xr-xtests/qemu-iotests/07712
-rw-r--r--tests/qemu-iotests/077.out26
-rwxr-xr-xtests/qemu-iotests/0834
-rw-r--r--tests/qemu-iotests/087.out12
-rw-r--r--tests/qemu-iotests/089.out2
-rwxr-xr-xtests/qemu-iotests/09398
-rw-r--r--tests/qemu-iotests/093.out4
-rwxr-xr-xtests/qemu-iotests/0952
-rw-r--r--tests/qemu-iotests/0963
-rwxr-xr-xtests/qemu-iotests/100145
-rw-r--r--tests/qemu-iotests/100.out89
-rwxr-xr-xtests/qemu-iotests/1094
-rw-r--r--tests/qemu-iotests/109.out12
-rw-r--r--tests/qemu-iotests/13635
-rw-r--r--tests/qemu-iotests/136.out4
-rw-r--r--tests/qemu-iotests/137.out4
-rw-r--r--tests/qemu-iotests/141.out4
-rw-r--r--tests/qemu-iotests/144.out2
-rwxr-xr-xtests/qemu-iotests/14912
-rw-r--r--tests/qemu-iotests/149.out240
-rwxr-xr-xtests/qemu-iotests/154305
-rw-r--r--tests/qemu-iotests/154.out285
-rwxr-xr-xtests/qemu-iotests/155261
-rw-r--r--tests/qemu-iotests/155.out5
-rwxr-xr-xtests/qemu-iotests/156174
-rw-r--r--tests/qemu-iotests/156.out48
-rwxr-xr-xtests/qemu-iotests/15789
-rw-r--r--tests/qemu-iotests/157.out22
-rwxr-xr-xtests/qemu-iotests/16296
-rw-r--r--tests/qemu-iotests/162.out17
-rw-r--r--tests/qemu-iotests/README3
-rw-r--r--tests/qemu-iotests/common15
-rw-r--r--tests/qemu-iotests/common.config21
-rw-r--r--tests/qemu-iotests/common.filter11
-rw-r--r--tests/qemu-iotests/common.rc69
-rw-r--r--tests/qemu-iotests/group7
-rw-r--r--tests/qemu-iotests/iotests.py163
-rw-r--r--tests/qht-bench.c487
-rw-r--r--tests/qom-test.c1
-rw-r--r--tests/rcutorture.c1
-rw-r--r--tests/rtc-test.c1
-rw-r--r--tests/rtl8139-test.c1
-rw-r--r--tests/spapr-phb-test.c1
-rw-r--r--tests/tcg/cris/check_addo.c14
-rw-r--r--tests/tcg/xtensa/linker.ld.S2
-rw-r--r--tests/tco-test.c1
-rw-r--r--tests/test-aio.c5
-rw-r--r--tests/test-base64.c1
-rw-r--r--tests/test-bitops.c73
-rw-r--r--tests/test-blockjob-txn.c15
-rw-r--r--tests/test-blockjob.c147
-rw-r--r--tests/test-clone-visitor.c206
-rw-r--r--tests/test-coroutine.c76
-rw-r--r--tests/test-crypto-cipher.c1
-rw-r--r--tests/test-crypto-hash.c54
-rw-r--r--tests/test-crypto-secret.c7
-rw-r--r--tests/test-crypto-xts.c18
-rw-r--r--tests/test-cutils.c1
-rw-r--r--tests/test-filter-mirror.c1
-rw-r--r--tests/test-filter-redirector.c7
-rw-r--r--tests/test-hbitmap.c7
-rw-r--r--tests/test-int128.c1
-rw-r--r--tests/test-io-channel-socket.c2
-rw-r--r--tests/test-io-task.c9
-rw-r--r--tests/test-iov.c1
-rw-r--r--tests/test-logging.c134
-rw-r--r--tests/test-mul64.c1
-rw-r--r--tests/test-netfilter.c1
-rw-r--r--tests/test-opts-visitor.c10
-rw-r--r--tests/test-qdev-global-props.c1
-rw-r--r--tests/test-qdist.c389
-rw-r--r--tests/test-qemu-opts.c1
-rw-r--r--tests/test-qga.c109
-rw-r--r--tests/test-qht-par.c55
-rw-r--r--tests/test-qht.c162
-rw-r--r--tests/test-qmp-commands.c34
-rw-r--r--tests/test-qmp-event.c1
-rw-r--r--tests/test-qmp-input-strict.c35
-rw-r--r--tests/test-qmp-input-visitor.c68
-rw-r--r--tests/test-qmp-output-visitor.c126
-rw-r--r--tests/test-rcu-list.c1
-rw-r--r--tests/test-rfifolock.c1
-rw-r--r--tests/test-string-input-visitor.c46
-rw-r--r--tests/test-string-output-visitor.c100
-rw-r--r--tests/test-thread-pool.c5
-rw-r--r--tests/test-throttle.c81
-rw-r--r--tests/test-timed-average.c1
-rw-r--r--tests/test-visitor-serialization.c44
-rw-r--r--tests/test-vmstate.c56
-rw-r--r--tests/test-write-threshold.c1
-rw-r--r--tests/test-x86-cpuid.c1
-rw-r--r--tests/tmp105-test.c1
-rw-r--r--tests/tpci200-test.c1
-rw-r--r--tests/usb-hcd-ehci-test.c1
-rw-r--r--tests/usb-hcd-ohci-test.c1
-rw-r--r--tests/usb-hcd-uhci-test.c1
-rw-r--r--tests/usb-hcd-xhci-test.c1
-rw-r--r--tests/vhost-user-bridge.c54
-rw-r--r--tests/vhost-user-test.c158
-rw-r--r--tests/virtio-9p-test.c1
-rw-r--r--tests/virtio-balloon-test.c1
-rw-r--r--tests/virtio-blk-test.c102
-rw-r--r--tests/virtio-console-test.c7
-rw-r--r--tests/virtio-net-test.c31
-rw-r--r--tests/virtio-rng-test.c1
-rw-r--r--tests/virtio-scsi-test.c62
-rw-r--r--tests/virtio-serial-test.c1
-rw-r--r--tests/vmxnet3-test.c1
-rw-r--r--tests/wdt_ib700-test.c7
263 files changed, 10467 insertions, 2321 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
index 9eed22988b..dbb52639f6 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -3,14 +3,17 @@ check-qfloat
check-qint
check-qjson
check-qlist
+check-qnull
check-qstring
check-qom-interface
check-qom-proplist
+qht-bench
rcutorture
test-aio
test-base64
test-bitops
test-blockjob-txn
+test-clone-visitor
test-coroutine
test-crypto-afsplit
test-crypto-block
@@ -47,7 +50,10 @@ test-qapi-types.[ch]
test-qapi-visit.[ch]
test-qdev-global-props
test-qemu-opts
+test-qdist
test-qga
+test-qht
+test-qht-par
test-qmp-commands
test-qmp-commands.h
test-qmp-event
diff --git a/tests/Makefile b/tests/Makefile.include
index 9194f1850b..14be4915b9 100644
--- a/tests/Makefile
+++ b/tests/Makefile.include
@@ -16,10 +16,14 @@ check-unit-y += tests/check-qstring$(EXESUF)
gcov-files-check-qstring-y = qobject/qstring.c
check-unit-y += tests/check-qlist$(EXESUF)
gcov-files-check-qlist-y = qobject/qlist.c
+check-unit-y += tests/check-qnull$(EXESUF)
+gcov-files-check-qnull-y = qobject/qnull.c
check-unit-y += tests/check-qjson$(EXESUF)
gcov-files-check-qjson-y = qobject/qjson.c
check-unit-y += tests/test-qmp-output-visitor$(EXESUF)
gcov-files-test-qmp-output-visitor-y = qapi/qmp-output-visitor.c
+check-unit-y += tests/test-clone-visitor$(EXESUF)
+gcov-files-test-clone-visitor-y = qapi/qapi-clone-visitor.c
check-unit-y += tests/test-qmp-input-visitor$(EXESUF)
gcov-files-test-qmp-input-visitor-y = qapi/qmp-input-visitor.c
check-unit-y += tests/test-qmp-input-strict$(EXESUF)
@@ -48,6 +52,7 @@ gcov-files-test-thread-pool-y = thread-pool.c
gcov-files-test-hbitmap-y = util/hbitmap.c
check-unit-y += tests/test-hbitmap$(EXESUF)
gcov-files-test-hbitmap-y = blockjob.c
+check-unit-y += tests/test-blockjob$(EXESUF)
check-unit-y += tests/test-blockjob-txn$(EXESUF)
check-unit-y += tests/test-x86-cpuid$(EXESUF)
# all code tested by test-x86-cpuid is inside topology.h
@@ -68,6 +73,12 @@ check-unit-y += tests/rcutorture$(EXESUF)
gcov-files-rcutorture-y = util/rcu.c
check-unit-y += tests/test-rcu-list$(EXESUF)
gcov-files-test-rcu-list-y = util/rcu.c
+check-unit-y += tests/test-qdist$(EXESUF)
+gcov-files-test-qdist-y = util/qdist.c
+check-unit-y += tests/test-qht$(EXESUF)
+gcov-files-test-qht-y = util/qht.c
+check-unit-y += tests/test-qht-par$(EXESUF)
+gcov-files-test-qht-par-y = util/qht.c
check-unit-y += tests/test-bitops$(EXESUF)
check-unit-$(CONFIG_HAS_GLIB_SUBPROCESS_TESTS) += tests/test-qdev-global-props$(EXESUF)
check-unit-y += tests/check-qom-interface$(EXESUF)
@@ -78,7 +89,7 @@ check-unit-y += tests/test-qemu-opts$(EXESUF)
gcov-files-test-qemu-opts-y = qom/test-qemu-opts.c
check-unit-y += tests/test-write-threshold$(EXESUF)
gcov-files-test-write-threshold-y = block/write-threshold.c
-check-unit-$(CONFIG_GNUTLS_HASH) += tests/test-crypto-hash$(EXESUF)
+check-unit-y += tests/test-crypto-hash$(EXESUF)
check-unit-y += tests/test-crypto-cipher$(EXESUF)
check-unit-y += tests/test-crypto-secret$(EXESUF)
check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlscredsx509$(EXESUF)
@@ -140,6 +151,8 @@ gcov-files-virtio-y += $(gcov-files-virtioserial-y)
check-qtest-pci-y += tests/e1000-test$(EXESUF)
gcov-files-pci-y += hw/net/e1000.c
+check-qtest-pci-y += tests/e1000e-test$(EXESUF)
+gcov-files-pci-y += hw/net/e1000e.c hw/net/e1000e_core.c
check-qtest-pci-y += tests/rtl8139-test$(EXESUF)
gcov-files-pci-y += hw/net/rtl8139.c
check-qtest-pci-y += tests/pcnet-test$(EXESUF)
@@ -196,8 +209,8 @@ check-qtest-i386-y += $(check-qtest-pci-y)
gcov-files-i386-y += $(gcov-files-pci-y)
check-qtest-i386-y += tests/vmxnet3-test$(EXESUF)
gcov-files-i386-y += hw/net/vmxnet3.c
-gcov-files-i386-y += hw/net/vmxnet_rx_pkt.c
-gcov-files-i386-y += hw/net/vmxnet_tx_pkt.c
+gcov-files-i386-y += hw/net/net_rx_pkt.c
+gcov-files-i386-y += hw/net/net_tx_pkt.c
check-qtest-i386-y += tests/pvpanic-test$(EXESUF)
gcov-files-i386-y += i386-softmmu/hw/misc/pvpanic.c
check-qtest-i386-y += tests/i82801b11-test$(EXESUF)
@@ -224,7 +237,8 @@ endif
check-qtest-i386-y += tests/test-netfilter$(EXESUF)
check-qtest-i386-y += tests/test-filter-mirror$(EXESUF)
check-qtest-i386-y += tests/test-filter-redirector$(EXESUF)
-check-qtest-x86_64-y = $(check-qtest-i386-y)
+check-qtest-i386-y += tests/postcopy-test$(EXESUF)
+check-qtest-x86_64-y += $(check-qtest-i386-y)
gcov-files-i386-y += i386-softmmu/hw/timer/mc146818rtc.c
gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
check-qtest-mips-y = tests/endianness-test$(EXESUF)
@@ -240,16 +254,24 @@ check-qtest-sparc64-y = tests/endianness-test$(EXESUF)
gcov-files-sparc-y += hw/timer/m48t59.c
gcov-files-sparc64-y += hw/timer/m48t59.c
check-qtest-arm-y = tests/tmp105-test$(EXESUF)
-check-qtest-arm-y = tests/ds1338-test$(EXESUF)
+check-qtest-arm-y += tests/ds1338-test$(EXESUF)
gcov-files-arm-y += hw/misc/tmp105.c
check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c
check-qtest-ppc-y += tests/boot-order-test$(EXESUF)
check-qtest-ppc64-y += tests/boot-order-test$(EXESUF)
+check-qtest-ppc-y += tests/drive_del-test$(EXESUF)
+check-qtest-ppc64-y += tests/drive_del-test$(EXESUF)
check-qtest-ppc64-y += tests/spapr-phb-test$(EXESUF)
gcov-files-ppc64-y += ppc64-softmmu/hw/ppc/spapr_pci.c
+check-qtest-ppc-y += tests/prom-env-test$(EXESUF)
+check-qtest-ppc64-y += tests/prom-env-test$(EXESUF)
+check-qtest-sparc-y += tests/prom-env-test$(EXESUF)
+#Disabled for now, triggers a TCG bug on 32-bit hosts
+#check-qtest-sparc64-y += tests/prom-env-test$(EXESUF)
check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
+check-qtest-ppc64-y += tests/postcopy-test$(EXESUF)
check-qtest-generic-y += tests/qom-test$(EXESUF)
@@ -266,6 +288,10 @@ qapi-schema += args-alternate.json
qapi-schema += args-any.json
qapi-schema += args-array-empty.json
qapi-schema += args-array-unknown.json
+qapi-schema += args-bad-boxed.json
+qapi-schema += args-boxed-anon.json
+qapi-schema += args-boxed-empty.json
+qapi-schema += args-boxed-string.json
qapi-schema += args-int.json
qapi-schema += args-invalid.json
qapi-schema += args-member-array-bad.json
@@ -299,6 +325,7 @@ qapi-schema += enum-wrong-data.json
qapi-schema += escape-outside-string.json
qapi-schema += escape-too-big.json
qapi-schema += escape-too-short.json
+qapi-schema += event-boxed-empty.json
qapi-schema += event-case.json
qapi-schema += event-nest-struct.json
qapi-schema += flat-union-array-branch.json
@@ -308,6 +335,7 @@ qapi-schema += flat-union-base-any.json
qapi-schema += flat-union-base-union.json
qapi-schema += flat-union-clash-member.json
qapi-schema += flat-union-empty.json
+qapi-schema += flat-union-incomplete-branch.json
qapi-schema += flat-union-inline.json
qapi-schema += flat-union-int-branch.json
qapi-schema += flat-union-invalid-branch-key.json
@@ -382,14 +410,18 @@ GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h \
tests/test-qmp-introspect.h
test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
- tests/check-qlist.o tests/check-qfloat.o tests/check-qjson.o \
+ tests/check-qlist.o tests/check-qfloat.o tests/check-qnull.o \
+ tests/check-qjson.o \
tests/test-coroutine.o tests/test-string-output-visitor.o \
tests/test-string-input-visitor.o tests/test-qmp-output-visitor.o \
+ tests/test-clone-visitor.o \
tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
tests/test-qmp-commands.o tests/test-visitor-serialization.o \
tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
tests/test-opts-visitor.o tests/test-qmp-event.o \
- tests/rcutorture.o tests/test-rcu-list.o
+ tests/rcutorture.o tests/test-rcu-list.o \
+ tests/test-qdist.o \
+ tests/test-qht.o tests/qht-bench.o tests/test-qht-par.o
$(test-obj-y): QEMU_INCLUDES += -Itests
QEMU_CFLAGS += -I$(SRC_PATH)/tests
@@ -410,6 +442,7 @@ tests/check-qstring$(EXESUF): tests/check-qstring.o $(test-util-obj-y)
tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y)
tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y)
tests/check-qfloat$(EXESUF): tests/check-qfloat.o $(test-util-obj-y)
+tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y)
tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
@@ -417,6 +450,7 @@ tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y)
tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
tests/test-rfifolock$(EXESUF): tests/test-rfifolock.o $(test-util-obj-y)
tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
+tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y)
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y)
tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y)
@@ -427,16 +461,21 @@ tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o
tests/test-int128$(EXESUF): tests/test-int128.o
tests/rcutorture$(EXESUF): tests/rcutorture.o $(test-util-obj-y)
tests/test-rcu-list$(EXESUF): tests/test-rcu-list.o $(test-util-obj-y)
+tests/test-qdist$(EXESUF): tests/test-qdist.o $(test-util-obj-y)
+tests/test-qht$(EXESUF): tests/test-qht.o $(test-util-obj-y)
+tests/test-qht-par$(EXESUF): tests/test-qht-par.o tests/qht-bench$(EXESUF) $(test-util-obj-y)
+tests/qht-bench$(EXESUF): tests/qht-bench.o $(test-util-obj-y)
tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
+ hw/core/bus.o \
hw/core/irq.o \
hw/core/fw-path-provider.o \
$(test-qapi-obj-y)
tests/test-vmstate$(EXESUF): tests/test-vmstate.o \
- migration/vmstate.o migration/qemu-file.o migration/qemu-file-buf.o \
- migration/qemu-file-unix.o qjson.o \
- $(test-qom-obj-y)
+ migration/vmstate.o migration/qemu-file.o \
+ migration/qemu-file-channel.o migration/qjson.o \
+ $(test-io-obj-y)
tests/test-timed-average$(EXESUF): tests/test-timed-average.o qemu-timer.o \
$(test-util-obj-y)
tests/test-base64$(EXESUF): tests/test-base64.o \
@@ -474,6 +513,7 @@ tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(
tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y)
tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y)
tests/test-qmp-output-visitor$(EXESUF): tests/test-qmp-output-visitor.o $(test-qapi-obj-y)
+tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o $(test-qapi-obj-y)
tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qapi-obj-y)
tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y)
tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
@@ -530,6 +570,7 @@ tests/rtc-test$(EXESUF): tests/rtc-test.o
tests/m48t59-test$(EXESUF): tests/m48t59-test.o
tests/endianness-test$(EXESUF): tests/endianness-test.o
tests/spapr-phb-test$(EXESUF): tests/spapr-phb-test.o $(libqos-obj-y)
+tests/prom-env-test$(EXESUF): tests/prom-env-test.o $(libqos-obj-y)
tests/fdc-test$(EXESUF): tests/fdc-test.o
tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y)
tests/ahci-test$(EXESUF): tests/ahci-test.o $(libqos-pc-obj-y)
@@ -546,6 +587,7 @@ tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
tests/q35-test$(EXESUF): tests/q35-test.o $(libqos-pc-obj-y)
tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
tests/e1000-test$(EXESUF): tests/e1000-test.o
+tests/e1000e-test$(EXESUF): tests/e1000e-test.o $(libqos-pc-obj-y)
tests/rtl8139-test$(EXESUF): tests/rtl8139-test.o $(libqos-pc-obj-y)
tests/pcnet-test$(EXESUF): tests/pcnet-test.o
tests/eepro100-test$(EXESUF): tests/eepro100-test.o
@@ -579,6 +621,7 @@ tests/usb-hcd-uhci-test$(EXESUF): tests/usb-hcd-uhci-test.o $(libqos-usb-obj-y)
tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y)
tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y)
tests/pc-cpu-test$(EXESUF): tests/pc-cpu-test.o
+tests/postcopy-test$(EXESUF): tests/postcopy-test.o
tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o $(qtest-obj-y) $(test-io-obj-y)
tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y)
@@ -589,6 +632,18 @@ tests/test-filter-redirector$(EXESUF): tests/test-filter-redirector.o $(qtest-ob
tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y)
tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o
+tests/migration/stress$(EXESUF): tests/migration/stress.o
+ $(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ," LINK $(TARGET_DIR)$@")
+
+INITRD_WORK_DIR=tests/migration/initrd
+
+tests/migration/initrd-stress.img: tests/migration/stress$(EXESUF)
+ mkdir -p $(INITRD_WORK_DIR)
+ cp $< $(INITRD_WORK_DIR)/init
+ (cd $(INITRD_WORK_DIR) && (find | cpio --quiet -o -H newc | gzip -9)) > $@
+ rm $(INITRD_WORK_DIR)/init
+ rmdir $(INITRD_WORK_DIR)
+
ifeq ($(CONFIG_POSIX),y)
LIBS += -lutil
endif
diff --git a/tests/ac97-test.c b/tests/ac97-test.c
index 75cab8f98f..e0d177bd9c 100644
--- a/tests/ac97-test.c
+++ b/tests/ac97-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
diff --git a/tests/acpi-test-data/pc/APIC.cphp b/tests/acpi-test-data/pc/APIC.cphp
new file mode 100644
index 0000000000..1bf8a0a63b
--- /dev/null
+++ b/tests/acpi-test-data/pc/APIC.cphp
Binary files differ
diff --git a/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT
index 9d1274d3c2..8053d71105 100644
--- a/tests/acpi-test-data/pc/DSDT
+++ b/tests/acpi-test-data/pc/DSDT
Binary files differ
diff --git a/tests/acpi-test-data/pc/DSDT.bridge b/tests/acpi-test-data/pc/DSDT.bridge
index cf48c62aa7..850e71a973 100644
--- a/tests/acpi-test-data/pc/DSDT.bridge
+++ b/tests/acpi-test-data/pc/DSDT.bridge
Binary files differ
diff --git a/tests/acpi-test-data/pc/DSDT.cphp b/tests/acpi-test-data/pc/DSDT.cphp
new file mode 100644
index 0000000000..e8b146208e
--- /dev/null
+++ b/tests/acpi-test-data/pc/DSDT.cphp
Binary files differ
diff --git a/tests/acpi-test-data/pc/DSDT.ipmikcs b/tests/acpi-test-data/pc/DSDT.ipmikcs
new file mode 100644
index 0000000000..8ac48afb6a
--- /dev/null
+++ b/tests/acpi-test-data/pc/DSDT.ipmikcs
Binary files differ
diff --git a/tests/acpi-test-data/q35/APIC.cphp b/tests/acpi-test-data/q35/APIC.cphp
new file mode 100644
index 0000000000..1bf8a0a63b
--- /dev/null
+++ b/tests/acpi-test-data/q35/APIC.cphp
Binary files differ
diff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT
index 1c089c34b0..58fbb3d2e2 100644
--- a/tests/acpi-test-data/q35/DSDT
+++ b/tests/acpi-test-data/q35/DSDT
Binary files differ
diff --git a/tests/acpi-test-data/q35/DSDT.bridge b/tests/acpi-test-data/q35/DSDT.bridge
index b29fcda0bb..c392802a95 100644
--- a/tests/acpi-test-data/q35/DSDT.bridge
+++ b/tests/acpi-test-data/q35/DSDT.bridge
Binary files differ
diff --git a/tests/acpi-test-data/q35/DSDT.cphp b/tests/acpi-test-data/q35/DSDT.cphp
new file mode 100644
index 0000000000..6cc28c6dae
--- /dev/null
+++ b/tests/acpi-test-data/q35/DSDT.cphp
Binary files differ
diff --git a/tests/acpi-test-data/q35/DSDT.ipmibt b/tests/acpi-test-data/q35/DSDT.ipmibt
new file mode 100644
index 0000000000..0ea38e1e72
--- /dev/null
+++ b/tests/acpi-test-data/q35/DSDT.ipmibt
Binary files differ
diff --git a/tests/ahci-test.c b/tests/ahci-test.c
index 6869f7f46d..9c0adce220 100644
--- a/tests/ahci-test.c
+++ b/tests/ahci-test.c
@@ -24,7 +24,6 @@
#include "qemu/osdep.h"
#include <getopt.h>
-#include <glib.h>
#include "libqtest.h"
#include "libqos/libqos-pc.h"
@@ -1064,11 +1063,34 @@ static void test_dma_fragmented(void)
g_free(tx);
}
+/*
+ * Write sector 1 with random data to make AHCI storage dirty
+ * Needed for flush tests so that flushes actually go though the block layer
+ */
+static void make_dirty(AHCIQState* ahci, uint8_t port)
+{
+ uint64_t ptr;
+ unsigned bufsize = 512;
+
+ ptr = ahci_alloc(ahci, bufsize);
+ g_assert(ptr);
+
+ ahci_guest_io(ahci, port, CMD_WRITE_DMA, ptr, bufsize, 1);
+ ahci_free(ahci, ptr);
+}
+
static void test_flush(void)
{
AHCIQState *ahci;
+ uint8_t port;
ahci = ahci_boot_and_enable(NULL);
+
+ port = ahci_port_select(ahci);
+ ahci_port_clear(ahci, port);
+
+ make_dirty(ahci, port);
+
ahci_test_flush(ahci);
ahci_shutdown(ahci);
}
@@ -1088,10 +1110,13 @@ static void test_flush_retry(void)
debug_path,
tmp_path, imgfmt);
- /* Issue Flush Command and wait for error */
port = ahci_port_select(ahci);
ahci_port_clear(ahci, port);
+ /* Issue write so that flush actually goes to disk */
+ make_dirty(ahci, port);
+
+ /* Issue Flush Command and wait for error */
cmd = ahci_guest_io_halt(ahci, port, CMD_FLUSH_CACHE, 0, 0, 0);
ahci_guest_io_resume(ahci, cmd);
@@ -1344,9 +1369,13 @@ static void test_flush_migrate(void)
set_context(src->parent);
- /* Issue Flush Command */
px = ahci_port_select(src);
ahci_port_clear(src, px);
+
+ /* Dirty device so that flush reaches disk */
+ make_dirty(src, px);
+
+ /* Issue Flush Command */
cmd = ahci_command_create(CMD_FLUSH_CACHE);
ahci_command_commit(src, cmd, px);
ahci_command_issue_async(src, cmd);
diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index 03528140c1..de4019e57d 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include <glib/gstdio.h>
#include "qemu-common.h"
#include "libqtest.h"
@@ -50,6 +49,8 @@ typedef struct {
GArray *tables;
uint32_t smbios_ep_addr;
struct smbios_21_entry_point smbios_ep_table;
+ uint8_t *required_struct_types;
+ int required_struct_types_len;
} test_data;
#define ACPI_READ_FIELD(field, addr) \
@@ -335,7 +336,7 @@ static void test_acpi_tables(test_data *data)
for (i = 0; i < tables_nr; i++) {
AcpiSdtTable ssdt_table;
- memset(&ssdt_table, 0 , sizeof(ssdt_table));
+ memset(&ssdt_table, 0, sizeof(ssdt_table));
uint32_t addr = data->rsdt_tables_addr[i + 1]; /* fadt is first */
test_dst_table(&ssdt_table, addr);
g_array_append_val(data->tables, ssdt_table);
@@ -464,7 +465,6 @@ static GArray *load_expected_aml(test_data *data)
{
int i;
AcpiSdtTable *sdt;
- gchar *aml_file = NULL;
GError *error = NULL;
gboolean ret;
@@ -472,6 +472,7 @@ static GArray *load_expected_aml(test_data *data)
for (i = 0; i < data->tables->len; ++i) {
AcpiSdtTable exp_sdt;
uint32_t signature;
+ gchar *aml_file = NULL;
const char *ext = data->variant ? data->variant : "";
sdt = &g_array_index(data->tables, AcpiSdtTable, i);
@@ -484,13 +485,21 @@ static GArray *load_expected_aml(test_data *data)
try_again:
aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine,
(gchar *)&signature, ext);
- if (data->variant && !g_file_test(aml_file, G_FILE_TEST_EXISTS)) {
- g_free(aml_file);
+ if (getenv("V")) {
+ fprintf(stderr, "\nLooking for expected file '%s'\n", aml_file);
+ }
+ if (g_file_test(aml_file, G_FILE_TEST_EXISTS)) {
+ exp_sdt.aml_file = aml_file;
+ } else if (*ext != '\0') {
+ /* try fallback to generic (extention less) expected file */
ext = "";
+ g_free(aml_file);
goto try_again;
}
- exp_sdt.aml_file = aml_file;
- g_assert(g_file_test(aml_file, G_FILE_TEST_EXISTS));
+ g_assert(exp_sdt.aml_file);
+ if (getenv("V")) {
+ fprintf(stderr, "\nUsing expected file '%s'\n", aml_file);
+ }
ret = g_file_get_contents(aml_file, &exp_sdt.aml,
&exp_sdt.aml_len, &error);
g_assert(ret);
@@ -654,7 +663,6 @@ static void test_smbios_structs(test_data *data)
uint32_t addr = ep_table->structure_table_address;
int i, len, max_len = 0;
uint8_t type, prv, crt;
- uint8_t required_struct_types[] = {0, 1, 3, 4, 16, 17, 19, 32, 127};
/* walk the smbios tables */
for (i = 0; i < ep_table->number_of_structures; i++) {
@@ -694,8 +702,8 @@ static void test_smbios_structs(test_data *data)
g_assert_cmpuint(ep_table->max_structure_size, ==, max_len);
/* required struct types must all be present */
- for (i = 0; i < ARRAY_SIZE(required_struct_types); i++) {
- g_assert(test_bit(required_struct_types[i], struct_bitmap));
+ for (i = 0; i < data->required_struct_types_len; i++) {
+ g_assert(test_bit(data->required_struct_types[i], struct_bitmap));
}
}
@@ -735,6 +743,10 @@ static void test_acpi_one(const char *params, test_data *data)
g_free(args);
}
+static uint8_t base_required_struct_types[] = {
+ 0, 1, 3, 4, 16, 17, 19, 32, 127
+};
+
static void test_acpi_piix4_tcg(void)
{
test_data data;
@@ -744,6 +756,8 @@ static void test_acpi_piix4_tcg(void)
*/
memset(&data, 0, sizeof(data));
data.machine = MACHINE_PC;
+ data.required_struct_types = base_required_struct_types;
+ data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
test_acpi_one("-machine accel=tcg", &data);
free_test_data(&data);
}
@@ -755,6 +769,8 @@ static void test_acpi_piix4_tcg_bridge(void)
memset(&data, 0, sizeof(data));
data.machine = MACHINE_PC;
data.variant = ".bridge";
+ data.required_struct_types = base_required_struct_types;
+ data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
test_acpi_one("-machine accel=tcg -device pci-bridge,chassis_nr=1", &data);
free_test_data(&data);
}
@@ -765,6 +781,8 @@ static void test_acpi_q35_tcg(void)
memset(&data, 0, sizeof(data));
data.machine = MACHINE_Q35;
+ data.required_struct_types = base_required_struct_types;
+ data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
test_acpi_one("-machine q35,accel=tcg", &data);
free_test_data(&data);
}
@@ -776,11 +794,76 @@ static void test_acpi_q35_tcg_bridge(void)
memset(&data, 0, sizeof(data));
data.machine = MACHINE_Q35;
data.variant = ".bridge";
+ data.required_struct_types = base_required_struct_types;
+ data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
test_acpi_one("-machine q35,accel=tcg -device pci-bridge,chassis_nr=1",
&data);
free_test_data(&data);
}
+static void test_acpi_piix4_tcg_cphp(void)
+{
+ test_data data;
+
+ memset(&data, 0, sizeof(data));
+ data.machine = MACHINE_PC;
+ data.variant = ".cphp";
+ test_acpi_one("-machine accel=tcg"
+ " -smp 2,cores=3,sockets=2,maxcpus=6",
+ &data);
+ free_test_data(&data);
+}
+
+static void test_acpi_q35_tcg_cphp(void)
+{
+ test_data data;
+
+ memset(&data, 0, sizeof(data));
+ data.machine = MACHINE_Q35;
+ data.variant = ".cphp";
+ test_acpi_one("-machine q35,accel=tcg"
+ " -smp 2,cores=3,sockets=2,maxcpus=6",
+ &data);
+ free_test_data(&data);
+}
+
+static uint8_t ipmi_required_struct_types[] = {
+ 0, 1, 3, 4, 16, 17, 19, 32, 38, 127
+};
+
+static void test_acpi_q35_tcg_ipmi(void)
+{
+ test_data data;
+
+ memset(&data, 0, sizeof(data));
+ data.machine = MACHINE_Q35;
+ data.variant = ".ipmibt";
+ data.required_struct_types = ipmi_required_struct_types;
+ data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types);
+ test_acpi_one("-machine q35,accel=tcg -device ipmi-bmc-sim,id=bmc0"
+ " -device isa-ipmi-bt,bmc=bmc0",
+ &data);
+ free_test_data(&data);
+}
+
+static void test_acpi_piix4_tcg_ipmi(void)
+{
+ test_data data;
+
+ /* Supplying -machine accel argument overrides the default (qtest).
+ * This is to make guest actually run.
+ */
+ memset(&data, 0, sizeof(data));
+ data.machine = MACHINE_PC;
+ data.variant = ".ipmikcs";
+ data.required_struct_types = ipmi_required_struct_types;
+ data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types);
+ test_acpi_one("-machine accel=tcg -device ipmi-bmc-sim,id=bmc0"
+ " -device isa-ipmi-kcs,irq=0,bmc=bmc0",
+ &data);
+ free_test_data(&data);
+}
+
int main(int argc, char *argv[])
{
const char *arch = qtest_get_arch();
@@ -797,6 +880,10 @@ int main(int argc, char *argv[])
qtest_add_func("acpi/piix4/tcg/bridge", test_acpi_piix4_tcg_bridge);
qtest_add_func("acpi/q35/tcg", test_acpi_q35_tcg);
qtest_add_func("acpi/q35/tcg/bridge", test_acpi_q35_tcg_bridge);
+ qtest_add_func("acpi/piix4/tcg/ipmi", test_acpi_piix4_tcg_ipmi);
+ qtest_add_func("acpi/q35/tcg/ipmi", test_acpi_q35_tcg_ipmi);
+ qtest_add_func("acpi/piix4/tcg/cpuhp", test_acpi_piix4_tcg_cphp);
+ qtest_add_func("acpi/q35/tcg/cpuhp", test_acpi_q35_tcg_cphp);
}
ret = g_test_run();
boot_sector_cleanup(disk);
diff --git a/tests/boot-order-test.c b/tests/boot-order-test.c
index a6d8bd5cbf..fc1e7941f7 100644
--- a/tests/boot-order-test.c
+++ b/tests/boot-order-test.c
@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqos/fw_cfg.h"
#include "libqtest.h"
diff --git a/tests/boot-sector.h b/tests/boot-sector.h
index 38be0290e3..f64b477aa3 100644
--- a/tests/boot-sector.h
+++ b/tests/boot-sector.h
@@ -11,8 +11,8 @@
* See the COPYING file in the top-level directory.
*/
-#ifndef TEST_BOOT_SECTOR
-#define TEST_BOOT_SECTOR
+#ifndef TEST_BOOT_SECTOR_H
+#define TEST_BOOT_SECTOR_H
/* Create boot disk file. */
int boot_sector_init(const char *fname);
@@ -23,4 +23,4 @@ void boot_sector_test(void);
/* unlink boot disk file. */
void boot_sector_cleanup(const char *fname);
-#endif /* TEST_BOOT_SECTOR */
+#endif /* TEST_BOOT_SECTOR_H */
diff --git a/tests/check-qdict.c b/tests/check-qdict.c
index a43056c5de..42da1e65a5 100644
--- a/tests/check-qdict.c
+++ b/tests/check-qdict.c
@@ -10,7 +10,6 @@
* See the COPYING.LIB file in the top-level directory.
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qapi/qmp/qint.h"
#include "qapi/qmp/qdict.h"
diff --git a/tests/check-qfloat.c b/tests/check-qfloat.c
index 3102608f55..1da2cdae08 100644
--- a/tests/check-qfloat.c
+++ b/tests/check-qfloat.c
@@ -11,7 +11,6 @@
*
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qapi/qmp/qfloat.h"
#include "qemu-common.h"
diff --git a/tests/check-qint.c b/tests/check-qint.c
index c86f7dfa38..b6e4555115 100644
--- a/tests/check-qint.c
+++ b/tests/check-qint.c
@@ -10,7 +10,6 @@
* See the COPYING.LIB file in the top-level directory.
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qapi/qmp/qint.h"
#include "qemu-common.h"
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index 99de6f5252..85955744eb 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -11,16 +11,9 @@
*
*/
#include "qemu/osdep.h"
-#include <glib.h>
-
-#include "qapi/qmp/qstring.h"
-#include "qapi/qmp/qint.h"
-#include "qapi/qmp/qdict.h"
-#include "qapi/qmp/qlist.h"
-#include "qapi/qmp/qfloat.h"
-#include "qapi/qmp/qbool.h"
-#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/types.h"
+#include "qapi/qmp/qjson.h"
#include "qemu-common.h"
static void escaped_string(void)
diff --git a/tests/check-qlist.c b/tests/check-qlist.c
index f231d5fa97..e16da5e5c6 100644
--- a/tests/check-qlist.c
+++ b/tests/check-qlist.c
@@ -10,7 +10,6 @@
* See the COPYING.LIB file in the top-level directory.
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qapi/qmp/qint.h"
#include "qapi/qmp/qlist.h"
diff --git a/tests/check-qnull.c b/tests/check-qnull.c
new file mode 100644
index 0000000000..dc906b116e
--- /dev/null
+++ b/tests/check-qnull.c
@@ -0,0 +1,73 @@
+/*
+ * QNull unit-tests.
+ *
+ * Copyright (C) 2016 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.
+ */
+#include "qemu/osdep.h"
+
+#include "qapi/qmp/qobject.h"
+#include "qemu-common.h"
+#include "qapi/qmp-input-visitor.h"
+#include "qapi/qmp-output-visitor.h"
+#include "qapi/error.h"
+
+/*
+ * Public Interface test-cases
+ *
+ * (with some violations to access 'private' data)
+ */
+
+static void qnull_ref_test(void)
+{
+ QObject *obj;
+
+ g_assert(qnull_.refcnt == 1);
+ obj = qnull();
+ g_assert(obj);
+ g_assert(obj == &qnull_);
+ g_assert(qnull_.refcnt == 2);
+ g_assert(qobject_type(obj) == QTYPE_QNULL);
+ qobject_decref(obj);
+ g_assert(qnull_.refcnt == 1);
+}
+
+static void qnull_visit_test(void)
+{
+ QObject *obj;
+ Visitor *v;
+
+ /*
+ * Most tests of interactions between QObject and visitors are in
+ * test-qmp-*-visitor; but these tests live here because they
+ * depend on layering violations to check qnull_ refcnt.
+ */
+
+ g_assert(qnull_.refcnt == 1);
+ obj = qnull();
+ v = qmp_input_visitor_new(obj, true);
+ qobject_decref(obj);
+ visit_type_null(v, NULL, &error_abort);
+ visit_free(v);
+
+ v = qmp_output_visitor_new(&obj);
+ visit_type_null(v, NULL, &error_abort);
+ visit_complete(v, &obj);
+ g_assert(obj == &qnull_);
+ qobject_decref(obj);
+ visit_free(v);
+
+ g_assert(qnull_.refcnt == 1);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/public/qnull_ref", qnull_ref_test);
+ g_test_add_func("/public/qnull_visit", qnull_visit_test);
+
+ return g_test_run();
+}
diff --git a/tests/check-qom-interface.c b/tests/check-qom-interface.c
index 09354deb70..719ddcf2e0 100644
--- a/tests/check-qom-interface.c
+++ b/tests/check-qom-interface.c
@@ -10,7 +10,6 @@
* See the COPYING.LIB file in the top-level directory.
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qom/object.h"
#include "qemu/module.h"
diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
index ffffd872f2..42defe7128 100644
--- a/tests/check-qom-proplist.c
+++ b/tests/check-qom-proplist.c
@@ -19,7 +19,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qapi/error.h"
#include "qom/object.h"
diff --git a/tests/check-qstring.c b/tests/check-qstring.c
index 9877b42c89..239e9d9da3 100644
--- a/tests/check-qstring.c
+++ b/tests/check-qstring.c
@@ -10,7 +10,6 @@
* See the COPYING.LIB file in the top-level directory.
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qapi/qmp/qstring.h"
#include "qemu-common.h"
diff --git a/tests/data/test-qga-config b/tests/data/test-qga-config
new file mode 100644
index 0000000000..4bb721a4a1
--- /dev/null
+++ b/tests/data/test-qga-config
@@ -0,0 +1,8 @@
+[general]
+daemon=false
+method=virtio-serial
+path=/path/to/org.qemu.guest_agent.0
+pidfile=/var/foo/qemu-ga.pid
+statedir=/var/state
+verbose=true
+blacklist=guest-ping;guest-get-time
diff --git a/tests/device-introspect-test.c b/tests/device-introspect-test.c
index 4477926014..37debc11f9 100644
--- a/tests/device-introspect-test.c
+++ b/tests/device-introspect-test.c
@@ -18,7 +18,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "qapi/qmp/qstring.h"
#include "libqtest.h"
diff --git a/tests/display-vga-test.c b/tests/display-vga-test.c
index 5706d338a1..91460215cc 100644
--- a/tests/display-vga-test.c
+++ b/tests/display-vga-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
static void pci_cirrus(void)
@@ -51,8 +50,6 @@ static void pci_virtio_vga(void)
int main(int argc, char **argv)
{
- int ret;
-
g_test_init(&argc, &argv, NULL);
qtest_add_func("/display/pci/cirrus", pci_cirrus);
@@ -63,7 +60,5 @@ int main(int argc, char **argv)
#ifdef CONFIG_VIRTIO_VGA
qtest_add_func("/display/pci/virtio-vga", pci_virtio_vga);
#endif
- ret = g_test_run();
-
- return ret;
+ return g_test_run();
}
diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
new file mode 100644
index 0000000000..4f4707dae0
--- /dev/null
+++ b/tests/docker/Makefile.include
@@ -0,0 +1,128 @@
+# Makefile for Docker tests
+
+.PHONY: docker docker-test docker-clean docker-image docker-qemu-src
+
+DOCKER_SUFFIX := .docker
+DOCKER_FILES_DIR := $(SRC_PATH)/tests/docker/dockerfiles
+DOCKER_IMAGES := $(notdir $(basename $(wildcard $(DOCKER_FILES_DIR)/*.docker)))
+DOCKER_TARGETS := $(patsubst %,docker-image-%,$(DOCKER_IMAGES))
+# Use a global constant ccache directory to speed up repetitive builds
+DOCKER_CCACHE_DIR := $$HOME/.cache/qemu-docker-ccache
+
+DOCKER_TESTS := $(notdir $(shell \
+ find $(SRC_PATH)/tests/docker/ -name 'test-*' -type f))
+
+DOCKER_TOOLS := travis
+
+TESTS ?= %
+IMAGES ?= %
+
+# Make archive from git repo $1 to tar.gz $2
+make-archive-maybe = $(if $(wildcard $1/*), \
+ $(call quiet-command, \
+ (cd $1; if git diff-index --quiet HEAD -- &>/dev/null; then \
+ git archive -1 HEAD --format=tar.gz; \
+ else \
+ git archive -1 $$(git stash create) --format=tar.gz; \
+ fi) > $2, \
+ " ARCHIVE $(notdir $2)"))
+
+CUR_TIME := $(shell date +%Y-%m-%d-%H.%M.%S.$$$$)
+DOCKER_SRC_COPY := docker-src.$(CUR_TIME)
+
+$(DOCKER_SRC_COPY):
+ @mkdir $@
+ $(call make-archive-maybe, $(SRC_PATH), $@/qemu.tgz)
+ $(call make-archive-maybe, $(SRC_PATH)/dtc, $@/dtc.tgz)
+ $(call make-archive-maybe, $(SRC_PATH)/pixman, $@/pixman.tgz)
+ $(call quiet-command, cp $(SRC_PATH)/tests/docker/run $@/run, \
+ " COPY RUNNER")
+
+docker-qemu-src: $(DOCKER_SRC_COPY)
+
+docker-image: ${DOCKER_TARGETS}
+
+# General rule for building docker images
+docker-image-%: $(DOCKER_FILES_DIR)/%.docker
+ $(call quiet-command,\
+ $(SRC_PATH)/tests/docker/docker.py build qemu:$* $< \
+ $(if $V,,--quiet) $(if $(NOCACHE),--no-cache) \
+ $(if $(EXECUTABLE),--include-executable=$(EXECUTABLE)),\
+ " BUILD $*")
+
+# Expand all the pre-requistes for each docker image and test combination
+$(foreach i,$(DOCKER_IMAGES), \
+ $(foreach t,$(DOCKER_TESTS) $(DOCKER_TOOLS), \
+ $(eval .PHONY: docker-$t@$i) \
+ $(eval docker-$t@$i: docker-image-$i docker-run-$t@$i) \
+ ) \
+ $(foreach t,$(DOCKER_TESTS), \
+ $(eval docker-test: docker-$t@$i) \
+ ) \
+)
+
+docker:
+ @echo 'Build QEMU and run tests inside Docker containers'
+ @echo
+ @echo 'Available targets:'
+ @echo
+ @echo ' docker: Print this help.'
+ @echo ' docker-test: Run all image/test combinations.'
+ @echo ' docker-clean: Kill and remove residual docker testing containers.'
+ @echo ' docker-TEST@IMAGE: Run "TEST" in container "IMAGE".'
+ @echo ' Note: "TEST" is one of the listed test name,'
+ @echo ' or a script name under $$QEMU_SRC/tests/docker/;'
+ @echo ' "IMAGE" is one of the listed container name."'
+ @echo ' docker-image: Build all images.'
+ @echo ' docker-image-IMAGE: Build image "IMAGE".'
+ @echo
+ @echo 'Available container images:'
+ @echo ' $(DOCKER_IMAGES)'
+ @echo
+ @echo 'Available tests:'
+ @echo ' $(DOCKER_TESTS)'
+ @echo
+ @echo 'Available tools:'
+ @echo ' $(DOCKER_TOOLS)'
+ @echo
+ @echo 'Special variables:'
+ @echo ' TARGET_LIST=a,b,c Override target list in builds.'
+ @echo ' EXTRA_CONFIGURE_OPTS="..."'
+ @echo ' Extra configure options.'
+ @echo ' IMAGES="a b c ..": Filters which images to build or run.'
+ @echo ' TESTS="x y z .." Filters which tests to run (for docker-test).'
+ @echo ' J=[0..9]* Overrides the -jN parameter for make commands'
+ @echo ' (default is 1)'
+ @echo ' DEBUG=1 Stop and drop to shell in the created container'
+ @echo ' before running the command.'
+ @echo ' NOCACHE=1 Ignore cache when build images.'
+ @echo ' EXECUTABLE=<path> Include executable in image.'
+
+docker-run-%: CMD = $(shell echo '$@' | sed -e 's/docker-run-\([^@]*\)@\(.*\)/\1/')
+docker-run-%: IMAGE = $(shell echo '$@' | sed -e 's/docker-run-\([^@]*\)@\(.*\)/\2/')
+docker-run-%: docker-qemu-src
+ @mkdir -p "$(DOCKER_CCACHE_DIR)"
+ @if test -z "$(IMAGE)" || test -z "$(CMD)"; \
+ then echo "Invalid target"; exit 1; \
+ fi
+ $(if $(filter $(TESTS),$(CMD)),$(if $(filter $(IMAGES),$(IMAGE)), \
+ $(call quiet-command,\
+ if $(SRC_PATH)/tests/docker/docker.py images | \
+ awk '$$1=="qemu" && $$2=="$(IMAGE)"{found=1} END{exit(!found)}'; then \
+ $(SRC_PATH)/tests/docker/docker.py run $(if $V,,--rm) \
+ -t \
+ $(if $(DEBUG),-i,--net=none) \
+ -e TARGET_LIST=$(TARGET_LIST) \
+ -e EXTRA_CONFIGURE_OPTS=$(EXTRA_CONFIGURE_OPTS) \
+ -e V=$V -e J=$J -e DEBUG=$(DEBUG)\
+ -e CCACHE_DIR=/var/tmp/ccache \
+ -v $$(realpath $(DOCKER_SRC_COPY)):/var/tmp/qemu:z$(COMMA)ro \
+ -v $(DOCKER_CCACHE_DIR):/var/tmp/ccache:z \
+ qemu:$(IMAGE) \
+ /var/tmp/qemu/run \
+ $(CMD); \
+ fi \
+ , " RUN $(CMD) in $(IMAGE)")))
+
+docker-clean:
+ $(call quiet-command, $(SRC_PATH)/tests/docker/docker.py clean)
diff --git a/tests/docker/common.rc b/tests/docker/common.rc
new file mode 100755
index 0000000000..0c6d8d5ece
--- /dev/null
+++ b/tests/docker/common.rc
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Common routines for docker test scripts.
+#
+# Copyright (c) 2016 Red Hat Inc.
+#
+# Authors:
+# Fam Zheng <famz@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2
+# or (at your option) any later version. See the COPYING file in
+# the top-level directory.
+
+requires()
+{
+ for c in $@; do
+ if ! echo "$FEATURES" | grep -wq -e "$c"; then
+ echo "Prerequisite '$c' not present, skip"
+ exit 0
+ fi
+ done
+}
+
+build_qemu()
+{
+ $QEMU_SRC/configure \
+ --enable-werror \
+ ${TARGET_LIST:+"--target-list=${TARGET_LIST}"} \
+ --prefix="$PWD/install" \
+ $EXTRA_CONFIGURE_OPTS \
+ "$@"
+ make $MAKEFLAGS
+}
diff --git a/tests/docker/docker.py b/tests/docker/docker.py
new file mode 100755
index 0000000000..222a1053fe
--- /dev/null
+++ b/tests/docker/docker.py
@@ -0,0 +1,335 @@
+#!/usr/bin/env python2
+#
+# Docker controlling module
+#
+# Copyright (c) 2016 Red Hat Inc.
+#
+# Authors:
+# Fam Zheng <famz@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2
+# or (at your option) any later version. See the COPYING file in
+# the top-level directory.
+
+import os
+import sys
+import subprocess
+import json
+import hashlib
+import atexit
+import uuid
+import argparse
+import tempfile
+import re
+from tarfile import TarFile, TarInfo
+from StringIO import StringIO
+from shutil import copy, rmtree
+
+def _text_checksum(text):
+ """Calculate a digest string unique to the text content"""
+ return hashlib.sha1(text).hexdigest()
+
+def _guess_docker_command():
+ """ Guess a working docker command or raise exception if not found"""
+ commands = [["docker"], ["sudo", "-n", "docker"]]
+ for cmd in commands:
+ if subprocess.call(cmd + ["images"],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE) == 0:
+ return cmd
+ commands_txt = "\n".join([" " + " ".join(x) for x in commands])
+ raise Exception("Cannot find working docker command. Tried:\n%s" % \
+ commands_txt)
+
+def _copy_with_mkdir(src, root_dir, sub_path):
+ """Copy src into root_dir, creating sub_path as needed."""
+ dest_dir = os.path.normpath("%s/%s" % (root_dir, sub_path))
+ try:
+ os.makedirs(dest_dir)
+ except OSError:
+ # we can safely ignore already created directories
+ pass
+
+ dest_file = "%s/%s" % (dest_dir, os.path.basename(src))
+ copy(src, dest_file)
+
+
+def _get_so_libs(executable):
+ """Return a list of libraries associated with an executable.
+
+ The paths may be symbolic links which would need to be resolved to
+ ensure theright data is copied."""
+
+ libs = []
+ ldd_re = re.compile(r"(/.*/)(\S*)")
+ try:
+ ldd_output = subprocess.check_output(["ldd", executable])
+ for line in ldd_output.split("\n"):
+ search = ldd_re.search(line)
+ if search and len(search.groups()) == 2:
+ so_path = search.groups()[0]
+ so_lib = search.groups()[1]
+ libs.append("%s/%s" % (so_path, so_lib))
+ except subprocess.CalledProcessError:
+ print "%s had no associated libraries (static build?)" % (executable)
+
+ return libs
+
+def _copy_binary_with_libs(src, dest_dir):
+ """Copy a binary executable and all its dependant libraries.
+
+ This does rely on the host file-system being fairly multi-arch
+ aware so the file don't clash with the guests layout."""
+
+ _copy_with_mkdir(src, dest_dir, "/usr/bin")
+
+ libs = _get_so_libs(src)
+ if libs:
+ for l in libs:
+ so_path = os.path.dirname(l)
+ _copy_with_mkdir(l , dest_dir, so_path)
+
+class Docker(object):
+ """ Running Docker commands """
+ def __init__(self):
+ self._command = _guess_docker_command()
+ self._instances = []
+ atexit.register(self._kill_instances)
+
+ def _do(self, cmd, quiet=True, infile=None, **kwargs):
+ if quiet:
+ kwargs["stdout"] = subprocess.PIPE
+ if infile:
+ kwargs["stdin"] = infile
+ return subprocess.call(self._command + cmd, **kwargs)
+
+ def _do_kill_instances(self, only_known, only_active=True):
+ cmd = ["ps", "-q"]
+ if not only_active:
+ cmd.append("-a")
+ for i in self._output(cmd).split():
+ resp = self._output(["inspect", i])
+ labels = json.loads(resp)[0]["Config"]["Labels"]
+ active = json.loads(resp)[0]["State"]["Running"]
+ if not labels:
+ continue
+ instance_uuid = labels.get("com.qemu.instance.uuid", None)
+ if not instance_uuid:
+ continue
+ if only_known and instance_uuid not in self._instances:
+ continue
+ print "Terminating", i
+ if active:
+ self._do(["kill", i])
+ self._do(["rm", i])
+
+ def clean(self):
+ self._do_kill_instances(False, False)
+ return 0
+
+ def _kill_instances(self):
+ return self._do_kill_instances(True)
+
+ def _output(self, cmd, **kwargs):
+ return subprocess.check_output(self._command + cmd,
+ stderr=subprocess.STDOUT,
+ **kwargs)
+
+ def get_image_dockerfile_checksum(self, tag):
+ resp = self._output(["inspect", tag])
+ labels = json.loads(resp)[0]["Config"].get("Labels", {})
+ return labels.get("com.qemu.dockerfile-checksum", "")
+
+ def build_image(self, tag, docker_dir, dockerfile, quiet=True, argv=None):
+ if argv == None:
+ argv = []
+
+ tmp_df = tempfile.NamedTemporaryFile(dir=docker_dir, suffix=".docker")
+ tmp_df.write(dockerfile)
+
+ tmp_df.write("\n")
+ tmp_df.write("LABEL com.qemu.dockerfile-checksum=%s" %
+ _text_checksum(dockerfile))
+ tmp_df.flush()
+
+ self._do(["build", "-t", tag, "-f", tmp_df.name] + argv + \
+ [docker_dir],
+ quiet=quiet)
+
+ def update_image(self, tag, tarball, quiet=True):
+ "Update a tagged image using "
+
+ self._do(["build", "-t", tag, "-"], quiet=quiet, infile=tarball)
+
+ def image_matches_dockerfile(self, tag, dockerfile):
+ try:
+ checksum = self.get_image_dockerfile_checksum(tag)
+ except Exception:
+ return False
+ return checksum == _text_checksum(dockerfile)
+
+ def run(self, cmd, keep, quiet):
+ label = uuid.uuid1().hex
+ if not keep:
+ self._instances.append(label)
+ ret = self._do(["run", "--label",
+ "com.qemu.instance.uuid=" + label] + cmd,
+ quiet=quiet)
+ if not keep:
+ self._instances.remove(label)
+ return ret
+
+ def command(self, cmd, argv, quiet):
+ return self._do([cmd] + argv, quiet=quiet)
+
+class SubCommand(object):
+ """A SubCommand template base class"""
+ name = None # Subcommand name
+ def shared_args(self, parser):
+ parser.add_argument("--quiet", action="store_true",
+ help="Run quietly unless an error occured")
+
+ def args(self, parser):
+ """Setup argument parser"""
+ pass
+ def run(self, args, argv):
+ """Run command.
+ args: parsed argument by argument parser.
+ argv: remaining arguments from sys.argv.
+ """
+ pass
+
+class RunCommand(SubCommand):
+ """Invoke docker run and take care of cleaning up"""
+ name = "run"
+ def args(self, parser):
+ parser.add_argument("--keep", action="store_true",
+ help="Don't remove image when command completes")
+ def run(self, args, argv):
+ return Docker().run(argv, args.keep, quiet=args.quiet)
+
+class BuildCommand(SubCommand):
+ """ Build docker image out of a dockerfile. Arguments: <tag> <dockerfile>"""
+ name = "build"
+ def args(self, parser):
+ parser.add_argument("--include-executable", "-e",
+ help="""Specify a binary that will be copied to the
+ container together with all its dependent
+ libraries""")
+ parser.add_argument("tag",
+ help="Image Tag")
+ parser.add_argument("dockerfile",
+ help="Dockerfile name")
+
+ def run(self, args, argv):
+ dockerfile = open(args.dockerfile, "rb").read()
+ tag = args.tag
+
+ dkr = Docker()
+ if dkr.image_matches_dockerfile(tag, dockerfile):
+ if not args.quiet:
+ print "Image is up to date."
+ else:
+ # Create a docker context directory for the build
+ docker_dir = tempfile.mkdtemp(prefix="docker_build")
+
+ # Is there a .pre file to run in the build context?
+ docker_pre = os.path.splitext(args.dockerfile)[0]+".pre"
+ if os.path.exists(docker_pre):
+ rc = subprocess.call(os.path.realpath(docker_pre),
+ cwd=docker_dir)
+ if rc == 3:
+ print "Skip"
+ return 0
+ elif rc != 0:
+ print "%s exited with code %d" % (docker_pre, rc)
+ return 1
+
+ # Do we include a extra binary?
+ if args.include_executable:
+ _copy_binary_with_libs(args.include_executable,
+ docker_dir)
+
+ dkr.build_image(tag, docker_dir, dockerfile,
+ quiet=args.quiet, argv=argv)
+
+ rmtree(docker_dir)
+
+ return 0
+
+class UpdateCommand(SubCommand):
+ """ Update a docker image with new executables. Arguments: <tag> <executable>"""
+ name = "update"
+ def args(self, parser):
+ parser.add_argument("tag",
+ help="Image Tag")
+ parser.add_argument("executable",
+ help="Executable to copy")
+
+ def run(self, args, argv):
+ # Create a temporary tarball with our whole build context and
+ # dockerfile for the update
+ tmp = tempfile.NamedTemporaryFile(suffix="dckr.tar.gz")
+ tmp_tar = TarFile(fileobj=tmp, mode='w')
+
+ # Add the executable to the tarball
+ bn = os.path.basename(args.executable)
+ ff = "/usr/bin/%s" % bn
+ tmp_tar.add(args.executable, arcname=ff)
+
+ # Add any associated libraries
+ libs = _get_so_libs(args.executable)
+ if libs:
+ for l in libs:
+ tmp_tar.add(os.path.realpath(l), arcname=l)
+
+ # Create a Docker buildfile
+ df = StringIO()
+ df.write("FROM %s\n" % args.tag)
+ df.write("ADD . /\n")
+ df.seek(0)
+
+ df_tar = TarInfo(name="Dockerfile")
+ df_tar.size = len(df.buf)
+ tmp_tar.addfile(df_tar, fileobj=df)
+
+ tmp_tar.close()
+
+ # reset the file pointers
+ tmp.flush()
+ tmp.seek(0)
+
+ # Run the build with our tarball context
+ dkr = Docker()
+ dkr.update_image(args.tag, tmp, quiet=args.quiet)
+
+ return 0
+
+class CleanCommand(SubCommand):
+ """Clean up docker instances"""
+ name = "clean"
+ def run(self, args, argv):
+ Docker().clean()
+ return 0
+
+class ImagesCommand(SubCommand):
+ """Run "docker images" command"""
+ name = "images"
+ def run(self, args, argv):
+ return Docker().command("images", argv, args.quiet)
+
+def main():
+ parser = argparse.ArgumentParser(description="A Docker helper",
+ usage="%s <subcommand> ..." % os.path.basename(sys.argv[0]))
+ subparsers = parser.add_subparsers(title="subcommands", help=None)
+ for cls in SubCommand.__subclasses__():
+ cmd = cls()
+ subp = subparsers.add_parser(cmd.name, help=cmd.__doc__)
+ cmd.shared_args(subp)
+ cmd.args(subp)
+ subp.set_defaults(cmdobj=cmd)
+ args, argv = parser.parse_known_args()
+ return args.cmdobj.run(args, argv)
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/tests/docker/dockerfiles/centos6.docker b/tests/docker/dockerfiles/centos6.docker
new file mode 100644
index 0000000000..8f4fe46379
--- /dev/null
+++ b/tests/docker/dockerfiles/centos6.docker
@@ -0,0 +1,6 @@
+FROM centos:6
+RUN yum install -y \
+ tar git make gcc g++ \
+ zlib-devel glib2-devel SDL-devel pixman-devel \
+ epel-release
+RUN yum install -y libfdt-devel ccache
diff --git a/tests/docker/dockerfiles/debian-bootstrap.docker b/tests/docker/dockerfiles/debian-bootstrap.docker
new file mode 100644
index 0000000000..3a9125e497
--- /dev/null
+++ b/tests/docker/dockerfiles/debian-bootstrap.docker
@@ -0,0 +1,21 @@
+# Create Debian Bootstrap Image
+#
+# This is intended to be pre-poluated by:
+# - a first stage debootstrap (see debian-bootstrap.pre)
+# - a native qemu-$arch that binfmt_misc will run
+FROM scratch
+
+# Add everything from the context into the container
+ADD . /
+
+# Patch all mounts as docker already has stuff set up
+RUN sed -i 's/in_target mount/echo not for docker in_target mount/g' /debootstrap/functions
+
+# Run stage 2
+RUN /debootstrap/debootstrap --second-stage
+
+# At this point we can install additional packages if we want
+# Duplicate deb line as deb-src
+RUN cat /etc/apt/sources.list | sed "s/deb/deb-src/" >> /etc/apt/sources.list
+RUN apt-get update
+RUN apt-get -y build-dep qemu
diff --git a/tests/docker/dockerfiles/debian-bootstrap.pre b/tests/docker/dockerfiles/debian-bootstrap.pre
new file mode 100755
index 0000000000..5d9c8d5ebc
--- /dev/null
+++ b/tests/docker/dockerfiles/debian-bootstrap.pre
@@ -0,0 +1,87 @@
+#!/bin/sh
+#
+# Simple wrapper for debootstrap, run in the docker build context
+#
+FAKEROOT=`which fakeroot 2> /dev/null`
+
+exit_and_skip()
+{
+ exit 3
+}
+
+#
+# fakeroot is needed to run the bootstrap stage
+#
+if [ -z $FAKEROOT ]; then
+ echo "Please install fakeroot to enable bootstraping"
+ exit_and_skip
+fi
+
+# We check in order for
+#
+# - DEBOOTSTRAP_DIR pointing at a development checkout
+# - PATH for the debootstrap script (installed)
+#
+# If neither option works then we checkout debootstrap from its
+# upstream SCM and run it from there.
+#
+
+if [ -z $DEBOOTSTRAP_DIR ]; then
+ DEBOOTSTRAP=`which debootstrap 2> /dev/null`
+ if [ -z $DEBOOTSTRAP ]; then
+ echo "No debootstrap installed, attempting to install from SCM"
+ DEBOOTSTRAP_SOURCE=https://anonscm.debian.org/git/d-i/debootstrap.git
+ git clone ${DEBOOTSTRAP_SOURCE} ./debootstrap.git
+ export DEBOOTSTRAP_DIR=./debootstrap.git
+ DEBOOTSTRAP=./debootstrap.git/debootstrap
+ fi
+else
+ DEBOOTSTRAP=${DEBOOTSTRAP_DIR}/debootstrap
+ if [ ! -f $DEBOOTSTRAP ]; then
+ echo "Couldn't find script at ${DEBOOTSTRAP}"
+ exit_and_skip
+ fi
+fi
+
+#
+# Finally check to see if any qemu's are installed
+#
+BINFMT_DIR=/proc/sys/fs/binfmt_misc
+if [ ! -e $BINFMT_DIR ]; then
+ echo "binfmt_misc needs enabling for a QEMU bootstrap to work"
+ exit_and_skip
+else
+ # DEB_ARCH and QEMU arch names are not totally aligned
+ case "${DEB_ARCH}" in
+ amd64)
+ QEMU=qemu-i386
+ ;;
+ armel|armhf)
+ QEMU=qemu-arm
+ ;;
+ arm64)
+ QEMU=qemu-aarch64
+ ;;
+ powerpc)
+ QEMU=qemu-ppc
+ ;;
+ ppc64el)
+ QEMU=qemu-ppc64le
+ ;;
+ s390)
+ QEMU=qemu-s390x
+ ;;
+ *)
+ QEMU=qemu-${DEB_ARCH}
+ ;;
+ esac
+ if [ ! -e "${BINFMT_DIR}/$QEMU" ]; then
+ echo "No binfmt_misc rule to run $QEMU, can't bootstrap"
+ exit_and_skip
+ fi
+fi
+
+echo "Building a rootfs using ${FAKEROOT} and ${DEBOOTSTRAP} ${DEB_ARCH}/${DEB_TYPE}"
+
+${FAKEROOT} ${DEBOOTSTRAP} --variant=buildd --foreign --arch=$DEB_ARCH $DEB_TYPE . http://httpredir.debian.org/debian || exit 1
+exit 0
diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker
new file mode 100644
index 0000000000..1d26a8e98a
--- /dev/null
+++ b/tests/docker/dockerfiles/fedora.docker
@@ -0,0 +1,7 @@
+FROM fedora:23
+RUN dnf install -y \
+ ccache git tar PyYAML sparse flex bison \
+ glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel \
+ gcc gcc-c++ clang make perl which bc findutils \
+ mingw{32,64}-{pixman,glib2,gmp,SDL,pkg-config,gtk2,gtk3,gnutls,nettle,libtasn1,libjpeg-turbo,libpng,curl,libssh2,bzip2}
+ENV FEATURES mingw clang pyyaml
diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker
new file mode 100644
index 0000000000..a8b88c318c
--- /dev/null
+++ b/tests/docker/dockerfiles/ubuntu.docker
@@ -0,0 +1,11 @@
+FROM ubuntu:14.04
+RUN echo "deb http://archive.ubuntu.com/ubuntu/ trusty universe multiverse" >> \
+ /etc/apt/sources.list
+RUN apt-get update
+RUN apt-get -y install flex bison \
+ libusb-1.0-0-dev libiscsi-dev librados-dev libncurses5-dev \
+ libseccomp-dev libgnutls-dev libssh2-1-dev libspice-server-dev \
+ libspice-protocol-dev libnss3-dev libfdt-dev \
+ libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev \
+ git make ccache python-yaml gcc clang sparse
+ENV FEATURES clang pyyaml
diff --git a/tests/docker/run b/tests/docker/run
new file mode 100755
index 0000000000..d85d49afc1
--- /dev/null
+++ b/tests/docker/run
@@ -0,0 +1,68 @@
+#!/bin/bash -e
+#
+# Docker test runner
+#
+# Copyright (c) 2016 Red Hat Inc.
+#
+# Authors:
+# Fam Zheng <famz@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2
+# or (at your option) any later version. See the COPYING file in
+# the top-level directory.
+
+set -e
+
+if test -n "$V"; then
+ set -x
+fi
+
+BASE="$(dirname $(readlink -e $0))"
+
+# Prepare the environment
+. /etc/profile || true
+export PATH=/usr/lib/ccache:$PATH
+
+if test -n "$J"; then
+ export MAKEFLAGS="$MAKEFLAGS -j$J"
+fi
+
+# We are in the container so the whole file system belong to us
+export TEST_DIR=/tmp/qemu-test
+mkdir -p $TEST_DIR/{src,build,install}
+
+# Extract the source tarballs
+tar -C $TEST_DIR/src -xzf $BASE/qemu.tgz
+for p in dtc pixman; do
+ if test -f $BASE/$p.tgz; then
+ tar -C $TEST_DIR/src/$p -xzf $BASE/$p.tgz
+ export FEATURES="$FEATURES $p"
+ fi
+done
+
+export QEMU_SRC="$TEST_DIR/src"
+
+cd "$QEMU_SRC/tests/docker"
+
+CMD="$QEMU_SRC/tests/docker/$@"
+
+if test -n "$DEBUG"; then
+ echo "* Prepared to run command:"
+ echo " $CMD"
+ echo "* Hit Ctrl-D to continue, or type 'exit 1' to abort"
+ echo
+ $SHELL
+fi
+
+if "$CMD"; then
+ exit 0
+elif test -n "$DEBUG"; then
+ echo "* Command failed:"
+ echo " $CMD"
+ echo "* Hit Ctrl-D to exit"
+ echo
+ # Force error after shell exits
+ $SHELL && exit 1
+else
+ exit 1
+fi
diff --git a/tests/docker/test-clang b/tests/docker/test-clang
new file mode 100755
index 0000000000..60e4e976b3
--- /dev/null
+++ b/tests/docker/test-clang
@@ -0,0 +1,24 @@
+#!/bin/bash -e
+#
+# Compile and check with clang.
+#
+# Copyright (c) 2016 Red Hat Inc.
+#
+# Authors:
+# Fam Zheng <famz@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2
+# or (at your option) any later version. See the COPYING file in
+# the top-level directory.
+
+. common.rc
+
+requires clang
+
+OPTS="--enable-debug --cxx=clang++ --cc=clang --host-cc=clang"
+# -fsanitize=undefined is broken on Fedora 23, skip it for now
+# See also: https://bugzilla.redhat.com/show_bug.cgi?id=1263834
+#OPTS="$OPTS --extra-cflags=-fsanitize=undefined \
+ #--extra-cflags=-fno-sanitize=float-divide-by-zero"
+build_qemu $OPTS
+make $MAKEFLAGS check
diff --git a/tests/docker/test-full b/tests/docker/test-full
new file mode 100755
index 0000000000..fd9b798947
--- /dev/null
+++ b/tests/docker/test-full
@@ -0,0 +1,17 @@
+#!/bin/bash -e
+#
+# Compile all the targets.
+#
+# Copyright (c) 2016 Red Hat Inc.
+#
+# Authors:
+# Fam Zheng <famz@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2
+# or (at your option) any later version. See the COPYING file in
+# the top-level directory.
+
+. common.rc
+
+build_qemu
+make check $MAKEFLAGS
diff --git a/tests/docker/test-mingw b/tests/docker/test-mingw
new file mode 100755
index 0000000000..c03757add8
--- /dev/null
+++ b/tests/docker/test-mingw
@@ -0,0 +1,34 @@
+#!/bin/bash -e
+#
+# Cross compile QEMU with mingw toolchain on Linux.
+#
+# Copyright (c) 2016 Red Hat Inc.
+#
+# Authors:
+# Fam Zheng <famz@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2
+# or (at your option) any later version. See the COPYING file in
+# the top-level directory.
+
+. common.rc
+
+requires mingw dtc
+
+for prefix in x86_64-w64-mingw32- i686-w64-mingw32-; do
+ TARGET_LIST=x86_64-softmmu,aarch64-softmmu \
+ build_qemu --cross-prefix=$prefix \
+ --enable-trace-backends=simple \
+ --enable-debug \
+ --enable-gnutls \
+ --enable-nettle \
+ --enable-curl \
+ --enable-vnc \
+ --enable-bzip2 \
+ --enable-guest-agent \
+ --with-sdlabi=1.2 \
+ --with-gtkabi=2.0
+ make clean
+
+done
+
diff --git a/tests/docker/test-quick b/tests/docker/test-quick
new file mode 100755
index 0000000000..07cdc59a10
--- /dev/null
+++ b/tests/docker/test-quick
@@ -0,0 +1,19 @@
+#!/bin/bash -e
+#
+# Quick compiling test that everyone already does. But why not automate it?
+#
+# Copyright (c) 2016 Red Hat Inc.
+#
+# Authors:
+# Fam Zheng <famz@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2
+# or (at your option) any later version. See the COPYING file in
+# the top-level directory.
+
+. common.rc
+
+DEF_TARGET_LIST="$(echo {x86_64,aarch64}-softmmu)"
+TARGET_LIST=${TARGET_LIST:-$DEF_TARGET_LIST} \
+build_qemu
+make check $MAKEFLAGS
diff --git a/tests/docker/travis b/tests/docker/travis
new file mode 100755
index 0000000000..d345393ced
--- /dev/null
+++ b/tests/docker/travis
@@ -0,0 +1,21 @@
+#!/bin/bash -e
+#
+# Mimic a travis testing matrix
+#
+# Copyright (c) 2016 Red Hat Inc.
+#
+# Authors:
+# Fam Zheng <famz@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2
+# or (at your option) any later version. See the COPYING file in
+# the top-level directory.
+
+. common.rc
+
+requires pyyaml
+cmdfile=/tmp/travis_cmd_list.sh
+$QEMU_SRC/tests/docker/travis.py $QEMU_SRC/.travis.yml > $cmdfile
+chmod +x $cmdfile
+cd "$QEMU_SRC"
+$cmdfile
diff --git a/tests/docker/travis.py b/tests/docker/travis.py
new file mode 100755
index 0000000000..8dcc964da4
--- /dev/null
+++ b/tests/docker/travis.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+#
+# Travis YAML config parser
+#
+# Copyright (c) 2016 Red Hat Inc.
+#
+# Authors:
+# Fam Zheng <famz@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2
+# or (at your option) any later version. See the COPYING file in
+# the top-level directory.
+
+import sys
+import yaml
+import itertools
+
+def load_yaml(fname):
+ return yaml.load(open(fname, "r").read())
+
+def conf_iter(conf):
+ def env_to_list(env):
+ return env if isinstance(env, list) else [env]
+ global_env = conf["env"]["global"]
+ for entry in conf["matrix"]["include"]:
+ yield {"env": global_env + env_to_list(entry["env"]),
+ "compiler": entry["compiler"]}
+ for entry in itertools.product(conf["compiler"],
+ conf["env"]["matrix"]):
+ yield {"env": global_env + env_to_list(entry[1]),
+ "compiler": entry[0]}
+
+def main():
+ if len(sys.argv) < 2:
+ sys.stderr.write("Usage: %s <travis-file>\n" % sys.argv[0])
+ return 1
+ conf = load_yaml(sys.argv[1])
+ for config in conf_iter(conf):
+ print "("
+ print "\n".join(config["env"])
+ print "alias cc=" + config["compiler"]
+ print "\n".join(conf["before_script"])
+ print "\n".join(conf["script"])
+ print ")"
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/tests/drive_del-test.c b/tests/drive_del-test.c
index fe03236f3a..121b9c917e 100644
--- a/tests/drive_del-test.c
+++ b/tests/drive_del-test.c
@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
static void drive_add(void)
@@ -116,7 +115,8 @@ int main(int argc, char **argv)
qtest_add_func("/drive_del/without-dev", test_drive_without_dev);
/* TODO I guess any arch with PCI would do */
- if (!strcmp(arch, "i386") || !strcmp(arch, "x86_64")) {
+ if (!strcmp(arch, "i386") || !strcmp(arch, "x86_64") ||
+ !strcmp(arch, "ppc") || !strcmp(arch, "ppc64")) {
qtest_add_func("/drive_del/after_failed_device_add",
test_after_failed_device_add);
qtest_add_func("/blockdev/drive_del_device_del",
diff --git a/tests/ds1338-test.c b/tests/ds1338-test.c
index 2792415841..26968bc82a 100644
--- a/tests/ds1338-test.c
+++ b/tests/ds1338-test.c
@@ -21,8 +21,6 @@
#include "libqtest.h"
#include "libqos/i2c.h"
-#include <glib.h>
-
#define IMX25_I2C_0_BASE 0x43F80000
#define DS1338_ADDR 0x68
diff --git a/tests/e1000-test.c b/tests/e1000-test.c
index a42b3810c1..59cab68a60 100644
--- a/tests/e1000-test.c
+++ b/tests/e1000-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
diff --git a/tests/e1000e-test.c b/tests/e1000e-test.c
new file mode 100644
index 0000000000..d497b0857c
--- /dev/null
+++ b/tests/e1000e-test.c
@@ -0,0 +1,478 @@
+ /*
+ * QTest testcase for e1000e NIC
+ *
+ * Copyright (c) 2015 Ravello Systems LTD (http://ravellosystems.com)
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry@daynix.com>
+ * Leonid Bloch <leonid@daynix.com>
+ * Yan Vugenfirer <yan@daynix.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "qemu-common.h"
+#include "libqos/pci-pc.h"
+#include "qemu/sockets.h"
+#include "qemu/iov.h"
+#include "qemu/bitops.h"
+#include "libqos/malloc.h"
+#include "libqos/malloc-pc.h"
+#include "libqos/malloc-generic.h"
+
+#define E1000E_IMS (0x00d0)
+
+#define E1000E_STATUS (0x0008)
+#define E1000E_STATUS_LU BIT(1)
+#define E1000E_STATUS_ASDV1000 BIT(9)
+
+#define E1000E_CTRL (0x0000)
+#define E1000E_CTRL_RESET BIT(26)
+
+#define E1000E_RCTL (0x0100)
+#define E1000E_RCTL_EN BIT(1)
+#define E1000E_RCTL_UPE BIT(3)
+#define E1000E_RCTL_MPE BIT(4)
+
+#define E1000E_RFCTL (0x5008)
+#define E1000E_RFCTL_EXTEN BIT(15)
+
+#define E1000E_TCTL (0x0400)
+#define E1000E_TCTL_EN BIT(1)
+
+#define E1000E_CTRL_EXT (0x0018)
+#define E1000E_CTRL_EXT_DRV_LOAD BIT(28)
+#define E1000E_CTRL_EXT_TXLSFLOW BIT(22)
+
+#define E1000E_RX0_MSG_ID (0)
+#define E1000E_TX0_MSG_ID (1)
+#define E1000E_OTHER_MSG_ID (2)
+
+#define E1000E_IVAR (0x00E4)
+#define E1000E_IVAR_TEST_CFG ((E1000E_RX0_MSG_ID << 0) | BIT(3) | \
+ (E1000E_TX0_MSG_ID << 8) | BIT(11) | \
+ (E1000E_OTHER_MSG_ID << 16) | BIT(19) | \
+ BIT(31))
+
+#define E1000E_RING_LEN (0x1000)
+#define E1000E_TXD_LEN (16)
+#define E1000E_RXD_LEN (16)
+
+#define E1000E_TDBAL (0x3800)
+#define E1000E_TDBAH (0x3804)
+#define E1000E_TDLEN (0x3808)
+#define E1000E_TDH (0x3810)
+#define E1000E_TDT (0x3818)
+
+#define E1000E_RDBAL (0x2800)
+#define E1000E_RDBAH (0x2804)
+#define E1000E_RDLEN (0x2808)
+#define E1000E_RDH (0x2810)
+#define E1000E_RDT (0x2818)
+
+typedef struct e1000e_device {
+ QPCIDevice *pci_dev;
+ void *mac_regs;
+
+ uint64_t tx_ring;
+ uint64_t rx_ring;
+} e1000e_device;
+
+static int test_sockets[2];
+static QGuestAllocator *test_alloc;
+static QPCIBus *test_bus;
+
+static void e1000e_pci_foreach_callback(QPCIDevice *dev, int devfn, void *data)
+{
+ *(QPCIDevice **) data = dev;
+}
+
+static QPCIDevice *e1000e_device_find(QPCIBus *bus)
+{
+ static const int e1000e_vendor_id = 0x8086;
+ static const int e1000e_dev_id = 0x10D3;
+
+ QPCIDevice *e1000e_dev = NULL;
+
+ qpci_device_foreach(bus, e1000e_vendor_id, e1000e_dev_id,
+ e1000e_pci_foreach_callback, &e1000e_dev);
+
+ g_assert_nonnull(e1000e_dev);
+
+ return e1000e_dev;
+}
+
+static void e1000e_macreg_write(e1000e_device *d, uint32_t reg, uint32_t val)
+{
+ qpci_io_writel(d->pci_dev, d->mac_regs + reg, val);
+}
+
+static uint32_t e1000e_macreg_read(e1000e_device *d, uint32_t reg)
+{
+ return qpci_io_readl(d->pci_dev, d->mac_regs + reg);
+}
+
+static void e1000e_device_init(QPCIBus *bus, e1000e_device *d)
+{
+ uint32_t val;
+
+ d->pci_dev = e1000e_device_find(bus);
+
+ /* Enable the device */
+ qpci_device_enable(d->pci_dev);
+
+ /* Map BAR0 (mac registers) */
+ d->mac_regs = qpci_iomap(d->pci_dev, 0, NULL);
+ g_assert_nonnull(d->mac_regs);
+
+ /* Reset the device */
+ val = e1000e_macreg_read(d, E1000E_CTRL);
+ e1000e_macreg_write(d, E1000E_CTRL, val | E1000E_CTRL_RESET);
+
+ /* Enable and configure MSI-X */
+ qpci_msix_enable(d->pci_dev);
+ e1000e_macreg_write(d, E1000E_IVAR, E1000E_IVAR_TEST_CFG);
+
+ /* Check the device status - link and speed */
+ val = e1000e_macreg_read(d, E1000E_STATUS);
+ g_assert_cmphex(val & (E1000E_STATUS_LU | E1000E_STATUS_ASDV1000),
+ ==, E1000E_STATUS_LU | E1000E_STATUS_ASDV1000);
+
+ /* Initialize TX/RX logic */
+ e1000e_macreg_write(d, E1000E_RCTL, 0);
+ e1000e_macreg_write(d, E1000E_TCTL, 0);
+
+ /* Notify the device that the driver is ready */
+ val = e1000e_macreg_read(d, E1000E_CTRL_EXT);
+ e1000e_macreg_write(d, E1000E_CTRL_EXT,
+ val | E1000E_CTRL_EXT_DRV_LOAD | E1000E_CTRL_EXT_TXLSFLOW);
+
+ /* Allocate and setup TX ring */
+ d->tx_ring = guest_alloc(test_alloc, E1000E_RING_LEN);
+ g_assert(d->tx_ring != 0);
+
+ e1000e_macreg_write(d, E1000E_TDBAL, (uint32_t) d->tx_ring);
+ e1000e_macreg_write(d, E1000E_TDBAH, (uint32_t) (d->tx_ring >> 32));
+ e1000e_macreg_write(d, E1000E_TDLEN, E1000E_RING_LEN);
+ e1000e_macreg_write(d, E1000E_TDT, 0);
+ e1000e_macreg_write(d, E1000E_TDH, 0);
+
+ /* Enable transmit */
+ e1000e_macreg_write(d, E1000E_TCTL, E1000E_TCTL_EN);
+
+ /* Allocate and setup RX ring */
+ d->rx_ring = guest_alloc(test_alloc, E1000E_RING_LEN);
+ g_assert(d->rx_ring != 0);
+
+ e1000e_macreg_write(d, E1000E_RDBAL, (uint32_t)d->rx_ring);
+ e1000e_macreg_write(d, E1000E_RDBAH, (uint32_t)(d->rx_ring >> 32));
+ e1000e_macreg_write(d, E1000E_RDLEN, E1000E_RING_LEN);
+ e1000e_macreg_write(d, E1000E_RDT, 0);
+ e1000e_macreg_write(d, E1000E_RDH, 0);
+
+ /* Enable receive */
+ e1000e_macreg_write(d, E1000E_RFCTL, E1000E_RFCTL_EXTEN);
+ e1000e_macreg_write(d, E1000E_RCTL, E1000E_RCTL_EN |
+ E1000E_RCTL_UPE |
+ E1000E_RCTL_MPE);
+
+ /* Enable all interrupts */
+ e1000e_macreg_write(d, E1000E_IMS, 0xFFFFFFFF);
+}
+
+static void e1000e_tx_ring_push(e1000e_device *d, void *descr)
+{
+ uint32_t tail = e1000e_macreg_read(d, E1000E_TDT);
+ uint32_t len = e1000e_macreg_read(d, E1000E_TDLEN) / E1000E_TXD_LEN;
+
+ memwrite(d->tx_ring + tail * E1000E_TXD_LEN, descr, E1000E_TXD_LEN);
+ e1000e_macreg_write(d, E1000E_TDT, (tail + 1) % len);
+
+ /* Read WB data for the packet transmitted */
+ memread(d->tx_ring + tail * E1000E_TXD_LEN, descr, E1000E_TXD_LEN);
+}
+
+static void e1000e_rx_ring_push(e1000e_device *d, void *descr)
+{
+ uint32_t tail = e1000e_macreg_read(d, E1000E_RDT);
+ uint32_t len = e1000e_macreg_read(d, E1000E_RDLEN) / E1000E_RXD_LEN;
+
+ memwrite(d->rx_ring + tail * E1000E_RXD_LEN, descr, E1000E_RXD_LEN);
+ e1000e_macreg_write(d, E1000E_RDT, (tail + 1) % len);
+
+ /* Read WB data for the packet received */
+ memread(d->rx_ring + tail * E1000E_RXD_LEN, descr, E1000E_RXD_LEN);
+}
+
+static void e1000e_wait_isr(e1000e_device *d, uint16_t msg_id)
+{
+ guint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
+
+ do {
+ if (qpci_msix_pending(d->pci_dev, msg_id)) {
+ return;
+ }
+ clock_step(10000);
+ } while (g_get_monotonic_time() < end_time);
+
+ g_error("Timeout expired");
+}
+
+static void e1000e_send_verify(e1000e_device *d)
+{
+ struct {
+ uint64_t buffer_addr;
+ union {
+ uint32_t data;
+ struct {
+ uint16_t length;
+ uint8_t cso;
+ uint8_t cmd;
+ } flags;
+ } lower;
+ union {
+ uint32_t data;
+ struct {
+ uint8_t status;
+ uint8_t css;
+ uint16_t special;
+ } fields;
+ } upper;
+ } descr;
+
+ static const uint32_t dtyp_data = BIT(20);
+ static const uint32_t dtyp_ext = BIT(29);
+ static const uint32_t dcmd_rs = BIT(27);
+ static const uint32_t dcmd_eop = BIT(24);
+ static const uint32_t dsta_dd = BIT(0);
+ static const int data_len = 64;
+ char buffer[64];
+ int ret;
+ uint32_t recv_len;
+
+ /* Prepare test data buffer */
+ uint64_t data = guest_alloc(test_alloc, data_len);
+ memwrite(data, "TEST", 5);
+
+ /* Prepare TX descriptor */
+ memset(&descr, 0, sizeof(descr));
+ descr.buffer_addr = cpu_to_le64(data);
+ descr.lower.data = cpu_to_le32(dcmd_rs |
+ dcmd_eop |
+ dtyp_ext |
+ dtyp_data |
+ data_len);
+
+ /* Put descriptor to the ring */
+ e1000e_tx_ring_push(d, &descr);
+
+ /* Wait for TX WB interrupt */
+ e1000e_wait_isr(d, E1000E_TX0_MSG_ID);
+
+ /* Check DD bit */
+ g_assert_cmphex(le32_to_cpu(descr.upper.data) & dsta_dd, ==, dsta_dd);
+
+ /* Check data sent to the backend */
+ ret = qemu_recv(test_sockets[0], &recv_len, sizeof(recv_len), 0);
+ g_assert_cmpint(ret, == , sizeof(recv_len));
+ qemu_recv(test_sockets[0], buffer, 64, 0);
+ g_assert_cmpstr(buffer, == , "TEST");
+
+ /* Free test data buffer */
+ guest_free(test_alloc, data);
+}
+
+static void e1000e_receive_verify(e1000e_device *d)
+{
+ union {
+ struct {
+ uint64_t buffer_addr;
+ uint64_t reserved;
+ } read;
+ struct {
+ struct {
+ uint32_t mrq;
+ union {
+ uint32_t rss;
+ struct {
+ uint16_t ip_id;
+ uint16_t csum;
+ } csum_ip;
+ } hi_dword;
+ } lower;
+ struct {
+ uint32_t status_error;
+ uint16_t length;
+ uint16_t vlan;
+ } upper;
+ } wb;
+ } descr;
+
+ static const uint32_t esta_dd = BIT(0);
+
+ char test[] = "TEST";
+ int len = htonl(sizeof(test));
+ struct iovec iov[] = {
+ {
+ .iov_base = &len,
+ .iov_len = sizeof(len),
+ },{
+ .iov_base = test,
+ .iov_len = sizeof(test),
+ },
+ };
+
+ static const int data_len = 64;
+ char buffer[64];
+ int ret;
+
+ /* Send a dummy packet to device's socket*/
+ ret = iov_send(test_sockets[0], iov, 2, 0, sizeof(len) + sizeof(test));
+ g_assert_cmpint(ret, == , sizeof(test) + sizeof(len));
+
+ /* Prepare test data buffer */
+ uint64_t data = guest_alloc(test_alloc, data_len);
+
+ /* Prepare RX descriptor */
+ memset(&descr, 0, sizeof(descr));
+ descr.read.buffer_addr = cpu_to_le64(data);
+
+ /* Put descriptor to the ring */
+ e1000e_rx_ring_push(d, &descr);
+
+ /* Wait for TX WB interrupt */
+ e1000e_wait_isr(d, E1000E_RX0_MSG_ID);
+
+ /* Check DD bit */
+ g_assert_cmphex(le32_to_cpu(descr.wb.upper.status_error) &
+ esta_dd, ==, esta_dd);
+
+ /* Check data sent to the backend */
+ memread(data, buffer, sizeof(buffer));
+ g_assert_cmpstr(buffer, == , "TEST");
+
+ /* Free test data buffer */
+ guest_free(test_alloc, data);
+}
+
+static void e1000e_device_clear(QPCIBus *bus, e1000e_device *d)
+{
+ qpci_iounmap(d->pci_dev, d->mac_regs);
+ qpci_msix_disable(d->pci_dev);
+}
+
+static void data_test_init(e1000e_device *d)
+{
+ char *cmdline;
+
+ int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, test_sockets);
+ g_assert_cmpint(ret, != , -1);
+
+ cmdline = g_strdup_printf("-netdev socket,fd=%d,id=hs0 "
+ "-device e1000e,netdev=hs0", test_sockets[1]);
+ g_assert_nonnull(cmdline);
+
+ qtest_start(cmdline);
+ g_free(cmdline);
+
+ test_bus = qpci_init_pc();
+ g_assert_nonnull(test_bus);
+
+ test_alloc = pc_alloc_init();
+ g_assert_nonnull(test_alloc);
+
+ e1000e_device_init(test_bus, d);
+}
+
+static void data_test_clear(e1000e_device *d)
+{
+ e1000e_device_clear(test_bus, d);
+ close(test_sockets[0]);
+ pc_alloc_uninit(test_alloc);
+ qpci_free_pc(test_bus);
+ qtest_end();
+}
+
+static void test_e1000e_init(gconstpointer data)
+{
+ e1000e_device d;
+
+ data_test_init(&d);
+ data_test_clear(&d);
+}
+
+static void test_e1000e_tx(gconstpointer data)
+{
+ e1000e_device d;
+
+ data_test_init(&d);
+ e1000e_send_verify(&d);
+ data_test_clear(&d);
+}
+
+static void test_e1000e_rx(gconstpointer data)
+{
+ e1000e_device d;
+
+ data_test_init(&d);
+ e1000e_receive_verify(&d);
+ data_test_clear(&d);
+}
+
+static void test_e1000e_multiple_transfers(gconstpointer data)
+{
+ static const long iterations = 4 * 1024;
+ long i;
+
+ e1000e_device d;
+
+ data_test_init(&d);
+
+ for (i = 0; i < iterations; i++) {
+ e1000e_send_verify(&d);
+ e1000e_receive_verify(&d);
+ }
+
+ data_test_clear(&d);
+}
+
+static void test_e1000e_hotplug(gconstpointer data)
+{
+ static const uint8_t slot = 0x06;
+
+ qtest_start("-device e1000e");
+
+ qpci_plug_device_test("e1000e", "e1000e_net", slot, NULL);
+ qpci_unplug_acpi_device_test("e1000e_net", slot);
+
+ qtest_end();
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ qtest_add_data_func("e1000e/init", NULL, test_e1000e_init);
+ qtest_add_data_func("e1000e/tx", NULL, test_e1000e_tx);
+ qtest_add_data_func("e1000e/rx", NULL, test_e1000e_rx);
+ qtest_add_data_func("e1000e/multiple_transfers", NULL,
+ test_e1000e_multiple_transfers);
+ qtest_add_data_func("e1000e/hotplug", NULL, test_e1000e_hotplug);
+
+ return g_test_run();
+}
diff --git a/tests/eepro100-test.c b/tests/eepro100-test.c
index e17eed0b7a..ed23258b0f 100644
--- a/tests/eepro100-test.c
+++ b/tests/eepro100-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
static void test_device(gconstpointer data)
diff --git a/tests/endianness-test.c b/tests/endianness-test.c
index cc5bccd88e..b7a120e0a4 100644
--- a/tests/endianness-test.c
+++ b/tests/endianness-test.c
@@ -12,7 +12,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "qemu/bswap.h"
@@ -283,7 +282,6 @@ static void test_endianness_combine(gconstpointer data)
int main(int argc, char **argv)
{
const char *arch = qtest_get_arch();
- int ret;
int i;
g_test_init(&argc, &argv, NULL);
@@ -306,7 +304,5 @@ int main(int argc, char **argv)
qtest_add_data_func(path, &test_cases[i], test_endianness_combine);
}
- ret = g_test_run();
-
- return ret;
+ return g_test_run();
}
diff --git a/tests/es1370-test.c b/tests/es1370-test.c
index 824dc31c64..199fe193ce 100644
--- a/tests/es1370-test.c
+++ b/tests/es1370-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index 53df1d0d88..738c6b4a5e 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -24,7 +24,6 @@
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "qemu-common.h"
diff --git a/tests/fw_cfg-test.c b/tests/fw_cfg-test.c
index b4392c2d38..688342bed5 100644
--- a/tests/fw_cfg-test.c
+++ b/tests/fw_cfg-test.c
@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "hw/nvram/fw_cfg_keys.h"
diff --git a/tests/hd-geo-test.c b/tests/hd-geo-test.c
index c8e669ac26..12ee3929da 100644
--- a/tests/hd-geo-test.c
+++ b/tests/hd-geo-test.c
@@ -16,7 +16,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "libqtest.h"
diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c
index 05029e90b2..3542ad114e 100644
--- a/tests/i440fx-test.c
+++ b/tests/i440fx-test.c
@@ -13,8 +13,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
-#include <sys/mman.h>
#include "libqtest.h"
#include "libqos/pci.h"
@@ -396,7 +394,6 @@ static void request_pflash(FirmwareTestFixture *fixture,
int main(int argc, char **argv)
{
TestData data;
- int ret;
g_test_init(&argc, &argv, NULL);
@@ -407,6 +404,5 @@ int main(int argc, char **argv)
add_firmware_test("i440fx/firmware/bios", request_bios);
add_firmware_test("i440fx/firmware/pflash", request_pflash);
- ret = g_test_run();
- return ret;
+ return g_test_run();
}
diff --git a/tests/i82801b11-test.c b/tests/i82801b11-test.c
index c3b5ebbca1..a6e31594c9 100644
--- a/tests/i82801b11-test.c
+++ b/tests/i82801b11-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
diff --git a/tests/ide-test.c b/tests/ide-test.c
index 0d9ab4df95..1e51af2a94 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -24,7 +24,6 @@
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/libqos.h"
@@ -32,6 +31,7 @@
#include "libqos/malloc-pc.h"
#include "qemu-common.h"
+#include "qemu/bswap.h"
#include "hw/pci/pci_ids.h"
#include "hw/pci/pci_regs.h"
@@ -499,6 +499,39 @@ static void test_identify(void)
ide_test_quit();
}
+/*
+ * Write sector 1 with random data to make IDE storage dirty
+ * Needed for flush tests so that flushes actually go though the block layer
+ */
+static void make_dirty(uint8_t device)
+{
+ uint8_t status;
+ size_t len = 512;
+ uintptr_t guest_buf;
+ void* buf;
+
+ guest_buf = guest_alloc(guest_malloc, len);
+ buf = g_malloc(len);
+ g_assert(guest_buf);
+ g_assert(buf);
+
+ memwrite(guest_buf, buf, len);
+
+ PrdtEntry prdt[] = {
+ {
+ .addr = cpu_to_le32(guest_buf),
+ .size = cpu_to_le32(len | PRDT_EOT),
+ },
+ };
+
+ status = send_dma_request(CMD_WRITE_DMA, 1, 1, prdt,
+ ARRAY_SIZE(prdt), NULL);
+ g_assert_cmphex(status, ==, BM_STS_INTR);
+ assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
+
+ g_free(buf);
+}
+
static void test_flush(void)
{
uint8_t data;
@@ -507,6 +540,11 @@ static void test_flush(void)
"-drive file=blkdebug::%s,if=ide,cache=writeback,format=raw",
tmp_path);
+ qtest_irq_intercept_in(global_qtest, "ioapic");
+
+ /* Dirty media so that CMD_FLUSH_CACHE will actually go to disk */
+ make_dirty(0);
+
/* Delay the completion of the flush request until we explicitly do it */
g_free(hmp("qemu-io ide0-hd0 \"break flush_to_os A\""));
@@ -549,6 +587,11 @@ static void test_retry_flush(const char *machine)
"rerror=stop,werror=stop",
debug_path, tmp_path);
+ qtest_irq_intercept_in(global_qtest, "ioapic");
+
+ /* Dirty media so that CMD_FLUSH_CACHE will actually go to disk */
+ make_dirty(0);
+
/* FLUSH CACHE command on device 0*/
outb(IDE_BASE + reg_device, 0);
outb(IDE_BASE + reg_command, CMD_FLUSH_CACHE);
diff --git a/tests/intel-hda-test.c b/tests/intel-hda-test.c
index 1be6add9b5..b782b2e944 100644
--- a/tests/intel-hda-test.c
+++ b/tests/intel-hda-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#define HDA_ID "hda0"
@@ -32,13 +31,9 @@ static void ich9_test(void)
int main(int argc, char **argv)
{
- int ret;
-
g_test_init(&argc, &argv, NULL);
qtest_add_func("/intel-hda/ich6", ich6_test);
qtest_add_func("/intel-hda/ich9", ich9_test);
- ret = g_test_run();
-
- return ret;
+ return g_test_run();
}
diff --git a/tests/ioh3420-test.c b/tests/ioh3420-test.c
index 93eb2f7506..b54c4b9f11 100644
--- a/tests/ioh3420-test.c
+++ b/tests/ioh3420-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
diff --git a/tests/ipmi-bt-test.c b/tests/ipmi-bt-test.c
index 812907fb7b..be9005eb85 100644
--- a/tests/ipmi-bt-test.c
+++ b/tests/ipmi-bt-test.c
@@ -29,7 +29,6 @@
#include <netinet/ip.h>
#include <netinet/tcp.h>
-#include <glib.h>
#include "libqtest.h"
#include "qemu-common.h"
diff --git a/tests/ipmi-kcs-test.c b/tests/ipmi-kcs-test.c
index 42c4b974c5..3750389651 100644
--- a/tests/ipmi-kcs-test.c
+++ b/tests/ipmi-kcs-test.c
@@ -24,7 +24,6 @@
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
diff --git a/tests/ipoctal232-test.c b/tests/ipoctal232-test.c
index 846aaf5711..684914164d 100644
--- a/tests/ipoctal232-test.c
+++ b/tests/ipoctal232-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
diff --git a/tests/ivshmem-test.c b/tests/ivshmem-test.c
index c027ff1e09..0957ee7555 100644
--- a/tests/ivshmem-test.c
+++ b/tests/ivshmem-test.c
@@ -9,9 +9,7 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include <glib/gstdio.h>
-#include <sys/mman.h>
#include "contrib/ivshmem-server/ivshmem-server.h"
#include "libqos/pci-pc.h"
#include "libqtest.h"
diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c
index ac6c155c83..f3be5500e1 100644
--- a/tests/libqos/ahci.c
+++ b/tests/libqos/ahci.c
@@ -23,7 +23,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/ahci.h"
diff --git a/tests/libqos/ahci.h b/tests/libqos/ahci.h
index 71dd7a6e5a..c69fb5ae90 100644
--- a/tests/libqos/ahci.h
+++ b/tests/libqos/ahci.h
@@ -1,5 +1,5 @@
-#ifndef __libqos_ahci_h
-#define __libqos_ahci_h
+#ifndef LIBQOS_AHCI_H
+#define LIBQOS_AHCI_H
/*
* AHCI qtest library functions and definitions
diff --git a/tests/libqos/fw_cfg.c b/tests/libqos/fw_cfg.c
index 76894d5759..4d9dc3fd0b 100644
--- a/tests/libqos/fw_cfg.c
+++ b/tests/libqos/fw_cfg.c
@@ -13,7 +13,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqos/fw_cfg.h"
#include "libqtest.h"
#include "qemu/bswap.h"
diff --git a/tests/libqos/i2c-imx.c b/tests/libqos/i2c-imx.c
index 51c3468f97..1c4b4314ba 100644
--- a/tests/libqos/i2c-imx.c
+++ b/tests/libqos/i2c-imx.c
@@ -20,7 +20,6 @@
#include "qemu/osdep.h"
#include "libqos/i2c.h"
-#include <glib.h>
#include "libqtest.h"
diff --git a/tests/libqos/i2c-omap.c b/tests/libqos/i2c-omap.c
index 2028f2f146..f603fdf43c 100644
--- a/tests/libqos/i2c-omap.c
+++ b/tests/libqos/i2c-omap.c
@@ -9,7 +9,6 @@
#include "qemu/osdep.h"
#include "libqos/i2c.h"
-#include <glib.h>
#include "qemu/bswap.h"
#include "libqtest.h"
diff --git a/tests/libqos/libqos-pc.h b/tests/libqos/libqos-pc.h
index b1820c5739..a0e4c45516 100644
--- a/tests/libqos/libqos-pc.h
+++ b/tests/libqos/libqos-pc.h
@@ -1,5 +1,5 @@
-#ifndef __libqos_pc_h
-#define __libqos_pc_h
+#ifndef LIBQOS_PC_H
+#define LIBQOS_PC_H
#include "libqos/libqos.h"
diff --git a/tests/libqos/libqos.c b/tests/libqos/libqos.c
index 79b0b29b4d..c7ba441d0b 100644
--- a/tests/libqos/libqos.c
+++ b/tests/libqos/libqos.c
@@ -1,5 +1,4 @@
#include "qemu/osdep.h"
-#include <glib.h>
#include <sys/wait.h>
#include "libqtest.h"
diff --git a/tests/libqos/libqos.h b/tests/libqos/libqos.h
index ca14d2e9fe..604980d125 100644
--- a/tests/libqos/libqos.h
+++ b/tests/libqos/libqos.h
@@ -1,5 +1,5 @@
-#ifndef __libqos_h
-#define __libqos_h
+#ifndef LIBQOS_H
+#define LIBQOS_H
#include "libqtest.h"
#include "libqos/pci.h"
diff --git a/tests/libqos/malloc-generic.c b/tests/libqos/malloc-generic.c
index 6000df2b82..33ce90b925 100644
--- a/tests/libqos/malloc-generic.c
+++ b/tests/libqos/malloc-generic.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqos/malloc-generic.h"
#include "libqos/malloc.h"
diff --git a/tests/libqos/malloc-pc.c b/tests/libqos/malloc-pc.c
index eee706bd63..dd2b900c5f 100644
--- a/tests/libqos/malloc-pc.c
+++ b/tests/libqos/malloc-pc.c
@@ -17,7 +17,6 @@
#include "hw/nvram/fw_cfg_keys.h"
#include "qemu-common.h"
-#include <glib.h>
#define PAGE_SIZE (4096)
diff --git a/tests/libqos/malloc.c b/tests/libqos/malloc.c
index c0df52f338..b8eff5f495 100644
--- a/tests/libqos/malloc.c
+++ b/tests/libqos/malloc.c
@@ -13,7 +13,7 @@
#include "qemu/osdep.h"
#include "libqos/malloc.h"
#include "qemu-common.h"
-#include <glib.h>
+#include "qemu/host-utils.h"
typedef QTAILQ_HEAD(MemList, MemBlock) MemList;
diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
index 77f15e5a0e..1ae2d3780f 100644
--- a/tests/libqos/pci-pc.c
+++ b/tests/libqos/pci-pc.c
@@ -19,7 +19,6 @@
#include "qemu-common.h"
#include "qemu/host-utils.h"
-#include <glib.h>
#define ACPI_PCIHP_ADDR 0xae00
#define PCI_EJ_BASE 0x0008
diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
index 0e104e14ed..ed78d91cea 100644
--- a/tests/libqos/pci.c
+++ b/tests/libqos/pci.c
@@ -14,7 +14,6 @@
#include "libqos/pci.h"
#include "hw/pci/pci_regs.h"
-#include <glib.h>
void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
void (*func)(QPCIDevice *dev, int devfn, void *data),
diff --git a/tests/libqos/usb.c b/tests/libqos/usb.c
index 87efb90782..f794d92da5 100644
--- a/tests/libqos/usb.c
+++ b/tests/libqos/usb.c
@@ -12,7 +12,6 @@
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "hw/usb/uhci-regs.h"
#include "libqos/usb.h"
diff --git a/tests/libqos/virtio-mmio.c b/tests/libqos/virtio-mmio.c
index a4382f3660..0cab38f296 100644
--- a/tests/libqos/virtio-mmio.c
+++ b/tests/libqos/virtio-mmio.c
@@ -8,12 +8,12 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/virtio.h"
#include "libqos/virtio-mmio.h"
#include "libqos/malloc.h"
#include "libqos/malloc-generic.h"
+#include "standard-headers/linux/virtio_ring.h"
static uint8_t qvirtio_mmio_config_readb(QVirtioDevice *d, uint64_t addr)
{
@@ -136,8 +136,8 @@ static QVirtQueue *qvirtio_mmio_virtqueue_setup(QVirtioDevice *d,
vq->free_head = 0;
vq->num_free = vq->size;
vq->align = dev->page_size;
- vq->indirect = (dev->features & QVIRTIO_F_RING_INDIRECT_DESC) != 0;
- vq->event = (dev->features & QVIRTIO_F_RING_EVENT_IDX) != 0;
+ vq->indirect = (dev->features & (1u << VIRTIO_RING_F_INDIRECT_DESC)) != 0;
+ vq->event = (dev->features & (1u << VIRTIO_RING_F_EVENT_IDX)) != 0;
writel(dev->addr + QVIRTIO_MMIO_QUEUE_NUM, vq->size);
@@ -154,6 +154,13 @@ static QVirtQueue *qvirtio_mmio_virtqueue_setup(QVirtioDevice *d,
return vq;
}
+static void qvirtio_mmio_virtqueue_cleanup(QVirtQueue *vq,
+ QGuestAllocator *alloc)
+{
+ guest_free(alloc, vq->desc);
+ g_free(vq);
+}
+
static void qvirtio_mmio_virtqueue_kick(QVirtioDevice *d, QVirtQueue *vq)
{
QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
@@ -176,6 +183,7 @@ const QVirtioBus qvirtio_mmio = {
.get_queue_size = qvirtio_mmio_get_queue_size,
.set_queue_address = qvirtio_mmio_set_queue_address,
.virtqueue_setup = qvirtio_mmio_virtqueue_setup,
+ .virtqueue_cleanup = qvirtio_mmio_virtqueue_cleanup,
.virtqueue_kick = qvirtio_mmio_virtqueue_kick,
};
diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c
index fde2ff0bcb..18b92b95dc 100644
--- a/tests/libqos/virtio-pci.c
+++ b/tests/libqos/virtio-pci.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/virtio.h"
#include "libqos/virtio-pci.h"
@@ -16,7 +15,10 @@
#include "libqos/pci-pc.h"
#include "libqos/malloc.h"
#include "libqos/malloc-pc.h"
+#include "standard-headers/linux/virtio_ring.h"
+#include "standard-headers/linux/virtio_pci.h"
+#include "hw/pci/pci.h"
#include "hw/pci/pci_regs.h"
typedef struct QVirtioPCIForeachData {
@@ -102,31 +104,31 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t addr)
static uint32_t qvirtio_pci_get_features(QVirtioDevice *d)
{
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- return qpci_io_readl(dev->pdev, dev->addr + QVIRTIO_PCI_DEVICE_FEATURES);
+ return qpci_io_readl(dev->pdev, dev->addr + VIRTIO_PCI_HOST_FEATURES);
}
static void qvirtio_pci_set_features(QVirtioDevice *d, uint32_t features)
{
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- qpci_io_writel(dev->pdev, dev->addr + QVIRTIO_PCI_GUEST_FEATURES, features);
+ qpci_io_writel(dev->pdev, dev->addr + VIRTIO_PCI_GUEST_FEATURES, features);
}
static uint32_t qvirtio_pci_get_guest_features(QVirtioDevice *d)
{
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- return qpci_io_readl(dev->pdev, dev->addr + QVIRTIO_PCI_GUEST_FEATURES);
+ return qpci_io_readl(dev->pdev, dev->addr + VIRTIO_PCI_GUEST_FEATURES);
}
static uint8_t qvirtio_pci_get_status(QVirtioDevice *d)
{
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_PCI_DEVICE_STATUS);
+ return qpci_io_readb(dev->pdev, dev->addr + VIRTIO_PCI_STATUS);
}
static void qvirtio_pci_set_status(QVirtioDevice *d, uint8_t status)
{
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- qpci_io_writeb(dev->pdev, dev->addr + QVIRTIO_PCI_DEVICE_STATUS, status);
+ qpci_io_writeb(dev->pdev, dev->addr + VIRTIO_PCI_STATUS, status);
}
static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
@@ -150,7 +152,7 @@ static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
}
}
} else {
- return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_PCI_ISR_STATUS) & 1;
+ return qpci_io_readb(dev->pdev, dev->addr + VIRTIO_PCI_ISR) & 1;
}
}
@@ -174,26 +176,26 @@ static bool qvirtio_pci_get_config_isr_status(QVirtioDevice *d)
}
}
} else {
- return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_PCI_ISR_STATUS) & 2;
+ return qpci_io_readb(dev->pdev, dev->addr + VIRTIO_PCI_ISR) & 2;
}
}
static void qvirtio_pci_queue_select(QVirtioDevice *d, uint16_t index)
{
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- qpci_io_writeb(dev->pdev, dev->addr + QVIRTIO_PCI_QUEUE_SELECT, index);
+ qpci_io_writeb(dev->pdev, dev->addr + VIRTIO_PCI_QUEUE_SEL, index);
}
static uint16_t qvirtio_pci_get_queue_size(QVirtioDevice *d)
{
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- return qpci_io_readw(dev->pdev, dev->addr + QVIRTIO_PCI_QUEUE_SIZE);
+ return qpci_io_readw(dev->pdev, dev->addr + VIRTIO_PCI_QUEUE_NUM);
}
static void qvirtio_pci_set_queue_address(QVirtioDevice *d, uint32_t pfn)
{
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- qpci_io_writel(dev->pdev, dev->addr + QVIRTIO_PCI_QUEUE_ADDRESS, pfn);
+ qpci_io_writel(dev->pdev, dev->addr + VIRTIO_PCI_QUEUE_PFN, pfn);
}
static QVirtQueue *qvirtio_pci_virtqueue_setup(QVirtioDevice *d,
@@ -211,9 +213,9 @@ static QVirtQueue *qvirtio_pci_virtqueue_setup(QVirtioDevice *d,
vqpci->vq.size = qvirtio_pci_get_queue_size(d);
vqpci->vq.free_head = 0;
vqpci->vq.num_free = vqpci->vq.size;
- vqpci->vq.align = QVIRTIO_PCI_ALIGN;
- vqpci->vq.indirect = (feat & QVIRTIO_F_RING_INDIRECT_DESC) != 0;
- vqpci->vq.event = (feat & QVIRTIO_F_RING_EVENT_IDX) != 0;
+ vqpci->vq.align = VIRTIO_PCI_VRING_ALIGN;
+ vqpci->vq.indirect = (feat & (1u << VIRTIO_RING_F_INDIRECT_DESC)) != 0;
+ vqpci->vq.event = (feat & (1u << VIRTIO_RING_F_EVENT_IDX)) != 0;
vqpci->msix_entry = -1;
vqpci->msix_addr = 0;
@@ -225,17 +227,27 @@ static QVirtQueue *qvirtio_pci_virtqueue_setup(QVirtioDevice *d,
/* Check power of 2 */
g_assert_cmpint(vqpci->vq.size & (vqpci->vq.size - 1), ==, 0);
- addr = guest_alloc(alloc, qvring_size(vqpci->vq.size, QVIRTIO_PCI_ALIGN));
+ addr = guest_alloc(alloc, qvring_size(vqpci->vq.size,
+ VIRTIO_PCI_VRING_ALIGN));
qvring_init(alloc, &vqpci->vq, addr);
- qvirtio_pci_set_queue_address(d, vqpci->vq.desc / QVIRTIO_PCI_ALIGN);
+ qvirtio_pci_set_queue_address(d, vqpci->vq.desc / VIRTIO_PCI_VRING_ALIGN);
return &vqpci->vq;
}
+static void qvirtio_pci_virtqueue_cleanup(QVirtQueue *vq,
+ QGuestAllocator *alloc)
+{
+ QVirtQueuePCI *vqpci = container_of(vq, QVirtQueuePCI, vq);
+
+ guest_free(alloc, vq->desc);
+ g_free(vqpci);
+}
+
static void qvirtio_pci_virtqueue_kick(QVirtioDevice *d, QVirtQueue *vq)
{
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
- qpci_io_writew(dev->pdev, dev->addr + QVIRTIO_PCI_QUEUE_NOTIFY, vq->index);
+ qpci_io_writew(dev->pdev, dev->addr + VIRTIO_PCI_QUEUE_NOTIFY, vq->index);
}
const QVirtioBus qvirtio_pci = {
@@ -254,6 +266,7 @@ const QVirtioBus qvirtio_pci = {
.get_queue_size = qvirtio_pci_get_queue_size,
.set_queue_address = qvirtio_pci_set_queue_address,
.virtqueue_setup = qvirtio_pci_virtqueue_setup,
+ .virtqueue_cleanup = qvirtio_pci_virtqueue_cleanup,
.virtqueue_kick = qvirtio_pci_virtqueue_kick,
};
@@ -264,7 +277,7 @@ void qvirtio_pci_foreach(QPCIBus *bus, uint16_t device_type,
.device_type = device_type,
.user_data = data };
- qpci_device_foreach(bus, QVIRTIO_VENDOR_ID, -1,
+ qpci_device_foreach(bus, PCI_VENDOR_ID_REDHAT_QUMRANET, -1,
qvirtio_pci_foreach_callback, &d);
}
@@ -315,9 +328,9 @@ void qvirtqueue_pci_msix_setup(QVirtioPCIDevice *d, QVirtQueuePCI *vqpci,
control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
qvirtio_pci_queue_select(&d->vdev, vqpci->vq.index);
- qpci_io_writew(d->pdev, d->addr + QVIRTIO_PCI_MSIX_QUEUE_VECTOR, entry);
- vector = qpci_io_readw(d->pdev, d->addr + QVIRTIO_PCI_MSIX_QUEUE_VECTOR);
- g_assert_cmphex(vector, !=, QVIRTIO_MSI_NO_VECTOR);
+ qpci_io_writew(d->pdev, d->addr + VIRTIO_MSI_QUEUE_VECTOR, entry);
+ vector = qpci_io_readw(d->pdev, d->addr + VIRTIO_MSI_QUEUE_VECTOR);
+ g_assert_cmphex(vector, !=, VIRTIO_MSI_NO_VECTOR);
}
void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d,
@@ -347,7 +360,7 @@ void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d,
qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL,
control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
- qpci_io_writew(d->pdev, d->addr + QVIRTIO_PCI_MSIX_CONF_VECTOR, entry);
- vector = qpci_io_readw(d->pdev, d->addr + QVIRTIO_PCI_MSIX_CONF_VECTOR);
- g_assert_cmphex(vector, !=, QVIRTIO_MSI_NO_VECTOR);
+ qpci_io_writew(d->pdev, d->addr + VIRTIO_MSI_CONFIG_VECTOR, entry);
+ vector = qpci_io_readw(d->pdev, d->addr + VIRTIO_MSI_CONFIG_VECTOR);
+ g_assert_cmphex(vector, !=, VIRTIO_MSI_NO_VECTOR);
}
diff --git a/tests/libqos/virtio-pci.h b/tests/libqos/virtio-pci.h
index 8f0e52ad47..efcac2d3de 100644
--- a/tests/libqos/virtio-pci.h
+++ b/tests/libqos/virtio-pci.h
@@ -13,23 +13,6 @@
#include "libqos/virtio.h"
#include "libqos/pci.h"
-#define QVIRTIO_PCI_DEVICE_FEATURES 0x00
-#define QVIRTIO_PCI_GUEST_FEATURES 0x04
-#define QVIRTIO_PCI_QUEUE_ADDRESS 0x08
-#define QVIRTIO_PCI_QUEUE_SIZE 0x0C
-#define QVIRTIO_PCI_QUEUE_SELECT 0x0E
-#define QVIRTIO_PCI_QUEUE_NOTIFY 0x10
-#define QVIRTIO_PCI_DEVICE_STATUS 0x12
-#define QVIRTIO_PCI_ISR_STATUS 0x13
-#define QVIRTIO_PCI_MSIX_CONF_VECTOR 0x14
-#define QVIRTIO_PCI_MSIX_QUEUE_VECTOR 0x16
-#define QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX 0x18
-#define QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX 0x14
-
-#define QVIRTIO_PCI_ALIGN 4096
-
-#define QVIRTIO_MSI_NO_VECTOR 0xFFFF
-
typedef struct QVirtioPCIDevice {
QVirtioDevice vdev;
QPCIDevice *pdev;
diff --git a/tests/libqos/virtio.c b/tests/libqos/virtio.c
index 613decea5a..d8c2970de7 100644
--- a/tests/libqos/virtio.c
+++ b/tests/libqos/virtio.c
@@ -8,9 +8,10 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/virtio.h"
+#include "standard-headers/linux/virtio_config.h"
+#include "standard-headers/linux/virtio_ring.h"
uint8_t qvirtio_config_readb(const QVirtioBus *bus, QVirtioDevice *d,
uint64_t addr)
@@ -53,30 +54,36 @@ QVirtQueue *qvirtqueue_setup(const QVirtioBus *bus, QVirtioDevice *d,
return bus->virtqueue_setup(d, alloc, index);
}
+void qvirtqueue_cleanup(const QVirtioBus *bus, QVirtQueue *vq,
+ QGuestAllocator *alloc)
+{
+ return bus->virtqueue_cleanup(vq, alloc);
+}
+
void qvirtio_reset(const QVirtioBus *bus, QVirtioDevice *d)
{
- bus->set_status(d, QVIRTIO_RESET);
- g_assert_cmphex(bus->get_status(d), ==, QVIRTIO_RESET);
+ bus->set_status(d, 0);
+ g_assert_cmphex(bus->get_status(d), ==, 0);
}
void qvirtio_set_acknowledge(const QVirtioBus *bus, QVirtioDevice *d)
{
- bus->set_status(d, bus->get_status(d) | QVIRTIO_ACKNOWLEDGE);
- g_assert_cmphex(bus->get_status(d), ==, QVIRTIO_ACKNOWLEDGE);
+ bus->set_status(d, bus->get_status(d) | VIRTIO_CONFIG_S_ACKNOWLEDGE);
+ g_assert_cmphex(bus->get_status(d), ==, VIRTIO_CONFIG_S_ACKNOWLEDGE);
}
void qvirtio_set_driver(const QVirtioBus *bus, QVirtioDevice *d)
{
- bus->set_status(d, bus->get_status(d) | QVIRTIO_DRIVER);
+ bus->set_status(d, bus->get_status(d) | VIRTIO_CONFIG_S_DRIVER);
g_assert_cmphex(bus->get_status(d), ==,
- QVIRTIO_DRIVER | QVIRTIO_ACKNOWLEDGE);
+ VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_ACKNOWLEDGE);
}
void qvirtio_set_driver_ok(const QVirtioBus *bus, QVirtioDevice *d)
{
- bus->set_status(d, bus->get_status(d) | QVIRTIO_DRIVER_OK);
- g_assert_cmphex(bus->get_status(d), ==,
- QVIRTIO_DRIVER_OK | QVIRTIO_DRIVER | QVIRTIO_ACKNOWLEDGE);
+ bus->set_status(d, bus->get_status(d) | VIRTIO_CONFIG_S_DRIVER_OK);
+ g_assert_cmphex(bus->get_status(d), ==, VIRTIO_CONFIG_S_DRIVER_OK |
+ VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_ACKNOWLEDGE);
}
void qvirtio_wait_queue_isr(const QVirtioBus *bus, QVirtioDevice *d,
@@ -134,7 +141,7 @@ void qvring_init(const QGuestAllocator *alloc, QVirtQueue *vq, uint64_t addr)
int i;
vq->desc = addr;
- vq->avail = vq->desc + vq->size*sizeof(QVRingDesc);
+ vq->avail = vq->desc + vq->size * sizeof(struct vring_desc);
vq->used = (uint64_t)((vq->avail + sizeof(uint16_t) * (3 + vq->size)
+ vq->align - 1) & ~(vq->align - 1));
@@ -155,7 +162,7 @@ void qvring_init(const QGuestAllocator *alloc, QVirtQueue *vq, uint64_t addr)
/* vq->used->flags */
writew(vq->used, 0);
/* vq->used->avail_event */
- writew(vq->used+2+(sizeof(struct QVRingUsedElem)*vq->size), 0);
+ writew(vq->used + 2 + sizeof(struct vring_used_elem) * vq->size, 0);
}
QVRingIndirectDesc *qvring_indirect_desc_setup(QVirtioDevice *d,
@@ -166,13 +173,13 @@ QVRingIndirectDesc *qvring_indirect_desc_setup(QVirtioDevice *d,
indirect->index = 0;
indirect->elem = elem;
- indirect->desc = guest_alloc(alloc, sizeof(QVRingDesc)*elem);
+ indirect->desc = guest_alloc(alloc, sizeof(struct vring_desc) * elem);
for (i = 0; i < elem - 1; ++i) {
/* indirect->desc[i].addr */
writeq(indirect->desc + (16 * i), 0);
/* indirect->desc[i].flags */
- writew(indirect->desc + (16 * i) + 12, QVRING_DESC_F_NEXT);
+ writew(indirect->desc + (16 * i) + 12, VRING_DESC_F_NEXT);
/* indirect->desc[i].next */
writew(indirect->desc + (16 * i) + 14, i + 1);
}
@@ -190,7 +197,7 @@ void qvring_indirect_desc_add(QVRingIndirectDesc *indirect, uint64_t data,
flags = readw(indirect->desc + (16 * indirect->index) + 12);
if (write) {
- flags |= QVRING_DESC_F_WRITE;
+ flags |= VRING_DESC_F_WRITE;
}
/* indirect->desc[indirect->index].addr */
@@ -210,11 +217,11 @@ uint32_t qvirtqueue_add(QVirtQueue *vq, uint64_t data, uint32_t len, bool write,
vq->num_free--;
if (write) {
- flags |= QVRING_DESC_F_WRITE;
+ flags |= VRING_DESC_F_WRITE;
}
if (next) {
- flags |= QVRING_DESC_F_NEXT;
+ flags |= VRING_DESC_F_NEXT;
}
/* vq->desc[vq->free_head].addr */
@@ -239,9 +246,9 @@ uint32_t qvirtqueue_add_indirect(QVirtQueue *vq, QVRingIndirectDesc *indirect)
writeq(vq->desc + (16 * vq->free_head), indirect->desc);
/* vq->desc[vq->free_head].len */
writel(vq->desc + (16 * vq->free_head) + 8,
- sizeof(QVRingDesc) * indirect->elem);
+ sizeof(struct vring_desc) * indirect->elem);
/* vq->desc[vq->free_head].flags */
- writew(vq->desc + (16 * vq->free_head) + 12, QVRING_DESC_F_INDIRECT);
+ writew(vq->desc + (16 * vq->free_head) + 12, VRING_DESC_F_INDIRECT);
return vq->free_head++; /* Return and increase, in this order */
}
@@ -264,10 +271,10 @@ void qvirtqueue_kick(const QVirtioBus *bus, QVirtioDevice *d, QVirtQueue *vq,
/* Must read after idx is updated */
flags = readw(vq->avail);
avail_event = readw(vq->used + 4 +
- (sizeof(struct QVRingUsedElem) * vq->size));
+ sizeof(struct vring_used_elem) * vq->size);
/* < 1 because we add elements to avail queue one by one */
- if ((flags & QVRING_USED_F_NO_NOTIFY) == 0 &&
+ if ((flags & VRING_USED_F_NO_NOTIFY) == 0 &&
(!vq->event || (uint16_t)(idx-avail_event) < 1)) {
bus->virtqueue_kick(d, vq);
}
diff --git a/tests/libqos/virtio.h b/tests/libqos/virtio.h
index 01012787b8..0250842bf2 100644
--- a/tests/libqos/virtio.h
+++ b/tests/libqos/virtio.h
@@ -11,78 +11,19 @@
#define LIBQOS_VIRTIO_H
#include "libqos/malloc.h"
+#include "standard-headers/linux/virtio_ring.h"
-#define QVIRTIO_VENDOR_ID 0x1AF4
-
-#define QVIRTIO_RESET 0x0
-#define QVIRTIO_ACKNOWLEDGE 0x1
-#define QVIRTIO_DRIVER 0x2
-#define QVIRTIO_DRIVER_OK 0x4
-
-#define QVIRTIO_NET_DEVICE_ID 0x1
-#define QVIRTIO_BLK_DEVICE_ID 0x2
-#define QVIRTIO_CONSOLE_DEVICE_ID 0x3
-#define QVIRTIO_RNG_DEVICE_ID 0x4
-#define QVIRTIO_BALLOON_DEVICE_ID 0x5
-#define QVIRTIO_RPMSG_DEVICE_ID 0x7
-#define QVIRTIO_SCSI_DEVICE_ID 0x8
-#define QVIRTIO_9P_DEVICE_ID 0x9
-
-#define QVIRTIO_F_NOTIFY_ON_EMPTY 0x01000000
-#define QVIRTIO_F_ANY_LAYOUT 0x08000000
-#define QVIRTIO_F_RING_INDIRECT_DESC 0x10000000
-#define QVIRTIO_F_RING_EVENT_IDX 0x20000000
#define QVIRTIO_F_BAD_FEATURE 0x40000000
-#define QVRING_DESC_F_NEXT 0x1
-#define QVRING_DESC_F_WRITE 0x2
-#define QVRING_DESC_F_INDIRECT 0x4
-
-#define QVIRTIO_F_NOTIFY_ON_EMPTY 0x01000000
-#define QVIRTIO_F_ANY_LAYOUT 0x08000000
-#define QVIRTIO_F_RING_INDIRECT_DESC 0x10000000
-#define QVIRTIO_F_RING_EVENT_IDX 0x20000000
-#define QVIRTIO_F_BAD_FEATURE 0x40000000
-
-#define QVRING_AVAIL_F_NO_INTERRUPT 1
-
-#define QVRING_USED_F_NO_NOTIFY 1
-
typedef struct QVirtioDevice {
/* Device type */
uint16_t device_type;
} QVirtioDevice;
-typedef struct QVRingDesc {
- uint64_t addr;
- uint32_t len;
- uint16_t flags;
- uint16_t next;
-} QVRingDesc;
-
-typedef struct QVRingAvail {
- uint16_t flags;
- uint16_t idx;
- uint16_t ring[0]; /* This is an array of uint16_t */
- uint16_t used_event;
-} QVRingAvail;
-
-typedef struct QVRingUsedElem {
- uint32_t id;
- uint32_t len;
-} QVRingUsedElem;
-
-typedef struct QVRingUsed {
- uint16_t flags;
- uint16_t idx;
- QVRingUsedElem ring[0]; /* This is an array of QVRingUsedElem structs */
- uint16_t avail_event;
-} QVRingUsed;
-
typedef struct QVirtQueue {
- uint64_t desc; /* This points to an array of QVRingDesc */
- uint64_t avail; /* This points to a QVRingAvail */
- uint64_t used; /* This points to a QVRingDesc */
+ uint64_t desc; /* This points to an array of struct vring_desc */
+ uint64_t avail; /* This points to a struct vring_avail */
+ uint64_t used; /* This points to a struct vring_desc */
uint16_t index;
uint32_t size;
uint32_t free_head;
@@ -93,7 +34,7 @@ typedef struct QVirtQueue {
} QVirtQueue;
typedef struct QVRingIndirectDesc {
- uint64_t desc; /* This points to an array fo QVRingDesc */
+ uint64_t desc; /* This points to an array fo struct vring_desc */
uint16_t index;
uint16_t elem;
} QVRingIndirectDesc;
@@ -138,15 +79,18 @@ typedef struct QVirtioBus {
QVirtQueue *(*virtqueue_setup)(QVirtioDevice *d, QGuestAllocator *alloc,
uint16_t index);
+ /* Free virtqueue resources */
+ void (*virtqueue_cleanup)(QVirtQueue *vq, QGuestAllocator *alloc);
+
/* Notify changes in virtqueue */
void (*virtqueue_kick)(QVirtioDevice *d, QVirtQueue *vq);
} QVirtioBus;
static inline uint32_t qvring_size(uint32_t num, uint32_t align)
{
- return ((sizeof(struct QVRingDesc) * num + sizeof(uint16_t) * (3 + num)
+ return ((sizeof(struct vring_desc) * num + sizeof(uint16_t) * (3 + num)
+ align - 1) & ~(align - 1))
- + sizeof(uint16_t) * 3 + sizeof(struct QVRingUsedElem) * num;
+ + sizeof(uint16_t) * 3 + sizeof(struct vring_used_elem) * num;
}
uint8_t qvirtio_config_readb(const QVirtioBus *bus, QVirtioDevice *d,
@@ -177,6 +121,8 @@ void qvirtio_wait_config_isr(const QVirtioBus *bus, QVirtioDevice *d,
gint64 timeout_us);
QVirtQueue *qvirtqueue_setup(const QVirtioBus *bus, QVirtioDevice *d,
QGuestAllocator *alloc, uint16_t index);
+void qvirtqueue_cleanup(const QVirtioBus *bus, QVirtQueue *vq,
+ QGuestAllocator *alloc);
void qvring_init(const QGuestAllocator *alloc, QVirtQueue *vq, uint64_t addr);
QVRingIndirectDesc *qvring_indirect_desc_setup(QVirtioDevice *d,
diff --git a/tests/libqtest.c b/tests/libqtest.c
index b12a9e4ca9..eb00f1392b 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -17,7 +17,6 @@
#include "qemu/osdep.h"
#include "libqtest.h"
-#include <glib.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
@@ -27,7 +26,7 @@
#include "qapi/qmp/qjson.h"
#define MAX_IRQ 256
-#define SOCKET_TIMEOUT 5
+#define SOCKET_TIMEOUT 50
QTestState *global_qtest;
diff --git a/tests/m48t59-test.c b/tests/m48t59-test.c
index a751fd350e..0f921ef38a 100644
--- a/tests/m48t59-test.c
+++ b/tests/m48t59-test.c
@@ -13,7 +13,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
diff --git a/tests/migration/.gitignore b/tests/migration/.gitignore
new file mode 100644
index 0000000000..84f37552e4
--- /dev/null
+++ b/tests/migration/.gitignore
@@ -0,0 +1,2 @@
+initrd-stress.img
+stress
diff --git a/tests/migration/guestperf-batch.py b/tests/migration/guestperf-batch.py
new file mode 100755
index 0000000000..cb150ce804
--- /dev/null
+++ b/tests/migration/guestperf-batch.py
@@ -0,0 +1,26 @@
+#!/usr/bin/python
+#
+# Migration test batch comparison invokation
+#
+# Copyright (c) 2016 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+import sys
+
+from guestperf.shell import BatchShell
+
+shell = BatchShell()
+sys.exit(shell.run(sys.argv[1:]))
diff --git a/tests/migration/guestperf-plot.py b/tests/migration/guestperf-plot.py
new file mode 100755
index 0000000000..d70bb7a557
--- /dev/null
+++ b/tests/migration/guestperf-plot.py
@@ -0,0 +1,26 @@
+#!/usr/bin/python
+#
+# Migration test graph plotting command
+#
+# Copyright (c) 2016 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+import sys
+
+from guestperf.shell import PlotShell
+
+shell = PlotShell()
+sys.exit(shell.run(sys.argv[1:]))
diff --git a/tests/migration/guestperf.py b/tests/migration/guestperf.py
new file mode 100755
index 0000000000..99b027e8ba
--- /dev/null
+++ b/tests/migration/guestperf.py
@@ -0,0 +1,27 @@
+#!/usr/bin/python
+#
+# Migration test direct invokation command
+#
+# Copyright (c) 2016 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+
+import sys
+
+from guestperf.shell import Shell
+
+shell = Shell()
+sys.exit(shell.run(sys.argv[1:]))
diff --git a/tests/migration/guestperf/__init__.py b/tests/migration/guestperf/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/migration/guestperf/__init__.py
diff --git a/tests/migration/guestperf/comparison.py b/tests/migration/guestperf/comparison.py
new file mode 100644
index 0000000000..d0b7df97c8
--- /dev/null
+++ b/tests/migration/guestperf/comparison.py
@@ -0,0 +1,124 @@
+#
+# Migration test scenario comparison mapping
+#
+# Copyright (c) 2016 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+from guestperf.scenario import Scenario
+
+class Comparison(object):
+ def __init__(self, name, scenarios):
+ self._name = name
+ self._scenarios = scenarios
+
+COMPARISONS = [
+ # Looking at effect of pausing guest during migration
+ # at various stages of iteration over RAM
+ Comparison("pause-iters", scenarios = [
+ Scenario("pause-iters-0",
+ pause=True, pause_iters=0),
+ Scenario("pause-iters-1",
+ pause=True, pause_iters=1),
+ Scenario("pause-iters-5",
+ pause=True, pause_iters=5),
+ Scenario("pause-iters-20",
+ pause=True, pause_iters=20),
+ ]),
+
+
+ # Looking at use of post-copy in relation to bandwidth
+ # available for migration
+ Comparison("post-copy-bandwidth", scenarios = [
+ Scenario("post-copy-bw-100mbs",
+ post_copy=True, bandwidth=12),
+ Scenario("post-copy-bw-300mbs",
+ post_copy=True, bandwidth=37),
+ Scenario("post-copy-bw-1gbs",
+ post_copy=True, bandwidth=125),
+ Scenario("post-copy-bw-10gbs",
+ post_copy=True, bandwidth=1250),
+ Scenario("post-copy-bw-100gbs",
+ post_copy=True, bandwidth=12500),
+ ]),
+
+
+ # Looking at effect of starting post-copy at different
+ # stages of the migration
+ Comparison("post-copy-iters", scenarios = [
+ Scenario("post-copy-iters-0",
+ post_copy=True, post_copy_iters=0),
+ Scenario("post-copy-iters-1",
+ post_copy=True, post_copy_iters=1),
+ Scenario("post-copy-iters-5",
+ post_copy=True, post_copy_iters=5),
+ Scenario("post-copy-iters-20",
+ post_copy=True, post_copy_iters=20),
+ ]),
+
+
+ # Looking at effect of auto-converge with different
+ # throttling percentage step rates
+ Comparison("auto-converge-iters", scenarios = [
+ Scenario("auto-converge-step-5",
+ auto_converge=True, auto_converge_step=5),
+ Scenario("auto-converge-step-10",
+ auto_converge=True, auto_converge_step=10),
+ Scenario("auto-converge-step-20",
+ auto_converge=True, auto_converge_step=20),
+ ]),
+
+
+ # Looking at use of auto-converge in relation to bandwidth
+ # available for migration
+ Comparison("auto-converge-bandwidth", scenarios = [
+ Scenario("auto-converge-bw-100mbs",
+ auto_converge=True, bandwidth=12),
+ Scenario("auto-converge-bw-300mbs",
+ auto_converge=True, bandwidth=37),
+ Scenario("auto-converge-bw-1gbs",
+ auto_converge=True, bandwidth=125),
+ Scenario("auto-converge-bw-10gbs",
+ auto_converge=True, bandwidth=1250),
+ Scenario("auto-converge-bw-100gbs",
+ auto_converge=True, bandwidth=12500),
+ ]),
+
+
+ # Looking at effect of multi-thread compression with
+ # varying numbers of threads
+ Comparison("compr-mt", scenarios = [
+ Scenario("compr-mt-threads-1",
+ compression_mt=True, compression_mt_threads=1),
+ Scenario("compr-mt-threads-2",
+ compression_mt=True, compression_mt_threads=2),
+ Scenario("compr-mt-threads-4",
+ compression_mt=True, compression_mt_threads=4),
+ ]),
+
+
+ # Looking at effect of xbzrle compression with varying
+ # cache sizes
+ Comparison("compr-xbzrle", scenarios = [
+ Scenario("compr-xbzrle-cache-5",
+ compression_xbzrle=True, compression_xbzrle_cache=5),
+ Scenario("compr-xbzrle-cache-10",
+ compression_xbzrle=True, compression_xbzrle_cache=10),
+ Scenario("compr-xbzrle-cache-20",
+ compression_xbzrle=True, compression_xbzrle_cache=10),
+ Scenario("compr-xbzrle-cache-50",
+ compression_xbzrle=True, compression_xbzrle_cache=50),
+ ]),
+]
diff --git a/tests/migration/guestperf/engine.py b/tests/migration/guestperf/engine.py
new file mode 100644
index 0000000000..0a13050bc6
--- /dev/null
+++ b/tests/migration/guestperf/engine.py
@@ -0,0 +1,439 @@
+#
+# Migration test main engine
+#
+# Copyright (c) 2016 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+
+import os
+import re
+import sys
+import time
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'scripts'))
+import qemu
+import qmp.qmp
+from guestperf.progress import Progress, ProgressStats
+from guestperf.report import Report
+from guestperf.timings import TimingRecord, Timings
+
+
+class Engine(object):
+
+ def __init__(self, binary, dst_host, kernel, initrd, transport="tcp",
+ sleep=15, verbose=False, debug=False):
+
+ self._binary = binary # Path to QEMU binary
+ self._dst_host = dst_host # Hostname of target host
+ self._kernel = kernel # Path to kernel image
+ self._initrd = initrd # Path to stress initrd
+ self._transport = transport # 'unix' or 'tcp' or 'rdma'
+ self._sleep = sleep
+ self._verbose = verbose
+ self._debug = debug
+
+ if debug:
+ self._verbose = debug
+
+ def _vcpu_timing(self, pid, tid_list):
+ records = []
+ now = time.time()
+
+ jiffies_per_sec = os.sysconf(os.sysconf_names['SC_CLK_TCK'])
+ for tid in tid_list:
+ statfile = "/proc/%d/task/%d/stat" % (pid, tid)
+ with open(statfile, "r") as fh:
+ stat = fh.readline()
+ fields = stat.split(" ")
+ stime = int(fields[13])
+ utime = int(fields[14])
+ records.append(TimingRecord(tid, now, 1000 * (stime + utime) / jiffies_per_sec))
+ return records
+
+ def _cpu_timing(self, pid):
+ records = []
+ now = time.time()
+
+ jiffies_per_sec = os.sysconf(os.sysconf_names['SC_CLK_TCK'])
+ statfile = "/proc/%d/stat" % pid
+ with open(statfile, "r") as fh:
+ stat = fh.readline()
+ fields = stat.split(" ")
+ stime = int(fields[13])
+ utime = int(fields[14])
+ return TimingRecord(pid, now, 1000 * (stime + utime) / jiffies_per_sec)
+
+ def _migrate_progress(self, vm):
+ info = vm.command("query-migrate")
+
+ if "ram" not in info:
+ info["ram"] = {}
+
+ return Progress(
+ info.get("status", "active"),
+ ProgressStats(
+ info["ram"].get("transferred", 0),
+ info["ram"].get("remaining", 0),
+ info["ram"].get("total", 0),
+ info["ram"].get("duplicate", 0),
+ info["ram"].get("skipped", 0),
+ info["ram"].get("normal", 0),
+ info["ram"].get("normal-bytes", 0),
+ info["ram"].get("dirty-pages-rate", 0),
+ info["ram"].get("mbps", 0),
+ info["ram"].get("dirty-sync-count", 0)
+ ),
+ time.time(),
+ info.get("total-time", 0),
+ info.get("downtime", 0),
+ info.get("expected-downtime", 0),
+ info.get("setup-time", 0),
+ info.get("x-cpu-throttle-percentage", 0),
+ )
+
+ def _migrate(self, hardware, scenario, src, dst, connect_uri):
+ src_qemu_time = []
+ src_vcpu_time = []
+ src_pid = src.get_pid()
+
+ vcpus = src.command("query-cpus")
+ src_threads = []
+ for vcpu in vcpus:
+ src_threads.append(vcpu["thread_id"])
+
+ # XXX how to get dst timings on remote host ?
+
+ if self._verbose:
+ print "Sleeping %d seconds for initial guest workload run" % self._sleep
+ sleep_secs = self._sleep
+ while sleep_secs > 1:
+ src_qemu_time.append(self._cpu_timing(src_pid))
+ src_vcpu_time.extend(self._vcpu_timing(src_pid, src_threads))
+ time.sleep(1)
+ sleep_secs -= 1
+
+ if self._verbose:
+ print "Starting migration"
+ if scenario._auto_converge:
+ resp = src.command("migrate-set-capabilities",
+ capabilities = [
+ { "capability": "auto-converge",
+ "state": True }
+ ])
+ resp = src.command("migrate-set-parameters",
+ x_cpu_throttle_increment=scenario._auto_converge_step)
+
+ if scenario._post_copy:
+ resp = src.command("migrate-set-capabilities",
+ capabilities = [
+ { "capability": "postcopy-ram",
+ "state": True }
+ ])
+ resp = dst.command("migrate-set-capabilities",
+ capabilities = [
+ { "capability": "postcopy-ram",
+ "state": True }
+ ])
+
+ resp = src.command("migrate_set_speed",
+ value=scenario._bandwidth * 1024 * 1024)
+
+ resp = src.command("migrate_set_downtime",
+ value=scenario._downtime / 1024.0)
+
+ if scenario._compression_mt:
+ resp = src.command("migrate-set-capabilities",
+ capabilities = [
+ { "capability": "compress",
+ "state": True }
+ ])
+ resp = src.command("migrate-set-parameters",
+ compress_threads=scenario._compression_mt_threads)
+ resp = dst.command("migrate-set-capabilities",
+ capabilities = [
+ { "capability": "compress",
+ "state": True }
+ ])
+ resp = dst.command("migrate-set-parameters",
+ decompress_threads=scenario._compression_mt_threads)
+
+ if scenario._compression_xbzrle:
+ resp = src.command("migrate-set-capabilities",
+ capabilities = [
+ { "capability": "xbzrle",
+ "state": True }
+ ])
+ resp = dst.command("migrate-set-capabilities",
+ capabilities = [
+ { "capability": "xbzrle",
+ "state": True }
+ ])
+ resp = src.command("migrate-set-cache-size",
+ value=(hardware._mem * 1024 * 1024 * 1024 / 100 *
+ scenario._compression_xbzrle_cache))
+
+ resp = src.command("migrate", uri=connect_uri)
+
+ post_copy = False
+ paused = False
+
+ progress_history = []
+
+ start = time.time()
+ loop = 0
+ while True:
+ loop = loop + 1
+ time.sleep(0.05)
+
+ progress = self._migrate_progress(src)
+ if (loop % 20) == 0:
+ src_qemu_time.append(self._cpu_timing(src_pid))
+ src_vcpu_time.extend(self._vcpu_timing(src_pid, src_threads))
+
+ if (len(progress_history) == 0 or
+ (progress_history[-1]._ram._iterations <
+ progress._ram._iterations)):
+ progress_history.append(progress)
+
+ if progress._status in ("completed", "failed", "cancelled"):
+ if progress._status == "completed" and paused:
+ dst.command("cont")
+ if progress_history[-1] != progress:
+ progress_history.append(progress)
+
+ if progress._status == "completed":
+ if self._verbose:
+ print "Sleeping %d seconds for final guest workload run" % self._sleep
+ sleep_secs = self._sleep
+ while sleep_secs > 1:
+ time.sleep(1)
+ src_qemu_time.append(self._cpu_timing(src_pid))
+ src_vcpu_time.extend(self._vcpu_timing(src_pid, src_threads))
+ sleep_secs -= 1
+
+ return [progress_history, src_qemu_time, src_vcpu_time]
+
+ if self._verbose and (loop % 20) == 0:
+ print "Iter %d: remain %5dMB of %5dMB (total %5dMB @ %5dMb/sec)" % (
+ progress._ram._iterations,
+ progress._ram._remaining_bytes / (1024 * 1024),
+ progress._ram._total_bytes / (1024 * 1024),
+ progress._ram._transferred_bytes / (1024 * 1024),
+ progress._ram._transfer_rate_mbs,
+ )
+
+ if progress._ram._iterations > scenario._max_iters:
+ if self._verbose:
+ print "No completion after %d iterations over RAM" % scenario._max_iters
+ src.command("migrate_cancel")
+ continue
+
+ if time.time() > (start + scenario._max_time):
+ if self._verbose:
+ print "No completion after %d seconds" % scenario._max_time
+ src.command("migrate_cancel")
+ continue
+
+ if (scenario._post_copy and
+ progress._ram._iterations >= scenario._post_copy_iters and
+ not post_copy):
+ if self._verbose:
+ print "Switching to post-copy after %d iterations" % scenario._post_copy_iters
+ resp = src.command("migrate-start-postcopy")
+ post_copy = True
+
+ if (scenario._pause and
+ progress._ram._iterations >= scenario._pause_iters and
+ not paused):
+ if self._verbose:
+ print "Pausing VM after %d iterations" % scenario._pause_iters
+ resp = src.command("stop")
+ paused = True
+
+ def _get_common_args(self, hardware, tunnelled=False):
+ args = [
+ "noapic",
+ "edd=off",
+ "printk.time=1",
+ "noreplace-smp",
+ "cgroup_disable=memory",
+ "pci=noearly",
+ "console=ttyS0",
+ ]
+ if self._debug:
+ args.append("debug")
+ else:
+ args.append("quiet")
+
+ args.append("ramsize=%s" % hardware._mem)
+
+ cmdline = " ".join(args)
+ if tunnelled:
+ cmdline = "'" + cmdline + "'"
+
+ argv = [
+ "-machine", "accel=kvm",
+ "-cpu", "host",
+ "-kernel", self._kernel,
+ "-initrd", self._initrd,
+ "-append", cmdline,
+ "-chardev", "stdio,id=cdev0",
+ "-device", "isa-serial,chardev=cdev0",
+ "-m", str((hardware._mem * 1024) + 512),
+ "-smp", str(hardware._cpus),
+ ]
+
+ if self._debug:
+ argv.extend(["-device", "sga"])
+
+ if hardware._prealloc_pages:
+ argv_source += ["-mem-path", "/dev/shm",
+ "-mem-prealloc"]
+ if hardware._locked_pages:
+ argv_source += ["-realtime", "mlock=on"]
+ if hardware._huge_pages:
+ pass
+
+ return argv
+
+ def _get_src_args(self, hardware):
+ return self._get_common_args(hardware)
+
+ def _get_dst_args(self, hardware, uri):
+ tunnelled = False
+ if self._dst_host != "localhost":
+ tunnelled = True
+ argv = self._get_common_args(hardware, tunnelled)
+ return argv + ["-incoming", uri]
+
+ @staticmethod
+ def _get_common_wrapper(cpu_bind, mem_bind):
+ wrapper = []
+ if len(cpu_bind) > 0 or len(mem_bind) > 0:
+ wrapper.append("numactl")
+ if cpu_bind:
+ wrapper.append("--physcpubind=%s" % ",".join(cpu_bind))
+ if mem_bind:
+ wrapper.append("--membind=%s" % ",".join(mem_bind))
+
+ return wrapper
+
+ def _get_src_wrapper(self, hardware):
+ return self._get_common_wrapper(hardware._src_cpu_bind, hardware._src_mem_bind)
+
+ def _get_dst_wrapper(self, hardware):
+ wrapper = self._get_common_wrapper(hardware._dst_cpu_bind, hardware._dst_mem_bind)
+ if self._dst_host != "localhost":
+ return ["ssh",
+ "-R", "9001:localhost:9001",
+ self._dst_host] + wrapper
+ else:
+ return wrapper
+
+ def _get_timings(self, vm):
+ log = vm.get_log()
+ if not log:
+ return []
+ if self._debug:
+ print log
+
+ regex = r"[^\s]+\s\((\d+)\):\sINFO:\s(\d+)ms\scopied\s\d+\sGB\sin\s(\d+)ms"
+ matcher = re.compile(regex)
+ records = []
+ for line in log.split("\n"):
+ match = matcher.match(line)
+ if match:
+ records.append(TimingRecord(int(match.group(1)),
+ int(match.group(2)) / 1000.0,
+ int(match.group(3))))
+ return records
+
+ def run(self, hardware, scenario, result_dir=os.getcwd()):
+ abs_result_dir = os.path.join(result_dir, scenario._name)
+
+ if self._transport == "tcp":
+ uri = "tcp:%s:9000" % self._dst_host
+ elif self._transport == "rdma":
+ uri = "rdma:%s:9000" % self._dst_host
+ elif self._transport == "unix":
+ if self._dst_host != "localhost":
+ raise Exception("Running use unix migration transport for non-local host")
+ uri = "unix:/var/tmp/qemu-migrate-%d.migrate" % os.getpid()
+ try:
+ os.remove(uri[5:])
+ os.remove(monaddr)
+ except:
+ pass
+
+ if self._dst_host != "localhost":
+ dstmonaddr = ("localhost", 9001)
+ else:
+ dstmonaddr = "/var/tmp/qemu-dst-%d-monitor.sock" % os.getpid()
+ srcmonaddr = "/var/tmp/qemu-src-%d-monitor.sock" % os.getpid()
+
+ src = qemu.QEMUMachine(self._binary,
+ args=self._get_src_args(hardware),
+ wrapper=self._get_src_wrapper(hardware),
+ name="qemu-src-%d" % os.getpid(),
+ monitor_address=srcmonaddr,
+ debug=self._debug)
+
+ dst = qemu.QEMUMachine(self._binary,
+ args=self._get_dst_args(hardware, uri),
+ wrapper=self._get_dst_wrapper(hardware),
+ name="qemu-dst-%d" % os.getpid(),
+ monitor_address=dstmonaddr,
+ debug=self._debug)
+
+ try:
+ src.launch()
+ dst.launch()
+
+ ret = self._migrate(hardware, scenario, src, dst, uri)
+ progress_history = ret[0]
+ qemu_timings = ret[1]
+ vcpu_timings = ret[2]
+ if uri[0:5] == "unix:":
+ os.remove(uri[5:])
+ if self._verbose:
+ print "Finished migration"
+
+ src.shutdown()
+ dst.shutdown()
+
+ return Report(hardware, scenario, progress_history,
+ Timings(self._get_timings(src) + self._get_timings(dst)),
+ Timings(qemu_timings),
+ Timings(vcpu_timings),
+ self._binary, self._dst_host, self._kernel,
+ self._initrd, self._transport, self._sleep)
+ except Exception as e:
+ if self._debug:
+ print "Failed: %s" % str(e)
+ try:
+ src.shutdown()
+ except:
+ pass
+ try:
+ dst.shutdown()
+ except:
+ pass
+
+ if self._debug:
+ print src.get_log()
+ print dst.get_log()
+ raise
+
diff --git a/tests/migration/guestperf/hardware.py b/tests/migration/guestperf/hardware.py
new file mode 100644
index 0000000000..a66c9dd180
--- /dev/null
+++ b/tests/migration/guestperf/hardware.py
@@ -0,0 +1,62 @@
+#
+# Migration test hardware configuration description
+#
+# Copyright (c) 2016 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+
+class Hardware(object):
+ def __init__(self, cpus=1, mem=1,
+ src_cpu_bind=None, src_mem_bind=None,
+ dst_cpu_bind=None, dst_mem_bind=None,
+ prealloc_pages = False,
+ huge_pages=False, locked_pages=False):
+ self._cpus = cpus
+ self._mem = mem # GiB
+ self._src_mem_bind = src_mem_bind # List of NUMA nodes
+ self._src_cpu_bind = src_cpu_bind # List of pCPUs
+ self._dst_mem_bind = dst_mem_bind # List of NUMA nodes
+ self._dst_cpu_bind = dst_cpu_bind # List of pCPUs
+ self._prealloc_pages = prealloc_pages
+ self._huge_pages = huge_pages
+ self._locked_pages = locked_pages
+
+
+ def serialize(self):
+ return {
+ "cpus": self._cpus,
+ "mem": self._mem,
+ "src_mem_bind": self._src_mem_bind,
+ "dst_mem_bind": self._dst_mem_bind,
+ "src_cpu_bind": self._src_cpu_bind,
+ "dst_cpu_bind": self._dst_cpu_bind,
+ "prealloc_pages": self._prealloc_pages,
+ "huge_pages": self._huge_pages,
+ "locked_pages": self._locked_pages,
+ }
+
+ @classmethod
+ def deserialize(cls, data):
+ return cls(
+ data["cpus"],
+ data["mem"],
+ data["src_cpu_bind"],
+ data["src_mem_bind"],
+ data["dst_cpu_bind"],
+ data["dst_mem_bind"],
+ data["prealloc_pages"],
+ data["huge_pages"],
+ data["locked_pages"])
diff --git a/tests/migration/guestperf/plot.py b/tests/migration/guestperf/plot.py
new file mode 100644
index 0000000000..bc42249e16
--- /dev/null
+++ b/tests/migration/guestperf/plot.py
@@ -0,0 +1,623 @@
+#
+# Migration test graph plotting
+#
+# Copyright (c) 2016 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+import sys
+
+
+class Plot(object):
+
+ # Generated using
+ # http://tools.medialab.sciences-po.fr/iwanthue/
+ COLORS = ["#CD54D0",
+ "#79D94C",
+ "#7470CD",
+ "#D2D251",
+ "#863D79",
+ "#76DDA6",
+ "#D4467B",
+ "#61923D",
+ "#CB9CCA",
+ "#D98F36",
+ "#8CC8DA",
+ "#CE4831",
+ "#5E7693",
+ "#9B803F",
+ "#412F4C",
+ "#CECBA6",
+ "#6D3229",
+ "#598B73",
+ "#C8827C",
+ "#394427"]
+
+ def __init__(self,
+ reports,
+ migration_iters,
+ total_guest_cpu,
+ split_guest_cpu,
+ qemu_cpu,
+ vcpu_cpu):
+
+ self._reports = reports
+ self._migration_iters = migration_iters
+ self._total_guest_cpu = total_guest_cpu
+ self._split_guest_cpu = split_guest_cpu
+ self._qemu_cpu = qemu_cpu
+ self._vcpu_cpu = vcpu_cpu
+ self._color_idx = 0
+
+ def _next_color(self):
+ color = self.COLORS[self._color_idx]
+ self._color_idx += 1
+ if self._color_idx >= len(self.COLORS):
+ self._color_idx = 0
+ return color
+
+ def _get_progress_label(self, progress):
+ if progress:
+ return "\n\n" + "\n".join(
+ ["Status: %s" % progress._status,
+ "Iteration: %d" % progress._ram._iterations,
+ "Throttle: %02d%%" % progress._throttle_pcent,
+ "Dirty rate: %dMB/s" % (progress._ram._dirty_rate_pps * 4 / 1024.0)])
+ else:
+ return "\n\n" + "\n".join(
+ ["Status: %s" % "none",
+ "Iteration: %d" % 0])
+
+ def _find_start_time(self, report):
+ startqemu = report._qemu_timings._records[0]._timestamp
+ startguest = report._guest_timings._records[0]._timestamp
+ if startqemu < startguest:
+ return startqemu
+ else:
+ return stasrtguest
+
+ def _get_guest_max_value(self, report):
+ maxvalue = 0
+ for record in report._guest_timings._records:
+ if record._value > maxvalue:
+ maxvalue = record._value
+ return maxvalue
+
+ def _get_qemu_max_value(self, report):
+ maxvalue = 0
+ oldvalue = None
+ oldtime = None
+ for record in report._qemu_timings._records:
+ if oldvalue is not None:
+ cpudelta = (record._value - oldvalue) / 1000.0
+ timedelta = record._timestamp - oldtime
+ if timedelta == 0:
+ continue
+ util = cpudelta / timedelta * 100.0
+ else:
+ util = 0
+ oldvalue = record._value
+ oldtime = record._timestamp
+
+ if util > maxvalue:
+ maxvalue = util
+ return maxvalue
+
+ def _get_total_guest_cpu_graph(self, report, starttime):
+ xaxis = []
+ yaxis = []
+ labels = []
+ progress_idx = -1
+ for record in report._guest_timings._records:
+ while ((progress_idx + 1) < len(report._progress_history) and
+ report._progress_history[progress_idx + 1]._now < record._timestamp):
+ progress_idx = progress_idx + 1
+
+ if progress_idx >= 0:
+ progress = report._progress_history[progress_idx]
+ else:
+ progress = None
+
+ xaxis.append(record._timestamp - starttime)
+ yaxis.append(record._value)
+ labels.append(self._get_progress_label(progress))
+
+ from plotly import graph_objs as go
+ return go.Scatter(x=xaxis,
+ y=yaxis,
+ name="Guest PIDs: %s" % report._scenario._name,
+ mode='lines',
+ line={
+ "dash": "solid",
+ "color": self._next_color(),
+ "shape": "linear",
+ "width": 1
+ },
+ text=labels)
+
+ def _get_split_guest_cpu_graphs(self, report, starttime):
+ threads = {}
+ for record in report._guest_timings._records:
+ if record._tid in threads:
+ continue
+ threads[record._tid] = {
+ "xaxis": [],
+ "yaxis": [],
+ "labels": [],
+ }
+
+ progress_idx = -1
+ for record in report._guest_timings._records:
+ while ((progress_idx + 1) < len(report._progress_history) and
+ report._progress_history[progress_idx + 1]._now < record._timestamp):
+ progress_idx = progress_idx + 1
+
+ if progress_idx >= 0:
+ progress = report._progress_history[progress_idx]
+ else:
+ progress = None
+
+ threads[record._tid]["xaxis"].append(record._timestamp - starttime)
+ threads[record._tid]["yaxis"].append(record._value)
+ threads[record._tid]["labels"].append(self._get_progress_label(progress))
+
+
+ graphs = []
+ from plotly import graph_objs as go
+ for tid in threads.keys():
+ graphs.append(
+ go.Scatter(x=threads[tid]["xaxis"],
+ y=threads[tid]["yaxis"],
+ name="PID %s: %s" % (tid, report._scenario._name),
+ mode="lines",
+ line={
+ "dash": "solid",
+ "color": self._next_color(),
+ "shape": "linear",
+ "width": 1
+ },
+ text=threads[tid]["labels"]))
+ return graphs
+
+ def _get_migration_iters_graph(self, report, starttime):
+ xaxis = []
+ yaxis = []
+ labels = []
+ for progress in report._progress_history:
+ xaxis.append(progress._now - starttime)
+ yaxis.append(0)
+ labels.append(self._get_progress_label(progress))
+
+ from plotly import graph_objs as go
+ return go.Scatter(x=xaxis,
+ y=yaxis,
+ text=labels,
+ name="Migration iterations",
+ mode="markers",
+ marker={
+ "color": self._next_color(),
+ "symbol": "star",
+ "size": 5
+ })
+
+ def _get_qemu_cpu_graph(self, report, starttime):
+ xaxis = []
+ yaxis = []
+ labels = []
+ progress_idx = -1
+
+ first = report._qemu_timings._records[0]
+ abstimestamps = [first._timestamp]
+ absvalues = [first._value]
+
+ for record in report._qemu_timings._records[1:]:
+ while ((progress_idx + 1) < len(report._progress_history) and
+ report._progress_history[progress_idx + 1]._now < record._timestamp):
+ progress_idx = progress_idx + 1
+
+ if progress_idx >= 0:
+ progress = report._progress_history[progress_idx]
+ else:
+ progress = None
+
+ oldvalue = absvalues[-1]
+ oldtime = abstimestamps[-1]
+
+ cpudelta = (record._value - oldvalue) / 1000.0
+ timedelta = record._timestamp - oldtime
+ if timedelta == 0:
+ continue
+ util = cpudelta / timedelta * 100.0
+
+ abstimestamps.append(record._timestamp)
+ absvalues.append(record._value)
+
+ xaxis.append(record._timestamp - starttime)
+ yaxis.append(util)
+ labels.append(self._get_progress_label(progress))
+
+ from plotly import graph_objs as go
+ return go.Scatter(x=xaxis,
+ y=yaxis,
+ yaxis="y2",
+ name="QEMU: %s" % report._scenario._name,
+ mode='lines',
+ line={
+ "dash": "solid",
+ "color": self._next_color(),
+ "shape": "linear",
+ "width": 1
+ },
+ text=labels)
+
+ def _get_vcpu_cpu_graphs(self, report, starttime):
+ threads = {}
+ for record in report._vcpu_timings._records:
+ if record._tid in threads:
+ continue
+ threads[record._tid] = {
+ "xaxis": [],
+ "yaxis": [],
+ "labels": [],
+ "absvalue": [record._value],
+ "abstime": [record._timestamp],
+ }
+
+ progress_idx = -1
+ for record in report._vcpu_timings._records:
+ while ((progress_idx + 1) < len(report._progress_history) and
+ report._progress_history[progress_idx + 1]._now < record._timestamp):
+ progress_idx = progress_idx + 1
+
+ if progress_idx >= 0:
+ progress = report._progress_history[progress_idx]
+ else:
+ progress = None
+
+ oldvalue = threads[record._tid]["absvalue"][-1]
+ oldtime = threads[record._tid]["abstime"][-1]
+
+ cpudelta = (record._value - oldvalue) / 1000.0
+ timedelta = record._timestamp - oldtime
+ if timedelta == 0:
+ continue
+ util = cpudelta / timedelta * 100.0
+ if util > 100:
+ util = 100
+
+ threads[record._tid]["absvalue"].append(record._value)
+ threads[record._tid]["abstime"].append(record._timestamp)
+
+ threads[record._tid]["xaxis"].append(record._timestamp - starttime)
+ threads[record._tid]["yaxis"].append(util)
+ threads[record._tid]["labels"].append(self._get_progress_label(progress))
+
+
+ graphs = []
+ from plotly import graph_objs as go
+ for tid in threads.keys():
+ graphs.append(
+ go.Scatter(x=threads[tid]["xaxis"],
+ y=threads[tid]["yaxis"],
+ yaxis="y2",
+ name="VCPU %s: %s" % (tid, report._scenario._name),
+ mode="lines",
+ line={
+ "dash": "solid",
+ "color": self._next_color(),
+ "shape": "linear",
+ "width": 1
+ },
+ text=threads[tid]["labels"]))
+ return graphs
+
+ def _generate_chart_report(self, report):
+ graphs = []
+ starttime = self._find_start_time(report)
+ if self._total_guest_cpu:
+ graphs.append(self._get_total_guest_cpu_graph(report, starttime))
+ if self._split_guest_cpu:
+ graphs.extend(self._get_split_guest_cpu_graphs(report, starttime))
+ if self._qemu_cpu:
+ graphs.append(self._get_qemu_cpu_graph(report, starttime))
+ if self._vcpu_cpu:
+ graphs.extend(self._get_vcpu_cpu_graphs(report, starttime))
+ if self._migration_iters:
+ graphs.append(self._get_migration_iters_graph(report, starttime))
+ return graphs
+
+ def _generate_annotation(self, starttime, progress):
+ return {
+ "text": progress._status,
+ "x": progress._now - starttime,
+ "y": 10,
+ }
+
+ def _generate_annotations(self, report):
+ starttime = self._find_start_time(report)
+ annotations = {}
+ started = False
+ for progress in report._progress_history:
+ if progress._status == "setup":
+ continue
+ if progress._status not in annotations:
+ annotations[progress._status] = self._generate_annotation(starttime, progress)
+
+ return annotations.values()
+
+ def _generate_chart(self):
+ from plotly.offline import plot
+ from plotly import graph_objs as go
+
+ graphs = []
+ yaxismax = 0
+ yaxismax2 = 0
+ for report in self._reports:
+ graphs.extend(self._generate_chart_report(report))
+
+ maxvalue = self._get_guest_max_value(report)
+ if maxvalue > yaxismax:
+ yaxismax = maxvalue
+
+ maxvalue = self._get_qemu_max_value(report)
+ if maxvalue > yaxismax2:
+ yaxismax2 = maxvalue
+
+ yaxismax += 100
+ if not self._qemu_cpu:
+ yaxismax2 = 110
+ yaxismax2 += 10
+
+ annotations = []
+ if self._migration_iters:
+ for report in self._reports:
+ annotations.extend(self._generate_annotations(report))
+
+ layout = go.Layout(title="Migration comparison",
+ xaxis={
+ "title": "Wallclock time (secs)",
+ "showgrid": False,
+ },
+ yaxis={
+ "title": "Memory update speed (ms/GB)",
+ "showgrid": False,
+ "range": [0, yaxismax],
+ },
+ yaxis2={
+ "title": "Hostutilization (%)",
+ "overlaying": "y",
+ "side": "right",
+ "range": [0, yaxismax2],
+ "showgrid": False,
+ },
+ annotations=annotations)
+
+ figure = go.Figure(data=graphs, layout=layout)
+
+ return plot(figure,
+ show_link=False,
+ include_plotlyjs=False,
+ output_type="div")
+
+
+ def _generate_report(self):
+ pieces = []
+ for report in self._reports:
+ pieces.append("""
+<h3>Report %s</h3>
+<table>
+""" % report._scenario._name)
+
+ pieces.append("""
+ <tr class="subhead">
+ <th colspan="2">Test config</th>
+ </tr>
+ <tr>
+ <th>Emulator:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>Kernel:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>Ramdisk:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>Transport:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>Host:</th>
+ <td>%s</td>
+ </tr>
+""" % (report._binary, report._kernel,
+ report._initrd, report._transport, report._dst_host))
+
+ hardware = report._hardware
+ pieces.append("""
+ <tr class="subhead">
+ <th colspan="2">Hardware config</th>
+ </tr>
+ <tr>
+ <th>CPUs:</th>
+ <td>%d</td>
+ </tr>
+ <tr>
+ <th>RAM:</th>
+ <td>%d GB</td>
+ </tr>
+ <tr>
+ <th>Source CPU bind:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>Source RAM bind:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>Dest CPU bind:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>Dest RAM bind:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>Preallocate RAM:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>Locked RAM:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>Huge pages:</th>
+ <td>%s</td>
+ </tr>
+""" % (hardware._cpus, hardware._mem,
+ ",".join(hardware._src_cpu_bind),
+ ",".join(hardware._src_mem_bind),
+ ",".join(hardware._dst_cpu_bind),
+ ",".join(hardware._dst_mem_bind),
+ "yes" if hardware._prealloc_pages else "no",
+ "yes" if hardware._locked_pages else "no",
+ "yes" if hardware._huge_pages else "no"))
+
+ scenario = report._scenario
+ pieces.append("""
+ <tr class="subhead">
+ <th colspan="2">Scenario config</th>
+ </tr>
+ <tr>
+ <th>Max downtime:</th>
+ <td>%d milli-sec</td>
+ </tr>
+ <tr>
+ <th>Max bandwidth:</th>
+ <td>%d MB/sec</td>
+ </tr>
+ <tr>
+ <th>Max iters:</th>
+ <td>%d</td>
+ </tr>
+ <tr>
+ <th>Max time:</th>
+ <td>%d secs</td>
+ </tr>
+ <tr>
+ <th>Pause:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>Pause iters:</th>
+ <td>%d</td>
+ </tr>
+ <tr>
+ <th>Post-copy:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>Post-copy iters:</th>
+ <td>%d</td>
+ </tr>
+ <tr>
+ <th>Auto-converge:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>Auto-converge iters:</th>
+ <td>%d</td>
+ </tr>
+ <tr>
+ <th>MT compression:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>MT compression threads:</th>
+ <td>%d</td>
+ </tr>
+ <tr>
+ <th>XBZRLE compression:</th>
+ <td>%s</td>
+ </tr>
+ <tr>
+ <th>XBZRLE compression cache:</th>
+ <td>%d%% of RAM</td>
+ </tr>
+""" % (scenario._downtime, scenario._bandwidth,
+ scenario._max_iters, scenario._max_time,
+ "yes" if scenario._pause else "no", scenario._pause_iters,
+ "yes" if scenario._post_copy else "no", scenario._post_copy_iters,
+ "yes" if scenario._auto_converge else "no", scenario._auto_converge_step,
+ "yes" if scenario._compression_mt else "no", scenario._compression_mt_threads,
+ "yes" if scenario._compression_xbzrle else "no", scenario._compression_xbzrle_cache))
+
+ pieces.append("""
+</table>
+""")
+
+ return "\n".join(pieces)
+
+ def _generate_style(self):
+ return """
+#report table tr th {
+ text-align: right;
+}
+#report table tr td {
+ text-align: left;
+}
+#report table tr.subhead th {
+ background: rgb(192, 192, 192);
+ text-align: center;
+}
+
+"""
+
+ def generate_html(self, fh):
+ print >>fh, """<html>
+ <head>
+ <script type="text/javascript" src="plotly.min.js">
+ </script>
+ <style type="text/css">
+%s
+ </style>
+ <title>Migration report</title>
+ </head>
+ <body>
+ <h1>Migration report</h1>
+ <h2>Chart summary</h2>
+ <div id="chart">
+""" % self._generate_style()
+ print >>fh, self._generate_chart()
+ print >>fh, """
+ </div>
+ <h2>Report details</h2>
+ <div id="report">
+"""
+ print >>fh, self._generate_report()
+ print >>fh, """
+ </div>
+ </body>
+</html>
+"""
+
+ def generate(self, filename):
+ if filename is None:
+ self.generate_html(sys.stdout)
+ else:
+ with open(filename, "w") as fh:
+ self.generate_html(fh)
diff --git a/tests/migration/guestperf/progress.py b/tests/migration/guestperf/progress.py
new file mode 100644
index 0000000000..46d2157b83
--- /dev/null
+++ b/tests/migration/guestperf/progress.py
@@ -0,0 +1,117 @@
+#
+# Migration test migration operation progress
+#
+# Copyright (c) 2016 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+
+class ProgressStats(object):
+
+ def __init__(self,
+ transferred_bytes,
+ remaining_bytes,
+ total_bytes,
+ duplicate_pages,
+ skipped_pages,
+ normal_pages,
+ normal_bytes,
+ dirty_rate_pps,
+ transfer_rate_mbs,
+ iterations):
+ self._transferred_bytes = transferred_bytes
+ self._remaining_bytes = remaining_bytes
+ self._total_bytes = total_bytes
+ self._duplicate_pages = duplicate_pages
+ self._skipped_pages = skipped_pages
+ self._normal_pages = normal_pages
+ self._normal_bytes = normal_bytes
+ self._dirty_rate_pps = dirty_rate_pps
+ self._transfer_rate_mbs = transfer_rate_mbs
+ self._iterations = iterations
+
+ def serialize(self):
+ return {
+ "transferred_bytes": self._transferred_bytes,
+ "remaining_bytes": self._remaining_bytes,
+ "total_bytes": self._total_bytes,
+ "duplicate_pages": self._duplicate_pages,
+ "skipped_pages": self._skipped_pages,
+ "normal_pages": self._normal_pages,
+ "normal_bytes": self._normal_bytes,
+ "dirty_rate_pps": self._dirty_rate_pps,
+ "transfer_rate_mbs": self._transfer_rate_mbs,
+ "iterations": self._iterations,
+ }
+
+ @classmethod
+ def deserialize(cls, data):
+ return cls(
+ data["transferred_bytes"],
+ data["remaining_bytes"],
+ data["total_bytes"],
+ data["duplicate_pages"],
+ data["skipped_pages"],
+ data["normal_pages"],
+ data["normal_bytes"],
+ data["dirty_rate_pps"],
+ data["transfer_rate_mbs"],
+ data["iterations"])
+
+
+class Progress(object):
+
+ def __init__(self,
+ status,
+ ram,
+ now,
+ duration,
+ downtime,
+ downtime_expected,
+ setup_time,
+ throttle_pcent):
+
+ self._status = status
+ self._ram = ram
+ self._now = now
+ self._duration = duration
+ self._downtime = downtime
+ self._downtime_expected = downtime_expected
+ self._setup_time = setup_time
+ self._throttle_pcent = throttle_pcent
+
+ def serialize(self):
+ return {
+ "status": self._status,
+ "ram": self._ram.serialize(),
+ "now": self._now,
+ "duration": self._duration,
+ "downtime": self._downtime,
+ "downtime_expected": self._downtime_expected,
+ "setup_time": self._setup_time,
+ "throttle_pcent": self._throttle_pcent,
+ }
+
+ @classmethod
+ def deserialize(cls, data):
+ return cls(
+ data["status"],
+ ProgressStats.deserialize(data["ram"]),
+ data["now"],
+ data["duration"],
+ data["downtime"],
+ data["downtime_expected"],
+ data["setup_time"],
+ data["throttle_pcent"])
diff --git a/tests/migration/guestperf/report.py b/tests/migration/guestperf/report.py
new file mode 100644
index 0000000000..6a1f971496
--- /dev/null
+++ b/tests/migration/guestperf/report.py
@@ -0,0 +1,98 @@
+#
+# Migration test output result reporting
+#
+# Copyright (c) 2016 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+import json
+
+from guestperf.hardware import Hardware
+from guestperf.scenario import Scenario
+from guestperf.progress import Progress
+from guestperf.timings import Timings
+
+class Report(object):
+
+ def __init__(self,
+ hardware,
+ scenario,
+ progress_history,
+ guest_timings,
+ qemu_timings,
+ vcpu_timings,
+ binary,
+ dst_host,
+ kernel,
+ initrd,
+ transport,
+ sleep):
+
+ self._hardware = hardware
+ self._scenario = scenario
+ self._progress_history = progress_history
+ self._guest_timings = guest_timings
+ self._qemu_timings = qemu_timings
+ self._vcpu_timings = vcpu_timings
+ self._binary = binary
+ self._dst_host = dst_host
+ self._kernel = kernel
+ self._initrd = initrd
+ self._transport = transport
+ self._sleep = sleep
+
+ def serialize(self):
+ return {
+ "hardware": self._hardware.serialize(),
+ "scenario": self._scenario.serialize(),
+ "progress_history": [progress.serialize() for progress in self._progress_history],
+ "guest_timings": self._guest_timings.serialize(),
+ "qemu_timings": self._qemu_timings.serialize(),
+ "vcpu_timings": self._vcpu_timings.serialize(),
+ "binary": self._binary,
+ "dst_host": self._dst_host,
+ "kernel": self._kernel,
+ "initrd": self._initrd,
+ "transport": self._transport,
+ "sleep": self._sleep,
+ }
+
+ @classmethod
+ def deserialize(cls, data):
+ return cls(
+ Hardware.deserialize(data["hardware"]),
+ Scenario.deserialize(data["scenario"]),
+ [Progress.deserialize(record) for record in data["progress_history"]],
+ Timings.deserialize(data["guest_timings"]),
+ Timings.deserialize(data["qemu_timings"]),
+ Timings.deserialize(data["vcpu_timings"]),
+ data["binary"],
+ data["dst_host"],
+ data["kernel"],
+ data["initrd"],
+ data["transport"],
+ data["sleep"])
+
+ def to_json(self):
+ return json.dumps(self.serialize(), indent=4)
+
+ @classmethod
+ def from_json(cls, data):
+ return cls.deserialize(json.loads(data))
+
+ @classmethod
+ def from_json_file(cls, filename):
+ with open(filename, "r") as fh:
+ return cls.deserialize(json.load(fh))
diff --git a/tests/migration/guestperf/scenario.py b/tests/migration/guestperf/scenario.py
new file mode 100644
index 0000000000..705c2e864f
--- /dev/null
+++ b/tests/migration/guestperf/scenario.py
@@ -0,0 +1,95 @@
+#
+# Migration test scenario parameter description
+#
+# Copyright (c) 2016 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+
+class Scenario(object):
+
+ def __init__(self, name,
+ downtime=500,
+ bandwidth=125000, # 1000 gig-e, effectively unlimited
+ max_iters=30,
+ max_time=300,
+ pause=False, pause_iters=5,
+ post_copy=False, post_copy_iters=5,
+ auto_converge=False, auto_converge_step=10,
+ compression_mt=False, compression_mt_threads=1,
+ compression_xbzrle=False, compression_xbzrle_cache=10):
+
+ self._name = name
+
+ # General migration tunables
+ self._downtime = downtime # milliseconds
+ self._bandwidth = bandwidth # MiB per second
+ self._max_iters = max_iters
+ self._max_time = max_time # seconds
+
+
+ # Strategies for ensuring completion
+ self._pause = pause
+ self._pause_iters = pause_iters
+
+ self._post_copy = post_copy
+ self._post_copy_iters = post_copy_iters
+
+ self._auto_converge = auto_converge
+ self._auto_converge_step = auto_converge_step # percentage CPU time
+
+ self._compression_mt = compression_mt
+ self._compression_mt_threads = compression_mt_threads
+
+ self._compression_xbzrle = compression_xbzrle
+ self._compression_xbzrle_cache = compression_xbzrle_cache # percentage of guest RAM
+
+ def serialize(self):
+ return {
+ "name": self._name,
+ "downtime": self._downtime,
+ "bandwidth": self._bandwidth,
+ "max_iters": self._max_iters,
+ "max_time": self._max_time,
+ "pause": self._pause,
+ "pause_iters": self._pause_iters,
+ "post_copy": self._post_copy,
+ "post_copy_iters": self._post_copy_iters,
+ "auto_converge": self._auto_converge,
+ "auto_converge_step": self._auto_converge_step,
+ "compression_mt": self._compression_mt,
+ "compression_mt_threads": self._compression_mt_threads,
+ "compression_xbzrle": self._compression_xbzrle,
+ "compression_xbzrle_cache": self._compression_xbzrle_cache,
+ }
+
+ @classmethod
+ def deserialize(cls, data):
+ return cls(
+ data["name"],
+ data["downtime"],
+ data["bandwidth"],
+ data["max_iters"],
+ data["max_time"],
+ data["pause"],
+ data["pause_iters"],
+ data["post_copy"],
+ data["post_copy_iters"],
+ data["auto_converge"],
+ data["auto_converge_step"],
+ data["compression_mt"],
+ data["compression_mt_threads"],
+ data["compression_xbzrle"],
+ data["compression_xbzrle_cache"])
diff --git a/tests/migration/guestperf/shell.py b/tests/migration/guestperf/shell.py
new file mode 100644
index 0000000000..185c5697a6
--- /dev/null
+++ b/tests/migration/guestperf/shell.py
@@ -0,0 +1,255 @@
+#
+# Migration test command line shell integration
+#
+# Copyright (c) 2016 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+
+import argparse
+import fnmatch
+import os
+import os.path
+import platform
+import sys
+
+from guestperf.hardware import Hardware
+from guestperf.engine import Engine
+from guestperf.scenario import Scenario
+from guestperf.comparison import COMPARISONS
+from guestperf.plot import Plot
+from guestperf.report import Report
+
+
+class BaseShell(object):
+
+ def __init__(self):
+ parser = argparse.ArgumentParser(description="Migration Test Tool")
+
+ # Test args
+ parser.add_argument("--debug", dest="debug", default=False, action="store_true")
+ parser.add_argument("--verbose", dest="verbose", default=False, action="store_true")
+ parser.add_argument("--sleep", dest="sleep", default=15, type=int)
+ parser.add_argument("--binary", dest="binary", default="/usr/bin/qemu-system-x86_64")
+ parser.add_argument("--dst-host", dest="dst_host", default="localhost")
+ parser.add_argument("--kernel", dest="kernel", default="/boot/vmlinuz-%s" % platform.release())
+ parser.add_argument("--initrd", dest="initrd", default="tests/migration/initrd-stress.img")
+ parser.add_argument("--transport", dest="transport", default="unix")
+
+
+ # Hardware args
+ parser.add_argument("--cpus", dest="cpus", default=1, type=int)
+ parser.add_argument("--mem", dest="mem", default=1, type=int)
+ parser.add_argument("--src-cpu-bind", dest="src_cpu_bind", default="")
+ parser.add_argument("--src-mem-bind", dest="src_mem_bind", default="")
+ parser.add_argument("--dst-cpu-bind", dest="dst_cpu_bind", default="")
+ parser.add_argument("--dst-mem-bind", dest="dst_mem_bind", default="")
+ parser.add_argument("--prealloc-pages", dest="prealloc_pages", default=False)
+ parser.add_argument("--huge-pages", dest="huge_pages", default=False)
+ parser.add_argument("--locked-pages", dest="locked_pages", default=False)
+
+ self._parser = parser
+
+ def get_engine(self, args):
+ return Engine(binary=args.binary,
+ dst_host=args.dst_host,
+ kernel=args.kernel,
+ initrd=args.initrd,
+ transport=args.transport,
+ sleep=args.sleep,
+ debug=args.debug,
+ verbose=args.verbose)
+
+ def get_hardware(self, args):
+ def split_map(value):
+ if value == "":
+ return []
+ return value.split(",")
+
+ return Hardware(cpus=args.cpus,
+ mem=args.mem,
+
+ src_cpu_bind=split_map(args.src_cpu_bind),
+ src_mem_bind=split_map(args.src_mem_bind),
+ dst_cpu_bind=split_map(args.dst_cpu_bind),
+ dst_mem_bind=split_map(args.dst_mem_bind),
+
+ locked_pages=args.locked_pages,
+ huge_pages=args.huge_pages,
+ prealloc_pages=args.prealloc_pages)
+
+
+class Shell(BaseShell):
+
+ def __init__(self):
+ super(Shell, self).__init__()
+
+ parser = self._parser
+
+ parser.add_argument("--output", dest="output", default=None)
+
+ # Scenario args
+ parser.add_argument("--max-iters", dest="max_iters", default=30, type=int)
+ parser.add_argument("--max-time", dest="max_time", default=300, type=int)
+ parser.add_argument("--bandwidth", dest="bandwidth", default=125000, type=int)
+ parser.add_argument("--downtime", dest="downtime", default=500, type=int)
+
+ parser.add_argument("--pause", dest="pause", default=False, action="store_true")
+ parser.add_argument("--pause-iters", dest="pause_iters", default=5, type=int)
+
+ parser.add_argument("--post-copy", dest="post_copy", default=False, action="store_true")
+ parser.add_argument("--post-copy-iters", dest="post_copy_iters", default=5, type=int)
+
+ parser.add_argument("--auto-converge", dest="auto_converge", default=False, action="store_true")
+ parser.add_argument("--auto-converge-step", dest="auto_converge_step", default=10, type=int)
+
+ parser.add_argument("--compression-mt", dest="compression_mt", default=False, action="store_true")
+ parser.add_argument("--compression-mt-threads", dest="compression_mt_threads", default=1, type=int)
+
+ parser.add_argument("--compression-xbzrle", dest="compression_xbzrle", default=False, action="store_true")
+ parser.add_argument("--compression-xbzrle-cache", dest="compression_xbzrle_cache", default=10, type=int)
+
+ def get_scenario(self, args):
+ return Scenario(name="perfreport",
+ downtime=args.downtime,
+ bandwidth=args.bandwidth,
+ max_iters=args.max_iters,
+ max_time=args.max_time,
+
+ pause=args.pause,
+ pause_iters=args.pause_iters,
+
+ post_copy=args.post_copy,
+ post_copy_iters=args.post_copy_iters,
+
+ auto_converge=args.auto_converge,
+ auto_converge_step=args.auto_converge_step,
+
+ compression_mt=args.compression_mt,
+ compression_mt_threads=args.compression_mt_threads,
+
+ compression_xbzrle=args.compression_xbzrle,
+ compression_xbzrle_cache=args.compression_xbzrle_cache)
+
+ def run(self, argv):
+ args = self._parser.parse_args(argv)
+
+ engine = self.get_engine(args)
+ hardware = self.get_hardware(args)
+ scenario = self.get_scenario(args)
+
+ try:
+ report = engine.run(hardware, scenario)
+ if args.output is None:
+ print report.to_json()
+ else:
+ with open(args.output, "w") as fh:
+ print >>fh, report.to_json()
+ return 0
+ except Exception as e:
+ print >>sys.stderr, "Error: %s" % str(e)
+ if args.debug:
+ raise
+ return 1
+
+
+class BatchShell(BaseShell):
+
+ def __init__(self):
+ super(BatchShell, self).__init__()
+
+ parser = self._parser
+
+ parser.add_argument("--filter", dest="filter", default="*")
+ parser.add_argument("--output", dest="output", default=os.getcwd())
+
+ def run(self, argv):
+ args = self._parser.parse_args(argv)
+
+ engine = self.get_engine(args)
+ hardware = self.get_hardware(args)
+
+ try:
+ for comparison in COMPARISONS:
+ compdir = os.path.join(args.output, comparison._name)
+ for scenario in comparison._scenarios:
+ name = os.path.join(comparison._name, scenario._name)
+ if not fnmatch.fnmatch(name, args.filter):
+ if args.verbose:
+ print "Skipping %s" % name
+ continue
+
+ if args.verbose:
+ print "Running %s" % name
+
+ dirname = os.path.join(args.output, comparison._name)
+ filename = os.path.join(dirname, scenario._name + ".json")
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
+ report = engine.run(hardware, scenario)
+ with open(filename, "w") as fh:
+ print >>fh, report.to_json()
+ except Exception as e:
+ print >>sys.stderr, "Error: %s" % str(e)
+ if args.debug:
+ raise
+
+
+class PlotShell(object):
+
+ def __init__(self):
+ super(PlotShell, self).__init__()
+
+ self._parser = argparse.ArgumentParser(description="Migration Test Tool")
+
+ self._parser.add_argument("--output", dest="output", default=None)
+
+ self._parser.add_argument("--debug", dest="debug", default=False, action="store_true")
+ self._parser.add_argument("--verbose", dest="verbose", default=False, action="store_true")
+
+ self._parser.add_argument("--migration-iters", dest="migration_iters", default=False, action="store_true")
+ self._parser.add_argument("--total-guest-cpu", dest="total_guest_cpu", default=False, action="store_true")
+ self._parser.add_argument("--split-guest-cpu", dest="split_guest_cpu", default=False, action="store_true")
+ self._parser.add_argument("--qemu-cpu", dest="qemu_cpu", default=False, action="store_true")
+ self._parser.add_argument("--vcpu-cpu", dest="vcpu_cpu", default=False, action="store_true")
+
+ self._parser.add_argument("reports", nargs='*')
+
+ def run(self, argv):
+ args = self._parser.parse_args(argv)
+
+ if len(args.reports) == 0:
+ print >>sys.stderr, "At least one report required"
+ return 1
+
+ if not (args.qemu_cpu or
+ args.vcpu_cpu or
+ args.total_guest_cpu or
+ args.split_guest_cpu):
+ print >>sys.stderr, "At least one chart type is required"
+ return 1
+
+ reports = []
+ for report in args.reports:
+ reports.append(Report.from_json_file(report))
+
+ plot = Plot(reports,
+ args.migration_iters,
+ args.total_guest_cpu,
+ args.split_guest_cpu,
+ args.qemu_cpu,
+ args.vcpu_cpu)
+
+ plot.generate(args.output)
diff --git a/tests/migration/guestperf/timings.py b/tests/migration/guestperf/timings.py
new file mode 100644
index 0000000000..f94d809896
--- /dev/null
+++ b/tests/migration/guestperf/timings.py
@@ -0,0 +1,55 @@
+#
+# Migration test timing records
+#
+# Copyright (c) 2016 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+
+class TimingRecord(object):
+
+ def __init__(self, tid, timestamp, value):
+
+ self._tid = tid
+ self._timestamp = timestamp
+ self._value = value
+
+ def serialize(self):
+ return {
+ "tid": self._tid,
+ "timestamp": self._timestamp,
+ "value": self._value
+ }
+
+ @classmethod
+ def deserialize(cls, data):
+ return cls(
+ data["tid"],
+ data["timestamp"],
+ data["value"])
+
+
+class Timings(object):
+
+ def __init__(self, records):
+
+ self._records = records
+
+ def serialize(self):
+ return [record.serialize() for record in self._records]
+
+ @classmethod
+ def deserialize(cls, data):
+ return Timings([TimingRecord.deserialize(record) for record in data])
diff --git a/tests/migration/stress.c b/tests/migration/stress.c
new file mode 100644
index 0000000000..cf8ce8b16d
--- /dev/null
+++ b/tests/migration/stress.c
@@ -0,0 +1,367 @@
+/*
+ * Migration stress workload
+ *
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/reboot.h>
+#include <sys/syscall.h>
+#include <linux/random.h>
+#include <sys/time.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+const char *argv0;
+
+#define PAGE_SIZE 4096
+
+static int gettid(void)
+{
+ return syscall(SYS_gettid);
+}
+
+static __attribute__((noreturn)) void exit_failure(void)
+{
+ if (getpid() == 1) {
+ sync();
+ reboot(RB_POWER_OFF);
+ fprintf(stderr, "%s (%05d): ERROR: cannot reboot: %s\n",
+ argv0, gettid(), strerror(errno));
+ abort();
+ } else {
+ exit(1);
+ }
+}
+
+static __attribute__((noreturn)) void exit_success(void)
+{
+ if (getpid() == 1) {
+ sync();
+ reboot(RB_POWER_OFF);
+ fprintf(stderr, "%s (%05d): ERROR: cannot reboot: %s\n",
+ argv0, gettid(), strerror(errno));
+ abort();
+ } else {
+ exit(0);
+ }
+}
+
+static int get_command_arg_str(const char *name,
+ char **val)
+{
+ static char line[1024];
+ FILE *fp = fopen("/proc/cmdline", "r");
+ char *start, *end;
+
+ if (fp == NULL) {
+ fprintf(stderr, "%s (%05d): ERROR: cannot open /proc/cmdline: %s\n",
+ argv0, gettid(), strerror(errno));
+ return -1;
+ }
+
+ if (!fgets(line, sizeof line, fp)) {
+ fprintf(stderr, "%s (%05d): ERROR: cannot read /proc/cmdline: %s\n",
+ argv0, gettid(), strerror(errno));
+ fclose(fp);
+ return -1;
+ }
+ fclose(fp);
+
+ start = strstr(line, name);
+ if (!start)
+ return 0;
+
+ start += strlen(name);
+
+ if (*start != '=') {
+ fprintf(stderr, "%s (%05d): ERROR: no value provided for '%s' in /proc/cmdline\n",
+ argv0, gettid(), name);
+ }
+ start++;
+
+ end = strstr(start, " ");
+ if (!end)
+ end = strstr(start, "\n");
+
+ if (end == start) {
+ fprintf(stderr, "%s (%05d): ERROR: no value provided for '%s' in /proc/cmdline\n",
+ argv0, gettid(), name);
+ return -1;
+ }
+
+ if (end)
+ *val = strndup(start, end - start);
+ else
+ *val = strdup(start);
+ return 1;
+}
+
+
+static int get_command_arg_ull(const char *name,
+ unsigned long long *val)
+{
+ char *valstr;
+ char *end;
+
+ int ret = get_command_arg_str(name, &valstr);
+ if (ret <= 0)
+ return ret;
+
+ errno = 0;
+ *val = strtoll(valstr, &end, 10);
+ if (errno || *end) {
+ fprintf(stderr, "%s (%05d): ERROR: cannot parse %s value %s\n",
+ argv0, gettid(), name, valstr);
+ free(valstr);
+ return -1;
+ }
+ free(valstr);
+ return 0;
+}
+
+
+static int random_bytes(char *buf, size_t len)
+{
+ int fd;
+
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s (%05d): ERROR: cannot open /dev/urandom: %s\n",
+ argv0, gettid(), strerror(errno));
+ return -1;
+ }
+
+ if (read(fd, buf, len) != len) {
+ fprintf(stderr, "%s (%05d): ERROR: cannot read /dev/urandom: %s\n",
+ argv0, gettid(), strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+
+static unsigned long long now(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ return (tv.tv_sec * 1000ull) + (tv.tv_usec / 1000ull);
+}
+
+static int stressone(unsigned long long ramsizeMB)
+{
+ size_t pagesPerMB = 1024 * 1024 / PAGE_SIZE;
+ char *ram = malloc(ramsizeMB * 1024 * 1024);
+ char *ramptr;
+ size_t i, j, k;
+ char *data = malloc(PAGE_SIZE);
+ char *dataptr;
+ size_t nMB = 0;
+ unsigned long long before, after;
+
+ if (!ram) {
+ fprintf(stderr, "%s (%05d): ERROR: cannot allocate %llu MB of RAM: %s\n",
+ argv0, gettid(), ramsizeMB, strerror(errno));
+ return -1;
+ }
+ if (!data) {
+ fprintf(stderr, "%s (%d): ERROR: cannot allocate %d bytes of RAM: %s\n",
+ argv0, gettid(), PAGE_SIZE, strerror(errno));
+ free(ram);
+ return -1;
+ }
+
+ /* We don't care about initial state, but we do want
+ * to fault it all into RAM, otherwise the first iter
+ * of the loop below will be quite slow. We cna't use
+ * 0x0 as the byte as gcc optimizes that away into a
+ * calloc instead :-) */
+ memset(ram, 0xfe, ramsizeMB * 1024 * 1024);
+
+ if (random_bytes(data, PAGE_SIZE) < 0) {
+ free(ram);
+ free(data);
+ return -1;
+ }
+
+ before = now();
+
+ while (1) {
+
+ ramptr = ram;
+ for (i = 0; i < ramsizeMB; i++, nMB++) {
+ for (j = 0; j < pagesPerMB; j++) {
+ dataptr = data;
+ for (k = 0; k < PAGE_SIZE; k += sizeof(long long)) {
+ ramptr += sizeof(long long);
+ dataptr += sizeof(long long);
+ *(unsigned long long *)ramptr ^= *(unsigned long long *)dataptr;
+ }
+ }
+
+ if (nMB == 1024) {
+ after = now();
+ fprintf(stderr, "%s (%05d): INFO: %06llums copied 1 GB in %05llums\n",
+ argv0, gettid(), after, after - before);
+ before = now();
+ nMB = 0;
+ }
+ }
+ }
+
+ free(data);
+ free(ram);
+}
+
+
+static void *stressthread(void *arg)
+{
+ unsigned long long ramsizeMB = *(unsigned long long *)arg;
+
+ stressone(ramsizeMB);
+
+ return NULL;
+}
+
+static int stress(unsigned long long ramsizeGB, int ncpus)
+{
+ size_t i;
+ unsigned long long ramsizeMB = ramsizeGB * 1024 / ncpus;
+ ncpus--;
+
+ for (i = 0; i < ncpus; i++) {
+ pthread_t thr;
+ pthread_create(&thr, NULL,
+ stressthread, &ramsizeMB);
+ }
+
+ stressone(ramsizeMB);
+
+ return 0;
+}
+
+
+static int mount_misc(const char *fstype, const char *dir)
+{
+ if (mkdir(dir, 0755) < 0 && errno != EEXIST) {
+ fprintf(stderr, "%s (%05d): ERROR: cannot create %s: %s\n",
+ argv0, gettid(), dir, strerror(errno));
+ return -1;
+ }
+
+ if (mount("none", dir, fstype, 0, NULL) < 0) {
+ fprintf(stderr, "%s (%05d): ERROR: cannot mount %s: %s\n",
+ argv0, gettid(), dir, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int mount_all(void)
+{
+ if (mount_misc("proc", "/proc") < 0 ||
+ mount_misc("sysfs", "/sys") < 0 ||
+ mount_misc("tmpfs", "/dev") < 0)
+ return -1;
+
+ mknod("/dev/urandom", 0777 | S_IFCHR, makedev(1, 9));
+ mknod("/dev/random", 0777 | S_IFCHR, makedev(1, 8));
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ unsigned long long ramsizeGB = 1;
+ char *end;
+ int ch;
+ int opt_ind = 0;
+ const char *sopt = "hr:c:";
+ struct option lopt[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "ramsize", required_argument, NULL, 'r' },
+ { "cpus", required_argument, NULL, 'c' },
+ { NULL, 0, NULL, 0 }
+ };
+ int ret;
+ int ncpus = 0;
+
+ argv0 = argv[0];
+
+ while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
+ switch (ch) {
+ case 'r':
+ errno = 0;
+ ramsizeGB = strtoll(optarg, &end, 10);
+ if (errno != 0 || *end) {
+ fprintf(stderr, "%s (%05d): ERROR: Cannot parse RAM size %s\n",
+ argv0, gettid(), optarg);
+ exit_failure();
+ }
+ break;
+
+ case 'c':
+ errno = 0;
+ ncpus = strtoll(optarg, &end, 10);
+ if (errno != 0 || *end) {
+ fprintf(stderr, "%s (%05d): ERROR: Cannot parse CPU count %s\n",
+ argv0, gettid(), optarg);
+ exit_failure();
+ }
+ break;
+
+ case '?':
+ case 'h':
+ fprintf(stderr, "%s: [--help][--ramsize GB][--cpus N]\n", argv0);
+ exit_failure();
+ }
+ }
+
+ if (getpid() == 1) {
+ if (mount_all() < 0)
+ exit_failure();
+
+ ret = get_command_arg_ull("ramsize", &ramsizeGB);
+ if (ret < 0)
+ exit_failure();
+ }
+
+ if (ncpus == 0)
+ ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+
+ fprintf(stdout, "%s (%05d): INFO: RAM %llu GiB across %d CPUs\n",
+ argv0, gettid(), ramsizeGB, ncpus);
+
+ if (stress(ramsizeGB, ncpus) < 0)
+ exit_failure();
+
+ exit_success();
+}
diff --git a/tests/ne2000-test.c b/tests/ne2000-test.c
index 3727875f2e..b7cf3dd2f5 100644
--- a/tests/ne2000-test.c
+++ b/tests/ne2000-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
diff --git a/tests/nvme-test.c b/tests/nvme-test.c
index ec06893eee..c8bece4434 100644
--- a/tests/nvme-test.c
+++ b/tests/nvme-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
diff --git a/tests/pc-cpu-test.c b/tests/pc-cpu-test.c
index 6b34ca588b..4428cea5f1 100644
--- a/tests/pc-cpu-test.c
+++ b/tests/pc-cpu-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "libqtest.h"
diff --git a/tests/pcnet-test.c b/tests/pcnet-test.c
index 2ddf4965c6..efb1ef44e9 100644
--- a/tests/pcnet-test.c
+++ b/tests/pcnet-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
diff --git a/tests/postcopy-test.c b/tests/postcopy-test.c
new file mode 100644
index 0000000000..229e9e901a
--- /dev/null
+++ b/tests/postcopy-test.c
@@ -0,0 +1,530 @@
+/*
+ * QTest testcase for postcopy
+ *
+ * Copyright (c) 2016 Red Hat, Inc. and/or its affiliates
+ * based on the vhost-user-test.c that is:
+ * Copyright (c) 2014 Virtual Open Systems Sarl.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+
+#include "libqtest.h"
+#include "qemu/option.h"
+#include "qemu/range.h"
+#include "qemu/sockets.h"
+#include "sysemu/char.h"
+#include "sysemu/sysemu.h"
+#include "hw/nvram/openbios_firmware_abi.h"
+
+#define MIN_NVRAM_SIZE 8192 /* from spapr_nvram.c */
+
+const unsigned start_address = 1024 * 1024;
+const unsigned end_address = 100 * 1024 * 1024;
+bool got_stop;
+
+#if defined(__linux__)
+#include <sys/syscall.h>
+#include <sys/vfs.h>
+#endif
+
+#if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD)
+#include <sys/eventfd.h>
+#include <sys/ioctl.h>
+#include <linux/userfaultfd.h>
+
+static bool ufd_version_check(void)
+{
+ struct uffdio_api api_struct;
+ uint64_t ioctl_mask;
+
+ int ufd = ufd = syscall(__NR_userfaultfd, O_CLOEXEC);
+
+ if (ufd == -1) {
+ g_test_message("Skipping test: userfaultfd not available");
+ return false;
+ }
+
+ api_struct.api = UFFD_API;
+ api_struct.features = 0;
+ if (ioctl(ufd, UFFDIO_API, &api_struct)) {
+ g_test_message("Skipping test: UFFDIO_API failed");
+ return false;
+ }
+
+ ioctl_mask = (__u64)1 << _UFFDIO_REGISTER |
+ (__u64)1 << _UFFDIO_UNREGISTER;
+ if ((api_struct.ioctls & ioctl_mask) != ioctl_mask) {
+ g_test_message("Skipping test: Missing userfault feature");
+ return false;
+ }
+
+ return true;
+}
+
+#else
+static bool ufd_version_check(void)
+{
+ g_test_message("Skipping test: Userfault not available (builtdtime)");
+ return false;
+}
+
+#endif
+
+static const char *tmpfs;
+
+/* A simple PC boot sector that modifies memory (1-100MB) quickly
+ * outputing a 'B' every so often if it's still running.
+ */
+unsigned char bootsect[] = {
+ 0xfa, 0x0f, 0x01, 0x16, 0x74, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00,
+ 0x0f, 0x22, 0xc0, 0x66, 0xea, 0x20, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x92, 0x0c, 0x02,
+ 0xe6, 0x92, 0xb8, 0x10, 0x00, 0x00, 0x00, 0x8e, 0xd8, 0x66, 0xb8, 0x41,
+ 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xb3, 0x00, 0xb8, 0x00, 0x00, 0x10,
+ 0x00, 0xfe, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40,
+ 0x06, 0x7c, 0xf2, 0xfe, 0xc3, 0x75, 0xe9, 0x66, 0xb8, 0x42, 0x00, 0x66,
+ 0xba, 0xf8, 0x03, 0xee, 0xeb, 0xde, 0x66, 0x90, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, 0x27, 0x00, 0x5c, 0x7c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
+};
+
+static void init_bootfile_x86(const char *bootpath)
+{
+ FILE *bootfile = fopen(bootpath, "wb");
+
+ g_assert_cmpint(fwrite(bootsect, 512, 1, bootfile), ==, 1);
+ fclose(bootfile);
+}
+
+static void init_bootfile_ppc(const char *bootpath)
+{
+ FILE *bootfile;
+ char buf[MIN_NVRAM_SIZE];
+ struct OpenBIOS_nvpart_v1 *header = (struct OpenBIOS_nvpart_v1 *)buf;
+
+ memset(buf, 0, MIN_NVRAM_SIZE);
+
+ /* Create a "common" partition in nvram to store boot-command property */
+
+ header->signature = OPENBIOS_PART_SYSTEM;
+ memcpy(header->name, "common", 6);
+ OpenBIOS_finish_partition(header, MIN_NVRAM_SIZE);
+
+ /* FW_MAX_SIZE is 4MB, but slof.bin is only 900KB,
+ * so let's modify memory between 1MB and 100MB
+ * to do like PC bootsector
+ */
+
+ sprintf(buf + 16,
+ "boot-command=hex .\" _\" begin %x %x do i c@ 1 + i c! 1000 +loop "
+ ".\" B\" 0 until", end_address, start_address);
+
+ /* Write partition to the NVRAM file */
+
+ bootfile = fopen(bootpath, "wb");
+ g_assert_cmpint(fwrite(buf, MIN_NVRAM_SIZE, 1, bootfile), ==, 1);
+ fclose(bootfile);
+}
+
+/*
+ * Wait for some output in the serial output file,
+ * we get an 'A' followed by an endless string of 'B's
+ * but on the destination we won't have the A.
+ */
+static void wait_for_serial(const char *side)
+{
+ char *serialpath = g_strdup_printf("%s/%s", tmpfs, side);
+ FILE *serialfile = fopen(serialpath, "r");
+ const char *arch = qtest_get_arch();
+ int started = (strcmp(side, "src_serial") == 0 &&
+ strcmp(arch, "ppc64") == 0) ? 0 : 1;
+
+ do {
+ int readvalue = fgetc(serialfile);
+
+ if (!started) {
+ /* SLOF prints its banner before starting test,
+ * to ignore it, mark the start of the test with '_',
+ * ignore all characters until this marker
+ */
+ switch (readvalue) {
+ case '_':
+ started = 1;
+ break;
+ case EOF:
+ fseek(serialfile, 0, SEEK_SET);
+ usleep(1000);
+ break;
+ }
+ continue;
+ }
+ switch (readvalue) {
+ case 'A':
+ /* Fine */
+ break;
+
+ case 'B':
+ /* It's alive! */
+ fclose(serialfile);
+ g_free(serialpath);
+ return;
+
+ case EOF:
+ started = (strcmp(side, "src_serial") == 0 &&
+ strcmp(arch, "ppc64") == 0) ? 0 : 1;
+ fseek(serialfile, 0, SEEK_SET);
+ usleep(1000);
+ break;
+
+ default:
+ fprintf(stderr, "Unexpected %d on %s serial\n", readvalue, side);
+ g_assert_not_reached();
+ }
+ } while (true);
+}
+
+/*
+ * Events can get in the way of responses we are actually waiting for.
+ */
+static QDict *return_or_event(QDict *response)
+{
+ const char *event_string;
+ if (!qdict_haskey(response, "event")) {
+ return response;
+ }
+
+ /* OK, it was an event */
+ event_string = qdict_get_str(response, "event");
+ if (!strcmp(event_string, "STOP")) {
+ got_stop = true;
+ }
+ QDECREF(response);
+ return return_or_event(qtest_qmp_receive(global_qtest));
+}
+
+
+/*
+ * It's tricky to use qemu's migration event capability with qtest,
+ * events suddenly appearing confuse the qmp()/hmp() responses.
+ * so wait for a couple of passes to have happened before
+ * going postcopy.
+ */
+
+static uint64_t get_migration_pass(void)
+{
+ QDict *rsp, *rsp_return, *rsp_ram;
+ uint64_t result;
+
+ rsp = return_or_event(qmp("{ 'execute': 'query-migrate' }"));
+ rsp_return = qdict_get_qdict(rsp, "return");
+ if (!qdict_haskey(rsp_return, "ram")) {
+ /* Still in setup */
+ result = 0;
+ } else {
+ rsp_ram = qdict_get_qdict(rsp_return, "ram");
+ result = qdict_get_try_int(rsp_ram, "dirty-sync-count", 0);
+ QDECREF(rsp);
+ }
+ return result;
+}
+
+static void wait_for_migration_complete(void)
+{
+ QDict *rsp, *rsp_return;
+ bool completed;
+
+ do {
+ const char *status;
+
+ rsp = return_or_event(qmp("{ 'execute': 'query-migrate' }"));
+ rsp_return = qdict_get_qdict(rsp, "return");
+ status = qdict_get_str(rsp_return, "status");
+ completed = strcmp(status, "completed") == 0;
+ g_assert_cmpstr(status, !=, "failed");
+ QDECREF(rsp);
+ usleep(1000 * 100);
+ } while (!completed);
+}
+
+static void wait_for_migration_pass(void)
+{
+ uint64_t initial_pass = get_migration_pass();
+ uint64_t pass;
+
+ /* Wait for the 1st sync */
+ do {
+ initial_pass = get_migration_pass();
+ if (got_stop || initial_pass) {
+ break;
+ }
+ usleep(1000 * 100);
+ } while (true);
+
+ do {
+ usleep(1000 * 100);
+ pass = get_migration_pass();
+ } while (pass == initial_pass && !got_stop);
+}
+
+static void check_guests_ram(void)
+{
+ /* Our ASM test will have been incrementing one byte from each page from
+ * 1MB to <100MB in order.
+ * This gives us a constraint that any page's byte should be equal or less
+ * than the previous pages byte (mod 256); and they should all be equal
+ * except for one transition at the point where we meet the incrementer.
+ * (We're running this with the guest stopped).
+ */
+ unsigned address;
+ uint8_t first_byte;
+ uint8_t last_byte;
+ bool hit_edge = false;
+ bool bad = false;
+
+ qtest_memread(global_qtest, start_address, &first_byte, 1);
+ last_byte = first_byte;
+
+ for (address = start_address + 4096; address < end_address; address += 4096)
+ {
+ uint8_t b;
+ qtest_memread(global_qtest, address, &b, 1);
+ if (b != last_byte) {
+ if (((b + 1) % 256) == last_byte && !hit_edge) {
+ /* This is OK, the guest stopped at the point of
+ * incrementing the previous page but didn't get
+ * to us yet.
+ */
+ hit_edge = true;
+ } else {
+ fprintf(stderr, "Memory content inconsistency at %x"
+ " first_byte = %x last_byte = %x current = %x"
+ " hit_edge = %x\n",
+ address, first_byte, last_byte, b, hit_edge);
+ bad = true;
+ }
+ }
+ last_byte = b;
+ }
+ g_assert_false(bad);
+}
+
+static void cleanup(const char *filename)
+{
+ char *path = g_strdup_printf("%s/%s", tmpfs, filename);
+
+ unlink(path);
+}
+
+static void test_migrate(void)
+{
+ char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+ QTestState *global = global_qtest, *from, *to;
+ unsigned char dest_byte_a, dest_byte_b, dest_byte_c, dest_byte_d;
+ gchar *cmd, *cmd_src, *cmd_dst;
+ QDict *rsp;
+
+ char *bootpath = g_strdup_printf("%s/bootsect", tmpfs);
+ const char *arch = qtest_get_arch();
+
+ got_stop = false;
+
+ if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+ init_bootfile_x86(bootpath);
+ cmd_src = g_strdup_printf("-machine accel=kvm:tcg -m 150M"
+ " -name pcsource,debug-threads=on"
+ " -serial file:%s/src_serial"
+ " -drive file=%s,format=raw",
+ tmpfs, bootpath);
+ cmd_dst = g_strdup_printf("-machine accel=kvm:tcg -m 150M"
+ " -name pcdest,debug-threads=on"
+ " -serial file:%s/dest_serial"
+ " -drive file=%s,format=raw"
+ " -incoming %s",
+ tmpfs, bootpath, uri);
+ } else if (strcmp(arch, "ppc64") == 0) {
+ init_bootfile_ppc(bootpath);
+ cmd_src = g_strdup_printf("-machine accel=kvm:tcg -m 256M"
+ " -name pcsource,debug-threads=on"
+ " -serial file:%s/src_serial"
+ " -drive file=%s,if=pflash,format=raw",
+ tmpfs, bootpath);
+ cmd_dst = g_strdup_printf("-machine accel=kvm:tcg -m 256M"
+ " -name pcdest,debug-threads=on"
+ " -serial file:%s/dest_serial"
+ " -incoming %s",
+ tmpfs, uri);
+ } else {
+ g_assert_not_reached();
+ }
+
+ from = qtest_start(cmd_src);
+ g_free(cmd_src);
+
+ to = qtest_init(cmd_dst);
+ g_free(cmd_dst);
+
+ global_qtest = from;
+ rsp = qmp("{ 'execute': 'migrate-set-capabilities',"
+ "'arguments': { "
+ "'capabilities': [ {"
+ "'capability': 'postcopy-ram',"
+ "'state': true } ] } }");
+ g_assert(qdict_haskey(rsp, "return"));
+ QDECREF(rsp);
+
+ global_qtest = to;
+ rsp = qmp("{ 'execute': 'migrate-set-capabilities',"
+ "'arguments': { "
+ "'capabilities': [ {"
+ "'capability': 'postcopy-ram',"
+ "'state': true } ] } }");
+ g_assert(qdict_haskey(rsp, "return"));
+ QDECREF(rsp);
+
+ /* We want to pick a speed slow enough that the test completes
+ * quickly, but that it doesn't complete precopy even on a slow
+ * machine, so also set the downtime.
+ */
+ global_qtest = from;
+ rsp = qmp("{ 'execute': 'migrate_set_speed',"
+ "'arguments': { 'value': 100000000 } }");
+ g_assert(qdict_haskey(rsp, "return"));
+ QDECREF(rsp);
+
+ /* 1ms downtime - it should never finish precopy */
+ rsp = qmp("{ 'execute': 'migrate_set_downtime',"
+ "'arguments': { 'value': 0.001 } }");
+ g_assert(qdict_haskey(rsp, "return"));
+ QDECREF(rsp);
+
+
+ /* Wait for the first serial output from the source */
+ wait_for_serial("src_serial");
+
+ cmd = g_strdup_printf("{ 'execute': 'migrate',"
+ "'arguments': { 'uri': '%s' } }",
+ uri);
+ rsp = qmp(cmd);
+ g_free(cmd);
+ g_assert(qdict_haskey(rsp, "return"));
+ QDECREF(rsp);
+
+ wait_for_migration_pass();
+
+ rsp = return_or_event(qmp("{ 'execute': 'migrate-start-postcopy' }"));
+ g_assert(qdict_haskey(rsp, "return"));
+ QDECREF(rsp);
+
+ if (!got_stop) {
+ qmp_eventwait("STOP");
+ }
+
+ global_qtest = to;
+ qmp_eventwait("RESUME");
+
+ wait_for_serial("dest_serial");
+ global_qtest = from;
+ wait_for_migration_complete();
+
+ qtest_quit(from);
+
+ global_qtest = to;
+
+ qtest_memread(to, start_address, &dest_byte_a, 1);
+
+ /* Destination still running, wait for a byte to change */
+ do {
+ qtest_memread(to, start_address, &dest_byte_b, 1);
+ usleep(10 * 1000);
+ } while (dest_byte_a == dest_byte_b);
+
+ qmp("{ 'execute' : 'stop'}");
+ /* With it stopped, check nothing changes */
+ qtest_memread(to, start_address, &dest_byte_c, 1);
+ sleep(1);
+ qtest_memread(to, start_address, &dest_byte_d, 1);
+ g_assert_cmpint(dest_byte_c, ==, dest_byte_d);
+
+ check_guests_ram();
+
+ qtest_quit(to);
+ g_free(uri);
+
+ global_qtest = global;
+
+ cleanup("bootsect");
+ cleanup("migsocket");
+ cleanup("src_serial");
+ cleanup("dest_serial");
+}
+
+int main(int argc, char **argv)
+{
+ char template[] = "/tmp/postcopy-test-XXXXXX";
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+
+ if (!ufd_version_check()) {
+ return 0;
+ }
+
+ tmpfs = mkdtemp(template);
+ if (!tmpfs) {
+ g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno));
+ }
+ g_assert(tmpfs);
+
+ module_call_init(MODULE_INIT_QOM);
+
+ qtest_add_func("/postcopy", test_migrate);
+
+ ret = g_test_run();
+
+ g_assert_cmpint(ret, ==, 0);
+
+ ret = rmdir(tmpfs);
+ if (ret != 0) {
+ g_test_message("unable to rmdir: path (%s): %s\n",
+ tmpfs, strerror(errno));
+ }
+
+ return ret;
+}
diff --git a/tests/prom-env-test.c b/tests/prom-env-test.c
new file mode 100644
index 0000000000..7a628574c3
--- /dev/null
+++ b/tests/prom-env-test.c
@@ -0,0 +1,90 @@
+/*
+ * Test OpenBIOS-based machines.
+ *
+ * Copyright (c) 2016 Red Hat Inc.
+ *
+ * Author:
+ * Thomas Huth <thuth@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2
+ * or later. See the COPYING file in the top-level directory.
+ *
+ * This test is used to check that some OpenBIOS machines can be started
+ * successfully in TCG mode. To do this, we first put some Forth code into
+ * the "boot-command" Open Firmware environment variable. This Forth code
+ * writes a well-known magic value to a known location in memory. Then we
+ * start the guest so that OpenBIOS can boot and finally run the Forth code.
+ * The testing code here then can finally check whether the value has been
+ * successfully written into the guest memory.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+
+#define MAGIC 0xcafec0de
+#define ADDRESS 0x4000
+
+static void check_guest_memory(void)
+{
+ uint32_t signature;
+ int i;
+
+ /* Poll until code has run and modified memory. Wait at most 30 seconds */
+ for (i = 0; i < 10000; ++i) {
+ signature = readl(ADDRESS);
+ if (signature == MAGIC) {
+ break;
+ }
+ g_usleep(10000);
+ }
+
+ g_assert_cmphex(signature, ==, MAGIC);
+}
+
+static void test_machine(const void *machine)
+{
+ char *args;
+
+ args = g_strdup_printf("-M %s,accel=tcg -prom-env 'boot-command=%x %x l!'",
+ (const char *)machine, MAGIC, ADDRESS);
+
+ qtest_start(args);
+ check_guest_memory();
+ qtest_quit(global_qtest);
+
+ g_free(args);
+}
+
+static void add_tests(const char *machines[])
+{
+ int i;
+ char *name;
+
+ for (i = 0; machines[i] != NULL; i++) {
+ name = g_strdup_printf("prom-env/%s", machines[i]);
+ qtest_add_data_func(name, machines[i], test_machine);
+ g_free(name);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ const char *sparc_machines[] = { "SPARCbook", "Voyager", "SS-20", NULL };
+ const char *sparc64_machines[] = { "sun4u", "sun4v", NULL };
+ const char *mac_machines[] = { "mac99", "g3beige", NULL };
+ const char *arch = qtest_get_arch();
+
+ g_test_init(&argc, &argv, NULL);
+
+ if (!strcmp(arch, "ppc") || !strcmp(arch, "ppc64")) {
+ add_tests(mac_machines);
+ } else if (!strcmp(arch, "sparc")) {
+ add_tests(sparc_machines);
+ } else if (!strcmp(arch, "sparc64")) {
+ add_tests(sparc64_machines);
+ } else {
+ g_assert_not_reached();
+ }
+
+ return g_test_run();
+}
diff --git a/tests/pvpanic-test.c b/tests/pvpanic-test.c
index d435833f79..3bfa678667 100644
--- a/tests/pvpanic-test.c
+++ b/tests/pvpanic-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
static void test_panic(void)
diff --git a/tests/pxe-test.c b/tests/pxe-test.c
index 875e4c4a26..b2cc355a95 100644
--- a/tests/pxe-test.c
+++ b/tests/pxe-test.c
@@ -12,7 +12,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include <glib/gstdio.h>
#include "qemu-common.h"
#include "libqtest.h"
diff --git a/tests/q35-test.c b/tests/q35-test.c
index a105f10782..71538fc17c 100644
--- a/tests/q35-test.c
+++ b/tests/q35-test.c
@@ -10,7 +10,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/pci.h"
#include "libqos/pci-pc.h"
diff --git a/tests/qapi-schema/args-bad-boxed.err b/tests/qapi-schema/args-bad-boxed.err
new file mode 100644
index 0000000000..ad0d417321
--- /dev/null
+++ b/tests/qapi-schema/args-bad-boxed.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-bad-boxed.json:2: 'boxed' of command 'foo' should only use true value
diff --git a/tests/qapi-schema/args-bad-boxed.exit b/tests/qapi-schema/args-bad-boxed.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/args-bad-boxed.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/args-bad-boxed.json b/tests/qapi-schema/args-bad-boxed.json
new file mode 100644
index 0000000000..dea0cd0aa5
--- /dev/null
+++ b/tests/qapi-schema/args-bad-boxed.json
@@ -0,0 +1,2 @@
+# 'boxed' should only appear with value true
+{ 'command': 'foo', 'boxed': false }
diff --git a/tests/qapi-schema/args-bad-boxed.out b/tests/qapi-schema/args-bad-boxed.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/args-bad-boxed.out
diff --git a/tests/qapi-schema/args-boxed-anon.err b/tests/qapi-schema/args-boxed-anon.err
new file mode 100644
index 0000000000..f24f345218
--- /dev/null
+++ b/tests/qapi-schema/args-boxed-anon.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-boxed-anon.json:2: 'data' for command 'foo' should be a type name
diff --git a/tests/qapi-schema/args-boxed-anon.exit b/tests/qapi-schema/args-boxed-anon.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/args-boxed-anon.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/args-boxed-anon.json b/tests/qapi-schema/args-boxed-anon.json
new file mode 100644
index 0000000000..95f60da2ed
--- /dev/null
+++ b/tests/qapi-schema/args-boxed-anon.json
@@ -0,0 +1,2 @@
+# 'boxed' can only be used with named types
+{ 'command': 'foo', 'boxed': true, 'data': { 'string': 'str' } }
diff --git a/tests/qapi-schema/args-boxed-anon.out b/tests/qapi-schema/args-boxed-anon.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/args-boxed-anon.out
diff --git a/tests/qapi-schema/args-boxed-empty.err b/tests/qapi-schema/args-boxed-empty.err
new file mode 100644
index 0000000000..039603e85c
--- /dev/null
+++ b/tests/qapi-schema/args-boxed-empty.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-boxed-empty.json:3: Cannot use 'boxed' with empty type
diff --git a/tests/qapi-schema/args-boxed-empty.exit b/tests/qapi-schema/args-boxed-empty.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/args-boxed-empty.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/args-boxed-empty.json b/tests/qapi-schema/args-boxed-empty.json
new file mode 100644
index 0000000000..52717e065f
--- /dev/null
+++ b/tests/qapi-schema/args-boxed-empty.json
@@ -0,0 +1,3 @@
+# 'boxed' requires a non-empty type
+{ 'struct': 'Empty', 'data': {} }
+{ 'command': 'foo', 'boxed': true, 'data': 'Empty' }
diff --git a/tests/qapi-schema/args-boxed-empty.out b/tests/qapi-schema/args-boxed-empty.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/args-boxed-empty.out
diff --git a/tests/qapi-schema/args-boxed-string.err b/tests/qapi-schema/args-boxed-string.err
new file mode 100644
index 0000000000..d326b48aef
--- /dev/null
+++ b/tests/qapi-schema/args-boxed-string.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-boxed-string.json:2: 'data' for command 'foo' cannot use built-in type 'str'
diff --git a/tests/qapi-schema/args-boxed-string.exit b/tests/qapi-schema/args-boxed-string.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/args-boxed-string.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/args-boxed-string.json b/tests/qapi-schema/args-boxed-string.json
new file mode 100644
index 0000000000..f91a1502e7
--- /dev/null
+++ b/tests/qapi-schema/args-boxed-string.json
@@ -0,0 +1,2 @@
+# 'boxed' requires a complex (not built-in) type
+{ 'command': 'foo', 'boxed': true, 'data': 'str' }
diff --git a/tests/qapi-schema/args-boxed-string.out b/tests/qapi-schema/args-boxed-string.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/args-boxed-string.out
diff --git a/tests/qapi-schema/args-union.err b/tests/qapi-schema/args-union.err
index 1d693d74da..f8ad223dde 100644
--- a/tests/qapi-schema/args-union.err
+++ b/tests/qapi-schema/args-union.err
@@ -1 +1 @@
-tests/qapi-schema/args-union.json:4: 'data' for command 'oops' cannot use union type 'Uni'
+tests/qapi-schema/args-union.json:3: 'data' for command 'oops' cannot use union type 'Uni'
diff --git a/tests/qapi-schema/args-union.json b/tests/qapi-schema/args-union.json
index 7bdcbb7f08..2fcaeaae16 100644
--- a/tests/qapi-schema/args-union.json
+++ b/tests/qapi-schema/args-union.json
@@ -1,4 +1,3 @@
-# we do not allow union arguments
-# TODO should we support this?
+# use of union arguments requires 'boxed':true
{ 'union': 'Uni', 'data': { 'case1': 'int', 'case2': 'str' } }
{ 'command': 'oops', 'data': 'Uni' }
diff --git a/tests/qapi-schema/event-boxed-empty.err b/tests/qapi-schema/event-boxed-empty.err
new file mode 100644
index 0000000000..68ec6f2d2b
--- /dev/null
+++ b/tests/qapi-schema/event-boxed-empty.err
@@ -0,0 +1 @@
+tests/qapi-schema/event-boxed-empty.json:2: Use of 'boxed' requires 'data'
diff --git a/tests/qapi-schema/event-boxed-empty.exit b/tests/qapi-schema/event-boxed-empty.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/event-boxed-empty.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/event-boxed-empty.json b/tests/qapi-schema/event-boxed-empty.json
new file mode 100644
index 0000000000..cb145f1433
--- /dev/null
+++ b/tests/qapi-schema/event-boxed-empty.json
@@ -0,0 +1,2 @@
+# 'boxed' requires a non-empty type
+{ 'event': 'FOO', 'boxed': true }
diff --git a/tests/qapi-schema/event-boxed-empty.out b/tests/qapi-schema/event-boxed-empty.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/event-boxed-empty.out
diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out
index b6b4134a80..5a0f2bf805 100644
--- a/tests/qapi-schema/event-case.out
+++ b/tests/qapi-schema/event-case.out
@@ -1,4 +1,5 @@
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
prefix QTYPE
event oops None
+ boxed=False
object q_empty
diff --git a/tests/qapi-schema/flat-union-incomplete-branch.err b/tests/qapi-schema/flat-union-incomplete-branch.err
new file mode 100644
index 0000000000..e826bf0789
--- /dev/null
+++ b/tests/qapi-schema/flat-union-incomplete-branch.err
@@ -0,0 +1 @@
+tests/qapi-schema/flat-union-incomplete-branch.json:6: Union 'TestUnion' data missing 'value2' branch
diff --git a/tests/qapi-schema/flat-union-incomplete-branch.exit b/tests/qapi-schema/flat-union-incomplete-branch.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/flat-union-incomplete-branch.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/flat-union-incomplete-branch.json b/tests/qapi-schema/flat-union-incomplete-branch.json
new file mode 100644
index 0000000000..25a411bc83
--- /dev/null
+++ b/tests/qapi-schema/flat-union-incomplete-branch.json
@@ -0,0 +1,9 @@
+# we require all branches of the union to be covered
+{ 'enum': 'TestEnum',
+ 'data': [ 'value1', 'value2' ] }
+{ 'struct': 'TestTypeA',
+ 'data': { 'string': 'str' } }
+{ 'union': 'TestUnion',
+ 'base': { 'type': 'TestEnum' },
+ 'discriminator': 'type',
+ 'data': { 'value1': 'TestTypeA' } }
diff --git a/tests/qapi-schema/flat-union-incomplete-branch.out b/tests/qapi-schema/flat-union-incomplete-branch.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/flat-union-incomplete-branch.out
diff --git a/tests/qapi-schema/ident-with-escape.out b/tests/qapi-schema/ident-with-escape.out
index 382ce2fa27..1d2722c02e 100644
--- a/tests/qapi-schema/ident-with-escape.out
+++ b/tests/qapi-schema/ident-with-escape.out
@@ -1,7 +1,7 @@
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
prefix QTYPE
command fooA q_obj_fooA-arg -> None
- gen=True success_response=True
+ gen=True success_response=True boxed=False
object q_empty
object q_obj_fooA-arg
member bar1: str optional=False
diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out
index ae3293a3ae..e8171c935f 100644
--- a/tests/qapi-schema/indented-expr.out
+++ b/tests/qapi-schema/indented-expr.out
@@ -1,7 +1,7 @@
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
prefix QTYPE
command eins None -> None
- gen=True success_response=True
+ gen=True success_response=True boxed=False
object q_empty
command zwei None -> None
- gen=True success_response=True
+ gen=True success_response=True boxed=False
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index f571e1bb34..17194637ba 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -127,6 +127,8 @@
{ 'command': 'guest-get-time', 'data': {'a': 'int', '*b': 'int' },
'returns': 'int' }
{ 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' }
+{ 'command': 'boxed-struct', 'boxed': true, 'data': 'UserDefZero' }
+{ 'command': 'boxed-union', 'data': 'UserDefNativeListUnion', 'boxed': true }
# For testing integer range flattening in opts-visitor. The following schema
# corresponds to the option format:
@@ -154,6 +156,8 @@
'data': { '*a': 'int', '*b': 'UserDefOne', 'c': 'str' } }
{ 'event': 'EVENT_D',
'data': { 'a' : 'EventStructOne', 'b' : 'str', '*c': 'str', '*enum3': 'EnumOne' } }
+{ 'event': 'EVENT_E', 'boxed': true, 'data': 'UserDefZero' }
+{ 'event': 'EVENT_F', 'boxed': true, 'data': 'UserDefAlternate' }
# test that we correctly compile downstream extensions, as well as munge
# ticklish names
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 19cd214f6b..9d99c4eebb 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -1,25 +1,39 @@
alternate AltIntNum
+ tag type
case i: int
case n: number
alternate AltNumInt
+ tag type
case n: number
case i: int
alternate AltNumStr
+ tag type
case n: number
case s: str
alternate AltStrBool
+ tag type
case s: str
case b: bool
alternate AltStrInt
+ tag type
case s: str
case i: int
alternate AltStrNum
+ tag type
case s: str
case n: number
event EVENT_A None
+ boxed=False
event EVENT_B None
+ boxed=False
event EVENT_C q_obj_EVENT_C-arg
+ boxed=False
event EVENT_D q_obj_EVENT_D-arg
+ boxed=False
+event EVENT_E UserDefZero
+ boxed=True
+event EVENT_F UserDefAlternate
+ boxed=True
object Empty1
object Empty2
base Empty1
@@ -50,6 +64,7 @@ object UserDefA
member boolean: bool optional=False
member a_b: int optional=True
alternate UserDefAlternate
+ tag type
case udfu: UserDefFlatUnion
case s: str
case i: int
@@ -72,6 +87,7 @@ object UserDefFlatUnion2
case value2: UserDefB
object UserDefNativeListUnion
member type: UserDefNativeListUnionKind optional=False
+ tag type
case integer: q_obj_intList-wrapper
case s8: q_obj_int8List-wrapper
case s16: q_obj_int16List-wrapper
@@ -116,7 +132,9 @@ object UserDefZero
object WrapAlternate
member alt: UserDefAlternate optional=False
event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
+ boxed=False
alternate __org.qemu_x-Alt
+ tag type
case __org.qemu_x-branch: str
case b: __org.qemu_x-Base
object __org.qemu_x-Base
@@ -130,6 +148,7 @@ object __org.qemu_x-Struct2
member array: __org.qemu_x-Union1List optional=False
object __org.qemu_x-Union1
member type: __org.qemu_x-Union1Kind optional=False
+ tag type
case __org.qemu_x-branch: q_obj_str-wrapper
enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch']
object __org.qemu_x-Union2
@@ -137,11 +156,15 @@ object __org.qemu_x-Union2
tag __org.qemu_x-member1
case __org.qemu_x-value: __org.qemu_x-Struct2
command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
- gen=True success_response=True
+ gen=True success_response=True boxed=False
+command boxed-struct UserDefZero -> None
+ gen=True success_response=True boxed=True
+command boxed-union UserDefNativeListUnion -> None
+ gen=True success_response=True boxed=True
command guest-get-time q_obj_guest-get-time-arg -> int
- gen=True success_response=True
+ gen=True success_response=True boxed=False
command guest-sync q_obj_guest-sync-arg -> any
- gen=True success_response=True
+ gen=True success_response=True boxed=False
object q_empty
object q_obj_EVENT_C-arg
member a: int optional=True
@@ -202,10 +225,10 @@ object q_obj_user_def_cmd2-arg
member ud1a: UserDefOne optional=False
member ud1b: UserDefOne optional=True
command user_def_cmd None -> None
- gen=True success_response=True
+ gen=True success_response=True boxed=False
command user_def_cmd0 Empty2 -> Empty2
- gen=True success_response=True
+ gen=True success_response=True boxed=False
command user_def_cmd1 q_obj_user_def_cmd1-arg -> None
- gen=True success_response=True
+ gen=True success_response=True boxed=False
command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo
- gen=True success_response=True
+ gen=True success_response=True boxed=False
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 649677e017..ef74e2c4c8 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -36,19 +36,20 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
self._print_variants(variants)
def visit_command(self, name, info, arg_type, ret_type,
- gen, success_response):
+ gen, success_response, boxed):
print 'command %s %s -> %s' % \
(name, arg_type and arg_type.name, ret_type and ret_type.name)
- print ' gen=%s success_response=%s' % (gen, success_response)
+ print ' gen=%s success_response=%s boxed=%s' % \
+ (gen, success_response, boxed)
- def visit_event(self, name, info, arg_type):
+ def visit_event(self, name, info, arg_type, boxed):
print 'event %s %s' % (name, arg_type and arg_type.name)
+ print ' boxed=%s' % boxed
@staticmethod
def _print_variants(variants):
if variants:
- if variants.tag_name:
- print ' tag %s' % variants.tag_name
+ print ' tag %s' % variants.tag_member.name
for v in variants.variants:
print ' case %s: %s' % (v.name, v.type.name)
diff --git a/tests/qemu-iotests/004 b/tests/qemu-iotests/004
index 67e1beb209..6f2aa3d9a2 100755
--- a/tests/qemu-iotests/004
+++ b/tests/qemu-iotests/004
@@ -37,7 +37,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
-_supported_fmt raw qcow qcow2 qed vdi vmdk vhdx
+_supported_fmt raw qcow qcow2 qed vdi vmdk vhdx luks
_supported_proto generic
_supported_os Linux
diff --git a/tests/qemu-iotests/012 b/tests/qemu-iotests/012
index d1d3f22093..01a770d59c 100755
--- a/tests/qemu-iotests/012
+++ b/tests/qemu-iotests/012
@@ -43,13 +43,16 @@ _supported_fmt generic
_supported_proto file
_supported_os Linux
+# Remove once all tests are fixed to use TEST_IMG_FILE
+# correctly and common.rc sets it unconditionally
+test -z "$TEST_IMG_FILE" && TEST_IMG_FILE=$TEST_IMG
size=128M
_make_test_img $size
echo
echo "== mark image read-only"
-chmod a-w "$TEST_IMG"
+chmod a-w "$TEST_IMG_FILE"
echo
echo "== read from read-only image"
diff --git a/tests/qemu-iotests/023.out b/tests/qemu-iotests/023.out
index d4e9be25e1..664871b30a 100644
--- a/tests/qemu-iotests/023.out
+++ b/tests/qemu-iotests/023.out
@@ -225,42 +225,78 @@ wrote 512/512 bytes at offset 108544
wrote 512/512 bytes at offset 109568
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 216
-offset 110848 is not sector aligned
-offset 111872 is not sector aligned
-offset 112896 is not sector aligned
-offset 113920 is not sector aligned
-offset 114944 is not sector aligned
-offset 115968 is not sector aligned
-offset 116992 is not sector aligned
-offset 118016 is not sector aligned
-offset 119040 is not sector aligned
-offset 120064 is not sector aligned
-offset 121088 is not sector aligned
-offset 122112 is not sector aligned
-offset 123136 is not sector aligned
-offset 124160 is not sector aligned
-offset 125184 is not sector aligned
-offset 126208 is not sector aligned
-offset 127232 is not sector aligned
-offset 128256 is not sector aligned
-offset 129280 is not sector aligned
-offset 130304 is not sector aligned
-offset 131328 is not sector aligned
-offset 132352 is not sector aligned
-offset 133376 is not sector aligned
-offset 134400 is not sector aligned
-offset 135424 is not sector aligned
-offset 136448 is not sector aligned
-offset 137472 is not sector aligned
-offset 138496 is not sector aligned
-offset 139520 is not sector aligned
-offset 140544 is not sector aligned
-offset 141568 is not sector aligned
-offset 142592 is not sector aligned
-offset 143616 is not sector aligned
-offset 144640 is not sector aligned
-offset 145664 is not sector aligned
-offset 146688 is not sector aligned
+wrote 512/512 bytes at offset 110848
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 111872
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 112896
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 113920
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 114944
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 115968
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 116992
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 118016
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 119040
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 120064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 121088
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 122112
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 123136
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 124160
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 125184
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 126208
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 127232
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 128256
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 129280
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 130304
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 131328
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 132352
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 133376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 134400
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 135424
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 136448
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 137472
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 138496
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 139520
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 140544
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 141568
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 142592
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 143616
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 144640
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 145664
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 146688
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 33
wrote 2048/2048 bytes at offset 147968
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -507,42 +543,78 @@ read 512/512 bytes at offset 108544
read 512/512 bytes at offset 109568
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 216
-offset 110848 is not sector aligned
-offset 111872 is not sector aligned
-offset 112896 is not sector aligned
-offset 113920 is not sector aligned
-offset 114944 is not sector aligned
-offset 115968 is not sector aligned
-offset 116992 is not sector aligned
-offset 118016 is not sector aligned
-offset 119040 is not sector aligned
-offset 120064 is not sector aligned
-offset 121088 is not sector aligned
-offset 122112 is not sector aligned
-offset 123136 is not sector aligned
-offset 124160 is not sector aligned
-offset 125184 is not sector aligned
-offset 126208 is not sector aligned
-offset 127232 is not sector aligned
-offset 128256 is not sector aligned
-offset 129280 is not sector aligned
-offset 130304 is not sector aligned
-offset 131328 is not sector aligned
-offset 132352 is not sector aligned
-offset 133376 is not sector aligned
-offset 134400 is not sector aligned
-offset 135424 is not sector aligned
-offset 136448 is not sector aligned
-offset 137472 is not sector aligned
-offset 138496 is not sector aligned
-offset 139520 is not sector aligned
-offset 140544 is not sector aligned
-offset 141568 is not sector aligned
-offset 142592 is not sector aligned
-offset 143616 is not sector aligned
-offset 144640 is not sector aligned
-offset 145664 is not sector aligned
-offset 146688 is not sector aligned
+read 512/512 bytes at offset 110848
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 111872
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 112896
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 113920
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 114944
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 115968
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 116992
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 118016
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 119040
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 120064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 121088
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 122112
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 123136
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 124160
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 125184
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 126208
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 127232
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 128256
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 129280
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 130304
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 131328
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 132352
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 133376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 134400
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 135424
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 136448
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 137472
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 138496
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 139520
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 140544
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 141568
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 142592
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 143616
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 144640
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 145664
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 146688
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 33
read 2048/2048 bytes at offset 147968
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -789,42 +861,78 @@ wrote 512/512 bytes at offset 108544
wrote 512/512 bytes at offset 109568
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 216
-offset 110848 is not sector aligned
-offset 111872 is not sector aligned
-offset 112896 is not sector aligned
-offset 113920 is not sector aligned
-offset 114944 is not sector aligned
-offset 115968 is not sector aligned
-offset 116992 is not sector aligned
-offset 118016 is not sector aligned
-offset 119040 is not sector aligned
-offset 120064 is not sector aligned
-offset 121088 is not sector aligned
-offset 122112 is not sector aligned
-offset 123136 is not sector aligned
-offset 124160 is not sector aligned
-offset 125184 is not sector aligned
-offset 126208 is not sector aligned
-offset 127232 is not sector aligned
-offset 128256 is not sector aligned
-offset 129280 is not sector aligned
-offset 130304 is not sector aligned
-offset 131328 is not sector aligned
-offset 132352 is not sector aligned
-offset 133376 is not sector aligned
-offset 134400 is not sector aligned
-offset 135424 is not sector aligned
-offset 136448 is not sector aligned
-offset 137472 is not sector aligned
-offset 138496 is not sector aligned
-offset 139520 is not sector aligned
-offset 140544 is not sector aligned
-offset 141568 is not sector aligned
-offset 142592 is not sector aligned
-offset 143616 is not sector aligned
-offset 144640 is not sector aligned
-offset 145664 is not sector aligned
-offset 146688 is not sector aligned
+wrote 512/512 bytes at offset 110848
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 111872
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 112896
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 113920
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 114944
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 115968
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 116992
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 118016
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 119040
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 120064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 121088
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 122112
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 123136
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 124160
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 125184
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 126208
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 127232
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 128256
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 129280
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 130304
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 131328
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 132352
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 133376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 134400
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 135424
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 136448
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 137472
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 138496
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 139520
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 140544
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 141568
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 142592
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 143616
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 144640
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 145664
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 146688
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 33
wrote 2048/2048 bytes at offset 147968
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -1071,42 +1179,78 @@ read 512/512 bytes at offset 108544
read 512/512 bytes at offset 109568
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 216
-offset 110848 is not sector aligned
-offset 111872 is not sector aligned
-offset 112896 is not sector aligned
-offset 113920 is not sector aligned
-offset 114944 is not sector aligned
-offset 115968 is not sector aligned
-offset 116992 is not sector aligned
-offset 118016 is not sector aligned
-offset 119040 is not sector aligned
-offset 120064 is not sector aligned
-offset 121088 is not sector aligned
-offset 122112 is not sector aligned
-offset 123136 is not sector aligned
-offset 124160 is not sector aligned
-offset 125184 is not sector aligned
-offset 126208 is not sector aligned
-offset 127232 is not sector aligned
-offset 128256 is not sector aligned
-offset 129280 is not sector aligned
-offset 130304 is not sector aligned
-offset 131328 is not sector aligned
-offset 132352 is not sector aligned
-offset 133376 is not sector aligned
-offset 134400 is not sector aligned
-offset 135424 is not sector aligned
-offset 136448 is not sector aligned
-offset 137472 is not sector aligned
-offset 138496 is not sector aligned
-offset 139520 is not sector aligned
-offset 140544 is not sector aligned
-offset 141568 is not sector aligned
-offset 142592 is not sector aligned
-offset 143616 is not sector aligned
-offset 144640 is not sector aligned
-offset 145664 is not sector aligned
-offset 146688 is not sector aligned
+read 512/512 bytes at offset 110848
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 111872
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 112896
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 113920
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 114944
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 115968
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 116992
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 118016
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 119040
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 120064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 121088
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 122112
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 123136
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 124160
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 125184
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 126208
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 127232
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 128256
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 129280
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 130304
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 131328
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 132352
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 133376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 134400
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 135424
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 136448
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 137472
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 138496
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 139520
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 140544
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 141568
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 142592
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 143616
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 144640
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 145664
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 146688
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 33
read 2048/2048 bytes at offset 147968
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -1355,42 +1499,78 @@ wrote 512/512 bytes at offset 4295075840
wrote 512/512 bytes at offset 4295076864
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 216
-offset 4295078144 is not sector aligned
-offset 4295079168 is not sector aligned
-offset 4295080192 is not sector aligned
-offset 4295081216 is not sector aligned
-offset 4295082240 is not sector aligned
-offset 4295083264 is not sector aligned
-offset 4295084288 is not sector aligned
-offset 4295085312 is not sector aligned
-offset 4295086336 is not sector aligned
-offset 4295087360 is not sector aligned
-offset 4295088384 is not sector aligned
-offset 4295089408 is not sector aligned
-offset 4295090432 is not sector aligned
-offset 4295091456 is not sector aligned
-offset 4295092480 is not sector aligned
-offset 4295093504 is not sector aligned
-offset 4295094528 is not sector aligned
-offset 4295095552 is not sector aligned
-offset 4295096576 is not sector aligned
-offset 4295097600 is not sector aligned
-offset 4295098624 is not sector aligned
-offset 4295099648 is not sector aligned
-offset 4295100672 is not sector aligned
-offset 4295101696 is not sector aligned
-offset 4295102720 is not sector aligned
-offset 4295103744 is not sector aligned
-offset 4295104768 is not sector aligned
-offset 4295105792 is not sector aligned
-offset 4295106816 is not sector aligned
-offset 4295107840 is not sector aligned
-offset 4295108864 is not sector aligned
-offset 4295109888 is not sector aligned
-offset 4295110912 is not sector aligned
-offset 4295111936 is not sector aligned
-offset 4295112960 is not sector aligned
-offset 4295113984 is not sector aligned
+wrote 512/512 bytes at offset 4295078144
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295079168
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295080192
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295081216
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295082240
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295083264
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295084288
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295085312
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295086336
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295087360
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295088384
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295089408
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295090432
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295091456
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295092480
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295093504
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295094528
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295095552
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295096576
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295097600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295098624
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295099648
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295100672
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295101696
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295102720
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295103744
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295104768
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295105792
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295106816
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295107840
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295108864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295109888
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295110912
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295111936
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295112960
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295113984
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 33
wrote 2048/2048 bytes at offset 4295115264
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -1637,42 +1817,78 @@ read 512/512 bytes at offset 4295075840
read 512/512 bytes at offset 4295076864
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 216
-offset 4295078144 is not sector aligned
-offset 4295079168 is not sector aligned
-offset 4295080192 is not sector aligned
-offset 4295081216 is not sector aligned
-offset 4295082240 is not sector aligned
-offset 4295083264 is not sector aligned
-offset 4295084288 is not sector aligned
-offset 4295085312 is not sector aligned
-offset 4295086336 is not sector aligned
-offset 4295087360 is not sector aligned
-offset 4295088384 is not sector aligned
-offset 4295089408 is not sector aligned
-offset 4295090432 is not sector aligned
-offset 4295091456 is not sector aligned
-offset 4295092480 is not sector aligned
-offset 4295093504 is not sector aligned
-offset 4295094528 is not sector aligned
-offset 4295095552 is not sector aligned
-offset 4295096576 is not sector aligned
-offset 4295097600 is not sector aligned
-offset 4295098624 is not sector aligned
-offset 4295099648 is not sector aligned
-offset 4295100672 is not sector aligned
-offset 4295101696 is not sector aligned
-offset 4295102720 is not sector aligned
-offset 4295103744 is not sector aligned
-offset 4295104768 is not sector aligned
-offset 4295105792 is not sector aligned
-offset 4295106816 is not sector aligned
-offset 4295107840 is not sector aligned
-offset 4295108864 is not sector aligned
-offset 4295109888 is not sector aligned
-offset 4295110912 is not sector aligned
-offset 4295111936 is not sector aligned
-offset 4295112960 is not sector aligned
-offset 4295113984 is not sector aligned
+read 512/512 bytes at offset 4295078144
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295079168
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295080192
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295081216
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295082240
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295083264
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295084288
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295085312
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295086336
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295087360
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295088384
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295089408
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295090432
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295091456
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295092480
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295093504
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295094528
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295095552
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295096576
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295097600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295098624
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295099648
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295100672
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295101696
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295102720
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295103744
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295104768
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295105792
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295106816
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295107840
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295108864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295109888
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295110912
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295111936
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295112960
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295113984
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 33
read 2048/2048 bytes at offset 4295115264
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -1919,42 +2135,78 @@ wrote 512/512 bytes at offset 4295075840
wrote 512/512 bytes at offset 4295076864
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 216
-offset 4295078144 is not sector aligned
-offset 4295079168 is not sector aligned
-offset 4295080192 is not sector aligned
-offset 4295081216 is not sector aligned
-offset 4295082240 is not sector aligned
-offset 4295083264 is not sector aligned
-offset 4295084288 is not sector aligned
-offset 4295085312 is not sector aligned
-offset 4295086336 is not sector aligned
-offset 4295087360 is not sector aligned
-offset 4295088384 is not sector aligned
-offset 4295089408 is not sector aligned
-offset 4295090432 is not sector aligned
-offset 4295091456 is not sector aligned
-offset 4295092480 is not sector aligned
-offset 4295093504 is not sector aligned
-offset 4295094528 is not sector aligned
-offset 4295095552 is not sector aligned
-offset 4295096576 is not sector aligned
-offset 4295097600 is not sector aligned
-offset 4295098624 is not sector aligned
-offset 4295099648 is not sector aligned
-offset 4295100672 is not sector aligned
-offset 4295101696 is not sector aligned
-offset 4295102720 is not sector aligned
-offset 4295103744 is not sector aligned
-offset 4295104768 is not sector aligned
-offset 4295105792 is not sector aligned
-offset 4295106816 is not sector aligned
-offset 4295107840 is not sector aligned
-offset 4295108864 is not sector aligned
-offset 4295109888 is not sector aligned
-offset 4295110912 is not sector aligned
-offset 4295111936 is not sector aligned
-offset 4295112960 is not sector aligned
-offset 4295113984 is not sector aligned
+wrote 512/512 bytes at offset 4295078144
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295079168
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295080192
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295081216
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295082240
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295083264
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295084288
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295085312
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295086336
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295087360
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295088384
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295089408
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295090432
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295091456
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295092480
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295093504
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295094528
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295095552
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295096576
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295097600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295098624
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295099648
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295100672
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295101696
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295102720
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295103744
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295104768
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295105792
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295106816
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295107840
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295108864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295109888
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295110912
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295111936
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295112960
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295113984
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 33
wrote 2048/2048 bytes at offset 4295115264
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -2201,42 +2453,78 @@ read 512/512 bytes at offset 4295075840
read 512/512 bytes at offset 4295076864
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 216
-offset 4295078144 is not sector aligned
-offset 4295079168 is not sector aligned
-offset 4295080192 is not sector aligned
-offset 4295081216 is not sector aligned
-offset 4295082240 is not sector aligned
-offset 4295083264 is not sector aligned
-offset 4295084288 is not sector aligned
-offset 4295085312 is not sector aligned
-offset 4295086336 is not sector aligned
-offset 4295087360 is not sector aligned
-offset 4295088384 is not sector aligned
-offset 4295089408 is not sector aligned
-offset 4295090432 is not sector aligned
-offset 4295091456 is not sector aligned
-offset 4295092480 is not sector aligned
-offset 4295093504 is not sector aligned
-offset 4295094528 is not sector aligned
-offset 4295095552 is not sector aligned
-offset 4295096576 is not sector aligned
-offset 4295097600 is not sector aligned
-offset 4295098624 is not sector aligned
-offset 4295099648 is not sector aligned
-offset 4295100672 is not sector aligned
-offset 4295101696 is not sector aligned
-offset 4295102720 is not sector aligned
-offset 4295103744 is not sector aligned
-offset 4295104768 is not sector aligned
-offset 4295105792 is not sector aligned
-offset 4295106816 is not sector aligned
-offset 4295107840 is not sector aligned
-offset 4295108864 is not sector aligned
-offset 4295109888 is not sector aligned
-offset 4295110912 is not sector aligned
-offset 4295111936 is not sector aligned
-offset 4295112960 is not sector aligned
-offset 4295113984 is not sector aligned
+read 512/512 bytes at offset 4295078144
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295079168
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295080192
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295081216
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295082240
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295083264
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295084288
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295085312
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295086336
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295087360
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295088384
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295089408
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295090432
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295091456
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295092480
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295093504
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295094528
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295095552
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295096576
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295097600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295098624
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295099648
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295100672
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295101696
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295102720
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295103744
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295104768
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295105792
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295106816
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295107840
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295108864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295109888
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295110912
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295111936
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295112960
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295113984
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 33
read 2048/2048 bytes at offset 4295115264
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -2489,42 +2777,78 @@ read 512/512 bytes at offset 108544
read 512/512 bytes at offset 109568
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 216
-offset 110848 is not sector aligned
-offset 111872 is not sector aligned
-offset 112896 is not sector aligned
-offset 113920 is not sector aligned
-offset 114944 is not sector aligned
-offset 115968 is not sector aligned
-offset 116992 is not sector aligned
-offset 118016 is not sector aligned
-offset 119040 is not sector aligned
-offset 120064 is not sector aligned
-offset 121088 is not sector aligned
-offset 122112 is not sector aligned
-offset 123136 is not sector aligned
-offset 124160 is not sector aligned
-offset 125184 is not sector aligned
-offset 126208 is not sector aligned
-offset 127232 is not sector aligned
-offset 128256 is not sector aligned
-offset 129280 is not sector aligned
-offset 130304 is not sector aligned
-offset 131328 is not sector aligned
-offset 132352 is not sector aligned
-offset 133376 is not sector aligned
-offset 134400 is not sector aligned
-offset 135424 is not sector aligned
-offset 136448 is not sector aligned
-offset 137472 is not sector aligned
-offset 138496 is not sector aligned
-offset 139520 is not sector aligned
-offset 140544 is not sector aligned
-offset 141568 is not sector aligned
-offset 142592 is not sector aligned
-offset 143616 is not sector aligned
-offset 144640 is not sector aligned
-offset 145664 is not sector aligned
-offset 146688 is not sector aligned
+read 512/512 bytes at offset 110848
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 111872
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 112896
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 113920
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 114944
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 115968
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 116992
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 118016
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 119040
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 120064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 121088
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 122112
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 123136
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 124160
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 125184
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 126208
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 127232
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 128256
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 129280
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 130304
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 131328
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 132352
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 133376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 134400
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 135424
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 136448
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 137472
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 138496
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 139520
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 140544
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 141568
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 142592
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 143616
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 144640
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 145664
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 146688
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 33
read 2048/2048 bytes at offset 147968
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -2771,42 +3095,78 @@ read 512/512 bytes at offset 108544
read 512/512 bytes at offset 109568
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 216
-offset 110848 is not sector aligned
-offset 111872 is not sector aligned
-offset 112896 is not sector aligned
-offset 113920 is not sector aligned
-offset 114944 is not sector aligned
-offset 115968 is not sector aligned
-offset 116992 is not sector aligned
-offset 118016 is not sector aligned
-offset 119040 is not sector aligned
-offset 120064 is not sector aligned
-offset 121088 is not sector aligned
-offset 122112 is not sector aligned
-offset 123136 is not sector aligned
-offset 124160 is not sector aligned
-offset 125184 is not sector aligned
-offset 126208 is not sector aligned
-offset 127232 is not sector aligned
-offset 128256 is not sector aligned
-offset 129280 is not sector aligned
-offset 130304 is not sector aligned
-offset 131328 is not sector aligned
-offset 132352 is not sector aligned
-offset 133376 is not sector aligned
-offset 134400 is not sector aligned
-offset 135424 is not sector aligned
-offset 136448 is not sector aligned
-offset 137472 is not sector aligned
-offset 138496 is not sector aligned
-offset 139520 is not sector aligned
-offset 140544 is not sector aligned
-offset 141568 is not sector aligned
-offset 142592 is not sector aligned
-offset 143616 is not sector aligned
-offset 144640 is not sector aligned
-offset 145664 is not sector aligned
-offset 146688 is not sector aligned
+read 512/512 bytes at offset 110848
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 111872
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 112896
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 113920
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 114944
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 115968
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 116992
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 118016
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 119040
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 120064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 121088
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 122112
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 123136
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 124160
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 125184
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 126208
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 127232
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 128256
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 129280
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 130304
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 131328
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 132352
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 133376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 134400
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 135424
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 136448
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 137472
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 138496
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 139520
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 140544
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 141568
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 142592
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 143616
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 144640
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 145664
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 146688
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 33
read 2048/2048 bytes at offset 147968
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -3055,42 +3415,78 @@ read 512/512 bytes at offset 4295075840
read 512/512 bytes at offset 4295076864
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 216
-offset 4295078144 is not sector aligned
-offset 4295079168 is not sector aligned
-offset 4295080192 is not sector aligned
-offset 4295081216 is not sector aligned
-offset 4295082240 is not sector aligned
-offset 4295083264 is not sector aligned
-offset 4295084288 is not sector aligned
-offset 4295085312 is not sector aligned
-offset 4295086336 is not sector aligned
-offset 4295087360 is not sector aligned
-offset 4295088384 is not sector aligned
-offset 4295089408 is not sector aligned
-offset 4295090432 is not sector aligned
-offset 4295091456 is not sector aligned
-offset 4295092480 is not sector aligned
-offset 4295093504 is not sector aligned
-offset 4295094528 is not sector aligned
-offset 4295095552 is not sector aligned
-offset 4295096576 is not sector aligned
-offset 4295097600 is not sector aligned
-offset 4295098624 is not sector aligned
-offset 4295099648 is not sector aligned
-offset 4295100672 is not sector aligned
-offset 4295101696 is not sector aligned
-offset 4295102720 is not sector aligned
-offset 4295103744 is not sector aligned
-offset 4295104768 is not sector aligned
-offset 4295105792 is not sector aligned
-offset 4295106816 is not sector aligned
-offset 4295107840 is not sector aligned
-offset 4295108864 is not sector aligned
-offset 4295109888 is not sector aligned
-offset 4295110912 is not sector aligned
-offset 4295111936 is not sector aligned
-offset 4295112960 is not sector aligned
-offset 4295113984 is not sector aligned
+read 512/512 bytes at offset 4295078144
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295079168
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295080192
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295081216
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295082240
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295083264
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295084288
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295085312
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295086336
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295087360
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295088384
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295089408
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295090432
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295091456
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295092480
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295093504
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295094528
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295095552
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295096576
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295097600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295098624
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295099648
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295100672
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295101696
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295102720
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295103744
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295104768
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295105792
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295106816
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295107840
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295108864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295109888
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295110912
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295111936
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295112960
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295113984
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 33
read 2048/2048 bytes at offset 4295115264
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -3337,42 +3733,78 @@ read 512/512 bytes at offset 4295075840
read 512/512 bytes at offset 4295076864
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 216
-offset 4295078144 is not sector aligned
-offset 4295079168 is not sector aligned
-offset 4295080192 is not sector aligned
-offset 4295081216 is not sector aligned
-offset 4295082240 is not sector aligned
-offset 4295083264 is not sector aligned
-offset 4295084288 is not sector aligned
-offset 4295085312 is not sector aligned
-offset 4295086336 is not sector aligned
-offset 4295087360 is not sector aligned
-offset 4295088384 is not sector aligned
-offset 4295089408 is not sector aligned
-offset 4295090432 is not sector aligned
-offset 4295091456 is not sector aligned
-offset 4295092480 is not sector aligned
-offset 4295093504 is not sector aligned
-offset 4295094528 is not sector aligned
-offset 4295095552 is not sector aligned
-offset 4295096576 is not sector aligned
-offset 4295097600 is not sector aligned
-offset 4295098624 is not sector aligned
-offset 4295099648 is not sector aligned
-offset 4295100672 is not sector aligned
-offset 4295101696 is not sector aligned
-offset 4295102720 is not sector aligned
-offset 4295103744 is not sector aligned
-offset 4295104768 is not sector aligned
-offset 4295105792 is not sector aligned
-offset 4295106816 is not sector aligned
-offset 4295107840 is not sector aligned
-offset 4295108864 is not sector aligned
-offset 4295109888 is not sector aligned
-offset 4295110912 is not sector aligned
-offset 4295111936 is not sector aligned
-offset 4295112960 is not sector aligned
-offset 4295113984 is not sector aligned
+read 512/512 bytes at offset 4295078144
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295079168
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295080192
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295081216
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295082240
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295083264
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295084288
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295085312
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295086336
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295087360
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295088384
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295089408
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295090432
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295091456
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295092480
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295093504
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295094528
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295095552
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295096576
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295097600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295098624
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295099648
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295100672
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295101696
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295102720
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295103744
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295104768
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295105792
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295106816
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295107840
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295108864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295109888
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295110912
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295111936
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295112960
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295113984
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 33
read 2048/2048 bytes at offset 4295115264
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -3623,42 +4055,78 @@ wrote 512/512 bytes at offset 109056
wrote 512/512 bytes at offset 110080
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 217
-offset 111360 is not sector aligned
-offset 112384 is not sector aligned
-offset 113408 is not sector aligned
-offset 114432 is not sector aligned
-offset 115456 is not sector aligned
-offset 116480 is not sector aligned
-offset 117504 is not sector aligned
-offset 118528 is not sector aligned
-offset 119552 is not sector aligned
-offset 120576 is not sector aligned
-offset 121600 is not sector aligned
-offset 122624 is not sector aligned
-offset 123648 is not sector aligned
-offset 124672 is not sector aligned
-offset 125696 is not sector aligned
-offset 126720 is not sector aligned
-offset 127744 is not sector aligned
-offset 128768 is not sector aligned
-offset 129792 is not sector aligned
-offset 130816 is not sector aligned
-offset 131840 is not sector aligned
-offset 132864 is not sector aligned
-offset 133888 is not sector aligned
-offset 134912 is not sector aligned
-offset 135936 is not sector aligned
-offset 136960 is not sector aligned
-offset 137984 is not sector aligned
-offset 139008 is not sector aligned
-offset 140032 is not sector aligned
-offset 141056 is not sector aligned
-offset 142080 is not sector aligned
-offset 143104 is not sector aligned
-offset 144128 is not sector aligned
-offset 145152 is not sector aligned
-offset 146176 is not sector aligned
-offset 147200 is not sector aligned
+wrote 512/512 bytes at offset 111360
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 112384
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 113408
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 114432
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 115456
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 116480
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 117504
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 118528
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 119552
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 120576
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 121600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 122624
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 123648
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 124672
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 125696
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 126720
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 127744
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 128768
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 129792
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 130816
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 131840
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 132864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 133888
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 134912
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 135936
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 136960
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 137984
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 139008
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 140032
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 141056
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 142080
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 143104
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 144128
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 145152
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 146176
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 147200
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 34
wrote 2048/2048 bytes at offset 148480
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -3905,42 +4373,78 @@ read 512/512 bytes at offset 109056
read 512/512 bytes at offset 110080
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 217
-offset 111360 is not sector aligned
-offset 112384 is not sector aligned
-offset 113408 is not sector aligned
-offset 114432 is not sector aligned
-offset 115456 is not sector aligned
-offset 116480 is not sector aligned
-offset 117504 is not sector aligned
-offset 118528 is not sector aligned
-offset 119552 is not sector aligned
-offset 120576 is not sector aligned
-offset 121600 is not sector aligned
-offset 122624 is not sector aligned
-offset 123648 is not sector aligned
-offset 124672 is not sector aligned
-offset 125696 is not sector aligned
-offset 126720 is not sector aligned
-offset 127744 is not sector aligned
-offset 128768 is not sector aligned
-offset 129792 is not sector aligned
-offset 130816 is not sector aligned
-offset 131840 is not sector aligned
-offset 132864 is not sector aligned
-offset 133888 is not sector aligned
-offset 134912 is not sector aligned
-offset 135936 is not sector aligned
-offset 136960 is not sector aligned
-offset 137984 is not sector aligned
-offset 139008 is not sector aligned
-offset 140032 is not sector aligned
-offset 141056 is not sector aligned
-offset 142080 is not sector aligned
-offset 143104 is not sector aligned
-offset 144128 is not sector aligned
-offset 145152 is not sector aligned
-offset 146176 is not sector aligned
-offset 147200 is not sector aligned
+read 512/512 bytes at offset 111360
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 112384
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 113408
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 114432
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 115456
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 116480
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 117504
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 118528
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 119552
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 120576
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 121600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 122624
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 123648
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 124672
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 125696
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 126720
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 127744
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 128768
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 129792
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 130816
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 131840
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 132864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 133888
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 134912
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 135936
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 136960
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 137984
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 139008
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 140032
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 141056
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 142080
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 143104
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 144128
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 145152
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 146176
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 147200
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 34
read 2048/2048 bytes at offset 148480
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -4187,42 +4691,78 @@ wrote 512/512 bytes at offset 109056
wrote 512/512 bytes at offset 110080
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 217
-offset 111360 is not sector aligned
-offset 112384 is not sector aligned
-offset 113408 is not sector aligned
-offset 114432 is not sector aligned
-offset 115456 is not sector aligned
-offset 116480 is not sector aligned
-offset 117504 is not sector aligned
-offset 118528 is not sector aligned
-offset 119552 is not sector aligned
-offset 120576 is not sector aligned
-offset 121600 is not sector aligned
-offset 122624 is not sector aligned
-offset 123648 is not sector aligned
-offset 124672 is not sector aligned
-offset 125696 is not sector aligned
-offset 126720 is not sector aligned
-offset 127744 is not sector aligned
-offset 128768 is not sector aligned
-offset 129792 is not sector aligned
-offset 130816 is not sector aligned
-offset 131840 is not sector aligned
-offset 132864 is not sector aligned
-offset 133888 is not sector aligned
-offset 134912 is not sector aligned
-offset 135936 is not sector aligned
-offset 136960 is not sector aligned
-offset 137984 is not sector aligned
-offset 139008 is not sector aligned
-offset 140032 is not sector aligned
-offset 141056 is not sector aligned
-offset 142080 is not sector aligned
-offset 143104 is not sector aligned
-offset 144128 is not sector aligned
-offset 145152 is not sector aligned
-offset 146176 is not sector aligned
-offset 147200 is not sector aligned
+wrote 512/512 bytes at offset 111360
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 112384
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 113408
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 114432
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 115456
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 116480
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 117504
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 118528
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 119552
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 120576
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 121600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 122624
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 123648
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 124672
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 125696
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 126720
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 127744
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 128768
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 129792
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 130816
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 131840
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 132864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 133888
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 134912
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 135936
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 136960
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 137984
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 139008
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 140032
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 141056
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 142080
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 143104
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 144128
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 145152
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 146176
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 147200
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 34
wrote 2048/2048 bytes at offset 148480
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -4469,42 +5009,78 @@ read 512/512 bytes at offset 109056
read 512/512 bytes at offset 110080
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 217
-offset 111360 is not sector aligned
-offset 112384 is not sector aligned
-offset 113408 is not sector aligned
-offset 114432 is not sector aligned
-offset 115456 is not sector aligned
-offset 116480 is not sector aligned
-offset 117504 is not sector aligned
-offset 118528 is not sector aligned
-offset 119552 is not sector aligned
-offset 120576 is not sector aligned
-offset 121600 is not sector aligned
-offset 122624 is not sector aligned
-offset 123648 is not sector aligned
-offset 124672 is not sector aligned
-offset 125696 is not sector aligned
-offset 126720 is not sector aligned
-offset 127744 is not sector aligned
-offset 128768 is not sector aligned
-offset 129792 is not sector aligned
-offset 130816 is not sector aligned
-offset 131840 is not sector aligned
-offset 132864 is not sector aligned
-offset 133888 is not sector aligned
-offset 134912 is not sector aligned
-offset 135936 is not sector aligned
-offset 136960 is not sector aligned
-offset 137984 is not sector aligned
-offset 139008 is not sector aligned
-offset 140032 is not sector aligned
-offset 141056 is not sector aligned
-offset 142080 is not sector aligned
-offset 143104 is not sector aligned
-offset 144128 is not sector aligned
-offset 145152 is not sector aligned
-offset 146176 is not sector aligned
-offset 147200 is not sector aligned
+read 512/512 bytes at offset 111360
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 112384
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 113408
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 114432
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 115456
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 116480
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 117504
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 118528
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 119552
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 120576
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 121600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 122624
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 123648
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 124672
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 125696
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 126720
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 127744
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 128768
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 129792
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 130816
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 131840
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 132864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 133888
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 134912
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 135936
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 136960
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 137984
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 139008
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 140032
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 141056
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 142080
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 143104
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 144128
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 145152
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 146176
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 147200
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 34
read 2048/2048 bytes at offset 148480
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -4753,42 +5329,78 @@ wrote 512/512 bytes at offset 4295076352
wrote 512/512 bytes at offset 4295077376
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 217
-offset 4295078656 is not sector aligned
-offset 4295079680 is not sector aligned
-offset 4295080704 is not sector aligned
-offset 4295081728 is not sector aligned
-offset 4295082752 is not sector aligned
-offset 4295083776 is not sector aligned
-offset 4295084800 is not sector aligned
-offset 4295085824 is not sector aligned
-offset 4295086848 is not sector aligned
-offset 4295087872 is not sector aligned
-offset 4295088896 is not sector aligned
-offset 4295089920 is not sector aligned
-offset 4295090944 is not sector aligned
-offset 4295091968 is not sector aligned
-offset 4295092992 is not sector aligned
-offset 4295094016 is not sector aligned
-offset 4295095040 is not sector aligned
-offset 4295096064 is not sector aligned
-offset 4295097088 is not sector aligned
-offset 4295098112 is not sector aligned
-offset 4295099136 is not sector aligned
-offset 4295100160 is not sector aligned
-offset 4295101184 is not sector aligned
-offset 4295102208 is not sector aligned
-offset 4295103232 is not sector aligned
-offset 4295104256 is not sector aligned
-offset 4295105280 is not sector aligned
-offset 4295106304 is not sector aligned
-offset 4295107328 is not sector aligned
-offset 4295108352 is not sector aligned
-offset 4295109376 is not sector aligned
-offset 4295110400 is not sector aligned
-offset 4295111424 is not sector aligned
-offset 4295112448 is not sector aligned
-offset 4295113472 is not sector aligned
-offset 4295114496 is not sector aligned
+wrote 512/512 bytes at offset 4295078656
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295079680
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295080704
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295081728
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295082752
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295083776
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295084800
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295085824
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295086848
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295087872
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295088896
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295089920
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295090944
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295091968
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295092992
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295094016
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295095040
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295096064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295097088
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295098112
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295099136
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295100160
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295101184
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295102208
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295103232
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295104256
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295105280
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295106304
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295107328
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295108352
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295109376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295110400
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295111424
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295112448
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295113472
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295114496
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 34
wrote 2048/2048 bytes at offset 4295115776
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -5035,42 +5647,78 @@ read 512/512 bytes at offset 4295076352
read 512/512 bytes at offset 4295077376
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 217
-offset 4295078656 is not sector aligned
-offset 4295079680 is not sector aligned
-offset 4295080704 is not sector aligned
-offset 4295081728 is not sector aligned
-offset 4295082752 is not sector aligned
-offset 4295083776 is not sector aligned
-offset 4295084800 is not sector aligned
-offset 4295085824 is not sector aligned
-offset 4295086848 is not sector aligned
-offset 4295087872 is not sector aligned
-offset 4295088896 is not sector aligned
-offset 4295089920 is not sector aligned
-offset 4295090944 is not sector aligned
-offset 4295091968 is not sector aligned
-offset 4295092992 is not sector aligned
-offset 4295094016 is not sector aligned
-offset 4295095040 is not sector aligned
-offset 4295096064 is not sector aligned
-offset 4295097088 is not sector aligned
-offset 4295098112 is not sector aligned
-offset 4295099136 is not sector aligned
-offset 4295100160 is not sector aligned
-offset 4295101184 is not sector aligned
-offset 4295102208 is not sector aligned
-offset 4295103232 is not sector aligned
-offset 4295104256 is not sector aligned
-offset 4295105280 is not sector aligned
-offset 4295106304 is not sector aligned
-offset 4295107328 is not sector aligned
-offset 4295108352 is not sector aligned
-offset 4295109376 is not sector aligned
-offset 4295110400 is not sector aligned
-offset 4295111424 is not sector aligned
-offset 4295112448 is not sector aligned
-offset 4295113472 is not sector aligned
-offset 4295114496 is not sector aligned
+read 512/512 bytes at offset 4295078656
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295079680
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295080704
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295081728
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295082752
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295083776
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295084800
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295085824
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295086848
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295087872
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295088896
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295089920
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295090944
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295091968
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295092992
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295094016
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295095040
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295096064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295097088
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295098112
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295099136
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295100160
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295101184
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295102208
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295103232
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295104256
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295105280
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295106304
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295107328
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295108352
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295109376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295110400
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295111424
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295112448
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295113472
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295114496
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 34
read 2048/2048 bytes at offset 4295115776
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -5317,42 +5965,78 @@ wrote 512/512 bytes at offset 4295076352
wrote 512/512 bytes at offset 4295077376
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 217
-offset 4295078656 is not sector aligned
-offset 4295079680 is not sector aligned
-offset 4295080704 is not sector aligned
-offset 4295081728 is not sector aligned
-offset 4295082752 is not sector aligned
-offset 4295083776 is not sector aligned
-offset 4295084800 is not sector aligned
-offset 4295085824 is not sector aligned
-offset 4295086848 is not sector aligned
-offset 4295087872 is not sector aligned
-offset 4295088896 is not sector aligned
-offset 4295089920 is not sector aligned
-offset 4295090944 is not sector aligned
-offset 4295091968 is not sector aligned
-offset 4295092992 is not sector aligned
-offset 4295094016 is not sector aligned
-offset 4295095040 is not sector aligned
-offset 4295096064 is not sector aligned
-offset 4295097088 is not sector aligned
-offset 4295098112 is not sector aligned
-offset 4295099136 is not sector aligned
-offset 4295100160 is not sector aligned
-offset 4295101184 is not sector aligned
-offset 4295102208 is not sector aligned
-offset 4295103232 is not sector aligned
-offset 4295104256 is not sector aligned
-offset 4295105280 is not sector aligned
-offset 4295106304 is not sector aligned
-offset 4295107328 is not sector aligned
-offset 4295108352 is not sector aligned
-offset 4295109376 is not sector aligned
-offset 4295110400 is not sector aligned
-offset 4295111424 is not sector aligned
-offset 4295112448 is not sector aligned
-offset 4295113472 is not sector aligned
-offset 4295114496 is not sector aligned
+wrote 512/512 bytes at offset 4295078656
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295079680
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295080704
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295081728
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295082752
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295083776
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295084800
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295085824
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295086848
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295087872
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295088896
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295089920
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295090944
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295091968
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295092992
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295094016
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295095040
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295096064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295097088
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295098112
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295099136
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295100160
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295101184
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295102208
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295103232
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295104256
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295105280
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295106304
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295107328
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295108352
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295109376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295110400
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295111424
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295112448
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295113472
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 4295114496
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 34
wrote 2048/2048 bytes at offset 4295115776
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -5599,42 +6283,78 @@ read 512/512 bytes at offset 4295076352
read 512/512 bytes at offset 4295077376
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 217
-offset 4295078656 is not sector aligned
-offset 4295079680 is not sector aligned
-offset 4295080704 is not sector aligned
-offset 4295081728 is not sector aligned
-offset 4295082752 is not sector aligned
-offset 4295083776 is not sector aligned
-offset 4295084800 is not sector aligned
-offset 4295085824 is not sector aligned
-offset 4295086848 is not sector aligned
-offset 4295087872 is not sector aligned
-offset 4295088896 is not sector aligned
-offset 4295089920 is not sector aligned
-offset 4295090944 is not sector aligned
-offset 4295091968 is not sector aligned
-offset 4295092992 is not sector aligned
-offset 4295094016 is not sector aligned
-offset 4295095040 is not sector aligned
-offset 4295096064 is not sector aligned
-offset 4295097088 is not sector aligned
-offset 4295098112 is not sector aligned
-offset 4295099136 is not sector aligned
-offset 4295100160 is not sector aligned
-offset 4295101184 is not sector aligned
-offset 4295102208 is not sector aligned
-offset 4295103232 is not sector aligned
-offset 4295104256 is not sector aligned
-offset 4295105280 is not sector aligned
-offset 4295106304 is not sector aligned
-offset 4295107328 is not sector aligned
-offset 4295108352 is not sector aligned
-offset 4295109376 is not sector aligned
-offset 4295110400 is not sector aligned
-offset 4295111424 is not sector aligned
-offset 4295112448 is not sector aligned
-offset 4295113472 is not sector aligned
-offset 4295114496 is not sector aligned
+read 512/512 bytes at offset 4295078656
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295079680
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295080704
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295081728
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295082752
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295083776
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295084800
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295085824
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295086848
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295087872
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295088896
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295089920
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295090944
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295091968
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295092992
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295094016
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295095040
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295096064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295097088
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295098112
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295099136
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295100160
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295101184
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295102208
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295103232
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295104256
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295105280
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295106304
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295107328
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295108352
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295109376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295110400
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295111424
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295112448
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295113472
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 4295114496
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== IO: pattern 34
read 2048/2048 bytes at offset 4295115776
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out
index d84d82c112..853173572b 100644
--- a/tests/qemu-iotests/026.out
+++ b/tests/qemu-iotests/026.out
@@ -14,7 +14,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_update; errno: 5; imm: off; once: off; write
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
@@ -23,7 +22,6 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_update; errno: 5; imm: off; once: off; write -b
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
@@ -42,7 +40,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_update; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -51,7 +48,6 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_update; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -78,11 +74,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_load; errno: 5; imm: off; once: off; write
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
read failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -90,11 +82,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_load; errno: 5; imm: off; once: off; write -b
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
read failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -118,11 +106,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_load; errno: 28; imm: off; once: off; write
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
read failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -130,11 +114,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_load; errno: 28; imm: off; once: off; write -b
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
read failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -306,14 +286,12 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_load; errno: 5; imm: off; once: off; write
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_load; errno: 5; imm: off; once: off; write -b
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
@@ -330,14 +308,12 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_load; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_load; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
@@ -354,14 +330,12 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_update_part; errno: 5; imm: off; once: off; write
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_update_part; errno: 5; imm: off; once: off; write -b
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
@@ -378,14 +352,12 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_update_part; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_update_part; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
@@ -402,14 +374,12 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc; errno: 5; imm: off; once: off; write
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc; errno: 5; imm: off; once: off; write -b
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
@@ -426,14 +396,12 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
@@ -450,15 +418,11 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: cluster_alloc; errno: 5; imm: off; once: off; write
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: cluster_alloc; errno: 5; imm: off; once: off; write -b
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -474,15 +438,11 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: cluster_alloc; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: cluster_alloc; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
@@ -553,7 +513,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -562,7 +521,6 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -581,7 +539,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -590,7 +547,6 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -635,8 +591,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_grow_alloc_table; errno: 5; imm: off; once: off
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -647,8 +601,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_grow_alloc_table; errno: 28; imm: off; once: off
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -659,7 +611,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_grow_write_table; errno: 5; imm: off; once: off
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
@@ -671,7 +622,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_grow_write_table; errno: 28; imm: off; once: off
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
index 9c2c8a9486..672d77c6ec 100644
--- a/tests/qemu-iotests/026.out.nocache
+++ b/tests/qemu-iotests/026.out.nocache
@@ -14,7 +14,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_update; errno: 5; imm: off; once: off; write
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
@@ -23,7 +22,6 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_update; errno: 5; imm: off; once: off; write -b
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
@@ -42,7 +40,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_update; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -51,7 +48,6 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_update; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -78,11 +74,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_load; errno: 5; imm: off; once: off; write
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
read failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -90,11 +82,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_load; errno: 5; imm: off; once: off; write -b
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
read failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -118,11 +106,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_load; errno: 28; imm: off; once: off; write
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
read failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -130,11 +114,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_load; errno: 28; imm: off; once: off; write -b
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
read failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -314,14 +294,12 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_load; errno: 5; imm: off; once: off; write
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_load; errno: 5; imm: off; once: off; write -b
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
@@ -338,14 +316,12 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_load; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_load; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
@@ -362,14 +338,12 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_update_part; errno: 5; imm: off; once: off; write
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_update_part; errno: 5; imm: off; once: off; write -b
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
@@ -386,14 +360,12 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_update_part; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_update_part; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
@@ -410,14 +382,12 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc; errno: 5; imm: off; once: off; write
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc; errno: 5; imm: off; once: off; write -b
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
@@ -434,14 +404,12 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
@@ -458,15 +426,11 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: cluster_alloc; errno: 5; imm: off; once: off; write
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: cluster_alloc; errno: 5; imm: off; once: off; write -b
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -482,15 +446,11 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: cluster_alloc; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: cluster_alloc; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
@@ -561,7 +521,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -570,7 +529,6 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -589,7 +547,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -598,7 +555,6 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -b
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -643,8 +599,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_grow_alloc_table; errno: 5; imm: off; once: off
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -655,8 +609,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_grow_alloc_table; errno: 28; imm: off; once: off
-Failed to flush the L2 table cache: No space left on device
-Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -667,7 +619,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_grow_write_table; errno: 5; imm: off; once: off
-Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
@@ -679,7 +630,6 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_grow_write_table; errno: 28; imm: off; once: off
-Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
diff --git a/tests/qemu-iotests/034 b/tests/qemu-iotests/034
index c711cfce94..1b28bdae63 100755
--- a/tests/qemu-iotests/034
+++ b/tests/qemu-iotests/034
@@ -1,6 +1,6 @@
#!/bin/bash
#
-# Test bdrv_write_zeroes with backing files
+# Test bdrv_pwrite_zeroes with backing files (see also 154)
#
# Copyright (C) 2012 Red Hat, Inc.
#
diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out
index 32c884694c..c6e0ac2da3 100644
--- a/tests/qemu-iotests/039.out
+++ b/tests/qemu-iotests/039.out
@@ -12,9 +12,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
- exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
else
- exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
fi )
incompatible_features 0x1
ERROR cluster 5 refcount=0 reference=1
@@ -51,9 +51,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
- exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
else
- exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
fi )
incompatible_features 0x1
ERROR cluster 5 refcount=0 reference=1
@@ -69,9 +69,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
- exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
else
- exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
fi )
incompatible_features 0x0
No errors were found on the image.
@@ -92,9 +92,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
- exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
else
- exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
fi )
incompatible_features 0x1
ERROR cluster 5 refcount=0 reference=1
@@ -106,9 +106,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
- exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
else
- exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
fi )
incompatible_features 0x0
No errors were found on the image.
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index b1c542f99b..cbf5e0ba5c 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -207,33 +207,6 @@ class TestSingleBlockdev(TestSingleDrive):
test_image_not_found = None
test_small_buffer2 = None
-class TestBlockdevAttached(iotests.QMPTestCase):
- image_len = 1 * 1024 * 1024 # MB
-
- def setUp(self):
- iotests.create_image(backing_img, self.image_len)
- qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
- qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, target_img)
- self.vm = iotests.VM().add_drive(test_img)
- self.vm.launch()
-
- def tearDown(self):
- self.vm.shutdown()
- os.remove(test_img)
- os.remove(target_img)
-
- def test_blockdev_attached(self):
- self.assert_no_active_block_jobs()
- args = {'options':
- {'driver': iotests.imgfmt,
- 'id': 'drive1',
- 'file': { 'filename': target_img, 'driver': 'file' } } }
- result = self.vm.qmp("blockdev-add", **args)
- self.assert_qmp(result, 'return', {})
- result = self.vm.qmp('blockdev-mirror', device='drive0', sync='full',
- target='drive1')
- self.assert_qmp(result, 'error/class', 'GenericError')
-
class TestSingleDriveZeroLength(TestSingleDrive):
image_len = 0
test_small_buffer2 = None
@@ -754,6 +727,36 @@ class TestUnbackedSource(iotests.QMPTestCase):
self.complete_and_wait()
self.assert_no_active_block_jobs()
+class TestGranularity(iotests.QMPTestCase):
+ image_len = 10 * 1024 * 1024 # MB
+
+ def setUp(self):
+ qemu_img('create', '-f', iotests.imgfmt, test_img,
+ str(TestGranularity.image_len))
+ qemu_io('-c', 'write 0 %d' % (self.image_len),
+ test_img)
+ self.vm = iotests.VM().add_drive(test_img)
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ self.assertTrue(iotests.compare_images(test_img, target_img),
+ 'target image does not match source after mirroring')
+ os.remove(test_img)
+ os.remove(target_img)
+
+ def test_granularity(self):
+ self.assert_no_active_block_jobs()
+ result = self.vm.qmp('drive-mirror', device='drive0',
+ sync='full', target=target_img,
+ mode='absolute-paths', granularity=8192)
+ self.assert_qmp(result, 'return', {})
+ event = self.vm.get_qmp_event(wait=60.0)
+ # Failures will manifest as COMPLETED/ERROR.
+ self.assert_qmp(event, 'event', 'BLOCK_JOB_READY')
+ self.complete_and_wait(drive='drive0', wait_ready=False)
+ self.assert_no_active_block_jobs()
+
class TestRepairQuorum(iotests.QMPTestCase):
""" This class test quorum file repair using drive-mirror.
It's mostly a fork of TestSingleDrive """
diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048
index e1eeac2a31..203c04fc7f 100755
--- a/tests/qemu-iotests/048
+++ b/tests/qemu-iotests/048
@@ -31,13 +31,13 @@ _cleanup()
{
echo "Cleanup"
_cleanup_test_img
- rm "${TEST_IMG2}"
+ rm "${TEST_IMG_FILE2}"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
_compare()
{
- $QEMU_IMG compare "$@" "$TEST_IMG" "${TEST_IMG2}"
+ $QEMU_IMG compare $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" "${TEST_IMG2}"
echo $?
}
@@ -46,25 +46,37 @@ _compare()
. ./common.filter
. ./common.pattern
-_supported_fmt raw qcow qcow2 qed
+_supported_fmt raw qcow qcow2 qed luks
_supported_proto file
_supported_os Linux
+# Remove once all tests are fixed to use TEST_IMG_FILE
+# correctly and common.rc sets it unconditionally
+test -z "$TEST_IMG_FILE" && TEST_IMG_FILE=$TEST_IMG
+
# Setup test basic parameters
TEST_IMG2=$TEST_IMG.2
+TEST_IMG_FILE2=$TEST_IMG_FILE.2
CLUSTER_SIZE=4096
-size=1024M
+size=128M
_make_test_img $size
io_pattern write 524288 $CLUSTER_SIZE $CLUSTER_SIZE 4 45
# Compare identical images
-cp "$TEST_IMG" "${TEST_IMG2}"
+cp "$TEST_IMG_FILE" "${TEST_IMG_FILE2}"
_compare
_compare -q
# Compare images with different size
-$QEMU_IMG resize -f $IMGFMT "$TEST_IMG" +512M
+if [ "$IMGOPTSSYNTAX" = "true" ]; then
+ $QEMU_IMG resize $QEMU_IMG_EXTRA_ARGS "$TEST_IMG" +32M
+else
+ $QEMU_IMG resize -f $IMGFMT "$TEST_IMG" +32M
+fi
+# Ensure extended space is zero-initialized
+$QEMU_IO "$TEST_IMG" -c "write -z $size 32M" | _filter_qemu_io
+
_compare
_compare -s
@@ -77,7 +89,7 @@ _compare
# Test unaligned case of mismatch offsets in allocated clusters
_make_test_img $size
io_pattern write 0 512 0 1 100
-cp "$TEST_IMG" "$TEST_IMG2"
+cp "$TEST_IMG_FILE" "$TEST_IMG_FILE2"
io_pattern write 512 512 0 1 101
_compare
diff --git a/tests/qemu-iotests/048.out b/tests/qemu-iotests/048.out
index 57100dc453..0bcf6635a1 100644
--- a/tests/qemu-iotests/048.out
+++ b/tests/qemu-iotests/048.out
@@ -1,5 +1,5 @@
QA output created by 048
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
=== IO: pattern 45
wrote 4096/4096 bytes at offset 524288
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -13,6 +13,8 @@ Images are identical.
0
0
Image resized.
+wrote 33554432/33554432 bytes at offset 134217728
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Warning: Image size mismatch!
Images are identical.
0
@@ -28,7 +30,7 @@ wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Content mismatch at offset 0!
1
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
=== IO: pattern 100
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/tests/qemu-iotests/052 b/tests/qemu-iotests/052
index 4b647242d2..842eaced3b 100755
--- a/tests/qemu-iotests/052
+++ b/tests/qemu-iotests/052
@@ -48,6 +48,10 @@ size=128M
_make_test_img $size
echo
+echo "== initializing whole image =="
+$QEMU_IO -c "write -z 0 $size" "$TEST_IMG" | _filter_qemu_io
+
+echo
echo "== reading whole image =="
$QEMU_IO -s -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io
diff --git a/tests/qemu-iotests/052.out b/tests/qemu-iotests/052.out
index 9dab51c0e8..a377d3028d 100644
--- a/tests/qemu-iotests/052.out
+++ b/tests/qemu-iotests/052.out
@@ -1,6 +1,10 @@
QA output created by 052
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
+== initializing whole image ==
+wrote 134217728/134217728 bytes at offset 0
+128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
== reading whole image ==
read 134217728/134217728 bytes at offset 0
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
index a03732e19c..a431b7f305 100644
--- a/tests/qemu-iotests/061.out
+++ b/tests/qemu-iotests/061.out
@@ -58,9 +58,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
- exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
else
- exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
fi )
magic 0x514649fb
version 3
@@ -220,9 +220,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
- exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
else
- exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
fi )
magic 0x514649fb
version 3
diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
index 2b40eadae3..8c6851e792 100644
--- a/tests/qemu-iotests/071.out
+++ b/tests/qemu-iotests/071.out
@@ -30,14 +30,10 @@ blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0
=== Testing blkdebug through filename ===
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
read failed: Input/output error
=== Testing blkdebug through file blockref ===
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
read failed: Input/output error
=== Testing blkdebug on existing block device ===
@@ -51,8 +47,6 @@ read failed: Input/output error
{"return": ""}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
-QEMU_PROG: Failed to flush the L2 table cache: Input/output error
-QEMU_PROG: Failed to flush the refcount block cache: Input/output error
=== Testing blkverify on existing block device ===
@@ -92,7 +86,5 @@ read failed: Input/output error
{"return": ""}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
-QEMU_PROG: Failed to flush the L2 table cache: Input/output error
-QEMU_PROG: Failed to flush the refcount block cache: Input/output error
*** done
diff --git a/tests/qemu-iotests/077 b/tests/qemu-iotests/077
index 4dc680b7fc..d2d2a2d687 100755
--- a/tests/qemu-iotests/077
+++ b/tests/qemu-iotests/077
@@ -60,7 +60,7 @@ EOF
# Sequential RMW requests on the same physical sector
off=0x1000
-for ev in "head" "after_head" "tail" "after_tail"; do
+for ev in "head" "after_head"; do
cat <<EOF
break pwritev_rmw_$ev A
aio_write -P 10 $((off + 0x200)) 0x200
@@ -211,16 +211,6 @@ function verify_io()
echo read -P 11 0x2400 0x200
echo read -P 0 0x2600 0xa00
- echo read -P 0 0x3000 0x200
- echo read -P 10 0x3200 0x200
- echo read -P 11 0x3400 0x200
- echo read -P 0 0x3600 0xa00
-
- echo read -P 0 0x4000 0x200
- echo read -P 10 0x4200 0x200
- echo read -P 11 0x4400 0x200
- echo read -P 0 0x4600 0xa00
-
# Chained dependencies
echo read -P 10 0x5000 0x200
echo read -P 11 0x5200 0x200
diff --git a/tests/qemu-iotests/077.out b/tests/qemu-iotests/077.out
index eab14ae2e1..16f951fd3d 100644
--- a/tests/qemu-iotests/077.out
+++ b/tests/qemu-iotests/077.out
@@ -19,16 +19,6 @@ wrote XXX/XXX bytes at offset XXX
XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote XXX/XXX bytes at offset XXX
XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-blkdebug: Resuming request 'A'
-wrote XXX/XXX bytes at offset XXX
-XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-wrote XXX/XXX bytes at offset XXX
-XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-blkdebug: Resuming request 'A'
-wrote XXX/XXX bytes at offset XXX
-XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-wrote XXX/XXX bytes at offset XXX
-XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote XXX/XXX bytes at offset XXX
XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote XXX/XXX bytes at offset XXX
@@ -114,22 +104,6 @@ read 512/512 bytes at offset 9216
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 2560/2560 bytes at offset 9728
2.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 512/512 bytes at offset 12288
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 512/512 bytes at offset 12800
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 512/512 bytes at offset 13312
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 2560/2560 bytes at offset 13824
-2.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 512/512 bytes at offset 16384
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 512/512 bytes at offset 16896
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 512/512 bytes at offset 17408
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 2560/2560 bytes at offset 17920
-2.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 512/512 bytes at offset 20480
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 512/512 bytes at offset 20992
diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083
index bc724ae058..bff9360048 100755
--- a/tests/qemu-iotests/083
+++ b/tests/qemu-iotests/083
@@ -43,7 +43,7 @@ choose_tcp_port() {
wait_for_tcp_port() {
while ! (netstat --tcp --listening --numeric | \
- grep "$1.*0\\.0\\.0\\.0:\\*.*LISTEN") 2>&1 >/dev/null; do
+ grep "$1.*0\\.0\\.0\\.0:\\*.*LISTEN") >/dev/null 2>&1; do
sleep 0.1
done
}
@@ -70,7 +70,7 @@ EOF
nbd_url="nbd:127.0.0.1:$port:exportname=foo"
fi
- $PYTHON nbd-fault-injector.py $extra_args "127.0.0.1:$port" "$TEST_DIR/nbd-fault-injector.conf" 2>&1 >/dev/null &
+ $PYTHON nbd-fault-injector.py $extra_args "127.0.0.1:$port" "$TEST_DIR/nbd-fault-injector.conf" >/dev/null 2>&1 &
wait_for_tcp_port "127\\.0\\.0\\.1:$port"
$QEMU_IO -c "read 0 512" "$nbd_url" 2>&1 | _filter_qemu_io | _filter_nbd
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
index 055c553cdb..a95c4b0be8 100644
--- a/tests/qemu-iotests/087.out
+++ b/tests/qemu-iotests/087.out
@@ -42,22 +42,14 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
Testing: -S
QMP_VERSION
{"return": {}}
-IMGFMT built-in AES encryption is deprecated
-Support for it will be removed in a future release.
-You can use 'qemu-img convert' to switch to an
-unencrypted IMGFMT image, or a LUKS raw image.
-{"error": {"class": "GenericError", "desc": "blockdev-add doesn't support encrypted devices"}}
+{"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
Testing:
QMP_VERSION
{"return": {}}
-IMGFMT built-in AES encryption is deprecated
-Support for it will be removed in a future release.
-You can use 'qemu-img convert' to switch to an
-unencrypted IMGFMT image, or a LUKS raw image.
-{"error": {"class": "GenericError", "desc": "Guest must be stopped for opening of encrypted image"}}
+{"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out
index 5b541a340c..18f5fdda7a 100644
--- a/tests/qemu-iotests/089.out
+++ b/tests/qemu-iotests/089.out
@@ -24,8 +24,6 @@ read 512/512 bytes at offset 0
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 512/512 bytes at offset 229376
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Failed to flush the L2 table cache: Input/output error
-Failed to flush the refcount block cache: Input/output error
read failed: Input/output error
=== Testing qemu-img info output ===
diff --git a/tests/qemu-iotests/093 b/tests/qemu-iotests/093
index ce8e13cb49..ffcb271b36 100755
--- a/tests/qemu-iotests/093
+++ b/tests/qemu-iotests/093
@@ -184,5 +184,103 @@ class ThrottleTestCase(iotests.QMPTestCase):
class ThrottleTestCoroutine(ThrottleTestCase):
test_img = "null-co://"
+class ThrottleTestGroupNames(iotests.QMPTestCase):
+ test_img = "null-aio://"
+ max_drives = 3
+
+ def setUp(self):
+ self.vm = iotests.VM()
+ for i in range(0, self.max_drives):
+ self.vm.add_drive(self.test_img, "throttling.iops-total=100")
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+
+ def set_io_throttle(self, device, params):
+ params["device"] = device
+ result = self.vm.qmp("block_set_io_throttle", conv_keys=False, **params)
+ self.assert_qmp(result, 'return', {})
+
+ def verify_name(self, device, name):
+ result = self.vm.qmp("query-block")
+ for r in result["return"]:
+ if r["device"] == device:
+ info = r["inserted"]
+ if name:
+ self.assertEqual(info["group"], name)
+ else:
+ self.assertFalse(info.has_key('group'))
+ return
+
+ raise Exception("No group information found for '%s'" % device)
+
+ def test_group_naming(self):
+ params = {"bps": 0,
+ "bps_rd": 0,
+ "bps_wr": 0,
+ "iops": 0,
+ "iops_rd": 0,
+ "iops_wr": 0}
+
+ # Check the drives added using the command line.
+ # The default throttling group name is the device name.
+ for i in range(self.max_drives):
+ devname = "drive%d" % i
+ self.verify_name(devname, devname)
+
+ # Clear throttling settings => the group name is gone.
+ for i in range(self.max_drives):
+ devname = "drive%d" % i
+ self.set_io_throttle(devname, params)
+ self.verify_name(devname, None)
+
+ # Set throttling settings using block_set_io_throttle and
+ # check the default group names.
+ params["iops"] = 10
+ for i in range(self.max_drives):
+ devname = "drive%d" % i
+ self.set_io_throttle(devname, params)
+ self.verify_name(devname, devname)
+
+ # Set a custom group name for each device
+ for i in range(3):
+ devname = "drive%d" % i
+ groupname = "group%d" % i
+ params['group'] = groupname
+ self.set_io_throttle(devname, params)
+ self.verify_name(devname, groupname)
+
+ # Put drive0 in group1 and check that all other devices remain
+ # unchanged
+ params['group'] = 'group1'
+ self.set_io_throttle('drive0', params)
+ self.verify_name('drive0', 'group1')
+ for i in range(1, self.max_drives):
+ devname = "drive%d" % i
+ groupname = "group%d" % i
+ self.verify_name(devname, groupname)
+
+ # Put drive0 in group2 and check that all other devices remain
+ # unchanged
+ params['group'] = 'group2'
+ self.set_io_throttle('drive0', params)
+ self.verify_name('drive0', 'group2')
+ for i in range(1, self.max_drives):
+ devname = "drive%d" % i
+ groupname = "group%d" % i
+ self.verify_name(devname, groupname)
+
+ # Clear throttling settings from drive0 check that all other
+ # devices remain unchanged
+ params["iops"] = 0
+ self.set_io_throttle('drive0', params)
+ self.verify_name('drive0', None)
+ for i in range(1, self.max_drives):
+ devname = "drive%d" % i
+ groupname = "group%d" % i
+ self.verify_name(devname, groupname)
+
+
if __name__ == '__main__':
iotests.main(supported_fmts=["raw"])
diff --git a/tests/qemu-iotests/093.out b/tests/qemu-iotests/093.out
index 89968f35d7..914e3737bd 100644
--- a/tests/qemu-iotests/093.out
+++ b/tests/qemu-iotests/093.out
@@ -1,5 +1,5 @@
-....
+.....
----------------------------------------------------------------------
-Ran 4 tests
+Ran 5 tests
OK
diff --git a/tests/qemu-iotests/095 b/tests/qemu-iotests/095
index dad04b9ac9..030adb22e1 100755
--- a/tests/qemu-iotests/095
+++ b/tests/qemu-iotests/095
@@ -74,6 +74,8 @@ _send_qemu_cmd $h "{ 'execute': 'block-commit',
'arguments': { 'device': 'test',
'top': '"${TEST_IMG}.snp1"' } }" "BLOCK_JOB_COMPLETED"
+_cleanup_qemu
+
echo
echo "=== Base image info after commit and resize ==="
TEST_IMG="${TEST_IMG}.base" _img_info | _filter_img_info
diff --git a/tests/qemu-iotests/096 b/tests/qemu-iotests/096
index e34204b8ff..aeeb3753cf 100644
--- a/tests/qemu-iotests/096
+++ b/tests/qemu-iotests/096
@@ -45,8 +45,9 @@ class TestLiveSnapshot(iotests.QMPTestCase):
os.remove(self.target_img)
def checkConfig(self, active_layer):
- result = self.vm.qmp('query-named-block-nodes')
+ result = self.vm.qmp('query-block')
for r in result['return']:
+ r = r['inserted']
if r['node-name'] == active_layer:
self.assertEqual(r['group'], self.group)
self.assertEqual(r['iops'], self.iops)
diff --git a/tests/qemu-iotests/100 b/tests/qemu-iotests/100
deleted file mode 100755
index 5b2fb33330..0000000000
--- a/tests/qemu-iotests/100
+++ /dev/null
@@ -1,145 +0,0 @@
-#!/bin/bash
-#
-# Test simple read/write using plain bdrv_read/bdrv_write
-#
-# Copyright (C) 2014 Red Hat, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-# creator
-owner=stefanha@redhat.com
-
-seq=`basename $0`
-echo "QA output created by $seq"
-
-here=`pwd`
-status=1 # failure is the default!
-
-_cleanup()
-{
- _cleanup_test_img
-}
-trap "_cleanup; exit \$status" 0 1 2 3 15
-
-# get standard environment, filters and checks
-. ./common.rc
-. ./common.filter
-
-_supported_fmt generic
-_supported_proto generic
-_supported_os Linux
-
-
-size=128M
-
-echo
-echo "== Single request =="
-_make_test_img $size
-$QEMU_IO -c "multiwrite 0 4k" "$TEST_IMG" | _filter_qemu_io
-
-echo
-echo "== verify pattern =="
-$QEMU_IO -c "read -P 0xcd 0 4k" "$TEST_IMG" | _filter_qemu_io
-$QEMU_IO -c "read -P 0 4k 4k" "$TEST_IMG" | _filter_qemu_io
-
-_cleanup_test_img
-
-echo
-echo "== Sequential requests =="
-_make_test_img $size
-$QEMU_IO -c "multiwrite 0 4k ; 4k 4k" "$TEST_IMG" | _filter_qemu_io
-
-echo
-echo "== verify pattern =="
-$QEMU_IO -c "read -P 0xcd 0 4k" "$TEST_IMG" | _filter_qemu_io
-$QEMU_IO -c "read -P 0xce 4k 4k" "$TEST_IMG" | _filter_qemu_io
-$QEMU_IO -c "read -P 0 8k 4k" "$TEST_IMG" | _filter_qemu_io
-
-_cleanup_test_img
-
-echo
-echo "== Superset overlapping requests =="
-_make_test_img $size
-$QEMU_IO -c "multiwrite 0 4k ; 1k 2k" "$TEST_IMG" | _filter_qemu_io
-
-echo
-echo "== verify pattern =="
-# Order of overlapping in-flight requests is not guaranteed so we cannot verify
-# [1k, 3k) since it could have either pattern 0xcd or 0xce.
-$QEMU_IO -c "read -P 0xcd 0 1k" "$TEST_IMG" | _filter_qemu_io
-$QEMU_IO -c "read -P 0xcd 3k 1k" "$TEST_IMG" | _filter_qemu_io
-$QEMU_IO -c "read -P 0 4k 4k" "$TEST_IMG" | _filter_qemu_io
-
-_cleanup_test_img
-
-echo
-echo "== Subset overlapping requests =="
-_make_test_img $size
-$QEMU_IO -c "multiwrite 1k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io
-
-echo
-echo "== verify pattern =="
-# Order of overlapping in-flight requests is not guaranteed so we cannot verify
-# [1k, 3k) since it could have either pattern 0xcd or 0xce.
-$QEMU_IO -c "read -P 0xce 0 1k" "$TEST_IMG" | _filter_qemu_io
-$QEMU_IO -c "read -P 0xce 3k 1k" "$TEST_IMG" | _filter_qemu_io
-$QEMU_IO -c "read -P 0 4k 4k" "$TEST_IMG" | _filter_qemu_io
-
-_cleanup_test_img
-
-echo
-echo "== Head overlapping requests =="
-_make_test_img $size
-$QEMU_IO -c "multiwrite 0k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io
-
-echo
-echo "== verify pattern =="
-# Order of overlapping in-flight requests is not guaranteed so we cannot verify
-# [0k, 2k) since it could have either pattern 0xcd or 0xce.
-$QEMU_IO -c "read -P 0xce 2k 2k" "$TEST_IMG" | _filter_qemu_io
-$QEMU_IO -c "read -P 0 4k 4k" "$TEST_IMG" | _filter_qemu_io
-
-_cleanup_test_img
-
-echo
-echo "== Tail overlapping requests =="
-_make_test_img $size
-$QEMU_IO -c "multiwrite 2k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io
-
-echo
-echo "== verify pattern =="
-# Order of overlapping in-flight requests is not guaranteed so we cannot verify
-# [2k, 4k) since it could have either pattern 0xcd or 0xce.
-$QEMU_IO -c "read -P 0xce 0k 2k" "$TEST_IMG" | _filter_qemu_io
-$QEMU_IO -c "read -P 0 4k 4k" "$TEST_IMG" | _filter_qemu_io
-
-_cleanup_test_img
-
-echo
-echo "== Disjoint requests =="
-_make_test_img $size
-$QEMU_IO -c "multiwrite 0 4k ; 64k 4k" "$TEST_IMG" | _filter_qemu_io
-
-echo
-echo "== verify pattern =="
-$QEMU_IO -c "read -P 0xcd 0 4k" "$TEST_IMG" | _filter_qemu_io
-$QEMU_IO -c "read -P 0 4k 60k" "$TEST_IMG" | _filter_qemu_io
-$QEMU_IO -c "read -P 0xce 64k 4k" "$TEST_IMG" | _filter_qemu_io
-$QEMU_IO -c "read -P 0 68k 4k" "$TEST_IMG" | _filter_qemu_io
-
-# success, all done
-echo "*** done"
-rm -f $seq.full
-status=0
diff --git a/tests/qemu-iotests/100.out b/tests/qemu-iotests/100.out
deleted file mode 100644
index 05649038d9..0000000000
--- a/tests/qemu-iotests/100.out
+++ /dev/null
@@ -1,89 +0,0 @@
-QA output created by 100
-
-== Single request ==
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-wrote 4096/4096 bytes at offset 0
-4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-== verify pattern ==
-read 4096/4096 bytes at offset 0
-4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 4096/4096 bytes at offset 4096
-4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-== Sequential requests ==
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-wrote 8192/8192 bytes at offset 0
-8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-== verify pattern ==
-read 4096/4096 bytes at offset 0
-4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 4096/4096 bytes at offset 4096
-4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 4096/4096 bytes at offset 8192
-4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-== Superset overlapping requests ==
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-wrote 6144/6144 bytes at offset 0
-6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-== verify pattern ==
-read 1024/1024 bytes at offset 0
-1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 1024/1024 bytes at offset 3072
-1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 4096/4096 bytes at offset 4096
-4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-== Subset overlapping requests ==
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-wrote 6144/6144 bytes at offset 1024
-6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-== verify pattern ==
-read 1024/1024 bytes at offset 0
-1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 1024/1024 bytes at offset 3072
-1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 4096/4096 bytes at offset 4096
-4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-== Head overlapping requests ==
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-wrote 6144/6144 bytes at offset 0
-6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-== verify pattern ==
-read 2048/2048 bytes at offset 2048
-2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 4096/4096 bytes at offset 4096
-4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-== Tail overlapping requests ==
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-wrote 6144/6144 bytes at offset 2048
-6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-== verify pattern ==
-read 2048/2048 bytes at offset 0
-2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 4096/4096 bytes at offset 4096
-4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-== Disjoint requests ==
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-wrote 8192/8192 bytes at offset 0
-8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-== verify pattern ==
-read 4096/4096 bytes at offset 0
-4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 61440/61440 bytes at offset 4096
-60 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 4096/4096 bytes at offset 65536
-4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read 4096/4096 bytes at offset 69632
-4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-*** done
diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
index f980b0c9e5..280ed27aa9 100755
--- a/tests/qemu-iotests/109
+++ b/tests/qemu-iotests/109
@@ -100,12 +100,10 @@ for sample_img in empty.bochs iotest-dirtylog-10G-4M.vhdx parallels-v1 \
_make_test_img 64M
bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src"
- run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR"
+ run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" | _filter_block_job_offset
$QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io
run_qemu "$TEST_IMG" "$TEST_IMG.src" "'format': 'raw'," "BLOCK_JOB_READY"
- # qemu-img compare can't handle unaligned file sizes
- $QEMU_IMG resize -f raw "$TEST_IMG.src" +0
$QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src"
done
diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out
index 38bc073a37..e5d70d75f1 100644
--- a/tests/qemu-iotests/109.out
+++ b/tests/qemu-iotests/109.out
@@ -135,7 +135,7 @@ Automatically detecting the format is dangerous for raw images, write operations
Specify the 'raw' format explicitly to remove the restrictions.
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
{"return": []}
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -143,7 +143,6 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2560, "offset": 2560, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
-Image resized.
Warning: Image size mismatch!
Images are identical.
@@ -156,7 +155,7 @@ Automatically detecting the format is dangerous for raw images, write operations
Specify the 'raw' format explicitly to remove the restrictions.
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
{"return": []}
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -164,7 +163,6 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}}
{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 31457280, "offset": 31457280, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
-Image resized.
Warning: Image size mismatch!
Images are identical.
@@ -177,7 +175,7 @@ Automatically detecting the format is dangerous for raw images, write operations
Specify the 'raw' format explicitly to remove the restrictions.
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
{"return": []}
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -185,7 +183,6 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 327680, "offset": 327680, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
-Image resized.
Warning: Image size mismatch!
Images are identical.
@@ -198,7 +195,7 @@ Automatically detecting the format is dangerous for raw images, write operations
Specify the 'raw' format explicitly to remove the restrictions.
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
{"return": []}
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -206,7 +203,6 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2048, "offset": 2048, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
-Image resized.
Warning: Image size mismatch!
Images are identical.
diff --git a/tests/qemu-iotests/136 b/tests/qemu-iotests/136
index e8c6937fc9..635b977552 100644
--- a/tests/qemu-iotests/136
+++ b/tests/qemu-iotests/136
@@ -226,18 +226,11 @@ sector = "%d"
highest_offset = wr_ops * wr_size
- # Two types of invalid operations: unaligned length and unaligned offset
- for i in range(invalid_rd_ops / 2):
- ops.append("aio_read 0 511")
+ for i in range(invalid_rd_ops):
+ ops.append("aio_read -i 0 512")
- for i in range(invalid_rd_ops / 2, invalid_rd_ops):
- ops.append("aio_read 13 512")
-
- for i in range(invalid_wr_ops / 2):
- ops.append("aio_write 0 511")
-
- for i in range(invalid_wr_ops / 2, invalid_wr_ops):
- ops.append("aio_write 13 512")
+ for i in range(invalid_wr_ops):
+ ops.append("aio_write -i 0 512")
for i in range(failed_rd_ops):
ops.append("aio_read %d 512" % bad_offset)
@@ -248,14 +241,6 @@ sector = "%d"
if failed_wr_ops > 0:
highest_offset = max(highest_offset, bad_offset + 512)
- for i in range(wr_merged):
- first = i * wr_size * 2
- second = first + wr_size
- ops.append("multiwrite %d %d ; %d %d" %
- (first, wr_size, second, wr_size))
-
- highest_offset = max(highest_offset, wr_merged * wr_size * 2)
-
# Now perform all operations
for op in ops:
self.vm.hmp_qemu_io("drive0", op)
@@ -309,19 +294,15 @@ sector = "%d"
def test_flush(self):
self.do_test_stats(flush_ops = 8)
- def test_merged(self):
- for i in range(5):
- self.do_test_stats(wr_merged = i * 3)
-
def test_all(self):
# rd_size, rd_ops, wr_size, wr_ops, flush_ops
# invalid_rd_ops, invalid_wr_ops,
# failed_rd_ops, failed_wr_ops
# wr_merged
- test_values = [[512, 1, 512, 1, 1, 4, 7, 5, 2, 1],
- [65536, 1, 2048, 12, 7, 7, 5, 2, 5, 5],
- [32768, 9, 8192, 1, 4, 3, 2, 4, 6, 4],
- [16384, 11, 3584, 16, 9, 8, 6, 7, 3, 4]]
+ test_values = [[512, 1, 512, 1, 1, 4, 7, 5, 2, 0],
+ [65536, 1, 2048, 12, 7, 7, 5, 2, 5, 0],
+ [32768, 9, 8192, 1, 4, 3, 2, 4, 6, 0],
+ [16384, 11, 3584, 16, 9, 8, 6, 7, 3, 0]]
for i in test_values:
self.do_test_stats(*i)
diff --git a/tests/qemu-iotests/136.out b/tests/qemu-iotests/136.out
index 0a5e9583a4..cfa5c0d0e6 100644
--- a/tests/qemu-iotests/136.out
+++ b/tests/qemu-iotests/136.out
@@ -1,5 +1,5 @@
-........................................
+...................................
----------------------------------------------------------------------
-Ran 40 tests
+Ran 35 tests
OK
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
index 88c702cf77..c0e753483b 100644
--- a/tests/qemu-iotests/137.out
+++ b/tests/qemu-iotests/137.out
@@ -32,9 +32,9 @@ Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of t
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
- exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
else
- exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+ exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@";
fi )
incompatible_features 0x0
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
index adceac1817..eaf1e603ed 100644
--- a/tests/qemu-iotests/141.out
+++ b/tests/qemu-iotests/141.out
@@ -18,8 +18,8 @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
{"return": {}}
Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
+{"return": {}}
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
@@ -28,8 +28,8 @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
=== Testing active block-commit ===
{"return": {}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+{"return": {}}
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out
index 410d74180a..387855c378 100644
--- a/tests/qemu-iotests/144.out
+++ b/tests/qemu-iotests/144.out
@@ -12,9 +12,9 @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/
=== Performing block-commit on active layer ===
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
{"return": {}}
+{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
=== Performing Live Snapshot 2 ===
diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149
index 52e23d2946..84072513db 100755
--- a/tests/qemu-iotests/149
+++ b/tests/qemu-iotests/149
@@ -153,6 +153,8 @@ def cryptsetup_format(config):
cipher = config.cipher + "-" + config.mode + "-" + config.ivgen
if config.ivgen_hash is not None:
cipher = cipher + ":" + config.ivgen_hash
+ elif config.ivgen == "essiv":
+ cipher = cipher + ":" + "sha256"
args.extend(["--cipher", cipher])
if config.mode == "xts":
args.extend(["--key-size", str(config.keylen * 2)])
@@ -479,6 +481,16 @@ configs = [
"6": "slot6",
"7": "slot7",
}),
+
+ # Check handling of default hash alg (sha256) with essiv
+ LUKSConfig("aes-256-cbc-essiv-auto-sha1",
+ "aes", 256, "cbc", "essiv", None, "sha1"),
+
+ # Check that a useless hash provided for 'plain64' iv gen
+ # is ignored and no error raised
+ LUKSConfig("aes-256-cbc-plain64-sha256-sha1",
+ "aes", 256, "cbc", "plain64", "sha256", "sha1"),
+
]
blacklist = [
diff --git a/tests/qemu-iotests/149.out b/tests/qemu-iotests/149.out
index 287f013012..90b5b55efb 100644
--- a/tests/qemu-iotests/149.out
+++ b/tests/qemu-iotests/149.out
@@ -1878,3 +1878,243 @@ sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain-sha1-pwallslots
# Delete image
unlink TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
+# ================= dm-crypt aes-256-cbc-essiv-auto-sha1 =================
+# Create image
+truncate TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-essiv-auto-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-essiv-auto-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
+
+# ================= qemu-img aes-256-cbc-essiv-auto-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=essiv,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=essiv hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-essiv-auto-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-essiv-auto-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
+
+# ================= dm-crypt aes-256-cbc-plain64-sha256-sha1 =================
+# Create image
+truncate TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain64:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-plain64-sha256-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-plain64-sha256-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
+
+# ================= qemu-img aes-256-cbc-plain64-sha256-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain64 ivgen-hash-alg=sha256 hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-plain64-sha256-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-plain64-sha256-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
+
diff --git a/tests/qemu-iotests/154 b/tests/qemu-iotests/154
new file mode 100755
index 0000000000..7ca7219f08
--- /dev/null
+++ b/tests/qemu-iotests/154
@@ -0,0 +1,305 @@
+#!/bin/bash
+#
+# qcow2 specific bdrv_pwrite_zeroes tests with backing files (complements 034)
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+
+CLUSTER_SIZE=4k
+size=128M
+
+echo
+echo == backing file contains zeros ==
+
+CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size
+_make_test_img -b "$TEST_IMG.base"
+
+# Make sure that the whole cluster is allocated even for partial write_zeroes
+# when the backing file contains zeros
+
+# X = non-zero data sector in backing file
+# - = sector unallocated in whole backing chain
+# 0 = sector touched by write_zeroes request
+
+# 1. Tail unaligned: 00 00 -- --
+# 2. Head unaligned: -- -- 00 00
+# 3. Both unaligned: -- 00 00 --
+# 4. Both, 2 clusters: -- -- -- 00 | 00 -- -- --
+
+$QEMU_IO -c "write -z 0 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 10k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 17k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 27k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
+
+echo
+echo == backing file contains non-zero data before write_zeroes ==
+
+CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size
+_make_test_img -b "$TEST_IMG.base"
+
+# Single cluster; non-zero data at the cluster start
+# ... | XX -- 00 -- | ...
+$QEMU_IO -c "write -P 0x11 32k 1k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 34k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 32k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 33k 3k" "$TEST_IMG" | _filter_qemu_io
+
+# Single cluster; non-zero data exists, but not at the cluster start
+# ... | -- XX 00 -- | ...
+$QEMU_IO -c "write -P 0x11 65k 1k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 66k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 65k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 64k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 66k 2k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
+
+echo
+echo == backing file contains non-zero data after write_zeroes ==
+
+CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size
+_make_test_img -b "$TEST_IMG.base"
+
+# Single cluster; non-zero data directly after request
+# ... | -- 00 XX -- | ...
+$QEMU_IO -c "write -P 0x11 34k 1k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 33k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 32k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 34k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 35k 1k" "$TEST_IMG" | _filter_qemu_io
+
+# Single cluster; non-zero data exists, but not directly after request
+# ... | -- 00 -- XX | ...
+$QEMU_IO -c "write -P 0x11 43k 1k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 41k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 43k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 40k 3k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
+
+echo
+echo == write_zeroes covers non-zero data ==
+
+CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size
+_make_test_img -b "$TEST_IMG.base"
+
+# non-zero data at front of request
+# Backing file: -- XX -- --
+# Active layer: -- 00 00 --
+
+$QEMU_IO -c "write -P 0x11 5k 1k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 5k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 4k 4k" "$TEST_IMG" | _filter_qemu_io
+
+# non-zero data at end of request
+# Backing file: -- -- XX --
+# Active layer: -- 00 00 --
+
+$QEMU_IO -c "write -P 0x11 14k 1k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 13k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 12k 4k" "$TEST_IMG" | _filter_qemu_io
+
+# non-zero data matches size of request
+# Backing file: -- XX XX --
+# Active layer: -- 00 00 --
+
+$QEMU_IO -c "write -P 0x11 21k 2k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 21k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 20k 4k" "$TEST_IMG" | _filter_qemu_io
+
+# non-zero data smaller than request
+# Backing file: -- -X X- --
+# Active layer: -- 00 00 --
+
+$QEMU_IO -c "write -P 0x11 30208 1k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 29k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 28k 4k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
+
+echo
+echo == spanning two clusters, non-zero before request ==
+
+CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size
+_make_test_img -b "$TEST_IMG.base"
+
+# Two clusters; non-zero data before request:
+# 1. At cluster start: 32k: XX -- -- 00 | 00 -- -- --
+# 2. Between unallocated space: 48k: -- XX -- 00 | 00 -- -- --
+# 3. Directly before request: 64k: -- -- XX 00 | 00 -- -- --
+
+$QEMU_IO -c "write -P 0x11 32k 1k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 35k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 32k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 33k 7k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "write -P 0x11 49k 1k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 51k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 48k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 49k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 50k 6k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "write -P 0x11 66k 1k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 67k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 64k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 66k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 67k 5k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
+
+echo
+echo == spanning two clusters, non-zero after request ==
+
+CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size
+_make_test_img -b "$TEST_IMG.base"
+
+# Two clusters; non-zero data after request:
+# 1. Directly after request: 32k: -- -- -- 00 | 00 XX -- --
+# 2. Between unallocated space: 48k: -- -- -- 00 | 00 -- XX --
+# 3. At cluster end: 64k: -- -- -- 00 | 00 -- -- XX
+
+$QEMU_IO -c "write -P 0x11 37k 1k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 35k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 32k 5k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 37k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 38k 2k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "write -P 0x11 54k 1k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 51k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 48k 6k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 54k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 55k 1k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "write -P 0x11 71k 1k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 67k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 64k 7k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 71k 1k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
+
+echo
+echo == spanning two clusters, partially overwriting backing file ==
+
+CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size
+_make_test_img -b "$TEST_IMG.base"
+
+# Backing file: -- -- XX XX | XX XX -- --
+# Active layer: -- -- XX 00 | 00 XX -- --
+
+$QEMU_IO -c "write -P 0x11 2k 4k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 3k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 0k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 2k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 3k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 5k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 6k 2k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
+
+echo
+echo == spanning multiple clusters, non-zero in first cluster ==
+
+CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size
+_make_test_img -b "$TEST_IMG.base"
+
+# Backing file: 64k: XX XX -- -- | -- -- -- -- | -- -- -- --
+# Active layer: 64k: XX XX 00 00 | 00 00 00 00 | 00 -- -- --
+
+$QEMU_IO -c "write -P 0x11 64k 2k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 66k 7k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 64k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 66k 10k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
+
+echo
+echo == spanning multiple clusters, non-zero in intermediate cluster ==
+
+CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size
+_make_test_img -b "$TEST_IMG.base"
+
+# Backing file: 64k: -- -- -- -- | -- XX XX -- | -- -- -- --
+# Active layer: 64k: -- -- 00 00 | 00 00 00 00 | 00 -- -- --
+
+$QEMU_IO -c "write -P 0x11 69k 2k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 66k 7k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 64k 12k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
+
+echo
+echo == spanning multiple clusters, non-zero in final cluster ==
+
+CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size
+_make_test_img -b "$TEST_IMG.base"
+
+# Backing file: 64k: -- -- -- -- | -- -- -- -- | -- -- XX XX
+# Active layer: 64k: -- -- 00 00 | 00 00 00 00 | 00 -- XX XX
+
+$QEMU_IO -c "write -P 0x11 74k 2k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 66k 7k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 64k 10k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 74k 2k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
+
+echo
+echo == spanning multiple clusters, partially overwriting backing file ==
+
+CLUSTER_SIZE=512 TEST_IMG="$TEST_IMG.base" _make_test_img $size
+_make_test_img -b "$TEST_IMG.base"
+
+# Backing file: 64k: -- XX XX XX | XX XX XX XX | XX XX XX --
+# Active layer: 64k: -- XX 00 00 | 00 00 00 00 | 00 XX XX --
+
+$QEMU_IO -c "write -P 0x11 65k 10k" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 66k 7k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 64k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 65k 1k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 66k 7k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0x11 73k 2k" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0 75k 1k" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/154.out b/tests/qemu-iotests/154.out
new file mode 100644
index 0000000000..da9eabdda8
--- /dev/null
+++ b/tests/qemu-iotests/154.out
@@ -0,0 +1,285 @@
+QA output created by 154
+
+== backing file contains zeros ==
+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
+wrote 2048/2048 bytes at offset 0
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 10240
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 17408
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 27648
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+[{ "start": 0, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 4096, "length": 4096, "depth": 1, "zero": true, "data": false},
+{ "start": 8192, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 12288, "length": 4096, "depth": 1, "zero": true, "data": false},
+{ "start": 16384, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 20480, "length": 4096, "depth": 1, "zero": true, "data": false},
+{ "start": 24576, "length": 8192, "depth": 0, "zero": true, "data": false},
+{ "start": 32768, "length": 134184960, "depth": 1, "zero": true, "data": false}]
+
+== backing file contains non-zero data before write_zeroes ==
+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
+wrote 1024/1024 bytes at offset 32768
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 34816
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 32768
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 3072/3072 bytes at offset 33792
+3 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 66560
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 67584
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 66560
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 65536
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 2048/2048 bytes at offset 67584
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+[{ "start": 0, "length": 32768, "depth": 1, "zero": true, "data": false},
+{ "start": 32768, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
+{ "start": 36864, "length": 28672, "depth": 1, "zero": true, "data": false},
+{ "start": 65536, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 24576},
+{ "start": 69632, "length": 134148096, "depth": 1, "zero": true, "data": false}]
+
+== backing file contains non-zero data after write_zeroes ==
+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
+wrote 1024/1024 bytes at offset 34816
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 33792
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 2048/2048 bytes at offset 32768
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 34816
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 35840
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 44032
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 41984
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 44032
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 3072/3072 bytes at offset 40960
+3 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+[{ "start": 0, "length": 32768, "depth": 1, "zero": true, "data": false},
+{ "start": 32768, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
+{ "start": 36864, "length": 4096, "depth": 1, "zero": true, "data": false},
+{ "start": 40960, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 24576},
+{ "start": 45056, "length": 134172672, "depth": 1, "zero": true, "data": false}]
+
+== write_zeroes covers non-zero data ==
+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
+wrote 1024/1024 bytes at offset 5120
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 5120
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 4096/4096 bytes at offset 4096
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 14336
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 13312
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 4096/4096 bytes at offset 12288
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 21504
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 21504
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 4096/4096 bytes at offset 20480
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 30208
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 29696
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 4096/4096 bytes at offset 28672
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+[{ "start": 0, "length": 4096, "depth": 1, "zero": true, "data": false},
+{ "start": 4096, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 8192, "length": 4096, "depth": 1, "zero": true, "data": false},
+{ "start": 12288, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 16384, "length": 4096, "depth": 1, "zero": true, "data": false},
+{ "start": 20480, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 24576, "length": 4096, "depth": 1, "zero": true, "data": false},
+{ "start": 28672, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 32768, "length": 134184960, "depth": 1, "zero": true, "data": false}]
+
+== spanning two clusters, non-zero before request ==
+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
+wrote 1024/1024 bytes at offset 32768
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 35840
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 32768
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 7168/7168 bytes at offset 33792
+7 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 50176
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 52224
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 49152
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 50176
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 6144/6144 bytes at offset 51200
+6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 67584
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 68608
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 2048/2048 bytes at offset 65536
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 67584
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 5120/5120 bytes at offset 68608
+5 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+[{ "start": 0, "length": 32768, "depth": 1, "zero": true, "data": false},
+{ "start": 32768, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
+{ "start": 36864, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 40960, "length": 8192, "depth": 1, "zero": true, "data": false},
+{ "start": 49152, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 24576},
+{ "start": 53248, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 57344, "length": 8192, "depth": 1, "zero": true, "data": false},
+{ "start": 65536, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 28672},
+{ "start": 69632, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 73728, "length": 134144000, "depth": 1, "zero": true, "data": false}]
+
+== spanning two clusters, non-zero after request ==
+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
+wrote 1024/1024 bytes at offset 37888
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 35840
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 5120/5120 bytes at offset 32768
+5 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 37888
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 2048/2048 bytes at offset 38912
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 55296
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 52224
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 6144/6144 bytes at offset 49152
+6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 55296
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 56320
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 72704
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 68608
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 7168/7168 bytes at offset 65536
+7 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 72704
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+[{ "start": 0, "length": 32768, "depth": 1, "zero": true, "data": false},
+{ "start": 32768, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 36864, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
+{ "start": 40960, "length": 8192, "depth": 1, "zero": true, "data": false},
+{ "start": 49152, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 53248, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 24576},
+{ "start": 57344, "length": 8192, "depth": 1, "zero": true, "data": false},
+{ "start": 65536, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 69632, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 28672},
+{ "start": 73728, "length": 134144000, "depth": 1, "zero": true, "data": false}]
+
+== spanning two clusters, partially overwriting backing file ==
+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
+wrote 4096/4096 bytes at offset 2048
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 2048/2048 bytes at offset 3072
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 2048/2048 bytes at offset 0
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 2048
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 2048/2048 bytes at offset 3072
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 5120
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 2048/2048 bytes at offset 6144
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+[{ "start": 0, "length": 8192, "depth": 0, "zero": false, "data": true, "offset": 20480},
+{ "start": 8192, "length": 134209536, "depth": 1, "zero": true, "data": false}]
+
+== spanning multiple clusters, non-zero in first cluster ==
+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
+wrote 2048/2048 bytes at offset 65536
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 7168/7168 bytes at offset 67584
+7 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 2048/2048 bytes at offset 65536
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 10240/10240 bytes at offset 67584
+10 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+[{ "start": 0, "length": 65536, "depth": 1, "zero": true, "data": false},
+{ "start": 65536, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
+{ "start": 69632, "length": 8192, "depth": 0, "zero": true, "data": false},
+{ "start": 77824, "length": 134139904, "depth": 1, "zero": true, "data": false}]
+
+== spanning multiple clusters, non-zero in intermediate cluster ==
+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
+wrote 2048/2048 bytes at offset 70656
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 7168/7168 bytes at offset 67584
+7 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 12288/12288 bytes at offset 65536
+12 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+[{ "start": 0, "length": 65536, "depth": 1, "zero": true, "data": false},
+{ "start": 65536, "length": 12288, "depth": 0, "zero": true, "data": false},
+{ "start": 77824, "length": 134139904, "depth": 1, "zero": true, "data": false}]
+
+== spanning multiple clusters, non-zero in final cluster ==
+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
+wrote 2048/2048 bytes at offset 75776
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 7168/7168 bytes at offset 67584
+7 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 10240/10240 bytes at offset 65536
+10 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 2048/2048 bytes at offset 75776
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+[{ "start": 0, "length": 65536, "depth": 1, "zero": true, "data": false},
+{ "start": 65536, "length": 8192, "depth": 0, "zero": true, "data": false},
+{ "start": 73728, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
+{ "start": 77824, "length": 134139904, "depth": 1, "zero": true, "data": false}]
+
+== spanning multiple clusters, partially overwriting backing file ==
+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
+wrote 10240/10240 bytes at offset 66560
+10 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 7168/7168 bytes at offset 67584
+7 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 65536
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 66560
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 7168/7168 bytes at offset 67584
+7 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 2048/2048 bytes at offset 74752
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 76800
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+[{ "start": 0, "length": 65536, "depth": 1, "zero": true, "data": false},
+{ "start": 65536, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 20480},
+{ "start": 69632, "length": 4096, "depth": 0, "zero": true, "data": false},
+{ "start": 73728, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": 24576},
+{ "start": 77824, "length": 134139904, "depth": 1, "zero": true, "data": false}]
+*** done
diff --git a/tests/qemu-iotests/155 b/tests/qemu-iotests/155
new file mode 100755
index 0000000000..4057b5e2aa
--- /dev/null
+++ b/tests/qemu-iotests/155
@@ -0,0 +1,261 @@
+#!/usr/bin/env python
+#
+# Test whether the backing BDSs are correct after completion of a
+# mirror block job; in "existing" modes (drive-mirror with
+# mode=existing and blockdev-mirror) the backing chain should not be
+# overridden.
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import iotests
+from iotests import qemu_img
+
+back0_img = os.path.join(iotests.test_dir, 'back0.' + iotests.imgfmt)
+back1_img = os.path.join(iotests.test_dir, 'back1.' + iotests.imgfmt)
+back2_img = os.path.join(iotests.test_dir, 'back2.' + iotests.imgfmt)
+source_img = os.path.join(iotests.test_dir, 'source.' + iotests.imgfmt)
+target_img = os.path.join(iotests.test_dir, 'target.' + iotests.imgfmt)
+
+
+# Class variables for controlling its behavior:
+#
+# existing: If True, explicitly create the target image and blockdev-add it
+# target_backing: If existing is True: Use this filename as the backing file
+# of the target image
+# (None: no backing file)
+# target_blockdev_backing: If existing is True: Pass this dict as "backing"
+# for the blockdev-add command
+# (None: do not pass "backing")
+# target_real_backing: If existing is True: The real filename of the backing
+# image during runtime, only makes sense if
+# target_blockdev_backing is not None
+# (None: same as target_backing)
+
+class BaseClass(iotests.QMPTestCase):
+ target_blockdev_backing = None
+ target_real_backing = None
+
+ def setUp(self):
+ qemu_img('create', '-f', iotests.imgfmt, back0_img, '1M')
+ qemu_img('create', '-f', iotests.imgfmt, '-b', back0_img, back1_img)
+ qemu_img('create', '-f', iotests.imgfmt, '-b', back1_img, back2_img)
+ qemu_img('create', '-f', iotests.imgfmt, '-b', back2_img, source_img)
+
+ self.vm = iotests.VM()
+ self.vm.add_drive(None, '', 'none')
+ self.vm.launch()
+
+ # Add the BDS via blockdev-add so it stays around after the mirror block
+ # job has been completed
+ result = self.vm.qmp('blockdev-add',
+ options={'node-name': 'source',
+ 'driver': iotests.imgfmt,
+ 'file': {'driver': 'file',
+ 'filename': source_img}})
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('x-blockdev-insert-medium',
+ device='drive0', node_name='source')
+ self.assert_qmp(result, 'return', {})
+
+ self.assertIntactSourceBackingChain()
+
+ if self.existing:
+ if self.target_backing:
+ qemu_img('create', '-f', iotests.imgfmt,
+ '-b', self.target_backing, target_img, '1M')
+ else:
+ qemu_img('create', '-f', iotests.imgfmt, target_img, '1M')
+
+ if self.cmd == 'blockdev-mirror':
+ options = { 'node-name': 'target',
+ 'driver': iotests.imgfmt,
+ 'file': { 'driver': 'file',
+ 'filename': target_img } }
+ if self.target_blockdev_backing:
+ options['backing'] = self.target_blockdev_backing
+
+ result = self.vm.qmp('blockdev-add', options=options)
+ self.assert_qmp(result, 'return', {})
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(source_img)
+ os.remove(back2_img)
+ os.remove(back1_img)
+ os.remove(back0_img)
+ try:
+ os.remove(target_img)
+ except OSError:
+ pass
+
+ def findBlockNode(self, node_name, id=None):
+ if id:
+ result = self.vm.qmp('query-block')
+ for device in result['return']:
+ if device['device'] == id:
+ if node_name:
+ self.assert_qmp(device, 'inserted/node-name', node_name)
+ return device['inserted']
+ else:
+ result = self.vm.qmp('query-named-block-nodes')
+ for node in result['return']:
+ if node['node-name'] == node_name:
+ return node
+
+ self.fail('Cannot find node %s/%s' % (id, node_name))
+
+ def assertIntactSourceBackingChain(self):
+ node = self.findBlockNode('source')
+
+ self.assert_qmp(node, 'image' + '/backing-image' * 0 + '/filename',
+ source_img)
+ self.assert_qmp(node, 'image' + '/backing-image' * 1 + '/filename',
+ back2_img)
+ self.assert_qmp(node, 'image' + '/backing-image' * 2 + '/filename',
+ back1_img)
+ self.assert_qmp(node, 'image' + '/backing-image' * 3 + '/filename',
+ back0_img)
+ self.assert_qmp_absent(node, 'image' + '/backing-image' * 4)
+
+ def assertCorrectBackingImage(self, node, default_image):
+ if self.existing:
+ if self.target_real_backing:
+ image = self.target_real_backing
+ else:
+ image = self.target_backing
+ else:
+ image = default_image
+
+ if image:
+ self.assert_qmp(node, 'image/backing-image/filename', image)
+ else:
+ self.assert_qmp_absent(node, 'image/backing-image')
+
+
+# Class variables for controlling its behavior:
+#
+# cmd: Mirroring command to execute, either drive-mirror or blockdev-mirror
+
+class MirrorBaseClass(BaseClass):
+ def runMirror(self, sync):
+ if self.cmd == 'blockdev-mirror':
+ result = self.vm.qmp(self.cmd, device='drive0', sync=sync,
+ target='target')
+ else:
+ if self.existing:
+ mode = 'existing'
+ else:
+ mode = 'absolute-paths'
+ result = self.vm.qmp(self.cmd, device='drive0', sync=sync,
+ target=target_img, format=iotests.imgfmt,
+ mode=mode, node_name='target')
+
+ self.assert_qmp(result, 'return', {})
+
+ self.vm.event_wait('BLOCK_JOB_READY')
+
+ result = self.vm.qmp('block-job-complete', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ self.vm.event_wait('BLOCK_JOB_COMPLETED')
+
+ def testFull(self):
+ self.runMirror('full')
+
+ node = self.findBlockNode('target', 'drive0')
+ self.assertCorrectBackingImage(node, None)
+ self.assertIntactSourceBackingChain()
+
+ def testTop(self):
+ self.runMirror('top')
+
+ node = self.findBlockNode('target', 'drive0')
+ self.assertCorrectBackingImage(node, back2_img)
+ self.assertIntactSourceBackingChain()
+
+ def testNone(self):
+ self.runMirror('none')
+
+ node = self.findBlockNode('target', 'drive0')
+ self.assertCorrectBackingImage(node, source_img)
+ self.assertIntactSourceBackingChain()
+
+
+class TestDriveMirrorAbsolutePaths(MirrorBaseClass):
+ cmd = 'drive-mirror'
+ existing = False
+
+class TestDriveMirrorExistingNoBacking(MirrorBaseClass):
+ cmd = 'drive-mirror'
+ existing = True
+ target_backing = None
+
+class TestDriveMirrorExistingBacking(MirrorBaseClass):
+ cmd = 'drive-mirror'
+ existing = True
+ target_backing = 'null-co://'
+
+class TestBlockdevMirrorNoBacking(MirrorBaseClass):
+ cmd = 'blockdev-mirror'
+ existing = True
+ target_backing = None
+
+class TestBlockdevMirrorBacking(MirrorBaseClass):
+ cmd = 'blockdev-mirror'
+ existing = True
+ target_backing = 'null-co://'
+
+class TestBlockdevMirrorForcedBacking(MirrorBaseClass):
+ cmd = 'blockdev-mirror'
+ existing = True
+ target_backing = None
+ target_blockdev_backing = { 'driver': 'null-co' }
+ target_real_backing = 'null-co://'
+
+
+class TestCommit(BaseClass):
+ existing = False
+
+ def testCommit(self):
+ result = self.vm.qmp('block-commit', device='drive0', base=back1_img)
+ self.assert_qmp(result, 'return', {})
+
+ self.vm.event_wait('BLOCK_JOB_READY')
+
+ result = self.vm.qmp('block-job-complete', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ self.vm.event_wait('BLOCK_JOB_COMPLETED')
+
+ node = self.findBlockNode(None, 'drive0')
+ self.assert_qmp(node, 'image' + '/backing-image' * 0 + '/filename',
+ back1_img)
+ self.assert_qmp(node, 'image' + '/backing-image' * 1 + '/filename',
+ back0_img)
+ self.assert_qmp_absent(node, 'image' + '/backing-image' * 2 +
+ '/filename')
+
+ self.assertIntactSourceBackingChain()
+
+
+BaseClass = None
+MirrorBaseClass = None
+
+if __name__ == '__main__':
+ iotests.main(supported_fmts=['qcow2'])
diff --git a/tests/qemu-iotests/155.out b/tests/qemu-iotests/155.out
new file mode 100644
index 0000000000..4176bb9402
--- /dev/null
+++ b/tests/qemu-iotests/155.out
@@ -0,0 +1,5 @@
+...................
+----------------------------------------------------------------------
+Ran 19 tests
+
+OK
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
new file mode 100755
index 0000000000..cc95ff1f98
--- /dev/null
+++ b/tests/qemu-iotests/156
@@ -0,0 +1,174 @@
+#!/bin/bash
+#
+# Tests oVirt-like storage migration:
+# - Create snapshot
+# - Create target image with (not yet existing) target backing chain
+# (i.e. just write the name of a soon-to-be-copied-over backing file into it)
+# - drive-mirror the snapshot to the target with mode=existing and sync=top
+# - In the meantime, copy the original source files to the destination via
+# conventional means (i.e. outside of qemu)
+# - Complete the drive-mirror job
+# - Delete all source images
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1 # failure is the default!
+
+_cleanup()
+{
+ rm -f "$TEST_IMG{,.target}{,.backing,.overlay}"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt qcow2 qed
+_supported_proto generic
+_supported_os Linux
+
+# Create source disk
+TEST_IMG="$TEST_IMG.backing" _make_test_img 1M
+_make_test_img -b "$TEST_IMG.backing" 1M
+
+$QEMU_IO -c 'write -P 1 0 256k' "$TEST_IMG.backing" | _filter_qemu_io
+$QEMU_IO -c 'write -P 2 64k 192k' "$TEST_IMG" | _filter_qemu_io
+
+_launch_qemu -drive if=none,id=source,file="$TEST_IMG"
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'qmp_capabilities' }" \
+ 'return'
+
+# Create snapshot
+TEST_IMG="$TEST_IMG.overlay" _make_test_img -b "$TEST_IMG" 1M
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': { 'device': 'source',
+ 'snapshot-file': '$TEST_IMG.overlay',
+ 'format': '$IMGFMT',
+ 'mode': 'existing' } }" \
+ 'return'
+
+# Write something to the snapshot
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io source \"write -P 3 128k 128k\"' } }" \
+ 'return'
+
+# Create target image
+TEST_IMG="$TEST_IMG.target.overlay" _make_test_img -b "$TEST_IMG.target" 1M
+
+# Mirror snapshot
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'drive-mirror',
+ 'arguments': { 'device': 'source',
+ 'target': '$TEST_IMG.target.overlay',
+ 'mode': 'existing',
+ 'sync': 'top' } }" \
+ 'return'
+
+# Wait for convergence
+_send_qemu_cmd $QEMU_HANDLE \
+ '' \
+ 'BLOCK_JOB_READY'
+
+# Write some more
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io source \"write -P 4 192k 64k\"' } }" \
+ 'return'
+
+# Copy source backing chain to the target before completing the job
+cp "$TEST_IMG.backing" "$TEST_IMG.target.backing"
+cp "$TEST_IMG" "$TEST_IMG.target"
+$QEMU_IMG rebase -u -b "$TEST_IMG.target.backing" "$TEST_IMG.target"
+
+# Complete block job
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'block-job-complete',
+ 'arguments': { 'device': 'source' } }" \
+ ''
+
+_send_qemu_cmd $QEMU_HANDLE \
+ '' \
+ 'BLOCK_JOB_COMPLETED'
+
+# Remove the source images
+rm -f "$TEST_IMG{,.backing,.overlay}"
+
+echo
+
+# Check online disk contents
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io source \"read -P 1 0k 64k\"' } }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io source \"read -P 2 64k 64k\"' } }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io source \"read -P 3 128k 64k\"' } }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line':
+ 'qemu-io source \"read -P 4 192k 64k\"' } }" \
+ 'return'
+
+echo
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'quit' }" \
+ 'return'
+
+wait=1 _cleanup_qemu
+
+echo
+
+# Check offline disk contents
+$QEMU_IO -c 'read -P 1 0k 64k' \
+ -c 'read -P 2 64k 64k' \
+ -c 'read -P 3 128k 64k' \
+ -c 'read -P 4 192k 64k' \
+ "$TEST_IMG.target.overlay" | _filter_qemu_io
+
+echo
+
+# success, all done
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/156.out b/tests/qemu-iotests/156.out
new file mode 100644
index 0000000000..3af82ae540
--- /dev/null
+++ b/tests/qemu-iotests/156.out
@@ -0,0 +1,48 @@
+QA output created by 156
+Formatting 'TEST_DIR/t.IMGFMT.backing', fmt=IMGFMT size=1048576
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.backing
+wrote 262144/262144 bytes at offset 0
+256 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)
+{"return": {}}
+Formatting 'TEST_DIR/t.IMGFMT.overlay', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT
+{"return": {}}
+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
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "source", "len": 131072, "offset": 131072, "speed": 0, "type": "mirror"}}
+wrote 65536/65536 bytes at offset 196608
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": ""}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "source", "len": 196608, "offset": 196608, "speed": 0, "type": "mirror"}}
+
+read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": ""}
+read 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": ""}
+read 65536/65536 bytes at offset 131072
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": ""}
+read 65536/65536 bytes at offset 196608
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": ""}
+
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+
+read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 65536/65536 bytes at offset 131072
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 65536/65536 bytes at offset 196608
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+*** done
diff --git a/tests/qemu-iotests/157 b/tests/qemu-iotests/157
new file mode 100755
index 0000000000..8d939cb747
--- /dev/null
+++ b/tests/qemu-iotests/157
@@ -0,0 +1,89 @@
+#!/bin/bash
+#
+# Test command line configuration of block devices with qdev
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt generic
+_supported_proto file
+_supported_os Linux
+
+function do_run_qemu()
+{
+ echo Testing: "$@"
+ (
+ if ! test -t 0; then
+ while read cmd; do
+ echo $cmd
+ done
+ fi
+ echo quit
+ ) | $QEMU -nodefaults -nographic -monitor stdio -serial none "$@"
+ echo
+}
+
+function run_qemu()
+{
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_imgfmt \
+ | _filter_qemu | _filter_generated_node_ids
+}
+
+
+size=128M
+drive="if=none,file=$TEST_IMG,driver=$IMGFMT"
+
+_make_test_img $size
+
+echo
+echo "=== Setting WCE with qdev and with manually created BB ==="
+echo
+
+# The qdev option takes precedence, but if it isn't given or 'auto', the BB
+# option is used instead.
+
+for cache in "writeback" "writethrough"; do
+ for wce in "" ",write-cache=auto" ",write-cache=on" ",write-cache=off"; do
+ echo "info block" \
+ | run_qemu -drive "$drive,cache=$cache" \
+ -device "virtio-blk,drive=none0$wce" \
+ | grep -e "Testing" -e "Cache mode"
+ done
+done
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/157.out b/tests/qemu-iotests/157.out
new file mode 100644
index 0000000000..77a9c03d2c
--- /dev/null
+++ b/tests/qemu-iotests/157.out
@@ -0,0 +1,22 @@
+QA output created by 157
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
+
+=== Setting WCE with qdev and with manually created BB ===
+
+Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writeback -device virtio-blk,drive=none0
+ Cache mode: writeback
+Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writeback -device virtio-blk,drive=none0,write-cache=auto
+ Cache mode: writeback
+Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writeback -device virtio-blk,drive=none0,write-cache=on
+ Cache mode: writeback
+Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writeback -device virtio-blk,drive=none0,write-cache=off
+ Cache mode: writethrough
+Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writethrough -device virtio-blk,drive=none0
+ Cache mode: writethrough
+Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writethrough -device virtio-blk,drive=none0,write-cache=auto
+ Cache mode: writethrough
+Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writethrough -device virtio-blk,drive=none0,write-cache=on
+ Cache mode: writeback
+Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writethrough -device virtio-blk,drive=none0,write-cache=off
+ Cache mode: writethrough
+*** done
diff --git a/tests/qemu-iotests/162 b/tests/qemu-iotests/162
new file mode 100755
index 0000000000..0b43ea3395
--- /dev/null
+++ b/tests/qemu-iotests/162
@@ -0,0 +1,96 @@
+#!/bin/bash
+#
+# Test case for specifying runtime options of the wrong type to some
+# block drivers
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1 # failure is the default!
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt generic
+_supported_os Linux
+
+echo
+echo '=== NBD ==='
+# NBD expects all of its arguments to be strings
+
+# So this should not crash
+$QEMU_IMG info 'json:{"driver": "nbd", "host": 42}'
+
+# And this should not treat @port as if it had not been specified
+# (We cannot use localhost with an invalid port here, but we need to use a
+# non-existing domain, because otherwise the error message will not contain
+# the port)
+$QEMU_IMG info 'json:{"driver": "nbd", "host": "does.not.exist.example.com", "port": 42}'
+
+# This is a test for NBD's bdrv_refresh_filename() implementation: It expects
+# either host or path to be set, but it must not assume that they are set to
+# strings in the options QDict
+$QEMU_NBD -k "$PWD/42" -f raw null-co:// &
+sleep 0.5
+$QEMU_IMG info 'json:{"driver": "nbd", "path": 42}' | grep '^image'
+rm -f 42
+
+
+echo
+echo '=== SSH ==='
+# SSH expects all of its arguments to be strings, except for @port, which is
+# expected to be an integer
+
+# So "0" should be converted to an integer here (instead of crashing)
+$QEMU_IMG info 'json:{"driver": "ssh", "host": "localhost", "port": "0", "path": "/foo"}'
+# The same, basically (all values for --image-opts are seen as strings in qemu)
+$QEMU_IMG info --image-opts \
+ driver=ssh,host=localhost,port=0,path=/foo
+
+# This, however, should fail because of the wrong type
+$QEMU_IMG info 'json:{"driver": "ssh", "host": "localhost", "port": 0.42, "path": "/foo"}'
+# Not really the same: Here, "0.42" will be passed instead of 0.42, but still,
+# qemu should not try to convert "0.42" to an integer
+$QEMU_IMG info --image-opts \
+ driver=ssh,host=localhost,port=0.42,path=/foo
+
+
+echo
+echo '=== blkdebug ==='
+# blkdebug expects all of its arguments to be strings, but its
+# bdrv_refresh_filename() implementation should not assume that they have been
+# passed as strings in the original options QDict.
+# So this should emit blkdebug:42:null-co:// as the filename:
+touch 42
+$QEMU_IMG info 'json:{"driver": "blkdebug", "config": 42,
+ "image.driver": "null-co"}' \
+ | grep '^image'
+rm -f 42
+
+
+# success, all done
+echo
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/162.out b/tests/qemu-iotests/162.out
new file mode 100644
index 0000000000..9bba72353a
--- /dev/null
+++ b/tests/qemu-iotests/162.out
@@ -0,0 +1,17 @@
+QA output created by 162
+
+=== NBD ===
+qemu-img: Could not open 'json:{"driver": "nbd", "host": 42}': Failed to connect socket: Invalid argument
+qemu-img: Could not open 'json:{"driver": "nbd", "host": "does.not.exist.example.com", "port": 42}': address resolution failed for does.not.exist.example.com:42: Name or service not known
+image: nbd+unix://?socket=42
+
+=== SSH ===
+qemu-img: Could not open 'json:{"driver": "ssh", "host": "localhost", "port": "0", "path": "/foo"}': Failed to connect socket: Connection refused
+qemu-img: Could not open 'driver=ssh,host=localhost,port=0,path=/foo': Failed to connect socket: Connection refused
+qemu-img: Could not open 'json:{"driver": "ssh", "host": "localhost", "port": 0.42, "path": "/foo"}': Parameter 'port' expects a number
+qemu-img: Could not open 'driver=ssh,host=localhost,port=0.42,path=/foo': Parameter 'port' expects a number
+
+=== blkdebug ===
+image: blkdebug:42:null-co://
+
+*** done
diff --git a/tests/qemu-iotests/README b/tests/qemu-iotests/README
index 4ccfdd1cc0..6079b401ae 100644
--- a/tests/qemu-iotests/README
+++ b/tests/qemu-iotests/README
@@ -17,4 +17,5 @@ additional options to test further image formats or I/O methods.
* Feedback and patches
Please send improvements to the test suite, general feedback or just
-reports of failing tests cases to qemu-devel@savannah.nongnu.org.
+reports of failing tests cases to qemu-devel@nongnu.org with a CC:
+to qemu-block@nongnu.org.
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
index 49e1931129..d60ea2ce3c 100644
--- a/tests/qemu-iotests/common
+++ b/tests/qemu-iotests/common
@@ -53,6 +53,8 @@ export QEMU_IO_OPTIONS=""
export CACHEMODE_IS_DEFAULT=true
export QEMU_OPTIONS="-nodefaults"
export VALGRIND_QEMU=
+export IMGKEYSECRET=
+export IMGOPTSSYNTAX=false
for r
do
@@ -207,6 +209,13 @@ testlist options
xpand=false
;;
+ -luks)
+ IMGOPTSSYNTAX=true
+ IMGFMT=luks
+ IMGKEYSECRET=123456
+ xpand=false
+ ;;
+
-qed)
IMGFMT=qed
xpand=false
@@ -399,7 +408,11 @@ BEGIN { for (t='$start'; t<='$end'; t++) printf "%03d\n",t }' \
done
# Set qemu-io cache mode with $CACHEMODE we have
-QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT --cache $CACHEMODE"
+if [ "$IMGOPTSSYNTAX" = "true" ]; then
+ QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --cache $CACHEMODE"
+else
+ QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT --cache $CACHEMODE"
+fi
# Set default options for qemu-img create -o if they were not specified
_set_default_imgopts
diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config
index f824651bac..f6384fbae7 100644
--- a/tests/qemu-iotests/common.config
+++ b/tests/qemu-iotests/common.config
@@ -123,12 +123,19 @@ _qemu_img_wrapper()
_qemu_io_wrapper()
{
local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind
+ local QEMU_IO_ARGS="$QEMU_IO_OPTIONS"
+ if [ "$IMGOPTSSYNTAX" = "true" ]; then
+ QEMU_IO_ARGS="--image-opts $QEMU_IO_ARGS"
+ if [ -n "$IMGKEYSECRET" ]; then
+ QEMU_IO_ARGS="--object secret,id=keysec0,data=$IMGKEYSECRET $QEMU_IO_ARGS"
+ fi
+ fi
local RETVAL
(
if [ "${VALGRIND_QEMU}" == "y" ]; then
- exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"
else
- exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"
+ exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"
fi
)
RETVAL=$?
@@ -154,6 +161,16 @@ export QEMU_IMG=_qemu_img_wrapper
export QEMU_IO=_qemu_io_wrapper
export QEMU_NBD=_qemu_nbd_wrapper
+QEMU_IMG_EXTRA_ARGS=
+if [ "$IMGOPTSSYNTAX" = "true" ]; then
+ QEMU_IMG_EXTRA_ARGS="--image-opts $QEMU_IMG_EXTRA_ARGS"
+ if [ -n "$IMGKEYSECRET" ]; then
+ QEMU_IMG_EXTRA_ARGS="--object secret,id=keysec0,data=$IMGKEYSECRET $QEMU_IMG_EXTRA_ARGS"
+ fi
+fi
+export QEMU_IMG_EXTRA_ARGS
+
+
default_machine=$($QEMU -machine help | sed -n '/(default)/ s/ .*//p')
default_alias_machine=$($QEMU -machine help | \
sed -n "/(alias of $default_machine)/ { s/ .*//p; q; }")
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index 8a6e1b57c1..3ab6e4d764 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -77,6 +77,12 @@ _filter_qmp()
-e ' QMP_VERSION'
}
+# replace block job offset
+_filter_block_job_offset()
+{
+ sed -e 's/, "offset": [0-9]\+,/, "offset": OFFSET,/'
+}
+
# replace driver-specific options in the "Formatting..." line
_filter_img_create()
{
@@ -92,12 +98,14 @@ _filter_img_create()
-e "s# zeroed_grain=\\(on\\|off\\)##g" \
-e "s# subformat='[^']*'##g" \
-e "s# adapter_type='[^']*'##g" \
+ -e "s# hwversion=[^ ]*##g" \
-e "s# lazy_refcounts=\\(on\\|off\\)##g" \
-e "s# block_size=[0-9]\\+##g" \
-e "s# block_state_zero=\\(on\\|off\\)##g" \
-e "s# log_size=[0-9]\\+##g" \
-e "s/archipelago:a/TEST_DIR\//g" \
- -e "s# refcount_bits=[0-9]\\+##g"
+ -e "s# refcount_bits=[0-9]\\+##g" \
+ -e "s# key-secret=[a-zA-Z0-9]\\+##g"
}
_filter_img_info()
@@ -115,6 +123,7 @@ _filter_img_info()
-e "/zeroed_grain: \\(on\\|off\\)/d" \
-e "/subformat: '[^']*'/d" \
-e "/adapter_type: '[^']*'/d" \
+ -e "/hwversion: '[^']*'/d" \
-e "/lazy_refcounts: \\(on\\|off\\)/d" \
-e "/block_size: [0-9]\\+/d" \
-e "/block_state_zero: \\(on\\|off\\)/d" \
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 5249ec5922..306b00c210 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -53,21 +53,45 @@ fi
# make sure we have a standard umask
umask 022
-if [ "$IMGPROTO" = "file" ]; then
- TEST_IMG=$TEST_DIR/t.$IMGFMT
-elif [ "$IMGPROTO" = "nbd" ]; then
- TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
- TEST_IMG="nbd:127.0.0.1:10810"
-elif [ "$IMGPROTO" = "ssh" ]; then
- TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
- TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE"
-elif [ "$IMGPROTO" = "nfs" ]; then
- TEST_DIR="nfs://127.0.0.1/$TEST_DIR"
- TEST_IMG=$TEST_DIR/t.$IMGFMT
-elif [ "$IMGPROTO" = "archipelago" ]; then
- TEST_IMG="archipelago:at.$IMGFMT"
+if [ "$IMGOPTSSYNTAX" = "true" ]; then
+ DRIVER="driver=$IMGFMT"
+ if [ "$IMGFMT" = "luks" ]; then
+ DRIVER="$DRIVER,key-secret=keysec0"
+ fi
+ if [ "$IMGPROTO" = "file" ]; then
+ TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
+ TEST_IMG="$DRIVER,file.filename=$TEST_DIR/t.$IMGFMT"
+ elif [ "$IMGPROTO" = "nbd" ]; then
+ TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
+ TEST_IMG="$DRIVER,file.driver=nbd,file.host=127.0.0.1,file.port=10810"
+ elif [ "$IMGPROTO" = "ssh" ]; then
+ TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
+ TEST_IMG="$DRIVER,file.driver=ssh,file.host=127.0.0.1,file.path=$TEST_IMG_FILE"
+ elif [ "$IMGPROTO" = "nfs" ]; then
+ TEST_DIR="$DRIVER,file.driver=nfs,file.filename=nfs://127.0.0.1/$TEST_DIR"
+ TEST_IMG=$TEST_DIR_OPTS/t.$IMGFMT
+ elif [ "$IMGPROTO" = "archipelago" ]; then
+ TEST_IMG="$DRIVER,file.driver=archipelago,file.volume=:at.$IMGFMT"
+ else
+ TEST_IMG="$DRIVER,file.driver=$IMGPROTO,file.filename=$TEST_DIR/t.$IMGFMT"
+ fi
else
- TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
+ if [ "$IMGPROTO" = "file" ]; then
+ TEST_IMG=$TEST_DIR/t.$IMGFMT
+ elif [ "$IMGPROTO" = "nbd" ]; then
+ TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
+ TEST_IMG="nbd:127.0.0.1:10810"
+ elif [ "$IMGPROTO" = "ssh" ]; then
+ TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
+ TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE"
+ elif [ "$IMGPROTO" = "nfs" ]; then
+ TEST_DIR="nfs://127.0.0.1/$TEST_DIR"
+ TEST_IMG=$TEST_DIR/t.$IMGFMT
+ elif [ "$IMGPROTO" = "archipelago" ]; then
+ TEST_IMG="archipelago:at.$IMGFMT"
+ else
+ TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
+ fi
fi
_optstr_add()
@@ -108,6 +132,7 @@ _make_test_img()
local img_name=""
local use_backing=0
local backing_file=""
+ local object_options=""
if [ -n "$TEST_IMG_FILE" ]; then
img_name=$TEST_IMG_FILE
@@ -118,6 +143,10 @@ _make_test_img()
if [ -n "$IMGOPTS" ]; then
optstr=$(_optstr_add "$optstr" "$IMGOPTS")
fi
+ if [ -n "$IMGKEYSECRET" ]; then
+ object_options="--object secret,id=keysec0,data=$IMGKEYSECRET"
+ optstr=$(_optstr_add "$optstr" "key-secret=keysec0")
+ fi
if [ "$1" = "-b" ]; then
use_backing=1
@@ -135,9 +164,9 @@ _make_test_img()
# XXX(hch): have global image options?
(
if [ $use_backing = 1 ]; then
- $QEMU_IMG create -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" $image_size 2>&1
+ $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" $image_size 2>&1
else
- $QEMU_IMG create -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1
+ $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1
fi
) | _filter_img_create
@@ -199,7 +228,13 @@ _cleanup_test_img()
_check_test_img()
{
- $QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1 | _filter_testdir | \
+ (
+ if [ "$IMGOPTSSYNTAX" = "true" ]; then
+ $QEMU_IMG check $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1
+ else
+ $QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1
+ fi
+ ) | _filter_testdir | \
sed -e '/allocated.*fragmented.*compressed clusters/d' \
-e 's/qemu-img: This image format does not support checks/No errors were found on the image./' \
-e '/Image end offset: [0-9]\+/d'
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 822953b6fa..50ddeed80a 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -106,7 +106,7 @@
097 rw auto backing
098 rw auto backing quick
099 rw auto quick
-100 rw auto quick
+# 100 was removed, do not reuse
101 rw auto quick
102 rw auto quick
103 rw auto quick
@@ -153,3 +153,8 @@
149 rw auto sudo
150 rw auto quick
152 rw auto quick
+154 rw auto backing quick
+155 rw auto
+156 rw auto quick
+157 auto
+162 auto quick
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 56f988ab3d..dbe0ee548a 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -24,8 +24,6 @@ import string
import unittest
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scripts'))
-sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scripts', 'qmp'))
-import qmp
import qtest
import struct
import json
@@ -41,13 +39,12 @@ qemu_io_args = [os.environ.get('QEMU_IO_PROG', 'qemu-io')]
if os.environ.get('QEMU_IO_OPTIONS'):
qemu_io_args += os.environ['QEMU_IO_OPTIONS'].strip().split(' ')
-qemu_args = [os.environ.get('QEMU_PROG', 'qemu')]
-if os.environ.get('QEMU_OPTIONS'):
- qemu_args += os.environ['QEMU_OPTIONS'].strip().split(' ')
+qemu_prog = os.environ.get('QEMU_PROG', 'qemu')
+qemu_opts = os.environ.get('QEMU_OPTIONS', '').strip().split(' ')
imgfmt = os.environ.get('IMGFMT', 'raw')
imgproto = os.environ.get('IMGPROTO', 'file')
-test_dir = os.environ.get('TEST_DIR', '/var/tmp')
+test_dir = os.environ.get('TEST_DIR')
output_dir = os.environ.get('OUTPUT_DIR', '.')
cachemode = os.environ.get('CACHEMODE')
qemu_default_machine = os.environ.get('QEMU_DEFAULT_MACHINE')
@@ -131,44 +128,13 @@ def log(msg, filters=[]):
msg = flt(msg)
print msg
-# Test if 'match' is a recursive subset of 'event'
-def event_match(event, match=None):
- if match is None:
- return True
-
- for key in match:
- if key in event:
- if isinstance(event[key], dict):
- if not event_match(event[key], match[key]):
- return False
- elif event[key] != match[key]:
- return False
- else:
- return False
-
- return True
-
-class VM(object):
+class VM(qtest.QEMUQtestMachine):
'''A QEMU VM'''
def __init__(self):
- self._monitor_path = os.path.join(test_dir, 'qemu-mon.%d' % os.getpid())
- self._qemu_log_path = os.path.join(test_dir, 'qemu-log.%d' % os.getpid())
- self._qtest_path = os.path.join(test_dir, 'qemu-qtest.%d' % os.getpid())
- self._args = qemu_args + ['-chardev',
- 'socket,id=mon,path=' + self._monitor_path,
- '-mon', 'chardev=mon,mode=control',
- '-qtest', 'unix:path=' + self._qtest_path,
- '-machine', 'accel=qtest',
- '-display', 'none', '-vga', 'none']
+ super(VM, self).__init__(qemu_prog, qemu_opts, test_dir=test_dir,
+ socket_scm_helper=socket_scm_helper)
self._num_drives = 0
- self._events = []
-
- # This can be used to add an unused monitor instance.
- def add_monitor_telnet(self, ip, port):
- args = 'tcp:%s:%d,server,nowait,telnet' % (ip, port)
- self._args.append('-monitor')
- self._args.append(args)
def add_drive_raw(self, opts):
self._args.append('-drive')
@@ -211,106 +177,6 @@ class VM(object):
return self.qmp('human-monitor-command',
command_line='qemu-io %s "%s"' % (drive, cmd))
- def add_fd(self, fd, fdset, opaque, opts=''):
- '''Pass a file descriptor to the VM'''
- options = ['fd=%d' % fd,
- 'set=%d' % fdset,
- 'opaque=%s' % opaque]
- if opts:
- options.append(opts)
-
- self._args.append('-add-fd')
- self._args.append(','.join(options))
- return self
-
- def send_fd_scm(self, fd_file_path):
- # In iotest.py, the qmp should always use unix socket.
- assert self._qmp.is_scm_available()
- bin = socket_scm_helper
- if os.path.exists(bin) == False:
- print "Scm help program does not present, path '%s'." % bin
- return -1
- fd_param = ["%s" % bin,
- "%d" % self._qmp.get_sock_fd(),
- "%s" % fd_file_path]
- devnull = open('/dev/null', 'rb')
- p = subprocess.Popen(fd_param, stdin=devnull, stdout=sys.stdout,
- stderr=sys.stderr)
- return p.wait()
-
- def launch(self):
- '''Launch the VM and establish a QMP connection'''
- devnull = open('/dev/null', 'rb')
- qemulog = open(self._qemu_log_path, 'wb')
- try:
- self._qmp = qmp.QEMUMonitorProtocol(self._monitor_path, server=True)
- self._qtest = qtest.QEMUQtestProtocol(self._qtest_path, server=True)
- self._popen = subprocess.Popen(self._args, stdin=devnull, stdout=qemulog,
- stderr=subprocess.STDOUT)
- self._qmp.accept()
- self._qtest.accept()
- except:
- _remove_if_exists(self._monitor_path)
- _remove_if_exists(self._qtest_path)
- raise
-
- def shutdown(self):
- '''Terminate the VM and clean up'''
- if not self._popen is None:
- self._qmp.cmd('quit')
- exitcode = self._popen.wait()
- if exitcode < 0:
- sys.stderr.write('qemu received signal %i: %s\n' % (-exitcode, ' '.join(self._args)))
- os.remove(self._monitor_path)
- os.remove(self._qtest_path)
- os.remove(self._qemu_log_path)
- self._popen = None
-
- underscore_to_dash = string.maketrans('_', '-')
- def qmp(self, cmd, conv_keys=True, **args):
- '''Invoke a QMP command and return the result dict'''
- qmp_args = dict()
- for k in args.keys():
- if conv_keys:
- qmp_args[k.translate(self.underscore_to_dash)] = args[k]
- else:
- qmp_args[k] = args[k]
-
- return self._qmp.cmd(cmd, args=qmp_args)
-
- def qtest(self, cmd):
- '''Send a qtest command to guest'''
- return self._qtest.cmd(cmd)
-
- def get_qmp_event(self, wait=False):
- '''Poll for one queued QMP events and return it'''
- if len(self._events) > 0:
- return self._events.pop(0)
- return self._qmp.pull_event(wait=wait)
-
- def get_qmp_events(self, wait=False):
- '''Poll for queued QMP events and return a list of dicts'''
- events = self._qmp.get_events(wait=wait)
- events.extend(self._events)
- del self._events[:]
- self._qmp.clear_events()
- return events
-
- def event_wait(self, name='BLOCK_JOB_COMPLETED', timeout=60.0, match=None):
- # Search cached events
- for event in self._events:
- if (event['event'] == name) and event_match(event, match):
- self._events.remove(event)
- return event
-
- # Poll for new events
- while True:
- event = self._qmp.pull_event(wait=timeout)
- if (event['event'] == name) and event_match(event, match):
- return event
- self._events.append(event)
-
- return None
index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
@@ -427,15 +293,6 @@ class QMPTestCase(unittest.TestCase):
event = self.wait_until_completed(drive=drive)
self.assert_qmp(event, 'data/type', 'mirror')
-def _remove_if_exists(path):
- '''Remove file object at path if it exists'''
- try:
- os.remove(path)
- except OSError as exception:
- if exception.errno == errno.ENOENT:
- return
- raise
-
def notrun(reason):
'''Skip this test suite'''
# Each test in qemu-iotests has a number ("seq")
@@ -461,6 +318,14 @@ def verify_quorum():
def main(supported_fmts=[], supported_oses=['linux']):
'''Run tests'''
+ # We are using TEST_DIR and QEMU_DEFAULT_MACHINE as proxies to
+ # indicate that we're not being run via "check". There may be
+ # other things set up by "check" that individual test cases rely
+ # on.
+ if test_dir is None or qemu_default_machine is None:
+ sys.stderr.write('Please run this test via the "check" script\n')
+ sys.exit(os.EX_USAGE)
+
debug = '-d' in sys.argv
verbosity = 1
verify_image_format(supported_fmts)
diff --git a/tests/qht-bench.c b/tests/qht-bench.c
new file mode 100644
index 0000000000..76360a0cf5
--- /dev/null
+++ b/tests/qht-bench.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2016, Emilio G. Cota <cota@braap.org>
+ *
+ * License: GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qemu/processor.h"
+#include "qemu/atomic.h"
+#include "qemu/qht.h"
+#include "qemu/rcu.h"
+#include "exec/tb-hash-xx.h"
+
+struct thread_stats {
+ size_t rd;
+ size_t not_rd;
+ size_t in;
+ size_t not_in;
+ size_t rm;
+ size_t not_rm;
+ size_t rz;
+ size_t not_rz;
+};
+
+struct thread_info {
+ void (*func)(struct thread_info *);
+ struct thread_stats stats;
+ uint64_t r;
+ bool write_op; /* writes alternate between insertions and removals */
+ bool resize_down;
+} QEMU_ALIGNED(64); /* avoid false sharing among threads */
+
+static struct qht ht;
+static QemuThread *rw_threads;
+
+#define DEFAULT_RANGE (4096)
+#define DEFAULT_QHT_N_ELEMS DEFAULT_RANGE
+
+static unsigned int duration = 1;
+static unsigned int n_rw_threads = 1;
+static unsigned long lookup_range = DEFAULT_RANGE;
+static unsigned long update_range = DEFAULT_RANGE;
+static size_t init_range = DEFAULT_RANGE;
+static size_t init_size = DEFAULT_RANGE;
+static size_t n_ready_threads;
+static long populate_offset;
+static long *keys;
+
+static size_t resize_min;
+static size_t resize_max;
+static struct thread_info *rz_info;
+static unsigned long resize_delay = 1000;
+static double resize_rate; /* 0.0 to 1.0 */
+static unsigned int n_rz_threads = 1;
+static QemuThread *rz_threads;
+
+static double update_rate; /* 0.0 to 1.0 */
+static uint64_t update_threshold;
+static uint64_t resize_threshold;
+
+static size_t qht_n_elems = DEFAULT_QHT_N_ELEMS;
+static int qht_mode;
+
+static bool test_start;
+static bool test_stop;
+
+static struct thread_info *rw_info;
+
+static const char commands_string[] =
+ " -d = duration, in seconds\n"
+ " -n = number of threads\n"
+ "\n"
+ " -o = offset at which keys start\n"
+ "\n"
+ " -g = set -s,-k,-K,-l,-r to the same value\n"
+ " -s = initial size hint\n"
+ " -k = initial number of keys\n"
+ " -K = initial range of keys (will be rounded up to pow2)\n"
+ " -l = lookup range of keys (will be rounded up to pow2)\n"
+ " -r = update range of keys (will be rounded up to pow2)\n"
+ "\n"
+ " -u = update rate (0.0 to 100.0), 50/50 split of insertions/removals\n"
+ "\n"
+ " -R = enable auto-resize\n"
+ " -S = resize rate (0.0 to 100.0)\n"
+ " -D = delay (in us) between potential resizes\n"
+ " -N = number of resize threads";
+
+static void usage_complete(int argc, char *argv[])
+{
+ fprintf(stderr, "Usage: %s [options]\n", argv[0]);
+ fprintf(stderr, "options:\n%s\n", commands_string);
+ exit(-1);
+}
+
+static bool is_equal(const void *obj, const void *userp)
+{
+ const long *a = obj;
+ const long *b = userp;
+
+ return *a == *b;
+}
+
+static inline uint32_t h(unsigned long v)
+{
+ return tb_hash_func5(v, 0, 0);
+}
+
+/*
+ * From: https://en.wikipedia.org/wiki/Xorshift
+ * This is faster than rand_r(), and gives us a wider range (RAND_MAX is only
+ * guaranteed to be >= INT_MAX).
+ */
+static uint64_t xorshift64star(uint64_t x)
+{
+ x ^= x >> 12; /* a */
+ x ^= x << 25; /* b */
+ x ^= x >> 27; /* c */
+ return x * UINT64_C(2685821657736338717);
+}
+
+static void do_rz(struct thread_info *info)
+{
+ struct thread_stats *stats = &info->stats;
+
+ if (info->r < resize_threshold) {
+ size_t size = info->resize_down ? resize_min : resize_max;
+ bool resized;
+
+ resized = qht_resize(&ht, size);
+ info->resize_down = !info->resize_down;
+
+ if (resized) {
+ stats->rz++;
+ } else {
+ stats->not_rz++;
+ }
+ }
+ g_usleep(resize_delay);
+}
+
+static void do_rw(struct thread_info *info)
+{
+ struct thread_stats *stats = &info->stats;
+ uint32_t hash;
+ long *p;
+
+ if (info->r >= update_threshold) {
+ bool read;
+
+ p = &keys[info->r & (lookup_range - 1)];
+ hash = h(*p);
+ read = qht_lookup(&ht, is_equal, p, hash);
+ if (read) {
+ stats->rd++;
+ } else {
+ stats->not_rd++;
+ }
+ } else {
+ p = &keys[info->r & (update_range - 1)];
+ hash = h(*p);
+ if (info->write_op) {
+ bool written = false;
+
+ if (qht_lookup(&ht, is_equal, p, hash) == NULL) {
+ written = qht_insert(&ht, p, hash);
+ }
+ if (written) {
+ stats->in++;
+ } else {
+ stats->not_in++;
+ }
+ } else {
+ bool removed = false;
+
+ if (qht_lookup(&ht, is_equal, p, hash)) {
+ removed = qht_remove(&ht, p, hash);
+ }
+ if (removed) {
+ stats->rm++;
+ } else {
+ stats->not_rm++;
+ }
+ }
+ info->write_op = !info->write_op;
+ }
+}
+
+static void *thread_func(void *p)
+{
+ struct thread_info *info = p;
+
+ rcu_register_thread();
+
+ atomic_inc(&n_ready_threads);
+ while (!atomic_mb_read(&test_start)) {
+ cpu_relax();
+ }
+
+ rcu_read_lock();
+ while (!atomic_read(&test_stop)) {
+ info->r = xorshift64star(info->r);
+ info->func(info);
+ }
+ rcu_read_unlock();
+
+ rcu_unregister_thread();
+ return NULL;
+}
+
+/* sets everything except info->func */
+static void prepare_thread_info(struct thread_info *info, int i)
+{
+ /* seed for the RNG; each thread should have a different one */
+ info->r = (i + 1) ^ time(NULL);
+ /* the first update will be a write */
+ info->write_op = true;
+ /* the first resize will be down */
+ info->resize_down = true;
+
+ memset(&info->stats, 0, sizeof(info->stats));
+}
+
+static void
+th_create_n(QemuThread **threads, struct thread_info **infos, const char *name,
+ void (*func)(struct thread_info *), int offset, int n)
+{
+ struct thread_info *info;
+ QemuThread *th;
+ int i;
+
+ th = g_malloc(sizeof(*th) * n);
+ *threads = th;
+
+ info = qemu_memalign(64, sizeof(*info) * n);
+ *infos = info;
+
+ for (i = 0; i < n; i++) {
+ prepare_thread_info(&info[i], offset + i);
+ info[i].func = func;
+ qemu_thread_create(&th[i], name, thread_func, &info[i],
+ QEMU_THREAD_JOINABLE);
+ }
+}
+
+static void create_threads(void)
+{
+ th_create_n(&rw_threads, &rw_info, "rw", do_rw, 0, n_rw_threads);
+ th_create_n(&rz_threads, &rz_info, "rz", do_rz, n_rw_threads, n_rz_threads);
+}
+
+static void pr_params(void)
+{
+ printf("Parameters:\n");
+ printf(" duration: %d s\n", duration);
+ printf(" # of threads: %u\n", n_rw_threads);
+ printf(" initial # of keys: %zu\n", init_size);
+ printf(" initial size hint: %zu\n", qht_n_elems);
+ printf(" auto-resize: %s\n",
+ qht_mode & QHT_MODE_AUTO_RESIZE ? "on" : "off");
+ if (resize_rate) {
+ printf(" resize_rate: %f%%\n", resize_rate * 100.0);
+ printf(" resize range: %zu-%zu\n", resize_min, resize_max);
+ printf(" # resize threads %u\n", n_rz_threads);
+ }
+ printf(" update rate: %f%%\n", update_rate * 100.0);
+ printf(" offset: %ld\n", populate_offset);
+ printf(" initial key range: %zu\n", init_range);
+ printf(" lookup range: %lu\n", lookup_range);
+ printf(" update range: %lu\n", update_range);
+}
+
+static void do_threshold(double rate, uint64_t *threshold)
+{
+ if (rate == 1.0) {
+ *threshold = UINT64_MAX;
+ } else {
+ *threshold = rate * UINT64_MAX;
+ }
+}
+
+static void htable_init(void)
+{
+ unsigned long n = MAX(init_range, update_range);
+ uint64_t r = time(NULL);
+ size_t retries = 0;
+ size_t i;
+
+ /* avoid allocating memory later by allocating all the keys now */
+ keys = g_malloc(sizeof(*keys) * n);
+ for (i = 0; i < n; i++) {
+ keys[i] = populate_offset + i;
+ }
+
+ /* some sanity checks */
+ g_assert_cmpuint(lookup_range, <=, n);
+
+ /* compute thresholds */
+ do_threshold(update_rate, &update_threshold);
+ do_threshold(resize_rate, &resize_threshold);
+
+ if (resize_rate) {
+ resize_min = n / 2;
+ resize_max = n;
+ assert(resize_min < resize_max);
+ } else {
+ n_rz_threads = 0;
+ }
+
+ /* initialize the hash table */
+ qht_init(&ht, qht_n_elems, qht_mode);
+ assert(init_size <= init_range);
+
+ pr_params();
+
+ fprintf(stderr, "Initialization: populating %zu items...", init_size);
+ for (i = 0; i < init_size; i++) {
+ for (;;) {
+ uint32_t hash;
+ long *p;
+
+ r = xorshift64star(r);
+ p = &keys[r & (init_range - 1)];
+ hash = h(*p);
+ if (qht_insert(&ht, p, hash)) {
+ break;
+ }
+ retries++;
+ }
+ }
+ fprintf(stderr, " populated after %zu retries\n", retries);
+}
+
+static void add_stats(struct thread_stats *s, struct thread_info *info, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ struct thread_stats *stats = &info[i].stats;
+
+ s->rd += stats->rd;
+ s->not_rd += stats->not_rd;
+
+ s->in += stats->in;
+ s->not_in += stats->not_in;
+
+ s->rm += stats->rm;
+ s->not_rm += stats->not_rm;
+
+ s->rz += stats->rz;
+ s->not_rz += stats->not_rz;
+ }
+}
+
+static void pr_stats(void)
+{
+ struct thread_stats s = {};
+ double tx;
+
+ add_stats(&s, rw_info, n_rw_threads);
+ add_stats(&s, rz_info, n_rz_threads);
+
+ printf("Results:\n");
+
+ if (resize_rate) {
+ printf(" Resizes: %zu (%.2f%% of %zu)\n",
+ s.rz, (double)s.rz / (s.rz + s.not_rz) * 100, s.rz + s.not_rz);
+ }
+
+ printf(" Read: %.2f M (%.2f%% of %.2fM)\n",
+ (double)s.rd / 1e6,
+ (double)s.rd / (s.rd + s.not_rd) * 100,
+ (double)(s.rd + s.not_rd) / 1e6);
+ printf(" Inserted: %.2f M (%.2f%% of %.2fM)\n",
+ (double)s.in / 1e6,
+ (double)s.in / (s.in + s.not_in) * 100,
+ (double)(s.in + s.not_in) / 1e6);
+ printf(" Removed: %.2f M (%.2f%% of %.2fM)\n",
+ (double)s.rm / 1e6,
+ (double)s.rm / (s.rm + s.not_rm) * 100,
+ (double)(s.rm + s.not_rm) / 1e6);
+
+ tx = (s.rd + s.not_rd + s.in + s.not_in + s.rm + s.not_rm) / 1e6 / duration;
+ printf(" Throughput: %.2f MT/s\n", tx);
+ printf(" Throughput/thread: %.2f MT/s/thread\n", tx / n_rw_threads);
+}
+
+static void run_test(void)
+{
+ unsigned int remaining;
+ int i;
+
+ while (atomic_read(&n_ready_threads) != n_rw_threads + n_rz_threads) {
+ cpu_relax();
+ }
+ atomic_mb_set(&test_start, true);
+ do {
+ remaining = sleep(duration);
+ } while (remaining);
+ atomic_mb_set(&test_stop, true);
+
+ for (i = 0; i < n_rw_threads; i++) {
+ qemu_thread_join(&rw_threads[i]);
+ }
+ for (i = 0; i < n_rz_threads; i++) {
+ qemu_thread_join(&rz_threads[i]);
+ }
+}
+
+static void parse_args(int argc, char *argv[])
+{
+ int c;
+
+ for (;;) {
+ c = getopt(argc, argv, "d:D:g:k:K:l:hn:N:o:r:Rs:S:u:");
+ if (c < 0) {
+ break;
+ }
+ switch (c) {
+ case 'd':
+ duration = atoi(optarg);
+ break;
+ case 'D':
+ resize_delay = atol(optarg);
+ break;
+ case 'g':
+ init_range = pow2ceil(atol(optarg));
+ lookup_range = pow2ceil(atol(optarg));
+ update_range = pow2ceil(atol(optarg));
+ qht_n_elems = atol(optarg);
+ init_size = atol(optarg);
+ break;
+ case 'h':
+ usage_complete(argc, argv);
+ exit(0);
+ case 'k':
+ init_size = atol(optarg);
+ break;
+ case 'K':
+ init_range = pow2ceil(atol(optarg));
+ break;
+ case 'l':
+ lookup_range = pow2ceil(atol(optarg));
+ break;
+ case 'n':
+ n_rw_threads = atoi(optarg);
+ break;
+ case 'N':
+ n_rz_threads = atoi(optarg);
+ break;
+ case 'o':
+ populate_offset = atol(optarg);
+ break;
+ case 'r':
+ update_range = pow2ceil(atol(optarg));
+ break;
+ case 'R':
+ qht_mode |= QHT_MODE_AUTO_RESIZE;
+ break;
+ case 's':
+ qht_n_elems = atol(optarg);
+ break;
+ case 'S':
+ resize_rate = atof(optarg) / 100.0;
+ if (resize_rate > 1.0) {
+ resize_rate = 1.0;
+ }
+ break;
+ case 'u':
+ update_rate = atof(optarg) / 100.0;
+ if (update_rate > 1.0) {
+ update_rate = 1.0;
+ }
+ break;
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ parse_args(argc, argv);
+ htable_init();
+ create_threads();
+ run_test();
+ pr_stats();
+ return 0;
+}
diff --git a/tests/qom-test.c b/tests/qom-test.c
index bd5cdde261..23493a2b0a 100644
--- a/tests/qom-test.c
+++ b/tests/qom-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "qemu/cutils.h"
diff --git a/tests/rcutorture.c b/tests/rcutorture.c
index 244f0f28b2..4002ecf123 100644
--- a/tests/rcutorture.c
+++ b/tests/rcutorture.c
@@ -61,7 +61,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu/atomic.h"
#include "qemu/rcu.h"
#include "qemu/thread.h"
diff --git a/tests/rtc-test.c b/tests/rtc-test.c
index fa7029aa8a..a086efd120 100644
--- a/tests/rtc-test.c
+++ b/tests/rtc-test.c
@@ -12,7 +12,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "hw/timer/mc146818rtc_regs.h"
diff --git a/tests/rtl8139-test.c b/tests/rtl8139-test.c
index 54e5aa7d0e..13de7eeafd 100644
--- a/tests/rtl8139-test.c
+++ b/tests/rtl8139-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/pci-pc.h"
#include "qemu/timer.h"
diff --git a/tests/spapr-phb-test.c b/tests/spapr-phb-test.c
index f53911d9f7..21004a76ec 100644
--- a/tests/spapr-phb-test.c
+++ b/tests/spapr-phb-test.c
@@ -8,7 +8,6 @@
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
diff --git a/tests/tcg/cris/check_addo.c b/tests/tcg/cris/check_addo.c
index 3d8e789f5a..4235e5fc65 100644
--- a/tests/tcg/cris/check_addo.c
+++ b/tests/tcg/cris/check_addo.c
@@ -51,7 +51,7 @@ int main(void)
t = (unsigned char *)x;
t -= 32768;
p = (unsigned char *) &y.v1;
- mb(); /* dont reorder anything beyond here. */
+ mb(); /* don't reorder anything beyond here. */
cris_tst_cc_init();
asm volatile ("setf\tzvnc\n");
cris_addo_pi_d(p, t);
@@ -62,7 +62,7 @@ int main(void)
t += 32770;
- mb(); /* dont reorder anything beyond here. */
+ mb(); /* don't reorder anything beyond here. */
cris_tst_cc_init();
asm volatile ("setf\tzvnc\n");
cris_addo_pi_w(p, t);
@@ -71,7 +71,7 @@ int main(void)
if (*r != 0x4455aa77)
err();
- mb(); /* dont reorder anything beyond here. */
+ mb(); /* don't reorder anything beyond here. */
cris_tst_cc_init();
asm volatile ("setf\tzvnc\n");
cris_addo_d(p, r);
@@ -81,7 +81,7 @@ int main(void)
if (*r != 0xee19ccff)
err();
- mb(); /* dont reorder anything beyond here. */
+ mb(); /* don't reorder anything beyond here. */
cris_tst_cc_init();
asm volatile ("setf\tzvnc\n");
cris_addo_pi_b(p, t);
@@ -90,7 +90,7 @@ int main(void)
if (*(uint16_t*)r != 0xff22)
err();
- mb(); /* dont reorder anything beyond here. */
+ mb(); /* don't reorder anything beyond here. */
cris_tst_cc_init();
asm volatile ("setf\tzvnc\n");
cris_addo_b(p, r);
@@ -100,7 +100,7 @@ int main(void)
if (*r != 0x4455aa77)
err();
- mb(); /* dont reorder anything beyond here. */
+ mb(); /* don't reorder anything beyond here. */
cris_tst_cc_init();
asm volatile ("setf\tzvnc\n");
cris_addo_w(p, r);
@@ -110,7 +110,7 @@ int main(void)
if (*r != 0xff224455)
err();
- mb(); /* dont reorder anything beyond here. */
+ mb(); /* don't reorder anything beyond here. */
cris_tst_cc_init();
asm volatile ("setf\tzvnc\n");
cris_addo_pi_d(p, t);
diff --git a/tests/tcg/xtensa/linker.ld.S b/tests/tcg/xtensa/linker.ld.S
index f1e7fa9f8d..5902302cf8 100644
--- a/tests/tcg/xtensa/linker.ld.S
+++ b/tests/tcg/xtensa/linker.ld.S
@@ -1,4 +1,4 @@
-#include <core-isa.h>
+#include "core-isa.h"
#if XTENSA_HAVE_BE
OUTPUT_FORMAT("elf32-xtensa-be")
diff --git a/tests/tco-test.c b/tests/tco-test.c
index ac11175e90..0d13aa8d63 100644
--- a/tests/tco-test.c
+++ b/tests/tco-test.c
@@ -7,7 +7,6 @@
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/pci.h"
diff --git a/tests/test-aio.c b/tests/test-aio.c
index 687dfa062e..03aa846970 100644
--- a/tests/test-aio.c
+++ b/tests/test-aio.c
@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "block/aio.h"
#include "qapi/error.h"
#include "qemu/timer.h"
@@ -453,7 +452,7 @@ static void test_timer_schedule(void)
{
TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
.max = 2,
- .clock_type = QEMU_CLOCK_VIRTUAL };
+ .clock_type = QEMU_CLOCK_REALTIME };
EventNotifier e;
/* aio_poll will not block to wait for timers to complete unless it has
@@ -783,7 +782,7 @@ static void test_source_timer_schedule(void)
{
TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
.max = 2,
- .clock_type = QEMU_CLOCK_VIRTUAL };
+ .clock_type = QEMU_CLOCK_REALTIME };
EventNotifier e;
int64_t expiry;
diff --git a/tests/test-base64.c b/tests/test-base64.c
index 922e839dd6..ec122ceba5 100644
--- a/tests/test-base64.c
+++ b/tests/test-base64.c
@@ -19,7 +19,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qapi/error.h"
#include "qemu/base64.h"
diff --git a/tests/test-bitops.c b/tests/test-bitops.c
index 5050950607..5a791d2e17 100644
--- a/tests/test-bitops.c
+++ b/tests/test-bitops.c
@@ -7,7 +7,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu/bitops.h"
typedef struct {
@@ -66,10 +65,82 @@ static void test_sextract64(void)
}
}
+typedef struct {
+ uint32_t unshuffled;
+ uint32_t shuffled;
+} Shuffle32Test;
+
+typedef struct {
+ uint64_t unshuffled;
+ uint64_t shuffled;
+} Shuffle64Test;
+
+static const Shuffle32Test test_shuffle32_data[] = {
+ { 0x0000FFFF, 0x55555555 },
+ { 0x000081C5, 0x40015011 },
+};
+
+static const Shuffle64Test test_shuffle64_data[] = {
+ { 0x00000000FFFFFFFFULL, 0x5555555555555555ULL },
+ { 0x00000000493AB02CULL, 0x1041054445000450ULL },
+};
+
+static void test_half_shuffle32(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(test_shuffle32_data); i++) {
+ const Shuffle32Test *test = &test_shuffle32_data[i];
+ uint32_t r = half_shuffle32(test->unshuffled);
+
+ g_assert_cmpint(r, ==, test->shuffled);
+ }
+}
+
+static void test_half_shuffle64(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(test_shuffle64_data); i++) {
+ const Shuffle64Test *test = &test_shuffle64_data[i];
+ uint64_t r = half_shuffle64(test->unshuffled);
+
+ g_assert_cmpint(r, ==, test->shuffled);
+ }
+}
+
+static void test_half_unshuffle32(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(test_shuffle32_data); i++) {
+ const Shuffle32Test *test = &test_shuffle32_data[i];
+ uint32_t r = half_unshuffle32(test->shuffled);
+
+ g_assert_cmpint(r, ==, test->unshuffled);
+ }
+}
+
+static void test_half_unshuffle64(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(test_shuffle64_data); i++) {
+ const Shuffle64Test *test = &test_shuffle64_data[i];
+ uint64_t r = half_unshuffle64(test->shuffled);
+
+ g_assert_cmpint(r, ==, test->unshuffled);
+ }
+}
+
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
g_test_add_func("/bitops/sextract32", test_sextract32);
g_test_add_func("/bitops/sextract64", test_sextract64);
+ g_test_add_func("/bitops/half_shuffle32", test_half_shuffle32);
+ g_test_add_func("/bitops/half_shuffle64", test_half_shuffle64);
+ g_test_add_func("/bitops/half_unshuffle32", test_half_unshuffle32);
+ g_test_add_func("/bitops/half_unshuffle64", test_half_unshuffle64);
return g_test_run();
}
diff --git a/tests/test-blockjob-txn.c b/tests/test-blockjob-txn.c
index 55fad9507a..d049cba8a3 100644
--- a/tests/test-blockjob-txn.c
+++ b/tests/test-blockjob-txn.c
@@ -11,10 +11,10 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qapi/error.h"
#include "qemu/main-loop.h"
#include "block/blockjob.h"
+#include "sysemu/block-backend.h"
typedef struct {
BlockJob common;
@@ -30,7 +30,7 @@ static const BlockJobDriver test_block_job_driver = {
static void test_block_job_complete(BlockJob *job, void *opaque)
{
- BlockDriverState *bs = job->bs;
+ BlockDriverState *bs = blk_bs(job->blk);
int rc = (intptr_t)opaque;
if (block_job_is_cancelled(job)) {
@@ -91,19 +91,22 @@ static BlockJob *test_block_job_start(unsigned int iterations,
BlockDriverState *bs;
TestBlockJob *s;
TestBlockJobCBData *data;
+ static unsigned counter;
+ char job_id[24];
data = g_new0(TestBlockJobCBData, 1);
bs = bdrv_new();
- s = block_job_create(&test_block_job_driver, bs, 0, test_block_job_cb,
- data, &error_abort);
+ snprintf(job_id, sizeof(job_id), "job%u", counter++);
+ s = block_job_create(job_id, &test_block_job_driver, bs, 0,
+ test_block_job_cb, data, &error_abort);
s->iterations = iterations;
s->use_timer = use_timer;
s->rc = rc;
s->result = result;
- s->common.co = qemu_coroutine_create(test_block_job_run);
+ s->common.co = qemu_coroutine_create(test_block_job_run, s);
data->job = s;
data->result = result;
- qemu_coroutine_enter(s->common.co, s);
+ qemu_coroutine_enter(s->common.co);
return &s->common;
}
diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c
new file mode 100644
index 0000000000..5b0e934a0c
--- /dev/null
+++ b/tests/test-blockjob.c
@@ -0,0 +1,147 @@
+/*
+ * Blockjob tests
+ *
+ * Copyright Igalia, S.L. 2016
+ *
+ * Authors:
+ * Alberto Garcia <berto@igalia.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/main-loop.h"
+#include "block/blockjob.h"
+#include "sysemu/block-backend.h"
+
+static const BlockJobDriver test_block_job_driver = {
+ .instance_size = sizeof(BlockJob),
+};
+
+static void block_job_cb(void *opaque, int ret)
+{
+}
+
+static BlockJob *do_test_id(BlockBackend *blk, const char *id,
+ bool should_succeed)
+{
+ BlockJob *job;
+ Error *errp = NULL;
+
+ job = block_job_create(id, &test_block_job_driver, blk_bs(blk), 0,
+ block_job_cb, NULL, &errp);
+ if (should_succeed) {
+ g_assert_null(errp);
+ g_assert_nonnull(job);
+ if (id) {
+ g_assert_cmpstr(job->id, ==, id);
+ } else {
+ g_assert_cmpstr(job->id, ==, blk_name(blk));
+ }
+ } else {
+ g_assert_nonnull(errp);
+ g_assert_null(job);
+ error_free(errp);
+ }
+
+ return job;
+}
+
+/* This creates a BlockBackend (optionally with a name) with a
+ * BlockDriverState inserted. */
+static BlockBackend *create_blk(const char *name)
+{
+ BlockBackend *blk = blk_new();
+ BlockDriverState *bs = bdrv_new();
+
+ blk_insert_bs(blk, bs);
+ bdrv_unref(bs);
+
+ if (name) {
+ Error *errp = NULL;
+ monitor_add_blk(blk, name, &errp);
+ g_assert_null(errp);
+ }
+
+ return blk;
+}
+
+/* This destroys the backend */
+static void destroy_blk(BlockBackend *blk)
+{
+ if (blk_name(blk)[0] != '\0') {
+ monitor_remove_blk(blk);
+ }
+
+ blk_remove_bs(blk);
+ blk_unref(blk);
+}
+
+static void test_job_ids(void)
+{
+ BlockBackend *blk[3];
+ BlockJob *job[3];
+
+ blk[0] = create_blk(NULL);
+ blk[1] = create_blk("drive1");
+ blk[2] = create_blk("drive2");
+
+ /* No job ID provided and the block backend has no name */
+ job[0] = do_test_id(blk[0], NULL, false);
+
+ /* These are all invalid job IDs */
+ job[0] = do_test_id(blk[0], "0id", false);
+ job[0] = do_test_id(blk[0], "", false);
+ job[0] = do_test_id(blk[0], " ", false);
+ job[0] = do_test_id(blk[0], "123", false);
+ job[0] = do_test_id(blk[0], "_id", false);
+ job[0] = do_test_id(blk[0], "-id", false);
+ job[0] = do_test_id(blk[0], ".id", false);
+ job[0] = do_test_id(blk[0], "#id", false);
+
+ /* This one is valid */
+ job[0] = do_test_id(blk[0], "id0", true);
+
+ /* We cannot have two jobs in the same BDS */
+ do_test_id(blk[0], "id1", false);
+
+ /* Duplicate job IDs are not allowed */
+ job[1] = do_test_id(blk[1], "id0", false);
+
+ /* But once job[0] finishes we can reuse its ID */
+ block_job_unref(job[0]);
+ job[1] = do_test_id(blk[1], "id0", true);
+
+ /* No job ID specified, defaults to the backend name ('drive1') */
+ block_job_unref(job[1]);
+ job[1] = do_test_id(blk[1], NULL, true);
+
+ /* Duplicate job ID */
+ job[2] = do_test_id(blk[2], "drive1", false);
+
+ /* The ID of job[2] would default to 'drive2' but it is already in use */
+ job[0] = do_test_id(blk[0], "drive2", true);
+ job[2] = do_test_id(blk[2], NULL, false);
+
+ /* This one is valid */
+ job[2] = do_test_id(blk[2], "id_2", true);
+
+ block_job_unref(job[0]);
+ block_job_unref(job[1]);
+ block_job_unref(job[2]);
+
+ destroy_blk(blk[0]);
+ destroy_blk(blk[1]);
+ destroy_blk(blk[2]);
+}
+
+int main(int argc, char **argv)
+{
+ qemu_init_main_loop(&error_abort);
+
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/blockjob/ids", test_job_ids);
+ return g_test_run();
+}
diff --git a/tests/test-clone-visitor.c b/tests/test-clone-visitor.c
new file mode 100644
index 0000000000..df0c045512
--- /dev/null
+++ b/tests/test-clone-visitor.c
@@ -0,0 +1,206 @@
+/*
+ * QAPI Clone Visitor unit-tests.
+ *
+ * Copyright (C) 2016 Red Hat Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include <glib.h>
+
+#include "qemu-common.h"
+#include "qapi/clone-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qapi/qmp/types.h"
+
+static void test_clone_struct(void)
+{
+ UserDefOne *src, *dst;
+
+ src = g_new0(UserDefOne, 1);
+ src->integer = 42;
+ src->string = g_strdup("Hello");
+ src->has_enum1 = false;
+ src->enum1 = ENUM_ONE_VALUE2;
+
+ dst = QAPI_CLONE(UserDefOne, src);
+ g_assert(dst);
+ g_assert_cmpint(dst->integer, ==, 42);
+ g_assert(dst->string != src->string);
+ g_assert_cmpstr(dst->string, ==, "Hello");
+ g_assert_cmpint(dst->has_enum1, ==, false);
+ /* Our implementation does this, but it is not required:
+ g_assert_cmpint(dst->enum1, ==, ENUM_ONE_VALUE2);
+ */
+
+ qapi_free_UserDefOne(src);
+ qapi_free_UserDefOne(dst);
+}
+
+static void test_clone_alternate(void)
+{
+ AltStrBool *b_src, *s_src, *b_dst, *s_dst;
+
+ b_src = g_new0(AltStrBool, 1);
+ b_src->type = QTYPE_QBOOL;
+ b_src->u.b = true;
+ s_src = g_new0(AltStrBool, 1);
+ s_src->type = QTYPE_QSTRING;
+ s_src->u.s = g_strdup("World");
+
+ b_dst = QAPI_CLONE(AltStrBool, b_src);
+ g_assert(b_dst);
+ g_assert_cmpint(b_dst->type, ==, b_src->type);
+ g_assert_cmpint(b_dst->u.b, ==, b_src->u.b);
+ s_dst = QAPI_CLONE(AltStrBool, s_src);
+ g_assert(s_dst);
+ g_assert_cmpint(s_dst->type, ==, s_src->type);
+ g_assert_cmpstr(s_dst->u.s, ==, s_src->u.s);
+ g_assert(s_dst->u.s != s_src->u.s);
+
+ qapi_free_AltStrBool(b_src);
+ qapi_free_AltStrBool(s_src);
+ qapi_free_AltStrBool(b_dst);
+ qapi_free_AltStrBool(s_dst);
+}
+
+static void test_clone_native_list(void)
+{
+ uint8List *src, *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;
+ }
+
+ dst = QAPI_CLONE(uint8List, src);
+ for (tmp = dst, i = 1; i <= 10; i++) {
+ g_assert(tmp);
+ g_assert_cmpint(tmp->value, ==, i);
+ tmp = tmp->next;
+ }
+ g_assert(!tmp);
+
+ qapi_free_uint8List(src);
+ qapi_free_uint8List(dst);
+}
+
+static void test_clone_empty(void)
+{
+ Empty2 *src, *dst;
+
+ src = g_new0(Empty2, 1);
+ dst = QAPI_CLONE(Empty2, src);
+ g_assert(dst);
+ qapi_free_Empty2(src);
+ qapi_free_Empty2(dst);
+}
+
+static void test_clone_complex1(void)
+{
+ UserDefNativeListUnion *src, *dst;
+
+ src = g_new0(UserDefNativeListUnion, 1);
+ src->type = USER_DEF_NATIVE_LIST_UNION_KIND_STRING;
+
+ dst = QAPI_CLONE(UserDefNativeListUnion, src);
+ g_assert(dst);
+ g_assert_cmpint(dst->type, ==, src->type);
+ g_assert(!dst->u.string.data);
+
+ qapi_free_UserDefNativeListUnion(src);
+ qapi_free_UserDefNativeListUnion(dst);
+}
+
+static void test_clone_complex2(void)
+{
+ WrapAlternate *src, *dst;
+
+ src = g_new0(WrapAlternate, 1);
+ src->alt = g_new(UserDefAlternate, 1);
+ src->alt->type = QTYPE_QDICT;
+ src->alt->u.udfu.integer = 42;
+ /* Clone intentionally converts NULL into "" for strings */
+ src->alt->u.udfu.string = NULL;
+ src->alt->u.udfu.enum1 = ENUM_ONE_VALUE3;
+ src->alt->u.udfu.u.value3.intb = 99;
+ src->alt->u.udfu.u.value3.has_a_b = true;
+ src->alt->u.udfu.u.value3.a_b = true;
+
+ dst = QAPI_CLONE(WrapAlternate, src);
+ g_assert(dst);
+ g_assert(dst->alt);
+ g_assert_cmpint(dst->alt->type, ==, QTYPE_QDICT);
+ g_assert_cmpint(dst->alt->u.udfu.integer, ==, 42);
+ g_assert_cmpstr(dst->alt->u.udfu.string, ==, "");
+ g_assert_cmpint(dst->alt->u.udfu.enum1, ==, ENUM_ONE_VALUE3);
+ g_assert_cmpint(dst->alt->u.udfu.u.value3.intb, ==, 99);
+ g_assert_cmpint(dst->alt->u.udfu.u.value3.has_a_b, ==, true);
+ g_assert_cmpint(dst->alt->u.udfu.u.value3.a_b, ==, true);
+
+ qapi_free_WrapAlternate(src);
+ qapi_free_WrapAlternate(dst);
+}
+
+static void test_clone_complex3(void)
+{
+ __org_qemu_x_Struct2 *src, *dst;
+ __org_qemu_x_Union1List *tmp;
+
+ src = g_new0(__org_qemu_x_Struct2, 1);
+ tmp = src->array = g_new0(__org_qemu_x_Union1List, 1);
+ tmp->value = g_new0(__org_qemu_x_Union1, 1);
+ tmp->value->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
+ tmp->value->u.__org_qemu_x_branch.data = g_strdup("one");
+ tmp = tmp->next = g_new0(__org_qemu_x_Union1List, 1);
+ tmp->value = g_new0(__org_qemu_x_Union1, 1);
+ tmp->value->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
+ tmp->value->u.__org_qemu_x_branch.data = g_strdup("two");
+ tmp = tmp->next = g_new0(__org_qemu_x_Union1List, 1);
+ tmp->value = g_new0(__org_qemu_x_Union1, 1);
+ tmp->value->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
+ tmp->value->u.__org_qemu_x_branch.data = g_strdup("three");
+
+ dst = QAPI_CLONE(__org_qemu_x_Struct2, src);
+ g_assert(dst);
+ tmp = dst->array;
+ g_assert(tmp);
+ g_assert(tmp->value);
+ g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch.data, ==, "one");
+ tmp = tmp->next;
+ g_assert(tmp);
+ g_assert(tmp->value);
+ g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch.data, ==, "two");
+ tmp = tmp->next;
+ g_assert(tmp);
+ g_assert(tmp->value);
+ g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch.data, ==, "three");
+ tmp = tmp->next;
+ g_assert(!tmp);
+
+ qapi_free___org_qemu_x_Struct2(src);
+ qapi_free___org_qemu_x_Struct2(dst);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/visitor/clone/struct", test_clone_struct);
+ g_test_add_func("/visitor/clone/alternate", test_clone_alternate);
+ g_test_add_func("/visitor/clone/native_list", test_clone_native_list);
+ g_test_add_func("/visitor/clone/empty", test_clone_empty);
+ g_test_add_func("/visitor/clone/complex1", test_clone_complex1);
+ g_test_add_func("/visitor/clone/complex2", test_clone_complex2);
+ g_test_add_func("/visitor/clone/complex3", test_clone_complex3);
+
+ return g_test_run();
+}
diff --git a/tests/test-coroutine.c b/tests/test-coroutine.c
index dd4ced946c..ee5e06d327 100644
--- a/tests/test-coroutine.c
+++ b/tests/test-coroutine.c
@@ -12,7 +12,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu/coroutine.h"
#include "qemu/coroutine_int.h"
@@ -31,8 +30,8 @@ static void test_in_coroutine(void)
g_assert(!qemu_in_coroutine());
- coroutine = qemu_coroutine_create(verify_in_coroutine);
- qemu_coroutine_enter(coroutine, NULL);
+ coroutine = qemu_coroutine_create(verify_in_coroutine, NULL);
+ qemu_coroutine_enter(coroutine);
}
/*
@@ -41,15 +40,16 @@ static void test_in_coroutine(void)
static void coroutine_fn verify_self(void *opaque)
{
- g_assert(qemu_coroutine_self() == opaque);
+ Coroutine **p_co = opaque;
+ g_assert(qemu_coroutine_self() == *p_co);
}
static void test_self(void)
{
Coroutine *coroutine;
- coroutine = qemu_coroutine_create(verify_self);
- qemu_coroutine_enter(coroutine, coroutine);
+ coroutine = qemu_coroutine_create(verify_self, &coroutine);
+ qemu_coroutine_enter(coroutine);
}
/*
@@ -71,8 +71,8 @@ static void coroutine_fn nest(void *opaque)
if (nd->n_enter < nd->max) {
Coroutine *child;
- child = qemu_coroutine_create(nest);
- qemu_coroutine_enter(child, nd);
+ child = qemu_coroutine_create(nest, nd);
+ qemu_coroutine_enter(child);
}
nd->n_return++;
@@ -87,8 +87,8 @@ static void test_nesting(void)
.max = 128,
};
- root = qemu_coroutine_create(nest);
- qemu_coroutine_enter(root, &nd);
+ root = qemu_coroutine_create(nest, &nd);
+ qemu_coroutine_enter(root);
/* Must enter and return from max nesting level */
g_assert_cmpint(nd.n_enter, ==, nd.max);
@@ -116,9 +116,9 @@ static void test_yield(void)
bool done = false;
int i = -1; /* one extra time to return from coroutine */
- coroutine = qemu_coroutine_create(yield_5_times);
+ coroutine = qemu_coroutine_create(yield_5_times, &done);
while (!done) {
- qemu_coroutine_enter(coroutine, &done);
+ qemu_coroutine_enter(coroutine);
i++;
}
g_assert_cmpint(i, ==, 5); /* coroutine must yield 5 times */
@@ -132,7 +132,7 @@ static void coroutine_fn c2_fn(void *opaque)
static void coroutine_fn c1_fn(void *opaque)
{
Coroutine *c2 = opaque;
- qemu_coroutine_enter(c2, NULL);
+ qemu_coroutine_enter(c2);
}
static void test_co_queue(void)
@@ -140,12 +140,12 @@ static void test_co_queue(void)
Coroutine *c1;
Coroutine *c2;
- c1 = qemu_coroutine_create(c1_fn);
- c2 = qemu_coroutine_create(c2_fn);
+ c2 = qemu_coroutine_create(c2_fn, NULL);
+ c1 = qemu_coroutine_create(c1_fn, c2);
- qemu_coroutine_enter(c1, c2);
+ qemu_coroutine_enter(c1);
memset(c1, 0xff, sizeof(Coroutine));
- qemu_coroutine_enter(c2, NULL);
+ qemu_coroutine_enter(c2);
}
/*
@@ -165,14 +165,14 @@ static void test_lifecycle(void)
bool done = false;
/* Create, enter, and return from coroutine */
- coroutine = qemu_coroutine_create(set_and_exit);
- qemu_coroutine_enter(coroutine, &done);
+ coroutine = qemu_coroutine_create(set_and_exit, &done);
+ qemu_coroutine_enter(coroutine);
g_assert(done); /* expect done to be true (first time) */
/* Repeat to check that no state affects this test */
done = false;
- coroutine = qemu_coroutine_create(set_and_exit);
- qemu_coroutine_enter(coroutine, &done);
+ coroutine = qemu_coroutine_create(set_and_exit, &done);
+ qemu_coroutine_enter(coroutine);
g_assert(done); /* expect done to be true (second time) */
}
@@ -206,12 +206,12 @@ static void do_order_test(void)
{
Coroutine *co;
- co = qemu_coroutine_create(co_order_test);
+ co = qemu_coroutine_create(co_order_test, NULL);
record_push(1, 1);
- qemu_coroutine_enter(co, NULL);
+ qemu_coroutine_enter(co);
record_push(1, 2);
g_assert(!qemu_in_coroutine());
- qemu_coroutine_enter(co, NULL);
+ qemu_coroutine_enter(co);
record_push(1, 3);
g_assert(!qemu_in_coroutine());
}
@@ -248,8 +248,8 @@ static void perf_lifecycle(void)
g_test_timer_start();
for (i = 0; i < max; i++) {
- coroutine = qemu_coroutine_create(empty_coroutine);
- qemu_coroutine_enter(coroutine, NULL);
+ coroutine = qemu_coroutine_create(empty_coroutine, NULL);
+ qemu_coroutine_enter(coroutine);
}
duration = g_test_timer_elapsed();
@@ -272,8 +272,8 @@ static void perf_nesting(void)
.n_return = 0,
.max = maxnesting,
};
- root = qemu_coroutine_create(nest);
- qemu_coroutine_enter(root, &nd);
+ root = qemu_coroutine_create(nest, &nd);
+ qemu_coroutine_enter(root);
}
duration = g_test_timer_elapsed();
@@ -302,11 +302,11 @@ static void perf_yield(void)
maxcycles = 100000000;
i = maxcycles;
- Coroutine *coroutine = qemu_coroutine_create(yield_loop);
+ Coroutine *coroutine = qemu_coroutine_create(yield_loop, &i);
g_test_timer_start();
while (i > 0) {
- qemu_coroutine_enter(coroutine, &i);
+ qemu_coroutine_enter(coroutine);
}
duration = g_test_timer_elapsed();
@@ -352,9 +352,9 @@ static void perf_cost(void)
g_test_timer_start();
while (i++ < maxcycles) {
- co = qemu_coroutine_create(perf_cost_func);
- qemu_coroutine_enter(co, &i);
- qemu_coroutine_enter(co, NULL);
+ co = qemu_coroutine_create(perf_cost_func, &i);
+ qemu_coroutine_enter(co);
+ qemu_coroutine_enter(co);
}
duration = g_test_timer_elapsed();
ops = (long)(maxcycles / (duration * 1000));
@@ -369,7 +369,15 @@ static void perf_cost(void)
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
- g_test_add_func("/basic/co_queue", test_co_queue);
+
+ /* This test assumes there is a freelist and marks freed coroutine memory
+ * with a sentinel value. If there is no freelist this would legitimately
+ * crash, so skip it.
+ */
+ if (CONFIG_COROUTINE_POOL) {
+ g_test_add_func("/basic/co_queue", test_co_queue);
+ }
+
g_test_add_func("/basic/lifecycle", test_lifecycle);
g_test_add_func("/basic/yield", test_yield);
g_test_add_func("/basic/nesting", test_nesting);
diff --git a/tests/test-crypto-cipher.c b/tests/test-crypto-cipher.c
index 66d1c63fd5..1b5130d5f6 100644
--- a/tests/test-crypto-cipher.c
+++ b/tests/test-crypto-cipher.c
@@ -19,7 +19,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "crypto/init.h"
#include "crypto/cipher.h"
diff --git a/tests/test-crypto-hash.c b/tests/test-crypto-hash.c
index 735d6d7e0b..42fc77a107 100644
--- a/tests/test-crypto-hash.c
+++ b/tests/test-crypto-hash.c
@@ -19,7 +19,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "crypto/init.h"
#include "crypto/hash.h"
@@ -31,27 +30,56 @@
#define OUTPUT_MD5 "628d206371563035ab8ef62f492bdec9"
#define OUTPUT_SHA1 "b2e74f26758a3a421e509cee045244b78753cc02"
+#define OUTPUT_SHA224 "e2f7415aad33ef79f6516b0986d7175f" \
+ "9ca3389a85bf6cfed078737b"
#define OUTPUT_SHA256 "bc757abb0436586f392b437e5dd24096" \
"f7f224de6b74d4d86e2abc6121b160d0"
+#define OUTPUT_SHA384 "887ce52efb4f46700376356583b7e279" \
+ "4f612bd024e4495087ddb946c448c69d" \
+ "56dbf7152a94a5e63a80f3ba9f0eed78"
+#define OUTPUT_SHA512 "3a90d79638235ec6c4c11bebd84d83c0" \
+ "549bc1e84edc4b6ec7086487641256cb" \
+ "63b54e4cb2d2032b393994aa263c0dbb" \
+ "e00a9f2fe9ef6037352232a1eec55ee7"
+#define OUTPUT_RIPEMD160 "f3d658fad3fdfb2b52c9369cf0d441249ddfa8a0"
#define OUTPUT_MD5_B64 "Yo0gY3FWMDWrjvYvSSveyQ=="
#define OUTPUT_SHA1_B64 "sudPJnWKOkIeUJzuBFJEt4dTzAI="
+#define OUTPUT_SHA224_B64 "4vdBWq0z73n2UWsJhtcXX5yjOJqFv2z+0Hhzew=="
#define OUTPUT_SHA256_B64 "vHV6uwQ2WG85K0N+XdJAlvfyJN5rdNTYbiq8YSGxYNA="
+#define OUTPUT_SHA384_B64 "iHzlLvtPRnADdjVlg7fieU9hK9Ak5ElQh925RsRI" \
+ "xp1W2/cVKpSl5jqA87qfDu14"
+#define OUTPUT_SHA512_B64 "OpDXljgjXsbEwRvr2E2DwFSbwehO3Etuxwhkh2QS" \
+ "VstjtU5MstIDKzk5lKomPA274AqfL+nvYDc1IjKh" \
+ "7sVe5w=="
+#define OUTPUT_RIPEMD160_B64 "89ZY+tP9+ytSyTac8NRBJJ3fqKA="
static const char *expected_outputs[] = {
[QCRYPTO_HASH_ALG_MD5] = OUTPUT_MD5,
[QCRYPTO_HASH_ALG_SHA1] = OUTPUT_SHA1,
+ [QCRYPTO_HASH_ALG_SHA224] = OUTPUT_SHA224,
[QCRYPTO_HASH_ALG_SHA256] = OUTPUT_SHA256,
+ [QCRYPTO_HASH_ALG_SHA384] = OUTPUT_SHA384,
+ [QCRYPTO_HASH_ALG_SHA512] = OUTPUT_SHA512,
+ [QCRYPTO_HASH_ALG_RIPEMD160] = OUTPUT_RIPEMD160,
};
static const char *expected_outputs_b64[] = {
[QCRYPTO_HASH_ALG_MD5] = OUTPUT_MD5_B64,
[QCRYPTO_HASH_ALG_SHA1] = OUTPUT_SHA1_B64,
+ [QCRYPTO_HASH_ALG_SHA224] = OUTPUT_SHA224_B64,
[QCRYPTO_HASH_ALG_SHA256] = OUTPUT_SHA256_B64,
+ [QCRYPTO_HASH_ALG_SHA384] = OUTPUT_SHA384_B64,
+ [QCRYPTO_HASH_ALG_SHA512] = OUTPUT_SHA512_B64,
+ [QCRYPTO_HASH_ALG_RIPEMD160] = OUTPUT_RIPEMD160_B64,
};
static const int expected_lens[] = {
[QCRYPTO_HASH_ALG_MD5] = 16,
[QCRYPTO_HASH_ALG_SHA1] = 20,
+ [QCRYPTO_HASH_ALG_SHA224] = 28,
[QCRYPTO_HASH_ALG_SHA256] = 32,
+ [QCRYPTO_HASH_ALG_SHA384] = 48,
+ [QCRYPTO_HASH_ALG_SHA512] = 64,
+ [QCRYPTO_HASH_ALG_RIPEMD160] = 20,
};
static const char hex[] = "0123456789abcdef";
@@ -69,6 +97,10 @@ static void test_hash_alloc(void)
int ret;
size_t j;
+ if (!qcrypto_hash_supports(i)) {
+ continue;
+ }
+
ret = qcrypto_hash_bytes(i,
INPUT_TEXT,
strlen(INPUT_TEXT),
@@ -99,6 +131,10 @@ static void test_hash_prealloc(void)
int ret;
size_t j;
+ if (!qcrypto_hash_supports(i)) {
+ continue;
+ }
+
resultlen = expected_lens[i];
result = g_new0(uint8_t, resultlen);
@@ -138,6 +174,10 @@ static void test_hash_iov(void)
int ret;
size_t j;
+ if (!qcrypto_hash_supports(i)) {
+ continue;
+ }
+
ret = qcrypto_hash_bytesv(i,
iov, 3,
&result,
@@ -166,6 +206,10 @@ static void test_hash_digest(void)
char *digest;
size_t digestsize;
+ if (!qcrypto_hash_supports(i)) {
+ continue;
+ }
+
digestsize = qcrypto_hash_digest_len(i);
g_assert_cmpint(digestsize * 2, ==, strlen(expected_outputs[i]));
@@ -176,7 +220,7 @@ static void test_hash_digest(void)
&digest,
NULL);
g_assert(ret == 0);
- g_assert(g_str_equal(digest, expected_outputs[i]));
+ g_assert_cmpstr(digest, ==, expected_outputs[i]);
g_free(digest);
}
}
@@ -192,13 +236,17 @@ static void test_hash_base64(void)
int ret;
char *digest;
+ if (!qcrypto_hash_supports(i)) {
+ continue;
+ }
+
ret = qcrypto_hash_base64(i,
INPUT_TEXT,
strlen(INPUT_TEXT),
&digest,
NULL);
g_assert(ret == 0);
- g_assert(g_str_equal(digest, expected_outputs_b64[i]));
+ g_assert_cmpstr(digest, ==, expected_outputs_b64[i]);
g_free(digest);
}
}
diff --git a/tests/test-crypto-secret.c b/tests/test-crypto-secret.c
index aa26c20499..13fc6c4c75 100644
--- a/tests/test-crypto-secret.c
+++ b/tests/test-crypto-secret.c
@@ -19,7 +19,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "crypto/init.h"
#include "crypto/secret.h"
@@ -50,7 +49,7 @@ static void test_secret_indirect_good(void)
{
Object *sec;
char *fname = NULL;
- int fd = g_file_open_tmp("secretXXXXXX",
+ int fd = g_file_open_tmp("qemu-test-crypto-secret-XXXXXX",
&fname,
NULL);
@@ -75,6 +74,7 @@ static void test_secret_indirect_good(void)
object_unparent(sec);
g_free(pw);
close(fd);
+ unlink(fname);
g_free(fname);
}
@@ -97,7 +97,7 @@ static void test_secret_indirect_emptyfile(void)
{
Object *sec;
char *fname = NULL;
- int fd = g_file_open_tmp("secretXXXXXX",
+ int fd = g_file_open_tmp("qemu-test-crypto-secretXXXXXX",
&fname,
NULL);
@@ -120,6 +120,7 @@ static void test_secret_indirect_emptyfile(void)
object_unparent(sec);
g_free(pw);
close(fd);
+ unlink(fname);
g_free(fname);
}
diff --git a/tests/test-crypto-xts.c b/tests/test-crypto-xts.c
index 7f68b063cd..1f1412c45a 100644
--- a/tests/test-crypto-xts.c
+++ b/tests/test-crypto-xts.c
@@ -340,7 +340,7 @@ static void test_xts_aes_decrypt(const void *ctx,
static void test_xts(const void *opaque)
{
const QCryptoXTSTestData *data = opaque;
- unsigned char OUT[512], Torg[16], T[16];
+ unsigned char out[512], Torg[16], T[16];
uint64_t seq;
int j;
unsigned long len;
@@ -371,38 +371,38 @@ static void test_xts(const void *opaque)
xts_encrypt(&aesdata, &aestweak,
test_xts_aes_encrypt,
test_xts_aes_decrypt,
- T, data->PTLEN, OUT, data->PTX);
+ T, data->PTLEN, out, data->PTX);
} else {
xts_encrypt(&aesdata, &aestweak,
test_xts_aes_encrypt,
test_xts_aes_decrypt,
- T, len, OUT, data->PTX);
+ T, len, out, data->PTX);
xts_encrypt(&aesdata, &aestweak,
test_xts_aes_encrypt,
test_xts_aes_decrypt,
- T, len, &OUT[len], &data->PTX[len]);
+ T, len, &out[len], &data->PTX[len]);
}
- g_assert(memcmp(OUT, data->CTX, data->PTLEN) == 0);
+ g_assert(memcmp(out, data->CTX, data->PTLEN) == 0);
memcpy(T, Torg, sizeof(T));
if (j == 0) {
xts_decrypt(&aesdata, &aestweak,
test_xts_aes_encrypt,
test_xts_aes_decrypt,
- T, data->PTLEN, OUT, data->CTX);
+ T, data->PTLEN, out, data->CTX);
} else {
xts_decrypt(&aesdata, &aestweak,
test_xts_aes_encrypt,
test_xts_aes_decrypt,
- T, len, OUT, data->CTX);
+ T, len, out, data->CTX);
xts_decrypt(&aesdata, &aestweak,
test_xts_aes_encrypt,
test_xts_aes_decrypt,
- T, len, &OUT[len], &data->CTX[len]);
+ T, len, &out[len], &data->CTX[len]);
}
- g_assert(memcmp(OUT, data->PTX, data->PTLEN) == 0);
+ g_assert(memcmp(out, data->PTX, data->PTLEN) == 0);
}
}
diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index fb8f5b5321..64e3e95ce2 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -26,7 +26,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu/cutils.h"
diff --git a/tests/test-filter-mirror.c b/tests/test-filter-mirror.c
index f60bf2adbe..ffaaffabd0 100644
--- a/tests/test-filter-mirror.c
+++ b/tests/test-filter-mirror.c
@@ -9,7 +9,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "qemu/iov.h"
#include "qemu/sockets.h"
diff --git a/tests/test-filter-redirector.c b/tests/test-filter-redirector.c
index b93012ceae..c63b68f03a 100644
--- a/tests/test-filter-redirector.c
+++ b/tests/test-filter-redirector.c
@@ -51,7 +51,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "qemu/iov.h"
#include "qemu/sockets.h"
@@ -210,12 +209,8 @@ static void test_redirector_rx(void)
int main(int argc, char **argv)
{
- int ret;
-
g_test_init(&argc, &argv, NULL);
qtest_add_func("/netfilter/redirector_tx", test_redirector_tx);
qtest_add_func("/netfilter/redirector_rx", test_redirector_rx);
- ret = g_test_run();
-
- return ret;
+ return g_test_run();
}
diff --git a/tests/test-hbitmap.c b/tests/test-hbitmap.c
index abe1427917..c0e9895fb9 100644
--- a/tests/test-hbitmap.c
+++ b/tests/test-hbitmap.c
@@ -10,7 +10,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu/hbitmap.h"
#define LOG_BITS_PER_LONG (BITS_PER_LONG == 32 ? 5 : 6)
@@ -80,7 +79,7 @@ static void hbitmap_test_init(TestHBitmapData *data,
size_t n;
data->hb = hbitmap_alloc(size, granularity);
- n = (size + BITS_PER_LONG - 1) / BITS_PER_LONG;
+ n = DIV_ROUND_UP(size, BITS_PER_LONG);
if (n == 0) {
n = 1;
}
@@ -94,7 +93,7 @@ static void hbitmap_test_init(TestHBitmapData *data,
static inline size_t hbitmap_test_array_size(size_t bits)
{
- size_t n = (bits + BITS_PER_LONG - 1) / BITS_PER_LONG;
+ size_t n = DIV_ROUND_UP(bits, BITS_PER_LONG);
return n ? n : 1;
}
@@ -186,7 +185,7 @@ static void hbitmap_test_reset_all(TestHBitmapData *data)
hbitmap_reset_all(data->hb);
- n = (data->size + BITS_PER_LONG - 1) / BITS_PER_LONG;
+ n = DIV_ROUND_UP(data->size, BITS_PER_LONG);
if (n == 0) {
n = 1;
}
diff --git a/tests/test-int128.c b/tests/test-int128.c
index cacf6beac8..4390123bd3 100644
--- a/tests/test-int128.c
+++ b/tests/test-int128.c
@@ -7,7 +7,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu/int128.h"
/* clang doesn't support __noclone__ but it does have a mechanism for
diff --git a/tests/test-io-channel-socket.c b/tests/test-io-channel-socket.c
index 855306b8dd..f73e063d7d 100644
--- a/tests/test-io-channel-socket.c
+++ b/tests/test-io-channel-socket.c
@@ -383,7 +383,7 @@ static void test_io_channel_unix(bool async)
qapi_free_SocketAddress(listen_addr);
qapi_free_SocketAddress(connect_addr);
- unlink(TEST_SOCKET);
+ g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS) == FALSE);
}
diff --git a/tests/test-io-task.c b/tests/test-io-task.c
index 5a9775086c..e091c12e10 100644
--- a/tests/test-io-task.c
+++ b/tests/test-io-task.c
@@ -19,7 +19,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "io/task.h"
#include "qapi/error.h"
@@ -111,7 +110,7 @@ static void test_task_data_free(void)
}
-static void test_task_error(void)
+static void test_task_failure(void)
{
QIOTask *task;
Object *obj = object_new(TYPE_DUMMY);
@@ -215,7 +214,7 @@ static void test_task_thread_complete(void)
}
-static void test_task_thread_error(void)
+static void test_task_thread_failure(void)
{
QIOTask *task;
Object *obj = object_new(TYPE_DUMMY);
@@ -263,8 +262,8 @@ int main(int argc, char **argv)
type_register_static(&dummy_info);
g_test_add_func("/crypto/task/complete", test_task_complete);
g_test_add_func("/crypto/task/datafree", test_task_data_free);
- g_test_add_func("/crypto/task/error", test_task_error);
+ g_test_add_func("/crypto/task/failure", test_task_failure);
g_test_add_func("/crypto/task/thread_complete", test_task_thread_complete);
- g_test_add_func("/crypto/task/thread_error", test_task_thread_error);
+ g_test_add_func("/crypto/task/thread_failure", test_task_thread_failure);
return g_test_run();
}
diff --git a/tests/test-iov.c b/tests/test-iov.c
index 3f25268dd4..46ae25efd6 100644
--- a/tests/test-iov.c
+++ b/tests/test-iov.c
@@ -1,5 +1,4 @@
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "qemu/iov.h"
#include "qemu/sockets.h"
diff --git a/tests/test-logging.c b/tests/test-logging.c
index ac8deedc9a..a12585f70a 100644
--- a/tests/test-logging.c
+++ b/tests/test-logging.c
@@ -25,14 +25,17 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
+#include <glib/gstdio.h>
#include "qemu-common.h"
-#include "include/qemu/log.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
static void test_parse_range(void)
{
- qemu_set_dfilter_ranges("0x1000+0x100");
+ Error *err = NULL;
+
+ qemu_set_dfilter_ranges("0x1000+0x100", &error_abort);
g_assert_false(qemu_log_in_addr_range(0xfff));
g_assert(qemu_log_in_addr_range(0x1000));
@@ -40,102 +43,101 @@ static void test_parse_range(void)
g_assert(qemu_log_in_addr_range(0x10ff));
g_assert_false(qemu_log_in_addr_range(0x1100));
- qemu_set_dfilter_ranges("0x1000-0x100");
+ qemu_set_dfilter_ranges("0x1000-0x100", &error_abort);
g_assert_false(qemu_log_in_addr_range(0x1001));
g_assert(qemu_log_in_addr_range(0x1000));
g_assert(qemu_log_in_addr_range(0x0f01));
g_assert_false(qemu_log_in_addr_range(0x0f00));
- qemu_set_dfilter_ranges("0x1000..0x1100");
+ qemu_set_dfilter_ranges("0x1000..0x1100", &error_abort);
g_assert_false(qemu_log_in_addr_range(0xfff));
g_assert(qemu_log_in_addr_range(0x1000));
g_assert(qemu_log_in_addr_range(0x1100));
g_assert_false(qemu_log_in_addr_range(0x1101));
- qemu_set_dfilter_ranges("0x1000..0x1000");
+ qemu_set_dfilter_ranges("0x1000..0x1000", &error_abort);
g_assert_false(qemu_log_in_addr_range(0xfff));
g_assert(qemu_log_in_addr_range(0x1000));
g_assert_false(qemu_log_in_addr_range(0x1001));
- qemu_set_dfilter_ranges("0x1000+0x100,0x2100-0x100,0x3000..0x3100");
+ qemu_set_dfilter_ranges("0x1000+0x100,0x2100-0x100,0x3000..0x3100",
+ &error_abort);
g_assert(qemu_log_in_addr_range(0x1050));
g_assert(qemu_log_in_addr_range(0x2050));
g_assert(qemu_log_in_addr_range(0x3050));
-}
-#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
-static void test_parse_invalid_range_subprocess(void)
-{
- qemu_set_dfilter_ranges("0x1000+onehundred");
-}
-static void test_parse_invalid_range(void)
-{
- g_test_trap_subprocess("/logging/parse_invalid_range/subprocess", 0, 0);
- g_test_trap_assert_failed();
- g_test_trap_assert_stdout("");
- g_test_trap_assert_stderr("*Failed to parse range in: 0x1000+onehundred\n");
-}
-static void test_parse_zero_range_subprocess(void)
-{
- qemu_set_dfilter_ranges("0x1000+0");
-}
-static void test_parse_zero_range(void)
-{
- g_test_trap_subprocess("/logging/parse_zero_range/subprocess", 0, 0);
- g_test_trap_assert_failed();
- g_test_trap_assert_stdout("");
- g_test_trap_assert_stderr("*Failed to parse range in: 0x1000+0\n");
-}
+ qemu_set_dfilter_ranges("0xffffffffffffffff-1", &error_abort);
+ g_assert(qemu_log_in_addr_range(UINT64_MAX));
+ g_assert_false(qemu_log_in_addr_range(UINT64_MAX - 1));
-/* As the only real failure from a bad log filename path spec is
- * reporting to the user we have to use the g_test_trap_subprocess
- * mechanism and check no errors reported on stderr.
- */
-static void test_parse_path_subprocess(void)
-{
- /* All these should work without issue */
- qemu_set_log_filename("/tmp/qemu.log");
- qemu_set_log_filename("/tmp/qemu-%d.log");
- qemu_set_log_filename("/tmp/qemu.log.%d");
+ qemu_set_dfilter_ranges("0..0xffffffffffffffff", &err);
+ g_assert(qemu_log_in_addr_range(0));
+ g_assert(qemu_log_in_addr_range(UINT64_MAX));
+
+ qemu_set_dfilter_ranges("2..1", &err);
+ error_free_or_abort(&err);
+
+ qemu_set_dfilter_ranges("0x1000+onehundred", &err);
+ error_free_or_abort(&err);
+
+ qemu_set_dfilter_ranges("0x1000+0", &err);
+ error_free_or_abort(&err);
}
-static void test_parse_path(void)
+
+static void set_log_path_tmp(char const *dir, char const *tpl, Error **errp)
{
- g_test_trap_subprocess ("/logging/parse_path/subprocess", 0, 0);
- g_test_trap_assert_passed();
- g_test_trap_assert_stdout("");
- g_test_trap_assert_stderr("");
+ gchar *file_path = g_build_filename(dir, tpl, NULL);
+
+ qemu_set_log_filename(file_path, errp);
+ g_free(file_path);
}
-static void test_parse_invalid_path_subprocess(void)
+
+static void test_parse_path(gconstpointer data)
{
- qemu_set_log_filename("/tmp/qemu-%d%d.log");
+ gchar const *tmp_path = data;
+ Error *err = NULL;
+
+ set_log_path_tmp(tmp_path, "qemu.log", &error_abort);
+ set_log_path_tmp(tmp_path, "qemu-%d.log", &error_abort);
+ set_log_path_tmp(tmp_path, "qemu.log.%d", &error_abort);
+
+ set_log_path_tmp(tmp_path, "qemu-%d%d.log", &err);
+ error_free_or_abort(&err);
}
-static void test_parse_invalid_path(void)
+
+/* Remove a directory and all its entries (non-recursive). */
+static void rmdir_full(gchar const *root)
{
- g_test_trap_subprocess ("/logging/parse_invalid_path/subprocess", 0, 0);
- g_test_trap_assert_passed();
- g_test_trap_assert_stdout("");
- g_test_trap_assert_stderr("Bad logfile format: /tmp/qemu-%d%d.log\n");
+ GDir *root_gdir = g_dir_open(root, 0, NULL);
+ gchar const *entry_name;
+
+ g_assert_nonnull(root_gdir);
+ while ((entry_name = g_dir_read_name(root_gdir)) != NULL) {
+ gchar *entry_path = g_build_filename(root, entry_name, NULL);
+ g_assert(g_remove(entry_path) == 0);
+ g_free(entry_path);
+ }
+ g_dir_close(root_gdir);
+ g_assert(g_rmdir(root) == 0);
}
-#endif /* CONFIG_HAS_GLIB_SUBPROCESS_TESTS */
int main(int argc, char **argv)
{
+ gchar *tmp_path = g_dir_make_tmp("qemu-test-logging.XXXXXX", NULL);
+ int rc;
+
g_test_init(&argc, &argv, NULL);
+ g_assert_nonnull(tmp_path);
g_test_add_func("/logging/parse_range", test_parse_range);
-#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
- g_test_add_func("/logging/parse_invalid_range/subprocess", test_parse_invalid_range_subprocess);
- g_test_add_func("/logging/parse_invalid_range", test_parse_invalid_range);
- g_test_add_func("/logging/parse_zero_range/subprocess", test_parse_zero_range_subprocess);
- g_test_add_func("/logging/parse_zero_range", test_parse_zero_range);
- g_test_add_func("/logging/parse_path", test_parse_path);
- g_test_add_func("/logging/parse_path/subprocess", test_parse_path_subprocess);
- g_test_add_func("/logging/parse_invalid_path", test_parse_invalid_path);
- g_test_add_func("/logging/parse_invalid_path/subprocess", test_parse_invalid_path_subprocess);
-#endif
-
- return g_test_run();
+ g_test_add_data_func("/logging/parse_path", tmp_path, test_parse_path);
+
+ rc = g_test_run();
+
+ rmdir_full(tmp_path);
+ g_free(tmp_path);
+ return rc;
}
diff --git a/tests/test-mul64.c b/tests/test-mul64.c
index 1282ec5a22..9be775d084 100644
--- a/tests/test-mul64.c
+++ b/tests/test-mul64.c
@@ -7,7 +7,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu/host-utils.h"
diff --git a/tests/test-netfilter.c b/tests/test-netfilter.c
index 7d105c3232..8b5a9b21b5 100644
--- a/tests/test-netfilter.c
+++ b/tests/test-netfilter.c
@@ -9,7 +9,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* add a netfilter to a netdev and then remove it */
diff --git a/tests/test-opts-visitor.c b/tests/test-opts-visitor.c
index 008e677388..0a9e75f1bb 100644
--- a/tests/test-opts-visitor.c
+++ b/tests/test-opts-visitor.c
@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu/config-file.h" /* qemu_add_opts() */
#include "qemu/option.h" /* qemu_opts_parse() */
@@ -38,16 +37,15 @@ setup_fixture(OptsVisitorFixture *f, gconstpointer test_data)
{
const char *opts_string = test_data;
QemuOpts *opts;
- OptsVisitor *ov;
+ Visitor *v;
opts = qemu_opts_parse(qemu_find_opts("userdef"), opts_string, false,
NULL);
g_assert(opts != NULL);
- ov = opts_visitor_new(opts);
- visit_type_UserDefOptions(opts_get_visitor(ov), NULL, &f->userdef,
- &f->err);
- opts_visitor_cleanup(ov);
+ v = opts_visitor_new(opts);
+ visit_type_UserDefOptions(v, NULL, &f->userdef, &f->err);
+ visit_free(v);
qemu_opts_del(opts);
}
diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c
index f0cc31e113..48e5b7315f 100644
--- a/tests/test-qdev-global-props.c
+++ b/tests/test-qdev-global-props.c
@@ -23,7 +23,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "hw/qdev.h"
#include "qom/object.h"
diff --git a/tests/test-qdist.c b/tests/test-qdist.c
new file mode 100644
index 0000000000..9541ce31eb
--- /dev/null
+++ b/tests/test-qdist.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2016, Emilio G. Cota <cota@braap.org>
+ *
+ * License: GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qemu/qdist.h"
+
+#include <math.h>
+
+struct entry_desc {
+ double x;
+ unsigned long count;
+
+ /* 0 prints a space, 1-8 prints from qdist_blocks[] */
+ int fill_code;
+};
+
+/* See: https://en.wikipedia.org/wiki/Block_Elements */
+static const gunichar qdist_blocks[] = {
+ 0x2581,
+ 0x2582,
+ 0x2583,
+ 0x2584,
+ 0x2585,
+ 0x2586,
+ 0x2587,
+ 0x2588
+};
+
+#define QDIST_NR_BLOCK_CODES ARRAY_SIZE(qdist_blocks)
+
+static char *pr_hist(const struct entry_desc *darr, size_t n)
+{
+ GString *s = g_string_new("");
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ int fill = darr[i].fill_code;
+
+ if (fill) {
+ assert(fill <= QDIST_NR_BLOCK_CODES);
+ g_string_append_unichar(s, qdist_blocks[fill - 1]);
+ } else {
+ g_string_append_c(s, ' ');
+ }
+ }
+ return g_string_free(s, FALSE);
+}
+
+static void
+histogram_check(const struct qdist *dist, const struct entry_desc *darr,
+ size_t n, size_t n_bins)
+{
+ char *pr = qdist_pr_plain(dist, n_bins);
+ char *str = pr_hist(darr, n);
+
+ g_assert_cmpstr(pr, ==, str);
+ g_free(pr);
+ g_free(str);
+}
+
+static void histogram_check_single_full(const struct qdist *dist, size_t n_bins)
+{
+ struct entry_desc desc = { .fill_code = 8 };
+
+ histogram_check(dist, &desc, 1, n_bins);
+}
+
+static void
+entries_check(const struct qdist *dist, const struct entry_desc *darr, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ struct qdist_entry *e = &dist->entries[i];
+
+ g_assert_cmpuint(e->count, ==, darr[i].count);
+ }
+}
+
+static void
+entries_insert(struct qdist *dist, const struct entry_desc *darr, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ qdist_add(dist, darr[i].x, darr[i].count);
+ }
+}
+
+static void do_test_bin(const struct entry_desc *a, size_t n_a,
+ const struct entry_desc *b, size_t n_b)
+{
+ struct qdist qda;
+ struct qdist qdb;
+
+ qdist_init(&qda);
+
+ entries_insert(&qda, a, n_a);
+ qdist_inc(&qda, a[0].x);
+ qdist_add(&qda, a[0].x, -1);
+
+ g_assert_cmpuint(qdist_unique_entries(&qda), ==, n_a);
+ g_assert_cmpfloat(qdist_xmin(&qda), ==, a[0].x);
+ g_assert_cmpfloat(qdist_xmax(&qda), ==, a[n_a - 1].x);
+ histogram_check(&qda, a, n_a, 0);
+ histogram_check(&qda, a, n_a, n_a);
+
+ qdist_bin__internal(&qdb, &qda, n_b);
+ g_assert_cmpuint(qdb.n, ==, n_b);
+ entries_check(&qdb, b, n_b);
+ g_assert_cmpuint(qdist_sample_count(&qda), ==, qdist_sample_count(&qdb));
+ /*
+ * No histogram_check() for $qdb, since we'd rebin it and that is a bug.
+ * Instead, regenerate it from $qda.
+ */
+ histogram_check(&qda, b, n_b, n_b);
+
+ qdist_destroy(&qdb);
+ qdist_destroy(&qda);
+}
+
+static void do_test_pr(uint32_t opt)
+{
+ static const struct entry_desc desc[] = {
+ [0] = { 1, 900, 8 },
+ [1] = { 2, 1, 1 },
+ [2] = { 3, 2, 1 }
+ };
+ static const char border[] = "|";
+ const char *llabel = NULL;
+ const char *rlabel = NULL;
+ struct qdist dist;
+ GString *s;
+ char *str;
+ char *pr;
+ size_t n;
+
+ n = ARRAY_SIZE(desc);
+ qdist_init(&dist);
+
+ entries_insert(&dist, desc, n);
+ histogram_check(&dist, desc, n, 0);
+
+ s = g_string_new("");
+
+ if (opt & QDIST_PR_LABELS) {
+ unsigned int lopts = opt & (QDIST_PR_NODECIMAL |
+ QDIST_PR_PERCENT |
+ QDIST_PR_100X |
+ QDIST_PR_NOBINRANGE);
+
+ if (lopts == 0) {
+ llabel = "[1.0,1.7)";
+ rlabel = "[2.3,3.0]";
+ } else if (lopts == QDIST_PR_NODECIMAL) {
+ llabel = "[1,2)";
+ rlabel = "[2,3]";
+ } else if (lopts == (QDIST_PR_PERCENT | QDIST_PR_NODECIMAL)) {
+ llabel = "[1,2)%";
+ rlabel = "[2,3]%";
+ } else if (lopts == QDIST_PR_100X) {
+ llabel = "[100.0,166.7)";
+ rlabel = "[233.3,300.0]";
+ } else if (lopts == (QDIST_PR_NOBINRANGE | QDIST_PR_NODECIMAL)) {
+ llabel = "1";
+ rlabel = "3";
+ } else {
+ g_assert_cmpstr("BUG", ==, "This is not meant to be exhaustive");
+ }
+ }
+
+ if (llabel) {
+ g_string_append(s, llabel);
+ }
+ if (opt & QDIST_PR_BORDER) {
+ g_string_append(s, border);
+ }
+
+ str = pr_hist(desc, n);
+ g_string_append(s, str);
+ g_free(str);
+
+ if (opt & QDIST_PR_BORDER) {
+ g_string_append(s, border);
+ }
+ if (rlabel) {
+ g_string_append(s, rlabel);
+ }
+
+ str = g_string_free(s, FALSE);
+ pr = qdist_pr(&dist, n, opt);
+ g_assert_cmpstr(pr, ==, str);
+ g_free(pr);
+ g_free(str);
+
+ qdist_destroy(&dist);
+}
+
+static inline void do_test_pr_label(uint32_t opt)
+{
+ opt |= QDIST_PR_LABELS;
+ do_test_pr(opt);
+}
+
+static void test_pr(void)
+{
+ do_test_pr(0);
+
+ do_test_pr(QDIST_PR_BORDER);
+
+ /* 100X should be ignored because we're not setting LABELS */
+ do_test_pr(QDIST_PR_100X);
+
+ do_test_pr_label(0);
+ do_test_pr_label(QDIST_PR_NODECIMAL);
+ do_test_pr_label(QDIST_PR_PERCENT | QDIST_PR_NODECIMAL);
+ do_test_pr_label(QDIST_PR_100X);
+ do_test_pr_label(QDIST_PR_NOBINRANGE | QDIST_PR_NODECIMAL);
+}
+
+static void test_bin_shrink(void)
+{
+ static const struct entry_desc a[] = {
+ [0] = { 0.0, 42922, 7 },
+ [1] = { 0.25, 47834, 8 },
+ [2] = { 0.50, 26628, 0 },
+ [3] = { 0.625, 597, 4 },
+ [4] = { 0.75, 10298, 1 },
+ [5] = { 0.875, 22, 2 },
+ [6] = { 1.0, 2771, 1 }
+ };
+ static const struct entry_desc b[] = {
+ [0] = { 0.0, 42922, 7 },
+ [1] = { 0.25, 47834, 8 },
+ [2] = { 0.50, 27225, 3 },
+ [3] = { 0.75, 13091, 1 }
+ };
+
+ return do_test_bin(a, ARRAY_SIZE(a), b, ARRAY_SIZE(b));
+}
+
+static void test_bin_expand(void)
+{
+ static const struct entry_desc a[] = {
+ [0] = { 0.0, 11713, 5 },
+ [1] = { 0.25, 20294, 0 },
+ [2] = { 0.50, 17266, 8 },
+ [3] = { 0.625, 1506, 0 },
+ [4] = { 0.75, 10355, 6 },
+ [5] = { 0.833, 2, 1 },
+ [6] = { 0.875, 99, 4 },
+ [7] = { 1.0, 4301, 2 }
+ };
+ static const struct entry_desc b[] = {
+ [0] = { 0.0, 11713, 5 },
+ [1] = { 0.0, 0, 0 },
+ [2] = { 0.0, 20294, 8 },
+ [3] = { 0.0, 0, 0 },
+ [4] = { 0.0, 0, 0 },
+ [5] = { 0.0, 17266, 6 },
+ [6] = { 0.0, 1506, 1 },
+ [7] = { 0.0, 10355, 4 },
+ [8] = { 0.0, 101, 1 },
+ [9] = { 0.0, 4301, 2 }
+ };
+
+ return do_test_bin(a, ARRAY_SIZE(a), b, ARRAY_SIZE(b));
+}
+
+static void test_bin_precision(void)
+{
+ static const struct entry_desc a[] = {
+ [0] = { 0, 213549, 8 },
+ [1] = { 1, 70, 1 },
+ };
+ static const struct entry_desc b[] = {
+ [0] = { 0, 213549, 8 },
+ [1] = { 0, 70, 1 },
+ };
+
+ return do_test_bin(a, ARRAY_SIZE(a), b, ARRAY_SIZE(b));
+}
+
+static void test_bin_simple(void)
+{
+ static const struct entry_desc a[] = {
+ [0] = { 10, 101, 8 },
+ [1] = { 11, 0, 0 },
+ [2] = { 12, 2, 1 }
+ };
+ static const struct entry_desc b[] = {
+ [0] = { 0, 101, 8 },
+ [1] = { 0, 0, 0 },
+ [2] = { 0, 0, 0 },
+ [3] = { 0, 0, 0 },
+ [4] = { 0, 2, 1 }
+ };
+
+ return do_test_bin(a, ARRAY_SIZE(a), b, ARRAY_SIZE(b));
+}
+
+static void test_single_full(void)
+{
+ struct qdist dist;
+
+ qdist_init(&dist);
+
+ qdist_add(&dist, 3, 102);
+ g_assert_cmpfloat(qdist_avg(&dist), ==, 3);
+ g_assert_cmpfloat(qdist_xmin(&dist), ==, 3);
+ g_assert_cmpfloat(qdist_xmax(&dist), ==, 3);
+
+ histogram_check_single_full(&dist, 0);
+ histogram_check_single_full(&dist, 1);
+ histogram_check_single_full(&dist, 10);
+
+ qdist_destroy(&dist);
+}
+
+static void test_single_empty(void)
+{
+ struct qdist dist;
+ char *pr;
+
+ qdist_init(&dist);
+
+ qdist_add(&dist, 3, 0);
+ g_assert_cmpuint(qdist_sample_count(&dist), ==, 0);
+ g_assert(isnan(qdist_avg(&dist)));
+ g_assert_cmpfloat(qdist_xmin(&dist), ==, 3);
+ g_assert_cmpfloat(qdist_xmax(&dist), ==, 3);
+
+ pr = qdist_pr_plain(&dist, 0);
+ g_assert_cmpstr(pr, ==, " ");
+ g_free(pr);
+
+ pr = qdist_pr_plain(&dist, 1);
+ g_assert_cmpstr(pr, ==, " ");
+ g_free(pr);
+
+ pr = qdist_pr_plain(&dist, 2);
+ g_assert_cmpstr(pr, ==, " ");
+ g_free(pr);
+
+ qdist_destroy(&dist);
+}
+
+static void test_none(void)
+{
+ struct qdist dist;
+ char *pr;
+
+ qdist_init(&dist);
+
+ g_assert(isnan(qdist_avg(&dist)));
+ g_assert(isnan(qdist_xmin(&dist)));
+ g_assert(isnan(qdist_xmax(&dist)));
+
+ pr = qdist_pr_plain(&dist, 0);
+ g_assert_cmpstr(pr, ==, "(empty)");
+ g_free(pr);
+
+ pr = qdist_pr_plain(&dist, 2);
+ g_assert_cmpstr(pr, ==, "(empty)");
+ g_free(pr);
+
+ pr = qdist_pr(&dist, 0, QDIST_PR_BORDER);
+ g_assert_cmpstr(pr, ==, "(empty)");
+ g_free(pr);
+
+ qdist_destroy(&dist);
+}
+
+int main(int argc, char *argv[])
+{
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/qdist/none", test_none);
+ g_test_add_func("/qdist/single/empty", test_single_empty);
+ g_test_add_func("/qdist/single/full", test_single_full);
+ g_test_add_func("/qdist/binning/simple", test_bin_simple);
+ g_test_add_func("/qdist/binning/precision", test_bin_precision);
+ g_test_add_func("/qdist/binning/expand", test_bin_expand);
+ g_test_add_func("/qdist/binning/shrink", test_bin_shrink);
+ g_test_add_func("/qdist/pr", test_pr);
+ return g_test_run();
+}
diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
index 32abed5ea1..a505a3e059 100644
--- a/tests/test-qemu-opts.c
+++ b/tests/test-qemu-opts.c
@@ -12,7 +12,6 @@
#include "qapi/qmp/qstring.h"
#include "qemu/config-file.h"
-#include <glib.h>
static QemuOptsList opts_list_01 = {
.name = "opts_list_01",
diff --git a/tests/test-qga.c b/tests/test-qga.c
index 72a89dec23..dac8fb8c0a 100644
--- a/tests/test-qga.c
+++ b/tests/test-qga.c
@@ -1,6 +1,5 @@
#include "qemu/osdep.h"
#include <locale.h>
-#include <glib.h>
#include <glib/gstdio.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -692,28 +691,11 @@ static void test_qga_blacklist(gconstpointer data)
static void test_qga_config(gconstpointer data)
{
GError *error = NULL;
- char *cwd, *cmd, *out, *err, *str, **strv, *conf, **argv = NULL;
+ char *cwd, *cmd, *out, *err, *str, **strv, **argv = NULL;
char *env[2];
- int status, tmp;
+ int status;
gsize n;
GKeyFile *kf;
- const char *qga_config =
- "[general]\n"
- "daemon=false\n"
- "method=virtio-serial\n"
- "path=/path/to/org.qemu.guest_agent.0\n"
- "pidfile=/var/foo/qemu-ga.pid\n"
- "statedir=/var/state\n"
- "verbose=true\n"
- "blacklist=guest-ping;guest-get-time\n";
-
- tmp = g_file_open_tmp(NULL, &conf, &error);
- g_assert_no_error(error);
- g_assert_cmpint(tmp, >=, 0);
- g_assert_cmpstr(conf, !=, "");
-
- g_file_set_contents(conf, qga_config, -1, &error);
- g_assert_no_error(error);
cwd = g_get_current_dir();
cmd = g_strdup_printf("%s%cqemu-ga -D",
@@ -721,7 +703,8 @@ static void test_qga_config(gconstpointer data)
g_shell_parse_argv(cmd, NULL, &argv, &error);
g_assert_no_error(error);
- env[0] = g_strdup_printf("QGA_CONF=%s", conf);
+ env[0] = g_strdup_printf("QGA_CONF=tests%cdata%ctest-qga-config",
+ G_DIR_SEPARATOR, G_DIR_SEPARATOR);
env[1] = NULL;
g_spawn_sync(NULL, argv, env, 0,
NULL, NULL, &out, &err, &status, &error);
@@ -776,11 +759,8 @@ static void test_qga_config(gconstpointer data)
g_free(out);
g_free(err);
- g_free(conf);
g_free(env[0]);
g_key_file_free(kf);
-
- close(tmp);
}
static void test_qga_fsfreeze_status(gconstpointer fix)
@@ -823,6 +803,84 @@ static void test_qga_fsfreeze_and_thaw(gconstpointer fix)
QDECREF(ret);
}
+static void test_qga_guest_exec(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret, *val;
+ const gchar *out;
+ guchar *decoded;
+ int64_t pid, now, exitcode;
+ gsize len;
+ bool exited;
+
+ /* exec 'echo foo bar' */
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {"
+ " 'path': '/bin/echo', 'arg': [ '-n', '\" test_str \"' ],"
+ " 'capture-output': true } }");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ val = qdict_get_qdict(ret, "return");
+ pid = qdict_get_int(val, "pid");
+ g_assert_cmpint(pid, >, 0);
+ QDECREF(ret);
+
+ /* wait for completion */
+ now = g_get_monotonic_time();
+ do {
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec-status',"
+ " 'arguments': { 'pid': %" PRId64 " } }", pid);
+ g_assert_nonnull(ret);
+ val = qdict_get_qdict(ret, "return");
+ exited = qdict_get_bool(val, "exited");
+ if (!exited) {
+ QDECREF(ret);
+ }
+ } while (!exited &&
+ g_get_monotonic_time() < now + 5 * G_TIME_SPAN_SECOND);
+ g_assert(exited);
+
+ /* check stdout */
+ exitcode = qdict_get_int(val, "exitcode");
+ g_assert_cmpint(exitcode, ==, 0);
+ out = qdict_get_str(val, "out-data");
+ decoded = g_base64_decode(out, &len);
+ g_assert_cmpint(len, ==, 12);
+ g_assert_cmpstr((char *)decoded, ==, "\" test_str \"");
+ g_free(decoded);
+ QDECREF(ret);
+}
+
+static void test_qga_guest_exec_invalid(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret, *error;
+ const gchar *class, *desc;
+
+ /* invalid command */
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {"
+ " 'path': '/bin/invalid-cmd42' } }");
+ g_assert_nonnull(ret);
+ error = qdict_get_qdict(ret, "error");
+ g_assert_nonnull(error);
+ class = qdict_get_str(error, "class");
+ desc = qdict_get_str(error, "desc");
+ g_assert_cmpstr(class, ==, "GenericError");
+ g_assert_cmpint(strlen(desc), >, 0);
+ QDECREF(ret);
+
+ /* invalid pid */
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec-status',"
+ " 'arguments': { 'pid': 0 } }");
+ g_assert_nonnull(ret);
+ error = qdict_get_qdict(ret, "error");
+ g_assert_nonnull(error);
+ class = qdict_get_str(error, "class");
+ desc = qdict_get_str(error, "desc");
+ g_assert_cmpstr(class, ==, "GenericError");
+ g_assert_cmpint(strlen(desc), >, 0);
+ QDECREF(ret);
+}
+
int main(int argc, char **argv)
{
TestFixture fix;
@@ -853,6 +911,9 @@ int main(int argc, char **argv)
g_test_add_data_func("/qga/blacklist", NULL, test_qga_blacklist);
g_test_add_data_func("/qga/config", NULL, test_qga_config);
+ g_test_add_data_func("/qga/guest-exec", &fix, test_qga_guest_exec);
+ g_test_add_data_func("/qga/guest-exec-invalid", &fix,
+ test_qga_guest_exec_invalid);
if (g_getenv("QGA_TEST_SIDE_EFFECTING")) {
g_test_add_data_func("/qga/fsfreeze-and-thaw", &fix,
diff --git a/tests/test-qht-par.c b/tests/test-qht-par.c
new file mode 100644
index 0000000000..d8a83caf5c
--- /dev/null
+++ b/tests/test-qht-par.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016, Emilio G. Cota <cota@braap.org>
+ *
+ * License: GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+
+#define TEST_QHT_STRING "tests/qht-bench 1>/dev/null 2>&1 -R -S0.1 -D10000 -N1 "
+
+static void test_qht(int n_threads, int update_rate, int duration)
+{
+ char *str;
+ int rc;
+
+ str = g_strdup_printf(TEST_QHT_STRING "-n %d -u %d -d %d",
+ n_threads, update_rate, duration);
+ rc = system(str);
+ g_free(str);
+ g_assert_cmpint(rc, ==, 0);
+}
+
+static void test_2th0u1s(void)
+{
+ test_qht(2, 0, 1);
+}
+
+static void test_2th20u1s(void)
+{
+ test_qht(2, 20, 1);
+}
+
+static void test_2th0u5s(void)
+{
+ test_qht(2, 0, 5);
+}
+
+static void test_2th20u5s(void)
+{
+ test_qht(2, 20, 5);
+}
+
+int main(int argc, char *argv[])
+{
+ g_test_init(&argc, &argv, NULL);
+
+ if (g_test_quick()) {
+ g_test_add_func("/qht/parallel/2threads-0%updates-1s", test_2th0u1s);
+ g_test_add_func("/qht/parallel/2threads-20%updates-1s", test_2th20u1s);
+ } else {
+ g_test_add_func("/qht/parallel/2threads-0%updates-5s", test_2th0u5s);
+ g_test_add_func("/qht/parallel/2threads-20%updates-5s", test_2th20u5s);
+ }
+ return g_test_run();
+}
diff --git a/tests/test-qht.c b/tests/test-qht.c
new file mode 100644
index 0000000000..46a64b6731
--- /dev/null
+++ b/tests/test-qht.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016, Emilio G. Cota <cota@braap.org>
+ *
+ * License: GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qemu/qht.h"
+
+#define N 5000
+
+static struct qht ht;
+static int32_t arr[N * 2];
+
+static bool is_equal(const void *obj, const void *userp)
+{
+ const int32_t *a = obj;
+ const int32_t *b = userp;
+
+ return *a == *b;
+}
+
+static void insert(int a, int b)
+{
+ int i;
+
+ for (i = a; i < b; i++) {
+ uint32_t hash;
+
+ arr[i] = i;
+ hash = i;
+
+ qht_insert(&ht, &arr[i], hash);
+ }
+}
+
+static void rm(int init, int end)
+{
+ int i;
+
+ for (i = init; i < end; i++) {
+ uint32_t hash;
+
+ hash = arr[i];
+ g_assert_true(qht_remove(&ht, &arr[i], hash));
+ }
+}
+
+static void check(int a, int b, bool expected)
+{
+ struct qht_stats stats;
+ int i;
+
+ for (i = a; i < b; i++) {
+ void *p;
+ uint32_t hash;
+ int32_t val;
+
+ val = i;
+ hash = i;
+ p = qht_lookup(&ht, is_equal, &val, hash);
+ g_assert_true(!!p == expected);
+ }
+ qht_statistics_init(&ht, &stats);
+ if (stats.used_head_buckets) {
+ g_assert_cmpfloat(qdist_avg(&stats.chain), >=, 1.0);
+ }
+ g_assert_cmpuint(stats.head_buckets, >, 0);
+ qht_statistics_destroy(&stats);
+}
+
+static void count_func(struct qht *ht, void *p, uint32_t hash, void *userp)
+{
+ unsigned int *curr = userp;
+
+ (*curr)++;
+}
+
+static void check_n(size_t expected)
+{
+ struct qht_stats stats;
+
+ qht_statistics_init(&ht, &stats);
+ g_assert_cmpuint(stats.entries, ==, expected);
+ qht_statistics_destroy(&stats);
+}
+
+static void iter_check(unsigned int count)
+{
+ unsigned int curr = 0;
+
+ qht_iter(&ht, count_func, &curr);
+ g_assert_cmpuint(curr, ==, count);
+}
+
+static void qht_do_test(unsigned int mode, size_t init_entries)
+{
+ /* under KVM we might fetch stats from an uninitialized qht */
+ check_n(0);
+
+ qht_init(&ht, 0, mode);
+
+ check_n(0);
+ insert(0, N);
+ check(0, N, true);
+ check_n(N);
+ check(-N, -1, false);
+ iter_check(N);
+
+ rm(101, 102);
+ check_n(N - 1);
+ insert(N, N * 2);
+ check_n(N + N - 1);
+ rm(N, N * 2);
+ check_n(N - 1);
+ insert(101, 102);
+ check_n(N);
+
+ rm(10, 200);
+ check_n(N - 190);
+ insert(150, 200);
+ check_n(N - 190 + 50);
+ insert(10, 150);
+ check_n(N);
+
+ rm(1, 2);
+ check_n(N - 1);
+ qht_reset_size(&ht, 0);
+ check_n(0);
+ check(0, N, false);
+
+ qht_destroy(&ht);
+}
+
+static void qht_test(unsigned int mode)
+{
+ qht_do_test(mode, 0);
+ qht_do_test(mode, 1);
+ qht_do_test(mode, 2);
+ qht_do_test(mode, 8);
+ qht_do_test(mode, 16);
+ qht_do_test(mode, 8192);
+ qht_do_test(mode, 16384);
+}
+
+static void test_default(void)
+{
+ qht_test(0);
+}
+
+static void test_resize(void)
+{
+ qht_test(QHT_MODE_AUTO_RESIZE);
+}
+
+int main(int argc, char *argv[])
+{
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/qht/mode/default", test_default);
+ g_test_add_func("/qht/mode/resize", test_resize);
+ return g_test_run();
+}
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index 14a9ebbd5a..261fd9e313 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -1,5 +1,4 @@
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "qapi/qmp/types.h"
#include "test-qmp-commands.h"
@@ -60,6 +59,14 @@ QObject *qmp_guest_sync(QObject *arg, Error **errp)
return arg;
}
+void qmp_boxed_struct(UserDefZero *arg, Error **errp)
+{
+}
+
+void qmp_boxed_union(UserDefNativeListUnion *arg, Error **errp)
+{
+}
+
__org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
__org_qemu_x_StructList *b,
__org_qemu_x_Union2 *c,
@@ -96,7 +103,7 @@ static void test_dispatch_cmd(void)
}
/* test commands that return an error due to invalid parameters */
-static void test_dispatch_cmd_error(void)
+static void test_dispatch_cmd_failure(void)
{
QDict *req = qdict_new();
QObject *resp;
@@ -217,25 +224,24 @@ static void test_dealloc_partial(void)
/* create partial object */
{
QDict *ud2_dict;
- QmpInputVisitor *qiv;
+ Visitor *v;
ud2_dict = qdict_new();
qdict_put_obj(ud2_dict, "string0", QOBJECT(qstring_from_str(text)));
- qiv = qmp_input_visitor_new(QOBJECT(ud2_dict));
- visit_type_UserDefTwo(qmp_input_get_visitor(qiv), NULL, &ud2, &err);
- qmp_input_visitor_cleanup(qiv);
+ v = qmp_input_visitor_new(QOBJECT(ud2_dict), true);
+ visit_type_UserDefTwo(v, NULL, &ud2, &err);
+ visit_free(v);
QDECREF(ud2_dict);
}
- /* verify partial success */
- assert(ud2 != NULL);
- assert(ud2->string0 != NULL);
- assert(strcmp(ud2->string0, text) == 0);
- assert(ud2->dict1 == NULL);
-
- /* confirm & release construction error */
+ /* verify that visit_type_XXX() cleans up properly on error */
error_free_or_abort(&err);
+ assert(!ud2);
+
+ /* Manually create a partial object, leaving ud2->dict1 at NULL */
+ ud2 = g_new0(UserDefTwo, 1);
+ ud2->string0 = g_strdup(text);
/* tear down partial object */
qapi_free_UserDefTwo(ud2);
@@ -247,7 +253,7 @@ int main(int argc, char **argv)
g_test_init(&argc, &argv, NULL);
g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd);
- g_test_add_func("/0.15/dispatch_cmd_error", test_dispatch_cmd_error);
+ g_test_add_func("/0.15/dispatch_cmd_failure", test_dispatch_cmd_failure);
g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io);
g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
g_test_add_func("/0.15/dealloc_partial", test_dealloc_partial);
diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
index a296fdbac2..633dc87402 100644
--- a/tests/test-qmp-event.c
+++ b/tests/test-qmp-event.c
@@ -12,7 +12,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "test-qapi-types.h"
diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c
index d71727e272..814550ac71 100644
--- a/tests/test-qmp-input-strict.c
+++ b/tests/test-qmp-input-strict.c
@@ -12,7 +12,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "qapi/error.h"
@@ -20,13 +19,14 @@
#include "test-qapi-types.h"
#include "test-qapi-visit.h"
#include "qapi/qmp/types.h"
+#include "qapi/qmp/qjson.h"
#include "test-qmp-introspect.h"
#include "qmp-introspect.h"
#include "qapi-visit.h"
typedef struct TestInputVisitorData {
QObject *obj;
- QmpInputVisitor *qiv;
+ Visitor *qiv;
} TestInputVisitorData;
static void validate_teardown(TestInputVisitorData *data,
@@ -36,7 +36,7 @@ static void validate_teardown(TestInputVisitorData *data,
data->obj = NULL;
if (data->qiv) {
- qmp_input_visitor_cleanup(data->qiv);
+ visit_free(data->qiv);
data->qiv = NULL;
}
}
@@ -48,20 +48,14 @@ static Visitor *validate_test_init_internal(TestInputVisitorData *data,
const char *json_string,
va_list *ap)
{
- Visitor *v;
-
validate_teardown(data, NULL);
data->obj = qobject_from_jsonv(json_string, ap);
g_assert(data->obj);
- data->qiv = qmp_input_visitor_new_strict(data->obj);
+ data->qiv = qmp_input_visitor_new(data->obj, true);
g_assert(data->qiv);
-
- v = qmp_input_get_visitor(data->qiv);
- g_assert(v);
-
- return v;
+ return data->qiv;
}
static GCC_FMT_ATTR(2, 3)
@@ -182,10 +176,7 @@ static void test_validate_fail_struct(TestInputVisitorData *data,
visit_type_TestStruct(v, NULL, &p, &err);
error_free_or_abort(&err);
- if (p) {
- g_free(p->string);
- }
- g_free(p);
+ g_assert(!p);
}
static void test_validate_fail_struct_nested(TestInputVisitorData *data,
@@ -199,7 +190,7 @@ static void test_validate_fail_struct_nested(TestInputVisitorData *data,
visit_type_UserDefTwo(v, NULL, &udp, &err);
error_free_or_abort(&err);
- qapi_free_UserDefTwo(udp);
+ g_assert(!udp);
}
static void test_validate_fail_list(TestInputVisitorData *data,
@@ -213,7 +204,7 @@ static void test_validate_fail_list(TestInputVisitorData *data,
visit_type_UserDefOneList(v, NULL, &head, &err);
error_free_or_abort(&err);
- qapi_free_UserDefOneList(head);
+ g_assert(!head);
}
static void test_validate_fail_union_native_list(TestInputVisitorData *data,
@@ -228,7 +219,7 @@ static void test_validate_fail_union_native_list(TestInputVisitorData *data,
visit_type_UserDefNativeListUnion(v, NULL, &tmp, &err);
error_free_or_abort(&err);
- qapi_free_UserDefNativeListUnion(tmp);
+ g_assert(!tmp);
}
static void test_validate_fail_union_flat(TestInputVisitorData *data,
@@ -242,7 +233,7 @@ static void test_validate_fail_union_flat(TestInputVisitorData *data,
visit_type_UserDefFlatUnion(v, NULL, &tmp, &err);
error_free_or_abort(&err);
- qapi_free_UserDefFlatUnion(tmp);
+ g_assert(!tmp);
}
static void test_validate_fail_union_flat_no_discrim(TestInputVisitorData *data,
@@ -257,13 +248,13 @@ static void test_validate_fail_union_flat_no_discrim(TestInputVisitorData *data,
visit_type_UserDefFlatUnion2(v, NULL, &tmp, &err);
error_free_or_abort(&err);
- qapi_free_UserDefFlatUnion2(tmp);
+ g_assert(!tmp);
}
static void test_validate_fail_alternate(TestInputVisitorData *data,
const void *unused)
{
- UserDefAlternate *tmp = NULL;
+ UserDefAlternate *tmp;
Visitor *v;
Error *err = NULL;
@@ -271,7 +262,7 @@ static void test_validate_fail_alternate(TestInputVisitorData *data,
visit_type_UserDefAlternate(v, NULL, &tmp, &err);
error_free_or_abort(&err);
- qapi_free_UserDefAlternate(tmp);
+ g_assert(!tmp);
}
static void do_test_validate_qmp_introspect(TestInputVisitorData *data,
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index 80527eb850..f583dce3ed 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "qapi/error.h"
@@ -19,10 +18,11 @@
#include "test-qapi-types.h"
#include "test-qapi-visit.h"
#include "qapi/qmp/types.h"
+#include "qapi/qmp/qjson.h"
typedef struct TestInputVisitorData {
QObject *obj;
- QmpInputVisitor *qiv;
+ Visitor *qiv;
} TestInputVisitorData;
static void visitor_input_teardown(TestInputVisitorData *data,
@@ -32,7 +32,7 @@ static void visitor_input_teardown(TestInputVisitorData *data,
data->obj = NULL;
if (data->qiv) {
- qmp_input_visitor_cleanup(data->qiv);
+ visit_free(data->qiv);
data->qiv = NULL;
}
}
@@ -44,20 +44,14 @@ static Visitor *visitor_input_test_init_internal(TestInputVisitorData *data,
const char *json_string,
va_list *ap)
{
- Visitor *v;
-
visitor_input_teardown(data, NULL);
data->obj = qobject_from_jsonv(json_string, ap);
g_assert(data->obj);
- data->qiv = qmp_input_visitor_new(data->obj);
+ data->qiv = qmp_input_visitor_new(data->obj, false);
g_assert(data->qiv);
-
- v = qmp_input_get_visitor(data->qiv);
- g_assert(v);
-
- return v;
+ return data->qiv;
}
static GCC_FMT_ATTR(2, 3)
@@ -279,6 +273,34 @@ static void test_visitor_in_any(TestInputVisitorData *data,
qobject_decref(res);
}
+static void test_visitor_in_null(TestInputVisitorData *data,
+ const void *unused)
+{
+ Visitor *v;
+ Error *err = NULL;
+ char *tmp;
+
+ /*
+ * FIXME: Since QAPI doesn't know the 'null' type yet, we can't
+ * test visit_type_null() by reading into a QAPI struct then
+ * checking that it was populated correctly. The best we can do
+ * for now is ensure that we consumed null from the input, proven
+ * by the fact that we can't re-read the key; and that we detect
+ * when input is not null.
+ */
+
+ v = visitor_input_test_init(data, "{ 'a': null, 'b': '' }");
+ visit_start_struct(v, NULL, NULL, 0, &error_abort);
+ visit_type_null(v, "a", &error_abort);
+ visit_type_str(v, "a", &tmp, &err);
+ g_assert(!tmp);
+ error_free_or_abort(&err);
+ visit_type_null(v, "b", &err);
+ error_free_or_abort(&err);
+ visit_check_struct(v, &error_abort);
+ visit_end_struct(v, NULL);
+}
+
static void test_visitor_in_union_flat(TestInputVisitorData *data,
const void *unused)
{
@@ -739,24 +761,30 @@ static void test_visitor_in_errors(TestInputVisitorData *data,
Error *err = NULL;
Visitor *v;
strList *q = NULL;
+ UserDefTwo *r = NULL;
+ WrapAlternate *s = NULL;
v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
"'string': -42 }");
visit_type_TestStruct(v, NULL, &p, &err);
error_free_or_abort(&err);
- /* FIXME - a failed parse should not leave a partially-allocated p
- * for us to clean up; this could cause callers to leak memory. */
- g_assert(p->string == NULL);
-
- g_free(p->string);
- g_free(p);
+ g_assert(!p);
v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
visit_type_strList(v, NULL, &q, &err);
error_free_or_abort(&err);
- assert(q);
- qapi_free_strList(q);
+ assert(!q);
+
+ v = visitor_input_test_init(data, "{ 'str':'hi' }");
+ visit_type_UserDefTwo(v, NULL, &r, &err);
+ error_free_or_abort(&err);
+ assert(!r);
+
+ v = visitor_input_test_init(data, "{ }");
+ visit_type_WrapAlternate(v, NULL, &s, &err);
+ error_free_or_abort(&err);
+ assert(!s);
}
static void test_visitor_in_wrong_type(TestInputVisitorData *data,
@@ -829,6 +857,8 @@ int main(int argc, char **argv)
&in_visitor_data, test_visitor_in_list);
input_visitor_test_add("/visitor/input/any",
&in_visitor_data, test_visitor_in_any);
+ input_visitor_test_add("/visitor/input/null",
+ &in_visitor_data, test_visitor_in_null);
input_visitor_test_add("/visitor/input/union-flat",
&in_visitor_data, test_visitor_in_union_flat);
input_visitor_test_add("/visitor/input/alternate",
diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c
index c70926793a..513d71f0d1 100644
--- a/tests/test-qmp-output-visitor.c
+++ b/tests/test-qmp-output-visitor.c
@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "qapi/error.h"
@@ -19,28 +18,40 @@
#include "test-qapi-types.h"
#include "test-qapi-visit.h"
#include "qapi/qmp/types.h"
+#include "qapi/qmp/qjson.h"
typedef struct TestOutputVisitorData {
- QmpOutputVisitor *qov;
Visitor *ov;
+ QObject *obj;
} TestOutputVisitorData;
static void visitor_output_setup(TestOutputVisitorData *data,
const void *unused)
{
- data->qov = qmp_output_visitor_new();
- g_assert(data->qov != NULL);
-
- data->ov = qmp_output_get_visitor(data->qov);
- g_assert(data->ov != NULL);
+ data->ov = qmp_output_visitor_new(&data->obj);
+ g_assert(data->ov);
}
static void visitor_output_teardown(TestOutputVisitorData *data,
const void *unused)
{
- qmp_output_visitor_cleanup(data->qov);
- data->qov = NULL;
+ visit_free(data->ov);
data->ov = NULL;
+ qobject_decref(data->obj);
+ data->obj = NULL;
+}
+
+static QObject *visitor_get(TestOutputVisitorData *data)
+{
+ visit_complete(data->ov, &data->obj);
+ g_assert(data->obj);
+ return data->obj;
+}
+
+static void visitor_reset(TestOutputVisitorData *data)
+{
+ visitor_output_teardown(data, NULL);
+ visitor_output_setup(data, NULL);
}
static void test_visitor_out_int(TestOutputVisitorData *data,
@@ -51,12 +62,9 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
visit_type_int(data->ov, NULL, &value, &error_abort);
- obj = qmp_output_get_qobject(data->qov);
- g_assert(obj != NULL);
+ obj = visitor_get(data);
g_assert(qobject_type(obj) == QTYPE_QINT);
g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value);
-
- qobject_decref(obj);
}
static void test_visitor_out_bool(TestOutputVisitorData *data,
@@ -67,12 +75,9 @@ static void test_visitor_out_bool(TestOutputVisitorData *data,
visit_type_bool(data->ov, NULL, &value, &error_abort);
- obj = qmp_output_get_qobject(data->qov);
- g_assert(obj != NULL);
+ obj = visitor_get(data);
g_assert(qobject_type(obj) == QTYPE_QBOOL);
g_assert(qbool_get_bool(qobject_to_qbool(obj)) == value);
-
- qobject_decref(obj);
}
static void test_visitor_out_number(TestOutputVisitorData *data,
@@ -83,12 +88,9 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
visit_type_number(data->ov, NULL, &value, &error_abort);
- obj = qmp_output_get_qobject(data->qov);
- g_assert(obj != NULL);
+ obj = visitor_get(data);
g_assert(qobject_type(obj) == QTYPE_QFLOAT);
g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value);
-
- qobject_decref(obj);
}
static void test_visitor_out_string(TestOutputVisitorData *data,
@@ -99,12 +101,9 @@ static void test_visitor_out_string(TestOutputVisitorData *data,
visit_type_str(data->ov, NULL, &string, &error_abort);
- obj = qmp_output_get_qobject(data->qov);
- g_assert(obj != NULL);
+ obj = visitor_get(data);
g_assert(qobject_type(obj) == QTYPE_QSTRING);
g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string);
-
- qobject_decref(obj);
}
static void test_visitor_out_no_string(TestOutputVisitorData *data,
@@ -116,12 +115,9 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
/* A null string should return "" */
visit_type_str(data->ov, NULL, &string, &error_abort);
- obj = qmp_output_get_qobject(data->qov);
- g_assert(obj != NULL);
+ obj = visitor_get(data);
g_assert(qobject_type(obj) == QTYPE_QSTRING);
g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, "");
-
- qobject_decref(obj);
}
static void test_visitor_out_enum(TestOutputVisitorData *data,
@@ -133,12 +129,11 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
for (i = 0; i < ENUM_ONE__MAX; i++) {
visit_type_EnumOne(data->ov, "unused", &i, &error_abort);
- obj = qmp_output_get_qobject(data->qov);
- g_assert(obj != NULL);
+ obj = visitor_get(data);
g_assert(qobject_type(obj) == QTYPE_QSTRING);
g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==,
EnumOne_lookup[i]);
- qobject_decref(obj);
+ visitor_reset(data);
}
}
@@ -153,6 +148,7 @@ static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
visit_type_EnumOne(data->ov, "unused", &bad_values[i], &err);
g_assert(err);
error_free(err);
+ visitor_reset(data);
}
}
@@ -169,8 +165,7 @@ static void test_visitor_out_struct(TestOutputVisitorData *data,
visit_type_TestStruct(data->ov, NULL, &p, &error_abort);
- obj = qmp_output_get_qobject(data->qov);
- g_assert(obj != NULL);
+ obj = visitor_get(data);
g_assert(qobject_type(obj) == QTYPE_QDICT);
qdict = qobject_to_qdict(obj);
@@ -178,8 +173,6 @@ static void test_visitor_out_struct(TestOutputVisitorData *data,
g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, false);
g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
-
- QDECREF(qdict);
}
static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
@@ -214,8 +207,7 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
visit_type_UserDefTwo(data->ov, "unused", &ud2, &error_abort);
- obj = qmp_output_get_qobject(data->qov);
- g_assert(obj != NULL);
+ obj = visitor_get(data);
g_assert(qobject_type(obj) == QTYPE_QDICT);
qdict = qobject_to_qdict(obj);
@@ -242,7 +234,6 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
- QDECREF(qdict);
qapi_free_UserDefTwo(ud2);
}
@@ -262,6 +253,7 @@ static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
visit_type_UserDefOne(data->ov, "unused", &pu, &err);
g_assert(err);
error_free(err);
+ visitor_reset(data);
}
}
@@ -293,8 +285,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
visit_type_TestStructList(data->ov, NULL, &head, &error_abort);
- obj = qmp_output_get_qobject(data->qov);
- g_assert(obj != NULL);
+ obj = visitor_get(data);
g_assert(qobject_type(obj) == QTYPE_QLIST);
qlist = qobject_to_qlist(obj);
@@ -315,7 +306,6 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
}
g_assert_cmpint(i, ==, max_items);
- QDECREF(qlist);
qapi_free_TestStructList(head);
}
@@ -359,13 +349,12 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
qobj = QOBJECT(qint_from_int(-42));
visit_type_any(data->ov, NULL, &qobj, &error_abort);
- obj = qmp_output_get_qobject(data->qov);
- g_assert(obj != NULL);
+ obj = visitor_get(data);
g_assert(qobject_type(obj) == QTYPE_QINT);
g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, -42);
- qobject_decref(obj);
qobject_decref(qobj);
+ visitor_reset(data);
qdict = qdict_new();
qdict_put(qdict, "integer", qint_from_int(-42));
qdict_put(qdict, "boolean", qbool_from_bool(true));
@@ -373,8 +362,7 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
qobj = QOBJECT(qdict);
visit_type_any(data->ov, NULL, &qobj, &error_abort);
qobject_decref(qobj);
- obj = qmp_output_get_qobject(data->qov);
- g_assert(obj != NULL);
+ obj = visitor_get(data);
qdict = qobject_to_qdict(obj);
g_assert(qdict);
qobj = qdict_get(qdict, "integer");
@@ -392,7 +380,6 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
qstring = qobject_to_qstring(qobj);
g_assert(qstring);
g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
- qobject_decref(obj);
}
static void test_visitor_out_union_flat(TestOutputVisitorData *data,
@@ -408,7 +395,7 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data,
tmp->u.value1.boolean = true;
visit_type_UserDefFlatUnion(data->ov, NULL, &tmp, &error_abort);
- arg = qmp_output_get_qobject(data->qov);
+ arg = visitor_get(data);
g_assert(qobject_type(arg) == QTYPE_QDICT);
qdict = qobject_to_qdict(arg);
@@ -419,7 +406,6 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data,
g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true);
qapi_free_UserDefFlatUnion(tmp);
- QDECREF(qdict);
}
static void test_visitor_out_alternate(TestOutputVisitorData *data,
@@ -434,27 +420,27 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
tmp->u.i = 42;
visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
- arg = qmp_output_get_qobject(data->qov);
+ arg = visitor_get(data);
g_assert(qobject_type(arg) == QTYPE_QINT);
g_assert_cmpint(qint_get_int(qobject_to_qint(arg)), ==, 42);
qapi_free_UserDefAlternate(tmp);
- qobject_decref(arg);
+ visitor_reset(data);
tmp = g_new0(UserDefAlternate, 1);
tmp->type = QTYPE_QSTRING;
tmp->u.s = g_strdup("hello");
visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
- arg = qmp_output_get_qobject(data->qov);
+ arg = visitor_get(data);
g_assert(qobject_type(arg) == QTYPE_QSTRING);
g_assert_cmpstr(qstring_get_str(qobject_to_qstring(arg)), ==, "hello");
qapi_free_UserDefAlternate(tmp);
- qobject_decref(arg);
+ visitor_reset(data);
tmp = g_new0(UserDefAlternate, 1);
tmp->type = QTYPE_QDICT;
tmp->u.udfu.integer = 1;
@@ -463,7 +449,7 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
tmp->u.udfu.u.value1.boolean = true;
visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
- arg = qmp_output_get_qobject(data->qov);
+ arg = visitor_get(data);
g_assert_cmpint(qobject_type(arg), ==, QTYPE_QDICT);
qdict = qobject_to_qdict(arg);
@@ -474,19 +460,26 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true);
qapi_free_UserDefAlternate(tmp);
- qobject_decref(arg);
}
-static void test_visitor_out_empty(TestOutputVisitorData *data,
- const void *unused)
+static void test_visitor_out_null(TestOutputVisitorData *data,
+ const void *unused)
{
QObject *arg;
+ QDict *qdict;
+ QObject *nil;
- arg = qmp_output_get_qobject(data->qov);
- g_assert(qobject_type(arg) == QTYPE_QNULL);
- /* Check that qnull reference counting is sane */
- g_assert(arg->refcnt == 2);
- qobject_decref(arg);
+ visit_start_struct(data->ov, NULL, NULL, 0, &error_abort);
+ visit_type_null(data->ov, "a", &error_abort);
+ visit_check_struct(data->ov, &error_abort);
+ visit_end_struct(data->ov, NULL);
+ arg = visitor_get(data);
+ g_assert(qobject_type(arg) == QTYPE_QDICT);
+ qdict = qobject_to_qdict(arg);
+ g_assert_cmpint(qdict_size(qdict), ==, 1);
+ nil = qdict_get(qdict, "a");
+ g_assert(nil);
+ g_assert(qobject_type(nil) == QTYPE_QNULL);
}
static void init_native_list(UserDefNativeListUnion *cvalue)
@@ -717,10 +710,9 @@ static void test_native_list(TestOutputVisitorData *data,
visit_type_UserDefNativeListUnion(data->ov, NULL, &cvalue, &error_abort);
- obj = qmp_output_get_qobject(data->qov);
+ obj = visitor_get(data);
check_native_list(obj, cvalue->type);
qapi_free_UserDefNativeListUnion(cvalue);
- qobject_decref(obj);
}
static void test_visitor_out_native_list_int(TestOutputVisitorData *data,
@@ -839,8 +831,8 @@ int main(int argc, char **argv)
&out_visitor_data, test_visitor_out_union_flat);
output_visitor_test_add("/visitor/output/alternate",
&out_visitor_data, test_visitor_out_alternate);
- output_visitor_test_add("/visitor/output/empty",
- &out_visitor_data, test_visitor_out_empty);
+ output_visitor_test_add("/visitor/output/null",
+ &out_visitor_data, test_visitor_out_null);
output_visitor_test_add("/visitor/output/native_list/int",
&out_visitor_data,
test_visitor_out_native_list_int);
diff --git a/tests/test-rcu-list.c b/tests/test-rcu-list.c
index 79d3750144..1514d7ec97 100644
--- a/tests/test-rcu-list.c
+++ b/tests/test-rcu-list.c
@@ -21,7 +21,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu/atomic.h"
#include "qemu/rcu.h"
#include "qemu/thread.h"
diff --git a/tests/test-rfifolock.c b/tests/test-rfifolock.c
index 9a3cb243ba..471a81114d 100644
--- a/tests/test-rfifolock.c
+++ b/tests/test-rfifolock.c
@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "qemu/rfifolock.h"
diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c
index 9e6906a567..d837ebedad 100644
--- a/tests/test-string-input-visitor.c
+++ b/tests/test-string-input-visitor.c
@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "qapi/error.h"
@@ -21,15 +20,15 @@
#include "qapi/qmp/types.h"
typedef struct TestInputVisitorData {
- StringInputVisitor *siv;
+ Visitor *v;
} TestInputVisitorData;
static void visitor_input_teardown(TestInputVisitorData *data,
const void *unused)
{
- if (data->siv) {
- string_input_visitor_cleanup(data->siv);
- data->siv = NULL;
+ if (data->v) {
+ visit_free(data->v);
+ data->v = NULL;
}
}
@@ -40,15 +39,9 @@ static
Visitor *visitor_input_test_init(TestInputVisitorData *data,
const char *string)
{
- Visitor *v;
-
- data->siv = string_input_visitor_new(string);
- g_assert(data->siv != NULL);
-
- v = string_input_get_visitor(data->siv);
- g_assert(v != NULL);
-
- return v;
+ data->v = string_input_visitor_new(string);
+ g_assert(data->v);
+ return data->v;
}
static void test_visitor_in_int(TestInputVisitorData *data,
@@ -63,6 +56,13 @@ static void test_visitor_in_int(TestInputVisitorData *data,
visit_type_int(v, NULL, &res, &err);
g_assert(!err);
g_assert_cmpint(res, ==, value);
+
+ visitor_input_teardown(data, unused);
+
+ v = visitor_input_test_init(data, "not an int");
+
+ visit_type_int(v, NULL, &res, &err);
+ error_free_or_abort(&err);
}
static void test_visitor_in_intList(TestInputVisitorData *data,
@@ -70,6 +70,7 @@ static void test_visitor_in_intList(TestInputVisitorData *data,
{
int64_t value[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20};
int16List *res = NULL, *tmp;
+ Error *err = NULL;
Visitor *v;
int i = 0;
@@ -84,12 +85,15 @@ static void test_visitor_in_intList(TestInputVisitorData *data,
}
g_assert(!tmp);
- tmp = res;
- while (tmp) {
- res = res->next;
- g_free(tmp);
- tmp = res;
- }
+ qapi_free_int16List(res);
+
+ visitor_input_teardown(data, unused);
+
+ v = visitor_input_test_init(data, "not an int list");
+
+ visit_type_int16List(v, NULL, &res, &err);
+ error_free_or_abort(&err);
+ g_assert(!res);
}
static void test_visitor_in_bool(TestInputVisitorData *data,
@@ -189,8 +193,6 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
visitor_input_teardown(data, NULL);
}
-
- data->siv = NULL;
}
/* Try to crash the visitors */
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index 1ecd75b853..444844a15a 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "qapi/error.h"
@@ -21,39 +20,53 @@
#include "qapi/qmp/types.h"
typedef struct TestOutputVisitorData {
- StringOutputVisitor *sov;
Visitor *ov;
+ char *str;
bool human;
} TestOutputVisitorData;
+static void visitor_output_setup_internal(TestOutputVisitorData *data,
+ bool human)
+{
+ data->human = human;
+ data->ov = string_output_visitor_new(human, &data->str);
+ g_assert(data->ov);
+}
+
static void visitor_output_setup(TestOutputVisitorData *data,
const void *unused)
{
- data->human = false;
- data->sov = string_output_visitor_new(data->human);
- g_assert(data->sov != NULL);
-
- data->ov = string_output_get_visitor(data->sov);
- g_assert(data->ov != NULL);
+ return visitor_output_setup_internal(data, false);
}
static void visitor_output_setup_human(TestOutputVisitorData *data,
const void *unused)
{
- data->human = true;
- data->sov = string_output_visitor_new(data->human);
- g_assert(data->sov != NULL);
-
- data->ov = string_output_get_visitor(data->sov);
- g_assert(data->ov != NULL);
+ return visitor_output_setup_internal(data, true);
}
static void visitor_output_teardown(TestOutputVisitorData *data,
const void *unused)
{
- string_output_visitor_cleanup(data->sov);
- data->sov = NULL;
+ visit_free(data->ov);
data->ov = NULL;
+ g_free(data->str);
+ data->str = NULL;
+}
+
+static char *visitor_get(TestOutputVisitorData *data)
+{
+ visit_complete(data->ov, &data->str);
+ g_assert(data->str);
+ return data->str;
+}
+
+static void visitor_reset(TestOutputVisitorData *data)
+{
+ bool human = data->human;
+
+ visitor_output_teardown(data, NULL);
+ visitor_output_setup_internal(data, human);
}
static void test_visitor_out_int(TestOutputVisitorData *data,
@@ -66,14 +79,12 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
visit_type_int(data->ov, NULL, &value, &err);
g_assert(!err);
- str = string_output_get_string(data->sov);
- g_assert(str != NULL);
+ str = visitor_get(data);
if (data->human) {
g_assert_cmpstr(str, ==, "42 (0x2a)");
} else {
g_assert_cmpstr(str, ==, "42");
}
- g_free(str);
}
static void test_visitor_out_intList(TestOutputVisitorData *data,
@@ -95,8 +106,7 @@ static void test_visitor_out_intList(TestOutputVisitorData *data,
visit_type_intList(data->ov, NULL, &list, &err);
g_assert(err == NULL);
- str = string_output_get_string(data->sov);
- g_assert(str != NULL);
+ str = visitor_get(data);
if (data->human) {
g_assert_cmpstr(str, ==,
"0-1,3-6,9-16,21-22,9223372036854775806-9223372036854775807 "
@@ -106,13 +116,7 @@ static void test_visitor_out_intList(TestOutputVisitorData *data,
g_assert_cmpstr(str, ==,
"0-1,3-6,9-16,21-22,9223372036854775806-9223372036854775807");
}
- g_free(str);
- while (list) {
- intList *tmp2;
- tmp2 = list->next;
- g_free(list);
- list = tmp2;
- }
+ qapi_free_intList(list);
}
static void test_visitor_out_bool(TestOutputVisitorData *data,
@@ -125,10 +129,8 @@ static void test_visitor_out_bool(TestOutputVisitorData *data,
visit_type_bool(data->ov, NULL, &value, &err);
g_assert(!err);
- str = string_output_get_string(data->sov);
- g_assert(str != NULL);
+ str = visitor_get(data);
g_assert_cmpstr(str, ==, "true");
- g_free(str);
}
static void test_visitor_out_number(TestOutputVisitorData *data,
@@ -141,10 +143,8 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
visit_type_number(data->ov, NULL, &value, &err);
g_assert(!err);
- str = string_output_get_string(data->sov);
- g_assert(str != NULL);
+ str = visitor_get(data);
g_assert_cmpstr(str, ==, "3.140000");
- g_free(str);
}
static void test_visitor_out_string(TestOutputVisitorData *data,
@@ -158,61 +158,50 @@ static void test_visitor_out_string(TestOutputVisitorData *data,
visit_type_str(data->ov, NULL, &string, &err);
g_assert(!err);
- str = string_output_get_string(data->sov);
- g_assert(str != NULL);
+ str = visitor_get(data);
if (data->human) {
g_assert_cmpstr(str, ==, string_human);
} else {
g_assert_cmpstr(str, ==, string);
}
- g_free(str);
}
static void test_visitor_out_no_string(TestOutputVisitorData *data,
const void *unused)
{
char *string = NULL;
- Error *err = NULL;
char *str;
/* A null string should return "" */
- visit_type_str(data->ov, NULL, &string, &err);
- g_assert(!err);
+ visit_type_str(data->ov, NULL, &string, &error_abort);
- str = string_output_get_string(data->sov);
- g_assert(str != NULL);
+ str = visitor_get(data);
if (data->human) {
g_assert_cmpstr(str, ==, "<null>");
} else {
g_assert_cmpstr(str, ==, "");
}
- g_free(str);
}
static void test_visitor_out_enum(TestOutputVisitorData *data,
const void *unused)
{
- Error *err = NULL;
char *str;
EnumOne i;
for (i = 0; i < ENUM_ONE__MAX; i++) {
- char *str_human;
-
- visit_type_EnumOne(data->ov, "unused", &i, &err);
- g_assert(!err);
+ visit_type_EnumOne(data->ov, "unused", &i, &error_abort);
- str_human = g_strdup_printf("\"%s\"", EnumOne_lookup[i]);
-
- str = string_output_get_string(data->sov);
- g_assert(str != NULL);
+ str = visitor_get(data);
if (data->human) {
+ char *str_human = g_strdup_printf("\"%s\"", EnumOne_lookup[i]);
+
g_assert_cmpstr(str, ==, str_human);
+ g_free(str_human);
} else {
g_assert_cmpstr(str, ==, EnumOne_lookup[i]);
}
- g_free(str_human);
- g_free(str);
+ visitor_reset(data);
}
}
@@ -225,8 +214,7 @@ static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
err = NULL;
visit_type_EnumOne(data->ov, "unused", &bad_values[i], &err);
- g_assert(err);
- error_free(err);
+ error_free_or_abort(&err);
}
}
diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
index 88dc7316b3..8dbf66a44a 100644
--- a/tests/test-thread-pool.c
+++ b/tests/test-thread-pool.c
@@ -1,5 +1,4 @@
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "block/aio.h"
#include "block/thread-pool.h"
@@ -92,9 +91,9 @@ static void co_test_cb(void *opaque)
static void test_submit_co(void)
{
WorkerTestData data;
- Coroutine *co = qemu_coroutine_create(co_test_cb);
+ Coroutine *co = qemu_coroutine_create(co_test_cb, &data);
- qemu_coroutine_enter(co, &data);
+ qemu_coroutine_enter(co);
/* Back here once the worker has started. */
diff --git a/tests/test-throttle.c b/tests/test-throttle.c
index 744a524368..363b59a38f 100644
--- a/tests/test-throttle.c
+++ b/tests/test-throttle.c
@@ -13,13 +13,13 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include <math.h>
#include "block/aio.h"
#include "qapi/error.h"
#include "qemu/throttle.h"
#include "qemu/error-report.h"
#include "block/throttle-groups.h"
+#include "sysemu/block-backend.h"
static AioContext *ctx;
static LeakyBucket bkt;
@@ -394,9 +394,25 @@ static void test_max_is_missing_limit(void)
cfg.buckets[i].max = 0;
cfg.buckets[i].avg = 100;
g_assert(throttle_is_valid(&cfg, NULL));
+
+ cfg.buckets[i].max = 30;
+ cfg.buckets[i].avg = 100;
+ g_assert(!throttle_is_valid(&cfg, NULL));
+
+ cfg.buckets[i].max = 100;
+ cfg.buckets[i].avg = 100;
+ g_assert(throttle_is_valid(&cfg, NULL));
}
}
+static void test_iops_size_is_missing_limit(void)
+{
+ /* A total/read/write iops limit is required */
+ throttle_config_init(&cfg);
+ cfg.op_size = 4096;
+ g_assert(!throttle_is_valid(&cfg, NULL));
+}
+
static void test_have_timer(void)
{
/* zero structures */
@@ -574,27 +590,32 @@ static void test_accounting(void)
static void test_groups(void)
{
ThrottleConfig cfg1, cfg2;
- BlockDriverState *bdrv1, *bdrv2, *bdrv3;
+ BlockBackend *blk1, *blk2, *blk3;
+ BlockBackendPublic *blkp1, *blkp2, *blkp3;
+
+ blk1 = blk_new();
+ blk2 = blk_new();
+ blk3 = blk_new();
- bdrv1 = bdrv_new();
- bdrv2 = bdrv_new();
- bdrv3 = bdrv_new();
+ blkp1 = blk_get_public(blk1);
+ blkp2 = blk_get_public(blk2);
+ blkp3 = blk_get_public(blk3);
- g_assert(bdrv1->throttle_state == NULL);
- g_assert(bdrv2->throttle_state == NULL);
- g_assert(bdrv3->throttle_state == NULL);
+ g_assert(blkp1->throttle_state == NULL);
+ g_assert(blkp2->throttle_state == NULL);
+ g_assert(blkp3->throttle_state == NULL);
- throttle_group_register_bs(bdrv1, "bar");
- throttle_group_register_bs(bdrv2, "foo");
- throttle_group_register_bs(bdrv3, "bar");
+ throttle_group_register_blk(blk1, "bar");
+ throttle_group_register_blk(blk2, "foo");
+ throttle_group_register_blk(blk3, "bar");
- g_assert(bdrv1->throttle_state != NULL);
- g_assert(bdrv2->throttle_state != NULL);
- g_assert(bdrv3->throttle_state != NULL);
+ g_assert(blkp1->throttle_state != NULL);
+ g_assert(blkp2->throttle_state != NULL);
+ g_assert(blkp3->throttle_state != NULL);
- g_assert(!strcmp(throttle_group_get_name(bdrv1), "bar"));
- g_assert(!strcmp(throttle_group_get_name(bdrv2), "foo"));
- g_assert(bdrv1->throttle_state == bdrv3->throttle_state);
+ g_assert(!strcmp(throttle_group_get_name(blk1), "bar"));
+ g_assert(!strcmp(throttle_group_get_name(blk2), "foo"));
+ g_assert(blkp1->throttle_state == blkp3->throttle_state);
/* Setting the config of a group member affects the whole group */
throttle_config_init(&cfg1);
@@ -602,29 +623,29 @@ static void test_groups(void)
cfg1.buckets[THROTTLE_BPS_WRITE].avg = 285000;
cfg1.buckets[THROTTLE_OPS_READ].avg = 20000;
cfg1.buckets[THROTTLE_OPS_WRITE].avg = 12000;
- throttle_group_config(bdrv1, &cfg1);
+ throttle_group_config(blk1, &cfg1);
- throttle_group_get_config(bdrv1, &cfg1);
- throttle_group_get_config(bdrv3, &cfg2);
+ throttle_group_get_config(blk1, &cfg1);
+ throttle_group_get_config(blk3, &cfg2);
g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
cfg2.buckets[THROTTLE_BPS_READ].avg = 4547;
cfg2.buckets[THROTTLE_BPS_WRITE].avg = 1349;
cfg2.buckets[THROTTLE_OPS_READ].avg = 123;
cfg2.buckets[THROTTLE_OPS_WRITE].avg = 86;
- throttle_group_config(bdrv3, &cfg1);
+ throttle_group_config(blk3, &cfg1);
- throttle_group_get_config(bdrv1, &cfg1);
- throttle_group_get_config(bdrv3, &cfg2);
+ throttle_group_get_config(blk1, &cfg1);
+ throttle_group_get_config(blk3, &cfg2);
g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
- throttle_group_unregister_bs(bdrv1);
- throttle_group_unregister_bs(bdrv2);
- throttle_group_unregister_bs(bdrv3);
+ throttle_group_unregister_blk(blk1);
+ throttle_group_unregister_blk(blk2);
+ throttle_group_unregister_blk(blk3);
- g_assert(bdrv1->throttle_state == NULL);
- g_assert(bdrv2->throttle_state == NULL);
- g_assert(bdrv3->throttle_state == NULL);
+ g_assert(blkp1->throttle_state == NULL);
+ g_assert(blkp2->throttle_state == NULL);
+ g_assert(blkp3->throttle_state == NULL);
}
int main(int argc, char **argv)
@@ -647,6 +668,8 @@ int main(int argc, char **argv)
g_test_add_func("/throttle/config/conflicting", test_conflicting_config);
g_test_add_func("/throttle/config/is_valid", test_is_valid);
g_test_add_func("/throttle/config/max", test_max_is_missing_limit);
+ g_test_add_func("/throttle/config/iops_size",
+ test_iops_size_is_missing_limit);
g_test_add_func("/throttle/config_functions", test_config_functions);
g_test_add_func("/throttle/accounting", test_accounting);
g_test_add_func("/throttle/groups", test_groups);
diff --git a/tests/test-timed-average.c b/tests/test-timed-average.c
index 1cc4ab3027..e2bcf5fe13 100644
--- a/tests/test-timed-average.c
+++ b/tests/test-timed-average.c
@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu/timed-average.h"
diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
index 9adbc30a41..dba4670762 100644
--- a/tests/test-visitor-serialization.c
+++ b/tests/test-visitor-serialization.c
@@ -12,7 +12,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include <float.h>
#include "qemu-common.h"
@@ -20,6 +19,7 @@
#include "test-qapi-visit.h"
#include "qapi/error.h"
#include "qapi/qmp/types.h"
+#include "qapi/qmp/qjson.h"
#include "qapi/qmp-input-visitor.h"
#include "qapi/qmp-output-visitor.h"
#include "qapi/string-input-visitor.h"
@@ -89,11 +89,11 @@ typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
static void dealloc_helper(void *native_in, VisitorFunc visit, Error **errp)
{
- QapiDeallocVisitor *qdv = qapi_dealloc_visitor_new();
+ Visitor *v = qapi_dealloc_visitor_new();
- visit(qapi_dealloc_get_visitor(qdv), &native_in, errp);
+ visit(v, &native_in, errp);
- qapi_dealloc_visitor_cleanup(qdv);
+ visit_free(v);
}
static void visit_primitive_type(Visitor *v, void **native, Error **errp)
@@ -1012,8 +1012,9 @@ static PrimitiveType pt_values[] = {
/* visitor-specific op implementations */
typedef struct QmpSerializeData {
- QmpOutputVisitor *qov;
- QmpInputVisitor *qiv;
+ Visitor *qov;
+ QObject *obj;
+ Visitor *qiv;
} QmpSerializeData;
static void qmp_serialize(void *native_in, void **datap,
@@ -1021,8 +1022,8 @@ static void qmp_serialize(void *native_in, void **datap,
{
QmpSerializeData *d = g_malloc0(sizeof(*d));
- d->qov = qmp_output_visitor_new();
- visit(qmp_output_get_visitor(d->qov), &native_in, errp);
+ d->qov = qmp_output_visitor_new(&d->obj);
+ visit(d->qov, &native_in, errp);
*datap = d;
}
@@ -1033,30 +1034,31 @@ static void qmp_deserialize(void **native_out, void *datap,
QString *output_json;
QObject *obj_orig, *obj;
- obj_orig = qmp_output_get_qobject(d->qov);
+ 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));
QDECREF(output_json);
- d->qiv = qmp_input_visitor_new(obj);
+ d->qiv = qmp_input_visitor_new(obj, true);
qobject_decref(obj_orig);
qobject_decref(obj);
- visit(qmp_input_get_visitor(d->qiv), native_out, errp);
+ visit(d->qiv, native_out, errp);
}
static void qmp_cleanup(void *datap)
{
QmpSerializeData *d = datap;
- qmp_output_visitor_cleanup(d->qov);
- qmp_input_visitor_cleanup(d->qiv);
+ visit_free(d->qov);
+ visit_free(d->qiv);
g_free(d);
}
typedef struct StringSerializeData {
char *string;
- StringOutputVisitor *sov;
- StringInputVisitor *siv;
+ Visitor *sov;
+ Visitor *siv;
} StringSerializeData;
static void string_serialize(void *native_in, void **datap,
@@ -1064,8 +1066,8 @@ static void string_serialize(void *native_in, void **datap,
{
StringSerializeData *d = g_malloc0(sizeof(*d));
- d->sov = string_output_visitor_new(false);
- visit(string_output_get_visitor(d->sov), &native_in, errp);
+ d->sov = string_output_visitor_new(false, &d->string);
+ visit(d->sov, &native_in, errp);
*datap = d;
}
@@ -1074,17 +1076,17 @@ static void string_deserialize(void **native_out, void *datap,
{
StringSerializeData *d = datap;
- d->string = string_output_get_string(d->sov);
+ visit_complete(d->sov, &d->string);
d->siv = string_input_visitor_new(d->string);
- visit(string_input_get_visitor(d->siv), native_out, errp);
+ visit(d->siv, native_out, errp);
}
static void string_cleanup(void *datap)
{
StringSerializeData *d = datap;
- string_output_visitor_cleanup(d->sov);
- string_input_visitor_cleanup(d->siv);
+ visit_free(d->sov);
+ visit_free(d->siv);
g_free(d->string);
g_free(d);
}
diff --git a/tests/test-vmstate.c b/tests/test-vmstate.c
index 713d4443b2..41fd841aed 100644
--- a/tests/test-vmstate.c
+++ b/tests/test-vmstate.c
@@ -23,12 +23,12 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "qemu-common.h"
#include "migration/migration.h"
#include "migration/vmstate.h"
#include "qemu/coroutine.h"
+#include "io/channel-file.h"
static char temp_file[] = "/tmp/vmst.test.XXXXXX";
static int temp_fd;
@@ -44,35 +44,22 @@ void yield_until_fd_readable(int fd)
select(fd + 1, &fds, NULL, NULL, NULL);
}
-/*
- * Some tests use 'open_test_file' to work on a real fd, some use
- * an in memory file (QEMUSizedBuffer+qemu_bufopen); we could pick one
- * but this way we test both.
- */
/* Duplicate temp_fd and seek to the beginning of the file */
static QEMUFile *open_test_file(bool write)
{
int fd = dup(temp_fd);
+ QIOChannel *ioc;
lseek(fd, 0, SEEK_SET);
if (write) {
g_assert_cmpint(ftruncate(fd, 0), ==, 0);
}
- return qemu_fdopen(fd, write ? "wb" : "rb");
-}
-
-/*
- * Check that the contents of the memory-buffered file f match
- * the given size/data.
- */
-static void check_mem_file(QEMUFile *f, void *data, size_t size)
-{
- uint8_t *result = g_malloc(size);
- const QEMUSizedBuffer *qsb = qemu_buf_get(f);
- g_assert_cmpint(qsb_get_length(qsb), ==, size);
- g_assert_cmpint(qsb_get_buffer(qsb, 0, size, result), ==, size);
- g_assert_cmpint(memcmp(result, data, size), ==, 0);
- g_free(result);
+ ioc = QIO_CHANNEL(qio_channel_file_new_fd(fd));
+ if (write) {
+ return qemu_fopen_channel_output(ioc);
+ } else {
+ return qemu_fopen_channel_input(ioc);
+ }
}
#define SUCCESS(val) \
@@ -392,7 +379,7 @@ static const VMStateDescription vmstate_skipping = {
static void test_save_noskip(void)
{
- QEMUFile *fsave = qemu_bufopen("w", NULL);
+ QEMUFile *fsave = open_test_file(true);
TestStruct obj = { .a = 1, .b = 2, .c = 3, .d = 4, .e = 5, .f = 6,
.skip_c_e = false };
vmstate_save_state(fsave, &vmstate_skipping, &obj, NULL);
@@ -406,13 +393,14 @@ static void test_save_noskip(void)
0, 0, 0, 5, /* e */
0, 0, 0, 0, 0, 0, 0, 6, /* f */
};
- check_mem_file(fsave, expected, sizeof(expected));
+
qemu_fclose(fsave);
+ compare_vmstate(expected, sizeof(expected));
}
static void test_save_skip(void)
{
- QEMUFile *fsave = qemu_bufopen("w", NULL);
+ QEMUFile *fsave = open_test_file(true);
TestStruct obj = { .a = 1, .b = 2, .c = 3, .d = 4, .e = 5, .f = 6,
.skip_c_e = true };
vmstate_save_state(fsave, &vmstate_skipping, &obj, NULL);
@@ -424,13 +412,14 @@ static void test_save_skip(void)
0, 0, 0, 0, 0, 0, 0, 4, /* d */
0, 0, 0, 0, 0, 0, 0, 6, /* f */
};
- check_mem_file(fsave, expected, sizeof(expected));
qemu_fclose(fsave);
+ compare_vmstate(expected, sizeof(expected));
}
static void test_load_noskip(void)
{
+ QEMUFile *fsave = open_test_file(true);
uint8_t buf[] = {
0, 0, 0, 10, /* a */
0, 0, 0, 20, /* b */
@@ -440,10 +429,10 @@ static void test_load_noskip(void)
0, 0, 0, 0, 0, 0, 0, 60, /* f */
QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
};
+ qemu_put_buffer(fsave, buf, sizeof(buf));
+ qemu_fclose(fsave);
- QEMUSizedBuffer *qsb = qsb_create(buf, sizeof(buf));
- g_assert(qsb);
- QEMUFile *loading = qemu_bufopen("r", qsb);
+ QEMUFile *loading = open_test_file(false);
TestStruct obj = { .skip_c_e = false };
vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
g_assert(!qemu_file_get_error(loading));
@@ -454,11 +443,11 @@ static void test_load_noskip(void)
g_assert_cmpint(obj.e, ==, 50);
g_assert_cmpint(obj.f, ==, 60);
qemu_fclose(loading);
- qsb_free(qsb);
}
static void test_load_skip(void)
{
+ QEMUFile *fsave = open_test_file(true);
uint8_t buf[] = {
0, 0, 0, 10, /* a */
0, 0, 0, 20, /* b */
@@ -466,10 +455,10 @@ static void test_load_skip(void)
0, 0, 0, 0, 0, 0, 0, 60, /* f */
QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
};
+ qemu_put_buffer(fsave, buf, sizeof(buf));
+ qemu_fclose(fsave);
- QEMUSizedBuffer *qsb = qsb_create(buf, sizeof(buf));
- g_assert(qsb);
- QEMUFile *loading = qemu_bufopen("r", qsb);
+ QEMUFile *loading = open_test_file(false);
TestStruct obj = { .skip_c_e = true, .c = 300, .e = 500 };
vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
g_assert(!qemu_file_get_error(loading));
@@ -480,13 +469,14 @@ static void test_load_skip(void)
g_assert_cmpint(obj.e, ==, 500);
g_assert_cmpint(obj.f, ==, 60);
qemu_fclose(loading);
- qsb_free(qsb);
}
int main(int argc, char **argv)
{
temp_fd = mkstemp(temp_file);
+ module_call_init(MODULE_INIT_QOM);
+
g_test_init(&argc, &argv, NULL);
g_test_add_func("/vmstate/simple/primitive", test_simple_primitive);
g_test_add_func("/vmstate/versioned/load/v1", test_load_v1);
diff --git a/tests/test-write-threshold.c b/tests/test-write-threshold.c
index fdbc8020fd..97ca12f710 100644
--- a/tests/test-write-threshold.c
+++ b/tests/test-write-threshold.c
@@ -7,7 +7,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "block/block_int.h"
#include "block/write-threshold.h"
diff --git a/tests/test-x86-cpuid.c b/tests/test-x86-cpuid.c
index 8eb0bc6ad5..ff225006e4 100644
--- a/tests/test-x86-cpuid.c
+++ b/tests/test-x86-cpuid.c
@@ -23,7 +23,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "hw/i386/topology.h"
diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c
index 235cae0137..a7940a4639 100644
--- a/tests/tmp105-test.c
+++ b/tests/tmp105-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/i2c.h"
diff --git a/tests/tpci200-test.c b/tests/tpci200-test.c
index cb2b00ca8b..0321ec27ec 100644
--- a/tests/tpci200-test.c
+++ b/tests/tpci200-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
diff --git a/tests/usb-hcd-ehci-test.c b/tests/usb-hcd-ehci-test.c
index a0f13ef40a..eb247ad453 100644
--- a/tests/usb-hcd-ehci-test.c
+++ b/tests/usb-hcd-ehci-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/pci-pc.h"
#include "hw/usb/uhci-regs.h"
diff --git a/tests/usb-hcd-ohci-test.c b/tests/usb-hcd-ohci-test.c
index efd6669c7c..4758813d78 100644
--- a/tests/usb-hcd-ohci-test.c
+++ b/tests/usb-hcd-ohci-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/usb.h"
diff --git a/tests/usb-hcd-uhci-test.c b/tests/usb-hcd-uhci-test.c
index 71ff2ea189..5cd59ad91f 100644
--- a/tests/usb-hcd-uhci-test.c
+++ b/tests/usb-hcd-uhci-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/usb.h"
#include "hw/usb/uhci-regs.h"
diff --git a/tests/usb-hcd-xhci-test.c b/tests/usb-hcd-xhci-test.c
index 7e2e212df3..22513e9eb5 100644
--- a/tests/usb-hcd-xhci-test.c
+++ b/tests/usb-hcd-xhci-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/usb.h"
diff --git a/tests/vhost-user-bridge.c b/tests/vhost-user-bridge.c
index 0779ba2602..775e031069 100644
--- a/tests/vhost-user-bridge.c
+++ b/tests/vhost-user-bridge.c
@@ -33,12 +33,9 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/unistd.h>
-#include <sys/mman.h>
#include <sys/eventfd.h>
#include <arpa/inet.h>
#include <netdb.h>
-#include <qemu/osdep.h>
-
#include <linux/vhost.h>
#include "qemu/atomic.h"
@@ -946,6 +943,13 @@ vubr_set_vring_addr_exec(VubrDev *dev, VhostUserMsg *vmsg)
DPRINT(" vring_avail at %p\n", vq->avail);
vq->last_used_index = vq->used->idx;
+
+ if (vq->last_avail_index != vq->used->idx) {
+ DPRINT("Last avail index != used index: %d != %d, resuming",
+ vq->last_avail_index, vq->used->idx);
+ vq->last_avail_index = vq->used->idx;
+ }
+
return 0;
}
@@ -1204,12 +1208,13 @@ vubr_accept_cb(int sock, void *ctx)
}
static VubrDev *
-vubr_new(const char *path)
+vubr_new(const char *path, bool client)
{
VubrDev *dev = (VubrDev *) calloc(1, sizeof(VubrDev));
dev->nregions = 0;
int i;
struct sockaddr_un un;
+ CallbackFunc cb;
size_t len;
for (i = 0; i < MAX_NR_VIRTQUEUE; i++) {
@@ -1238,21 +1243,30 @@ vubr_new(const char *path)
un.sun_family = AF_UNIX;
strcpy(un.sun_path, path);
len = sizeof(un.sun_family) + strlen(path);
- unlink(path);
- if (bind(dev->sock, (struct sockaddr *) &un, len) == -1) {
- vubr_die("bind");
- }
+ if (!client) {
+ unlink(path);
- if (listen(dev->sock, 1) == -1) {
- vubr_die("listen");
+ if (bind(dev->sock, (struct sockaddr *) &un, len) == -1) {
+ vubr_die("bind");
+ }
+
+ if (listen(dev->sock, 1) == -1) {
+ vubr_die("listen");
+ }
+ cb = vubr_accept_cb;
+
+ DPRINT("Waiting for connections on UNIX socket %s ...\n", path);
+ } else {
+ if (connect(dev->sock, (struct sockaddr *)&un, len) == -1) {
+ vubr_die("connect");
+ }
+ cb = vubr_receive_cb;
}
dispatcher_init(&dev->dispatcher);
- dispatcher_add(&dev->dispatcher, dev->sock, (void *)dev,
- vubr_accept_cb);
+ dispatcher_add(&dev->dispatcher, dev->sock, (void *)dev, cb);
- DPRINT("Waiting for connections on UNIX socket %s ...\n", path);
return dev;
}
@@ -1369,8 +1383,9 @@ main(int argc, char *argv[])
{
VubrDev *dev;
int opt;
+ bool client = false;
- while ((opt = getopt(argc, argv, "l:r:u:")) != -1) {
+ while ((opt = getopt(argc, argv, "l:r:u:c")) != -1) {
switch (opt) {
case 'l':
@@ -1386,16 +1401,20 @@ main(int argc, char *argv[])
case 'u':
ud_socket_path = strdup(optarg);
break;
+ case 'c':
+ client = true;
+ break;
default:
goto out;
}
}
- DPRINT("ud socket: %s\n", ud_socket_path);
+ DPRINT("ud socket: %s (%s)\n", ud_socket_path,
+ client ? "client" : "server");
DPRINT("local: %s:%s\n", lhost, lport);
DPRINT("remote: %s:%s\n", rhost, rport);
- dev = vubr_new(ud_socket_path);
+ dev = vubr_new(ud_socket_path, client);
if (!dev) {
return 1;
}
@@ -1406,13 +1425,14 @@ main(int argc, char *argv[])
out:
fprintf(stderr, "Usage: %s ", argv[0]);
- fprintf(stderr, "[-u ud_socket_path] [-l lhost:lport] [-r rhost:rport]\n");
+ fprintf(stderr, "[-c] [-u ud_socket_path] [-l lhost:lport] [-r rhost:rport]\n");
fprintf(stderr, "\t-u path to unix doman socket. default: %s\n",
DEFAULT_UD_SOCKET);
fprintf(stderr, "\t-l local host and port. default: %s:%s\n",
DEFAULT_LHOST, DEFAULT_LPORT);
fprintf(stderr, "\t-r remote host and port. default: %s:%s\n",
DEFAULT_RHOST, DEFAULT_RPORT);
+ fprintf(stderr, "\t-c client mode\n");
return 1;
}
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 69615968ce..27b10c19b8 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -9,18 +9,16 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "qemu/option.h"
#include "qemu/range.h"
+#include "qemu/sockets.h"
#include "sysemu/char.h"
#include "sysemu/sysemu.h"
#include <linux/vhost.h>
-#include <sys/mman.h>
#include <sys/vfs.h>
-#include <qemu/sockets.h>
/* GLIB version compatibility flags */
#if !GLIB_CHECK_VERSION(2, 26, 0)
@@ -34,7 +32,7 @@
#define QEMU_CMD_ACCEL " -machine accel=tcg"
#define QEMU_CMD_MEM " -m %d -object memory-backend-file,id=mem,size=%dM,"\
"mem-path=%s,share=on -numa node,memdev=mem"
-#define QEMU_CMD_CHR " -chardev socket,id=%s,path=%s"
+#define QEMU_CMD_CHR " -chardev socket,id=%s,path=%s%s"
#define QEMU_CMD_NETDEV " -netdev vhost-user,id=net0,chardev=%s,vhostforce"
#define QEMU_CMD_NET " -device virtio-net-pci,netdev=net0,romfile=./pc-bios/pxe-virtio.rom"
@@ -129,25 +127,12 @@ typedef struct TestServer {
int fds_num;
int fds[VHOST_MEMORY_MAX_NREGIONS];
VhostUserMemory memory;
- GMutex data_mutex;
- GCond data_cond;
+ CompatGMutex data_mutex;
+ CompatGCond data_cond;
int log_fd;
uint64_t rings;
} TestServer;
-#if !GLIB_CHECK_VERSION(2, 32, 0)
-static gboolean g_cond_wait_until(CompatGCond cond, CompatGMutex mutex,
- gint64 end_time)
-{
- gboolean ret = FALSE;
- end_time -= g_get_monotonic_time();
- GTimeVal time = { end_time / G_TIME_SPAN_SECOND,
- end_time % G_TIME_SPAN_SECOND };
- ret = g_cond_timed_wait(cond, mutex, &time);
- return ret;
-}
-#endif
-
static const char *tmpfs;
static const char *root;
@@ -246,7 +231,12 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
if (msg.size) {
p += VHOST_USER_HDR_SIZE;
- g_assert_cmpint(qemu_chr_fe_read_all(chr, p, msg.size), ==, msg.size);
+ size = qemu_chr_fe_read_all(chr, p, msg.size);
+ if (size != msg.size) {
+ g_test_message("Wrong message size received %d != %d\n",
+ size, msg.size);
+ return;
+ }
}
switch (msg.request) {
@@ -363,17 +353,10 @@ static const char *init_hugepagefs(const char *path)
static TestServer *test_server_new(const gchar *name)
{
TestServer *server = g_new0(TestServer, 1);
- gchar *chr_path;
server->socket_path = g_strdup_printf("%s/%s.sock", tmpfs, name);
server->mig_path = g_strdup_printf("%s/%s.mig", tmpfs, name);
-
- chr_path = g_strdup_printf("unix:%s,server,nowait", server->socket_path);
server->chr_name = g_strdup_printf("chr-%s", name);
- server->chr = qemu_chr_new(server->chr_name, chr_path, NULL);
- g_free(chr_path);
-
- qemu_chr_add_handlers(server->chr, chr_can_read, chr_read, NULL, server);
g_mutex_init(&server->data_mutex);
g_cond_init(&server->data_cond);
@@ -383,13 +366,34 @@ static TestServer *test_server_new(const gchar *name)
return server;
}
-#define GET_QEMU_CMD(s) \
- g_strdup_printf(QEMU_CMD, 512, 512, (root), (s)->chr_name, \
- (s)->socket_path, (s)->chr_name)
+static void test_server_create_chr(TestServer *server, const gchar *opt)
+{
+ gchar *chr_path;
+
+ chr_path = g_strdup_printf("unix:%s%s", server->socket_path, opt);
+ server->chr = qemu_chr_new(server->chr_name, chr_path, NULL);
+ g_free(chr_path);
+
+ qemu_chr_add_handlers(server->chr, chr_can_read, chr_read, NULL, server);
+}
+
+static void test_server_listen(TestServer *server)
+{
+ test_server_create_chr(server, ",server,nowait");
+}
+
+static inline void test_server_connect(TestServer *server)
+{
+ test_server_create_chr(server, ",reconnect=1");
+}
+
+#define GET_QEMU_CMD(s) \
+ g_strdup_printf(QEMU_CMD, 512, 512, (root), (s)->chr_name, \
+ (s)->socket_path, "", (s)->chr_name)
-#define GET_QEMU_CMDE(s, mem, extra, ...) \
- g_strdup_printf(QEMU_CMD extra, (mem), (mem), (root), (s)->chr_name, \
- (s)->socket_path, (s)->chr_name, ##__VA_ARGS__)
+#define GET_QEMU_CMDE(s, mem, chr_opts, extra, ...) \
+ g_strdup_printf(QEMU_CMD extra, (mem), (mem), (root), (s)->chr_name, \
+ (s)->socket_path, (chr_opts), (s)->chr_name, ##__VA_ARGS__)
static gboolean _test_server_free(TestServer *server)
{
@@ -537,7 +541,10 @@ static void test_migrate(void)
guint8 *log;
guint64 size;
- cmd = GET_QEMU_CMDE(s, 2, "");
+ test_server_listen(s);
+ test_server_listen(dest);
+
+ cmd = GET_QEMU_CMDE(s, 2, "", "");
from = qtest_start(cmd);
g_free(cmd);
@@ -545,7 +552,7 @@ static void test_migrate(void)
size = get_log_size(s);
g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8));
- cmd = GET_QEMU_CMDE(dest, 2, " -incoming %s", uri);
+ cmd = GET_QEMU_CMDE(dest, 2, "", " -incoming %s", uri);
to = qtest_init(cmd);
g_free(cmd);
@@ -605,6 +612,81 @@ static void test_migrate(void)
global_qtest = global;
}
+#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
+static void wait_for_rings_started(TestServer *s, size_t count)
+{
+ gint64 end_time;
+
+ g_mutex_lock(&s->data_mutex);
+ end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
+ while (ctpop64(s->rings) != count) {
+ if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) {
+ /* timeout has passed */
+ g_assert_cmpint(ctpop64(s->rings), ==, count);
+ break;
+ }
+ }
+
+ g_mutex_unlock(&s->data_mutex);
+}
+
+static gboolean
+reconnect_cb(gpointer user_data)
+{
+ TestServer *s = user_data;
+
+ qemu_chr_disconnect(s->chr);
+
+ return FALSE;
+}
+
+static gpointer
+connect_thread(gpointer data)
+{
+ TestServer *s = data;
+
+ /* wait for qemu to start before first try, to avoid extra warnings */
+ g_usleep(G_USEC_PER_SEC);
+ test_server_connect(s);
+
+ return NULL;
+}
+
+static void test_reconnect_subprocess(void)
+{
+ TestServer *s = test_server_new("reconnect");
+ char *cmd;
+
+ g_thread_new("connect", connect_thread, s);
+ cmd = GET_QEMU_CMDE(s, 2, ",server", "");
+ qtest_start(cmd);
+ g_free(cmd);
+
+ wait_for_fds(s);
+ wait_for_rings_started(s, 2);
+
+ /* reconnect */
+ s->fds_num = 0;
+ s->rings = 0;
+ g_idle_add(reconnect_cb, s);
+ wait_for_fds(s);
+ wait_for_rings_started(s, 2);
+
+ qtest_end();
+ test_server_free(s);
+ return;
+}
+
+static void test_reconnect(void)
+{
+ gchar *path = g_strdup_printf("/%s/vhost-user/reconnect/subprocess",
+ qtest_get_arch());
+ g_test_trap_subprocess(path, 0, 0);
+ g_test_trap_assert_passed();
+ g_free(path);
+}
+#endif
+
int main(int argc, char **argv)
{
QTestState *s = NULL;
@@ -636,6 +718,7 @@ int main(int argc, char **argv)
}
server = test_server_new("test");
+ test_server_listen(server);
loop = g_main_loop_new(NULL, FALSE);
/* run the main loop thread so the chardev may operate */
@@ -648,6 +731,11 @@ int main(int argc, char **argv)
qtest_add_data_func("/vhost-user/read-guest-mem", server, read_guest_mem);
qtest_add_func("/vhost-user/migrate", test_migrate);
+#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
+ qtest_add_func("/vhost-user/reconnect/subprocess",
+ test_reconnect_subprocess);
+ qtest_add_func("/vhost-user/reconnect", test_reconnect);
+#endif
ret = g_test_run();
diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 59d0f1fa9b..1e39335a79 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "qemu-common.h"
diff --git a/tests/virtio-balloon-test.c b/tests/virtio-balloon-test.c
index b010ce98e8..0d0046bf25 100644
--- a/tests/virtio-balloon-test.c
+++ b/tests/virtio-balloon-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
index 3a66630d79..811cf756c8 100644
--- a/tests/virtio-blk-test.c
+++ b/tests/virtio-blk-test.c
@@ -9,7 +9,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/virtio.h"
#include "libqos/virtio-pci.h"
@@ -19,25 +18,11 @@
#include "libqos/malloc-pc.h"
#include "libqos/malloc-generic.h"
#include "qemu/bswap.h"
-
-#define QVIRTIO_BLK_F_BARRIER 0x00000001
-#define QVIRTIO_BLK_F_SIZE_MAX 0x00000002
-#define QVIRTIO_BLK_F_SEG_MAX 0x00000004
-#define QVIRTIO_BLK_F_GEOMETRY 0x00000010
-#define QVIRTIO_BLK_F_RO 0x00000020
-#define QVIRTIO_BLK_F_BLK_SIZE 0x00000040
-#define QVIRTIO_BLK_F_SCSI 0x00000080
-#define QVIRTIO_BLK_F_WCE 0x00000200
-#define QVIRTIO_BLK_F_TOPOLOGY 0x00000400
-#define QVIRTIO_BLK_F_CONFIG_WCE 0x00000800
-
-#define QVIRTIO_BLK_T_IN 0
-#define QVIRTIO_BLK_T_OUT 1
-#define QVIRTIO_BLK_T_SCSI_CMD 2
-#define QVIRTIO_BLK_T_SCSI_CMD_OUT 3
-#define QVIRTIO_BLK_T_FLUSH 4
-#define QVIRTIO_BLK_T_FLUSH_OUT 5
-#define QVIRTIO_BLK_T_GET_ID 8
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_config.h"
+#include "standard-headers/linux/virtio_ring.h"
+#include "standard-headers/linux/virtio_blk.h"
+#include "standard-headers/linux/virtio_pci.h"
#define TEST_IMAGE_SIZE (64 * 1024 * 1024)
#define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000)
@@ -119,9 +104,9 @@ static QVirtioPCIDevice *virtio_blk_pci_init(QPCIBus *bus, int slot)
{
QVirtioPCIDevice *dev;
- dev = qvirtio_pci_device_find(bus, QVIRTIO_BLK_DEVICE_ID);
+ dev = qvirtio_pci_device_find(bus, VIRTIO_ID_BLOCK);
g_assert(dev != NULL);
- g_assert_cmphex(dev->vdev.device_type, ==, QVIRTIO_BLK_DEVICE_ID);
+ g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
g_assert_cmphex(dev->pdev->devfn, ==, ((slot << 3) | PCI_FN));
qvirtio_pci_device_enable(dev);
@@ -182,15 +167,16 @@ static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
features = qvirtio_get_features(bus, dev);
features = features & ~(QVIRTIO_F_BAD_FEATURE |
- QVIRTIO_F_RING_INDIRECT_DESC | QVIRTIO_F_RING_EVENT_IDX |
- QVIRTIO_BLK_F_SCSI);
+ (1u << VIRTIO_RING_F_INDIRECT_DESC) |
+ (1u << VIRTIO_RING_F_EVENT_IDX) |
+ (1u << VIRTIO_BLK_F_SCSI));
qvirtio_set_features(bus, dev, features);
qvirtio_set_driver_ok(bus, dev);
/* Write and read with 3 descriptor layout */
/* Write request */
- req.type = QVIRTIO_BLK_T_OUT;
+ req.type = VIRTIO_BLK_T_OUT;
req.ioprio = 1;
req.sector = 0;
req.data = g_malloc0(512);
@@ -213,7 +199,7 @@ static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
guest_free(alloc, req_addr);
/* Read request */
- req.type = QVIRTIO_BLK_T_IN;
+ req.type = VIRTIO_BLK_T_IN;
req.ioprio = 1;
req.sector = 0;
req.data = g_malloc0(512);
@@ -239,10 +225,10 @@ static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
guest_free(alloc, req_addr);
- if (features & QVIRTIO_F_ANY_LAYOUT) {
+ if (features & (1u << VIRTIO_F_ANY_LAYOUT)) {
/* Write and read with 2 descriptor layout */
/* Write request */
- req.type = QVIRTIO_BLK_T_OUT;
+ req.type = VIRTIO_BLK_T_OUT;
req.ioprio = 1;
req.sector = 1;
req.data = g_malloc0(512);
@@ -263,7 +249,7 @@ static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
guest_free(alloc, req_addr);
/* Read request */
- req.type = QVIRTIO_BLK_T_IN;
+ req.type = VIRTIO_BLK_T_IN;
req.ioprio = 1;
req.sector = 1;
req.data = g_malloc0(512);
@@ -306,13 +292,13 @@ static void pci_basic(void)
alloc, 0);
/* MSI-X is not enabled */
- addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX;
+ addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
test_basic(&qvirtio_pci, &dev->vdev, alloc, &vqpci->vq,
(uint64_t)(uintptr_t)addr);
/* End test */
- guest_free(alloc, vqpci->vq.desc);
+ qvirtqueue_cleanup(&qvirtio_pci, &vqpci->vq, alloc);
pc_alloc_uninit(alloc);
qvirtio_pci_device_disable(dev);
g_free(dev);
@@ -341,16 +327,17 @@ static void pci_indirect(void)
dev = virtio_blk_pci_init(bus, PCI_SLOT);
/* MSI-X is not enabled */
- addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX;
+ addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
(uint64_t)(uintptr_t)addr);
g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
- g_assert_cmphex(features & QVIRTIO_F_RING_INDIRECT_DESC, !=, 0);
- features = features & ~(QVIRTIO_F_BAD_FEATURE | QVIRTIO_F_RING_EVENT_IDX |
- QVIRTIO_BLK_F_SCSI);
+ g_assert_cmphex(features & (1u << VIRTIO_RING_F_INDIRECT_DESC), !=, 0);
+ features = features & ~(QVIRTIO_F_BAD_FEATURE |
+ (1u << VIRTIO_RING_F_EVENT_IDX) |
+ (1u << VIRTIO_BLK_F_SCSI));
qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);
alloc = pc_alloc_init();
@@ -359,7 +346,7 @@ static void pci_indirect(void)
qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
/* Write request */
- req.type = QVIRTIO_BLK_T_OUT;
+ req.type = VIRTIO_BLK_T_OUT;
req.ioprio = 1;
req.sector = 0;
req.data = g_malloc0(512);
@@ -384,7 +371,7 @@ static void pci_indirect(void)
guest_free(alloc, req_addr);
/* Read request */
- req.type = QVIRTIO_BLK_T_IN;
+ req.type = VIRTIO_BLK_T_IN;
req.ioprio = 1;
req.sector = 0;
req.data = g_malloc0(512);
@@ -414,7 +401,7 @@ static void pci_indirect(void)
guest_free(alloc, req_addr);
/* End test */
- guest_free(alloc, vqpci->vq.desc);
+ qvirtqueue_cleanup(&qvirtio_pci, &vqpci->vq, alloc);
pc_alloc_uninit(alloc);
qvirtio_pci_device_disable(dev);
g_free(dev);
@@ -435,7 +422,7 @@ static void pci_config(void)
dev = virtio_blk_pci_init(bus, PCI_SLOT);
/* MSI-X is not enabled */
- addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX;
+ addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
(uint64_t)(uintptr_t)addr);
@@ -482,7 +469,7 @@ static void pci_msix(void)
qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
/* MSI-X is enabled */
- addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX;
+ addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(true);
capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
(uint64_t)(uintptr_t)addr);
@@ -490,8 +477,9 @@ static void pci_msix(void)
features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
features = features & ~(QVIRTIO_F_BAD_FEATURE |
- QVIRTIO_F_RING_INDIRECT_DESC |
- QVIRTIO_F_RING_EVENT_IDX | QVIRTIO_BLK_F_SCSI);
+ (1u << VIRTIO_RING_F_INDIRECT_DESC) |
+ (1u << VIRTIO_RING_F_EVENT_IDX) |
+ (1u << VIRTIO_BLK_F_SCSI));
qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);
vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
@@ -510,7 +498,7 @@ static void pci_msix(void)
g_assert_cmpint(capacity, ==, n_size / 512);
/* Write request */
- req.type = QVIRTIO_BLK_T_OUT;
+ req.type = VIRTIO_BLK_T_OUT;
req.ioprio = 1;
req.sector = 0;
req.data = g_malloc0(512);
@@ -534,7 +522,7 @@ static void pci_msix(void)
guest_free(alloc, req_addr);
/* Read request */
- req.type = QVIRTIO_BLK_T_IN;
+ req.type = VIRTIO_BLK_T_IN;
req.ioprio = 1;
req.sector = 0;
req.data = g_malloc0(512);
@@ -564,7 +552,7 @@ static void pci_msix(void)
guest_free(alloc, req_addr);
/* End test */
- guest_free(alloc, vqpci->vq.desc);
+ qvirtqueue_cleanup(&qvirtio_pci, &vqpci->vq, alloc);
pc_alloc_uninit(alloc);
qpci_msix_disable(dev->pdev);
qvirtio_pci_device_disable(dev);
@@ -597,7 +585,7 @@ static void pci_idx(void)
qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
/* MSI-X is enabled */
- addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX;
+ addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(true);
capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
(uint64_t)(uintptr_t)addr);
@@ -605,8 +593,9 @@ static void pci_idx(void)
features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
features = features & ~(QVIRTIO_F_BAD_FEATURE |
- QVIRTIO_F_RING_INDIRECT_DESC |
- QVIRTIO_F_NOTIFY_ON_EMPTY | QVIRTIO_BLK_F_SCSI);
+ (1u << VIRTIO_RING_F_INDIRECT_DESC) |
+ (1u << VIRTIO_F_NOTIFY_ON_EMPTY) |
+ (1u << VIRTIO_BLK_F_SCSI));
qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);
vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
@@ -616,7 +605,7 @@ static void pci_idx(void)
qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
/* Write request */
- req.type = QVIRTIO_BLK_T_OUT;
+ req.type = VIRTIO_BLK_T_OUT;
req.ioprio = 1;
req.sector = 0;
req.data = g_malloc0(512);
@@ -635,7 +624,7 @@ static void pci_idx(void)
QVIRTIO_BLK_TIMEOUT_US);
/* Write request */
- req.type = QVIRTIO_BLK_T_OUT;
+ req.type = VIRTIO_BLK_T_OUT;
req.ioprio = 1;
req.sector = 1;
req.data = g_malloc0(512);
@@ -661,7 +650,7 @@ static void pci_idx(void)
guest_free(alloc, req_addr);
/* Read request */
- req.type = QVIRTIO_BLK_T_IN;
+ req.type = VIRTIO_BLK_T_IN;
req.ioprio = 1;
req.sector = 1;
req.data = g_malloc0(512);
@@ -690,7 +679,7 @@ static void pci_idx(void)
guest_free(alloc, req_addr);
/* End test */
- guest_free(alloc, vqpci->vq.desc);
+ qvirtqueue_cleanup(&qvirtio_pci, &vqpci->vq, alloc);
pc_alloc_uninit(alloc);
qpci_msix_disable(dev->pdev);
qvirtio_pci_device_disable(dev);
@@ -733,7 +722,7 @@ static void mmio_basic(void)
dev = qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR, MMIO_PAGE_SIZE);
g_assert(dev != NULL);
- g_assert_cmphex(dev->vdev.device_type, ==, QVIRTIO_BLK_DEVICE_ID);
+ g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
qvirtio_reset(&qvirtio_mmio, &dev->vdev);
qvirtio_set_acknowledge(&qvirtio_mmio, &dev->vdev);
@@ -756,7 +745,7 @@ static void mmio_basic(void)
g_assert_cmpint(capacity, ==, n_size / 512);
/* End test */
- guest_free(alloc, vq->desc);
+ qvirtqueue_cleanup(&qvirtio_mmio, vq, alloc);
generic_alloc_uninit(alloc);
g_free(dev);
test_end();
@@ -764,7 +753,6 @@ static void mmio_basic(void)
int main(int argc, char **argv)
{
- int ret;
const char *arch = qtest_get_arch();
g_test_init(&argc, &argv, NULL);
@@ -780,7 +768,5 @@ int main(int argc, char **argv)
qtest_add_func("/virtio/blk/mmio/basic", mmio_basic);
}
- ret = g_test_run();
-
- return ret;
+ return g_test_run();
}
diff --git a/tests/virtio-console-test.c b/tests/virtio-console-test.c
index 0b9c2a55ef..1c3de072f4 100644
--- a/tests/virtio-console-test.c
+++ b/tests/virtio-console-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
@@ -28,13 +27,9 @@ static void serialport_pci_nop(void)
int main(int argc, char **argv)
{
- int ret;
-
g_test_init(&argc, &argv, NULL);
qtest_add_func("/virtio/console/pci/nop", console_pci_nop);
qtest_add_func("/virtio/serialport/pci/nop", serialport_pci_nop);
- ret = g_test_run();
-
- return ret;
+ return g_test_run();
}
diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c
index 04cfcd594e..361506faf5 100644
--- a/tests/virtio-net-test.c
+++ b/tests/virtio-net-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "qemu-common.h"
#include "qemu/sockets.h"
@@ -21,6 +20,8 @@
#include "libqos/malloc-generic.h"
#include "qemu/bswap.h"
#include "hw/virtio/virtio-net.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_ring.h"
#define PCI_SLOT_HP 0x06
#define PCI_SLOT 0x04
@@ -40,9 +41,9 @@ static QVirtioPCIDevice *virtio_net_pci_init(QPCIBus *bus, int slot)
{
QVirtioPCIDevice *dev;
- dev = qvirtio_pci_device_find(bus, QVIRTIO_NET_DEVICE_ID);
+ dev = qvirtio_pci_device_find(bus, VIRTIO_ID_NET);
g_assert(dev != NULL);
- g_assert_cmphex(dev->vdev.device_type, ==, QVIRTIO_NET_DEVICE_ID);
+ g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_NET);
qvirtio_pci_device_enable(dev);
qvirtio_reset(&qvirtio_pci, &dev->vdev);
@@ -70,8 +71,8 @@ static void driver_init(const QVirtioBus *bus, QVirtioDevice *dev)
features = qvirtio_get_features(bus, dev);
features = features & ~(QVIRTIO_F_BAD_FEATURE |
- QVIRTIO_F_RING_INDIRECT_DESC |
- QVIRTIO_F_RING_EVENT_IDX);
+ (1u << VIRTIO_RING_F_INDIRECT_DESC) |
+ (1u << VIRTIO_RING_F_EVENT_IDX));
qvirtio_set_features(bus, dev, features);
qvirtio_set_driver_ok(bus, dev);
@@ -148,6 +149,7 @@ static void rx_stop_cont_test(const QVirtioBus *bus, QVirtioDevice *dev,
char test[] = "TEST";
char buffer[64];
int len = htonl(sizeof(test));
+ QDict *rsp;
struct iovec iov[] = {
{
.iov_base = &len,
@@ -164,7 +166,8 @@ static void rx_stop_cont_test(const QVirtioBus *bus, QVirtioDevice *dev,
free_head = qvirtqueue_add(vq, req_addr, 64, true, false);
qvirtqueue_kick(bus, dev, vq, free_head);
- qmp("{ 'execute' : 'stop'}");
+ rsp = qmp("{ 'execute' : 'stop'}");
+ QDECREF(rsp);
ret = iov_send(socket, iov, 2, 0, sizeof(len) + sizeof(test));
g_assert_cmpint(ret, ==, sizeof(test) + sizeof(len));
@@ -172,8 +175,10 @@ static void rx_stop_cont_test(const QVirtioBus *bus, QVirtioDevice *dev,
/* We could check the status, but this command is more importantly to
* ensure the packet data gets queued in QEMU, before we do 'cont'.
*/
- qmp("{ 'execute' : 'query-status'}");
- qmp("{ 'execute' : 'cont'}");
+ rsp = qmp("{ 'execute' : 'query-status'}");
+ QDECREF(rsp);
+ rsp = qmp("{ 'execute' : 'cont'}");
+ QDECREF(rsp);
qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_NET_TIMEOUT_US);
memread(req_addr + VNET_HDR_SIZE, buffer, sizeof(test));
@@ -228,9 +233,11 @@ static void pci_basic(gconstpointer data)
/* End test */
close(sv[0]);
- guest_free(alloc, tx->vq.desc);
+ qvirtqueue_cleanup(&qvirtio_pci, &tx->vq, alloc);
+ qvirtqueue_cleanup(&qvirtio_pci, &rx->vq, alloc);
pc_alloc_uninit(alloc);
qvirtio_pci_device_disable(dev);
+ g_free(dev->pdev);
g_free(dev);
qpci_free_pc(bus);
test_end();
@@ -249,8 +256,6 @@ static void hotplug(void)
int main(int argc, char **argv)
{
- int ret;
-
g_test_init(&argc, &argv, NULL);
#ifndef _WIN32
qtest_add_data_func("/virtio/net/pci/basic", send_recv_test, pci_basic);
@@ -259,7 +264,5 @@ int main(int argc, char **argv)
#endif
qtest_add_func("/virtio/net/pci/hotplug", hotplug);
- ret = g_test_run();
-
- return ret;
+ return g_test_run();
}
diff --git a/tests/virtio-rng-test.c b/tests/virtio-rng-test.c
index 771dbd73af..e1b26401f9 100644
--- a/tests/virtio-rng-test.c
+++ b/tests/virtio-rng-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "libqos/pci.h"
diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
index d78747a466..f1489e68a0 100644
--- a/tests/virtio-scsi-test.c
+++ b/tests/virtio-scsi-test.c
@@ -9,7 +9,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "block/scsi.h"
#include "libqos/virtio.h"
@@ -18,11 +17,13 @@
#include "libqos/malloc.h"
#include "libqos/malloc-pc.h"
#include "libqos/malloc-generic.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_pci.h"
+#include "standard-headers/linux/virtio_scsi.h"
#define PCI_SLOT 0x02
#define PCI_FN 0x00
#define QVIRTIO_SCSI_TIMEOUT_US (1 * 1000 * 1000)
-#define CDB_SIZE 32
#define MAX_NUM_QUEUES 64
@@ -34,24 +35,6 @@ typedef struct {
QVirtQueue *vq[MAX_NUM_QUEUES + 2];
} QVirtIOSCSI;
-typedef struct {
- uint8_t lun[8];
- int64_t tag;
- uint8_t task_attr;
- uint8_t prio;
- uint8_t crn;
- uint8_t cdb[CDB_SIZE];
-} QEMU_PACKED QVirtIOSCSICmdReq;
-
-typedef struct {
- uint32_t sense_len;
- uint32_t resid;
- uint16_t status_qualifier;
- uint8_t status;
- uint8_t response;
- uint8_t sense[96];
-} QEMU_PACKED QVirtIOSCSICmdResp;
-
static void qvirtio_scsi_start(const char *extra_opts)
{
char *cmdline;
@@ -75,7 +58,7 @@ static void qvirtio_scsi_pci_free(QVirtIOSCSI *vs)
int i;
for (i = 0; i < vs->num_queues + 2; i++) {
- guest_free(vs->alloc, vs->vq[i]->desc);
+ qvirtqueue_cleanup(&qvirtio_pci, vs->vq[i], vs->alloc);
}
pc_alloc_uninit(vs->alloc);
qvirtio_pci_device_disable(container_of(vs->dev, QVirtioPCIDevice, vdev));
@@ -100,11 +83,11 @@ static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb,
const uint8_t *data_in,
size_t data_in_len,
uint8_t *data_out, size_t data_out_len,
- QVirtIOSCSICmdResp *resp_out)
+ struct virtio_scsi_cmd_resp *resp_out)
{
QVirtQueue *vq;
- QVirtIOSCSICmdReq req = { { 0 } };
- QVirtIOSCSICmdResp resp = { .response = 0xff, .status = 0xff };
+ struct virtio_scsi_cmd_req req = { { 0 } };
+ struct virtio_scsi_cmd_resp resp = { .response = 0xff, .status = 0xff };
uint64_t req_addr, resp_addr, data_in_addr = 0, data_out_addr = 0;
uint8_t response;
uint32_t free_head;
@@ -113,7 +96,7 @@ static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb,
req.lun[0] = 1; /* Select LUN */
req.lun[1] = 1; /* Select target 1 */
- memcpy(req.cdb, cdb, CDB_SIZE);
+ memcpy(req.cdb, cdb, VIRTIO_SCSI_CDB_SIZE);
/* XXX: Fix endian if any multi-byte field in req/resp is used */
@@ -138,7 +121,8 @@ static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb,
qvirtqueue_kick(&qvirtio_pci, vs->dev, vq, free_head);
qvirtio_wait_queue_isr(&qvirtio_pci, vs->dev, vq, QVIRTIO_SCSI_TIMEOUT_US);
- response = readb(resp_addr + offsetof(QVirtIOSCSICmdResp, response));
+ response = readb(resp_addr +
+ offsetof(struct virtio_scsi_cmd_resp, response));
if (resp_out) {
memread(resp_addr, resp_out, sizeof(*resp_out));
@@ -153,10 +137,10 @@ static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb,
static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
{
- const uint8_t test_unit_ready_cdb[CDB_SIZE] = {};
+ const uint8_t test_unit_ready_cdb[VIRTIO_SCSI_CDB_SIZE] = {};
QVirtIOSCSI *vs;
QVirtioPCIDevice *dev;
- QVirtIOSCSICmdResp resp;
+ struct virtio_scsi_cmd_resp resp;
void *addr;
int i;
@@ -164,17 +148,17 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
vs->alloc = pc_alloc_init();
vs->bus = qpci_init_pc();
- dev = qvirtio_pci_device_find(vs->bus, QVIRTIO_SCSI_DEVICE_ID);
+ dev = qvirtio_pci_device_find(vs->bus, VIRTIO_ID_SCSI);
vs->dev = (QVirtioDevice *)dev;
g_assert(dev != NULL);
- g_assert_cmphex(vs->dev->device_type, ==, QVIRTIO_SCSI_DEVICE_ID);
+ g_assert_cmphex(vs->dev->device_type, ==, VIRTIO_ID_SCSI);
qvirtio_pci_device_enable(dev);
qvirtio_reset(&qvirtio_pci, vs->dev);
qvirtio_set_acknowledge(&qvirtio_pci, vs->dev);
qvirtio_set_driver(&qvirtio_pci, vs->dev);
- addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX;
+ addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
vs->num_queues = qvirtio_config_readl(&qvirtio_pci, vs->dev,
(uint64_t)(uintptr_t)addr);
@@ -239,10 +223,12 @@ static void test_unaligned_write_same(void)
QVirtIOSCSI *vs;
uint8_t buf1[512] = { 0 };
uint8_t buf2[512] = { 1 };
- const uint8_t write_same_cdb_1[CDB_SIZE] = { 0x41, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x02, 0x00 };
- const uint8_t write_same_cdb_2[CDB_SIZE] = { 0x41, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x33, 0x00, 0x00 };
+ const uint8_t write_same_cdb_1[VIRTIO_SCSI_CDB_SIZE] = {
+ 0x41, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00
+ };
+ const uint8_t write_same_cdb_2[VIRTIO_SCSI_CDB_SIZE] = {
+ 0x41, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x33, 0x00, 0x00
+ };
qvirtio_scsi_start("-drive file=blkdebug::null-co://,if=none,id=dr1"
",format=raw,file.align=4k "
@@ -261,15 +247,11 @@ static void test_unaligned_write_same(void)
int main(int argc, char **argv)
{
- int ret;
-
g_test_init(&argc, &argv, NULL);
qtest_add_func("/virtio/scsi/pci/nop", pci_nop);
qtest_add_func("/virtio/scsi/pci/hotplug", hotplug);
qtest_add_func("/virtio/scsi/pci/scsi-disk/unaligned-write-same",
test_unaligned_write_same);
- ret = g_test_run();
-
- return ret;
+ return g_test_run();
}
diff --git a/tests/virtio-serial-test.c b/tests/virtio-serial-test.c
index 480d4abb2d..b14d943ada 100644
--- a/tests/virtio-serial-test.c
+++ b/tests/virtio-serial-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
diff --git a/tests/vmxnet3-test.c b/tests/vmxnet3-test.c
index 6ef0e2f043..159c0ad728 100644
--- a/tests/vmxnet3-test.c
+++ b/tests/vmxnet3-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
diff --git a/tests/wdt_ib700-test.c b/tests/wdt_ib700-test.c
index efe3370453..49f4f0c221 100644
--- a/tests/wdt_ib700-test.c
+++ b/tests/wdt_ib700-test.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "qemu/timer.h"
@@ -118,15 +117,11 @@ static void ib700_none(void)
int main(int argc, char **argv)
{
- int ret;
-
g_test_init(&argc, &argv, NULL);
qtest_add_func("/wdt_ib700/pause", ib700_pause);
qtest_add_func("/wdt_ib700/reset", ib700_reset);
qtest_add_func("/wdt_ib700/shutdown", ib700_shutdown);
qtest_add_func("/wdt_ib700/none", ib700_none);
- ret = g_test_run();
-
- return ret;
+ return g_test_run();
}