diff options
author | SeokYeon Hwang <syeon.hwang@samsung.com> | 2016-11-30 14:11:48 +0900 |
---|---|---|
committer | SeokYeon Hwang <syeon.hwang@samsung.com> | 2016-11-30 14:11:58 +0900 |
commit | 2371603ef207b015cc29728296b21cb1722d8ae6 (patch) | |
tree | 25cbb62daf29066fa874b9a4b8f754bc18187806 /tests | |
parent | d5df306aedcc13cf5a2463ddf858c8d718a788d5 (diff) | |
parent | d4dcb59384ab4433702f015fdddda1eff8e3927f (diff) | |
download | qemu-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')
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 Binary files differnew file mode 100644 index 0000000000..1bf8a0a63b --- /dev/null +++ b/tests/acpi-test-data/pc/APIC.cphp diff --git a/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT Binary files differindex 9d1274d3c2..8053d71105 100644 --- a/tests/acpi-test-data/pc/DSDT +++ b/tests/acpi-test-data/pc/DSDT diff --git a/tests/acpi-test-data/pc/DSDT.bridge b/tests/acpi-test-data/pc/DSDT.bridge Binary files differindex cf48c62aa7..850e71a973 100644 --- a/tests/acpi-test-data/pc/DSDT.bridge +++ b/tests/acpi-test-data/pc/DSDT.bridge diff --git a/tests/acpi-test-data/pc/DSDT.cphp b/tests/acpi-test-data/pc/DSDT.cphp Binary files differnew file mode 100644 index 0000000000..e8b146208e --- /dev/null +++ b/tests/acpi-test-data/pc/DSDT.cphp diff --git a/tests/acpi-test-data/pc/DSDT.ipmikcs b/tests/acpi-test-data/pc/DSDT.ipmikcs Binary files differnew file mode 100644 index 0000000000..8ac48afb6a --- /dev/null +++ b/tests/acpi-test-data/pc/DSDT.ipmikcs diff --git a/tests/acpi-test-data/q35/APIC.cphp b/tests/acpi-test-data/q35/APIC.cphp Binary files differnew file mode 100644 index 0000000000..1bf8a0a63b --- /dev/null +++ b/tests/acpi-test-data/q35/APIC.cphp diff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT Binary files differindex 1c089c34b0..58fbb3d2e2 100644 --- a/tests/acpi-test-data/q35/DSDT +++ b/tests/acpi-test-data/q35/DSDT diff --git a/tests/acpi-test-data/q35/DSDT.bridge b/tests/acpi-test-data/q35/DSDT.bridge Binary files differindex b29fcda0bb..c392802a95 100644 --- a/tests/acpi-test-data/q35/DSDT.bridge +++ b/tests/acpi-test-data/q35/DSDT.bridge diff --git a/tests/acpi-test-data/q35/DSDT.cphp b/tests/acpi-test-data/q35/DSDT.cphp Binary files differnew file mode 100644 index 0000000000..6cc28c6dae --- /dev/null +++ b/tests/acpi-test-data/q35/DSDT.cphp diff --git a/tests/acpi-test-data/q35/DSDT.ipmibt b/tests/acpi-test-data/q35/DSDT.ipmibt Binary files differnew file mode 100644 index 0000000000..0ea38e1e72 --- /dev/null +++ b/tests/acpi-test-data/q35/DSDT.ipmibt 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(); } |