aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml8
-rw-r--r--.gitlab-ci.yml28
-rw-r--r--.shippable.yml4
-rw-r--r--.travis.yml114
-rw-r--r--MAINTAINERS19
-rw-r--r--Makefile.objs1
-rw-r--r--accel/tcg/cpu-exec.c4
-rw-r--r--accel/tcg/translate-all.c4
-rw-r--r--accel/tcg/translator.c4
-rw-r--r--audio/audio.c2
-rw-r--r--audio/paaudio.c70
-rw-r--r--backends/Makefile.objs4
-rw-r--r--backends/dbus-vmstate.c510
-rw-r--r--backends/trace-events7
-rw-r--r--block.c107
-rw-r--r--block/Makefile.objs1
-rw-r--r--block/backup-top.c4
-rw-r--r--block/blkdebug.c93
-rw-r--r--block/filter-compress.c168
-rw-r--r--block/qcow2-bitmap.c41
-rw-r--r--block/qcow2.c123
-rw-r--r--block/throttle-groups.c4
-rw-r--r--blockjob.c3
-rw-r--r--bsd-user/main.c2
-rwxr-xr-xconfigure34
-rw-r--r--contrib/vhost-user-gpu/50-qemu-gpu.json.in2
-rw-r--r--docs/arm-cpu-features.rst6
-rw-r--r--docs/devel/testing.rst6
-rw-r--r--docs/interop/dbus-vmstate.rst74
-rw-r--r--docs/interop/dbus.rst110
-rw-r--r--docs/interop/index.rst2
-rw-r--r--docs/virtio-net-failover.rst4
-rw-r--r--docs/virtio-pmem.rst19
-rw-r--r--exec.c4
-rw-r--r--hmp-commands.hx8
-rw-r--r--hw/arm/aspeed_ast2600.c3
-rw-r--r--hw/arm/sbsa-ref.c1
-rw-r--r--hw/arm/smmuv3-internal.h6
-rw-r--r--hw/arm/smmuv3.c28
-rw-r--r--hw/audio/hda-codec.c8
-rw-r--r--hw/block/dataplane/virtio-blk.c2
-rw-r--r--hw/block/onenand.c2
-rw-r--r--hw/core/Makefile.objs1
-rw-r--r--hw/core/machine.c4
-rw-r--r--hw/core/numa.c7
-rw-r--r--hw/core/qdev.c21
-rw-r--r--hw/core/vmstate-if.c23
-rw-r--r--hw/display/bochs-display.c2
-rw-r--r--hw/display/qxl-render.c9
-rw-r--r--hw/display/qxl.c1
-rw-r--r--hw/ide/cmd646.c2
-rw-r--r--hw/ide/isa.c2
-rw-r--r--hw/ide/piix.c2
-rw-r--r--hw/ide/via.c2
-rw-r--r--hw/misc/max111x.c2
-rw-r--r--hw/net/can/can_sja1000.c4
-rw-r--r--hw/net/eepro100.c4
-rw-r--r--hw/net/virtio-net.c3
-rw-r--r--hw/nvram/eeprom93xx.c4
-rw-r--r--hw/ppc/spapr_drc.c9
-rw-r--r--hw/ppc/spapr_iommu.c4
-rw-r--r--hw/s390x/s390-skeys.c2
-rw-r--r--include/block/block.h1
-rw-r--r--include/exec/log.h34
-rw-r--r--include/hw/vmstate-if.h40
-rw-r--r--include/migration/register.h4
-rw-r--r--include/migration/vmstate.h10
-rw-r--r--include/qemu/dbus.h19
-rw-r--r--include/qemu/log.h48
-rw-r--r--include/qemu/osdep.h1
-rw-r--r--include/qom/object.h3
-rw-r--r--include/ui/console.h2
-rw-r--r--include/ui/qemu-pixman.h2
-rw-r--r--linux-user/main.c2
-rw-r--r--linux-user/mmap.c56
-rw-r--r--linux-user/trace-events6
-rw-r--r--migration/savevm.c20
-rw-r--r--monitor/hmp-cmds.c28
-rw-r--r--monitor/misc.c3
-rw-r--r--net/can/can_socketcan.c5
-rw-r--r--pc-bios/bios-256k.binbin262144 -> 262144 bytes
-rw-r--r--pc-bios/bios.binbin131072 -> 131072 bytes
-rw-r--r--pc-bios/s390-ccw.imgbin42608 -> 42608 bytes
-rw-r--r--pc-bios/s390-ccw/jump2ipl.c12
-rw-r--r--pc-bios/s390-netboot.imgbin67232 -> 67232 bytes
-rw-r--r--pc-bios/vgabios-ati.binbin39424 -> 39424 bytes
-rw-r--r--pc-bios/vgabios-bochs-display.binbin28672 -> 28672 bytes
-rw-r--r--pc-bios/vgabios-cirrus.binbin38912 -> 38912 bytes
-rw-r--r--pc-bios/vgabios-qxl.binbin39424 -> 39424 bytes
-rw-r--r--pc-bios/vgabios-ramfb.binbin28672 -> 28672 bytes
-rw-r--r--pc-bios/vgabios-stdvga.binbin39424 -> 39424 bytes
-rw-r--r--pc-bios/vgabios-virtio.binbin39424 -> 39424 bytes
-rw-r--r--pc-bios/vgabios-vmware.binbin39424 -> 39424 bytes
-rw-r--r--pc-bios/vgabios.binbin38912 -> 38912 bytes
-rw-r--r--qapi/block-core.json30
-rw-r--r--qemu-deprecated.texi19
-rw-r--r--qemu-doc.texi1
-rw-r--r--qemu-img.c3
-rw-r--r--qemu-options.hx4
-rw-r--r--roms/config.seabios-128k1
m---------roms/seabios0
-rw-r--r--stubs/vmstate.c4
-rw-r--r--target/arm/arm-powerctl.c3
-rw-r--r--target/arm/cpu.c65
-rw-r--r--target/arm/cpu.h5
-rw-r--r--target/arm/helper.c42
-rw-r--r--target/cris/translate.c4
-rw-r--r--target/i386/cpu.c8
-rw-r--r--target/i386/translate.c5
-rw-r--r--target/lm32/translate.c4
-rw-r--r--target/microblaze/translate.c4
-rw-r--r--target/nios2/translate.c4
-rw-r--r--target/s390x/cpu.c12
-rw-r--r--target/s390x/cpu.h1
-rw-r--r--target/s390x/helper.h5
-rw-r--r--target/s390x/insn-data.def8
-rw-r--r--target/s390x/mem_helper.c38
-rw-r--r--target/s390x/misc_helper.c10
-rw-r--r--target/s390x/translate.c21
-rw-r--r--target/sparc/TODO88
-rw-r--r--target/tilegx/translate.c6
-rw-r--r--target/unicore32/translate.c4
-rw-r--r--target/xtensa/cpu.h10
-rwxr-xr-xtarget/xtensa/import_core.sh6
-rw-r--r--target/xtensa/overlay_tool.h15
-rw-r--r--target/xtensa/translate.c3
-rw-r--r--tcg/tcg.c28
-rw-r--r--tests/Makefile.include30
-rw-r--r--tests/boot-sector.c4
-rwxr-xr-xtests/dbus-vmstate-daemon.sh95
-rw-r--r--tests/dbus-vmstate-test.c382
-rw-r--r--tests/dbus-vmstate1.xml12
-rwxr-xr-xtests/docker/common.rc7
-rw-r--r--tests/docker/dockerfiles/centos7.docker1
-rw-r--r--tests/docker/dockerfiles/debian10.docker1
-rw-r--r--tests/docker/dockerfiles/fedora.docker1
-rw-r--r--tests/docker/dockerfiles/ubuntu.docker1
-rw-r--r--tests/hd-geo-test.c12
-rw-r--r--tests/migration-helpers.c167
-rw-r--r--tests/migration-helpers.h37
-rw-r--r--tests/migration-test.c176
-rwxr-xr-xtests/qemu-iotests/0055
-rwxr-xr-xtests/qemu-iotests/0075
-rwxr-xr-xtests/qemu-iotests/0142
-rwxr-xr-xtests/qemu-iotests/0155
-rwxr-xr-xtests/qemu-iotests/0196
-rwxr-xr-xtests/qemu-iotests/0206
-rwxr-xr-xtests/qemu-iotests/02410
-rwxr-xr-xtests/qemu-iotests/0265
-rwxr-xr-xtests/qemu-iotests/0282
-rwxr-xr-xtests/qemu-iotests/0297
-rwxr-xr-xtests/qemu-iotests/0304
-rwxr-xr-xtests/qemu-iotests/0319
-rw-r--r--tests/qemu-iotests/031.out36
-rwxr-xr-xtests/qemu-iotests/03615
-rw-r--r--tests/qemu-iotests/036.out66
-rwxr-xr-xtests/qemu-iotests/03927
-rw-r--r--tests/qemu-iotests/039.out22
-rwxr-xr-xtests/qemu-iotests/04144
-rw-r--r--tests/qemu-iotests/041.out4
-rwxr-xr-xtests/qemu-iotests/0434
-rwxr-xr-xtests/qemu-iotests/0462
-rwxr-xr-xtests/qemu-iotests/0484
-rwxr-xr-xtests/qemu-iotests/0495
-rw-r--r--tests/qemu-iotests/049.out5
-rwxr-xr-xtests/qemu-iotests/0508
-rwxr-xr-xtests/qemu-iotests/0518
-rwxr-xr-xtests/qemu-iotests/0534
-rwxr-xr-xtests/qemu-iotests/0587
-rwxr-xr-xtests/qemu-iotests/05920
-rwxr-xr-xtests/qemu-iotests/06017
-rw-r--r--tests/qemu-iotests/060.out20
-rwxr-xr-xtests/qemu-iotests/06163
-rw-r--r--tests/qemu-iotests/061.out72
-rwxr-xr-xtests/qemu-iotests/0625
-rwxr-xr-xtests/qemu-iotests/06318
-rw-r--r--tests/qemu-iotests/063.out3
-rwxr-xr-xtests/qemu-iotests/0667
-rwxr-xr-xtests/qemu-iotests/0676
-rwxr-xr-xtests/qemu-iotests/0686
-rwxr-xr-xtests/qemu-iotests/0692
-rwxr-xr-xtests/qemu-iotests/0717
-rwxr-xr-xtests/qemu-iotests/0734
-rwxr-xr-xtests/qemu-iotests/0744
-rwxr-xr-xtests/qemu-iotests/0796
-rwxr-xr-xtests/qemu-iotests/0807
-rwxr-xr-xtests/qemu-iotests/0816
-rwxr-xr-xtests/qemu-iotests/08518
-rw-r--r--tests/qemu-iotests/085.out8
-rwxr-xr-xtests/qemu-iotests/0882
-rwxr-xr-xtests/qemu-iotests/0902
-rwxr-xr-xtests/qemu-iotests/0912
-rw-r--r--tests/qemu-iotests/091.out2
-rwxr-xr-xtests/qemu-iotests/0922
-rwxr-xr-xtests/qemu-iotests/0944
-rwxr-xr-xtests/qemu-iotests/0955
-rwxr-xr-xtests/qemu-iotests/0986
-rwxr-xr-xtests/qemu-iotests/09910
-rwxr-xr-xtests/qemu-iotests/1035
-rwxr-xr-xtests/qemu-iotests/1062
-rwxr-xr-xtests/qemu-iotests/10810
-rwxr-xr-xtests/qemu-iotests/1094
-rwxr-xr-xtests/qemu-iotests/11011
-rw-r--r--tests/qemu-iotests/110.out4
-rwxr-xr-xtests/qemu-iotests/1113
-rwxr-xr-xtests/qemu-iotests/11237
-rwxr-xr-xtests/qemu-iotests/1142
-rwxr-xr-xtests/qemu-iotests/1153
-rwxr-xr-xtests/qemu-iotests/1219
-rwxr-xr-xtests/qemu-iotests/1226
-rwxr-xr-xtests/qemu-iotests/1234
-rwxr-xr-xtests/qemu-iotests/1252
-rwxr-xr-xtests/qemu-iotests/13717
-rw-r--r--tests/qemu-iotests/137.out6
-rwxr-xr-xtests/qemu-iotests/1388
-rwxr-xr-xtests/qemu-iotests/1414
-rwxr-xr-xtests/qemu-iotests/1422
-rwxr-xr-xtests/qemu-iotests/1444
-rwxr-xr-xtests/qemu-iotests/15312
-rwxr-xr-xtests/qemu-iotests/15610
-rwxr-xr-xtests/qemu-iotests/1592
-rwxr-xr-xtests/qemu-iotests/1603
-rwxr-xr-xtests/qemu-iotests/1614
-rwxr-xr-xtests/qemu-iotests/1702
-rwxr-xr-xtests/qemu-iotests/1726
-rwxr-xr-xtests/qemu-iotests/1733
-rwxr-xr-xtests/qemu-iotests/1742
-rwxr-xr-xtests/qemu-iotests/1752
-rwxr-xr-xtests/qemu-iotests/1767
-rwxr-xr-xtests/qemu-iotests/1786
-rwxr-xr-xtests/qemu-iotests/1822
-rwxr-xr-xtests/qemu-iotests/1832
-rwxr-xr-xtests/qemu-iotests/1854
-rwxr-xr-xtests/qemu-iotests/1876
-rwxr-xr-xtests/qemu-iotests/1904
-rwxr-xr-xtests/qemu-iotests/19111
-rwxr-xr-xtests/qemu-iotests/1952
-rwxr-xr-xtests/qemu-iotests/1976
-rwxr-xr-xtests/qemu-iotests/1986
-rw-r--r--tests/qemu-iotests/198.out4
-rwxr-xr-xtests/qemu-iotests/2007
-rwxr-xr-xtests/qemu-iotests/2016
-rwxr-xr-xtests/qemu-iotests/206232
-rwxr-xr-xtests/qemu-iotests/2078
-rwxr-xr-xtests/qemu-iotests/21081
-rwxr-xr-xtests/qemu-iotests/21112
-rwxr-xr-xtests/qemu-iotests/212101
-rwxr-xr-xtests/qemu-iotests/213113
-rwxr-xr-xtests/qemu-iotests/21446
-rw-r--r--tests/qemu-iotests/214.out14
-rwxr-xr-xtests/qemu-iotests/2156
-rwxr-xr-xtests/qemu-iotests/2173
-rwxr-xr-xtests/qemu-iotests/22011
-rwxr-xr-xtests/qemu-iotests/2252
-rwxr-xr-xtests/qemu-iotests/2293
-rwxr-xr-xtests/qemu-iotests/2324
-rwxr-xr-xtests/qemu-iotests/2352
-rwxr-xr-xtests/qemu-iotests/237139
-rwxr-xr-xtests/qemu-iotests/24310
-rwxr-xr-xtests/qemu-iotests/24415
-rwxr-xr-xtests/qemu-iotests/2474
-rwxr-xr-xtests/qemu-iotests/2494
-rwxr-xr-xtests/qemu-iotests/2505
-rwxr-xr-xtests/qemu-iotests/2522
-rwxr-xr-xtests/qemu-iotests/25510
-rwxr-xr-xtests/qemu-iotests/2615
-rwxr-xr-xtests/qemu-iotests/2652
-rwxr-xr-xtests/qemu-iotests/26669
-rw-r--r--tests/qemu-iotests/266.out14
-rwxr-xr-xtests/qemu-iotests/26718
-rwxr-xr-xtests/qemu-iotests/2736
-rw-r--r--tests/qemu-iotests/273.out27
-rwxr-xr-xtests/qemu-iotests/27957
-rw-r--r--tests/qemu-iotests/279.out35
-rwxr-xr-xtests/qemu-iotests/28083
-rw-r--r--tests/qemu-iotests/280.out50
-rwxr-xr-xtests/qemu-iotests/check6
-rw-r--r--tests/qemu-iotests/common.filter47
-rw-r--r--tests/qemu-iotests/common.rc76
-rw-r--r--tests/qemu-iotests/group2
-rw-r--r--tests/qemu-iotests/iotests.py43
-rwxr-xr-xtests/qemu-iotests/qcow2.py23
-rw-r--r--tests/tcg/Makefile.prereqs2
-rwxr-xr-xtests/tcg/configure.sh6
-rw-r--r--tests/test-keyval.c2
-rw-r--r--tests/test-logging.c80
-rw-r--r--tests/test-util-filemonitor.c11
-rw-r--r--tests/vm/Makefile.include1
-rwxr-xr-xtests/vm/basevm.py5
-rwxr-xr-xtests/vm/centos2
-rwxr-xr-xtests/vm/fedora4
-rwxr-xr-xtests/vm/freebsd3
-rwxr-xr-xtests/vm/netbsd3
-rwxr-xr-xtests/vm/openbsd3
-rwxr-xr-xtests/vm/ubuntu.i3862
-rw-r--r--trace/control.c35
-rw-r--r--ui/console.c73
-rw-r--r--ui/trace-events2
-rw-r--r--util/Makefile.objs3
-rw-r--r--util/cutils.c8
-rw-r--r--util/dbus.c57
-rw-r--r--util/log.c100
-rw-r--r--util/osdep.c15
303 files changed, 4372 insertions, 1793 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 27efc48..90645fe 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -22,7 +22,9 @@ macos_task:
install_script:
- brew install pkg-config python gnu-sed glib pixman make sdl2
script:
- - ./configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; }
+ - mkdir build
+ - cd build
+ - ../configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; }
- gmake -j$(sysctl -n hw.ncpu)
- gmake check -j$(sysctl -n hw.ncpu)
@@ -33,6 +35,8 @@ macos_xcode_task:
install_script:
- brew install pkg-config gnu-sed glib pixman make sdl2
script:
- - ./configure --cc=clang || { cat config.log; exit 1; }
+ - mkdir build
+ - cd build
+ - ../configure --cc=clang || { cat config.log; exit 1; }
- gmake -j$(sysctl -n hw.ncpu)
- gmake check -j$(sysctl -n hw.ncpu)
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e3db1b8..ebcef0e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -6,7 +6,9 @@ build-system1:
script:
- apt-get install -y -qq libgtk-3-dev libvte-dev nettle-dev libcacard-dev
libusb-dev libvde-dev libspice-protocol-dev libgl1-mesa-dev libvdeplug-dev
- - ./configure --enable-werror --target-list="aarch64-softmmu alpha-softmmu
+ - mkdir build
+ - cd build
+ - ../configure --enable-werror --target-list="aarch64-softmmu alpha-softmmu
cris-softmmu hppa-softmmu lm32-softmmu moxie-softmmu microblazeel-softmmu
mips64el-softmmu m68k-softmmu ppc-softmmu riscv64-softmmu sparc-softmmu"
- make -j2
@@ -16,7 +18,9 @@ build-system2:
script:
- apt-get install -y -qq libsdl2-dev libgcrypt-dev libbrlapi-dev libaio-dev
libfdt-dev liblzo2-dev librdmacm-dev libibverbs-dev libibumad-dev
- - ./configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu
+ - mkdir build
+ - cd build
+ - ../configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu
microblaze-softmmu mips-softmmu riscv32-softmmu s390x-softmmu sh4-softmmu
sparc64-softmmu x86_64-softmmu xtensa-softmmu nios2-softmmu or1k-softmmu"
- make -j2
@@ -24,7 +28,9 @@ build-system2:
build-disabled:
script:
- - ./configure --enable-werror --disable-rdma --disable-slirp --disable-curl
+ - mkdir build
+ - cd build
+ - ../configure --enable-werror --disable-rdma --disable-slirp --disable-curl
--disable-capstone --disable-live-block-migration --disable-glusterfs
--disable-replication --disable-coroutine-pool --disable-smartcard
--disable-guest-agent --disable-curses --disable-libxml2 --disable-tpm
@@ -37,7 +43,9 @@ build-disabled:
build-tcg-disabled:
script:
- apt-get install -y -qq clang libgtk-3-dev libusb-dev
- - ./configure --cc=clang --enable-werror --disable-tcg --audio-drv-list=""
+ - mkdir build
+ - cd build
+ - ../configure --cc=clang --enable-werror --disable-tcg --audio-drv-list=""
- make -j2
- make check-unit
- make check-qapi-schema
@@ -52,7 +60,9 @@ build-tcg-disabled:
build-user:
script:
- - ./configure --enable-werror --disable-system --disable-guest-agent
+ - mkdir build
+ - cd build
+ - ../configure --enable-werror --disable-system --disable-guest-agent
--disable-capstone --disable-slirp --disable-fdt
- make -j2
- make run-tcg-tests-i386-linux-user run-tcg-tests-x86_64-linux-user
@@ -61,7 +71,9 @@ build-clang:
script:
- apt-get install -y -qq clang libsdl2-dev libattr1-dev libcap-ng-dev
xfslibs-dev libiscsi-dev libnfs-dev libseccomp-dev gnutls-dev librbd-dev
- - ./configure --cc=clang --cxx=clang++ --enable-werror
+ - mkdir build
+ - cd build
+ - ../configure --cc=clang --cxx=clang++ --enable-werror
--target-list="alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu
ppc-softmmu s390x-softmmu x86_64-softmmu arm-linux-user"
- make -j2
@@ -70,7 +82,9 @@ build-clang:
build-tci:
script:
- TARGETS="aarch64 alpha arm hppa m68k microblaze moxie ppc64 s390x x86_64"
- - ./configure --enable-tcg-interpreter
+ - mkdir build
+ - cd build
+ - ../configure --enable-tcg-interpreter
--target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)"
- make -j2
- make tests/boot-serial-test tests/cdrom-test tests/pxe-test
diff --git a/.shippable.yml b/.shippable.yml
index f74a3de..83aae08 100644
--- a/.shippable.yml
+++ b/.shippable.yml
@@ -35,5 +35,7 @@ build:
options: "-e HOME=/root"
ci:
- unset CC
- - ./configure ${QEMU_CONFIGURE_OPTS} --target-list=${TARGET_LIST}
+ - mkdir build
+ - cd build
+ - ../configure ${QEMU_CONFIGURE_OPTS} --target-list=${TARGET_LIST}
- make -j$(($(getconf _NPROCESSORS_ONLN) + 1))
diff --git a/.travis.yml b/.travis.yml
index 6cb8af6..638fba4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -73,8 +73,8 @@ notifications:
env:
global:
- - SRC_DIR="."
- - BUILD_DIR="."
+ - SRC_DIR=".."
+ - BUILD_DIR="build"
- BASE_CONFIG="--disable-docs --disable-tools"
- TEST_CMD="make check V=1"
# This is broadly a list of "mainline" softmmu targets which have support across the major distros
@@ -181,17 +181,12 @@ matrix:
- env:
- - CONFIG="--disable-user --target-list=${MAIN_SOFTMMU_TARGETS}"
- - CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-default"
- compiler: clang
-
-
- - env:
- CONFIG="--target-list=${MAIN_SOFTMMU_TARGETS} "
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-sanitize"
compiler: clang
before_script:
- - ./configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log && exit 1; }
+ - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
+ - ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log && exit 1; }
- env:
@@ -214,10 +209,11 @@ matrix:
- TEST_CMD=""
- # We manually include builds which we disable "make check" for
+ # Check the TCG interpreter (TCI)
- env:
- - CONFIG="--enable-debug --enable-tcg-interpreter"
- - TEST_CMD=""
+ - CONFIG="--enable-debug-tcg --enable-tcg-interpreter --disable-kvm --disable-containers
+ --target-list=alpha-softmmu,arm-softmmu,hppa-softmmu,m68k-softmmu,microblaze-softmmu,moxie-softmmu,ppc-softmmu,s390x-softmmu,x86_64-softmmu"
+ - TEST_CMD="make check-qtest check-tcg V=1"
# We don't need to exercise every backend with every front-end
@@ -251,7 +247,7 @@ matrix:
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
language: python
python:
- - "3.4"
+ - "3.5"
- env:
@@ -322,7 +318,8 @@ matrix:
- CONFIG="--cc=gcc-9 --cxx=g++-9 --disable-pie --disable-linux-user"
- TEST_CMD=""
before_script:
- - ./configure ${CONFIG} --extra-cflags="-g3 -O0 -Wno-error=stringop-truncation -fsanitize=thread -fuse-ld=gold" || { cat config.log && exit 1; }
+ - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
+ - ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-g3 -O0 -Wno-error=stringop-truncation -fsanitize=thread -fuse-ld=gold" || { cat config.log && exit 1; }
# Run check-tcg against linux-user
@@ -353,6 +350,92 @@ matrix:
- TEST_CMD="make -j3 check-tcg V=1"
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
+ - arch: arm64
+ dist: xenial
+ addons:
+ apt_packages:
+ - libaio-dev
+ - libattr1-dev
+ - libbrlapi-dev
+ - libcap-ng-dev
+ - libgcrypt20-dev
+ - libgnutls28-dev
+ - libgtk-3-dev
+ - libiscsi-dev
+ - liblttng-ust-dev
+ - libncurses5-dev
+ - libnfs-dev
+ - libnss3-dev
+ - libpixman-1-dev
+ - libpng-dev
+ - librados-dev
+ - libsdl2-dev
+ - libseccomp-dev
+ - liburcu-dev
+ - libusb-1.0-0-dev
+ - libvdeplug-dev
+ - libvte-2.91-dev
+ env:
+ - TEST_CMD="make check check-tcg V=1"
+ - CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS}"
+
+ - arch: ppc64le
+ dist: xenial
+ addons:
+ apt_packages:
+ - libaio-dev
+ - libattr1-dev
+ - libbrlapi-dev
+ - libcap-ng-dev
+ - libgcrypt20-dev
+ - libgnutls28-dev
+ - libgtk-3-dev
+ - libiscsi-dev
+ - liblttng-ust-dev
+ - libncurses5-dev
+ - libnfs-dev
+ - libnss3-dev
+ - libpixman-1-dev
+ - libpng-dev
+ - librados-dev
+ - libsdl2-dev
+ - libseccomp-dev
+ - liburcu-dev
+ - libusb-1.0-0-dev
+ - libvdeplug-dev
+ - libvte-2.91-dev
+ env:
+ - TEST_CMD="make check check-tcg V=1"
+ - CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},ppc64le-linux-user"
+
+ - arch: s390x
+ dist: bionic
+ addons:
+ apt_packages:
+ - libaio-dev
+ - libattr1-dev
+ - libbrlapi-dev
+ - libcap-ng-dev
+ - libgcrypt20-dev
+ - libgnutls28-dev
+ - libgtk-3-dev
+ - libiscsi-dev
+ - liblttng-ust-dev
+ - libncurses5-dev
+ - libnfs-dev
+ - libnss3-dev
+ - libpixman-1-dev
+ - libpng-dev
+ - librados-dev
+ - libsdl2-dev
+ - libseccomp-dev
+ - liburcu-dev
+ - libusb-1.0-0-dev
+ - libvdeplug-dev
+ - libvte-2.91-dev
+ env:
+ - TEST_CMD="make check check-tcg V=1"
+ - CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user"
# Release builds
# The make-release script expect a QEMU version, so our tag must start with a 'v'.
@@ -373,5 +456,6 @@ matrix:
- make -C ${SRC_DIR} qemu-${QEMU_VERSION}.tar.bz2
- ls -l ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2
- tar -xf ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2 && cd qemu-${QEMU_VERSION}
- - ./configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
+ - mkdir -p release-build && cd release-build
+ - ../configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
- make install
diff --git a/MAINTAINERS b/MAINTAINERS
index 0c36106..cd2dc13 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1483,6 +1483,7 @@ S: Odd Fixes
F: include/hw/sd/sd*
F: hw/sd/core.c
F: hw/sd/sd*
+F: hw/sd/ssi-sd.c
F: tests/sd*
USB
@@ -1871,12 +1872,12 @@ M: John Snow <jsnow@redhat.com>
R: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
L: qemu-block@nongnu.org
S: Supported
-F: util/hbitmap.c
-F: block/dirty-bitmap.c
F: include/qemu/hbitmap.h
F: include/block/dirty-bitmap.h
-F: qcow2-bitmap.c
+F: block/dirty-bitmap.c
+F: block/qcow2-bitmap.c
F: migration/block-dirty-bitmap.c
+F: util/hbitmap.c
F: tests/test-hbitmap.c
F: docs/interop/bitmaps.rst
T: git https://github.com/jnsnow/qemu.git bitmaps
@@ -2195,6 +2196,8 @@ Migration
M: Juan Quintela <quintela@redhat.com>
M: Dr. David Alan Gilbert <dgilbert@redhat.com>
S: Maintained
+F: hw/core/vmstate-if.c
+F: include/hw/vmstate-if.h
F: include/migration/
F: migration/
F: scripts/vmstate-static-checker.py
@@ -2203,6 +2206,16 @@ F: tests/migration-test.c
F: docs/devel/migration.rst
F: qapi/migration.json
+D-Bus
+M: Marc-André Lureau <marcandre.lureau@redhat.com>
+S: Maintained
+F: backends/dbus-vmstate.c
+F: tests/dbus-vmstate*
+F: util/dbus.c
+F: include/qemu/dbus.h
+F: docs/interop/dbus.rst
+F: docs/interop/dbus-vmstate.rst
+
Seccomp
M: Eduardo Otubo <otubo@redhat.com>
S: Supported
diff --git a/Makefile.objs b/Makefile.objs
index 02bf5ce..7c1e50f 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -128,6 +128,7 @@ vhost-user-gpu-obj-y = contrib/vhost-user-gpu/
trace-events-subdirs =
trace-events-subdirs += accel/kvm
trace-events-subdirs += accel/tcg
+trace-events-subdirs += backends
trace-events-subdirs += crypto
trace-events-subdirs += monitor
ifeq ($(CONFIG_USER_ONLY),y)
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index c01f59c..62068d1 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -156,7 +156,7 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
#if defined(DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)
&& qemu_log_in_addr_range(itb->pc)) {
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
int flags = 0;
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
flags |= CPU_DUMP_FPU;
@@ -165,7 +165,7 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
flags |= CPU_DUMP_CCOP;
#endif
log_cpu_state(cpu, flags);
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
#endif /* DEBUG_DISAS */
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 9f48da9..bb325a2 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1804,7 +1804,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) &&
qemu_log_in_addr_range(tb->pc)) {
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
qemu_log("OUT: [size=%d]\n", gen_code_size);
if (tcg_ctx->data_gen_ptr) {
size_t code_size = tcg_ctx->data_gen_ptr - tb->tc.ptr;
@@ -1829,7 +1829,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
}
qemu_log("\n");
qemu_log_flush();
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
#endif
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index f977682..603d17f 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -138,11 +138,11 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(db->pc_first)) {
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
qemu_log("----------------\n");
ops->disas_log(db, cpu);
qemu_log("\n");
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
#endif
}
diff --git a/audio/audio.c b/audio/audio.c
index 56fae55..abea027 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1738,7 +1738,7 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
if (dev->timer_period <= 0) {
s->period_ticks = 1;
} else {
- s->period_ticks = dev->timer_period * SCALE_US;
+ s->period_ticks = dev->timer_period * (int64_t)SCALE_US;
}
e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
diff --git a/audio/paaudio.c b/audio/paaudio.c
index 55a91f8..dbfe48c 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -156,34 +156,48 @@ static size_t qpa_read(HWVoiceIn *hw, void *data, size_t length)
{
PAVoiceIn *p = (PAVoiceIn *) hw;
PAConnection *c = p->g->conn;
- size_t l;
- int r;
+ size_t total = 0;
pa_threaded_mainloop_lock(c->mainloop);
CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail,
"pa_threaded_mainloop_lock failed\n");
+ if (pa_stream_get_state(p->stream) != PA_STREAM_READY) {
+ /* wait for stream to become ready */
+ goto unlock;
+ }
+
+ while (total < length) {
+ size_t l;
+ int r;
+
+ if (!p->read_length) {
+ r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
+ CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
+ "pa_stream_peek failed\n");
+ if (!p->read_length) {
+ /* buffer is empty */
+ break;
+ }
+ }
- if (!p->read_length) {
- r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
- CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
- "pa_stream_peek failed\n");
- }
-
- l = MIN(p->read_length, length);
- memcpy(data, p->read_data, l);
+ l = MIN(p->read_length, length - total);
+ memcpy((char *)data + total, p->read_data, l);
- p->read_data += l;
- p->read_length -= l;
+ p->read_data += l;
+ p->read_length -= l;
+ total += l;
- if (!p->read_length) {
- r = pa_stream_drop(p->stream);
- CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
- "pa_stream_drop failed\n");
+ if (!p->read_length) {
+ r = pa_stream_drop(p->stream);
+ CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
+ "pa_stream_drop failed\n");
+ }
}
+unlock:
pa_threaded_mainloop_unlock(c->mainloop);
- return l;
+ return total;
unlock_and_fail:
pa_threaded_mainloop_unlock(c->mainloop);
@@ -536,7 +550,6 @@ static void qpa_simple_disconnect(PAConnection *c, pa_stream *stream)
{
int err;
- pa_threaded_mainloop_lock(c->mainloop);
/*
* wait until actually connects. workaround pa bug #247
* https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/247
@@ -550,7 +563,6 @@ static void qpa_simple_disconnect(PAConnection *c, pa_stream *stream)
dolog("Failed to disconnect! err=%d\n", err);
}
pa_stream_unref(stream);
- pa_threaded_mainloop_unlock(c->mainloop);
}
static void qpa_fini_out (HWVoiceOut *hw)
@@ -558,8 +570,12 @@ static void qpa_fini_out (HWVoiceOut *hw)
PAVoiceOut *pa = (PAVoiceOut *) hw;
if (pa->stream) {
- qpa_simple_disconnect(pa->g->conn, pa->stream);
+ PAConnection *c = pa->g->conn;
+
+ pa_threaded_mainloop_lock(c->mainloop);
+ qpa_simple_disconnect(c, pa->stream);
pa->stream = NULL;
+ pa_threaded_mainloop_unlock(c->mainloop);
}
}
@@ -568,8 +584,20 @@ static void qpa_fini_in (HWVoiceIn *hw)
PAVoiceIn *pa = (PAVoiceIn *) hw;
if (pa->stream) {
- qpa_simple_disconnect(pa->g->conn, pa->stream);
+ PAConnection *c = pa->g->conn;
+
+ pa_threaded_mainloop_lock(c->mainloop);
+ if (pa->read_length) {
+ int r = pa_stream_drop(pa->stream);
+ if (r) {
+ qpa_logerr(pa_context_errno(c->context),
+ "pa_stream_drop failed\n");
+ }
+ pa->read_length = 0;
+ }
+ qpa_simple_disconnect(c, pa->stream);
pa->stream = NULL;
+ pa_threaded_mainloop_unlock(c->mainloop);
}
}
diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index f069111..28a847c 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -17,3 +17,7 @@ endif
common-obj-$(call land,$(CONFIG_VHOST_USER),$(CONFIG_VIRTIO)) += vhost-user.o
common-obj-$(CONFIG_LINUX) += hostmem-memfd.o
+
+common-obj-$(CONFIG_GIO) += dbus-vmstate.o
+dbus-vmstate.o-cflags = $(GIO_CFLAGS)
+dbus-vmstate.o-libs = $(GIO_LIBS)
diff --git a/backends/dbus-vmstate.c b/backends/dbus-vmstate.c
new file mode 100644
index 0000000..56b482a
--- /dev/null
+++ b/backends/dbus-vmstate.c
@@ -0,0 +1,510 @@
+/*
+ * QEMU dbus-vmstate
+ *
+ * Copyright (C) 2019 Red Hat Inc
+ *
+ * Authors:
+ * Marc-André Lureau <marcandre.lureau@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qemu/dbus.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "qom/object_interfaces.h"
+#include "qapi/qmp/qerror.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+typedef struct DBusVMState DBusVMState;
+typedef struct DBusVMStateClass DBusVMStateClass;
+
+#define TYPE_DBUS_VMSTATE "dbus-vmstate"
+#define DBUS_VMSTATE(obj) \
+ OBJECT_CHECK(DBusVMState, (obj), TYPE_DBUS_VMSTATE)
+#define DBUS_VMSTATE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(DBusVMStateClass, (obj), TYPE_DBUS_VMSTATE)
+#define DBUS_VMSTATE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(DBusVMStateClass, (klass), TYPE_DBUS_VMSTATE)
+
+struct DBusVMStateClass {
+ ObjectClass parent_class;
+};
+
+struct DBusVMState {
+ Object parent;
+
+ GDBusConnection *bus;
+ char *dbus_addr;
+ char *id_list;
+
+ uint32_t data_size;
+ uint8_t *data;
+};
+
+static const GDBusPropertyInfo vmstate_property_info[] = {
+ { -1, (char *) "Id", (char *) "s",
+ G_DBUS_PROPERTY_INFO_FLAGS_READABLE, NULL },
+};
+
+static const GDBusPropertyInfo * const vmstate_property_info_pointers[] = {
+ &vmstate_property_info[0],
+ NULL
+};
+
+static const GDBusInterfaceInfo vmstate1_interface_info = {
+ -1,
+ (char *) "org.qemu.VMState1",
+ (GDBusMethodInfo **) NULL,
+ (GDBusSignalInfo **) NULL,
+ (GDBusPropertyInfo **) &vmstate_property_info_pointers,
+ NULL,
+};
+
+#define DBUS_VMSTATE_SIZE_LIMIT (1 * MiB)
+
+static GHashTable *
+get_id_list_set(DBusVMState *self)
+{
+ g_auto(GStrv) ids = NULL;
+ g_autoptr(GHashTable) set = NULL;
+ int i;
+
+ if (!self->id_list) {
+ return NULL;
+ }
+
+ ids = g_strsplit(self->id_list, ",", -1);
+ set = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+ for (i = 0; ids[i]; i++) {
+ g_hash_table_add(set, ids[i]);
+ ids[i] = NULL;
+ }
+
+ return g_steal_pointer(&set);
+}
+
+static GHashTable *
+dbus_get_proxies(DBusVMState *self, GError **err)
+{
+ g_autoptr(GHashTable) proxies = NULL;
+ g_autoptr(GHashTable) ids = NULL;
+ g_auto(GStrv) names = NULL;
+ Error *error = NULL;
+ size_t i;
+
+ ids = get_id_list_set(self);
+ proxies = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, g_object_unref);
+
+ names = qemu_dbus_get_queued_owners(self->bus, "org.qemu.VMState1", &error);
+ if (!names) {
+ g_set_error(err, G_IO_ERROR, G_IO_ERROR_FAILED, "%s",
+ error_get_pretty(error));
+ error_free(error);
+ return NULL;
+ }
+
+ for (i = 0; names[i]; i++) {
+ g_autoptr(GDBusProxy) proxy = NULL;
+ g_autoptr(GVariant) result = NULL;
+ g_autofree char *id = NULL;
+ size_t size;
+
+ proxy = g_dbus_proxy_new_sync(self->bus, G_DBUS_PROXY_FLAGS_NONE,
+ (GDBusInterfaceInfo *) &vmstate1_interface_info,
+ names[i],
+ "/org/qemu/VMState1",
+ "org.qemu.VMState1",
+ NULL, err);
+ if (!proxy) {
+ return NULL;
+ }
+
+ result = g_dbus_proxy_get_cached_property(proxy, "Id");
+ if (!result) {
+ g_set_error_literal(err, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "VMState Id property is missing.");
+ return NULL;
+ }
+
+ id = g_variant_dup_string(result, &size);
+ if (ids && !g_hash_table_remove(ids, id)) {
+ g_clear_pointer(&id, g_free);
+ g_clear_object(&proxy);
+ continue;
+ }
+ if (size == 0 || size >= 256) {
+ g_set_error(err, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "VMState Id '%s' is invalid.", id);
+ return NULL;
+ }
+
+ if (!g_hash_table_insert(proxies, id, proxy)) {
+ g_set_error(err, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Duplicated VMState Id '%s'", id);
+ return NULL;
+ }
+ id = NULL;
+ proxy = NULL;
+
+ g_clear_pointer(&result, g_variant_unref);
+ }
+
+ if (ids) {
+ g_autofree char **left = NULL;
+
+ left = (char **)g_hash_table_get_keys_as_array(ids, NULL);
+ if (*left) {
+ g_autofree char *leftids = g_strjoinv(",", left);
+ g_set_error(err, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Required VMState Id are missing: %s", leftids);
+ return NULL;
+ }
+ }
+
+ return g_steal_pointer(&proxies);
+}
+
+static int
+dbus_load_state_proxy(GDBusProxy *proxy, const uint8_t *data, size_t size)
+{
+ g_autoptr(GError) err = NULL;
+ g_autoptr(GVariant) result = NULL;
+ g_autoptr(GVariant) value = NULL;
+
+ value = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
+ data, size, sizeof(char));
+ result = g_dbus_proxy_call_sync(proxy, "Load",
+ g_variant_new("(@ay)",
+ g_steal_pointer(&value)),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ -1, NULL, &err);
+ if (!result) {
+ error_report("%s: Failed to Load: %s", __func__, err->message);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int dbus_vmstate_post_load(void *opaque, int version_id)
+{
+ DBusVMState *self = DBUS_VMSTATE(opaque);
+ g_autoptr(GInputStream) m = NULL;
+ g_autoptr(GDataInputStream) s = NULL;
+ g_autoptr(GError) err = NULL;
+ g_autoptr(GHashTable) proxies = NULL;
+ uint32_t nelem;
+
+ trace_dbus_vmstate_post_load(version_id);
+
+ proxies = dbus_get_proxies(self, &err);
+ if (!proxies) {
+ error_report("%s: Failed to get proxies: %s", __func__, err->message);
+ return -1;
+ }
+
+ m = g_memory_input_stream_new_from_data(self->data, self->data_size, NULL);
+ s = g_data_input_stream_new(m);
+ g_data_input_stream_set_byte_order(s, G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN);
+
+ nelem = g_data_input_stream_read_uint32(s, NULL, &err);
+ if (err) {
+ goto error;
+ }
+
+ while (nelem > 0) {
+ GDBusProxy *proxy = NULL;
+ uint32_t len;
+ gsize bytes_read, avail;
+ char id[256];
+
+ len = g_data_input_stream_read_uint32(s, NULL, &err);
+ if (err) {
+ goto error;
+ }
+ if (len >= 256) {
+ error_report("%s: Invalid DBus vmstate proxy name %u",
+ __func__, len);
+ return -1;
+ }
+ if (!g_input_stream_read_all(G_INPUT_STREAM(s), id, len,
+ &bytes_read, NULL, &err)) {
+ goto error;
+ }
+ g_return_val_if_fail(bytes_read == len, -1);
+ id[len] = 0;
+
+ trace_dbus_vmstate_loading(id);
+
+ proxy = g_hash_table_lookup(proxies, id);
+ if (!proxy) {
+ error_report("%s: Failed to find proxy Id '%s'", __func__, id);
+ return -1;
+ }
+
+ len = g_data_input_stream_read_uint32(s, NULL, &err);
+ avail = g_buffered_input_stream_get_available(
+ G_BUFFERED_INPUT_STREAM(s));
+
+ if (len > DBUS_VMSTATE_SIZE_LIMIT || len > avail) {
+ error_report("%s: Invalid vmstate size: %u", __func__, len);
+ return -1;
+ }
+
+ if (dbus_load_state_proxy(proxy,
+ g_buffered_input_stream_peek_buffer(G_BUFFERED_INPUT_STREAM(s),
+ NULL),
+ len) < 0) {
+ error_report("%s: Failed to restore Id '%s'", __func__, id);
+ return -1;
+ }
+
+ if (!g_seekable_seek(G_SEEKABLE(s), len, G_SEEK_CUR, NULL, &err)) {
+ goto error;
+ }
+
+ nelem -= 1;
+ }
+
+ return 0;
+
+error:
+ error_report("%s: Failed to read from stream: %s", __func__, err->message);
+ return -1;
+}
+
+static void
+dbus_save_state_proxy(gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GDataOutputStream *s = user_data;
+ const char *id = key;
+ GDBusProxy *proxy = value;
+ g_autoptr(GVariant) result = NULL;
+ g_autoptr(GVariant) child = NULL;
+ g_autoptr(GError) err = NULL;
+ const uint8_t *data;
+ gsize size;
+
+ trace_dbus_vmstate_saving(id);
+
+ result = g_dbus_proxy_call_sync(proxy, "Save",
+ NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ -1, NULL, &err);
+ if (!result) {
+ error_report("%s: Failed to Save: %s", __func__, err->message);
+ return;
+ }
+
+ child = g_variant_get_child_value(result, 0);
+ data = g_variant_get_fixed_array(child, &size, sizeof(char));
+ if (!data) {
+ error_report("%s: Failed to Save: not a byte array", __func__);
+ return;
+ }
+ if (size > DBUS_VMSTATE_SIZE_LIMIT) {
+ error_report("%s: Too large vmstate data to save: %zu",
+ __func__, (size_t)size);
+ return;
+ }
+
+ if (!g_data_output_stream_put_uint32(s, strlen(id), NULL, &err) ||
+ !g_data_output_stream_put_string(s, id, NULL, &err) ||
+ !g_data_output_stream_put_uint32(s, size, NULL, &err) ||
+ !g_output_stream_write_all(G_OUTPUT_STREAM(s),
+ data, size, NULL, NULL, &err)) {
+ error_report("%s: Failed to write to stream: %s",
+ __func__, err->message);
+ }
+}
+
+static int dbus_vmstate_pre_save(void *opaque)
+{
+ DBusVMState *self = DBUS_VMSTATE(opaque);
+ g_autoptr(GOutputStream) m = NULL;
+ g_autoptr(GDataOutputStream) s = NULL;
+ g_autoptr(GHashTable) proxies = NULL;
+ g_autoptr(GError) err = NULL;
+
+ trace_dbus_vmstate_pre_save();
+
+ proxies = dbus_get_proxies(self, &err);
+ if (!proxies) {
+ error_report("%s: Failed to get proxies: %s", __func__, err->message);
+ return -1;
+ }
+
+ m = g_memory_output_stream_new_resizable();
+ s = g_data_output_stream_new(m);
+ g_data_output_stream_set_byte_order(s, G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN);
+
+ if (!g_data_output_stream_put_uint32(s, g_hash_table_size(proxies),
+ NULL, &err)) {
+ error_report("%s: Failed to write to stream: %s",
+ __func__, err->message);
+ return -1;
+ }
+
+ g_hash_table_foreach(proxies, dbus_save_state_proxy, s);
+
+ if (g_memory_output_stream_get_size(G_MEMORY_OUTPUT_STREAM(m))
+ > UINT32_MAX) {
+ error_report("%s: DBus vmstate buffer is too large", __func__);
+ return -1;
+ }
+
+ if (!g_output_stream_close(G_OUTPUT_STREAM(m), NULL, &err)) {
+ error_report("%s: Failed to close stream: %s", __func__, err->message);
+ return -1;
+ }
+
+ g_free(self->data);
+ self->data_size =
+ g_memory_output_stream_get_size(G_MEMORY_OUTPUT_STREAM(m));
+ self->data =
+ g_memory_output_stream_steal_data(G_MEMORY_OUTPUT_STREAM(m));
+
+ return 0;
+}
+
+static const VMStateDescription dbus_vmstate = {
+ .name = TYPE_DBUS_VMSTATE,
+ .version_id = 0,
+ .pre_save = dbus_vmstate_pre_save,
+ .post_load = dbus_vmstate_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(data_size, DBusVMState),
+ VMSTATE_VBUFFER_ALLOC_UINT32(data, DBusVMState, 0, 0, data_size),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void
+dbus_vmstate_complete(UserCreatable *uc, Error **errp)
+{
+ DBusVMState *self = DBUS_VMSTATE(uc);
+ g_autoptr(GError) err = NULL;
+
+ if (!object_resolve_path_type("", TYPE_DBUS_VMSTATE, NULL)) {
+ error_setg(errp, "There is already an instance of %s",
+ TYPE_DBUS_VMSTATE);
+ return;
+ }
+
+ if (!self->dbus_addr) {
+ error_setg(errp, QERR_MISSING_PARAMETER, "addr");
+ return;
+ }
+
+ self->bus = g_dbus_connection_new_for_address_sync(self->dbus_addr,
+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
+ G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
+ NULL, NULL, &err);
+ if (err) {
+ error_setg(errp, "failed to connect to DBus: '%s'", err->message);
+ return;
+ }
+
+ if (vmstate_register(VMSTATE_IF(self), -1, &dbus_vmstate, self) < 0) {
+ error_setg(errp, "Failed to register vmstate");
+ }
+}
+
+static void
+dbus_vmstate_finalize(Object *o)
+{
+ DBusVMState *self = DBUS_VMSTATE(o);
+
+ vmstate_unregister(VMSTATE_IF(self), &dbus_vmstate, self);
+
+ g_clear_object(&self->bus);
+ g_free(self->dbus_addr);
+ g_free(self->id_list);
+ g_free(self->data);
+}
+
+static char *
+get_dbus_addr(Object *o, Error **errp)
+{
+ DBusVMState *self = DBUS_VMSTATE(o);
+
+ return g_strdup(self->dbus_addr);
+}
+
+static void
+set_dbus_addr(Object *o, const char *str, Error **errp)
+{
+ DBusVMState *self = DBUS_VMSTATE(o);
+
+ g_free(self->dbus_addr);
+ self->dbus_addr = g_strdup(str);
+}
+
+static char *
+get_id_list(Object *o, Error **errp)
+{
+ DBusVMState *self = DBUS_VMSTATE(o);
+
+ return g_strdup(self->id_list);
+}
+
+static void
+set_id_list(Object *o, const char *str, Error **errp)
+{
+ DBusVMState *self = DBUS_VMSTATE(o);
+
+ g_free(self->id_list);
+ self->id_list = g_strdup(str);
+}
+
+static char *
+dbus_vmstate_get_id(VMStateIf *vmif)
+{
+ return g_strdup(TYPE_DBUS_VMSTATE);
+}
+
+static void
+dbus_vmstate_class_init(ObjectClass *oc, void *data)
+{
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+ VMStateIfClass *vc = VMSTATE_IF_CLASS(oc);
+
+ ucc->complete = dbus_vmstate_complete;
+ vc->get_id = dbus_vmstate_get_id;
+
+ object_class_property_add_str(oc, "addr",
+ get_dbus_addr, set_dbus_addr,
+ &error_abort);
+ object_class_property_add_str(oc, "id-list",
+ get_id_list, set_id_list,
+ &error_abort);
+}
+
+static const TypeInfo dbus_vmstate_info = {
+ .name = TYPE_DBUS_VMSTATE,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(DBusVMState),
+ .instance_finalize = dbus_vmstate_finalize,
+ .class_size = sizeof(DBusVMStateClass),
+ .class_init = dbus_vmstate_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { TYPE_VMSTATE_IF },
+ { }
+ }
+};
+
+static void
+register_types(void)
+{
+ type_register_static(&dbus_vmstate_info);
+}
+
+type_init(register_types);
diff --git a/backends/trace-events b/backends/trace-events
new file mode 100644
index 0000000..59058f7
--- /dev/null
+++ b/backends/trace-events
@@ -0,0 +1,7 @@
+# See docs/devel/tracing.txt for syntax documentation.
+
+# dbus-vmstate.c
+dbus_vmstate_pre_save(void)
+dbus_vmstate_post_load(int version_id) "version_id: %d"
+dbus_vmstate_loading(const char *id) "id: %s"
+dbus_vmstate_saving(const char *id) "id: %s"
diff --git a/block.c b/block.c
index 473eb6e..ecd09db 100644
--- a/block.c
+++ b/block.c
@@ -2227,6 +2227,24 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
*nshared = shared;
}
+uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
+{
+ static const uint64_t permissions[] = {
+ [BLOCK_PERMISSION_CONSISTENT_READ] = BLK_PERM_CONSISTENT_READ,
+ [BLOCK_PERMISSION_WRITE] = BLK_PERM_WRITE,
+ [BLOCK_PERMISSION_WRITE_UNCHANGED] = BLK_PERM_WRITE_UNCHANGED,
+ [BLOCK_PERMISSION_RESIZE] = BLK_PERM_RESIZE,
+ [BLOCK_PERMISSION_GRAPH_MOD] = BLK_PERM_GRAPH_MOD,
+ };
+
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(permissions) != BLOCK_PERMISSION__MAX);
+ QEMU_BUILD_BUG_ON(1UL << ARRAY_SIZE(permissions) != BLK_PERM_ALL + 1);
+
+ assert(qapi_perm < BLOCK_PERMISSION__MAX);
+
+ return permissions[qapi_perm];
+}
+
static void bdrv_replace_child_noperm(BdrvChild *child,
BlockDriverState *new_bs)
{
@@ -4854,36 +4872,23 @@ static void xdbg_graph_add_node(XDbgBlockGraphConstructor *gr, void *node,
static void xdbg_graph_add_edge(XDbgBlockGraphConstructor *gr, void *parent,
const BdrvChild *child)
{
- typedef struct {
- unsigned int flag;
- BlockPermission num;
- } PermissionMap;
-
- static const PermissionMap permissions[] = {
- { BLK_PERM_CONSISTENT_READ, BLOCK_PERMISSION_CONSISTENT_READ },
- { BLK_PERM_WRITE, BLOCK_PERMISSION_WRITE },
- { BLK_PERM_WRITE_UNCHANGED, BLOCK_PERMISSION_WRITE_UNCHANGED },
- { BLK_PERM_RESIZE, BLOCK_PERMISSION_RESIZE },
- { BLK_PERM_GRAPH_MOD, BLOCK_PERMISSION_GRAPH_MOD },
- { 0, 0 }
- };
- const PermissionMap *p;
+ BlockPermission qapi_perm;
XDbgBlockGraphEdge *edge;
- QEMU_BUILD_BUG_ON(1UL << (ARRAY_SIZE(permissions) - 1) != BLK_PERM_ALL + 1);
-
edge = g_new0(XDbgBlockGraphEdge, 1);
edge->parent = xdbg_graph_node_num(gr, parent);
edge->child = xdbg_graph_node_num(gr, child->bs);
edge->name = g_strdup(child->name);
- for (p = permissions; p->flag; p++) {
- if (p->flag & child->perm) {
- QAPI_LIST_ADD(edge->perm, p->num);
+ for (qapi_perm = 0; qapi_perm < BLOCK_PERMISSION__MAX; qapi_perm++) {
+ uint64_t flag = bdrv_qapi_perm_to_blk_perm(qapi_perm);
+
+ if (flag & child->perm) {
+ QAPI_LIST_ADD(edge->perm, qapi_perm);
}
- if (p->flag & child->shared_perm) {
- QAPI_LIST_ADD(edge->shared_perm, p->num);
+ if (flag & child->shared_perm) {
+ QAPI_LIST_ADD(edge->shared_perm, qapi_perm);
}
}
@@ -5335,10 +5340,6 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs,
return;
}
- if (!(bs->open_flags & BDRV_O_INACTIVE)) {
- return;
- }
-
QLIST_FOREACH(child, &bs->children, next) {
bdrv_co_invalidate_cache(child->bs, &local_err);
if (local_err) {
@@ -5360,34 +5361,36 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs,
* just keep the extended permissions for the next time that an activation
* of the image is tried.
*/
- bs->open_flags &= ~BDRV_O_INACTIVE;
- bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
- ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, NULL, &local_err);
- if (ret < 0) {
- bs->open_flags |= BDRV_O_INACTIVE;
- error_propagate(errp, local_err);
- return;
- }
- bdrv_set_perm(bs, perm, shared_perm);
-
- if (bs->drv->bdrv_co_invalidate_cache) {
- bs->drv->bdrv_co_invalidate_cache(bs, &local_err);
- if (local_err) {
+ if (bs->open_flags & BDRV_O_INACTIVE) {
+ bs->open_flags &= ~BDRV_O_INACTIVE;
+ bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
+ ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, NULL, &local_err);
+ if (ret < 0) {
bs->open_flags |= BDRV_O_INACTIVE;
error_propagate(errp, local_err);
return;
}
- }
+ bdrv_set_perm(bs, perm, shared_perm);
- FOR_EACH_DIRTY_BITMAP(bs, bm) {
- bdrv_dirty_bitmap_skip_store(bm, false);
- }
+ if (bs->drv->bdrv_co_invalidate_cache) {
+ bs->drv->bdrv_co_invalidate_cache(bs, &local_err);
+ if (local_err) {
+ bs->open_flags |= BDRV_O_INACTIVE;
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
- ret = refresh_total_sectors(bs, bs->total_sectors);
- if (ret < 0) {
- bs->open_flags |= BDRV_O_INACTIVE;
- error_setg_errno(errp, -ret, "Could not refresh total sector count");
- return;
+ FOR_EACH_DIRTY_BITMAP(bs, bm) {
+ bdrv_dirty_bitmap_skip_store(bm, false);
+ }
+
+ ret = refresh_total_sectors(bs, bs->total_sectors);
+ if (ret < 0) {
+ bs->open_flags |= BDRV_O_INACTIVE;
+ error_setg_errno(errp, -ret, "Could not refresh total sector count");
+ return;
+ }
}
QLIST_FOREACH(parent, &bs->parents, next_parent) {
@@ -5751,12 +5754,11 @@ void bdrv_img_create(const char *filename, const char *fmt,
return;
}
+ /* Create parameter list */
create_opts = qemu_opts_append(create_opts, drv->create_opts);
create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
- /* Create parameter list with default values */
opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
- qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size, &error_abort);
/* Parse -o options */
if (options) {
@@ -5766,6 +5768,13 @@ void bdrv_img_create(const char *filename, const char *fmt,
}
}
+ if (!qemu_opt_get(opts, BLOCK_OPT_SIZE)) {
+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size, &error_abort);
+ } else if (img_size != UINT64_C(-1)) {
+ error_setg(errp, "The image size must be specified only once");
+ goto out;
+ }
+
if (base_filename) {
qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename, &local_err);
if (local_err) {
diff --git a/block/Makefile.objs b/block/Makefile.objs
index e394fe0..330529b 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -43,6 +43,7 @@ block-obj-y += crypto.o
block-obj-y += aio_task.o
block-obj-y += backup-top.o
+block-obj-y += filter-compress.o
common-obj-y += stream.o
diff --git a/block/backup-top.c b/block/backup-top.c
index 7cdb1f8..818d3f2 100644
--- a/block/backup-top.c
+++ b/block/backup-top.c
@@ -257,12 +257,12 @@ void bdrv_backup_top_drop(BlockDriverState *bs)
BDRVBackupTopState *s = bs->opaque;
AioContext *aio_context = bdrv_get_aio_context(bs);
- block_copy_state_free(s->bcs);
-
aio_context_acquire(aio_context);
bdrv_drained_begin(bs);
+ block_copy_state_free(s->bcs);
+
s->active = false;
bdrv_child_refresh_perms(bs, bs->backing, &error_abort);
bdrv_replace_node(bs, backing_bs(bs), &error_abort);
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 5ae96c5..af44aa9 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -28,10 +28,14 @@
#include "qemu/cutils.h"
#include "qemu/config-file.h"
#include "block/block_int.h"
+#include "block/qdict.h"
#include "qemu/module.h"
#include "qemu/option.h"
+#include "qapi/qapi-visit-block-core.h"
#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qstring.h"
+#include "qapi/qobject-input-visitor.h"
#include "sysemu/qtest.h"
typedef struct BDRVBlkdebugState {
@@ -44,6 +48,9 @@ typedef struct BDRVBlkdebugState {
uint64_t opt_discard;
uint64_t max_discard;
+ uint64_t take_child_perms;
+ uint64_t unshare_child_perms;
+
/* For blkdebug_refresh_filename() */
char *config_file;
@@ -344,6 +351,69 @@ static void blkdebug_parse_filename(const char *filename, QDict *options,
qdict_put_str(options, "x-image", filename);
}
+static int blkdebug_parse_perm_list(uint64_t *dest, QDict *options,
+ const char *prefix, Error **errp)
+{
+ int ret = 0;
+ QDict *subqdict = NULL;
+ QObject *crumpled_subqdict = NULL;
+ Visitor *v = NULL;
+ BlockPermissionList *perm_list = NULL, *element;
+ Error *local_err = NULL;
+
+ *dest = 0;
+
+ qdict_extract_subqdict(options, &subqdict, prefix);
+ if (!qdict_size(subqdict)) {
+ goto out;
+ }
+
+ crumpled_subqdict = qdict_crumple(subqdict, errp);
+ if (!crumpled_subqdict) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ v = qobject_input_visitor_new(crumpled_subqdict);
+ visit_type_BlockPermissionList(v, NULL, &perm_list, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (element = perm_list; element; element = element->next) {
+ *dest |= bdrv_qapi_perm_to_blk_perm(element->value);
+ }
+
+out:
+ qapi_free_BlockPermissionList(perm_list);
+ visit_free(v);
+ qobject_unref(subqdict);
+ qobject_unref(crumpled_subqdict);
+ return ret;
+}
+
+static int blkdebug_parse_perms(BDRVBlkdebugState *s, QDict *options,
+ Error **errp)
+{
+ int ret;
+
+ ret = blkdebug_parse_perm_list(&s->take_child_perms, options,
+ "take-child-perms.", errp);
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = blkdebug_parse_perm_list(&s->unshare_child_perms, options,
+ "unshare-child-perms.", errp);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
static QemuOptsList runtime_opts = {
.name = "blkdebug",
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
@@ -419,6 +489,12 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
/* Set initial state */
s->state = 1;
+ /* Parse permissions modifiers before opening the image file */
+ ret = blkdebug_parse_perms(s, options, errp);
+ if (ret < 0) {
+ goto out;
+ }
+
/* Open the image file */
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
bs, &child_file, false, &local_err);
@@ -916,6 +992,21 @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
return 0;
}
+static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
+ const BdrvChildRole *role,
+ BlockReopenQueue *reopen_queue,
+ uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared)
+{
+ BDRVBlkdebugState *s = bs->opaque;
+
+ bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
+ nperm, nshared);
+
+ *nperm |= s->take_child_perms;
+ *nshared &= ~s->unshare_child_perms;
+}
+
static const char *const blkdebug_strong_runtime_opts[] = {
"config",
"inject-error.",
@@ -940,7 +1031,7 @@ static BlockDriver bdrv_blkdebug = {
.bdrv_file_open = blkdebug_open,
.bdrv_close = blkdebug_close,
.bdrv_reopen_prepare = blkdebug_reopen_prepare,
- .bdrv_child_perm = bdrv_filter_default_perms,
+ .bdrv_child_perm = blkdebug_child_perm,
.bdrv_getlength = blkdebug_getlength,
.bdrv_refresh_filename = blkdebug_refresh_filename,
diff --git a/block/filter-compress.c b/block/filter-compress.c
new file mode 100644
index 0000000..60137fb
--- /dev/null
+++ b/block/filter-compress.c
@@ -0,0 +1,168 @@
+/*
+ * Compress filter block driver
+ *
+ * Copyright (c) 2019 Virtuozzo International GmbH
+ *
+ * Author:
+ * Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
+ * (based on block/copy-on-read.c by Max Reitz)
+ *
+ * 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 or
+ * (at your option) any later version of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "block/block_int.h"
+#include "qemu/module.h"
+#include "qapi/error.h"
+
+
+static int compress_open(BlockDriverState *bs, QDict *options, int flags,
+ Error **errp)
+{
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
+ errp);
+ if (!bs->file) {
+ return -EINVAL;
+ }
+
+ if (!bs->file->bs->drv || !block_driver_can_compress(bs->file->bs->drv)) {
+ error_setg(errp,
+ "Compression is not supported for underlying format: %s",
+ bdrv_get_format_name(bs->file->bs) ?: "(no format)");
+
+ return -ENOTSUP;
+ }
+
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
+ (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
+
+ bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
+ ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
+ bs->file->bs->supported_zero_flags);
+
+ return 0;
+}
+
+
+static int64_t compress_getlength(BlockDriverState *bs)
+{
+ return bdrv_getlength(bs->file->bs);
+}
+
+
+static int coroutine_fn compress_co_preadv_part(BlockDriverState *bs,
+ uint64_t offset, uint64_t bytes,
+ QEMUIOVector *qiov,
+ size_t qiov_offset,
+ int flags)
+{
+ return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
+ flags);
+}
+
+
+static int coroutine_fn compress_co_pwritev_part(BlockDriverState *bs,
+ uint64_t offset,
+ uint64_t bytes,
+ QEMUIOVector *qiov,
+ size_t qiov_offset, int flags)
+{
+ return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
+ flags | BDRV_REQ_WRITE_COMPRESSED);
+}
+
+
+static int coroutine_fn compress_co_pwrite_zeroes(BlockDriverState *bs,
+ int64_t offset, int bytes,
+ BdrvRequestFlags flags)
+{
+ return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
+}
+
+
+static int coroutine_fn compress_co_pdiscard(BlockDriverState *bs,
+ int64_t offset, int bytes)
+{
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
+}
+
+
+static void compress_refresh_limits(BlockDriverState *bs, Error **errp)
+{
+ BlockDriverInfo bdi;
+ int ret;
+
+ if (!bs->file) {
+ return;
+ }
+
+ ret = bdrv_get_info(bs->file->bs, &bdi);
+ if (ret < 0 || bdi.cluster_size == 0) {
+ return;
+ }
+
+ bs->bl.request_alignment = bdi.cluster_size;
+}
+
+
+static void compress_eject(BlockDriverState *bs, bool eject_flag)
+{
+ bdrv_eject(bs->file->bs, eject_flag);
+}
+
+
+static void compress_lock_medium(BlockDriverState *bs, bool locked)
+{
+ bdrv_lock_medium(bs->file->bs, locked);
+}
+
+
+static bool compress_recurse_is_first_non_filter(BlockDriverState *bs,
+ BlockDriverState *candidate)
+{
+ return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
+}
+
+
+static BlockDriver bdrv_compress = {
+ .format_name = "compress",
+
+ .bdrv_open = compress_open,
+ .bdrv_child_perm = bdrv_filter_default_perms,
+
+ .bdrv_getlength = compress_getlength,
+
+ .bdrv_co_preadv_part = compress_co_preadv_part,
+ .bdrv_co_pwritev_part = compress_co_pwritev_part,
+ .bdrv_co_pwrite_zeroes = compress_co_pwrite_zeroes,
+ .bdrv_co_pdiscard = compress_co_pdiscard,
+ .bdrv_refresh_limits = compress_refresh_limits,
+
+ .bdrv_eject = compress_eject,
+ .bdrv_lock_medium = compress_lock_medium,
+
+ .bdrv_co_block_status = bdrv_co_block_status_from_file,
+
+ .bdrv_recurse_is_first_non_filter = compress_recurse_is_first_non_filter,
+
+ .has_variable_length = true,
+ .is_filter = true,
+};
+
+static void bdrv_compress_init(void)
+{
+ bdrv_register(&bdrv_compress);
+}
+
+block_init(bdrv_compress_init);
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index c6c8ebb..d41f5d0 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -1703,8 +1703,14 @@ bool coroutine_fn qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
Error **errp)
{
BDRVQcow2State *s = bs->opaque;
- bool found;
- Qcow2BitmapList *bm_list;
+ BdrvDirtyBitmap *bitmap;
+ uint64_t bitmap_directory_size = 0;
+ uint32_t nb_bitmaps = 0;
+
+ if (bdrv_find_dirty_bitmap(bs, name)) {
+ error_setg(errp, "Bitmap already exists: %s", name);
+ return false;
+ }
if (s->qcow_version < 3) {
/* Without autoclear_features, we would always have to assume
@@ -1720,38 +1726,27 @@ bool coroutine_fn qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
goto fail;
}
- if (s->nb_bitmaps == 0) {
- return true;
+ FOR_EACH_DIRTY_BITMAP(bs, bitmap) {
+ if (bdrv_dirty_bitmap_get_persistence(bitmap)) {
+ nb_bitmaps++;
+ bitmap_directory_size +=
+ calc_dir_entry_size(strlen(bdrv_dirty_bitmap_name(bitmap)), 0);
+ }
}
+ nb_bitmaps++;
+ bitmap_directory_size += calc_dir_entry_size(strlen(name), 0);
- if (s->nb_bitmaps >= QCOW2_MAX_BITMAPS) {
+ if (nb_bitmaps > QCOW2_MAX_BITMAPS) {
error_setg(errp,
"Maximum number of persistent bitmaps is already reached");
goto fail;
}
- if (s->bitmap_directory_size + calc_dir_entry_size(strlen(name), 0) >
- QCOW2_MAX_BITMAP_DIRECTORY_SIZE)
- {
+ if (bitmap_directory_size > QCOW2_MAX_BITMAP_DIRECTORY_SIZE) {
error_setg(errp, "Not enough space in the bitmap directory");
goto fail;
}
- qemu_co_mutex_lock(&s->lock);
- bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
- s->bitmap_directory_size, errp);
- qemu_co_mutex_unlock(&s->lock);
- if (bm_list == NULL) {
- goto fail;
- }
-
- found = find_bitmap_by_name(bm_list, name);
- bitmap_list_free(bm_list);
- if (found) {
- error_setg(errp, "Bitmap with the same name is already stored");
- goto fail;
- }
-
return true;
fail:
diff --git a/block/qcow2.c b/block/qcow2.c
index 7c18721..cef9d72 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -367,7 +367,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
return -EINVAL;
}
- if (bitmaps_ext.bitmap_directory_offset & (s->cluster_size - 1)) {
+ if (offset_into_cluster(s, bitmaps_ext.bitmap_directory_offset)) {
error_setg(errp, "bitmaps_ext: "
"invalid bitmap directory offset");
return -EINVAL;
@@ -1705,14 +1705,14 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
if (!(bdrv_get_flags(bs) & BDRV_O_INACTIVE)) {
/* It's case 1, 2 or 3.2. Or 3.1 which is BUG in management layer. */
bool header_updated = qcow2_load_dirty_bitmaps(bs, &local_err);
+ if (local_err != NULL) {
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ goto fail;
+ }
update_header = update_header && !header_updated;
}
- if (local_err != NULL) {
- error_propagate(errp, local_err);
- ret = -EINVAL;
- goto fail;
- }
if (update_header) {
ret = qcow2_update_header(bs);
@@ -1722,7 +1722,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
}
}
- bs->supported_zero_flags = header.version >= 3 ? BDRV_REQ_MAY_UNMAP : 0;
+ bs->supported_zero_flags = header.version >= 3 ?
+ BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0;
/* Repair image if dirty */
if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
@@ -1958,9 +1959,8 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
{
BDRVQcow2State *s = bs->opaque;
uint64_t cluster_offset;
- int index_in_cluster, ret;
unsigned int bytes;
- int status = 0;
+ int ret, status = 0;
qemu_co_mutex_lock(&s->lock);
@@ -1981,8 +1981,7 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
if ((ret == QCOW2_CLUSTER_NORMAL || ret == QCOW2_CLUSTER_ZERO_ALLOC) &&
!s->crypto) {
- index_in_cluster = offset & (s->cluster_size - 1);
- *map = cluster_offset | index_in_cluster;
+ *map = cluster_offset | offset_into_cluster(s, offset);
*file = s->data_file->bs;
status |= BDRV_BLOCK_OFFSET_VALID;
}
@@ -4222,10 +4221,8 @@ fail:
return ret;
}
-/* XXX: put compressed sectors first, then all the cluster aligned
- tables to avoid losing bytes in alignment */
static coroutine_fn int
-qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
+qcow2_co_pwritev_compressed_task(BlockDriverState *bs,
uint64_t offset, uint64_t bytes,
QEMUIOVector *qiov, size_t qiov_offset)
{
@@ -4235,32 +4232,11 @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
uint8_t *buf, *out_buf;
uint64_t cluster_offset;
- if (has_data_file(bs)) {
- return -ENOTSUP;
- }
-
- if (bytes == 0) {
- /* align end of file to a sector boundary to ease reading with
- sector based I/Os */
- int64_t len = bdrv_getlength(bs->file->bs);
- if (len < 0) {
- return len;
- }
- return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
- }
-
- if (offset_into_cluster(s, offset)) {
- return -EINVAL;
- }
+ assert(bytes == s->cluster_size || (bytes < s->cluster_size &&
+ (offset + bytes == bs->total_sectors << BDRV_SECTOR_BITS)));
buf = qemu_blockalign(bs, s->cluster_size);
- if (bytes != s->cluster_size) {
- if (bytes > s->cluster_size ||
- offset + bytes != bs->total_sectors << BDRV_SECTOR_BITS)
- {
- qemu_vfree(buf);
- return -EINVAL;
- }
+ if (bytes < s->cluster_size) {
/* Zero-pad last write if image size is not cluster aligned */
memset(buf + bytes, 0, s->cluster_size - bytes);
}
@@ -4309,6 +4285,77 @@ fail:
return ret;
}
+static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task)
+{
+ Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
+
+ assert(!t->cluster_type && !t->l2meta);
+
+ return qcow2_co_pwritev_compressed_task(t->bs, t->offset, t->bytes, t->qiov,
+ t->qiov_offset);
+}
+
+/*
+ * XXX: put compressed sectors first, then all the cluster aligned
+ * tables to avoid losing bytes in alignment
+ */
+static coroutine_fn int
+qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
+ uint64_t offset, uint64_t bytes,
+ QEMUIOVector *qiov, size_t qiov_offset)
+{
+ BDRVQcow2State *s = bs->opaque;
+ AioTaskPool *aio = NULL;
+ int ret = 0;
+
+ if (has_data_file(bs)) {
+ return -ENOTSUP;
+ }
+
+ if (bytes == 0) {
+ /*
+ * align end of file to a sector boundary to ease reading with
+ * sector based I/Os
+ */
+ int64_t len = bdrv_getlength(bs->file->bs);
+ if (len < 0) {
+ return len;
+ }
+ return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
+ }
+
+ if (offset_into_cluster(s, offset)) {
+ return -EINVAL;
+ }
+
+ while (bytes && aio_task_pool_status(aio) == 0) {
+ uint64_t chunk_size = MIN(bytes, s->cluster_size);
+
+ if (!aio && chunk_size != bytes) {
+ aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
+ }
+
+ ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_compressed_task_entry,
+ 0, 0, offset, chunk_size, qiov, qiov_offset, NULL);
+ if (ret < 0) {
+ break;
+ }
+ qiov_offset += chunk_size;
+ offset += chunk_size;
+ bytes -= chunk_size;
+ }
+
+ if (aio) {
+ aio_task_pool_wait_all(aio);
+ if (ret == 0) {
+ ret = aio_task_pool_status(aio);
+ }
+ g_free(aio);
+ }
+
+ return ret;
+}
+
static int coroutine_fn
qcow2_co_preadv_compressed(BlockDriverState *bs,
uint64_t file_cluster_offset,
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
index 77014c7..37695b0 100644
--- a/block/throttle-groups.c
+++ b/block/throttle-groups.c
@@ -893,8 +893,7 @@ static void throttle_group_set_limits(Object *obj, Visitor *v,
{
ThrottleGroup *tg = THROTTLE_GROUP(obj);
ThrottleConfig cfg;
- ThrottleLimits arg = { 0 };
- ThrottleLimits *argp = &arg;
+ ThrottleLimits *argp;
Error *local_err = NULL;
visit_type_ThrottleLimits(v, name, &argp, &local_err);
@@ -912,6 +911,7 @@ static void throttle_group_set_limits(Object *obj, Visitor *v,
unlock:
qemu_mutex_unlock(&tg->lock);
ret:
+ qapi_free_ThrottleLimits(argp);
error_propagate(errp, local_err);
return;
}
diff --git a/blockjob.c b/blockjob.c
index c6e20e2..5d63b1e 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -261,7 +261,8 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
return;
}
if (speed < 0) {
- error_setg(errp, QERR_INVALID_PARAMETER, "speed");
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "speed",
+ "a non-negative value");
return;
}
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 470a8bf..7f4e3cd 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -963,7 +963,7 @@ int main(int argc, char **argv)
if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
qemu_log("guest_base 0x%lx\n", guest_base);
- log_page_dump();
+ log_page_dump("binary load");
qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);
diff --git a/configure b/configure
index 5723a29..0ce2c03 100755
--- a/configure
+++ b/configure
@@ -302,6 +302,7 @@ audio_win_int=""
libs_qga=""
debug_info="yes"
stack_protector=""
+use_containers="yes"
if test -e "$source_path/.git"
then
@@ -902,9 +903,9 @@ fi
: ${install=${INSTALL-install}}
# We prefer python 3.x. A bare 'python' is traditionally
# python 2.x, but some distros have it as python 3.x, so
-# we check that before python2
+# we check that too
python=
-for binary in "${PYTHON-python3}" python python2
+for binary in "${PYTHON-python3}" python
do
if has "$binary"
then
@@ -1535,6 +1536,10 @@ for opt do
;;
--disable-plugins) plugins="no"
;;
+ --enable-containers) use_containers="yes"
+ ;;
+ --disable-containers) use_containers="no"
+ ;;
*)
echo "ERROR: unknown option $opt"
echo "Try '$0 --help' for more information"
@@ -1718,6 +1723,7 @@ Advanced options (experts only):
track the maximum stack usage of stacks created by qemu_alloc_stack
--enable-plugins
enable plugins via shared library loading
+ --disable-containers don't use containers for cross-building
Optional features, enabled with --enable-FEATURE and
disabled with --disable-FEATURE, default is enabled if available:
@@ -1836,8 +1842,8 @@ fi
# Note that if the Python conditional here evaluates True we will exit
# with status 1 which is a shell 'false' value.
-if ! $python -c 'import sys; sys.exit(sys.version_info < (2,7))'; then
- error_exit "Cannot use '$python', Python 2 >= 2.7 or Python 3 is required." \
+if ! $python -c 'import sys; sys.exit(sys.version_info < (3,5))'; then
+ error_exit "Cannot use '$python', Python >= 3.5 is required." \
"Use --python=/path/to/python to specify a supported Python."
fi
@@ -3695,10 +3701,16 @@ if $pkg_config --atleast-version=$glib_req_ver gio-2.0; then
gio=yes
gio_cflags=$($pkg_config --cflags gio-2.0)
gio_libs=$($pkg_config --libs gio-2.0)
+ gdbus_codegen=$($pkg_config --variable=gdbus_codegen gio-2.0)
else
gio=no
fi
+if $pkg_config --atleast-version=$glib_req_ver gio-unix-2.0; then
+ gio_cflags="$gio_cflags $($pkg_config --cflags gio-unix-2.0)"
+ gio_libs="$gio_libs $($pkg_config --libs gio-unix-2.0)"
+fi
+
# Sanity check that the current size_t matches the
# size that glib thinks it should be. This catches
# problems on multi-arch where people try to build
@@ -6399,6 +6411,7 @@ else
echo "local state directory queried at runtime"
echo "Windows SDK $win_sdk"
fi
+echo "Build directory $(pwd)"
echo "Source path $source_path"
echo "GIT binary $git"
echo "GIT submodules $git_submodules"
@@ -6587,15 +6600,6 @@ if test "$supported_os" = "no"; then
echo "us upstream at qemu-devel@nongnu.org."
fi
-# Note that if the Python conditional here evaluates True we will exit
-# with status 1 which is a shell 'false' value.
-if ! $python -c 'import sys; sys.exit(sys.version_info < (3,0))'; then
- echo
- echo "warning: Python 2 support is deprecated" >&2
- echo "warning: Python 3 will be required for building future versions of QEMU" >&2
- python2="y"
-fi
-
config_host_mak="config-host.mak"
echo "# Automatically generated by configure - do not modify" >config-all-disas.mak
@@ -6906,6 +6910,7 @@ if test "$gio" = "yes" ; then
echo "CONFIG_GIO=y" >> $config_host_mak
echo "GIO_CFLAGS=$gio_cflags" >> $config_host_mak
echo "GIO_LIBS=$gio_libs" >> $config_host_mak
+ echo "GDBUS_CODEGEN=$gdbus_codegen" >> $config_host_mak
fi
echo "CONFIG_TLS_PRIORITY=\"$tls_priority\"" >> $config_host_mak
if test "$gnutls" = "yes" ; then
@@ -7440,7 +7445,6 @@ echo "INSTALL_DATA=$install -c -m 0644" >> $config_host_mak
echo "INSTALL_PROG=$install -c -m 0755" >> $config_host_mak
echo "INSTALL_LIB=$install -c -m 0644" >> $config_host_mak
echo "PYTHON=$python" >> $config_host_mak
-echo "PYTHON2=$python2" >> $config_host_mak
echo "CC=$cc" >> $config_host_mak
if $iasl -h > /dev/null 2>&1; then
echo "IASL=$iasl" >> $config_host_mak
@@ -7996,7 +8000,7 @@ done
(for i in $cross_cc_vars; do
export $i
done
-export target_list source_path
+export target_list source_path use_containers
$source_path/tests/tcg/configure.sh)
# temporary config to build submodules
diff --git a/contrib/vhost-user-gpu/50-qemu-gpu.json.in b/contrib/vhost-user-gpu/50-qemu-gpu.json.in
index 658b545..f5edd09 100644
--- a/contrib/vhost-user-gpu/50-qemu-gpu.json.in
+++ b/contrib/vhost-user-gpu/50-qemu-gpu.json.in
@@ -1,5 +1,5 @@
{
"description": "QEMU vhost-user-gpu",
"type": "gpu",
- "binary": "@libexecdir@/vhost-user-gpu",
+ "binary": "@libexecdir@/vhost-user-gpu"
}
diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst
index 1b367e2..9b537a7 100644
--- a/docs/arm-cpu-features.rst
+++ b/docs/arm-cpu-features.rst
@@ -41,9 +41,9 @@ CPU type is possible with the `query-cpu-model-expansion` QMP command.
Below are some examples where `scripts/qmp/qmp-shell` (see the top comment
block in the script for usage) is used to issue the QMP commands.
-(1) Determine which CPU features are available for the `max` CPU type
- (Note, we started QEMU with qemu-system-aarch64, so `max` is
- implementing the ARMv8-A reference manual in this case)::
+1. Determine which CPU features are available for the `max` CPU type
+ (Note, we started QEMU with qemu-system-aarch64, so `max` is
+ implementing the ARMv8-A reference manual in this case)::
(QEMU) query-cpu-model-expansion type=full model={"name":"max"}
{ "return": {
diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
index 27f2868..ab5be0c 100644
--- a/docs/devel/testing.rst
+++ b/docs/devel/testing.rst
@@ -418,13 +418,15 @@ access, so they SHOULD NOT be exposed to external interfaces if you are
concerned about attackers taking control of the guest and potentially
exploiting a QEMU security bug to compromise the host.
-QEMU binary
------------
+QEMU binaries
+-------------
By default, qemu-system-x86_64 is searched in $PATH to run the guest. If there
isn't one, or if it is older than 2.10, the test won't work. In this case,
provide the QEMU binary in env var: ``QEMU=/path/to/qemu-2.10+``.
+Likewise the path to qemu-img can be set in QEMU_IMG environment variable.
+
Make jobs
---------
diff --git a/docs/interop/dbus-vmstate.rst b/docs/interop/dbus-vmstate.rst
new file mode 100644
index 0000000..1d719c1
--- /dev/null
+++ b/docs/interop/dbus-vmstate.rst
@@ -0,0 +1,74 @@
+=============
+D-Bus VMState
+=============
+
+Introduction
+============
+
+The QEMU dbus-vmstate object's aim is to migrate helpers' data running
+on a QEMU D-Bus bus. (refer to the :doc:`dbus` document for
+some recommendations on D-Bus usage)
+
+Upon migration, QEMU will go through the queue of
+``org.qemu.VMState1`` D-Bus name owners and query their ``Id``. It
+must be unique among the helpers.
+
+It will then save arbitrary data of each Id to be transferred in the
+migration stream and restored/loaded at the corresponding destination
+helper.
+
+For now, the data amount to be transferred is arbitrarily limited to
+1Mb. The state must be saved quickly (a fraction of a second). (D-Bus
+imposes a time limit on reply anyway, and migration would fail if data
+isn't given quickly enough.)
+
+dbus-vmstate object can be configured with the expected list of
+helpers by setting its ``id-list`` property, with a comma-separated
+``Id`` list.
+
+Interface
+=========
+
+On object path ``/org/qemu/VMState1``, the following
+``org.qemu.VMState1`` interface should be implemented:
+
+.. code:: xml
+
+ <interface name="org.qemu.VMState1">
+ <property name="Id" type="s" access="read"/>
+ <method name="Load">
+ <arg type="ay" name="data" direction="in"/>
+ </method>
+ <method name="Save">
+ <arg type="ay" name="data" direction="out"/>
+ </method>
+ </interface>
+
+"Id" property
+-------------
+
+A string that identifies the helper uniquely. (maximum 256 bytes
+including terminating NUL byte)
+
+.. note::
+
+ The helper ID namespace is a separate namespace. In particular, it is not
+ related to QEMU "id" used in -object/-device objects.
+
+Load(in u8[] bytes) method
+--------------------------
+
+The method called on destination with the state to restore.
+
+The helper may be initially started in a waiting state (with
+an --incoming argument for example), and it may resume on success.
+
+An error may be returned to the caller.
+
+Save(out u8[] bytes) method
+---------------------------
+
+The method called on the source to get the current state to be
+migrated. The helper should continue to run normally.
+
+An error may be returned to the caller.
diff --git a/docs/interop/dbus.rst b/docs/interop/dbus.rst
new file mode 100644
index 0000000..76a5bde
--- /dev/null
+++ b/docs/interop/dbus.rst
@@ -0,0 +1,110 @@
+=====
+D-Bus
+=====
+
+Introduction
+============
+
+QEMU may be running with various helper processes involved:
+ - vhost-user* processes (gpu, virtfs, input, etc...)
+ - TPM emulation (or other devices)
+ - user networking (slirp)
+ - network services (DHCP/DNS, samba/ftp etc)
+ - background tasks (compression, streaming etc)
+ - client UI
+ - admin & cli
+
+Having several processes allows stricter security rules, as well as
+greater modularity.
+
+While QEMU itself uses QMP as primary IPC (and Spice/VNC for remote
+display), D-Bus is the de facto IPC of choice on Unix systems. The
+wire format is machine friendly, good bindings exist for various
+languages, and there are various tools available.
+
+Using a bus, helper processes can discover and communicate with each
+other easily, without going through QEMU. The bus topology is also
+easier to apprehend and debug than a mesh. However, it is wise to
+consider the security aspects of it.
+
+Security
+========
+
+A QEMU D-Bus bus should be private to a single VM. Thus, only
+cooperative tasks are running on the same bus to serve the VM.
+
+D-Bus, the protocol and standard, doesn't have mechanisms to enforce
+security between peers once the connection is established. Peers may
+have additional mechanisms to enforce security rules, based for
+example on UNIX credentials.
+
+The daemon can control which peers can send/recv messages using
+various metadata attributes, however, this is alone is not generally
+sufficient to make the deployment secure. The semantics of the actual
+methods implemented using D-Bus are just as critical. Peers need to
+carefully validate any information they received from a peer with a
+different trust level.
+
+dbus-daemon policy
+------------------
+
+dbus-daemon can enforce various policies based on the UID/GID of the
+processes that are connected to it. It is thus a good idea to run
+helpers as different UID from QEMU and set appropriate policies.
+
+Depending on the use case, you may choose different scenarios:
+
+ - Everything the same UID
+
+ - Convenient for developers
+ - Improved reliability - crash of one part doens't take
+ out entire VM
+ - No security benefit over traditional QEMU, unless additional
+ unless additional controls such as SELinux or AppArmor are
+ applied
+
+ - Two UIDs, one for QEMU, one for dbus & helpers
+
+ - Moderately improved user based security isolation
+
+ - Many UIDs, one for QEMU one for dbus and one for each helpers
+
+ - Best user based security isolation
+ - Complex to manager distinct UIDs needed for each VM
+
+For example, to allow only ``qemu`` user to talk to ``qemu-helper``
+``org.qemu.Helper1`` service, a dbus-daemon policy may contain:
+
+.. code:: xml
+
+ <policy user="qemu">
+ <allow send_destination="org.qemu.Helper1"/>
+ <allow receive_sender="org.qemu.Helper1"/>
+ </policy>
+
+ <policy user="qemu-helper">
+ <allow own="org.qemu.Helper1"/>
+ </policy>
+
+
+dbus-daemon can also perfom SELinux checks based on the security
+context of the source and the target. For example, ``virtiofs_t``
+could be allowed to send a message to ``svirt_t``, but ``virtiofs_t``
+wouldn't be allowed to send a message to ``virtiofs_t``.
+
+See dbus-daemon man page for details.
+
+Guidelines
+==========
+
+When implementing new D-Bus interfaces, it is recommended to follow
+the "D-Bus API Design Guidelines":
+https://dbus.freedesktop.org/doc/dbus-api-design.html
+
+The "org.qemu.*" prefix is reserved for services implemented &
+distributed by the QEMU project.
+
+QEMU Interfaces
+===============
+
+:doc:`dbus-vmstate`
diff --git a/docs/interop/index.rst b/docs/interop/index.rst
index 3e33fb5..049387a 100644
--- a/docs/interop/index.rst
+++ b/docs/interop/index.rst
@@ -13,6 +13,8 @@ Contents:
:maxdepth: 2
bitmaps
+ dbus
+ dbus-vmstate
live-block-operations
pr-helper
qemu-ga
diff --git a/docs/virtio-net-failover.rst b/docs/virtio-net-failover.rst
index 22f64c7..6002dc5 100644
--- a/docs/virtio-net-failover.rst
+++ b/docs/virtio-net-failover.rst
@@ -1,6 +1,6 @@
-========================
+======================================
QEMU virtio-net standby (net_failover)
-========================
+======================================
This document explains the setup and usage of virtio-net standby feature which
is used to create a net_failover pair of devices.
diff --git a/docs/virtio-pmem.rst b/docs/virtio-pmem.rst
index e77881b..4bf5d00 100644
--- a/docs/virtio-pmem.rst
+++ b/docs/virtio-pmem.rst
@@ -27,17 +27,18 @@ virtio pmem usage
-----------------
A virtio pmem device backed by a memory-backend-file can be created on
- the QEMU command line as in the following example:
+ the QEMU command line as in the following example::
- -object memory-backend-file,id=mem1,share,mem-path=./virtio_pmem.img,size=4G
- -device virtio-pmem-pci,memdev=mem1,id=nv1
+ -object memory-backend-file,id=mem1,share,mem-path=./virtio_pmem.img,size=4G
+ -device virtio-pmem-pci,memdev=mem1,id=nv1
- where:
- - "object memory-backend-file,id=mem1,share,mem-path=<image>, size=<image size>"
- creates a backend file with the specified size.
+ where:
- - "device virtio-pmem-pci,id=nvdimm1,memdev=mem1" creates a virtio pmem
- pci device whose storage is provided by above memory backend device.
+ - "object memory-backend-file,id=mem1,share,mem-path=<image>, size=<image size>"
+ creates a backend file with the specified size.
+
+ - "device virtio-pmem-pci,id=nvdimm1,memdev=mem1" creates a virtio pmem
+ pci device whose storage is provided by above memory backend device.
Multiple virtio pmem devices can be created if multiple pairs of "-object"
and "-device" are provided.
@@ -50,7 +51,7 @@ memory backing has to be added via 'object_add'; afterwards, the virtio
pmem device can be added via 'device_add'.
For example, the following commands add another 4GB virtio pmem device to
-the guest:
+the guest::
(qemu) object_add memory-backend-file,id=mem2,share=on,mem-path=virtio_pmem2.img,size=4G
(qemu) device_add virtio-pmem-pci,id=virtio_pmem2,memdev=mem2
diff --git a/exec.c b/exec.c
index efdc0ae..d4b769d 100644
--- a/exec.c
+++ b/exec.c
@@ -1225,13 +1225,13 @@ void cpu_abort(CPUState *cpu, const char *fmt, ...)
fprintf(stderr, "\n");
cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP);
if (qemu_log_separate()) {
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
qemu_log("qemu: fatal: ");
qemu_log_vprintf(fmt, ap2);
qemu_log("\n");
log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP);
qemu_log_flush();
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
qemu_log_close();
}
va_end(ap2);
diff --git a/hmp-commands.hx b/hmp-commands.hx
index cfcc044..dc23185 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1875,9 +1875,11 @@ ETEXI
{
.name = "qemu-io",
- .args_type = "device:B,command:s",
- .params = "[device] \"[command]\"",
- .help = "run a qemu-io command on a block device",
+ .args_type = "qdev:-d,device:B,command:s",
+ .params = "[-d] [device] \"[command]\"",
+ .help = "run a qemu-io command on a block device\n\t\t\t"
+ "-d: [device] is a device ID rather than a "
+ "drive ID or node name",
.cmd = hmp_qemu_io,
},
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index be88005..89e4b00 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -250,6 +250,9 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
object_property_set_int(OBJECT(&s->cpu[i]), aspeed_calc_affinity(i),
"mp-affinity", &error_abort);
+ object_property_set_int(OBJECT(&s->cpu[i]), 1125000000, "cntfrq",
+ &error_abort);
+
/*
* TODO: the secondary CPUs are started and a boot helper
* is needed when using -kernel
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
index 5853bde..9b5bcb5 100644
--- a/hw/arm/sbsa-ref.c
+++ b/hw/arm/sbsa-ref.c
@@ -789,7 +789,6 @@ static void sbsa_ref_class_init(ObjectClass *oc, void *data)
mc->possible_cpu_arch_ids = sbsa_ref_possible_cpu_arch_ids;
mc->cpu_index_to_instance_props = sbsa_ref_cpu_index_to_props;
mc->get_default_cpu_node_id = sbsa_ref_get_default_cpu_node_id;
- mc->numa_mem_supported = true;
}
static const TypeInfo sbsa_ref_info = {
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
index d190181..4112394 100644
--- a/hw/arm/smmuv3-internal.h
+++ b/hw/arm/smmuv3-internal.h
@@ -99,7 +99,7 @@ REG32(GERROR_IRQ_CFG2, 0x74)
#define A_STRTAB_BASE 0x80 /* 64b */
-#define SMMU_BASE_ADDR_MASK 0xffffffffffe0
+#define SMMU_BASE_ADDR_MASK 0xfffffffffffc0
REG32(STRTAB_BASE_CFG, 0x88)
FIELD(STRTAB_BASE_CFG, FMT, 16, 2)
@@ -461,8 +461,8 @@ typedef struct SMMUEventInfo {
} while (0)
#define EVT_SET_ADDR2(x, addr) \
do { \
- (x)->word[7] = deposit32((x)->word[7], 3, 29, addr >> 16); \
- (x)->word[7] = deposit32((x)->word[7], 0, 16, addr & 0xffff);\
+ (x)->word[7] = (uint32_t)(addr >> 32); \
+ (x)->word[6] = (uint32_t)(addr & 0xffffffff); \
} while (0)
void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event);
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index e2fbb83..8b5f157 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -172,7 +172,7 @@ void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *info)
case SMMU_EVT_F_STE_FETCH:
EVT_SET_SSID(&evt, info->u.f_ste_fetch.ssid);
EVT_SET_SSV(&evt, info->u.f_ste_fetch.ssv);
- EVT_SET_ADDR(&evt, info->u.f_ste_fetch.addr);
+ EVT_SET_ADDR2(&evt, info->u.f_ste_fetch.addr);
break;
case SMMU_EVT_C_BAD_STE:
EVT_SET_SSID(&evt, info->u.c_bad_ste.ssid);
@@ -376,21 +376,32 @@ bad_ste:
static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
SMMUEventInfo *event)
{
- dma_addr_t addr;
+ dma_addr_t addr, strtab_base;
+ uint32_t log2size;
+ int strtab_size_shift;
int ret;
trace_smmuv3_find_ste(sid, s->features, s->sid_split);
- /* Check SID range */
- if (sid > (1 << SMMU_IDR1_SIDSIZE)) {
+ log2size = FIELD_EX32(s->strtab_base_cfg, STRTAB_BASE_CFG, LOG2SIZE);
+ /*
+ * Check SID range against both guest-configured and implementation limits
+ */
+ if (sid >= (1 << MIN(log2size, SMMU_IDR1_SIDSIZE))) {
event->type = SMMU_EVT_C_BAD_STREAMID;
return -EINVAL;
}
if (s->features & SMMU_FEATURE_2LVL_STE) {
int l1_ste_offset, l2_ste_offset, max_l2_ste, span;
- dma_addr_t strtab_base, l1ptr, l2ptr;
+ dma_addr_t l1ptr, l2ptr;
STEDesc l1std;
- strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK;
+ /*
+ * Align strtab base address to table size. For this purpose, assume it
+ * is not bounded by SMMU_IDR1_SIDSIZE.
+ */
+ strtab_size_shift = MAX(5, (int)log2size - s->sid_split - 1 + 3);
+ strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK &
+ ~MAKE_64BIT_MASK(0, strtab_size_shift);
l1_ste_offset = sid >> s->sid_split;
l2_ste_offset = sid & ((1 << s->sid_split) - 1);
l1ptr = (dma_addr_t)(strtab_base + l1_ste_offset * sizeof(l1std));
@@ -429,7 +440,10 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
}
addr = l2ptr + l2_ste_offset * sizeof(*ste);
} else {
- addr = s->strtab_base + sid * sizeof(*ste);
+ strtab_size_shift = log2size + 5;
+ strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK &
+ ~MAKE_64BIT_MASK(0, strtab_size_shift);
+ addr = strtab_base + sid * sizeof(*ste);
}
if (smmu_get_ste(s, addr, ste, event)) {
diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c
index f17e8d8..e711a99 100644
--- a/hw/audio/hda-codec.c
+++ b/hw/audio/hda-codec.c
@@ -265,8 +265,6 @@ static void hda_audio_input_cb(void *opaque, int avail)
int64_t to_transfer = MIN(B_SIZE - (wpos - rpos), avail);
- hda_timer_sync_adjust(st, -((wpos - rpos) + to_transfer - (B_SIZE >> 1)));
-
while (to_transfer) {
uint32_t start = (uint32_t) (wpos & B_MASK);
uint32_t chunk = (uint32_t) MIN(B_SIZE - start, to_transfer);
@@ -278,6 +276,8 @@ static void hda_audio_input_cb(void *opaque, int avail)
break;
}
}
+
+ hda_timer_sync_adjust(st, -((wpos - rpos) - (B_SIZE >> 1)));
}
static void hda_audio_output_timer(void *opaque)
@@ -338,8 +338,6 @@ static void hda_audio_output_cb(void *opaque, int avail)
return;
}
- hda_timer_sync_adjust(st, (wpos - rpos) - to_transfer - (B_SIZE >> 1));
-
while (to_transfer) {
uint32_t start = (uint32_t) (rpos & B_MASK);
uint32_t chunk = (uint32_t) MIN(B_SIZE - start, to_transfer);
@@ -351,6 +349,8 @@ static void hda_audio_output_cb(void *opaque, int avail)
break;
}
}
+
+ hda_timer_sync_adjust(st, (wpos - rpos) - (B_SIZE >> 1));
}
static void hda_audio_compat_input_cb(void *opaque, int avail)
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 119906a5..1b52e815 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -67,7 +67,7 @@ static void notify_guest_bh(void *opaque)
memset(s->batch_notify_vqs, 0, sizeof(bitmap));
for (j = 0; j < nvqs; j += BITS_PER_LONG) {
- unsigned long bits = bitmap[j];
+ unsigned long bits = bitmap[j / BITS_PER_LONG];
while (bits != 0) {
unsigned i = j + ctzl(bits);
diff --git a/hw/block/onenand.c b/hw/block/onenand.c
index fcc5a69..9c233c1 100644
--- a/hw/block/onenand.c
+++ b/hw/block/onenand.c
@@ -822,7 +822,7 @@ static void onenand_realize(DeviceState *dev, Error **errp)
onenand_mem_setup(s);
sysbus_init_irq(sbd, &s->intr);
sysbus_init_mmio(sbd, &s->container);
- vmstate_register(dev,
+ vmstate_register(VMSTATE_IF(dev),
((s->shift & 0x7f) << 24)
| ((s->id.man & 0xff) << 16)
| ((s->id.dev & 0xff) << 8)
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
index fd0550d..0edd9e6 100644
--- a/hw/core/Makefile.objs
+++ b/hw/core/Makefile.objs
@@ -9,6 +9,7 @@ common-obj-y += hotplug.o
common-obj-$(CONFIG_SOFTMMU) += nmi.o
common-obj-$(CONFIG_SOFTMMU) += vm-change-state-handler.o
common-obj-y += cpu.o
+common-obj-y += vmstate-if.o
common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
common-obj-$(CONFIG_XILINX_AXI) += stream.o
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 56137e9..73bf1f8 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -843,7 +843,7 @@ static void machine_initfn(Object *obj)
NULL);
}
- if (mc->numa_mem_supported) {
+ if (mc->cpu_index_to_instance_props && mc->get_default_cpu_node_id) {
ms->numa_state = g_new0(NumaState, 1);
}
@@ -966,7 +966,7 @@ void machine_run_board_init(MachineState *machine)
{
MachineClass *machine_class = MACHINE_GET_CLASS(machine);
- if (machine_class->numa_mem_supported) {
+ if (machine->numa_state) {
numa_complete_configuration(machine);
if (machine->numa_state->num_nodes) {
machine_numa_finish_cpu_init(machine);
diff --git a/hw/core/numa.c b/hw/core/numa.c
index e3332a9..19f082d 100644
--- a/hw/core/numa.c
+++ b/hw/core/numa.c
@@ -83,10 +83,6 @@ static void parse_numa_node(MachineState *ms, NumaNodeOptions *node,
return;
}
- if (!mc->cpu_index_to_instance_props || !mc->get_default_cpu_node_id) {
- error_setg(errp, "NUMA is not supported by this machine-type");
- return;
- }
for (cpus = node->cpus; cpus; cpus = cpus->next) {
CpuInstanceProperties props;
if (cpus->value >= max_cpus) {
@@ -178,9 +174,8 @@ void parse_numa_distance(MachineState *ms, NumaDistOptions *dist, Error **errp)
void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp)
{
Error *err = NULL;
- MachineClass *mc = MACHINE_GET_CLASS(ms);
- if (!mc->numa_mem_supported) {
+ if (!ms->numa_state) {
error_setg(errp, "NUMA is not supported by this machine-type");
goto end;
}
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 82d3ee5..501228b 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -889,7 +889,8 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
dev->canonical_path = object_get_canonical_path(OBJECT(dev));
if (qdev_get_vmsd(dev)) {
- if (vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
+ if (vmstate_register_with_alias_id(VMSTATE_IF(dev),
+ -1, qdev_get_vmsd(dev), dev,
dev->instance_id_alias,
dev->alias_required_for_version,
&local_err) < 0) {
@@ -923,7 +924,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
local_err ? NULL : &local_err);
}
if (qdev_get_vmsd(dev)) {
- vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
+ vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev);
}
if (dc->unrealize) {
dc->unrealize(dev, local_err ? NULL : &local_err);
@@ -947,7 +948,7 @@ child_realize_fail:
}
if (qdev_get_vmsd(dev)) {
- vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
+ vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev);
}
post_realize_fail:
@@ -1087,9 +1088,18 @@ static void device_unparent(Object *obj)
}
}
+static char *
+device_vmstate_if_get_id(VMStateIf *obj)
+{
+ DeviceState *dev = DEVICE(obj);
+
+ return qdev_get_dev_path(dev);
+}
+
static void device_class_init(ObjectClass *class, void *data)
{
DeviceClass *dc = DEVICE_CLASS(class);
+ VMStateIfClass *vc = VMSTATE_IF_CLASS(class);
class->unparent = device_unparent;
@@ -1101,6 +1111,7 @@ static void device_class_init(ObjectClass *class, void *data)
*/
dc->hotpluggable = true;
dc->user_creatable = true;
+ vc->get_id = device_vmstate_if_get_id;
}
void device_class_set_parent_reset(DeviceClass *dc,
@@ -1158,6 +1169,10 @@ static const TypeInfo device_type_info = {
.class_init = device_class_init,
.abstract = true,
.class_size = sizeof(DeviceClass),
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_VMSTATE_IF },
+ { }
+ }
};
static void qdev_register_types(void)
diff --git a/hw/core/vmstate-if.c b/hw/core/vmstate-if.c
new file mode 100644
index 0000000..bf45362
--- /dev/null
+++ b/hw/core/vmstate-if.c
@@ -0,0 +1,23 @@
+/*
+ * VMState interface
+ *
+ * Copyright (c) 2009-2019 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 "hw/vmstate-if.h"
+
+static const TypeInfo vmstate_if_info = {
+ .name = TYPE_VMSTATE_IF,
+ .parent = TYPE_INTERFACE,
+ .class_size = sizeof(VMStateIfClass),
+};
+
+static void vmstate_register_types(void)
+{
+ type_register_static(&vmstate_if_info);
+}
+
+type_init(vmstate_register_types);
diff --git a/hw/display/bochs-display.c b/hw/display/bochs-display.c
index dc1bd16..215db9a 100644
--- a/hw/display/bochs-display.c
+++ b/hw/display/bochs-display.c
@@ -252,6 +252,8 @@ static void bochs_display_update(void *opaque)
dpy_gfx_update(s->con, 0, ys,
mode.width, y - ys);
}
+
+ g_free(snap);
}
}
diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
index f7fdc49..3ce2e57 100644
--- a/hw/display/qxl-render.c
+++ b/hw/display/qxl-render.c
@@ -109,7 +109,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qxl->guest_primary.surface.mem,
MEMSLOT_GROUP_GUEST);
if (!qxl->guest_primary.data) {
- return;
+ goto end;
}
qxl_set_rect_to_surface(qxl, &qxl->dirty[0]);
qxl->num_dirty_rects = 1;
@@ -137,7 +137,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
}
if (!qxl->guest_primary.data) {
- return;
+ goto end;
}
for (i = 0; i < qxl->num_dirty_rects; i++) {
if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
@@ -158,6 +158,11 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qxl->dirty[i].bottom - qxl->dirty[i].top);
}
qxl->num_dirty_rects = 0;
+
+end:
+ if (qxl->render_update_cookie_num == 0) {
+ graphic_hw_update_done(qxl->ssd.dcl.con);
+ }
}
/*
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index cd7eb39..6d43b74 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -1181,6 +1181,7 @@ static const QXLInterface qxl_interface = {
static const GraphicHwOps qxl_ops = {
.gfx_update = qxl_hw_update,
+ .gfx_update_async = true,
};
static void qxl_enter_vga_mode(PCIQXLDevice *d)
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 19984d2..3f9be96 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -302,7 +302,7 @@ static void pci_cmd646_ide_realize(PCIDevice *dev, Error **errp)
}
g_free(irq);
- vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d);
+ vmstate_register(VMSTATE_IF(dev), 0, &vmstate_ide_pci, d);
qemu_register_reset(cmd646_reset, d);
}
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index 7b6e283..9c7f88b 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -75,7 +75,7 @@ static void isa_ide_realizefn(DeviceState *dev, Error **errp)
ide_init_ioport(&s->bus, isadev, s->iobase, s->iobase2);
isa_init_irq(isadev, &s->irq, s->isairq);
ide_init2(&s->bus, s->irq);
- vmstate_register(dev, 0, &vmstate_ide_isa, s);
+ vmstate_register(VMSTATE_IF(dev), 0, &vmstate_ide_isa, s);
ide_register_restart_cb(&s->bus);
}
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index db313dd..bc575b4 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -156,7 +156,7 @@ static void pci_piix_ide_realize(PCIDevice *dev, Error **errp)
bmdma_setup_bar(d);
pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar);
- vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d);
+ vmstate_register(VMSTATE_IF(dev), 0, &vmstate_ide_pci, d);
pci_piix_init_ports(d);
}
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 053622b..096de8d 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -190,7 +190,7 @@ static void via_ide_realize(PCIDevice *dev, Error **errp)
bmdma_setup_bar(d);
pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar);
- vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d);
+ vmstate_register(VMSTATE_IF(dev), 0, &vmstate_ide_pci, d);
for (i = 0; i < 2; i++) {
ide_bus_new(&d->bus[i], sizeof(d->bus[i]), DEVICE(d), i, 2);
diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c
index a713149..211008c 100644
--- a/hw/misc/max111x.c
+++ b/hw/misc/max111x.c
@@ -146,7 +146,7 @@ static int max111x_init(SSISlave *d, int inputs)
s->input[7] = 0x80;
s->com = 0;
- vmstate_register(dev, -1, &vmstate_max111x, s);
+ vmstate_register(VMSTATE_IF(dev), -1, &vmstate_max111x, s);
return 0;
}
diff --git a/hw/net/can/can_sja1000.c b/hw/net/can/can_sja1000.c
index 1f81341..39c78fa 100644
--- a/hw/net/can/can_sja1000.c
+++ b/hw/net/can/can_sja1000.c
@@ -247,8 +247,8 @@ int can_sja_accept_filter(CanSJA1000State *s,
static void can_display_msg(const char *prefix, const qemu_can_frame *msg)
{
int i;
+ FILE *logfile = qemu_log_lock();
- qemu_log_lock();
qemu_log("%s%03X [%01d] %s %s",
prefix,
msg->can_id & QEMU_CAN_EFF_MASK,
@@ -261,7 +261,7 @@ static void can_display_msg(const char *prefix, const qemu_can_frame *msg)
}
qemu_log("\n");
qemu_log_flush();
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
static void buff2frame_pel(const uint8_t *buff, qemu_can_frame *frame)
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index cc2dd8b..cc71a7a 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -1815,7 +1815,7 @@ static void pci_nic_uninit(PCIDevice *pci_dev)
{
EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
- vmstate_unregister(&pci_dev->qdev, s->vmstate, s);
+ vmstate_unregister(VMSTATE_IF(&pci_dev->qdev), s->vmstate, s);
g_free(s->vmstate);
eeprom93xx_free(&pci_dev->qdev, s->eeprom);
qemu_del_nic(s->nic);
@@ -1874,7 +1874,7 @@ static void e100_nic_realize(PCIDevice *pci_dev, Error **errp)
s->vmstate = g_memdup(&vmstate_eepro100, sizeof(vmstate_eepro100));
s->vmstate->name = qemu_get_queue(s->nic)->model;
- vmstate_register(&pci_dev->qdev, -1, s->vmstate, s);
+ vmstate_register(VMSTATE_IF(&pci_dev->qdev), -1, s->vmstate, s);
}
static void eepro100_instance_init(Object *obj)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index db3d7c3..777d62d 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -2853,7 +2853,8 @@ static void virtio_net_handle_migration_primary(VirtIONet *n,
if (migration_in_setup(s) && !should_be_hidden) {
if (failover_unplug_primary(n)) {
- vmstate_unregister(n->primary_dev, qdev_get_vmsd(n->primary_dev),
+ vmstate_unregister(VMSTATE_IF(n->primary_dev),
+ qdev_get_vmsd(n->primary_dev),
n->primary_dev);
qapi_event_send_unplug_primary(n->primary_device_id);
atomic_set(&n->primary_should_be_hidden, true);
diff --git a/hw/nvram/eeprom93xx.c b/hw/nvram/eeprom93xx.c
index 5b01b9b..07f0954 100644
--- a/hw/nvram/eeprom93xx.c
+++ b/hw/nvram/eeprom93xx.c
@@ -321,7 +321,7 @@ eeprom_t *eeprom93xx_new(DeviceState *dev, uint16_t nwords)
/* Output DO is tristate, read results in 1. */
eeprom->eedo = 1;
logout("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);
- vmstate_register(dev, 0, &vmstate_eeprom, eeprom);
+ vmstate_register(VMSTATE_IF(dev), 0, &vmstate_eeprom, eeprom);
return eeprom;
}
@@ -329,7 +329,7 @@ void eeprom93xx_free(DeviceState *dev, eeprom_t *eeprom)
{
/* Destroy EEPROM. */
logout("eeprom = 0x%p\n", eeprom);
- vmstate_unregister(dev, &vmstate_eeprom, eeprom);
+ vmstate_unregister(VMSTATE_IF(dev), &vmstate_eeprom, eeprom);
g_free(eeprom);
}
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 62f1a42..17aeac3 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -511,7 +511,7 @@ static void realize(DeviceState *d, Error **errp)
error_propagate(errp, err);
return;
}
- vmstate_register(DEVICE(drc), spapr_drc_index(drc), &vmstate_spapr_drc,
+ vmstate_register(VMSTATE_IF(drc), spapr_drc_index(drc), &vmstate_spapr_drc,
drc);
trace_spapr_drc_realize_complete(spapr_drc_index(drc));
}
@@ -523,7 +523,7 @@ static void unrealize(DeviceState *d, Error **errp)
gchar *name;
trace_spapr_drc_unrealize(spapr_drc_index(drc));
- vmstate_unregister(DEVICE(drc), &vmstate_spapr_drc, drc);
+ vmstate_unregister(VMSTATE_IF(drc), &vmstate_spapr_drc, drc);
root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
name = g_strdup_printf("%x", spapr_drc_index(drc));
object_property_del(root_container, name, errp);
@@ -619,7 +619,8 @@ static void realize_physical(DeviceState *d, Error **errp)
return;
}
- vmstate_register(DEVICE(drcp), spapr_drc_index(SPAPR_DR_CONNECTOR(drcp)),
+ vmstate_register(VMSTATE_IF(drcp),
+ spapr_drc_index(SPAPR_DR_CONNECTOR(drcp)),
&vmstate_spapr_drc_physical, drcp);
qemu_register_reset(drc_physical_reset, drcp);
}
@@ -635,7 +636,7 @@ static void unrealize_physical(DeviceState *d, Error **errp)
return;
}
- vmstate_unregister(DEVICE(drcp), &vmstate_spapr_drc_physical, drcp);
+ vmstate_unregister(VMSTATE_IF(drcp), &vmstate_spapr_drc_physical, drcp);
qemu_unregister_reset(drc_physical_reset, drcp);
}
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 3d3bcc8..5704fe6 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -317,7 +317,7 @@ static void spapr_tce_table_realize(DeviceState *dev, Error **errp)
QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
- vmstate_register(DEVICE(tcet), tcet->liobn, &vmstate_spapr_tce_table,
+ vmstate_register(VMSTATE_IF(tcet), tcet->liobn, &vmstate_spapr_tce_table,
tcet);
}
@@ -420,7 +420,7 @@ static void spapr_tce_table_unrealize(DeviceState *dev, Error **errp)
{
SpaprTceTable *tcet = SPAPR_TCE_TABLE(dev);
- vmstate_unregister(DEVICE(tcet), &vmstate_spapr_tce_table, tcet);
+ vmstate_unregister(VMSTATE_IF(tcet), &vmstate_spapr_tce_table, tcet);
QLIST_REMOVE(tcet, list);
diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c
index bd37f39..5da6e52 100644
--- a/hw/s390x/s390-skeys.c
+++ b/hw/s390x/s390-skeys.c
@@ -392,7 +392,7 @@ static inline void s390_skeys_set_migration_enabled(Object *obj, bool value,
register_savevm_live(TYPE_S390_SKEYS, 0, 1,
&savevm_s390_storage_keys, ss);
} else {
- unregister_savevm(DEVICE(ss), TYPE_S390_SKEYS, ss);
+ unregister_savevm(VMSTATE_IF(ss), TYPE_S390_SKEYS, ss);
}
}
diff --git a/include/block/block.h b/include/block/block.h
index 1df9848..e9dcfef 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -280,6 +280,7 @@ enum {
};
char *bdrv_perm_names(uint64_t perm);
+uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm);
/* disk I/O throttling */
void bdrv_init(void);
diff --git a/include/exec/log.h b/include/exec/log.h
index e2cfd43..fcc7b9e 100644
--- a/include/exec/log.h
+++ b/include/exec/log.h
@@ -15,8 +15,15 @@
*/
static inline void log_cpu_state(CPUState *cpu, int flags)
{
+ QemuLogFile *logfile;
+
if (qemu_log_enabled()) {
- cpu_dump_state(cpu, qemu_logfile, flags);
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ cpu_dump_state(cpu, logfile->fd, flags);
+ }
+ rcu_read_unlock();
}
}
@@ -40,19 +47,36 @@ static inline void log_cpu_state_mask(int mask, CPUState *cpu, int flags)
static inline void log_target_disas(CPUState *cpu, target_ulong start,
target_ulong len)
{
- target_disas(qemu_logfile, cpu, start, len);
+ QemuLogFile *logfile;
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ target_disas(logfile->fd, cpu, start, len);
+ }
+ rcu_read_unlock();
}
static inline void log_disas(void *code, unsigned long size)
{
- disas(qemu_logfile, code, size);
+ QemuLogFile *logfile;
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ disas(logfile->fd, code, size);
+ }
+ rcu_read_unlock();
}
#if defined(CONFIG_USER_ONLY)
/* page_dump() output to the log file: */
-static inline void log_page_dump(void)
+static inline void log_page_dump(const char *operation)
{
- page_dump(qemu_logfile);
+ FILE *logfile = qemu_log_lock();
+ if (logfile) {
+ qemu_log("page layout changed following %s\n", operation);
+ page_dump(logfile);
+ }
+ qemu_log_unlock(logfile);
}
#endif
#endif
diff --git a/include/hw/vmstate-if.h b/include/hw/vmstate-if.h
new file mode 100644
index 0000000..8ff7f0f
--- /dev/null
+++ b/include/hw/vmstate-if.h
@@ -0,0 +1,40 @@
+/*
+ * VMState interface
+ *
+ * Copyright (c) 2009-2019 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.
+ */
+
+#ifndef VMSTATE_IF_H
+#define VMSTATE_IF_H
+
+#include "qom/object.h"
+
+#define TYPE_VMSTATE_IF "vmstate-if"
+
+#define VMSTATE_IF_CLASS(klass) \
+ OBJECT_CLASS_CHECK(VMStateIfClass, (klass), TYPE_VMSTATE_IF)
+#define VMSTATE_IF_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(VMStateIfClass, (obj), TYPE_VMSTATE_IF)
+#define VMSTATE_IF(obj) \
+ INTERFACE_CHECK(VMStateIf, (obj), TYPE_VMSTATE_IF)
+
+typedef struct VMStateIf VMStateIf;
+
+typedef struct VMStateIfClass {
+ InterfaceClass parent_class;
+
+ char * (*get_id)(VMStateIf *obj);
+} VMStateIfClass;
+
+static inline char *vmstate_if_get_id(VMStateIf *vmif)
+{
+ if (!vmif) {
+ return NULL;
+ }
+
+ return VMSTATE_IF_GET_CLASS(vmif)->get_id(vmif);
+}
+
+#endif /* VMSTATE_IF_H */
diff --git a/include/migration/register.h b/include/migration/register.h
index a13359a..00c38eb 100644
--- a/include/migration/register.h
+++ b/include/migration/register.h
@@ -14,6 +14,8 @@
#ifndef MIGRATION_REGISTER_H
#define MIGRATION_REGISTER_H
+#include "hw/vmstate-if.h"
+
typedef struct SaveVMHandlers {
/* This runs inside the iothread lock. */
SaveStateHandler *save_state;
@@ -74,6 +76,6 @@ int register_savevm_live(const char *idstr,
const SaveVMHandlers *ops,
void *opaque);
-void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque);
+void unregister_savevm(VMStateIf *obj, const char *idstr, void *opaque);
#endif
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index ac4f46a..4aef72c 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -27,6 +27,8 @@
#ifndef QEMU_VMSTATE_H
#define QEMU_VMSTATE_H
+#include "hw/vmstate-if.h"
+
typedef struct VMStateInfo VMStateInfo;
typedef struct VMStateField VMStateField;
@@ -1156,22 +1158,22 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque);
/* Returns: 0 on success, -1 on failure */
-int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
+int vmstate_register_with_alias_id(VMStateIf *obj, int instance_id,
const VMStateDescription *vmsd,
void *base, int alias_id,
int required_for_version,
Error **errp);
/* Returns: 0 on success, -1 on failure */
-static inline int vmstate_register(DeviceState *dev, int instance_id,
+static inline int vmstate_register(VMStateIf *obj, int instance_id,
const VMStateDescription *vmsd,
void *opaque)
{
- return vmstate_register_with_alias_id(dev, instance_id, vmsd,
+ return vmstate_register_with_alias_id(obj, instance_id, vmsd,
opaque, -1, 0, NULL);
}
-void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
+void vmstate_unregister(VMStateIf *obj, const VMStateDescription *vmsd,
void *opaque);
struct MemoryRegion;
diff --git a/include/qemu/dbus.h b/include/qemu/dbus.h
new file mode 100644
index 0000000..9d591f9
--- /dev/null
+++ b/include/qemu/dbus.h
@@ -0,0 +1,19 @@
+/*
+ * Helpers for using D-Bus
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef DBUS_H
+#define DBUS_H
+
+#include <gio/gio.h>
+
+GStrv qemu_dbus_get_queued_owners(GDBusConnection *connection,
+ const char *name,
+ Error **errp);
+
+#endif /* DBUS_H */
diff --git a/include/qemu/log.h b/include/qemu/log.h
index a91105b..e0f4e40 100644
--- a/include/qemu/log.h
+++ b/include/qemu/log.h
@@ -3,9 +3,16 @@
/* A small part of this API is split into its own header */
#include "qemu/log-for-trace.h"
+#include "qemu/rcu.h"
+
+typedef struct QemuLogFile {
+ struct rcu_head rcu;
+ FILE *fd;
+} QemuLogFile;
/* Private global variable, don't use */
-extern FILE *qemu_logfile;
+extern QemuLogFile *qemu_logfile;
+
/*
* The new API:
@@ -25,7 +32,16 @@ static inline bool qemu_log_enabled(void)
*/
static inline bool qemu_log_separate(void)
{
- return qemu_logfile != NULL && qemu_logfile != stderr;
+ QemuLogFile *logfile;
+ bool res = false;
+
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile && logfile->fd != stderr) {
+ res = true;
+ }
+ rcu_read_unlock();
+ return res;
}
#define CPU_LOG_TB_OUT_ASM (1 << 0)
@@ -53,14 +69,25 @@ static inline bool qemu_log_separate(void)
* qemu_loglevel is never set when qemu_logfile is unset.
*/
-static inline void qemu_log_lock(void)
+static inline FILE *qemu_log_lock(void)
{
- qemu_flockfile(qemu_logfile);
+ QemuLogFile *logfile;
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ qemu_flockfile(logfile->fd);
+ return logfile->fd;
+ } else {
+ return NULL;
+ }
}
-static inline void qemu_log_unlock(void)
+static inline void qemu_log_unlock(FILE *fd)
{
- qemu_funlockfile(qemu_logfile);
+ if (fd) {
+ qemu_funlockfile(fd);
+ }
+ rcu_read_unlock();
}
/* Logging functions: */
@@ -70,9 +97,14 @@ static inline void qemu_log_unlock(void)
static inline void GCC_FMT_ATTR(1, 0)
qemu_log_vprintf(const char *fmt, va_list va)
{
- if (qemu_logfile) {
- vfprintf(qemu_logfile, fmt, va);
+ QemuLogFile *logfile;
+
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ vfprintf(logfile->fd, fmt, va);
}
+ rcu_read_unlock();
}
/* log only if a bit is set on the current loglevel mask:
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 0f97d68..9bd3dcf 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -462,6 +462,7 @@ int qemu_mprotect_none(void *addr, size_t size);
int qemu_open(const char *name, int flags, ...);
int qemu_close(int fd);
+int qemu_unlink(const char *name);
#ifndef _WIN32
int qemu_dup(int fd);
#endif
diff --git a/include/qom/object.h b/include/qom/object.h
index 1d7b7e5..54a5488 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -1766,4 +1766,7 @@ Object *container_get(Object *root, const char *path);
* Returns the instance_size of the given @typename.
*/
size_t object_type_get_instance_size(const char *typename);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(Object, object_unref)
+
#endif
diff --git a/include/ui/console.h b/include/ui/console.h
index f981696..281f9c1 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -365,6 +365,7 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch)
typedef struct GraphicHwOps {
void (*invalidate)(void *opaque);
void (*gfx_update)(void *opaque);
+ bool gfx_update_async; /* if true, calls graphic_hw_update_done() */
void (*text_update)(void *opaque, console_ch_t *text);
void (*update_interval)(void *opaque, uint64_t interval);
int (*ui_info)(void *opaque, uint32_t head, QemuUIInfo *info);
@@ -380,6 +381,7 @@ void graphic_console_set_hwops(QemuConsole *con,
void graphic_console_close(QemuConsole *con);
void graphic_hw_update(QemuConsole *con);
+void graphic_hw_update_done(QemuConsole *con);
void graphic_hw_invalidate(QemuConsole *con);
void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata);
void graphic_hw_gl_block(QemuConsole *con, bool block);
diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h
index 0668109..3b7cf70 100644
--- a/include/ui/qemu-pixman.h
+++ b/include/ui/qemu-pixman.h
@@ -90,4 +90,6 @@ void qemu_pixman_glyph_render(pixman_image_t *glyph,
pixman_color_t *bgcol,
int x, int y, int cw, int ch);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(pixman_image_t, qemu_pixman_image_unref)
+
#endif /* QEMU_PIXMAN_H */
diff --git a/linux-user/main.c b/linux-user/main.c
index 6ff7851..8718d03 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -826,7 +826,7 @@ int main(int argc, char **argv, char **envp)
if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
qemu_log("guest_base 0x%lx\n", guest_base);
- log_page_dump();
+ log_page_dump("binary load");
qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 46a6e3a..8685f02 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -17,11 +17,10 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
-
+#include "trace.h"
+#include "exec/log.h"
#include "qemu.h"
-//#define DEBUG_MMAP
-
static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
static __thread int mmap_lock_count;
@@ -66,13 +65,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
abi_ulong end, host_start, host_end, addr;
int prot1, ret;
-#ifdef DEBUG_MMAP
- printf("mprotect: start=0x" TARGET_ABI_FMT_lx
- "len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c\n", start, len,
- prot & PROT_READ ? 'r' : '-',
- prot & PROT_WRITE ? 'w' : '-',
- prot & PROT_EXEC ? 'x' : '-');
-#endif
+ trace_target_mprotect(start, len, prot);
if ((start & ~TARGET_PAGE_MASK) != 0)
return -TARGET_EINVAL;
@@ -369,32 +362,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
mmap_lock();
-#ifdef DEBUG_MMAP
- {
- printf("mmap: start=0x" TARGET_ABI_FMT_lx
- " len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c flags=",
- start, len,
- prot & PROT_READ ? 'r' : '-',
- prot & PROT_WRITE ? 'w' : '-',
- prot & PROT_EXEC ? 'x' : '-');
- if (flags & MAP_FIXED)
- printf("MAP_FIXED ");
- if (flags & MAP_ANONYMOUS)
- printf("MAP_ANON ");
- switch(flags & MAP_TYPE) {
- case MAP_PRIVATE:
- printf("MAP_PRIVATE ");
- break;
- case MAP_SHARED:
- printf("MAP_SHARED ");
- break;
- default:
- printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE);
- break;
- }
- printf("fd=%d offset=" TARGET_ABI_FMT_lx "\n", fd, offset);
- }
-#endif
+ trace_target_mmap(start, len, prot, flags, fd, offset);
if (!len) {
errno = EINVAL;
@@ -569,11 +537,10 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
the_end1:
page_set_flags(start, start + len, prot | PAGE_VALID);
the_end:
-#ifdef DEBUG_MMAP
- printf("ret=0x" TARGET_ABI_FMT_lx "\n", start);
- page_dump(stdout);
- printf("\n");
-#endif
+ trace_target_mmap_complete(start);
+ if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
+ log_page_dump(__func__);
+ }
tb_invalidate_phys_range(start, start + len);
mmap_unlock();
return start;
@@ -628,11 +595,8 @@ int target_munmap(abi_ulong start, abi_ulong len)
abi_ulong end, real_start, real_end, addr;
int prot, ret;
-#ifdef DEBUG_MMAP
- printf("munmap: start=0x" TARGET_ABI_FMT_lx " len=0x"
- TARGET_ABI_FMT_lx "\n",
- start, len);
-#endif
+ trace_target_munmap(start, len);
+
if (start & ~TARGET_PAGE_MASK)
return -TARGET_EINVAL;
len = TARGET_PAGE_ALIGN(len);
diff --git a/linux-user/trace-events b/linux-user/trace-events
index 6df234b..f6de1b8 100644
--- a/linux-user/trace-events
+++ b/linux-user/trace-events
@@ -11,3 +11,9 @@ user_handle_signal(void *env, int target_sig) "env=%p signal %d"
user_host_signal(void *env, int host_sig, int target_sig) "env=%p signal %d (target %d("
user_queue_signal(void *env, int target_sig) "env=%p signal %d"
user_s390x_restore_sigregs(void *env, uint64_t sc_psw_addr, uint64_t env_psw_addr) "env=%p frame psw.addr 0x%"PRIx64 " current psw.addr 0x%"PRIx64
+
+# mmap.c
+target_mprotect(uint64_t start, uint64_t len, int flags) "start=0x%"PRIx64 " len=0x%"PRIx64 " prot=0x%x"
+target_mmap(uint64_t start, uint64_t len, int pflags, int mflags, int fd, uint64_t offset) "start=0x%"PRIx64 " len=0x%"PRIx64 " prot=0x%x flags=0x%x fd=%d offset=0x%"PRIx64
+target_mmap_complete(uint64_t retaddr) "retaddr=0x%"PRIx64
+target_munmap(uint64_t start, uint64_t len) "start=0x%"PRIx64" len=0x%"PRIx64
diff --git a/migration/savevm.c b/migration/savevm.c
index a71b930..59efc19 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -760,17 +760,17 @@ int register_savevm_live(const char *idstr,
return 0;
}
-void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
+void unregister_savevm(VMStateIf *obj, const char *idstr, void *opaque)
{
SaveStateEntry *se, *new_se;
char id[256] = "";
- if (dev) {
- char *path = qdev_get_dev_path(dev);
- if (path) {
- pstrcpy(id, sizeof(id), path);
+ if (obj) {
+ char *oid = vmstate_if_get_id(obj);
+ if (oid) {
+ pstrcpy(id, sizeof(id), oid);
pstrcat(id, sizeof(id), "/");
- g_free(path);
+ g_free(oid);
}
}
pstrcat(id, sizeof(id), idstr);
@@ -784,7 +784,7 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
}
}
-int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
+int vmstate_register_with_alias_id(VMStateIf *obj, int instance_id,
const VMStateDescription *vmsd,
void *opaque, int alias_id,
int required_for_version,
@@ -802,8 +802,8 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
se->vmsd = vmsd;
se->alias_id = alias_id;
- if (dev) {
- char *id = qdev_get_dev_path(dev);
+ if (obj) {
+ char *id = vmstate_if_get_id(obj);
if (id) {
if (snprintf(se->idstr, sizeof(se->idstr), "%s/", id) >=
sizeof(se->idstr)) {
@@ -834,7 +834,7 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
return 0;
}
-void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
+void vmstate_unregister(VMStateIf *obj, const VMStateDescription *vmsd,
void *opaque)
{
SaveStateEntry *se, *new_se;
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index c5dea30..d0e0af8 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -2467,23 +2467,31 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
{
BlockBackend *blk;
BlockBackend *local_blk = NULL;
+ bool qdev = qdict_get_try_bool(qdict, "qdev", false);
const char* device = qdict_get_str(qdict, "device");
const char* command = qdict_get_str(qdict, "command");
Error *err = NULL;
int ret;
- blk = blk_by_name(device);
- if (!blk) {
- BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err);
- if (bs) {
- blk = local_blk = blk_new(bdrv_get_aio_context(bs),
- 0, BLK_PERM_ALL);
- ret = blk_insert_bs(blk, bs, &err);
- if (ret < 0) {
+ if (qdev) {
+ blk = blk_by_qdev_id(device, &err);
+ if (!blk) {
+ goto fail;
+ }
+ } else {
+ blk = blk_by_name(device);
+ if (!blk) {
+ BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err);
+ if (bs) {
+ blk = local_blk = blk_new(bdrv_get_aio_context(bs),
+ 0, BLK_PERM_ALL);
+ ret = blk_insert_bs(blk, bs, &err);
+ if (ret < 0) {
+ goto fail;
+ }
+ } else {
goto fail;
}
- } else {
- goto fail;
}
}
diff --git a/monitor/misc.c b/monitor/misc.c
index a74cff3..a04d7ed 100644
--- a/monitor/misc.c
+++ b/monitor/misc.c
@@ -106,9 +106,6 @@ struct MonFdset {
QLIST_ENTRY(MonFdset) next;
};
-/* QMP checker flags */
-#define QMP_ACCEPT_UNKNOWNS 1
-
/* Protects mon_fdsets */
static QemuMutex mon_fdsets_lock;
static QLIST_HEAD(, MonFdset) mon_fdsets;
diff --git a/net/can/can_socketcan.c b/net/can/can_socketcan.c
index 8a6ffad..29bfacd 100644
--- a/net/can/can_socketcan.c
+++ b/net/can/can_socketcan.c
@@ -76,8 +76,7 @@ QEMU_BUILD_BUG_ON(offsetof(qemu_can_frame, data)
static void can_host_socketcan_display_msg(struct qemu_can_frame *msg)
{
int i;
-
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
qemu_log("[cansocketcan]: %03X [%01d] %s %s",
msg->can_id & QEMU_CAN_EFF_MASK,
msg->can_dlc,
@@ -89,7 +88,7 @@ static void can_host_socketcan_display_msg(struct qemu_can_frame *msg)
}
qemu_log("\n");
qemu_log_flush();
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
static void can_host_socketcan_read(void *opaque)
diff --git a/pc-bios/bios-256k.bin b/pc-bios/bios-256k.bin
index 40e7e67..4af7f7d 100644
--- a/pc-bios/bios-256k.bin
+++ b/pc-bios/bios-256k.bin
Binary files differ
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index 97b1e23..67874c3 100644
--- a/pc-bios/bios.bin
+++ b/pc-bios/bios.bin
Binary files differ
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
index c84ae93..91cdee4 100644
--- a/pc-bios/s390-ccw.img
+++ b/pc-bios/s390-ccw.img
Binary files differ
diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c
index 266f150..da13c43 100644
--- a/pc-bios/s390-ccw/jump2ipl.c
+++ b/pc-bios/s390-ccw/jump2ipl.c
@@ -12,11 +12,11 @@
#define KERN_IMAGE_START 0x010000UL
#define PSW_MASK_64 0x0000000100000000ULL
#define PSW_MASK_32 0x0000000080000000ULL
-#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64)
+#define PSW_MASK_SHORTPSW 0x0008000000000000ULL
+#define RESET_PSW_MASK (PSW_MASK_SHORTPSW | PSW_MASK_32 | PSW_MASK_64)
typedef struct ResetInfo {
- uint32_t ipl_mask;
- uint32_t ipl_addr;
+ uint64_t ipl_psw;
uint32_t ipl_continue;
} ResetInfo;
@@ -50,7 +50,9 @@ void jump_to_IPL_code(uint64_t address)
ResetInfo *current = 0;
save = *current;
- current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2;
+
+ current->ipl_psw = (uint64_t) &jump_to_IPL_2;
+ current->ipl_psw |= RESET_PSW_MASK;
current->ipl_continue = address & 0x7fffffff;
debug_print_int("set IPL addr to", current->ipl_continue);
@@ -82,7 +84,7 @@ void jump_to_low_kernel(void)
}
/* Trying to get PSW at zero address */
- if (*((uint64_t *)0) & IPL_PSW_MASK) {
+ if (*((uint64_t *)0) & RESET_PSW_MASK) {
jump_to_IPL_code((*((uint64_t *)0)) & 0x7fffffff);
}
diff --git a/pc-bios/s390-netboot.img b/pc-bios/s390-netboot.img
index f9ef28e..6bb5c86 100644
--- a/pc-bios/s390-netboot.img
+++ b/pc-bios/s390-netboot.img
Binary files differ
diff --git a/pc-bios/vgabios-ati.bin b/pc-bios/vgabios-ati.bin
index b5314fb..6202cf7 100644
--- a/pc-bios/vgabios-ati.bin
+++ b/pc-bios/vgabios-ati.bin
Binary files differ
diff --git a/pc-bios/vgabios-bochs-display.bin b/pc-bios/vgabios-bochs-display.bin
index 5033cc8..b675f86 100644
--- a/pc-bios/vgabios-bochs-display.bin
+++ b/pc-bios/vgabios-bochs-display.bin
Binary files differ
diff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin
index 4a36439..63fde14 100644
--- a/pc-bios/vgabios-cirrus.bin
+++ b/pc-bios/vgabios-cirrus.bin
Binary files differ
diff --git a/pc-bios/vgabios-qxl.bin b/pc-bios/vgabios-qxl.bin
index f6811bc..8016882 100644
--- a/pc-bios/vgabios-qxl.bin
+++ b/pc-bios/vgabios-qxl.bin
Binary files differ
diff --git a/pc-bios/vgabios-ramfb.bin b/pc-bios/vgabios-ramfb.bin
index 79986b2..1dc413d 100644
--- a/pc-bios/vgabios-ramfb.bin
+++ b/pc-bios/vgabios-ramfb.bin
Binary files differ
diff --git a/pc-bios/vgabios-stdvga.bin b/pc-bios/vgabios-stdvga.bin
index d709ec6..f92b9a6 100644
--- a/pc-bios/vgabios-stdvga.bin
+++ b/pc-bios/vgabios-stdvga.bin
Binary files differ
diff --git a/pc-bios/vgabios-virtio.bin b/pc-bios/vgabios-virtio.bin
index b99faf4..b0d2f70 100644
--- a/pc-bios/vgabios-virtio.bin
+++ b/pc-bios/vgabios-virtio.bin
Binary files differ
diff --git a/pc-bios/vgabios-vmware.bin b/pc-bios/vgabios-vmware.bin
index 8c92ab7..1c2776e 100644
--- a/pc-bios/vgabios-vmware.bin
+++ b/pc-bios/vgabios-vmware.bin
Binary files differ
diff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin
index aeae036..c5aad8f 100644
--- a/pc-bios/vgabios.bin
+++ b/pc-bios/vgabios.bin
Binary files differ
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 0cf68fe..7ff5e5e 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2884,15 +2884,16 @@
# @copy-on-read: Since 3.0
# @blklogwrites: Since 3.0
# @blkreplay: Since 4.2
+# @compress: Since 5.0
#
# Since: 2.9
##
{ 'enum': 'BlockdevDriver',
'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs',
- 'cloop', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster',
- 'host_cdrom', 'host_device', 'http', 'https', 'iscsi', 'luks',
- 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'qcow',
- 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
+ 'cloop', 'compress', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps',
+ 'gluster', 'host_cdrom', 'host_device', 'http', 'https', 'iscsi',
+ 'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels',
+ 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
{ 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
'sheepdog',
'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
@@ -2963,9 +2964,13 @@
#
# Driver specific block device options for the NVMe backend.
#
-# @device: controller address of the NVMe device.
+# @device: PCI controller address of the NVMe device in
+# format hhhh:bb:ss.f (host:bus:slot.function)
# @namespace: namespace number of the device, starting from 1.
#
+# Note that the PCI @device must have been unbound from any host
+# kernel driver before instructing QEMU to add the blockdev.
+#
# Since: 2.12
##
{ 'struct': 'BlockdevOptionsNVMe',
@@ -3450,6 +3455,16 @@
#
# @set-state: array of state-change descriptions
#
+# @take-child-perms: Permissions to take on @image in addition to what
+# is necessary anyway (which depends on how the
+# blkdebug node is used). Defaults to none.
+# (since 5.0)
+#
+# @unshare-child-perms: Permissions not to share on @image in addition
+# to what cannot be shared anyway (which depends
+# on how the blkdebug node is used). Defaults
+# to none. (since 5.0)
+#
# Since: 2.9
##
{ 'struct': 'BlockdevOptionsBlkdebug',
@@ -3459,7 +3474,9 @@
'*opt-write-zero': 'int32', '*max-write-zero': 'int32',
'*opt-discard': 'int32', '*max-discard': 'int32',
'*inject-error': ['BlkdebugInjectErrorOptions'],
- '*set-state': ['BlkdebugSetStateOptions'] } }
+ '*set-state': ['BlkdebugSetStateOptions'],
+ '*take-child-perms': ['BlockPermission'],
+ '*unshare-child-perms': ['BlockPermission'] } }
##
# @BlockdevOptionsBlklogwrites:
@@ -4044,6 +4061,7 @@
'blkreplay': 'BlockdevOptionsBlkreplay',
'bochs': 'BlockdevOptionsGenericFormat',
'cloop': 'BlockdevOptionsGenericFormat',
+ 'compress': 'BlockdevOptionsGenericFormat',
'copy-on-read':'BlockdevOptionsGenericFormat',
'dmg': 'BlockdevOptionsGenericFormat',
'file': 'BlockdevOptionsFile',
diff --git a/qemu-deprecated.texi b/qemu-deprecated.texi
index 97ba3cb..0968d37 100644
--- a/qemu-deprecated.texi
+++ b/qemu-deprecated.texi
@@ -284,6 +284,17 @@ spec you can use the ``-cpu rv64gcsu,priv_spec=v1.9.1`` command line argument.
@section Device options
+@subsection Emulated device options
+
+@subsubsection -device virtio-blk,scsi=on|off (since 5.0.0)
+
+The virtio-blk SCSI passthrough feature is a legacy VIRTIO feature. VIRTIO 1.0
+and later do not support it because the virtio-scsi device was introduced for
+full SCSI support. Use virtio-scsi instead when SCSI passthrough is required.
+
+Note this also applies to ``-device virtio-blk-pci,scsi=on|off'', which is an
+alias.
+
@subsection Block device options
@subsubsection "backing": "" (since 2.12.0)
@@ -373,6 +384,14 @@ guarantees must resolve the CPU model aliases using te
``alias-of'' field returned by the ``query-cpu-definitions'' QMP
command.
+While those guarantees are kept, the return value of
+``query-cpu-definitions'' will have existing CPU model aliases
+point to a version that doesn't break runnability guarantees
+(specifically, version 1 of those CPU models). In future QEMU
+versions, aliases will point to newer CPU model versions
+depending on the machine type, so management software must
+resolve CPU model aliases before starting a virtual machine.
+
@node Recently removed features
@appendix Recently removed features
diff --git a/qemu-doc.texi b/qemu-doc.texi
index eea91a2..39f9504 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -38,7 +38,6 @@
* Introduction::
* QEMU PC System emulator::
* QEMU System emulator for non PC targets::
-* QEMU Guest Agent::
* QEMU User space emulator::
* System requirements::
* Security::
diff --git a/qemu-img.c b/qemu-img.c
index 95a24b9..6233b8c 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2680,7 +2680,10 @@ static ImageInfoList *collect_image_info_list(bool image_opts,
blk_unref(blk);
+ /* Clear parameters that only apply to the topmost image */
filename = fmt = NULL;
+ image_opts = false;
+
if (chain) {
if (info->has_full_backing_filename) {
filename = info->full_backing_filename;
diff --git a/qemu-options.hx b/qemu-options.hx
index 64442b6..e9d6231 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -334,8 +334,8 @@ format(true color). The resolution should be supported by the SVGA mode, so
the recommended is 320x240, 640x480, 800x640.
A timeout could be passed to bios, guest will pause for @var{rb_timeout} ms
-when boot failed, then reboot. If @option{reboot-timeout} is not set,
-guest will not reboot by default. Currently Seabios for X86
+when boot failed, then reboot. If @var{rb_timeout} is '-1', guest will not
+reboot, qemu passes '-1' to bios by default. Currently Seabios for X86
system support it.
Do strict boot via @option{strict=on} as far as firmware/BIOS
diff --git a/roms/config.seabios-128k b/roms/config.seabios-128k
index a17502c..c43912b 100644
--- a/roms/config.seabios-128k
+++ b/roms/config.seabios-128k
@@ -15,3 +15,4 @@ CONFIG_PVSCSI=n
CONFIG_NVME=n
CONFIG_USE_SMM=n
CONFIG_VGAHOOKS=n
+CONFIG_HOST_BIOS_GEOMETRY=n
diff --git a/roms/seabios b/roms/seabios
-Subproject c9ba5276e3217ac6a1ec772dbebf568ba3a8a55
+Subproject f21b5a4aeb020f2a5e2c6503f906a9349dd2f06
diff --git a/stubs/vmstate.c b/stubs/vmstate.c
index e1e89b8..6951d9f 100644
--- a/stubs/vmstate.c
+++ b/stubs/vmstate.c
@@ -3,7 +3,7 @@
const VMStateDescription vmstate_dummy = {};
-int vmstate_register_with_alias_id(DeviceState *dev,
+int vmstate_register_with_alias_id(VMStateIf *obj,
int instance_id,
const VMStateDescription *vmsd,
void *base, int alias_id,
@@ -13,7 +13,7 @@ int vmstate_register_with_alias_id(DeviceState *dev,
return 0;
}
-void vmstate_unregister(DeviceState *dev,
+void vmstate_unregister(VMStateIf *obj,
const VMStateDescription *vmsd,
void *opaque)
{
diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
index b064513..b75f813 100644
--- a/target/arm/arm-powerctl.c
+++ b/target/arm/arm-powerctl.c
@@ -127,6 +127,9 @@ static void arm_set_cpu_on_async_work(CPUState *target_cpu_state,
target_cpu->env.regs[0] = info->context_id;
}
+ /* CP15 update requires rebuilding hflags */
+ arm_rebuild_hflags(&target_cpu->env);
+
/* Start the new CPU at the requested address */
cpu_set_pc(target_cpu_state, info->entry);
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index dd51ada..d62fd5f 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -976,6 +976,10 @@ static void arm_cpu_initfn(Object *obj)
}
}
+static Property arm_cpu_gt_cntfrq_property =
+ DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq_hz,
+ NANOSECONDS_PER_SECOND / GTIMER_SCALE);
+
static Property arm_cpu_reset_cbar_property =
DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
@@ -1055,6 +1059,30 @@ static void arm_set_init_svtor(Object *obj, Visitor *v, const char *name,
visit_type_uint32(v, name, &cpu->init_svtor, errp);
}
+unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
+{
+ /*
+ * The exact approach to calculating guest ticks is:
+ *
+ * muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), cpu->gt_cntfrq_hz,
+ * NANOSECONDS_PER_SECOND);
+ *
+ * We don't do that. Rather we intentionally use integer division
+ * truncation below and in the caller for the conversion of host monotonic
+ * time to guest ticks to provide the exact inverse for the semantics of
+ * the QEMUTimer scale factor. QEMUTimer's scale facter is an integer, so
+ * it loses precision when representing frequencies where
+ * `(NANOSECONDS_PER_SECOND % cpu->gt_cntfrq) > 0` holds. Failing to
+ * provide an exact inverse leads to scheduling timers with negative
+ * periods, which in turn leads to sticky behaviour in the guest.
+ *
+ * Finally, CNTFRQ is effectively capped at 1GHz to ensure our scale factor
+ * cannot become zero.
+ */
+ return NANOSECONDS_PER_SECOND > cpu->gt_cntfrq_hz ?
+ NANOSECONDS_PER_SECOND / cpu->gt_cntfrq_hz : 1;
+}
+
void arm_cpu_post_init(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
@@ -1172,6 +1200,11 @@ void arm_cpu_post_init(Object *obj)
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
&error_abort);
+
+ if (arm_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER)) {
+ qdev_property_add_static(DEVICE(cpu), &arm_cpu_gt_cntfrq_property,
+ &error_abort);
+ }
}
static void arm_cpu_finalizefn(Object *obj)
@@ -1251,14 +1284,30 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
}
}
- cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
- arm_gt_ptimer_cb, cpu);
- cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
- arm_gt_vtimer_cb, cpu);
- cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
- arm_gt_htimer_cb, cpu);
- cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
- arm_gt_stimer_cb, cpu);
+
+ {
+ uint64_t scale;
+
+ if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
+ if (!cpu->gt_cntfrq_hz) {
+ error_setg(errp, "Invalid CNTFRQ: %"PRId64"Hz",
+ cpu->gt_cntfrq_hz);
+ return;
+ }
+ scale = gt_cntfrq_period_ns(cpu);
+ } else {
+ scale = GTIMER_SCALE;
+ }
+
+ cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+ arm_gt_ptimer_cb, cpu);
+ cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+ arm_gt_vtimer_cb, cpu);
+ cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+ arm_gt_htimer_cb, cpu);
+ cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+ arm_gt_stimer_cb, cpu);
+ }
#endif
cpu_exec_realizefn(cs, &local_err);
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 5f70e9e..40f2c45 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -932,8 +932,13 @@ struct ARMCPU {
*/
DECLARE_BITMAP(sve_vq_map, ARM_MAX_VQ);
DECLARE_BITMAP(sve_vq_init, ARM_MAX_VQ);
+
+ /* Generic timer counter frequency, in Hz */
+ uint64_t gt_cntfrq_hz;
};
+unsigned int gt_cntfrq_period_ns(ARMCPU *cpu);
+
void arm_cpu_post_init(Object *obj);
uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 5074b5f..b6bec42 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2449,7 +2449,9 @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
static uint64_t gt_get_countervalue(CPUARMState *env)
{
- return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE;
+ ARMCPU *cpu = env_archcpu(env);
+
+ return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / gt_cntfrq_period_ns(cpu);
}
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
@@ -2485,10 +2487,11 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
* set the timer for as far in the future as possible. When the
* timer expires we will reset the timer for any remaining period.
*/
- if (nexttick > INT64_MAX / GTIMER_SCALE) {
- nexttick = INT64_MAX / GTIMER_SCALE;
+ if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) {
+ timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX);
+ } else {
+ timer_mod(cpu->gt_timer[timeridx], nexttick);
}
- timer_mod(cpu->gt_timer[timeridx], nexttick);
trace_arm_gt_recalc(timeridx, irqstate, nexttick);
} else {
/* Timer disabled: ISTATUS and timer output always clear */
@@ -2720,6 +2723,13 @@ void arm_gt_stimer_cb(void *opaque)
gt_recalc_timer(cpu, GTIMER_SEC);
}
+static void arm_gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *opaque)
+{
+ ARMCPU *cpu = env_archcpu(env);
+
+ cpu->env.cp15.c14_cntfrq = cpu->gt_cntfrq_hz;
+}
+
static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
/* Note that CNTFRQ is purely reads-as-written for the benefit
* of software; writing it doesn't actually change the timer frequency.
@@ -2734,7 +2744,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0,
.access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
.fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq),
- .resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE,
+ .resetfn = arm_gt_cntfrq_reset,
},
/* overall control: mostly access permissions */
{ .name = "CNTKCTL", .state = ARM_CP_STATE_BOTH,
@@ -2913,11 +2923,13 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
+ ARMCPU *cpu = env_archcpu(env);
+
/* Currently we have no support for QEMUTimer in linux-user so we
* can't call gt_get_countervalue(env), instead we directly
* call the lower level functions.
*/
- return cpu_get_clock() / GTIMER_SCALE;
+ return cpu_get_clock() / gt_cntfrq_period_ns(cpu);
}
static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
@@ -11500,6 +11512,20 @@ void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el)
env->hflags = rebuild_hflags_a64(env, el, fp_el, mmu_idx);
}
+static inline void assert_hflags_rebuild_correctly(CPUARMState *env)
+{
+#ifdef CONFIG_DEBUG_TCG
+ uint32_t env_flags_current = env->hflags;
+ uint32_t env_flags_rebuilt = rebuild_hflags_internal(env);
+
+ if (unlikely(env_flags_current != env_flags_rebuilt)) {
+ fprintf(stderr, "TCG hflags mismatch (current:0x%08x rebuilt:0x%08x)\n",
+ env_flags_current, env_flags_rebuilt);
+ abort();
+ }
+#endif
+}
+
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *pflags)
{
@@ -11507,9 +11533,7 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
uint32_t pstate_for_ss;
*cs_base = 0;
-#ifdef CONFIG_DEBUG_TCG
- assert(flags == rebuild_hflags_internal(env));
-#endif
+ assert_hflags_rebuild_correctly(env);
if (FIELD_EX32(flags, TBFLAG_ANY, AARCH64_STATE)) {
*pc = env->pc;
diff --git a/target/cris/translate.c b/target/cris/translate.c
index e752bd0..cb57516 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -3273,11 +3273,11 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
#if !DISAS_CRIS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
qemu_log("--------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start);
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
#endif
#endif
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index e1eb9f4..31556b7 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -3981,7 +3981,13 @@ static PropValue tcg_default_props[] = {
};
-X86CPUVersion default_cpu_version = CPU_VERSION_LATEST;
+/*
+ * We resolve CPU model aliases using -v1 when using "-machine
+ * none", but this is just for compatibility while libvirt isn't
+ * adapted to resolve CPU model versions before creating VMs.
+ * See "Runnability guarantee of CPU models" at * qemu-deprecated.texi.
+ */
+X86CPUVersion default_cpu_version = 1;
void x86_cpu_set_default_version(X86CPUVersion version)
{
diff --git a/target/i386/translate.c b/target/i386/translate.c
index 77e932d..7c99ef1 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -2502,14 +2502,15 @@ static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
gen_illegal_opcode(s);
if (qemu_loglevel_mask(LOG_UNIMP)) {
+ FILE *logfile = qemu_log_lock();
target_ulong pc = s->pc_start, end = s->pc;
- qemu_log_lock();
+
qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
for (; pc < end; ++pc) {
qemu_log(" %02x", cpu_ldub_code(env, pc));
}
qemu_log("\n");
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
}
diff --git a/target/lm32/translate.c b/target/lm32/translate.c
index 778cae1..73db965 100644
--- a/target/lm32/translate.c
+++ b/target/lm32/translate.c
@@ -1137,10 +1137,10 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
qemu_log("\n");
log_target_disas(cs, pc_start, dc->pc - pc_start);
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
#endif
}
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index bdc7d53..525115b 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -1765,10 +1765,10 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
#if !SIM_COMPAT
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
qemu_log("--------------\n");
log_target_disas(cs, pc_start, dc->pc - pc_start);
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
#endif
#endif
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index e17656e..82107bf 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -892,11 +892,11 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(tb->pc)) {
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(tb->pc));
log_target_disas(cs, tb->pc, dc->pc - tb->pc);
qemu_log("\n");
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
#endif
}
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 99ea090..625daee 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -76,8 +76,16 @@ static bool s390_cpu_has_work(CPUState *cs)
static void s390_cpu_load_normal(CPUState *s)
{
S390CPU *cpu = S390_CPU(s);
- cpu->env.psw.addr = ldl_phys(s->as, 4) & PSW_MASK_ESA_ADDR;
- cpu->env.psw.mask = PSW_MASK_32 | PSW_MASK_64;
+ uint64_t spsw = ldq_phys(s->as, 0);
+
+ cpu->env.psw.mask = spsw & 0xffffffff80000000ULL;
+ /*
+ * Invert short psw indication, so SIE will report a specification
+ * exception if it was not set.
+ */
+ cpu->env.psw.mask ^= PSW_MASK_SHORTPSW;
+ cpu->env.psw.addr = spsw & 0x7fffffffULL;
+
s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
}
#endif
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index aa829e9..e195e5c 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -269,6 +269,7 @@ extern const VMStateDescription vmstate_s390_cpu;
#define PSW_MASK_EXT 0x0100000000000000ULL
#define PSW_MASK_KEY 0x00F0000000000000ULL
#define PSW_SHIFT_KEY 52
+#define PSW_MASK_SHORTPSW 0x0008000000000000ULL
#define PSW_MASK_MCHECK 0x0004000000000000ULL
#define PSW_MASK_WAIT 0x0002000000000000ULL
#define PSW_MASK_PSTATE 0x0001000000000000ULL
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index 56e8149..b5813c2 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -324,13 +324,10 @@ DEF_HELPER_FLAGS_4(ipte, TCG_CALL_NO_RWG, void, env, i64, i64, i32)
DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env)
DEF_HELPER_FLAGS_1(purge, TCG_CALL_NO_RWG, void, env)
DEF_HELPER_2(lra, i64, env, i64)
-DEF_HELPER_FLAGS_2(lura, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_2(lurag, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_3(stura, TCG_CALL_NO_WG, void, env, i64, i64)
-DEF_HELPER_FLAGS_3(sturg, TCG_CALL_NO_WG, void, env, i64, i64)
DEF_HELPER_1(per_check_exception, void, env)
DEF_HELPER_FLAGS_3(per_branch, TCG_CALL_NO_RWG, void, env, i64, i64)
DEF_HELPER_FLAGS_2(per_ifetch, TCG_CALL_NO_RWG, void, env, i64)
+DEF_HELPER_FLAGS_1(per_store_real, TCG_CALL_NO_RWG, void, env)
DEF_HELPER_FLAGS_1(stfl, TCG_CALL_NO_RWG, void, env)
DEF_HELPER_2(xsch, void, env, i64)
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index 449eee1..2bc77f0 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -1275,8 +1275,8 @@
F(0xe313, LRAY, RXY_a, LD, 0, a2, r1, 0, lra, 0, IF_PRIV)
F(0xe303, LRAG, RXY_a, Z, 0, a2, r1, 0, lra, 0, IF_PRIV)
/* LOAD USING REAL ADDRESS */
- F(0xb24b, LURA, RRE, Z, 0, r2, new, r1_32, lura, 0, IF_PRIV)
- F(0xb905, LURAG, RRE, Z, 0, r2, r1, 0, lurag, 0, IF_PRIV)
+ E(0xb24b, LURA, RRE, Z, 0, 0, new, r1_32, lura, 0, MO_TEUL, IF_PRIV)
+ E(0xb905, LURAG, RRE, Z, 0, 0, r1, 0, lura, 0, MO_TEQ, IF_PRIV)
/* MOVE TO PRIMARY */
F(0xda00, MVCP, SS_d, Z, la1, a2, 0, 0, mvcp, 0, IF_PRIV)
/* MOVE TO SECONDARY */
@@ -1329,8 +1329,8 @@
/* STORE THEN OR SYSTEM MASK */
F(0xad00, STOSM, SI, Z, la1, 0, 0, 0, stnosm, 0, IF_PRIV)
/* STORE USING REAL ADDRESS */
- F(0xb246, STURA, RRE, Z, r1_o, r2_o, 0, 0, stura, 0, IF_PRIV)
- F(0xb925, STURG, RRE, Z, r1_o, r2_o, 0, 0, sturg, 0, IF_PRIV)
+ E(0xb246, STURA, RRE, Z, r1_o, 0, 0, 0, stura, 0, MO_TEUL, IF_PRIV)
+ E(0xb925, STURG, RRE, Z, r1_o, 0, 0, 0, stura, 0, MO_TEQ, IF_PRIV)
/* TEST BLOCK */
F(0xb22c, TB, RRE, Z, 0, r2_o, 0, 0, testblock, 0, IF_PRIV)
/* TEST PROTECTION */
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 2325767..2921419 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -2329,44 +2329,6 @@ void HELPER(purge)(CPUS390XState *env)
tlb_flush_all_cpus_synced(env_cpu(env));
}
-/* load using real address */
-uint64_t HELPER(lura)(CPUS390XState *env, uint64_t addr)
-{
- return cpu_ldl_real_ra(env, wrap_address(env, addr), GETPC());
-}
-
-uint64_t HELPER(lurag)(CPUS390XState *env, uint64_t addr)
-{
- return cpu_ldq_real_ra(env, wrap_address(env, addr), GETPC());
-}
-
-/* store using real address */
-void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint64_t v1)
-{
- cpu_stl_real_ra(env, wrap_address(env, addr), (uint32_t)v1, GETPC());
-
- if ((env->psw.mask & PSW_MASK_PER) &&
- (env->cregs[9] & PER_CR9_EVENT_STORE) &&
- (env->cregs[9] & PER_CR9_EVENT_STORE_REAL)) {
- /* PSW is saved just before calling the helper. */
- env->per_address = env->psw.addr;
- env->per_perc_atmid = PER_CODE_EVENT_STORE_REAL | get_per_atmid(env);
- }
-}
-
-void HELPER(sturg)(CPUS390XState *env, uint64_t addr, uint64_t v1)
-{
- cpu_stq_real_ra(env, wrap_address(env, addr), v1, GETPC());
-
- if ((env->psw.mask & PSW_MASK_PER) &&
- (env->cregs[9] & PER_CR9_EVENT_STORE) &&
- (env->cregs[9] & PER_CR9_EVENT_STORE_REAL)) {
- /* PSW is saved just before calling the helper. */
- env->per_address = env->psw.addr;
- env->per_perc_atmid = PER_CODE_EVENT_STORE_REAL | get_per_atmid(env);
- }
-}
-
/* load real address */
uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr)
{
diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c
index bfb457f..58dbc02 100644
--- a/target/s390x/misc_helper.c
+++ b/target/s390x/misc_helper.c
@@ -620,6 +620,16 @@ void HELPER(per_ifetch)(CPUS390XState *env, uint64_t addr)
}
}
}
+
+void HELPER(per_store_real)(CPUS390XState *env)
+{
+ if ((env->cregs[9] & PER_CR9_EVENT_STORE) &&
+ (env->cregs[9] & PER_CR9_EVENT_STORE_REAL)) {
+ /* PSW is saved just before calling the helper. */
+ env->per_address = env->psw.addr;
+ env->per_perc_atmid = PER_CODE_EVENT_STORE_REAL | get_per_atmid(env);
+ }
+}
#endif
static uint8_t stfl_bytes[2048];
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 151dfa9..4292bb0 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -3272,13 +3272,8 @@ static DisasJumpType op_lpq(DisasContext *s, DisasOps *o)
#ifndef CONFIG_USER_ONLY
static DisasJumpType op_lura(DisasContext *s, DisasOps *o)
{
- gen_helper_lura(o->out, cpu_env, o->in2);
- return DISAS_NEXT;
-}
-
-static DisasJumpType op_lurag(DisasContext *s, DisasOps *o)
-{
- gen_helper_lurag(o->out, cpu_env, o->in2);
+ o->addr1 = get_address(s, 0, get_field(s->fields, r2), 0);
+ tcg_gen_qemu_ld_tl(o->out, o->addr1, MMU_REAL_IDX, s->insn->data);
return DISAS_NEXT;
}
#endif
@@ -4506,13 +4501,13 @@ static DisasJumpType op_stnosm(DisasContext *s, DisasOps *o)
static DisasJumpType op_stura(DisasContext *s, DisasOps *o)
{
- gen_helper_stura(cpu_env, o->in2, o->in1);
- return DISAS_NEXT;
-}
+ o->addr1 = get_address(s, 0, get_field(s->fields, r2), 0);
+ tcg_gen_qemu_st_tl(o->in1, o->addr1, MMU_REAL_IDX, s->insn->data);
-static DisasJumpType op_sturg(DisasContext *s, DisasOps *o)
-{
- gen_helper_sturg(cpu_env, o->in2, o->in1);
+ if (s->base.tb->flags & FLAG_MASK_PER) {
+ update_psw_addr(s);
+ gen_helper_per_store_real(cpu_env);
+ }
return DISAS_NEXT;
}
#endif
diff --git a/target/sparc/TODO b/target/sparc/TODO
deleted file mode 100644
index b8c727e..0000000
--- a/target/sparc/TODO
+++ /dev/null
@@ -1,88 +0,0 @@
-TODO-list:
-
-CPU common:
-- Unimplemented features/bugs:
- - Delay slot handling may fail sometimes (branch end of page, delay
- slot next page)
- - Atomical instructions
- - CPU features should match real CPUs (also ASI selection)
-- Optimizations/improvements:
- - Condition code/branch handling like x86, also for FPU?
- - Remove remaining explicit alignment checks
- - Global register for regwptr, so that windowed registers can be
- accessed directly
- - Improve Sparc32plus addressing
- - NPC/PC static optimisations (use JUMP_TB when possible)? (Is this
- obsolete?)
- - Synthetic instructions
- - MMU model dependent on CPU model
- - Select ASI helper at translation time (on V9 only if known)
- - KQemu/KVM support for VM only
- - Hardware breakpoint/watchpoint support
- - Cache emulation mode
- - Reverse-endian pages
- - Faster FPU emulation
- - Busy loop detection
-
-Sparc32 CPUs:
-- Unimplemented features/bugs:
- - Sun4/Sun4c MMUs
- - Some V8 ASIs
-
-Sparc64 CPUs:
-- Unimplemented features/bugs:
- - Interrupt handling
- - Secondary address space, other MMU functions
- - Many V9/UA2005/UA2007 ASIs
- - Rest of V9 instructions, missing VIS instructions
- - IG/MG/AG vs. UA2007 globals
- - Full hypervisor support
- - SMP/CMT
- - Sun4v CPUs
-
-Sun4:
-- To be added
-
-Sun4c:
-- A lot of unimplemented features
-- Maybe split from Sun4m
-
-Sun4m:
-- Unimplemented features/bugs:
- - Hardware devices do not match real boards
- - Floppy does not work
- - CS4231: merge with cs4231a, add DMA
- - Add cg6, bwtwo
- - Arbitrary resolution support
- - PCI for MicroSparc-IIe
- - JavaStation machines
- - SBus slot probing, FCode ROM support
- - SMP probing support
- - Interrupt routing does not match real HW
- - SuSE 7.3 keyboard sometimes unresponsive
- - Gentoo 2004.1 SMP does not work
- - SS600MP ledma -> lebuffer
- - Type 5 keyboard
- - Less fixed hardware choices
- - DBRI audio (Am7930)
- - BPP parallel
- - Diagnostic switch
- - ESP PIO mode
-
-Sun4d:
-- A lot of unimplemented features:
- - SBI
- - IO-unit
-- Maybe split from Sun4m
-
-Sun4u:
-- Unimplemented features/bugs:
- - Interrupt controller
- - PCI/IOMMU support (Simba, JIO, Tomatillo, Psycho, Schizo, Safari...)
- - SMP
- - Happy Meal Ethernet, flash, I2C, GPIO
- - A lot of real machine types
-
-Sun4v:
-- A lot of unimplemented features
- - A lot of real machine types
diff --git a/target/tilegx/translate.c b/target/tilegx/translate.c
index 68dd4aa..abce7e1 100644
--- a/target/tilegx/translate.c
+++ b/target/tilegx/translate.c
@@ -2388,7 +2388,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
dc->zero = NULL;
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
- qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(pc_start));
}
gen_tb_start(tb);
@@ -2417,11 +2416,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
gen_tb_end(tb, num_insns);
tb->size = dc->pc - pc_start;
tb->icount = num_insns;
-
- if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
- qemu_log("\n");
- qemu_log_unlock();
- }
}
void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb,
diff --git a/target/unicore32/translate.c b/target/unicore32/translate.c
index 0e01f35..0f6891b 100644
--- a/target/unicore32/translate.c
+++ b/target/unicore32/translate.c
@@ -1994,12 +1994,12 @@ done_generating:
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start);
qemu_log("\n");
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
#endif
tb->size = dc->pc - pc_start;
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index b363ffc..75e65df 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -645,7 +645,9 @@ static inline int xtensa_get_cintlevel(const CPUXtensaState *env)
static inline int xtensa_get_ring(const CPUXtensaState *env)
{
- if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
+ if (xtensa_option_bits_enabled(env->config,
+ XTENSA_OPTION_BIT(XTENSA_OPTION_MMU) |
+ XTENSA_OPTION_BIT(XTENSA_OPTION_MPU))) {
return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
} else {
return 0;
@@ -654,8 +656,10 @@ static inline int xtensa_get_ring(const CPUXtensaState *env)
static inline int xtensa_get_cring(const CPUXtensaState *env)
{
- if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) &&
- (env->sregs[PS] & PS_EXCM) == 0) {
+ if (xtensa_option_bits_enabled(env->config,
+ XTENSA_OPTION_BIT(XTENSA_OPTION_MMU) |
+ XTENSA_OPTION_BIT(XTENSA_OPTION_MPU)) &&
+ (env->sregs[PS] & PS_EXCM) == 0) {
return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
} else {
return 0;
diff --git a/target/xtensa/import_core.sh b/target/xtensa/import_core.sh
index e4a2e39..8f844cf 100755
--- a/target/xtensa/import_core.sh
+++ b/target/xtensa/import_core.sh
@@ -19,8 +19,9 @@ exit
[ $# -ge 3 ] && FREQ="$3"
mkdir -p "$TARGET"
-tar -xf "$OVERLAY" -C "$TARGET" --strip-components=1 \
- --xform='s/core/core-isa/' config/core.h
+tar -xf "$OVERLAY" -C "$TARGET" --strip-components=2 \
+ xtensa/config/core-isa.h \
+ xtensa/config/core-matmap.h
tar -xf "$OVERLAY" -O gdb/xtensa-config.c | \
sed -n '1,/*\//p;/XTREG/,/XTREG_END/p' > "$TARGET"/gdb-config.inc.c
#
@@ -44,6 +45,7 @@ cat <<EOF > "${TARGET}.c"
#include "qemu/host-utils.h"
#include "core-$NAME/core-isa.h"
+#include "core-$NAME/core-matmap.h"
#include "overlay_tool.h"
#define xtensa_modules xtensa_modules_$NAME
diff --git a/target/xtensa/overlay_tool.h b/target/xtensa/overlay_tool.h
index f0cc33a..cab5320 100644
--- a/target/xtensa/overlay_tool.h
+++ b/target/xtensa/overlay_tool.h
@@ -373,15 +373,28 @@
#elif XCHAL_HAVE_MPU
#ifndef XTENSA_MPU_BG_MAP
+#ifdef XCHAL_MPU_BACKGROUND_MAP
+#define XCHAL_MPU_BGMAP(s, vaddr_start, vaddr_last, rights, memtype, x...) \
+ { .vaddr = (vaddr_start), .attr = ((rights) << 8) | ((memtype) << 12), },
+
+#define XTENSA_MPU_BG_MAP (xtensa_mpu_entry []){\
+ XCHAL_MPU_BACKGROUND_MAP(0) \
+}
+
+#define XTENSA_MPU_BG_MAP_ENTRIES XCHAL_MPU_BACKGROUND_ENTRIES
+#else
#define XTENSA_MPU_BG_MAP (xtensa_mpu_entry []){\
{ .vaddr = 0, .attr = 0x00006700, }, \
}
+
+#define XTENSA_MPU_BG_MAP_ENTRIES 1
+#endif
#endif
#define TLB_SECTION \
.mpu_align = XCHAL_MPU_ALIGN, \
.n_mpu_fg_segments = XCHAL_MPU_ENTRIES, \
- .n_mpu_bg_segments = 1, \
+ .n_mpu_bg_segments = XTENSA_MPU_BG_MAP_ENTRIES, \
.mpu_bg = XTENSA_MPU_BG_MAP
#ifndef XCHAL_SYSROM0_PADDR
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index a99f529..e6d9107 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -2713,7 +2713,8 @@ static void translate_wsr_ps(DisasContext *dc, const OpcodeArg arg[],
uint32_t mask = PS_WOE | PS_CALLINC | PS_OWB |
PS_UM | PS_EXCM | PS_INTLEVEL;
- if (option_enabled(dc, XTENSA_OPTION_MMU)) {
+ if (option_enabled(dc, XTENSA_OPTION_MMU) ||
+ option_enabled(dc, XTENSA_OPTION_MPU)) {
mask |= PS_RING;
}
tcg_gen_andi_i32(cpu_SR[par[0]], arg[0].in, mask);
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 5475d49..4f616ba 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1085,7 +1085,7 @@ void tcg_prologue_init(TCGContext *s)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
qemu_log("PROLOGUE: [size=%zu]\n", prologue_size);
if (s->data_gen_ptr) {
size_t code_size = s->data_gen_ptr - buf0;
@@ -1110,7 +1110,7 @@ void tcg_prologue_init(TCGContext *s)
}
qemu_log("\n");
qemu_log_flush();
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
#endif
@@ -2114,9 +2114,17 @@ static void tcg_dump_ops(TCGContext *s, bool have_prefs)
}
if (have_prefs || op->life) {
- for (; col < 40; ++col) {
- putc(' ', qemu_logfile);
+
+ QemuLogFile *logfile;
+
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ for (; col < 40; ++col) {
+ putc(' ', logfile->fd);
+ }
}
+ rcu_read_unlock();
}
if (op->life) {
@@ -4041,11 +4049,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)
&& qemu_log_in_addr_range(tb->pc))) {
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
qemu_log("OP:\n");
tcg_dump_ops(s, false);
qemu_log("\n");
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
#endif
@@ -4086,11 +4094,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_IND)
&& qemu_log_in_addr_range(tb->pc))) {
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
qemu_log("OP before indirect lowering:\n");
tcg_dump_ops(s, false);
qemu_log("\n");
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
#endif
/* Replace indirect temps with direct temps. */
@@ -4107,11 +4115,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT)
&& qemu_log_in_addr_range(tb->pc))) {
- qemu_log_lock();
+ FILE *logfile = qemu_log_lock();
qemu_log("OP after optimization and liveness analysis:\n");
tcg_dump_ops(s, true);
qemu_log("\n");
- qemu_log_unlock();
+ qemu_log_unlock(logfile);
}
#endif
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 31b8667..49e3b0d 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -158,12 +158,17 @@ check-qtest-generic-$(CONFIG_MODULES) += tests/modules-test$(EXESUF)
check-qtest-generic-y += tests/device-introspect-test$(EXESUF)
check-qtest-generic-y += tests/cdrom-test$(EXESUF)
+DBUS_DAEMON := $(shell which dbus-daemon 2>/dev/null)
+ifneq ($(GDBUS_CODEGEN),)
+ifneq ($(DBUS_DAEMON),)
+check-qtest-pci-$(CONFIG_GIO) += tests/dbus-vmstate-test$(EXESUF)
+endif
+endif
check-qtest-pci-$(CONFIG_RTL8139_PCI) += tests/rtl8139-test$(EXESUF)
check-qtest-pci-$(CONFIG_VGA) += tests/display-vga-test$(EXESUF)
check-qtest-pci-$(CONFIG_HDA) += tests/intel-hda-test$(EXESUF)
check-qtest-pci-$(CONFIG_IVSHMEM_DEVICE) += tests/ivshmem-test$(EXESUF)
-
check-qtest-i386-$(CONFIG_ISA_TESTDEV) = tests/endianness-test$(EXESUF)
check-qtest-i386-y += tests/fdc-test$(EXESUF)
check-qtest-i386-y += tests/ide-test$(EXESUF)
@@ -579,6 +584,7 @@ tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
hw/core/irq.o \
hw/core/fw-path-provider.o \
hw/core/reset.o \
+ hw/core/vmstate-if.o \
$(test-qapi-obj-y)
tests/test-vmstate$(EXESUF): tests/test-vmstate.o \
migration/vmstate.o migration/vmstate-types.o migration/qemu-file.o \
@@ -633,6 +639,19 @@ tests/qapi-schema/doc-good.test.texi: $(SRC_PATH)/tests/qapi-schema/doc-good.jso
@mv tests/qapi-schema/doc-good-qapi-doc.texi $@
@rm -f tests/qapi-schema/doc-good-qapi-*.[ch] tests/qapi-schema/doc-good-qmp-*.[ch]
+tests/dbus-vmstate1.h tests/dbus-vmstate1.c: tests/dbus-vmstate1-gen-timestamp ;
+tests/dbus-vmstate1-gen-timestamp: $(SRC_PATH)/tests/dbus-vmstate1.xml
+ $(call quiet-command,$(GDBUS_CODEGEN) $< \
+ --interface-prefix org.qemu --generate-c-code tests/dbus-vmstate1, \
+ "GEN","$(@:%-timestamp=%)")
+ @>$@
+
+tests/dbus-vmstate-test.o-cflags := -DSRCDIR="$(SRC_PATH)"
+tests/dbus-vmstate1.o-cflags := $(GIO_CFLAGS)
+tests/dbus-vmstate1.o-libs := $(GIO_LIBS)
+
+tests/dbus-vmstate-test.o: tests/dbus-vmstate1.h
+
tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y)
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-qapi-events.o
@@ -826,7 +845,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/cpu-plug-test$(EXESUF): tests/cpu-plug-test.o
-tests/migration-test$(EXESUF): tests/migration-test.o
+tests/migration-test$(EXESUF): tests/migration-test.o tests/migration-helpers.o
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)
tests/test-keyval$(EXESUF): tests/test-keyval.o $(test-util-obj-y) $(test-qapi-obj-y)
@@ -836,6 +855,7 @@ tests/test-filter-mirror$(EXESUF): tests/test-filter-mirror.o $(qtest-obj-y)
tests/test-filter-redirector$(EXESUF): tests/test-filter-redirector.o $(qtest-obj-y)
tests/test-x86-cpuid-compat$(EXESUF): tests/test-x86-cpuid-compat.o $(qtest-obj-y)
tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y) $(libqos-spapr-obj-y)
+tests/dbus-vmstate-test$(EXESUF): tests/dbus-vmstate-test.o tests/migration-helpers.o tests/dbus-vmstate1.o $(libqos-pc-obj-y) $(libqos-spapr-obj-y)
tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o $(test-util-obj-y) libvhost-user.a
tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y)
tests/test-arm-mptimer$(EXESUF): tests/test-arm-mptimer.o
@@ -1157,7 +1177,6 @@ TESTS_RESULTS_DIR=$(BUILD_DIR)/tests/results
AVOCADO_SHOW=app
AVOCADO_TAGS=$(patsubst %-softmmu,-t arch:%, $(filter %-softmmu,$(TARGET_DIRS)))
-ifneq ($(PYTHON2),y)
$(TESTS_VENV_DIR): $(TESTS_VENV_REQ)
$(call quiet-command, \
$(PYTHON) -m venv --system-site-packages $@, \
@@ -1166,10 +1185,6 @@ $(TESTS_VENV_DIR): $(TESTS_VENV_REQ)
$(TESTS_VENV_DIR)/bin/python -m pip -q install -r $(TESTS_VENV_REQ), \
PIP, $(TESTS_VENV_REQ))
$(call quiet-command, touch $@)
-else
-$(TESTS_VENV_DIR):
- $(error "venv directory for tests requires Python 3")
-endif
$(TESTS_RESULTS_DIR):
$(call quiet-command, mkdir -p $@, \
@@ -1199,6 +1214,7 @@ check-clean:
rm -rf $(check-unit-y) tests/*.o $(QEMU_IOTESTS_HELPERS-y)
rm -rf $(sort $(foreach target,$(SYSEMU_TARGET_LIST), $(check-qtest-$(target)-y)) $(check-qtest-generic-y))
rm -f tests/test-qapi-gen-timestamp
+ rm -f tests/dbus-vmstate1-gen-timestamp
rm -rf $(TESTS_VENV_DIR) $(TESTS_RESULTS_DIR)
clean: check-clean
diff --git a/tests/boot-sector.c b/tests/boot-sector.c
index 7824286..9e66c6d 100644
--- a/tests/boot-sector.c
+++ b/tests/boot-sector.c
@@ -75,11 +75,11 @@ static const uint8_t s390x_psw_and_magic[] = {
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* in the s390-ccw bios */
};
static const uint8_t s390x_code[] = {
- 0xa7, 0xf4, 0x00, 0x0a, /* j 0x10010 */
+ 0xa7, 0xf4, 0x00, 0x08, /* j 0x10010 */
0x00, 0x00, 0x00, 0x00,
'S', '3', '9', '0',
'E', 'P', 0x00, 0x01,
- 0xa7, 0x38, HIGH(SIGNATURE_ADDR), LOW(SIGNATURE_ADDR), /* lhi r3,0x7c10 */
+ 0xa7, 0x39, HIGH(SIGNATURE_ADDR), LOW(SIGNATURE_ADDR), /* lghi r3,0x7c10 */
0xa7, 0x48, LOW(SIGNATURE), HIGH(SIGNATURE), /* lhi r4,0xadde */
0x40, 0x40, 0x30, 0x00, /* sth r4,0(r3) */
0xa7, 0xf4, 0xff, 0xfa /* j 0x10010 */
diff --git a/tests/dbus-vmstate-daemon.sh b/tests/dbus-vmstate-daemon.sh
new file mode 100755
index 0000000..474e250
--- /dev/null
+++ b/tests/dbus-vmstate-daemon.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+# dbus-daemon wrapper script for dbus-vmstate testing
+#
+# This script allows to tweak the dbus-daemon policy during the test
+# to test different configurations.
+#
+# 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/>.
+#
+# Copyright (C) 2019 Red Hat, Inc.
+
+write_config()
+{
+ CONF="$1"
+ cat > "$CONF" <<EOF
+<busconfig>
+ <type>session</type>
+ <listen>unix:tmpdir=$DBUS_VMSTATE_TEST_TMPDIR</listen>
+
+ <policy context="default">
+ <!-- Holes must be punched in service configuration files for
+ name ownership and sending method calls -->
+ <deny own="*"/>
+ <deny send_type="method_call"/>
+
+ <!-- Signals and reply messages (method returns, errors) are allowed
+ by default -->
+ <allow send_type="signal"/>
+ <allow send_requested_reply="true" send_type="method_return"/>
+ <allow send_requested_reply="true" send_type="error"/>
+
+ <!-- All messages may be received by default -->
+ <allow receive_type="method_call"/>
+ <allow receive_type="method_return"/>
+ <allow receive_type="error"/>
+ <allow receive_type="signal"/>
+
+ <!-- Allow anyone to talk to the message bus -->
+ <allow send_destination="org.freedesktop.DBus"
+ send_interface="org.freedesktop.DBus" />
+ <allow send_destination="org.freedesktop.DBus"
+ send_interface="org.freedesktop.DBus.Introspectable"/>
+ <allow send_destination="org.freedesktop.DBus"
+ send_interface="org.freedesktop.DBus.Properties"/>
+ <!-- But disallow some specific bus services -->
+ <deny send_destination="org.freedesktop.DBus"
+ send_interface="org.freedesktop.DBus"
+ send_member="UpdateActivationEnvironment"/>
+ <deny send_destination="org.freedesktop.DBus"
+ send_interface="org.freedesktop.DBus.Debug.Stats"/>
+ <deny send_destination="org.freedesktop.DBus"
+ send_interface="org.freedesktop.systemd1.Activator"/>
+
+ <allow own="org.qemu.VMState1"/>
+ <allow send_destination="org.qemu.VMState1"/>
+ <allow receive_sender="org.qemu.VMState1"/>
+
+ </policy>
+
+ <include if_selinux_enabled="yes"
+ selinux_root_relative="yes">contexts/dbus_contexts</include>
+
+</busconfig>
+EOF
+}
+
+ARGS=
+for arg in "$@"
+do
+ case $arg in
+ --config-file=*)
+ CONF="${arg#*=}"
+ write_config "$CONF"
+ ARGS="$ARGS $1"
+ shift
+ ;;
+ *)
+ ARGS="$ARGS $1"
+ shift
+ ;;
+ esac
+done
+
+exec dbus-daemon $ARGS
diff --git a/tests/dbus-vmstate-test.c b/tests/dbus-vmstate-test.c
new file mode 100644
index 0000000..2e5e47d
--- /dev/null
+++ b/tests/dbus-vmstate-test.c
@@ -0,0 +1,382 @@
+#include "qemu/osdep.h"
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+#include "libqtest.h"
+#include "qemu-common.h"
+#include "dbus-vmstate1.h"
+#include "migration-helpers.h"
+
+static char *workdir;
+
+typedef struct TestServerId {
+ const char *name;
+ const char *data;
+ size_t size;
+} TestServerId;
+
+static const TestServerId idA = {
+ "idA", "I'am\0idA!", sizeof("I'am\0idA!")
+};
+
+static const TestServerId idB = {
+ "idB", "I'am\0idB!", sizeof("I'am\0idB!")
+};
+
+typedef struct TestServer {
+ const TestServerId *id;
+ bool save_called;
+ bool load_called;
+} TestServer;
+
+typedef struct Test {
+ const char *id_list;
+ bool migrate_fail;
+ bool without_dst_b;
+ TestServer srcA;
+ TestServer dstA;
+ TestServer srcB;
+ TestServer dstB;
+ GMainLoop *loop;
+ QTestState *src_qemu;
+} Test;
+
+static gboolean
+vmstate_load(VMState1 *object, GDBusMethodInvocation *invocation,
+ const gchar *arg_data, gpointer user_data)
+{
+ TestServer *h = user_data;
+ g_autoptr(GVariant) var = NULL;
+ GVariant *args;
+ const uint8_t *data;
+ size_t size;
+
+ args = g_dbus_method_invocation_get_parameters(invocation);
+ var = g_variant_get_child_value(args, 0);
+ data = g_variant_get_fixed_array(var, &size, sizeof(char));
+ g_assert_cmpuint(size, ==, h->id->size);
+ g_assert(!memcmp(data, h->id->data, h->id->size));
+ h->load_called = true;
+
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("()"));
+ return TRUE;
+}
+
+static gboolean
+vmstate_save(VMState1 *object, GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ TestServer *h = user_data;
+ GVariant *var;
+
+ var = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
+ h->id->data, h->id->size, sizeof(char));
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(@ay)", var));
+ h->save_called = true;
+
+ return TRUE;
+}
+
+typedef struct WaitNamed {
+ GMainLoop *loop;
+ bool named;
+} WaitNamed;
+
+static void
+named_cb(GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ WaitNamed *t = user_data;
+
+ t->named = true;
+ g_main_loop_quit(t->loop);
+}
+
+static GDBusConnection *
+get_connection(Test *test, guint *ownid)
+{
+ g_autofree gchar *addr = NULL;
+ WaitNamed *wait;
+ GError *err = NULL;
+ GDBusConnection *c;
+
+ wait = g_new0(WaitNamed, 1);
+ wait->loop = test->loop;
+ addr = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SESSION, NULL, &err);
+ g_assert_no_error(err);
+
+ c = g_dbus_connection_new_for_address_sync(
+ addr,
+ G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION |
+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
+ NULL, NULL, &err);
+ g_assert_no_error(err);
+ *ownid = g_bus_own_name_on_connection(c, "org.qemu.VMState1",
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ named_cb, named_cb, wait, g_free);
+ if (!wait->named) {
+ g_main_loop_run(wait->loop);
+ }
+
+ return c;
+}
+
+static GDBusObjectManagerServer *
+get_server(GDBusConnection *conn, TestServer *s, const TestServerId *id)
+{
+ g_autoptr(GDBusObjectSkeleton) sk = NULL;
+ g_autoptr(VMState1Skeleton) v = NULL;
+ GDBusObjectManagerServer *os;
+
+ s->id = id;
+ os = g_dbus_object_manager_server_new("/org/qemu");
+ sk = g_dbus_object_skeleton_new("/org/qemu/VMState1");
+
+ v = VMSTATE1_SKELETON(vmstate1_skeleton_new());
+ g_object_set(v, "id", id->name, NULL);
+
+ g_signal_connect(v, "handle-load", G_CALLBACK(vmstate_load), s);
+ g_signal_connect(v, "handle-save", G_CALLBACK(vmstate_save), s);
+
+ g_dbus_object_skeleton_add_interface(sk, G_DBUS_INTERFACE_SKELETON(v));
+ g_dbus_object_manager_server_export(os, sk);
+ g_dbus_object_manager_server_set_connection(os, conn);
+
+ return os;
+}
+
+static void
+set_id_list(Test *test, QTestState *s)
+{
+ if (!test->id_list) {
+ return;
+ }
+
+ g_assert(!qmp_rsp_is_err(qtest_qmp(s,
+ "{ 'execute': 'qom-set', 'arguments': "
+ "{ 'path': '/objects/dv', 'property': 'id-list', 'value': %s } }",
+ test->id_list)));
+}
+
+static gpointer
+dbus_vmstate_thread(gpointer data)
+{
+ GMainLoop *loop = data;
+
+ g_main_loop_run(loop);
+
+ return NULL;
+}
+
+static void
+test_dbus_vmstate(Test *test)
+{
+ g_autofree char *src_qemu_args = NULL;
+ g_autofree char *dst_qemu_args = NULL;
+ g_autoptr(GTestDBus) srcbus = NULL;
+ g_autoptr(GTestDBus) dstbus = NULL;
+ g_autoptr(GDBusConnection) srcconnA = NULL;
+ g_autoptr(GDBusConnection) srcconnB = NULL;
+ g_autoptr(GDBusConnection) dstconnA = NULL;
+ g_autoptr(GDBusConnection) dstconnB = NULL;
+ g_autoptr(GDBusObjectManagerServer) srcserverA = NULL;
+ g_autoptr(GDBusObjectManagerServer) srcserverB = NULL;
+ g_autoptr(GDBusObjectManagerServer) dstserverA = NULL;
+ g_autoptr(GDBusObjectManagerServer) dstserverB = NULL;
+ g_auto(GStrv) srcaddr = NULL;
+ g_auto(GStrv) dstaddr = NULL;
+ g_autoptr(GThread) thread = NULL;
+ g_autoptr(GMainLoop) loop = NULL;
+ g_autofree char *uri = NULL;
+ QTestState *src_qemu = NULL, *dst_qemu = NULL;
+ guint ownsrcA, ownsrcB, owndstA, owndstB;
+
+ uri = g_strdup_printf("unix:%s/migsocket", workdir);
+
+ loop = g_main_loop_new(NULL, FALSE);
+ test->loop = loop;
+
+ srcbus = g_test_dbus_new(G_TEST_DBUS_NONE);
+ g_test_dbus_up(srcbus);
+ srcconnA = get_connection(test, &ownsrcA);
+ srcserverA = get_server(srcconnA, &test->srcA, &idA);
+ srcconnB = get_connection(test, &ownsrcB);
+ srcserverB = get_server(srcconnB, &test->srcB, &idB);
+
+ /* remove ,guid=foo part */
+ srcaddr = g_strsplit(g_test_dbus_get_bus_address(srcbus), ",", 2);
+ src_qemu_args =
+ g_strdup_printf("-object dbus-vmstate,id=dv,addr=%s", srcaddr[0]);
+
+ dstbus = g_test_dbus_new(G_TEST_DBUS_NONE);
+ g_test_dbus_up(dstbus);
+ dstconnA = get_connection(test, &owndstA);
+ dstserverA = get_server(dstconnA, &test->dstA, &idA);
+ if (!test->without_dst_b) {
+ dstconnB = get_connection(test, &owndstB);
+ dstserverB = get_server(dstconnB, &test->dstB, &idB);
+ }
+
+ dstaddr = g_strsplit(g_test_dbus_get_bus_address(dstbus), ",", 2);
+ dst_qemu_args =
+ g_strdup_printf("-object dbus-vmstate,id=dv,addr=%s -incoming %s",
+ dstaddr[0], uri);
+
+ src_qemu = qtest_init(src_qemu_args);
+ dst_qemu = qtest_init(dst_qemu_args);
+ set_id_list(test, src_qemu);
+ set_id_list(test, dst_qemu);
+
+ thread = g_thread_new("dbus-vmstate-thread", dbus_vmstate_thread, loop);
+
+ migrate_qmp(src_qemu, uri, "{}");
+ test->src_qemu = src_qemu;
+ if (test->migrate_fail) {
+ wait_for_migration_fail(src_qemu, true);
+ qtest_set_expected_status(dst_qemu, 1);
+ } else {
+ wait_for_migration_complete(src_qemu);
+ }
+
+ qtest_quit(dst_qemu);
+ qtest_quit(src_qemu);
+ g_bus_unown_name(ownsrcA);
+ g_bus_unown_name(ownsrcB);
+ g_bus_unown_name(owndstA);
+ if (!test->without_dst_b) {
+ g_bus_unown_name(owndstB);
+ }
+
+ g_main_loop_quit(test->loop);
+}
+
+static void
+check_not_migrated(TestServer *s, TestServer *d)
+{
+ assert(!s->save_called);
+ assert(!s->load_called);
+ assert(!d->save_called);
+ assert(!d->load_called);
+}
+
+static void
+check_migrated(TestServer *s, TestServer *d)
+{
+ assert(s->save_called);
+ assert(!s->load_called);
+ assert(!d->save_called);
+ assert(d->load_called);
+}
+
+static void
+test_dbus_vmstate_without_list(void)
+{
+ Test test = { 0, };
+
+ test_dbus_vmstate(&test);
+
+ check_migrated(&test.srcA, &test.dstA);
+ check_migrated(&test.srcB, &test.dstB);
+}
+
+static void
+test_dbus_vmstate_with_list(void)
+{
+ Test test = { .id_list = "idA,idB" };
+
+ test_dbus_vmstate(&test);
+
+ check_migrated(&test.srcA, &test.dstA);
+ check_migrated(&test.srcB, &test.dstB);
+}
+
+static void
+test_dbus_vmstate_only_a(void)
+{
+ Test test = { .id_list = "idA" };
+
+ test_dbus_vmstate(&test);
+
+ check_migrated(&test.srcA, &test.dstA);
+ check_not_migrated(&test.srcB, &test.dstB);
+}
+
+static void
+test_dbus_vmstate_missing_src(void)
+{
+ Test test = { .id_list = "idA,idC", .migrate_fail = true };
+
+ /* run in subprocess to silence QEMU error reporting */
+ if (g_test_subprocess()) {
+ test_dbus_vmstate(&test);
+ check_not_migrated(&test.srcA, &test.dstA);
+ check_not_migrated(&test.srcB, &test.dstB);
+ return;
+ }
+
+ g_test_trap_subprocess(NULL, 0, 0);
+ g_test_trap_assert_passed();
+}
+
+static void
+test_dbus_vmstate_missing_dst(void)
+{
+ Test test = { .id_list = "idA,idB",
+ .without_dst_b = true,
+ .migrate_fail = true };
+
+ /* run in subprocess to silence QEMU error reporting */
+ if (g_test_subprocess()) {
+ test_dbus_vmstate(&test);
+ assert(test.srcA.save_called);
+ assert(test.srcB.save_called);
+ assert(!test.dstB.save_called);
+ return;
+ }
+
+ g_test_trap_subprocess(NULL, 0, 0);
+ g_test_trap_assert_passed();
+}
+
+int
+main(int argc, char **argv)
+{
+ GError *err = NULL;
+ g_autofree char *dbus_daemon = NULL;
+ int ret;
+
+ dbus_daemon = g_build_filename(G_STRINGIFY(SRCDIR),
+ "tests",
+ "dbus-vmstate-daemon.sh",
+ NULL);
+ g_setenv("G_TEST_DBUS_DAEMON", dbus_daemon, true);
+
+ g_test_init(&argc, &argv, NULL);
+
+ workdir = g_dir_make_tmp("dbus-vmstate-test-XXXXXX", &err);
+ if (!workdir) {
+ g_error("Unable to create temporary dir: %s\n", err->message);
+ exit(1);
+ }
+
+ g_setenv("DBUS_VMSTATE_TEST_TMPDIR", workdir, true);
+
+ qtest_add_func("/dbus-vmstate/without-list",
+ test_dbus_vmstate_without_list);
+ qtest_add_func("/dbus-vmstate/with-list",
+ test_dbus_vmstate_with_list);
+ qtest_add_func("/dbus-vmstate/only-a",
+ test_dbus_vmstate_only_a);
+ qtest_add_func("/dbus-vmstate/missing-src",
+ test_dbus_vmstate_missing_src);
+ qtest_add_func("/dbus-vmstate/missing-dst",
+ test_dbus_vmstate_missing_dst);
+
+ ret = g_test_run();
+
+ rmdir(workdir);
+ g_free(workdir);
+
+ return ret;
+}
diff --git a/tests/dbus-vmstate1.xml b/tests/dbus-vmstate1.xml
new file mode 100644
index 0000000..cc8563b
--- /dev/null
+++ b/tests/dbus-vmstate1.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+ <interface name="org.qemu.VMState1">
+ <property name="Id" type="s" access="read"/>
+ <method name="Load">
+ <arg type="ay" name="data" direction="in"/>
+ </method>
+ <method name="Save">
+ <arg type="ay" name="data" direction="out"/>
+ </method>
+ </interface>
+</node>
diff --git a/tests/docker/common.rc b/tests/docker/common.rc
index 512202b..02cd67a 100755
--- a/tests/docker/common.rc
+++ b/tests/docker/common.rc
@@ -53,12 +53,7 @@ check_qemu()
INVOCATION="$@"
fi
- if command -v gtester > /dev/null 2>&1 && \
- gtester --version > /dev/null 2>&1; then
- make $MAKEFLAGS $INVOCATION
- else
- echo "No working gtester, skipping make $INVOCATION"
- fi
+ make $MAKEFLAGS $INVOCATION
}
test_fail()
diff --git a/tests/docker/dockerfiles/centos7.docker b/tests/docker/dockerfiles/centos7.docker
index 9536370..562d65b 100644
--- a/tests/docker/dockerfiles/centos7.docker
+++ b/tests/docker/dockerfiles/centos7.docker
@@ -8,6 +8,7 @@ ENV PACKAGES \
bzip2-devel \
ccache \
csnappy-devel \
+ dbus-daemon \
flex \
gcc-c++ \
gcc \
diff --git a/tests/docker/dockerfiles/debian10.docker b/tests/docker/dockerfiles/debian10.docker
index dad498b..5de79ae 100644
--- a/tests/docker/dockerfiles/debian10.docker
+++ b/tests/docker/dockerfiles/debian10.docker
@@ -21,6 +21,7 @@ RUN apt update && \
build-essential \
ca-certificates \
clang \
+ dbus \
flex \
gettext \
git \
diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker
index 51d475e..987a3c1 100644
--- a/tests/docker/dockerfiles/fedora.docker
+++ b/tests/docker/dockerfiles/fedora.docker
@@ -8,6 +8,7 @@ ENV PACKAGES \
ccache \
clang \
cyrus-sasl-devel \
+ dbus-daemon \
device-mapper-multipath-devel \
findutils \
flex \
diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker
index 18f1100..4177f33 100644
--- a/tests/docker/dockerfiles/ubuntu.docker
+++ b/tests/docker/dockerfiles/ubuntu.docker
@@ -13,6 +13,7 @@ FROM ubuntu:19.04
ENV PACKAGES flex bison \
ccache \
clang \
+ dbus \
gcc \
gettext \
git \
diff --git a/tests/hd-geo-test.c b/tests/hd-geo-test.c
index 7e86c54..a2498005 100644
--- a/tests/hd-geo-test.c
+++ b/tests/hd-geo-test.c
@@ -34,8 +34,13 @@ static char *create_test_img(int secs)
fd = mkstemp(template);
g_assert(fd >= 0);
ret = ftruncate(fd, (off_t)secs * 512);
- g_assert(ret == 0);
close(fd);
+
+ if (ret) {
+ free(template);
+ template = NULL;
+ }
+
return template;
}
@@ -934,6 +939,10 @@ int main(int argc, char **argv)
for (i = 0; i < backend_last; i++) {
if (img_secs[i] >= 0) {
img_file_name[i] = create_test_img(img_secs[i]);
+ if (!img_file_name[i]) {
+ g_test_message("Could not create test images.");
+ goto test_add_done;
+ }
} else {
img_file_name[i] = NULL;
}
@@ -965,6 +974,7 @@ int main(int argc, char **argv)
"skipping hd-geo/override/* tests");
}
+test_add_done:
ret = g_test_run();
for (i = 0; i < backend_last; i++) {
diff --git a/tests/migration-helpers.c b/tests/migration-helpers.c
new file mode 100644
index 0000000..516093b
--- /dev/null
+++ b/tests/migration-helpers.c
@@ -0,0 +1,167 @@
+/*
+ * QTest migration helpers
+ *
+ * Copyright (c) 2016-2018 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 "qapi/qmp/qjson.h"
+
+#include "migration-helpers.h"
+
+bool got_stop;
+
+static void stop_cb(void *opaque, const char *name, QDict *data)
+{
+ if (!strcmp(name, "STOP")) {
+ got_stop = true;
+ }
+}
+
+/*
+ * Events can get in the way of responses we are actually waiting for.
+ */
+QDict *wait_command_fd(QTestState *who, int fd, const char *command, ...)
+{
+ va_list ap;
+
+ va_start(ap, command);
+ qtest_qmp_vsend_fds(who, &fd, 1, command, ap);
+ va_end(ap);
+
+ return qtest_qmp_receive_success(who, stop_cb, NULL);
+}
+
+/*
+ * Events can get in the way of responses we are actually waiting for.
+ */
+QDict *wait_command(QTestState *who, const char *command, ...)
+{
+ va_list ap;
+
+ va_start(ap, command);
+ qtest_qmp_vsend(who, command, ap);
+ va_end(ap);
+
+ return qtest_qmp_receive_success(who, stop_cb, NULL);
+}
+
+/*
+ * Send QMP command "migrate".
+ * Arguments are built from @fmt... (formatted like
+ * qobject_from_jsonf_nofail()) with "uri": @uri spliced in.
+ */
+void migrate_qmp(QTestState *who, const char *uri, const char *fmt, ...)
+{
+ va_list ap;
+ QDict *args, *rsp;
+
+ va_start(ap, fmt);
+ args = qdict_from_vjsonf_nofail(fmt, ap);
+ va_end(ap);
+
+ g_assert(!qdict_haskey(args, "uri"));
+ qdict_put_str(args, "uri", uri);
+
+ rsp = qtest_qmp(who, "{ 'execute': 'migrate', 'arguments': %p}", args);
+
+ g_assert(qdict_haskey(rsp, "return"));
+ qobject_unref(rsp);
+}
+
+/*
+ * Note: caller is responsible to free the returned object via
+ * qobject_unref() after use
+ */
+QDict *migrate_query(QTestState *who)
+{
+ return wait_command(who, "{ 'execute': 'query-migrate' }");
+}
+
+/*
+ * Note: caller is responsible to free the returned object via
+ * g_free() after use
+ */
+static gchar *migrate_query_status(QTestState *who)
+{
+ QDict *rsp_return = migrate_query(who);
+ gchar *status = g_strdup(qdict_get_str(rsp_return, "status"));
+
+ g_assert(status);
+ qobject_unref(rsp_return);
+
+ return status;
+}
+
+static bool check_migration_status(QTestState *who, const char *goal,
+ const char **ungoals)
+{
+ bool ready;
+ char *current_status;
+ const char **ungoal;
+
+ current_status = migrate_query_status(who);
+ ready = strcmp(current_status, goal) == 0;
+ if (!ungoals) {
+ g_assert_cmpstr(current_status, !=, "failed");
+ /*
+ * If looking for a state other than completed,
+ * completion of migration would cause the test to
+ * hang.
+ */
+ if (strcmp(goal, "completed") != 0) {
+ g_assert_cmpstr(current_status, !=, "completed");
+ }
+ } else {
+ for (ungoal = ungoals; *ungoal; ungoal++) {
+ g_assert_cmpstr(current_status, !=, *ungoal);
+ }
+ }
+ g_free(current_status);
+ return ready;
+}
+
+void wait_for_migration_status(QTestState *who,
+ const char *goal, const char **ungoals)
+{
+ while (!check_migration_status(who, goal, ungoals)) {
+ usleep(1000);
+ }
+}
+
+void wait_for_migration_complete(QTestState *who)
+{
+ wait_for_migration_status(who, "completed", NULL);
+}
+
+void wait_for_migration_fail(QTestState *from, bool allow_active)
+{
+ QDict *rsp_return;
+ char *status;
+ bool failed;
+
+ do {
+ status = migrate_query_status(from);
+ bool result = !strcmp(status, "setup") || !strcmp(status, "failed") ||
+ (allow_active && !strcmp(status, "active"));
+ if (!result) {
+ fprintf(stderr, "%s: unexpected status status=%s allow_active=%d\n",
+ __func__, status, allow_active);
+ }
+ g_assert(result);
+ failed = !strcmp(status, "failed");
+ g_free(status);
+ } while (!failed);
+
+ /* Is the machine currently running? */
+ rsp_return = wait_command(from, "{ 'execute': 'query-status' }");
+ g_assert(qdict_haskey(rsp_return, "running"));
+ g_assert(qdict_get_bool(rsp_return, "running"));
+ qobject_unref(rsp_return);
+}
diff --git a/tests/migration-helpers.h b/tests/migration-helpers.h
new file mode 100644
index 0000000..a11808b
--- /dev/null
+++ b/tests/migration-helpers.h
@@ -0,0 +1,37 @@
+/*
+ * QTest migration helpers
+ *
+ * Copyright (c) 2016-2018 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.
+ *
+ */
+#ifndef MIGRATION_HELPERS_H_
+#define MIGRATION_HELPERS_H_
+
+#include "libqtest.h"
+
+extern bool got_stop;
+
+GCC_FMT_ATTR(3, 4)
+QDict *wait_command_fd(QTestState *who, int fd, const char *command, ...);
+
+GCC_FMT_ATTR(2, 3)
+QDict *wait_command(QTestState *who, const char *command, ...);
+
+GCC_FMT_ATTR(3, 4)
+void migrate_qmp(QTestState *who, const char *uri, const char *fmt, ...);
+
+QDict *migrate_query(QTestState *who);
+
+void wait_for_migration_status(QTestState *who,
+ const char *goal, const char **ungoals);
+
+void wait_for_migration_complete(QTestState *who);
+
+void wait_for_migration_fail(QTestState *from, bool allow_active);
+
+#endif /* MIGRATION_HELPERS_H_ */
diff --git a/tests/migration-test.c b/tests/migration-test.c
index e56e6dc..53afec4 100644
--- a/tests/migration-test.c
+++ b/tests/migration-test.c
@@ -14,7 +14,6 @@
#include "libqtest.h"
#include "qapi/qmp/qdict.h"
-#include "qapi/qmp/qjson.h"
#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/range.h"
@@ -24,6 +23,7 @@
#include "qapi/qobject-input-visitor.h"
#include "qapi/qobject-output-visitor.h"
+#include "migration-helpers.h"
#include "migration/migration-test.h"
/* TODO actually test the results and get rid of this */
@@ -31,7 +31,6 @@
unsigned start_address;
unsigned end_address;
-bool got_stop;
static bool uffd_feature_thread_id;
#if defined(__linux__)
@@ -157,67 +156,6 @@ static void wait_for_serial(const char *side)
} while (true);
}
-static void stop_cb(void *opaque, const char *name, QDict *data)
-{
- if (!strcmp(name, "STOP")) {
- got_stop = true;
- }
-}
-
-/*
- * Events can get in the way of responses we are actually waiting for.
- */
-GCC_FMT_ATTR(3, 4)
-static QDict *wait_command_fd(QTestState *who, int fd, const char *command, ...)
-{
- va_list ap;
-
- va_start(ap, command);
- qtest_qmp_vsend_fds(who, &fd, 1, command, ap);
- va_end(ap);
-
- return qtest_qmp_receive_success(who, stop_cb, NULL);
-}
-
-/*
- * Events can get in the way of responses we are actually waiting for.
- */
-GCC_FMT_ATTR(2, 3)
-static QDict *wait_command(QTestState *who, const char *command, ...)
-{
- va_list ap;
-
- va_start(ap, command);
- qtest_qmp_vsend(who, command, ap);
- va_end(ap);
-
- return qtest_qmp_receive_success(who, stop_cb, NULL);
-}
-
-/*
- * Note: caller is responsible to free the returned object via
- * qobject_unref() after use
- */
-static QDict *migrate_query(QTestState *who)
-{
- return wait_command(who, "{ 'execute': 'query-migrate' }");
-}
-
-/*
- * Note: caller is responsible to free the returned object via
- * g_free() after use
- */
-static gchar *migrate_query_status(QTestState *who)
-{
- QDict *rsp_return = migrate_query(who);
- gchar *status = g_strdup(qdict_get_str(rsp_return, "status"));
-
- g_assert(status);
- qobject_unref(rsp_return);
-
- return status;
-}
-
/*
* It's tricky to use qemu's migration event capability with qtest,
* events suddenly appearing confuse the qmp()/hmp() responses.
@@ -265,48 +203,6 @@ static void read_blocktime(QTestState *who)
qobject_unref(rsp_return);
}
-static bool check_migration_status(QTestState *who, const char *goal,
- const char **ungoals)
-{
- bool ready;
- char *current_status;
- const char **ungoal;
-
- current_status = migrate_query_status(who);
- ready = strcmp(current_status, goal) == 0;
- if (!ungoals) {
- g_assert_cmpstr(current_status, !=, "failed");
- /*
- * If looking for a state other than completed,
- * completion of migration would cause the test to
- * hang.
- */
- if (strcmp(goal, "completed") != 0) {
- g_assert_cmpstr(current_status, !=, "completed");
- }
- } else {
- for (ungoal = ungoals; *ungoal; ungoal++) {
- g_assert_cmpstr(current_status, !=, *ungoal);
- }
- }
- g_free(current_status);
- return ready;
-}
-
-static void wait_for_migration_status(QTestState *who,
- const char *goal,
- const char **ungoals)
-{
- while (!check_migration_status(who, goal, ungoals)) {
- usleep(1000);
- }
-}
-
-static void wait_for_migration_complete(QTestState *who)
-{
- wait_for_migration_status(who, "completed", NULL);
-}
-
static void wait_for_migration_pass(QTestState *who)
{
uint64_t initial_pass = get_migration_pass(who);
@@ -506,30 +402,6 @@ static void migrate_set_capability(QTestState *who, const char *capability,
qobject_unref(rsp);
}
-/*
- * Send QMP command "migrate".
- * Arguments are built from @fmt... (formatted like
- * qobject_from_jsonf_nofail()) with "uri": @uri spliced in.
- */
-GCC_FMT_ATTR(3, 4)
-static void migrate(QTestState *who, const char *uri, const char *fmt, ...)
-{
- va_list ap;
- QDict *args, *rsp;
-
- va_start(ap, fmt);
- args = qdict_from_vjsonf_nofail(fmt, ap);
- va_end(ap);
-
- g_assert(!qdict_haskey(args, "uri"));
- qdict_put_str(args, "uri", uri);
-
- rsp = qtest_qmp(who, "{ 'execute': 'migrate', 'arguments': %p}", args);
-
- g_assert(qdict_haskey(rsp, "return"));
- qobject_unref(rsp);
-}
-
static void migrate_postcopy_start(QTestState *from, QTestState *to)
{
QDict *rsp;
@@ -800,7 +672,7 @@ static int migrate_postcopy_prepare(QTestState **from_ptr,
/* Wait for the first serial output from the source */
wait_for_serial("src_serial");
- migrate(from, uri, "{}");
+ migrate_qmp(from, uri, "{}");
g_free(uri);
wait_for_migration_pass(from);
@@ -891,7 +763,7 @@ static void test_postcopy_recovery(void)
wait_for_migration_status(from, "postcopy-paused",
(const char * []) { "failed", "active",
"completed", NULL });
- migrate(from, uri, "{'resume': true}");
+ migrate_qmp(from, uri, "{'resume': true}");
g_free(uri);
/* Restore the postcopy bandwidth to unlimited */
@@ -900,32 +772,6 @@ static void test_postcopy_recovery(void)
migrate_postcopy_complete(from, to);
}
-static void wait_for_migration_fail(QTestState *from, bool allow_active)
-{
- QDict *rsp_return;
- char *status;
- bool failed;
-
- do {
- status = migrate_query_status(from);
- bool result = !strcmp(status, "setup") || !strcmp(status, "failed") ||
- (allow_active && !strcmp(status, "active"));
- if (!result) {
- fprintf(stderr, "%s: unexpected status status=%s allow_active=%d\n",
- __func__, status, allow_active);
- }
- g_assert(result);
- failed = !strcmp(status, "failed");
- g_free(status);
- } while (!failed);
-
- /* Is the machine currently running? */
- rsp_return = wait_command(from, "{ 'execute': 'query-status' }");
- g_assert(qdict_haskey(rsp_return, "running"));
- g_assert(qdict_get_bool(rsp_return, "running"));
- qobject_unref(rsp_return);
-}
-
static void test_baddest(void)
{
MigrateStart *args = migrate_start_new();
@@ -936,7 +782,7 @@ static void test_baddest(void)
if (test_migrate_start(&from, &to, "tcp:0:0", args)) {
return;
}
- migrate(from, "tcp:0:0", "{}");
+ migrate_qmp(from, "tcp:0:0", "{}");
wait_for_migration_fail(from, false);
test_migrate_end(from, to, false);
}
@@ -963,7 +809,7 @@ static void test_precopy_unix(void)
/* Wait for the first serial output from the source */
wait_for_serial("src_serial");
- migrate(from, uri, "{}");
+ migrate_qmp(from, uri, "{}");
wait_for_migration_pass(from);
@@ -1000,7 +846,7 @@ static void test_ignore_shared(void)
/* Wait for the first serial output from the source */
wait_for_serial("src_serial");
- migrate(from, uri, "{}");
+ migrate_qmp(from, uri, "{}");
wait_for_migration_pass(from);
@@ -1047,7 +893,7 @@ static void test_xbzrle(const char *uri)
/* Wait for the first serial output from the source */
wait_for_serial("src_serial");
- migrate(from, uri, "{}");
+ migrate_qmp(from, uri, "{}");
wait_for_migration_pass(from);
@@ -1098,7 +944,7 @@ static void test_precopy_tcp(void)
uri = migrate_get_socket_address(to, "socket-address");
- migrate(from, uri, "{}");
+ migrate_qmp(from, uri, "{}");
wait_for_migration_pass(from);
@@ -1167,7 +1013,7 @@ static void test_migrate_fd_proto(void)
close(pair[1]);
/* Start migration to the 2nd socket*/
- migrate(from, "fd:fd-mig", "{}");
+ migrate_qmp(from, "fd:fd-mig", "{}");
wait_for_migration_pass(from);
@@ -1222,7 +1068,7 @@ static void do_test_validate_uuid(MigrateStart *args, bool should_fail)
/* Wait for the first serial output from the source */
wait_for_serial("src_serial");
- migrate(from, uri, "{}");
+ migrate_qmp(from, uri, "{}");
if (should_fail) {
qtest_set_expected_status(to, 1);
@@ -1316,7 +1162,7 @@ static void test_migrate_auto_converge(void)
/* Wait for the first serial output from the source */
wait_for_serial("src_serial");
- migrate(from, uri, "{}");
+ migrate_qmp(from, uri, "{}");
/* Wait for throttling begins */
percentage = 0;
diff --git a/tests/qemu-iotests/005 b/tests/qemu-iotests/005
index 5844276..b6d03ac 100755
--- a/tests/qemu-iotests/005
+++ b/tests/qemu-iotests/005
@@ -59,10 +59,7 @@ fi
# Sanity check: For raw, we require a file system that permits the creation
# of a HUGE (but very sparse) file. Check we can create it before continuing.
if [ "$IMGFMT" = "raw" ]; then
- if ! truncate --size=5T "$TEST_IMG"; then
- _notrun "file system on $TEST_DIR does not support large enough files"
- fi
- rm "$TEST_IMG"
+ _require_large_file 5T
fi
echo
diff --git a/tests/qemu-iotests/007 b/tests/qemu-iotests/007
index 7d3544b..160683a 100755
--- a/tests/qemu-iotests/007
+++ b/tests/qemu-iotests/007
@@ -41,8 +41,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto generic
# refcount_bits must be at least 4 so we can create ten internal snapshots
-# (1 bit supports none, 2 bits support two, 4 bits support 14)
-_unsupported_imgopts 'refcount_bits=\(1\|2\)[^0-9]'
+# (1 bit supports none, 2 bits support two, 4 bits support 14);
+# snapshot are generally impossible with external data files
+_unsupported_imgopts 'refcount_bits=\(1\|2\)[^0-9]' data_file
echo
echo "creating image"
diff --git a/tests/qemu-iotests/014 b/tests/qemu-iotests/014
index 2f728a1..e1221c0 100755
--- a/tests/qemu-iotests/014
+++ b/tests/qemu-iotests/014
@@ -43,6 +43,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
+# Compression and snapshots do not work with external data files
+_unsupported_imgopts data_file
TEST_OFFSETS="0 4294967296"
TEST_OPS="writev read write readv"
diff --git a/tests/qemu-iotests/015 b/tests/qemu-iotests/015
index eec5387..4d8effd 100755
--- a/tests/qemu-iotests/015
+++ b/tests/qemu-iotests/015
@@ -40,8 +40,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
# actually any format that supports snapshots
_supported_fmt qcow2
_supported_proto generic
-# Internal snapshots are (currently) impossible with refcount_bits=1
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
+# Internal snapshots are (currently) impossible with refcount_bits=1,
+# and generally impossible with external data files
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
echo
echo "creating image"
diff --git a/tests/qemu-iotests/019 b/tests/qemu-iotests/019
index b4f5234..813a84a 100755
--- a/tests/qemu-iotests/019
+++ b/tests/qemu-iotests/019
@@ -30,9 +30,9 @@ status=1 # failure is the default!
_cleanup()
{
- _cleanup_test_img
- rm -f "$TEST_IMG.base"
- rm -f "$TEST_IMG.orig"
+ _cleanup_test_img
+ _rm_test_img "$TEST_IMG.base"
+ _rm_test_img "$TEST_IMG.orig"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
index f41b92f..20f8f18 100755
--- a/tests/qemu-iotests/020
+++ b/tests/qemu-iotests/020
@@ -28,9 +28,9 @@ status=1 # failure is the default!
_cleanup()
{
- _cleanup_test_img
- rm -f "$TEST_IMG.base"
- rm -f "$TEST_IMG.orig"
+ _cleanup_test_img
+ _rm_test_img "$TEST_IMG.base"
+ _rm_test_img "$TEST_IMG.orig"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/024 b/tests/qemu-iotests/024
index 23298c6..e2e7662 100755
--- a/tests/qemu-iotests/024
+++ b/tests/qemu-iotests/024
@@ -29,12 +29,12 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_DIR/t.$IMGFMT.base_old"
- rm -f "$TEST_DIR/t.$IMGFMT.base_new"
+ _rm_test_img "$TEST_DIR/t.$IMGFMT.base_old"
+ _rm_test_img "$TEST_DIR/t.$IMGFMT.base_new"
- rm -f "$TEST_DIR/subdir/t.$IMGFMT"
- rm -f "$TEST_DIR/subdir/t.$IMGFMT.base_old"
- rm -f "$TEST_DIR/subdir/t.$IMGFMT.base_new"
+ _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT"
+ _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.base_old"
+ _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.base_new"
rmdir "$TEST_DIR/subdir" 2> /dev/null
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
index 3430029..a4aa747 100755
--- a/tests/qemu-iotests/026
+++ b/tests/qemu-iotests/026
@@ -49,7 +49,10 @@ _supported_cache_modes writethrough none
# 32 and 64 bits do not work either, however, due to different leaked cluster
# count on error.
# Thus, the only remaining option is refcount_bits=16.
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
+#
+# As for data_file, none of the refcount tests can work for it.
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' \
+ data_file
echo "Errors while writing 128 kB"
echo
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
index bba1ee5..e2556d8 100755
--- a/tests/qemu-iotests/028
+++ b/tests/qemu-iotests/028
@@ -32,7 +32,7 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_qemu
- rm -f "${TEST_IMG}.copy"
+ _rm_test_img "${TEST_IMG}.copy"
_cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
index 94c2713..2161a4b 100755
--- a/tests/qemu-iotests/029
+++ b/tests/qemu-iotests/029
@@ -28,7 +28,7 @@ status=1 # failure is the default!
_cleanup()
{
- rm -f $TEST_IMG.snap
+ _rm_test_img "$TEST_IMG.snap"
_cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -42,8 +42,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto generic
_unsupported_proto vxhs
-# Internal snapshots are (currently) impossible with refcount_bits=1
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
+# Internal snapshots are (currently) impossible with refcount_bits=1,
+# and generally impossible with external data files
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
offset_size=24
offset_l1_size=36
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index f3766f2..be35bde 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -943,7 +943,7 @@ class TestSetSpeed(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
result = self.vm.qmp('block-stream', device='drive0', speed=-1)
- self.assert_qmp(result, 'error/desc', "Invalid parameter 'speed'")
+ self.assert_qmp(result, 'error/desc', "Parameter 'speed' expects a non-negative value")
self.assert_no_active_block_jobs()
@@ -952,7 +952,7 @@ class TestSetSpeed(iotests.QMPTestCase):
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
- self.assert_qmp(result, 'error/desc', "Invalid parameter 'speed'")
+ self.assert_qmp(result, 'error/desc', "Parameter 'speed' expects a non-negative value")
self.cancel_and_wait(resume=True)
diff --git a/tests/qemu-iotests/031 b/tests/qemu-iotests/031
index a3c25ec..646ecd5 100755
--- a/tests/qemu-iotests/031
+++ b/tests/qemu-iotests/031
@@ -40,19 +40,22 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
# This tests qcow2-specific low-level functionality
_supported_fmt qcow2
_supported_proto file
+# We want to test compat=0.10, which does not support external data
+# files or refcount widths other than 16
+_unsupported_imgopts data_file 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
CLUSTER_SIZE=65536
# qcow2.py output depends on the exact options used, so override the command
# line here as an exception
-for IMGOPTS in "compat=0.10" "compat=1.1"; do
+for compat in "compat=0.10" "compat=1.1"; do
echo
- echo ===== Testing with -o $IMGOPTS =====
+ echo ===== Testing with -o $compat =====
echo
echo === Create image with unknown header extension ===
echo
- _make_test_img 64M
+ _make_test_img -o $compat 64M
$PYTHON qcow2.py "$TEST_IMG" add-header-ext 0x12345678 "This is a test header extension"
$PYTHON qcow2.py "$TEST_IMG" dump-header
_check_test_img
diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out
index 68a74d0..d535e40 100644
--- a/tests/qemu-iotests/031.out
+++ b/tests/qemu-iotests/031.out
@@ -18,9 +18,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x0
+incompatible_features []
+compatible_features []
+autoclear_features []
refcount_order 4
header_length 72
@@ -46,9 +46,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x0
+incompatible_features []
+compatible_features []
+autoclear_features []
refcount_order 4
header_length 72
@@ -74,9 +74,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x0
+incompatible_features []
+compatible_features []
+autoclear_features []
refcount_order 4
header_length 72
@@ -109,9 +109,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x0
+incompatible_features []
+compatible_features []
+autoclear_features []
refcount_order 4
header_length 104
@@ -142,9 +142,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x0
+incompatible_features []
+compatible_features []
+autoclear_features []
refcount_order 4
header_length 104
@@ -175,9 +175,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x0
+incompatible_features []
+compatible_features []
+autoclear_features []
refcount_order 4
header_length 104
diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036
index f06ff67..5125984 100755
--- a/tests/qemu-iotests/036
+++ b/tests/qemu-iotests/036
@@ -43,9 +43,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
# This tests qcow2-specific low-level functionality
_supported_fmt qcow2
_supported_proto file
-
-# Only qcow2v3 and later supports feature bits
-IMGOPTS="compat=1.1"
+# Only qcow2v3 and later supports feature bits;
+# qcow2.py does not support external data files
+_unsupported_imgopts 'compat=0.10' data_file
echo
echo === Image with unknown incompatible feature bit ===
@@ -55,7 +55,8 @@ $PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
# Without feature table
$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
-$PYTHON qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep features
+$PYTHON qcow2.py "$TEST_IMG" dump-header-exts
_img_info
# With feature table containing bit 63
@@ -103,14 +104,16 @@ echo === Create image with unknown autoclear feature bit ===
echo
_make_test_img 64M
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit autoclear 63
-$PYTHON qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep features
+$PYTHON qcow2.py "$TEST_IMG" dump-header-exts
echo
echo === Repair image ===
echo
_check_test_img -r all
-$PYTHON qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep features
+$PYTHON qcow2.py "$TEST_IMG" dump-header-exts
# success, all done
echo "*** done"
diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out
index e489b44..0b52b93 100644
--- a/tests/qemu-iotests/036.out
+++ b/tests/qemu-iotests/036.out
@@ -3,25 +3,9 @@ QA output created by 036
=== Image with unknown incompatible feature bit ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-magic 0x514649fb
-version 3
-backing_file_offset 0x0
-backing_file_size 0x0
-cluster_bits 16
-size 67108864
-crypt_method 0
-l1_size 1
-l1_table_offset 0x30000
-refcount_table_offset 0x10000
-refcount_table_clusters 1
-nb_snapshots 0
-snapshot_offset 0x0
-incompatible_features 0x8000000000000000
-compatible_features 0x0
-autoclear_features 0x0
-refcount_order 4
-header_length 104
-
+incompatible_features [63]
+compatible_features []
+autoclear_features []
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): Unknown incompatible feature: 8000000000000000
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): Test feature
@@ -37,25 +21,9 @@ qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): tes
=== Create image with unknown autoclear feature bit ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-magic 0x514649fb
-version 3
-backing_file_offset 0x0
-backing_file_size 0x0
-cluster_bits 16
-size 67108864
-crypt_method 0
-l1_size 1
-l1_table_offset 0x30000
-refcount_table_offset 0x10000
-refcount_table_clusters 1
-nb_snapshots 0
-snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x8000000000000000
-refcount_order 4
-header_length 104
-
+incompatible_features []
+compatible_features []
+autoclear_features [63]
Header extension:
magic 0x6803f857
length 192
@@ -65,25 +33,9 @@ data <binary>
=== Repair image ===
No errors were found on the image.
-magic 0x514649fb
-version 3
-backing_file_offset 0x0
-backing_file_size 0x0
-cluster_bits 16
-size 67108864
-crypt_method 0
-l1_size 1
-l1_table_offset 0x30000
-refcount_table_offset 0x10000
-refcount_table_clusters 1
-nb_snapshots 0
-snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x0
-refcount_order 4
-header_length 104
-
+incompatible_features []
+compatible_features []
+autoclear_features []
Header extension:
magic 0x6803f857
length 192
diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039
index 325da63..ddce48a 100755
--- a/tests/qemu-iotests/039
+++ b/tests/qemu-iotests/039
@@ -44,14 +44,16 @@ _supported_proto file
_supported_os Linux
_default_cache_mode writethrough
_supported_cache_modes writethrough
+# Some of these test cases expect no external data file so that all
+# clusters are part of the qcow2 image and refcounted
+_unsupported_imgopts data_file
size=128M
echo
echo "== Checking that image is clean on shutdown =="
-IMGOPTS="compat=1.1,lazy_refcounts=on"
-_make_test_img $size
+_make_test_img -o "compat=1.1,lazy_refcounts=on" $size
$QEMU_IO -c "write -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io
@@ -62,8 +64,7 @@ _check_test_img
echo
echo "== Creating a dirty image file =="
-IMGOPTS="compat=1.1,lazy_refcounts=on"
-_make_test_img $size
+_make_test_img -o "compat=1.1,lazy_refcounts=on" $size
_NO_VALGRIND \
$QEMU_IO -c "write -P 0x5a 0 512" \
@@ -98,8 +99,7 @@ $QEMU_IO -c "read -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io
echo
echo "== Opening a dirty image read/write should repair it =="
-IMGOPTS="compat=1.1,lazy_refcounts=on"
-_make_test_img $size
+_make_test_img -o "compat=1.1,lazy_refcounts=on" $size
_NO_VALGRIND \
$QEMU_IO -c "write -P 0x5a 0 512" \
@@ -117,8 +117,7 @@ $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
echo
echo "== Creating an image file with lazy_refcounts=off =="
-IMGOPTS="compat=1.1,lazy_refcounts=off"
-_make_test_img $size
+_make_test_img -o "compat=1.1,lazy_refcounts=off" $size
_NO_VALGRIND \
$QEMU_IO -c "write -P 0x5a 0 512" \
@@ -132,11 +131,9 @@ _check_test_img
echo
echo "== Committing to a backing file with lazy_refcounts=on =="
-IMGOPTS="compat=1.1,lazy_refcounts=on"
-TEST_IMG="$TEST_IMG".base _make_test_img $size
+TEST_IMG="$TEST_IMG".base _make_test_img -o "compat=1.1,lazy_refcounts=on" $size
-IMGOPTS="compat=1.1,lazy_refcounts=on,backing_file=$TEST_IMG.base"
-_make_test_img $size
+_make_test_img -o "compat=1.1,lazy_refcounts=on,backing_file=$TEST_IMG.base" $size
$QEMU_IO -c "write 0 512" "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG commit "$TEST_IMG"
@@ -151,8 +148,7 @@ TEST_IMG="$TEST_IMG".base _check_test_img
echo
echo "== Changing lazy_refcounts setting at runtime =="
-IMGOPTS="compat=1.1,lazy_refcounts=off"
-_make_test_img $size
+_make_test_img -o "compat=1.1,lazy_refcounts=off" $size
_NO_VALGRIND \
$QEMU_IO -c "reopen -o lazy-refcounts=on" \
@@ -164,8 +160,7 @@ $QEMU_IO -c "reopen -o lazy-refcounts=on" \
$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
_check_test_img
-IMGOPTS="compat=1.1,lazy_refcounts=on"
-_make_test_img $size
+_make_test_img -o "compat=1.1,lazy_refcounts=on" $size
_NO_VALGRIND \
$QEMU_IO -c "reopen -o lazy-refcounts=off" \
diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out
index 2e356d5..bdafa3a 100644
--- a/tests/qemu-iotests/039.out
+++ b/tests/qemu-iotests/039.out
@@ -4,7 +4,7 @@ QA output created by 039
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)
-incompatible_features 0x0
+incompatible_features []
No errors were found on the image.
== Creating a dirty image file ==
@@ -12,7 +12,7 @@ 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.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
-incompatible_features 0x1
+incompatible_features [0]
ERROR cluster 5 refcount=0 reference=1
ERROR OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=0
@@ -22,7 +22,7 @@ Data may be corrupted, or further writes to the image may corrupt it.
== Read-only access must still work ==
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-incompatible_features 0x1
+incompatible_features [0]
== Repairing the image file must succeed ==
ERROR cluster 5 refcount=0 reference=1
@@ -36,7 +36,7 @@ The following inconsistencies were found and repaired:
Double checking the fixed image now...
No errors were found on the image.
-incompatible_features 0x0
+incompatible_features []
== Data should still be accessible after repair ==
read 512/512 bytes at offset 0
@@ -47,21 +47,21 @@ 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.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
-incompatible_features 0x1
+incompatible_features [0]
ERROR cluster 5 refcount=0 reference=1
Rebuilding refcount structure
Repairing cluster 1 refcount=1 reference=0
Repairing cluster 2 refcount=1 reference=0
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-incompatible_features 0x0
+incompatible_features []
== Creating an image file with lazy_refcounts=off ==
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.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
-incompatible_features 0x0
+incompatible_features []
No errors were found on the image.
== Committing to a backing file with lazy_refcounts=on ==
@@ -70,8 +70,8 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Image committed.
-incompatible_features 0x0
-incompatible_features 0x0
+incompatible_features []
+incompatible_features []
No errors were found on the image.
No errors were found on the image.
@@ -80,7 +80,7 @@ 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.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
-incompatible_features 0x1
+incompatible_features [0]
ERROR cluster 5 refcount=0 reference=1
ERROR OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=0
@@ -90,6 +90,6 @@ 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.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
-incompatible_features 0x0
+incompatible_features []
No errors were found on the image.
*** done
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index 8568426..d7be30b 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -1121,6 +1121,50 @@ class TestOrphanedSource(iotests.QMPTestCase):
target='dest-ro')
self.assert_qmp(result, 'error/class', 'GenericError')
+ def test_failing_permission_in_complete(self):
+ self.assert_no_active_block_jobs()
+
+ # Unshare consistent-read on the target
+ # (The mirror job does not care)
+ result = self.vm.qmp('blockdev-add',
+ driver='blkdebug',
+ node_name='dest-perm',
+ image='dest',
+ unshare_child_perms=['consistent-read'])
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('blockdev-mirror', job_id='job', device='src',
+ sync='full', target='dest',
+ filter_node_name='mirror-filter')
+ self.assert_qmp(result, 'return', {})
+
+ # Require consistent-read on the source
+ # (We can only add this node once the job has started, or it
+ # will complain that it does not want to run on non-root nodes)
+ result = self.vm.qmp('blockdev-add',
+ driver='blkdebug',
+ node_name='src-perm',
+ image='src',
+ take_child_perms=['consistent-read'])
+ self.assert_qmp(result, 'return', {})
+
+ # While completing, mirror will attempt to replace src by
+ # dest, which must fail because src-perm requires
+ # consistent-read but dest-perm does not share it; thus
+ # aborting the job when it is supposed to complete
+ self.complete_and_wait('job',
+ completion_error='Operation not permitted')
+
+ # Assert that all of our nodes are still there (except for the
+ # mirror filter, which should be gone despite the failure)
+ nodes = self.vm.qmp('query-named-block-nodes')['return']
+ nodes = [node['node-name'] for node in nodes]
+
+ for expect in ('src', 'src-perm', 'dest', 'dest-perm'):
+ self.assertTrue(expect in nodes, '%s disappeared' % expect)
+ self.assertFalse('mirror-filter' in nodes,
+ 'Mirror filter node did not disappear')
+
if __name__ == '__main__':
iotests.main(supported_fmts=['qcow2', 'qed'],
supported_protocols=['file'])
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
index 2c448b4..f496be9 100644
--- a/tests/qemu-iotests/041.out
+++ b/tests/qemu-iotests/041.out
@@ -1,5 +1,5 @@
-..........................................................................................
+...........................................................................................
----------------------------------------------------------------------
-Ran 90 tests
+Ran 91 tests
OK
diff --git a/tests/qemu-iotests/043 b/tests/qemu-iotests/043
index 67cc7e7..b102e49 100755
--- a/tests/qemu-iotests/043
+++ b/tests/qemu-iotests/043
@@ -29,7 +29,9 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG".[123].base
+ for img in "$TEST_IMG".[123].base; do
+ _rm_test_img "$img"
+ done
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/046 b/tests/qemu-iotests/046
index 4e03ead..a066eec 100755
--- a/tests/qemu-iotests/046
+++ b/tests/qemu-iotests/046
@@ -38,6 +38,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
+# data_file does not support compressed clusters
+_unsupported_imgopts data_file
CLUSTER_SIZE=64k
size=128M
diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048
index bde408c..2af6b74 100755
--- a/tests/qemu-iotests/048
+++ b/tests/qemu-iotests/048
@@ -31,7 +31,7 @@ _cleanup()
{
echo "Cleanup"
_cleanup_test_img
- rm "${TEST_IMG_FILE2}"
+ _rm_test_img "${TEST_IMG_FILE2}"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -49,6 +49,8 @@ _compare()
_supported_fmt raw qcow2 qed luks
_supported_proto file
_supported_os Linux
+# Using 'cp' is incompatible with external data files
+_unsupported_imgopts data_file
# Remove once all tests are fixed to use TEST_IMG_FILE
# correctly and common.rc sets it unconditionally
diff --git a/tests/qemu-iotests/049 b/tests/qemu-iotests/049
index c100d30..051a1c7 100755
--- a/tests/qemu-iotests/049
+++ b/tests/qemu-iotests/049
@@ -78,6 +78,11 @@ for s in $sizes; do
test_qemu_img create -f $IMGFMT -o size=$s "$TEST_IMG"
done
+echo "== 4. Specify size twice (-o and traditional parameter) =="
+echo
+
+test_qemu_img create -f $IMGFMT -o size=10M "$TEST_IMG" 20M
+
echo "== Check correct interpretation of suffixes for cluster size =="
echo
sizes="1024 1024b 1k 1K 1M "
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
index 6b50540..affa55b 100644
--- a/tests/qemu-iotests/049.out
+++ b/tests/qemu-iotests/049.out
@@ -121,6 +121,11 @@ qemu-img: TEST_DIR/t.qcow2: Parameter 'size' expects a non-negative number below
Optional suffix k, M, G, T, P or E means kilo-, mega-, giga-, tera-, peta-
and exabytes, respectively.
+== 4. Specify size twice (-o and traditional parameter) ==
+
+qemu-img create -f qcow2 -o size=10M TEST_DIR/t.qcow2 20M
+qemu-img: TEST_DIR/t.qcow2: The image size must be specified only once
+
== Check correct interpretation of suffixes for cluster size ==
qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M
diff --git a/tests/qemu-iotests/050 b/tests/qemu-iotests/050
index 211fc00..cdc5356 100755
--- a/tests/qemu-iotests/050
+++ b/tests/qemu-iotests/050
@@ -29,8 +29,8 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG.old"
- rm -f "$TEST_IMG.new"
+ _rm_test_img "$TEST_IMG.old"
+ _rm_test_img "$TEST_IMG.new"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -41,10 +41,6 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2 qed
_supported_proto file
-if test "$IMGFMT" = qcow2 && test $IMGOPTS = ""; then
- IMGOPTS=compat=1.1
-fi
-
echo
echo "== Creating images =="
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
index 53bcdbc..034d3a3 100755
--- a/tests/qemu-iotests/051
+++ b/tests/qemu-iotests/051
@@ -39,8 +39,10 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
# A compat=0.10 image is created in this test which does not support anything
-# other than refcount_bits=16
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
+# other than refcount_bits=16;
+# it also will not support an external data file
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
+_require_drivers nbd
do_run_qemu()
{
@@ -157,7 +159,7 @@ echo
echo === With version 2 images enabling lazy refcounts must fail ===
echo
-_make_test_img -ocompat=0.10 $size
+_make_test_img -o compat=0.10 $size
run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=on
run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=off
diff --git a/tests/qemu-iotests/053 b/tests/qemu-iotests/053
index e82bb69..71d299c 100755
--- a/tests/qemu-iotests/053
+++ b/tests/qemu-iotests/053
@@ -28,8 +28,8 @@ status=1 # failure is the default!
_cleanup()
{
- rm -f "$TEST_IMG.orig"
- _cleanup_test_img
+ _rm_test_img "$TEST_IMG.orig"
+ _cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/058 b/tests/qemu-iotests/058
index 8c3212a..d5304bb 100755
--- a/tests/qemu-iotests/058
+++ b/tests/qemu-iotests/058
@@ -42,7 +42,7 @@ _cleanup()
{
nbd_server_stop
_cleanup_test_img
- rm -f "$converted_image"
+ _rm_test_img "$converted_image"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -56,8 +56,9 @@ _supported_fmt qcow2
_supported_proto file
_supported_os Linux
_require_command QEMU_NBD
-# Internal snapshots are (currently) impossible with refcount_bits=1
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
+# Internal snapshots are (currently) impossible with refcount_bits=1,
+# and generally impossible with external data files
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
nbd_snapshot_img="nbd:unix:$nbd_unix_socket"
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
index 10bfbae..5438025 100755
--- a/tests/qemu-iotests/059
+++ b/tests/qemu-iotests/059
@@ -29,7 +29,7 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG.qcow2"
+ IMGFMT=qcow2 _rm_test_img "$TEST_IMG.qcow2"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -70,18 +70,18 @@ poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00"
echo
echo "=== Testing monolithicFlat creation and opening ==="
-IMGOPTS="subformat=monolithicFlat" _make_test_img 2G
+_make_test_img -o "subformat=monolithicFlat" 2G
_img_info
_cleanup_test_img
echo
echo "=== Testing monolithicFlat with zeroed_grain ==="
-IMGOPTS="subformat=monolithicFlat,zeroed_grain=on" _make_test_img 2G
+_make_test_img -o "subformat=monolithicFlat,zeroed_grain=on" 2G
_cleanup_test_img
echo
echo "=== Testing big twoGbMaxExtentFlat ==="
-IMGOPTS="subformat=twoGbMaxExtentFlat" _make_test_img 1000G
+_make_test_img -o "subformat=twoGbMaxExtentFlat" 1000G
$QEMU_IMG info $TEST_IMG | _filter_testdir | sed -e 's/cid: [0-9]*/cid: XXXXXXXX/'
_cleanup_test_img
@@ -101,13 +101,13 @@ _img_info
echo
echo "=== Testing truncated sparse ==="
-IMGOPTS="subformat=monolithicSparse" _make_test_img 100G
+_make_test_img -o "subformat=monolithicSparse" 100G
truncate -s 10M $TEST_IMG
_img_info
echo
echo "=== Converting to streamOptimized from image with small cluster size==="
-TEST_IMG="$TEST_IMG.qcow2" IMGFMT=qcow2 IMGOPTS="cluster_size=4096" _make_test_img 1G
+TEST_IMG="$TEST_IMG.qcow2" IMGFMT=qcow2 _make_test_img -o "cluster_size=4096" 1G
$QEMU_IO -f qcow2 -c "write -P 0xa 0 512" "$TEST_IMG.qcow2" | _filter_qemu_io
$QEMU_IO -f qcow2 -c "write -P 0xb 10240 512" "$TEST_IMG.qcow2" | _filter_qemu_io
$QEMU_IMG convert -f qcow2 -O vmdk -o subformat=streamOptimized "$TEST_IMG.qcow2" "$TEST_IMG" 2>&1
@@ -117,7 +117,7 @@ echo "=== Testing monolithicFlat with internally generated JSON file name ==="
echo '--- blkdebug ---'
# Should work, because bdrv_dirname() works fine with blkdebug
-IMGOPTS="subformat=monolithicFlat" _make_test_img 64M
+_make_test_img -o "subformat=monolithicFlat" 64M
$QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.image.filename=$TEST_IMG,file.inject-error.0.event=read_aio" \
-c info \
2>&1 \
@@ -126,7 +126,7 @@ _cleanup_test_img
echo '--- quorum ---'
# Should not work, because bdrv_dirname() does not work with quorum
-IMGOPTS="subformat=monolithicFlat" _make_test_img 64M
+_make_test_img -o "subformat=monolithicFlat" 64M
cp "$TEST_IMG" "$TEST_IMG.orig"
filename="json:{
@@ -161,7 +161,7 @@ _cleanup_test_img
echo
echo "=== Testing 4TB monolithicFlat creation and IO ==="
-IMGOPTS="subformat=monolithicFlat" _make_test_img 4T
+_make_test_img -o "subformat=monolithicFlat" 4T
_img_info
$QEMU_IO -c "write -P 0xa 900G 512" "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c "read -v 900G 1024" "$TEST_IMG" | _filter_qemu_io
@@ -170,7 +170,7 @@ _cleanup_test_img
echo
echo "=== Testing qemu-img map on extents ==="
for fmt in monolithicSparse twoGbMaxExtentSparse; do
- IMGOPTS="subformat=$fmt" _make_test_img 31G
+ _make_test_img -o "subformat=$fmt" 31G
$QEMU_IO -c "write 65024 1k" "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c "write 2147483136 1k" "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c "write 5G 1k" "$TEST_IMG" | _filter_qemu_io
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
index b91d832..043f129 100755
--- a/tests/qemu-iotests/060
+++ b/tests/qemu-iotests/060
@@ -44,10 +44,17 @@ _filter_io_error()
. ./common.rc
. ./common.filter
-# This tests qocw2-specific low-level functionality
+# This tests qcow2-specific low-level functionality
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
+# These tests only work for compat=1.1 images without an external
+# data file with refcount_bits=16
+_unsupported_imgopts 'compat=0.10' data_file \
+ 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
+
+# The repair process will create a large file - so check for availability first
+_require_large_file 64G
rt_offset=65536 # 0x10000 (XXX: just an assumption)
rb_offset=131072 # 0x20000 (XXX: just an assumption)
@@ -55,8 +62,6 @@ l1_offset=196608 # 0x30000 (XXX: just an assumption)
l2_offset=262144 # 0x40000 (XXX: just an assumption)
l2_offset_after_snapshot=524288 # 0x80000 (XXX: just an assumption)
-IMGOPTS="compat=1.1"
-
OPEN_RW="open -o overlap-check=all $TEST_IMG"
# Overlap checks are done before write operations only, therefore opening an
# image read-only makes the overlap-check option irrelevant
@@ -158,7 +163,7 @@ $QEMU_IO -c 'write 0k 64k' "$BACKING_IMG" | _filter_qemu_io
# compat=0.10 is required in order to make the following discard actually
# unallocate the sector rather than make it a zero sector - we want COW, after
# all.
-IMGOPTS='compat=0.10' _make_test_img -b "$BACKING_IMG" 1G
+_make_test_img -o 'compat=0.10' -b "$BACKING_IMG" 1G
# Write two clusters, the second one enforces creation of an L2 table after
# the first data cluster.
$QEMU_IO -c 'write 0k 64k' -c 'write 512M 64k' "$TEST_IMG" | _filter_qemu_io
@@ -398,7 +403,7 @@ echo
echo "=== Discarding a non-covered in-bounds refblock ==="
echo
-IMGOPTS='refcount_bits=1' _make_test_img 64M
+_make_test_img -o 'refcount_bits=1' 64M
# Pretend there's a refblock somewhere where there is no refblock to
# cover it (but the covering refblock has a valid index in the
@@ -422,7 +427,7 @@ echo
echo "=== Discarding a refblock covered by an unaligned refblock ==="
echo
-IMGOPTS='refcount_bits=1' _make_test_img 64M
+_make_test_img -o 'refcount_bits=1' 64M
# Same as above
poke_file "$TEST_IMG" "$(($rt_offset+8))" "\x00\x00\x00\x10\x00\x00\x00\x00"
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
index 0f6b065..d27692a 100644
--- a/tests/qemu-iotests/060.out
+++ b/tests/qemu-iotests/060.out
@@ -7,10 +7,10 @@ ERROR cluster 3 refcount=1 reference=3
1 errors were found on the image.
Data may be corrupted, or further writes to the image may corrupt it.
-incompatible_features 0x0
+incompatible_features []
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with active L1 table); further corruption events will be suppressed
write failed: Input/output error
-incompatible_features 0x2
+incompatible_features [1]
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 64 MiB (67108864 bytes)
@@ -33,10 +33,10 @@ ERROR cluster 2 refcount=1 reference=2
2 errors were found on the image.
Data may be corrupted, or further writes to the image may corrupt it.
-incompatible_features 0x0
+incompatible_features []
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with refcount block); further corruption events will be suppressed
write failed: Input/output error
-incompatible_features 0x2
+incompatible_features [1]
ERROR refcount block 0 refcount=2
ERROR cluster 2 refcount=1 reference=2
Rebuilding refcount structure
@@ -49,10 +49,10 @@ The following inconsistencies were found and repaired:
Double checking the fixed image now...
No errors were found on the image.
-incompatible_features 0x0
+incompatible_features []
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-incompatible_features 0x0
+incompatible_features []
=== Testing cluster data reference into inactive L2 table ===
@@ -69,10 +69,10 @@ Data may be corrupted, or further writes to the image may corrupt it.
1 leaked clusters were found on the image.
This means waste of disk space, but no harm to data.
-incompatible_features 0x0
+incompatible_features []
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with inactive L2 table); further corruption events will be suppressed
write failed: Input/output error
-incompatible_features 0x2
+incompatible_features [1]
ERROR cluster 4 refcount=1 reference=2
Leaked cluster 9 refcount=1 reference=0
Repairing cluster 4 refcount=1 reference=2
@@ -85,10 +85,10 @@ The following inconsistencies were found and repaired:
Double checking the fixed image now...
No errors were found on the image.
-incompatible_features 0x0
+incompatible_features []
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-incompatible_features 0x0
+incompatible_features []
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
index 4eac5b8..36b0404 100755
--- a/tests/qemu-iotests/061
+++ b/tests/qemu-iotests/061
@@ -29,7 +29,7 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f $TEST_IMG.data
+ _rm_test_img "$TEST_IMG.data"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -37,15 +37,20 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
-# This tests qocw2-specific low-level functionality
+# This tests qcow2-specific low-level functionality
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
+# Conversion between different compat versions can only really work
+# with refcount_bits=16;
+# we have explicit tests for data_file here, but the whole test does
+# not work with it
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
echo
echo "=== Testing version downgrade with zero expansion ==="
echo
-IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
+_make_test_img -o "compat=1.1,lazy_refcounts=on" 64M
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
$PYTHON qcow2.py "$TEST_IMG" dump-header
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
@@ -56,7 +61,7 @@ _check_test_img
echo
echo "=== Testing version downgrade with zero expansion and 4K cache entries ==="
echo
-IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
+_make_test_img -o "compat=1.1,lazy_refcounts=on" 64M
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c "write -z 32M 128k" "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c map "$TEST_IMG" | _filter_qemu_io
@@ -72,7 +77,7 @@ _check_test_img
echo
echo "=== Testing dirty version downgrade ==="
echo
-IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
+_make_test_img -o "compat=1.1,lazy_refcounts=on" 64M
_NO_VALGRIND \
$QEMU_IO -c "write -P 0x2a 0 128k" -c flush \
-c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 | _filter_qemu_io
@@ -85,7 +90,7 @@ _check_test_img
echo
echo "=== Testing version downgrade with unknown compat/autoclear flags ==="
echo
-IMGOPTS="compat=1.1" _make_test_img 64M
+_make_test_img -o "compat=1.1" 64M
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit compatible 42
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit autoclear 42
$PYTHON qcow2.py "$TEST_IMG" dump-header
@@ -96,7 +101,7 @@ _check_test_img
echo
echo "=== Testing version upgrade and resize ==="
echo
-IMGOPTS="compat=0.10" _make_test_img 64M
+_make_test_img -o "compat=0.10" 64M
$QEMU_IO -c "write -P 0x2a 42M 64k" "$TEST_IMG" | _filter_qemu_io
$PYTHON qcow2.py "$TEST_IMG" dump-header
$QEMU_IMG amend -o "compat=1.1,lazy_refcounts=on,size=128M" "$TEST_IMG"
@@ -107,7 +112,7 @@ _check_test_img
echo
echo "=== Testing dirty lazy_refcounts=off ==="
echo
-IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
+_make_test_img -o "compat=1.1,lazy_refcounts=on" 64M
_NO_VALGRIND \
$QEMU_IO -c "write -P 0x2a 0 128k" -c flush \
-c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 | _filter_qemu_io
@@ -120,8 +125,8 @@ _check_test_img
echo
echo "=== Testing backing file ==="
echo
-IMGOPTS="compat=1.1" _make_test_img 64M
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
+_make_test_img -o "compat=1.1" 64M
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
$QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG amend -o "backing_file=$TEST_IMG.base,backing_fmt=qcow2" "$TEST_IMG"
@@ -131,7 +136,7 @@ _check_test_img
echo
echo "=== Testing invalid configurations ==="
echo
-IMGOPTS="compat=0.10" _make_test_img 64M
+_make_test_img -o "compat=0.10" 64M
$QEMU_IMG amend -o "lazy_refcounts=on" "$TEST_IMG"
$QEMU_IMG amend -o "compat=1.1" "$TEST_IMG" # actually valid
$QEMU_IMG amend -o "compat=0.10,lazy_refcounts=on" "$TEST_IMG"
@@ -144,7 +149,7 @@ $QEMU_IMG amend -o "preallocation=on" "$TEST_IMG"
echo
echo "=== Testing correct handling of unset value ==="
echo
-IMGOPTS="compat=1.1,cluster_size=1k" _make_test_img 64M
+_make_test_img -o "compat=1.1,cluster_size=1k" 64M
echo "Should work:"
$QEMU_IMG amend -o "lazy_refcounts=on" "$TEST_IMG"
echo "Should not work:" # Just to know which of these tests actually fails
@@ -153,7 +158,7 @@ $QEMU_IMG amend -o "cluster_size=64k" "$TEST_IMG"
echo
echo "=== Testing zero expansion on inactive clusters ==="
echo
-IMGOPTS="compat=1.1" _make_test_img 64M
+_make_test_img -o "compat=1.1" 64M
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG snapshot -c foo "$TEST_IMG"
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG" | _filter_qemu_io
@@ -167,7 +172,7 @@ $QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
echo
echo "=== Testing zero expansion on shared L2 table ==="
echo
-IMGOPTS="compat=1.1" _make_test_img 64M
+_make_test_img -o "compat=1.1" 64M
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG snapshot -c foo "$TEST_IMG"
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
@@ -180,9 +185,9 @@ $QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
echo
echo "=== Testing zero expansion on backed image ==="
echo
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 64M
$QEMU_IO -c "read -P 0x2a 0 128k" -c "write -z 0 64k" "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
_check_test_img
@@ -191,9 +196,9 @@ $QEMU_IO -c "read -P 0 0 64k" -c "read -P 0x2a 64k 64k" "$TEST_IMG" | _filter_qe
echo
echo "=== Testing zero expansion on backed inactive clusters ==="
echo
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 64M
$QEMU_IO -c "write -z 0 64k" "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG snapshot -c foo "$TEST_IMG"
$QEMU_IO -c "write -P 0x42 0 128k" "$TEST_IMG" | _filter_qemu_io
@@ -207,9 +212,9 @@ $QEMU_IO -c "read -P 0 0 64k" -c "read -P 0x2a 64k 64k" "$TEST_IMG" | _filter_qe
echo
echo "=== Testing zero expansion on backed image with shared L2 table ==="
echo
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 64M
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG snapshot -c foo "$TEST_IMG"
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
@@ -222,7 +227,7 @@ $QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
echo
echo "=== Testing preallocated zero expansion on full image ==="
echo
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG" _make_test_img 64M
+TEST_IMG="$TEST_IMG" _make_test_img -o "compat=1.1" 64M
$QEMU_IO -c "write -P 0x2a 0 64M" "$TEST_IMG" -c "write -z 0 64M" | _filter_qemu_io
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
_check_test_img
@@ -231,8 +236,8 @@ $QEMU_IO -c "read -P 0 0 64M" "$TEST_IMG" | _filter_qemu_io
echo
echo "=== Testing progress report without snapshot ==="
echo
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 4G
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 4G
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 4G
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 4G
$QEMU_IO -c "write -z 0 64k" \
-c "write -z 1G 64k" \
-c "write -z 2G 64k" \
@@ -243,8 +248,8 @@ _check_test_img
echo
echo "=== Testing progress report with snapshot ==="
echo
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 4G
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 4G
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 4G
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 4G
$QEMU_IO -c "write -z 0 64k" \
-c "write -z 1G 64k" \
-c "write -z 2G 64k" \
@@ -256,7 +261,7 @@ _check_test_img
echo
echo "=== Testing version downgrade with external data file ==="
echo
-IMGOPTS="compat=1.1,data_file=$TEST_IMG.data" _make_test_img 64M
+_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
_img_info --format-specific
_check_test_img
@@ -264,11 +269,11 @@ _check_test_img
echo
echo "=== Try changing the external data file ==="
echo
-IMGOPTS="compat=1.1" _make_test_img 64M
+_make_test_img -o "compat=1.1" 64M
$QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
echo
-IMGOPTS="compat=1.1,data_file=$TEST_IMG.data" _make_test_img 64M
+_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M
$QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
_img_info --format-specific
TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
@@ -281,7 +286,7 @@ TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info -
echo
echo "=== Clearing and setting data-file-raw ==="
echo
-IMGOPTS="compat=1.1,data_file=$TEST_IMG.data,data_file_raw=on" _make_test_img 64M
+_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data,data_file_raw=on" 64M
$QEMU_IMG amend -o "data_file_raw=on" "$TEST_IMG"
_img_info --format-specific
_check_test_img
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
index d6a7c2a..8b3091a 100644
--- a/tests/qemu-iotests/061.out
+++ b/tests/qemu-iotests/061.out
@@ -18,9 +18,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x1
-autoclear_features 0x0
+incompatible_features []
+compatible_features [0]
+autoclear_features []
refcount_order 4
header_length 104
@@ -42,9 +42,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x0
+incompatible_features []
+compatible_features []
+autoclear_features []
refcount_order 4
header_length 72
@@ -76,9 +76,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x1
-autoclear_features 0x0
+incompatible_features []
+compatible_features [0]
+autoclear_features []
refcount_order 4
header_length 104
@@ -100,9 +100,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x0
+incompatible_features []
+compatible_features []
+autoclear_features []
refcount_order 4
header_length 72
@@ -132,9 +132,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x1
-compatible_features 0x1
-autoclear_features 0x0
+incompatible_features [0]
+compatible_features [0]
+autoclear_features []
refcount_order 4
header_length 104
@@ -161,9 +161,9 @@ refcount_table_offset 0x80000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x0
+incompatible_features []
+compatible_features []
+autoclear_features []
refcount_order 4
header_length 72
@@ -187,9 +187,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x40000000000
-autoclear_features 0x40000000000
+incompatible_features []
+compatible_features [42]
+autoclear_features [42]
refcount_order 4
header_length 104
@@ -211,9 +211,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x0
+incompatible_features []
+compatible_features []
+autoclear_features []
refcount_order 4
header_length 72
@@ -237,9 +237,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x0
+incompatible_features []
+compatible_features []
+autoclear_features []
refcount_order 4
header_length 72
@@ -256,9 +256,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x1
-autoclear_features 0x0
+incompatible_features []
+compatible_features [0]
+autoclear_features []
refcount_order 4
header_length 104
@@ -290,9 +290,9 @@ refcount_table_offset 0x10000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x1
-compatible_features 0x1
-autoclear_features 0x0
+incompatible_features [0]
+compatible_features [0]
+autoclear_features []
refcount_order 4
header_length 104
@@ -319,9 +319,9 @@ refcount_table_offset 0x80000
refcount_table_clusters 1
nb_snapshots 0
snapshot_offset 0x0
-incompatible_features 0x0
-compatible_features 0x0
-autoclear_features 0x0
+incompatible_features []
+compatible_features []
+autoclear_features []
refcount_order 4
header_length 104
diff --git a/tests/qemu-iotests/062 b/tests/qemu-iotests/062
index d5f818f..f26b88d 100755
--- a/tests/qemu-iotests/062
+++ b/tests/qemu-iotests/062
@@ -37,11 +37,12 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
-# This tests qocw2-specific low-level functionality
+# This tests qcow2-specific low-level functionality
_supported_fmt qcow2
_supported_proto generic
+# We need zero clusters and snapshots
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file
-IMGOPTS="compat=1.1"
IMG_SIZE=64M
echo
diff --git a/tests/qemu-iotests/063 b/tests/qemu-iotests/063
index 7cf0427..c750b38 100755
--- a/tests/qemu-iotests/063
+++ b/tests/qemu-iotests/063
@@ -29,8 +29,10 @@ status=1 # failure is the default!
_cleanup()
{
- _cleanup_test_img
- rm -f "$TEST_IMG.orig" "$TEST_IMG.raw1" "$TEST_IMG.raw2"
+ _cleanup_test_img
+ for img in "$TEST_IMG".{orig,raw1,raw2,target}; do
+ _rm_test_img "$img"
+ done
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -49,15 +51,13 @@ _unsupported_imgopts "subformat=monolithicFlat" \
_make_test_img 4M
echo "== Testing conversion with -n fails with no target file =="
-# check .orig file does not exist
-rm -f "$TEST_IMG.orig"
if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG.orig" >/dev/null 2>&1; then
exit 1
fi
echo "== Testing conversion with -n succeeds with a target file =="
-rm -f "$TEST_IMG.orig"
-cp "$TEST_IMG" "$TEST_IMG.orig"
+_rm_test_img "$TEST_IMG.orig"
+TEST_IMG="$TEST_IMG.orig" _make_test_img 4M
if ! $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG.orig" ; then
exit 1
fi
@@ -83,10 +83,8 @@ fi
_check_test_img
echo "== Testing conversion to a smaller file fails =="
-rm -f "$TEST_IMG.orig"
-mv "$TEST_IMG" "$TEST_IMG.orig"
-_make_test_img 2M
-if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG.orig" "$TEST_IMG" >/dev/null 2>&1; then
+TEST_IMG="$TEST_IMG.target" _make_test_img 2M
+if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG.target" >/dev/null 2>&1; then
exit 1
fi
diff --git a/tests/qemu-iotests/063.out b/tests/qemu-iotests/063.out
index 7b691b2..890b719 100644
--- a/tests/qemu-iotests/063.out
+++ b/tests/qemu-iotests/063.out
@@ -2,11 +2,12 @@ QA output created by 063
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304
== Testing conversion with -n fails with no target file ==
== Testing conversion with -n succeeds with a target file ==
+Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=4194304
== Testing conversion to raw is the same after conversion with -n ==
== Testing conversion back to original format ==
No errors were found on the image.
== Testing conversion to a smaller file fails ==
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2097152
+Formatting 'TEST_DIR/t.IMGFMT.target', fmt=IMGFMT size=2097152
== Regression testing for copy offloading bug ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
Formatting 'TEST_DIR/t.IMGFMT.target', fmt=IMGFMT size=1048576
diff --git a/tests/qemu-iotests/066 b/tests/qemu-iotests/066
index 28f8c98..a4ac613 100755
--- a/tests/qemu-iotests/066
+++ b/tests/qemu-iotests/066
@@ -36,12 +36,15 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
-# This tests qocw2-specific low-level functionality
+# This tests qcow2-specific low-level functionality
_supported_fmt qcow2
_supported_proto generic
+# We need zero clusters and snapshots
+# (TODO: Consider splitting the snapshot part into a separate test
+# file, so this one runs with refcount_bits=1 and data_file)
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file
# Intentionally create an unaligned image
-IMGOPTS="compat=1.1"
IMG_SIZE=$((64 * 1024 * 1024 + 512))
echo
diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067
index 926c79b..a63be9c 100755
--- a/tests/qemu-iotests/067
+++ b/tests/qemu-iotests/067
@@ -32,8 +32,10 @@ status=1 # failure is the default!
_supported_fmt qcow2
_supported_proto file
-# Because anything other than 16 would change the output of query-block
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
+# Because anything other than 16 would change the output of query-block,
+# and external data files would change the output of
+# query-named-block-nodes
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
do_run_qemu()
{
diff --git a/tests/qemu-iotests/068 b/tests/qemu-iotests/068
index 22f5ca3..ccd1a9f 100755
--- a/tests/qemu-iotests/068
+++ b/tests/qemu-iotests/068
@@ -36,11 +36,13 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
-# This tests qocw2-specific low-level functionality
+# This tests qcow2-specific low-level functionality
_supported_fmt qcow2
_supported_proto generic
+# Internal snapshots are (currently) impossible with refcount_bits=1,
+# and generally impossible with external data files
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file
-IMGOPTS="compat=1.1"
IMG_SIZE=128K
case "$QEMU_DEFAULT_MACHINE" in
diff --git a/tests/qemu-iotests/069 b/tests/qemu-iotests/069
index 3974714..b997b12 100755
--- a/tests/qemu-iotests/069
+++ b/tests/qemu-iotests/069
@@ -47,7 +47,7 @@ echo "=== Creating an image with a backing file and deleting that file ==="
echo
TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE
_make_test_img -b "$TEST_IMG.base" $IMG_SIZE
-rm -f "$TEST_IMG.base"
+_rm_test_img "$TEST_IMG.base"
# Just open the image and close it right again (this should print an error message)
$QEMU_IO -c quit "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071
index fab5266..88faebc 100755
--- a/tests/qemu-iotests/071
+++ b/tests/qemu-iotests/071
@@ -39,6 +39,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
_require_drivers blkdebug blkverify
+# blkdebug can only inject errors on bs->file, not on the data_file,
+# so thie test does not work with external data files
+_unsupported_imgopts data_file
do_run_qemu()
{
@@ -58,7 +61,7 @@ echo
echo "=== Testing blkverify through filename ==="
echo
-TEST_IMG="$TEST_IMG.base" IMGOPTS="" IMGFMT="raw" _make_test_img $IMG_SIZE |\
+TEST_IMG="$TEST_IMG.base" IMGFMT="raw" _make_test_img --no-opts $IMG_SIZE |\
_filter_imgfmt
_make_test_img $IMG_SIZE
$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \
@@ -73,7 +76,7 @@ echo
echo "=== Testing blkverify through file blockref ==="
echo
-TEST_IMG="$TEST_IMG.base" IMGOPTS="" IMGFMT="raw" _make_test_img $IMG_SIZE |\
+TEST_IMG="$TEST_IMG.base" IMGFMT="raw" _make_test_img --no-opts $IMG_SIZE |\
_filter_imgfmt
_make_test_img $IMG_SIZE
$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base,file.test.driver=$IMGFMT,file.test.file.filename=$TEST_IMG" \
diff --git a/tests/qemu-iotests/073 b/tests/qemu-iotests/073
index e684b1b..23a1bdf 100755
--- a/tests/qemu-iotests/073
+++ b/tests/qemu-iotests/073
@@ -39,6 +39,10 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto generic
_unsupported_proto vxhs
+# External data files do not support compressed clusters
+# (TODO: Consider writing a version for external data files that does
+# not test compressed clusters)
+_unsupported_imgopts data_file
CLUSTER_SIZE=64k
size=128M
diff --git a/tests/qemu-iotests/074 b/tests/qemu-iotests/074
index bb4ad1c..db03edf 100755
--- a/tests/qemu-iotests/074
+++ b/tests/qemu-iotests/074
@@ -31,7 +31,7 @@ _cleanup()
{
echo "Cleanup"
_cleanup_test_img
- rm "${TEST_IMG2}"
+ _rm_test_img "${TEST_IMG2}"
rm -f "$TEST_DIR/blkdebug.conf"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -50,6 +50,8 @@ _compare()
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
+# blkdebug can only inject errors on bs->file
+_unsupported_imgopts data_file
# Setup test basic parameters
TEST_IMG2=$TEST_IMG.2
diff --git a/tests/qemu-iotests/079 b/tests/qemu-iotests/079
index 81f0c21..3642b51 100755
--- a/tests/qemu-iotests/079
+++ b/tests/qemu-iotests/079
@@ -39,13 +39,15 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file nfs
+# Some containers (e.g. non-x86 on Travis) do not allow large files
+_require_large_file 4G
+
echo "=== Check option preallocation and cluster_size ==="
echo
cluster_sizes="16384 32768 65536 131072 262144 524288 1048576 2097152 4194304"
for s in $cluster_sizes; do
- IMGOPTS=$(_optstr_add "$IMGOPTS" "preallocation=metadata,cluster_size=$s") \
- _make_test_img 4G
+ _make_test_img -o "preallocation=metadata,cluster_size=$s" 4G
done
# success, all done
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
index 4bcb502..a3d13c4 100755
--- a/tests/qemu-iotests/080
+++ b/tests/qemu-iotests/080
@@ -28,7 +28,7 @@ status=1 # failure is the default!
_cleanup()
{
- rm -f $TEST_IMG.snap
+ _rm_test_img "$TEST_IMG.snap"
_cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -40,9 +40,10 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
-# - Internal snapshots are (currently) impossible with refcount_bits=1
+# - Internal snapshots are (currently) impossible with refcount_bits=1,
+# and generally impossible with external data files
# - This is generally a test for compat=1.1 images
-_unsupported_imgopts 'refcount_bits=1[^0-9]' 'compat=0.10'
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file 'compat=0.10'
header_size=104
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
index 85acdf7..537d40d 100755
--- a/tests/qemu-iotests/081
+++ b/tests/qemu-iotests/081
@@ -28,9 +28,9 @@ status=1 # failure is the default!
_cleanup()
{
- rm -rf $TEST_DIR/1.raw
- rm -rf $TEST_DIR/2.raw
- rm -rf $TEST_DIR/3.raw
+ _rm_test_img "$TEST_DIR/1.raw"
+ _rm_test_img "$TEST_DIR/2.raw"
+ _rm_test_img "$TEST_DIR/3.raw"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/085 b/tests/qemu-iotests/085
index d40fdab..46981db 100755
--- a/tests/qemu-iotests/085
+++ b/tests/qemu-iotests/085
@@ -41,10 +41,13 @@ _cleanup()
_cleanup_qemu
for i in $(seq 1 ${SNAPSHOTS})
do
- rm -f "${TEST_DIR}/${i}-${snapshot_virt0}"
- rm -f "${TEST_DIR}/${i}-${snapshot_virt1}"
+ _rm_test_img "${TEST_DIR}/${i}-${snapshot_virt0}"
+ _rm_test_img "${TEST_DIR}/${i}-${snapshot_virt1}"
+ done
+ for img in "${TEST_IMG}".{1,2,base}
+ do
+ _rm_test_img "$img"
done
- rm -f "${TEST_IMG}" "${TEST_IMG}.1" "${TEST_IMG}.2" "${TEST_IMG}.base"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -102,8 +105,7 @@ add_snapshot_image()
{
base_image="${TEST_DIR}/$((${1}-1))-${snapshot_virt0}"
snapshot_file="${TEST_DIR}/${1}-${snapshot_virt0}"
- _make_test_img -u -b "${base_image}" "$size"
- mv "${TEST_IMG}" "${snapshot_file}"
+ TEST_IMG=$snapshot_file _make_test_img -u -b "${base_image}" "$size"
do_blockdev_add "$1" "'backing': null, " "${snapshot_file}"
}
@@ -119,10 +121,8 @@ blockdev_snapshot()
size=128M
-_make_test_img $size
-mv "${TEST_IMG}" "${TEST_IMG}.1"
-_make_test_img $size
-mv "${TEST_IMG}" "${TEST_IMG}.2"
+TEST_IMG="$TEST_IMG.1" _make_test_img $size
+TEST_IMG="$TEST_IMG.2" _make_test_img $size
echo
echo === Running QEMU ===
diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out
index bb50227..d94ad22 100644
--- a/tests/qemu-iotests/085.out
+++ b/tests/qemu-iotests/085.out
@@ -1,6 +1,6 @@
QA output created by 085
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
+Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=134217728
+Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728
=== Running QEMU ===
@@ -68,12 +68,12 @@ Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_fil
=== Create a couple of snapshots using blockdev-snapshot ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/10-snapshot-v0.IMGFMT
+Formatting 'TEST_DIR/11-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/10-snapshot-v0.IMGFMT
{ 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_11', 'backing': null, 'file': { 'driver': 'file', 'filename': 'TEST_DIR/11-snapshot-v0.IMGFMT', 'node-name': 'file_11' } } }
{"return": {}}
{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_11' } }
{"return": {}}
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/11-snapshot-v0.IMGFMT
+Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/11-snapshot-v0.IMGFMT
{ 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_12', 'backing': null, 'file': { 'driver': 'file', 'filename': 'TEST_DIR/12-snapshot-v0.IMGFMT', 'node-name': 'file_12' } } }
{"return": {}}
{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_12' } }
diff --git a/tests/qemu-iotests/088 b/tests/qemu-iotests/088
index b44edd0..ef11633 100755
--- a/tests/qemu-iotests/088
+++ b/tests/qemu-iotests/088
@@ -28,7 +28,7 @@ status=1 # failure is the default!
_cleanup()
{
- rm -f $TEST_IMG.snap
+ _rm_test_img "$TEST_IMG.snap"
_cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/090 b/tests/qemu-iotests/090
index 9f8cfbb..1246e4f 100755
--- a/tests/qemu-iotests/090
+++ b/tests/qemu-iotests/090
@@ -38,6 +38,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file nfs
+# External data files do not support compressed clusters
+_unsupported_imgopts data_file
IMG_SIZE=128K
diff --git a/tests/qemu-iotests/091 b/tests/qemu-iotests/091
index f4b4465..0874fa8 100755
--- a/tests/qemu-iotests/091
+++ b/tests/qemu-iotests/091
@@ -101,7 +101,7 @@ echo "Check image pattern"
${QEMU_IO} -c "read -P 0x22 0 4M" "${TEST_IMG}" | _filter_testdir | _filter_qemu_io
echo "Running 'qemu-img check -r all \$TEST_IMG'"
-"${QEMU_IMG}" check -r all "${TEST_IMG}" 2>&1 | _filter_testdir | _filter_qemu
+_check_test_img -r all
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/091.out b/tests/qemu-iotests/091.out
index 5017f8c..5ec7b00 100644
--- a/tests/qemu-iotests/091.out
+++ b/tests/qemu-iotests/091.out
@@ -23,6 +23,4 @@ read 4194304/4194304 bytes at offset 0
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Running 'qemu-img check -r all $TEST_IMG'
No errors were found on the image.
-80/16384 = 0.49% allocated, 0.00% fragmented, 0.00% compressed clusters
-Image end offset: 5570560
*** done
diff --git a/tests/qemu-iotests/092 b/tests/qemu-iotests/092
index e2e0726..40ec62b 100755
--- a/tests/qemu-iotests/092
+++ b/tests/qemu-iotests/092
@@ -28,7 +28,7 @@ status=1 # failure is the default!
_cleanup()
{
- rm -f $TEST_IMG.snap
+ _rm_test_img "$TEST_IMG.snap"
_cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/094 b/tests/qemu-iotests/094
index 9343e09..2d3e100 100755
--- a/tests/qemu-iotests/094
+++ b/tests/qemu-iotests/094
@@ -30,7 +30,7 @@ _cleanup()
{
_cleanup_qemu
_cleanup_test_img
- rm -f "$TEST_DIR/source.$IMGFMT"
+ _rm_test_img "$TEST_DIR/source.$IMGFMT"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -45,7 +45,7 @@ _supported_proto nbd
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
_make_test_img 64M
-$QEMU_IMG create -f $IMGFMT "$TEST_DIR/source.$IMGFMT" 64M | _filter_img_create
+TEST_IMG_FILE="$TEST_DIR/source.$IMGFMT" IMGPROTO=file _make_test_img 64M
_launch_qemu -drive if=none,id=src,file="$TEST_DIR/source.$IMGFMT",format=raw \
-nodefaults
diff --git a/tests/qemu-iotests/095 b/tests/qemu-iotests/095
index 58fe174..155ae86 100755
--- a/tests/qemu-iotests/095
+++ b/tests/qemu-iotests/095
@@ -32,8 +32,9 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_qemu
- rm -f "${TEST_IMG}.base" "${TEST_IMG}.snp1"
- _cleanup_test_img
+ _rm_test_img "${TEST_IMG}.base"
+ _rm_test_img "${TEST_IMG}.snp1"
+ _cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/098 b/tests/qemu-iotests/098
index 1c1d1c4..1e29d96 100755
--- a/tests/qemu-iotests/098
+++ b/tests/qemu-iotests/098
@@ -40,8 +40,10 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
-
-IMGOPTS="compat=1.1"
+# The code path we want to test here only works for compat=1.1 images;
+# blkdebug can only inject errors on bs->file, so external data files
+# do not work with this test
+_unsupported_imgopts 'compat=0.10' data_file
for event in l1_update empty_image_prepare reftable_update refblock_alloc; do
diff --git a/tests/qemu-iotests/099 b/tests/qemu-iotests/099
index c3cf667..65e8e92 100755
--- a/tests/qemu-iotests/099
+++ b/tests/qemu-iotests/099
@@ -29,7 +29,10 @@ status=1 # failure is the default!
_cleanup()
{
- _cleanup_test_img
+ _cleanup_test_img
+ _rm_test_img "$TEST_IMG.compare"
+ rm -f "$TEST_DIR/blkdebug.conf"
+
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -43,8 +46,9 @@ _supported_fmt qcow qcow2 qed vdi vhdx vmdk vpc
_supported_proto file
_supported_os Linux
_require_drivers blkdebug blkverify
+# data_file would change the json:{} filenames
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \
- "subformat=twoGbMaxExtentSparse"
+ "subformat=twoGbMaxExtentSparse" data_file
do_run_qemu()
{
@@ -121,8 +125,6 @@ echo
test_qemu "file.driver=blkdebug,file.image.filename=$TEST_IMG"
-rm -f "$TEST_IMG.compare" "$TEST_DIR/blkdebug.conf"
-
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/103 b/tests/qemu-iotests/103
index 554b9de..8c1ebe0 100755
--- a/tests/qemu-iotests/103
+++ b/tests/qemu-iotests/103
@@ -38,8 +38,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file nfs
-# Internal snapshots are (currently) impossible with refcount_bits=1
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
+# Internal snapshots are (currently) impossible with refcount_bits=1,
+# and generally impossible with external data files
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
IMG_SIZE=64K
diff --git a/tests/qemu-iotests/106 b/tests/qemu-iotests/106
index ac47eaa..b5d1ec4 100755
--- a/tests/qemu-iotests/106
+++ b/tests/qemu-iotests/106
@@ -51,7 +51,7 @@ for create_mode in off falloc full; do
echo
echo "--- create_mode=$create_mode growth_mode=$growth_mode ---"
- IMGOPTS="preallocation=$create_mode" _make_test_img ${CREATION_SIZE}K
+ _make_test_img -o "preallocation=$create_mode" ${CREATION_SIZE}K
$QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K
expected_size=0
diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
index 9c08172..5f7076f 100755
--- a/tests/qemu-iotests/108
+++ b/tests/qemu-iotests/108
@@ -37,12 +37,14 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
-# This tests qocw2-specific low-level functionality
+# This tests qcow2-specific low-level functionality
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
-# This test directly modifies a refblock so it relies on refcount_bits being 16
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
+# This test directly modifies a refblock so it relies on refcount_bits being 16;
+# and the low-level modification it performs are not tuned for external data
+# files
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
echo
echo '=== Repairing an image without any refcount table ==='
@@ -65,7 +67,7 @@ echo
echo '=== Repairing unreferenced data cluster in new refblock area ==='
echo
-IMGOPTS='cluster_size=512' _make_test_img 64M
+_make_test_img -o 'cluster_size=512' 64M
# Allocate the first 128 kB in the image (first refblock)
$QEMU_IO -c 'write 0 0x1b200' "$TEST_IMG" | _filter_qemu_io
# should be 131072 == 0x20000
diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
index 9897ceb..ba638db 100755
--- a/tests/qemu-iotests/109
+++ b/tests/qemu-iotests/109
@@ -29,8 +29,8 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_qemu
- rm -f $TEST_IMG.src
- _cleanup_test_img
+ _rm_test_img "$TEST_IMG.src"
+ _cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
index 2ef516b..139c02c 100755
--- a/tests/qemu-iotests/110
+++ b/tests/qemu-iotests/110
@@ -28,8 +28,8 @@ status=1 # failure is the default!
_cleanup()
{
- _cleanup_test_img
- rm -f "$TEST_IMG.copy"
+ _cleanup_test_img
+ _rm_test_img "$TEST_IMG.copy"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -67,6 +67,7 @@ echo
# Across blkdebug without a config file, you cannot reconstruct filenames, so
# qemu is incapable of knowing the directory of the top image from the filename
# alone. However, using bdrv_dirname(), it should still work.
+# (Filter out the json:{} filename so this test works with external data files)
TEST_IMG="json:{
'driver': '$IMGFMT',
'file': {
@@ -82,7 +83,8 @@ TEST_IMG="json:{
}
]
}
-}" _img_info | _filter_img_info | grep -v 'backing file format'
+}" _img_info | _filter_img_info | grep -v 'backing file format' \
+ | _filter_json_filename
echo
echo '=== Backing name is always relative to the backed image ==='
@@ -114,7 +116,8 @@ TEST_IMG="json:{
}
]
}
-}" _img_info | _filter_img_info | grep -v 'backing file format'
+}" _img_info | _filter_img_info | grep -v 'backing file format' \
+ | _filter_json_filename
# success, all done
diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out
index f60b263..f835553 100644
--- a/tests/qemu-iotests/110.out
+++ b/tests/qemu-iotests/110.out
@@ -11,7 +11,7 @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
=== Non-reconstructable filename ===
-image: json:{"driver": "IMGFMT", "file": {"set-state.0.event": "read_aio", "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "set-state.0.new_state": 42}}
+image: json:{ /* filtered */ }
file format: IMGFMT
virtual size: 64 MiB (67108864 bytes)
backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
@@ -22,7 +22,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.b
=== Nodes without a common directory ===
-image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.copy"}], "driver": "quorum", "vote-threshold": 1}}
+image: json:{ /* filtered */ }
file format: IMGFMT
virtual size: 64 MiB (67108864 bytes)
backing file: t.IMGFMT.base (cannot determine actual path)
diff --git a/tests/qemu-iotests/111 b/tests/qemu-iotests/111
index 490a5bb..3b43d1b 100755
--- a/tests/qemu-iotests/111
+++ b/tests/qemu-iotests/111
@@ -41,8 +41,7 @@ _supported_fmt qed qcow qcow2 vmdk
_supported_proto file
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
-$QEMU_IMG create -f $IMGFMT -b "$TEST_IMG.inexistent" "$TEST_IMG" 2>&1 \
- | _filter_testdir | _filter_imgfmt
+_make_test_img -b "$TEST_IMG.inexistent"
# success, all done
echo '*** done'
diff --git a/tests/qemu-iotests/112 b/tests/qemu-iotests/112
index 706c10b..20ff5c2 100755
--- a/tests/qemu-iotests/112
+++ b/tests/qemu-iotests/112
@@ -40,8 +40,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
# This test will set refcount_bits on its own which would conflict with the
-# manual setting; compat will be overridden as well
-_unsupported_imgopts refcount_bits 'compat=0.10'
+# manual setting; compat will be overridden as well;
+# and external data files do not work well with our refcount testing
+_unsupported_imgopts refcount_bits 'compat=0.10' data_file
print_refcount_bits()
{
@@ -53,20 +54,20 @@ echo '=== refcount_bits limits ==='
echo
# Must be positive (non-zero)
-IMGOPTS="$IMGOPTS,refcount_bits=0" _make_test_img 64M
+_make_test_img -o "refcount_bits=0" 64M
# Must be positive (non-negative)
-IMGOPTS="$IMGOPTS,refcount_bits=-1" _make_test_img 64M
+_make_test_img -o "refcount_bits=-1" 64M
# May not exceed 64
-IMGOPTS="$IMGOPTS,refcount_bits=128" _make_test_img 64M
+_make_test_img -o "refcount_bits=128" 64M
# Must be a power of two
-IMGOPTS="$IMGOPTS,refcount_bits=42" _make_test_img 64M
+_make_test_img -o "refcount_bits=42" 64M
# 1 is the minimum
-IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
+_make_test_img -o "refcount_bits=1" 64M
print_refcount_bits
# 64 is the maximum
-IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M
+_make_test_img -o "refcount_bits=64" 64M
print_refcount_bits
# 16 is the default
@@ -78,19 +79,19 @@ echo '=== refcount_bits and compat=0.10 ==='
echo
# Should work
-IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=16" _make_test_img 64M
+_make_test_img -o "compat=0.10,refcount_bits=16" 64M
print_refcount_bits
# Should not work
-IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=1" _make_test_img 64M
-IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=64" _make_test_img 64M
+_make_test_img -o "compat=0.10,refcount_bits=1" 64M
+_make_test_img -o "compat=0.10,refcount_bits=64" 64M
echo
echo '=== Snapshot limit on refcount_bits=1 ==='
echo
-IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
+_make_test_img -o "refcount_bits=1" 64M
print_refcount_bits
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
@@ -106,7 +107,7 @@ echo
echo '=== Snapshot limit on refcount_bits=2 ==='
echo
-IMGOPTS="$IMGOPTS,refcount_bits=2" _make_test_img 64M
+_make_test_img -o "refcount_bits=2" 64M
print_refcount_bits
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
@@ -124,7 +125,7 @@ echo
echo '=== Compressed clusters with refcount_bits=1 ==='
echo
-IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
+_make_test_img -o "refcount_bits=1" 64M
print_refcount_bits
# Both should fit into a single host cluster; instead of failing to increase the
@@ -140,7 +141,7 @@ echo
echo '=== MSb set in 64 bit refcount ==='
echo
-IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M
+_make_test_img -o "refcount_bits=64" 64M
print_refcount_bits
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
@@ -158,7 +159,7 @@ echo
echo '=== Snapshot on maximum 64 bit refcount value ==='
echo
-IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M
+_make_test_img -o "refcount_bits=64" 64M
print_refcount_bits
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
@@ -239,7 +240,7 @@ echo
echo '=== Testing too many references for check ==='
echo
-IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
+_make_test_img -o "refcount_bits=1" 64M
print_refcount_bits
# This cluster should be created at 0x50000
@@ -262,7 +263,7 @@ echo
echo '=== Multiple walks necessary during amend ==='
echo
-IMGOPTS="$IMGOPTS,refcount_bits=1,cluster_size=512" _make_test_img 64k
+_make_test_img -o "refcount_bits=1,cluster_size=512" 64k
# Cluster 0 is the image header, clusters 1 to 4 are used by the L1 table, a
# single L2 table, the reftable and a single refblock. This creates 58 data
diff --git a/tests/qemu-iotests/114 b/tests/qemu-iotests/114
index f90a744..26104ff 100755
--- a/tests/qemu-iotests/114
+++ b/tests/qemu-iotests/114
@@ -39,6 +39,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto generic
_unsupported_proto vxhs
+# qcow2.py does not work too well with external data files
+_unsupported_imgopts data_file
TEST_IMG="$TEST_IMG.base" _make_test_img 64M
diff --git a/tests/qemu-iotests/115 b/tests/qemu-iotests/115
index 9ed3cb6..d254b18 100755
--- a/tests/qemu-iotests/115
+++ b/tests/qemu-iotests/115
@@ -64,8 +64,7 @@ echo
# least 256 MB. We can achieve that by using preallocation=metadata for an image
# which has a guest disk size of 256 MB.
-IMGOPTS="$IMGOPTS,refcount_bits=64,cluster_size=512,preallocation=metadata" \
- _make_test_img 256M
+_make_test_img -o "refcount_bits=64,cluster_size=512,preallocation=metadata" 256M
# We know for sure that the L1 and refcount tables do not overlap with any other
# structure because the metadata overlap checks would have caught that case.
diff --git a/tests/qemu-iotests/121 b/tests/qemu-iotests/121
index 90a0424..90ea0db 100755
--- a/tests/qemu-iotests/121
+++ b/tests/qemu-iotests/121
@@ -39,6 +39,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
+# Refcount structures are used much differently with external data
+# files
+_unsupported_imgopts data_file
echo
echo '=== New refcount structures may not conflict with existing structures ==='
@@ -50,7 +53,7 @@ echo
# Preallocation speeds up the write operation, but preallocating everything will
# destroy the purpose of the write; so preallocate one KB less than what would
# cause a reftable growth...
-IMGOPTS='preallocation=metadata,cluster_size=1k' _make_test_img 64512K
+_make_test_img -o 'preallocation=metadata,cluster_size=1k' 64512K
# ...and make the image the desired size afterwards.
$QEMU_IMG resize "$TEST_IMG" 65M
@@ -73,7 +76,7 @@ echo
echo '--- Test 2 ---'
echo
-IMGOPTS='preallocation=metadata,cluster_size=1k' _make_test_img 64513K
+_make_test_img -o 'preallocation=metadata,cluster_size=1k' 64513K
# This results in an L1 table growth which in turn results in some clusters at
# the start of the image becoming free
$QEMU_IMG resize "$TEST_IMG" 65M
@@ -96,7 +99,7 @@ echo
echo '=== Allocating a new refcount block must not leave holes in the image ==='
echo
-IMGOPTS='cluster_size=512,refcount_bits=16' _make_test_img 1M
+_make_test_img -o 'cluster_size=512,refcount_bits=16' 1M
# This results in an image with 256 used clusters: the qcow2 header,
# the refcount table, one refcount block, the L1 table, four L2 tables
diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122
index 059011e..dfa3509 100755
--- a/tests/qemu-iotests/122
+++ b/tests/qemu-iotests/122
@@ -28,8 +28,10 @@ status=1 # failure is the default!
_cleanup()
{
- rm -f "$TEST_IMG".[123]
- _cleanup_test_img
+ for img in "$TEST_IMG".[123]; do
+ _rm_test_img "$img"
+ done
+ _cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/123 b/tests/qemu-iotests/123
index d33950e..01b771c 100755
--- a/tests/qemu-iotests/123
+++ b/tests/qemu-iotests/123
@@ -29,7 +29,7 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "$SRC_IMG"
+ _rm_test_img "$SRC_IMG"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -44,7 +44,7 @@ _supported_os Linux
SRC_IMG="$TEST_DIR/source.$IMGFMT"
_make_test_img 1M
-$QEMU_IMG create -f $IMGFMT "$SRC_IMG" 1M | _filter_img_create
+TEST_IMG_FILE=$SRC_IMG IMGPROTO=file _make_test_img 1M
$QEMU_IO -c 'write -P 42 0 1M' "$SRC_IMG" | _filter_qemu_io
diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125
index 4e31aa4..d510984 100755
--- a/tests/qemu-iotests/125
+++ b/tests/qemu-iotests/125
@@ -114,7 +114,7 @@ for GROWTH_SIZE in 16 48 80; do
for growth_mode in off metadata falloc full; do
echo "--- cluster_size=$cluster_size growth_size=$GROWTH_SIZE create_mode=$create_mode growth_mode=$growth_mode ---"
- IMGOPTS="preallocation=$create_mode,cluster_size=$cluster_size" _make_test_img ${CREATION_SIZE}
+ _make_test_img -o "preallocation=$create_mode,cluster_size=$cluster_size" ${CREATION_SIZE}
$QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K
host_size_0=$(get_image_size_on_host)
diff --git a/tests/qemu-iotests/137 b/tests/qemu-iotests/137
index 089821d..7ae8689 100755
--- a/tests/qemu-iotests/137
+++ b/tests/qemu-iotests/137
@@ -117,7 +117,7 @@ $QEMU_IO \
-c "reopen -o cache-clean-interval=-1" \
"$TEST_IMG" | _filter_qemu_io
-IMGOPTS="cluster_size=256k" _make_test_img 32P
+_make_test_img -o "cluster_size=256k" 32P
$QEMU_IO \
-c "reopen -o l2-cache-entry-size=512,l2-cache-size=1T" \
"$TEST_IMG" | _filter_qemu_io
@@ -138,14 +138,21 @@ $QEMU_IO \
"$TEST_IMG" 2>&1 | _filter_qemu_io
# The dirty bit must not be set
-$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+# (Filter the external data file bit)
+if $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features \
+ | grep -q '\<0\>'
+then
+ echo 'ERROR: Dirty bit set'
+else
+ echo 'OK: Dirty bit not set'
+fi
# Similarly we can test whether corruption detection has been enabled:
-# Create L1/L2, overwrite first entry in refcount block, allocate something.
+# Create L1, overwrite refcounts, force allocation of L2 by writing
+# data.
# Disabling the checks should fail, so the corruption must be detected.
_make_test_img 64M
-$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io
-poke_file "$TEST_IMG" "$((0x20000))" "\x00\x00"
+poke_file "$TEST_IMG" "$((0x20000))" "\x00\x00\x00\x00\x00\x00\x00\x00"
$QEMU_IO \
-c "reopen -o overlap-check=none,lazy-refcounts=42" \
-c "write 64k 64k" \
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
index 1c6569e..86377c8 100644
--- a/tests/qemu-iotests/137.out
+++ b/tests/qemu-iotests/137.out
@@ -36,11 +36,9 @@ qemu-io: Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
-incompatible_features 0x0
+OK: Dirty bit not set
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-wrote 65536/65536 bytes at offset 0
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qemu-io: Parameter 'lazy-refcounts' expects 'on' or 'off'
-qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with qcow2_header); further corruption events will be suppressed
+qcow2: Marking image as corrupt: Preventing invalid allocation of L2 table at offset 0; further corruption events will be suppressed
write failed: Input/output error
*** done
diff --git a/tests/qemu-iotests/138 b/tests/qemu-iotests/138
index 6a73137..54b0104 100755
--- a/tests/qemu-iotests/138
+++ b/tests/qemu-iotests/138
@@ -36,17 +36,19 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
-# This tests qocw2-specific low-level functionality
+# This tests qcow2-specific low-level functionality
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
+# With an external data file, data clusters are not refcounted
+# (and so qemu-img check does not check their refcount)
+_unsupported_imgopts data_file
echo
echo '=== Check on an image with a multiple of 2^32 clusters ==='
echo
-IMGOPTS=$(_optstr_add "$IMGOPTS" "cluster_size=512") \
- _make_test_img 512
+_make_test_img -o "cluster_size=512" 512
# Allocate L2 table
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
index 8c2ae79..5192d25 100755
--- a/tests/qemu-iotests/141
+++ b/tests/qemu-iotests/141
@@ -30,7 +30,9 @@ _cleanup()
{
_cleanup_qemu
_cleanup_test_img
- rm -f "$TEST_DIR"/{b,m,o}.$IMGFMT
+ for img in "$TEST_DIR"/{b,m,o}.$IMGFMT; do
+ _rm_test_img "$img"
+ done
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/142 b/tests/qemu-iotests/142
index 6b62271..daefcba 100755
--- a/tests/qemu-iotests/142
+++ b/tests/qemu-iotests/142
@@ -29,7 +29,7 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f $TEST_IMG.snap
+ _rm_test_img "$TEST_IMG.snap"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/144 b/tests/qemu-iotests/144
index 011ed4f..4569ac0 100755
--- a/tests/qemu-iotests/144
+++ b/tests/qemu-iotests/144
@@ -34,7 +34,9 @@ TMP_SNAP2=${TEST_DIR}/tmp2.qcow2
_cleanup()
{
_cleanup_qemu
- rm -f "${TEST_IMG}" "${TMP_SNAP1}" "${TMP_SNAP2}"
+ for img in "${TEST_IMG}" "${TMP_SNAP1}" "${TMP_SNAP2}"; do
+ _rm_test_img "$img"
+ done
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
index c969a1a..2b13111 100755
--- a/tests/qemu-iotests/153
+++ b/tests/qemu-iotests/153
@@ -30,13 +30,9 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "${TEST_IMG}.base"
- rm -f "${TEST_IMG}.overlay"
- rm -f "${TEST_IMG}.convert"
- rm -f "${TEST_IMG}.a"
- rm -f "${TEST_IMG}.b"
- rm -f "${TEST_IMG}.c"
- rm -f "${TEST_IMG}.lnk"
+ for img in "${TEST_IMG}".{base,overlay,convert,a,b,c,lnk}; do
+ _rm_test_img "$img"
+ done
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -98,7 +94,7 @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do
echo
echo "== Creating test image =="
- $QEMU_IMG create -f $IMGFMT "${TEST_IMG}" -b ${TEST_IMG}.base | _filter_img_create
+ _make_test_img -b "${TEST_IMG}.base"
echo
echo "== Launching QEMU, opts: '$opts1' =="
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
index 2ffa3ca..5559df6 100755
--- a/tests/qemu-iotests/156
+++ b/tests/qemu-iotests/156
@@ -37,7 +37,9 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_qemu
- rm -f "$TEST_IMG"{,.target}{,.backing,.overlay}
+ for img in "$TEST_IMG"{,.target}{,.backing,.overlay}; do
+ _rm_test_img "$img"
+ done
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -49,6 +51,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2 qed
_supported_proto generic
_unsupported_proto vxhs
+# Copying files around with cp does not work with external data files
+_unsupported_imgopts data_file
# Create source disk
TEST_IMG="$TEST_IMG.backing" _make_test_img 1M
@@ -120,7 +124,9 @@ _send_qemu_cmd $QEMU_HANDLE \
'"status": "null"'
# Remove the source images
-rm -f "$TEST_IMG{,.backing,.overlay}"
+for img in "$TEST_IMG{,.backing,.overlay}"; do
+ _rm_test_img "$img"
+done
echo
diff --git a/tests/qemu-iotests/159 b/tests/qemu-iotests/159
index 2557140..f969005 100755
--- a/tests/qemu-iotests/159
+++ b/tests/qemu-iotests/159
@@ -28,7 +28,7 @@ status=1
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG.out"
+ _rm_test_img "$TEST_IMG.out"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/160 b/tests/qemu-iotests/160
index df89d38..0572b5a 100755
--- a/tests/qemu-iotests/160
+++ b/tests/qemu-iotests/160
@@ -28,7 +28,8 @@ status=1
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG.out" "$TEST_IMG.out.dd"
+ _rm_test_img "$TEST_IMG.out"
+ _rm_test_img "$TEST_IMG.out.dd"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/161 b/tests/qemu-iotests/161
index 456a4bd..f572a19 100755
--- a/tests/qemu-iotests/161
+++ b/tests/qemu-iotests/161
@@ -30,8 +30,8 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG.base"
- rm -f "$TEST_IMG.int"
+ _rm_test_img "$TEST_IMG.base"
+ _rm_test_img "$TEST_IMG.int"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/170 b/tests/qemu-iotests/170
index 05dd6ed..6c8f0e8 100755
--- a/tests/qemu-iotests/170
+++ b/tests/qemu-iotests/170
@@ -28,7 +28,7 @@ status=1
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG.out"
+ _rm_test_img "$TEST_IMG.out"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/172 b/tests/qemu-iotests/172
index d67997e..7195fb8 100755
--- a/tests/qemu-iotests/172
+++ b/tests/qemu-iotests/172
@@ -28,9 +28,9 @@ status=1 # failure is the default!
_cleanup()
{
- _cleanup_test_img
- rm -f "$TEST_IMG.2"
- rm -f "$TEST_IMG.3"
+ _cleanup_test_img
+ _rm_test_img "$TEST_IMG.2"
+ _rm_test_img "$TEST_IMG.3"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/173 b/tests/qemu-iotests/173
index 29dcaa1..ec6d170 100755
--- a/tests/qemu-iotests/173
+++ b/tests/qemu-iotests/173
@@ -29,7 +29,8 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_qemu
- rm -f "${QEMU_TEST_DIR}/image.base" "${QEMU_TEST_DIR}/image.snp1"
+ _rm_test_img "${TEST_DIR}/image.base"
+ _rm_test_img "${TEST_DIR}/image.snp1"
_cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/174 b/tests/qemu-iotests/174
index 0a952a7..e2f14a3 100755
--- a/tests/qemu-iotests/174
+++ b/tests/qemu-iotests/174
@@ -40,7 +40,7 @@ _unsupported_fmt raw
size=256K
-IMGFMT=raw IMGKEYSECRET= IMGOPTS= _make_test_img $size | _filter_imgfmt
+IMGFMT=raw IMGKEYSECRET= _make_test_img --no-opts $size | _filter_imgfmt
echo
echo "== reading wrong format should fail =="
diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175
index 55db280..020ed8e 100755
--- a/tests/qemu-iotests/175
+++ b/tests/qemu-iotests/175
@@ -95,7 +95,7 @@ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_block
for mode in off full falloc; do
echo
echo "== creating image with preallocation $mode =="
- IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt
+ _make_test_img -o preallocation=$mode $size | _filter_imgfmt
stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size
done
diff --git a/tests/qemu-iotests/176 b/tests/qemu-iotests/176
index 50df4c0..117c8b6 100755
--- a/tests/qemu-iotests/176
+++ b/tests/qemu-iotests/176
@@ -47,8 +47,11 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
-# Persistent dirty bitmaps require compat=1.1
-_unsupported_imgopts 'compat=0.10'
+# Persistent dirty bitmaps require compat=1.1;
+# Internal snapshots forbid using an external data file
+# (they work with refcount_bits=1 here, though, because there actually
+# is no data when creating the snapshot)
+_unsupported_imgopts 'compat=0.10' data_file
run_qemu()
{
diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178
index 21231ca..51a70fe 100755
--- a/tests/qemu-iotests/178
+++ b/tests/qemu-iotests/178
@@ -29,7 +29,7 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG.converted"
+ _rm_test_img "$TEST_IMG.converted"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -62,8 +62,8 @@ $QEMU_IMG measure -O foo "$TEST_IMG" # unknown image file format
make_test_img_with_fmt() {
# Shadow global variables within this function
- local IMGFMT="$1" IMGOPTS=""
- _make_test_img "$2"
+ local IMGFMT="$1"
+ _make_test_img --no-opts "$2"
}
qemu_io_with_fmt() {
diff --git a/tests/qemu-iotests/182 b/tests/qemu-iotests/182
index 1ccb850..56a2dd5 100755
--- a/tests/qemu-iotests/182
+++ b/tests/qemu-iotests/182
@@ -30,7 +30,7 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG.overlay"
+ _rm_test_img "$TEST_IMG.overlay"
rm -f "$SOCK_DIR/nbd.socket"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/183 b/tests/qemu-iotests/183
index bced83f..3f74b9f 100755
--- a/tests/qemu-iotests/183
+++ b/tests/qemu-iotests/183
@@ -31,7 +31,7 @@ MIG_SOCKET="${SOCK_DIR}/migrate"
_cleanup()
{
rm -f "${MIG_SOCKET}"
- rm -f "${TEST_IMG}.dest"
+ _rm_test_img "${TEST_IMG}.dest"
_cleanup_test_img
_cleanup_qemu
}
diff --git a/tests/qemu-iotests/185 b/tests/qemu-iotests/185
index 454ff60..e50f19e 100755
--- a/tests/qemu-iotests/185
+++ b/tests/qemu-iotests/185
@@ -28,8 +28,8 @@ status=1 # failure is the default!
_cleanup()
{
- rm -f "${TEST_IMG}.mid"
- rm -f "${TEST_IMG}.copy"
+ _rm_test_img "${TEST_IMG}.mid"
+ _rm_test_img "${TEST_IMG}.copy"
_cleanup_test_img
_cleanup_qemu
}
diff --git a/tests/qemu-iotests/187 b/tests/qemu-iotests/187
index 2fcef9e..c6e1dc5 100755
--- a/tests/qemu-iotests/187
+++ b/tests/qemu-iotests/187
@@ -28,9 +28,9 @@ status=1 # failure is the default!
_cleanup()
{
- _cleanup_test_img
- rm -f "$TEST_IMG.2"
- rm -f "$TEST_IMG.3"
+ _cleanup_test_img
+ _rm_test_img "$TEST_IMG.2"
+ _rm_test_img "$TEST_IMG.3"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/190 b/tests/qemu-iotests/190
index eb766ad..6d416504 100755
--- a/tests/qemu-iotests/190
+++ b/tests/qemu-iotests/190
@@ -29,7 +29,7 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG.converted"
+ _rm_test_img "$TEST_IMG.converted"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -45,7 +45,7 @@ _supported_proto file
echo "== Huge file =="
echo
-IMGOPTS='cluster_size=2M' _make_test_img 2T
+_make_test_img -o 'cluster_size=2M' 2T
$QEMU_IMG measure -O raw -f qcow2 "$TEST_IMG"
$QEMU_IMG measure -O qcow2 -o cluster_size=64k -f qcow2 "$TEST_IMG"
diff --git a/tests/qemu-iotests/191 b/tests/qemu-iotests/191
index 528022e..b05db68 100755
--- a/tests/qemu-iotests/191
+++ b/tests/qemu-iotests/191
@@ -28,9 +28,9 @@ status=1 # failure is the default!
_cleanup()
{
- rm -f "${TEST_IMG}.mid"
- rm -f "${TEST_IMG}.ovl2"
- rm -f "${TEST_IMG}.ovl3"
+ _rm_test_img "${TEST_IMG}.mid"
+ _rm_test_img "${TEST_IMG}.ovl2"
+ _rm_test_img "${TEST_IMG}.ovl3"
_cleanup_test_img
_cleanup_qemu
}
@@ -43,6 +43,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
+# An external data file would change the query-named-block-nodes output
+_unsupported_imgopts data_file
size=64M
@@ -51,8 +53,7 @@ echo === Preparing and starting VM ===
echo
TEST_IMG="${TEST_IMG}.base" _make_test_img $size
-IMGOPTS=$(_optstr_add "$IMGOPTS" "backing_fmt=$IMGFMT") \
- TEST_IMG="${TEST_IMG}.mid" _make_test_img -b "${TEST_IMG}.base"
+TEST_IMG="${TEST_IMG}.mid" _make_test_img -o "backing_fmt=$IMGFMT" -b "${TEST_IMG}.base"
_make_test_img -b "${TEST_IMG}.mid"
TEST_IMG="${TEST_IMG}.ovl2" _make_test_img -b "${TEST_IMG}.mid"
diff --git a/tests/qemu-iotests/195 b/tests/qemu-iotests/195
index ef7b9a9..48984b7 100755
--- a/tests/qemu-iotests/195
+++ b/tests/qemu-iotests/195
@@ -29,7 +29,7 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG.mid"
+ _rm_test_img "$TEST_IMG.mid"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/197 b/tests/qemu-iotests/197
index 1d4f678..95f05b0 100755
--- a/tests/qemu-iotests/197
+++ b/tests/qemu-iotests/197
@@ -43,7 +43,7 @@ esac
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_WRAP"
+ _rm_test_img "$TEST_WRAP"
rm -f "$BLKDBG_CONF"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -66,8 +66,8 @@ if [ "$IMGFMT" = "vpc" ]; then
fi
_make_test_img 4G
$QEMU_IO -c "write -P 55 3G 1k" "$TEST_IMG" | _filter_qemu_io
-IMGPROTO=file IMGFMT=qcow2 IMGOPTS= TEST_IMG_FILE="$TEST_WRAP" \
- _make_test_img -F "$IMGFMT" -b "$TEST_IMG" | _filter_img_create
+IMGPROTO=file IMGFMT=qcow2 TEST_IMG_FILE="$TEST_WRAP" \
+ _make_test_img --no-opts -F "$IMGFMT" -b "$TEST_IMG" | _filter_img_create
$QEMU_IO -f qcow2 -c "write -z -u 1M 64k" "$TEST_WRAP" | _filter_qemu_io
# Ensure that a read of two clusters, but where one is already allocated,
diff --git a/tests/qemu-iotests/198 b/tests/qemu-iotests/198
index c8f824c..fb0d5a2 100755
--- a/tests/qemu-iotests/198
+++ b/tests/qemu-iotests/198
@@ -92,13 +92,15 @@ echo
echo "== checking image base =="
$QEMU_IMG info --image-opts $IMGSPECBASE | _filter_img_info --format-specific \
| sed -e "/^disk size:/ D" -e '/refcount bits:/ D' -e '/compat:/ D' \
- -e '/lazy refcounts:/ D' -e '/corrupt:/ D'
+ -e '/lazy refcounts:/ D' -e '/corrupt:/ D' -e '/^\s*data file/ D' \
+ | _filter_json_filename
echo
echo "== checking image layer =="
$QEMU_IMG info --image-opts $IMGSPECLAYER | _filter_img_info --format-specific \
| sed -e "/^disk size:/ D" -e '/refcount bits:/ D' -e '/compat:/ D' \
- -e '/lazy refcounts:/ D' -e '/corrupt:/ D'
+ -e '/lazy refcounts:/ D' -e '/corrupt:/ D' -e '/^\s*data file/ D' \
+ | _filter_json_filename
# success, all done
diff --git a/tests/qemu-iotests/198.out b/tests/qemu-iotests/198.out
index e86b175..831ce3a 100644
--- a/tests/qemu-iotests/198.out
+++ b/tests/qemu-iotests/198.out
@@ -32,7 +32,7 @@ read 16777216/16777216 bytes at offset 0
16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== checking image base ==
-image: json:{"encrypt.key-secret": "sec0", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.base"}}
+image: json:{ /* filtered */ }
file format: IMGFMT
virtual size: 16 MiB (16777216 bytes)
Format specific information:
@@ -74,7 +74,7 @@ Format specific information:
master key iters: 1024
== checking image layer ==
-image: json:{"encrypt.key-secret": "sec1", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}}
+image: json:{ /* filtered */ }
file format: IMGFMT
virtual size: 16 MiB (16777216 bytes)
backing file: TEST_DIR/t.IMGFMT.base
diff --git a/tests/qemu-iotests/200 b/tests/qemu-iotests/200
index 72d431f..a2cdd7f 100755
--- a/tests/qemu-iotests/200
+++ b/tests/qemu-iotests/200
@@ -31,7 +31,8 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_qemu
- rm -f "${TEST_IMG}" "${BACKING_IMG}"
+ _rm_test_img "${TEST_IMG}"
+ _rm_test_img "${BACKING_IMG}"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -46,8 +47,8 @@ _supported_proto file
BACKING_IMG="${TEST_DIR}/backing.img"
TEST_IMG="${TEST_DIR}/test.img"
-${QEMU_IMG} create -f $IMGFMT "${BACKING_IMG}" 512M | _filter_img_create
-${QEMU_IMG} create -f $IMGFMT -F $IMGFMT "${TEST_IMG}" -b "${BACKING_IMG}" 512M | _filter_img_create
+TEST_IMG="$BACKING_IMG" _make_test_img 512M
+_make_test_img -F $IMGFMT -b "$BACKING_IMG" 512M
${QEMU_IO} -c "write -P 0xa5 512 300M" "${BACKING_IMG}" | _filter_qemu_io
diff --git a/tests/qemu-iotests/201 b/tests/qemu-iotests/201
index 86fa37e..133ba9f 100755
--- a/tests/qemu-iotests/201
+++ b/tests/qemu-iotests/201
@@ -43,9 +43,9 @@ _supported_fmt qcow2
_supported_proto generic
_supported_os Linux
-# Internal snapshots are (currently) impossible with refcount_bits=1
-# This was taken from test 080
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
+# Internal snapshots are (currently) impossible with refcount_bits=1,
+# and generally impossible with external data files
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
size=64M
_make_test_img $size
diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206
index 5bb738b..9f16a7d 100755
--- a/tests/qemu-iotests/206
+++ b/tests/qemu-iotests/206
@@ -25,16 +25,6 @@ from iotests import imgfmt
iotests.verify_image_format(supported_fmts=['qcow2'])
-def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create',
- filters=[iotests.filter_qmp_testfiles],
- job_id='job0', options=options)
-
- if 'return' in result:
- assert result['return'] == {}
- vm.run_job('job0')
- iotests.log("")
-
with iotests.FilePath('t.qcow2') as disk_path, \
iotests.FilePath('t.qcow2.base') as backing_path, \
iotests.VM() as vm:
@@ -50,18 +40,18 @@ with iotests.FilePath('t.qcow2') as disk_path, \
size = 128 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0 })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
vm.qmp_log('blockdev-add',
filters=[iotests.filter_qmp_testfiles],
driver='file', filename=disk_path,
node_name='imgfile')
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'imgfile',
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'imgfile',
+ 'size': size })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -76,23 +66,23 @@ with iotests.FilePath('t.qcow2') as disk_path, \
size = 64 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0,
- 'preallocation': 'off',
- 'nocow': False })
-
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': {
- 'driver': 'file',
- 'filename': disk_path,
- },
- 'size': size,
- 'version': 'v3',
- 'cluster-size': 65536,
- 'preallocation': 'off',
- 'lazy-refcounts': False,
- 'refcount-bits': 16 })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0,
+ 'preallocation': 'off',
+ 'nocow': False })
+
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'version': 'v3',
+ 'cluster-size': 65536,
+ 'preallocation': 'off',
+ 'lazy-refcounts': False,
+ 'refcount-bits': 16 })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -107,23 +97,23 @@ with iotests.FilePath('t.qcow2') as disk_path, \
size = 32 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0,
- 'preallocation': 'falloc',
- 'nocow': True })
-
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': {
- 'driver': 'file',
- 'filename': disk_path,
- },
- 'size': size,
- 'version': 'v3',
- 'cluster-size': 2097152,
- 'preallocation': 'metadata',
- 'lazy-refcounts': True,
- 'refcount-bits': 1 })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0,
+ 'preallocation': 'falloc',
+ 'nocow': True })
+
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'version': 'v3',
+ 'cluster-size': 2097152,
+ 'preallocation': 'metadata',
+ 'lazy-refcounts': True,
+ 'refcount-bits': 1 })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -135,20 +125,20 @@ with iotests.FilePath('t.qcow2') as disk_path, \
iotests.log("")
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0 })
-
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': {
- 'driver': 'file',
- 'filename': disk_path,
- },
- 'size': size,
- 'backing-file': backing_path,
- 'backing-fmt': 'qcow2',
- 'version': 'v2',
- 'cluster-size': 512 })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'backing-file': backing_path,
+ 'backing-fmt': 'qcow2',
+ 'version': 'v2',
+ 'cluster-size': 512 })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -160,22 +150,22 @@ with iotests.FilePath('t.qcow2') as disk_path, \
iotests.log("")
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': {
- 'driver': 'file',
- 'filename': disk_path,
- },
- 'size': size,
- 'encrypt': {
- 'format': 'luks',
- 'key-secret': 'keysec0',
- 'cipher-alg': 'twofish-128',
- 'cipher-mode': 'ctr',
- 'ivgen-alg': 'plain64',
- 'ivgen-hash-alg': 'md5',
- 'hash-alg': 'sha1',
- 'iter-time': 10,
- }})
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'encrypt': {
+ 'format': 'luks',
+ 'key-secret': 'keysec0',
+ 'cipher-alg': 'twofish-128',
+ 'cipher-mode': 'ctr',
+ 'ivgen-alg': 'plain64',
+ 'ivgen-hash-alg': 'md5',
+ 'hash-alg': 'sha1',
+ 'iter-time': 10,
+ }})
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -187,9 +177,9 @@ with iotests.FilePath('t.qcow2') as disk_path, \
iotests.log("")
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': "this doesn't exist",
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': "this doesn't exist",
+ 'size': size })
vm.shutdown()
#
@@ -211,9 +201,9 @@ with iotests.FilePath('t.qcow2') as disk_path, \
vm.launch()
for size in [ 1234, 18446744073709551104, 9223372036854775808,
9223372036854775296 ]:
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': size })
vm.shutdown()
#
@@ -222,20 +212,20 @@ with iotests.FilePath('t.qcow2') as disk_path, \
iotests.log("=== Invalid version ===")
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 67108864,
- 'version': 'v1' })
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 67108864,
- 'version': 'v2',
- 'lazy-refcounts': True })
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 67108864,
- 'version': 'v2',
- 'refcount-bits': 8 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'version': 'v1' })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'version': 'v2',
+ 'lazy-refcounts': True })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'version': 'v2',
+ 'refcount-bits': 8 })
vm.shutdown()
#
@@ -244,15 +234,15 @@ with iotests.FilePath('t.qcow2') as disk_path, \
iotests.log("=== Invalid backing file options ===")
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 67108864,
- 'backing-file': '/dev/null',
- 'preallocation': 'full' })
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 67108864,
- 'backing-fmt': imgfmt })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'backing-file': '/dev/null',
+ 'preallocation': 'full' })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'backing-fmt': imgfmt })
vm.shutdown()
#
@@ -262,14 +252,14 @@ with iotests.FilePath('t.qcow2') as disk_path, \
vm.launch()
for csize in [ 1234, 128, 4194304, 0 ]:
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 67108864,
- 'cluster-size': csize })
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 281474976710656,
- 'cluster-size': 512 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'cluster-size': csize })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 281474976710656,
+ 'cluster-size': 512 })
vm.shutdown()
#
@@ -279,8 +269,8 @@ with iotests.FilePath('t.qcow2') as disk_path, \
vm.launch()
for refcount_bits in [ 128, 0, 7 ]:
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 67108864,
- 'refcount-bits': refcount_bits })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'refcount-bits': refcount_bits })
vm.shutdown()
diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
index ec8c1d0..812ab34 100755
--- a/tests/qemu-iotests/207
+++ b/tests/qemu-iotests/207
@@ -35,13 +35,7 @@ def filter_hash(qmsg):
return iotests.filter_qmp(qmsg, _filter)
def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
- filters=[iotests.filter_qmp_testfiles, filter_hash])
-
- if 'return' in result:
- assert result['return'] == {}
- vm.run_job('job0')
- iotests.log("")
+ vm.blockdev_create(options, filters=[iotests.filter_qmp_testfiles, filter_hash])
with iotests.FilePath('t.img') as disk_path, \
iotests.VM() as vm:
diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
index 565e3b7..4ca0fe2 100755
--- a/tests/qemu-iotests/210
+++ b/tests/qemu-iotests/210
@@ -26,15 +26,6 @@ from iotests import imgfmt
iotests.verify_image_format(supported_fmts=['luks'])
iotests.verify_protocol(supported=['file'])
-def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
- filters=[iotests.filter_qmp_testfiles])
-
- if 'return' in result:
- assert result['return'] == {}
- vm.run_job('job0')
- iotests.log("")
-
with iotests.FilePath('t.luks') as disk_path, \
iotests.VM() as vm:
@@ -49,18 +40,18 @@ with iotests.FilePath('t.luks') as disk_path, \
size = 128 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0 })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'imgfile',
- 'key-secret': 'keysec0',
- 'size': size,
- 'iter-time': 10 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'imgfile',
+ 'key-secret': 'keysec0',
+ 'size': size,
+ 'iter-time': 10 })
vm.shutdown()
# TODO Proper support for images to be used with imgopts and/or protocols
@@ -79,22 +70,22 @@ with iotests.FilePath('t.luks') as disk_path, \
size = 64 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0 })
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': {
- 'driver': 'file',
- 'filename': disk_path,
- },
- 'size': size,
- 'key-secret': 'keysec0',
- 'cipher-alg': 'twofish-128',
- 'cipher-mode': 'ctr',
- 'ivgen-alg': 'plain64',
- 'ivgen-hash-alg': 'md5',
- 'hash-alg': 'sha1',
- 'iter-time': 10 })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'key-secret': 'keysec0',
+ 'cipher-alg': 'twofish-128',
+ 'cipher-mode': 'ctr',
+ 'ivgen-alg': 'plain64',
+ 'ivgen-hash-alg': 'md5',
+ 'hash-alg': 'sha1',
+ 'iter-time': 10 })
vm.shutdown()
# TODO Proper support for images to be used with imgopts and/or protocols
@@ -113,9 +104,9 @@ with iotests.FilePath('t.luks') as disk_path, \
size = 64 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': "this doesn't exist",
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': "this doesn't exist",
+ 'size': size })
vm.shutdown()
#
@@ -126,11 +117,11 @@ with iotests.FilePath('t.luks') as disk_path, \
vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'key-secret': 'keysec0',
- 'size': 0,
- 'iter-time': 10 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'key-secret': 'keysec0',
+ 'size': 0,
+ 'iter-time': 10 })
vm.shutdown()
# TODO Proper support for images to be used with imgopts and/or protocols
@@ -157,10 +148,10 @@ with iotests.FilePath('t.luks') as disk_path, \
vm.launch()
for size in [ 18446744073709551104, 9223372036854775808, 9223372036854775296 ]:
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'key-secret': 'keysec0',
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'key-secret': 'keysec0',
+ 'size': size })
vm.shutdown()
#
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
index 6afc894..8834ebf 100755
--- a/tests/qemu-iotests/211
+++ b/tests/qemu-iotests/211
@@ -27,15 +27,9 @@ iotests.verify_image_format(supported_fmts=['vdi'])
iotests.verify_protocol(supported=['file'])
def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
- filters=[iotests.filter_qmp_testfiles])
-
- if 'return' in result:
- assert result['return'] == {}
- error = vm.run_job('job0')
- if error and 'Could not allocate bmap' in error:
- iotests.notrun('Insufficient memory')
- iotests.log("")
+ error = vm.blockdev_create(options)
+ if error and 'Could not allocate bmap' in error:
+ iotests.notrun('Insufficient memory')
with iotests.FilePath('t.vdi') as disk_path, \
iotests.VM() as vm:
diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212
index 42b74f2..8f3ccc7 100755
--- a/tests/qemu-iotests/212
+++ b/tests/qemu-iotests/212
@@ -26,15 +26,6 @@ from iotests import imgfmt
iotests.verify_image_format(supported_fmts=['parallels'])
iotests.verify_protocol(supported=['file'])
-def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
- filters=[iotests.filter_qmp_testfiles])
-
- if 'return' in result:
- assert result['return'] == {}
- vm.run_job('job0')
- iotests.log("")
-
with iotests.FilePath('t.parallels') as disk_path, \
iotests.VM() as vm:
@@ -47,16 +38,16 @@ with iotests.FilePath('t.parallels') as disk_path, \
size = 128 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0 })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'imgfile',
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'imgfile',
+ 'size': size })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -71,16 +62,16 @@ with iotests.FilePath('t.parallels') as disk_path, \
size = 64 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0 })
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': {
- 'driver': 'file',
- 'filename': disk_path,
- },
- 'size': size,
- 'cluster-size': 1048576 })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'cluster-size': 1048576 })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -95,16 +86,16 @@ with iotests.FilePath('t.parallels') as disk_path, \
size = 32 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0 })
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': {
- 'driver': 'file',
- 'filename': disk_path,
- },
- 'size': size,
- 'cluster-size': 65536 })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'cluster-size': 65536 })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -116,9 +107,9 @@ with iotests.FilePath('t.parallels') as disk_path, \
iotests.log("")
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': "this doesn't exist",
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': "this doesn't exist",
+ 'size': size })
vm.shutdown()
#
@@ -129,9 +120,9 @@ with iotests.FilePath('t.parallels') as disk_path, \
vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 0 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 0 })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -143,9 +134,9 @@ with iotests.FilePath('t.parallels') as disk_path, \
iotests.log("")
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 4503599627369984})
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 4503599627369984})
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -171,9 +162,9 @@ with iotests.FilePath('t.parallels') as disk_path, \
vm.launch()
for size in [ 1234, 18446744073709551104, 9223372036854775808,
9223372036854775296, 4503599627370497 ]:
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': size })
vm.shutdown()
#
@@ -185,12 +176,12 @@ with iotests.FilePath('t.parallels') as disk_path, \
vm.launch()
for csize in [ 1234, 128, 4294967296, 9223372036854775808,
18446744073709551104, 0 ]:
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 67108864,
- 'cluster-size': csize })
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 281474976710656,
- 'cluster-size': 512 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'cluster-size': csize })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 281474976710656,
+ 'cluster-size': 512 })
vm.shutdown()
diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213
index 5604f3c..3fc8dc6 100755
--- a/tests/qemu-iotests/213
+++ b/tests/qemu-iotests/213
@@ -26,15 +26,6 @@ from iotests import imgfmt
iotests.verify_image_format(supported_fmts=['vhdx'])
iotests.verify_protocol(supported=['file'])
-def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
- filters=[iotests.filter_qmp_testfiles])
-
- if 'return' in result:
- assert result['return'] == {}
- vm.run_job('job0')
- iotests.log("")
-
with iotests.FilePath('t.vhdx') as disk_path, \
iotests.VM() as vm:
@@ -47,16 +38,16 @@ with iotests.FilePath('t.vhdx') as disk_path, \
size = 128 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0 })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'imgfile',
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'imgfile',
+ 'size': size })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -71,19 +62,19 @@ with iotests.FilePath('t.vhdx') as disk_path, \
size = 64 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0 })
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': {
- 'driver': 'file',
- 'filename': disk_path,
- },
- 'size': size,
- 'log-size': 1048576,
- 'block-size': 8388608,
- 'subformat': 'dynamic',
- 'block-state-zero': True })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'log-size': 1048576,
+ 'block-size': 8388608,
+ 'subformat': 'dynamic',
+ 'block-state-zero': True })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -98,19 +89,19 @@ with iotests.FilePath('t.vhdx') as disk_path, \
size = 32 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0 })
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': {
- 'driver': 'file',
- 'filename': disk_path,
- },
- 'size': size,
- 'log-size': 8388608,
- 'block-size': 268435456,
- 'subformat': 'fixed',
- 'block-state-zero': False })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'log-size': 8388608,
+ 'block-size': 268435456,
+ 'subformat': 'fixed',
+ 'block-state-zero': False })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -122,9 +113,9 @@ with iotests.FilePath('t.vhdx') as disk_path, \
iotests.log("")
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': "this doesn't exist",
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': "this doesn't exist",
+ 'size': size })
vm.shutdown()
#
@@ -135,9 +126,9 @@ with iotests.FilePath('t.vhdx') as disk_path, \
vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 0 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 0 })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -149,9 +140,9 @@ with iotests.FilePath('t.vhdx') as disk_path, \
iotests.log("")
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 70368744177664 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 70368744177664 })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -176,9 +167,9 @@ with iotests.FilePath('t.vhdx') as disk_path, \
vm.launch()
for size in [ 18446744073709551104, 9223372036854775808,
9223372036854775296, 70368744177665 ]:
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': size })
vm.shutdown()
#
@@ -189,10 +180,10 @@ with iotests.FilePath('t.vhdx') as disk_path, \
vm.launch()
for bsize in [ 1234567, 128, 3145728, 536870912, 0 ]:
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 67108864,
- 'block-size': bsize })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'block-size': bsize })
vm.shutdown()
#
@@ -203,8 +194,8 @@ with iotests.FilePath('t.vhdx') as disk_path, \
vm.launch()
for lsize in [ 1234567, 128, 4294967296, 0 ]:
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 67108864,
- 'log-size': lsize })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'log-size': lsize })
vm.shutdown()
diff --git a/tests/qemu-iotests/214 b/tests/qemu-iotests/214
index 21ec8a2..3500e0c 100755
--- a/tests/qemu-iotests/214
+++ b/tests/qemu-iotests/214
@@ -39,7 +39,8 @@ _supported_proto file
# Repairing the corrupted image requires qemu-img check to store a
# refcount up to 3, which requires at least two refcount bits.
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
+# External data files do not support compressed clusters.
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
echo
@@ -89,6 +90,49 @@ _check_test_img -r all
$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
$QEMU_IO -c "read -P 0x22 4M 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
+echo
+echo "=== Write compressed data of multiple clusters ==="
+echo
+cluster_size=0x10000
+_make_test_img 2M -o cluster_size=$cluster_size
+
+echo "Write uncompressed data:"
+let data_size="8 * $cluster_size"
+$QEMU_IO -c "write -P 0xaa 0 $data_size" "$TEST_IMG" \
+ 2>&1 | _filter_qemu_io | _filter_testdir
+sizeA=$($QEMU_IMG info --output=json "$TEST_IMG" |
+ sed -n '/"actual-size":/ s/[^0-9]//gp')
+
+_make_test_img 2M -o cluster_size=$cluster_size
+echo "Write compressed data:"
+let data_size="3 * $cluster_size + $cluster_size / 2"
+# Set compress on. That will align the written data
+# by the cluster size and will write them compressed.
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT \
+$QEMU_IO -c "write -P 0xbb 0 $data_size" --image-opts \
+ "driver=compress,file.driver=$IMGFMT,file.file.driver=file,file.file.filename=$TEST_IMG" \
+ 2>&1 | _filter_qemu_io | _filter_testdir
+
+let offset="4 * $cluster_size + $cluster_size / 4"
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT \
+$QEMU_IO -c "write -P 0xcc $offset $data_size" "json:{\
+ 'driver': 'compress',
+ 'file': {'driver': '$IMGFMT',
+ 'file': {'driver': 'file',
+ 'filename': '$TEST_IMG'}}}" | \
+ _filter_qemu_io | _filter_testdir
+
+sizeB=$($QEMU_IMG info --output=json "$TEST_IMG" |
+ sed -n '/"actual-size":/ s/[^0-9]//gp')
+
+if [ $sizeA -le $sizeB ]
+then
+ echo "Compression ERROR"
+fi
+
+$QEMU_IMG check --output=json "$TEST_IMG" |
+ sed -n 's/,$//; /"compressed-clusters":/ s/^ *//p'
+
# success, all done
echo '*** done'
rm -f $seq.full
diff --git a/tests/qemu-iotests/214.out b/tests/qemu-iotests/214.out
index 0fcd8dc..9fc6728 100644
--- a/tests/qemu-iotests/214.out
+++ b/tests/qemu-iotests/214.out
@@ -32,4 +32,18 @@ read 4194304/4194304 bytes at offset 0
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 4194304/4194304 bytes at offset 4194304
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Write compressed data of multiple clusters ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2097152
+Write uncompressed data:
+wrote 524288/524288 bytes at offset 0
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2097152
+Write compressed data:
+wrote 229376/229376 bytes at offset 0
+224 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 229376/229376 bytes at offset 278528
+224 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+"compressed-clusters": 8
*** done
diff --git a/tests/qemu-iotests/215 b/tests/qemu-iotests/215
index 2eb377d..f99bae7 100755
--- a/tests/qemu-iotests/215
+++ b/tests/qemu-iotests/215
@@ -40,7 +40,7 @@ esac
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_WRAP"
+ _rm_test_img "$TEST_WRAP"
rm -f "$BLKDBG_CONF"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -63,8 +63,8 @@ if [ "$IMGFMT" = "vpc" ]; then
fi
_make_test_img 4G
$QEMU_IO -c "write -P 55 3G 1k" "$TEST_IMG" | _filter_qemu_io
-IMGPROTO=file IMGFMT=qcow2 IMGOPTS= TEST_IMG_FILE="$TEST_WRAP" \
- _make_test_img -F "$IMGFMT" -b "$TEST_IMG" | _filter_img_create
+IMGPROTO=file IMGFMT=qcow2 TEST_IMG_FILE="$TEST_WRAP" \
+ _make_test_img --no-opts -F "$IMGFMT" -b "$TEST_IMG" | _filter_img_create
$QEMU_IO -f qcow2 -c "write -z -u 1M 64k" "$TEST_WRAP" | _filter_qemu_io
# Ensure that a read of two clusters, but where one is already allocated,
diff --git a/tests/qemu-iotests/217 b/tests/qemu-iotests/217
index 58a78a6..d89116c 100755
--- a/tests/qemu-iotests/217
+++ b/tests/qemu-iotests/217
@@ -40,7 +40,8 @@ _supported_proto file
# This test needs clusters with at least a refcount of 2 so that
# OFLAG_COPIED is not set. refcount_bits=1 is therefore unsupported.
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
+# (As are external data files.)
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
echo
echo '=== Simulating an I/O error during snapshot deletion ==='
diff --git a/tests/qemu-iotests/220 b/tests/qemu-iotests/220
index 2d62c5d..a9259b7 100755
--- a/tests/qemu-iotests/220
+++ b/tests/qemu-iotests/220
@@ -37,16 +37,17 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
+# To use a different refcount width but 16 bits we need compat=1.1,
+# and external data files do not support compressed clusters.
+_unsupported_imgopts 'compat=0.10' data_file
echo "== Creating huge file =="
# Sanity check: We require a file system that permits the creation
# of a HUGE (but very sparse) file. tmpfs works, ext4 does not.
-if ! truncate --size=513T "$TEST_IMG"; then
- _notrun "file system on $TEST_DIR does not support large enough files"
-fi
-rm "$TEST_IMG"
-IMGOPTS='cluster_size=2M,refcount_bits=1' _make_test_img 513T
+_require_large_file 513T
+
+_make_test_img -o 'cluster_size=2M,refcount_bits=1' 513T
echo "== Populating refcounts =="
# We want an image with 256M refcounts * 2M clusters = 512T referenced.
diff --git a/tests/qemu-iotests/225 b/tests/qemu-iotests/225
index fbd7404..c9a334c 100755
--- a/tests/qemu-iotests/225
+++ b/tests/qemu-iotests/225
@@ -29,7 +29,7 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG.not_base"
+ _rm_test_img "$TEST_IMG.not_base"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/229 b/tests/qemu-iotests/229
index e18a464..866168b 100755
--- a/tests/qemu-iotests/229
+++ b/tests/qemu-iotests/229
@@ -31,7 +31,8 @@ _cleanup()
{
_cleanup_qemu
_cleanup_test_img
- rm -f "$TEST_IMG" "$DEST_IMG"
+ _rm_test_img "$TEST_IMG"
+ _rm_test_img "$DEST_IMG"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
index 65b0e42..685356a 100755
--- a/tests/qemu-iotests/232
+++ b/tests/qemu-iotests/232
@@ -29,7 +29,9 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f $TEST_IMG.[01234]
+ for img in "$TEST_IMG".[01234]; do
+ _rm_test_img "$img"
+ done
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/235 b/tests/qemu-iotests/235
index fedd111..3d75339 100755
--- a/tests/qemu-iotests/235
+++ b/tests/qemu-iotests/235
@@ -49,7 +49,7 @@ qemu_img_create('-f', iotests.imgfmt, '-o', 'preallocation=metadata', disk,
str(size))
vm = QEMUMachine(iotests.qemu_prog)
-vm.add_args('-machine', 'accel=kvm:tcg')
+vm.add_args('-accel', 'kvm', '-accel', 'tcg')
if iotests.qemu_default_machine == 's390-ccw-virtio':
vm.add_args('-no-shutdown')
vm.add_args('-drive', 'id=src,file=' + disk)
diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237
index 06897f8..a2242a4 100755
--- a/tests/qemu-iotests/237
+++ b/tests/qemu-iotests/237
@@ -26,15 +26,6 @@ from iotests import imgfmt
iotests.verify_image_format(supported_fmts=['vmdk'])
-def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
- filters=[iotests.filter_qmp_testfiles])
-
- if 'return' in result:
- assert result['return'] == {}
- vm.run_job('job0')
- iotests.log("")
-
with iotests.FilePath('t.vmdk') as disk_path, \
iotests.FilePath('t.vmdk.1') as extent1_path, \
iotests.FilePath('t.vmdk.2') as extent2_path, \
@@ -50,16 +41,16 @@ with iotests.FilePath('t.vmdk') as disk_path, \
size = 5 * 1024 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0 })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'imgfile',
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'imgfile',
+ 'size': size })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -74,21 +65,21 @@ with iotests.FilePath('t.vmdk') as disk_path, \
size = 64 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0 })
-
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': {
- 'driver': 'file',
- 'filename': disk_path,
- },
- 'size': size,
- 'extents': [],
- 'subformat': 'monolithicSparse',
- 'adapter-type': 'ide',
- 'hwversion': '4',
- 'zeroed-grain': False })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'extents': [],
+ 'subformat': 'monolithicSparse',
+ 'adapter-type': 'ide',
+ 'hwversion': '4',
+ 'zeroed-grain': False })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -103,20 +94,20 @@ with iotests.FilePath('t.vmdk') as disk_path, \
size = 32 * 1024 * 1024
vm.launch()
- blockdev_create(vm, { 'driver': 'file',
- 'filename': disk_path,
- 'size': 0 })
-
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': {
- 'driver': 'file',
- 'filename': disk_path,
- },
- 'size': size,
- 'extents': [],
- 'subformat': 'monolithicSparse',
- 'adapter-type': 'buslogic',
- 'zeroed-grain': True })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'extents': [],
+ 'subformat': 'monolithicSparse',
+ 'adapter-type': 'buslogic',
+ 'zeroed-grain': True })
vm.shutdown()
iotests.img_info_log(disk_path)
@@ -128,9 +119,9 @@ with iotests.FilePath('t.vmdk') as disk_path, \
iotests.log("")
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': "this doesn't exist",
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': "this doesn't exist",
+ 'size': size })
vm.shutdown()
#
@@ -148,10 +139,10 @@ with iotests.FilePath('t.vmdk') as disk_path, \
vm.launch()
for adapter_type in [ 'ide', 'buslogic', 'lsilogic', 'legacyESX' ]:
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': size,
- 'adapter-type': adapter_type })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': size,
+ 'adapter-type': adapter_type })
vm.shutdown()
# Invalid
@@ -160,10 +151,10 @@ with iotests.FilePath('t.vmdk') as disk_path, \
vm.launch()
for adapter_type in [ 'foo', 'IDE', 'legacyesx', 1 ]:
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': size,
- 'adapter-type': adapter_type })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': size,
+ 'adapter-type': adapter_type })
vm.shutdown()
#
@@ -185,10 +176,10 @@ with iotests.FilePath('t.vmdk') as disk_path, \
iotests.log("")
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': size,
- 'subformat': 'monolithicFlat' })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': size,
+ 'subformat': 'monolithicFlat' })
vm.shutdown()
# Correct extent
@@ -196,11 +187,11 @@ with iotests.FilePath('t.vmdk') as disk_path, \
iotests.log("")
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': size,
- 'subformat': 'monolithicFlat',
- 'extents': ['ext1'] })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': size,
+ 'subformat': 'monolithicFlat',
+ 'extents': ['ext1'] })
vm.shutdown()
# Extra extent
@@ -208,11 +199,11 @@ with iotests.FilePath('t.vmdk') as disk_path, \
iotests.log("")
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': 512,
- 'subformat': 'monolithicFlat',
- 'extents': ['ext1', 'ext2', 'ext3'] })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 512,
+ 'subformat': 'monolithicFlat',
+ 'extents': ['ext1', 'ext2', 'ext3'] })
vm.shutdown()
# Split formats
@@ -228,11 +219,11 @@ with iotests.FilePath('t.vmdk') as disk_path, \
extents = [ "ext%d" % (i) for i in range(1, num_extents + 1) ]
vm.launch()
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'node0',
- 'size': size,
- 'subformat': subfmt,
- 'extents': extents })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': size,
+ 'subformat': subfmt,
+ 'extents': extents })
vm.shutdown()
iotests.img_info_log(disk_path)
diff --git a/tests/qemu-iotests/243 b/tests/qemu-iotests/243
index e563761..a61852f 100755
--- a/tests/qemu-iotests/243
+++ b/tests/qemu-iotests/243
@@ -29,7 +29,7 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f $TEST_IMG.data
+ _rm_test_img "$TEST_IMG.data"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -40,6 +40,10 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
+# External data files do not work with compat=0.10, and because there
+# is an explicit case for external data files here, we cannot allow
+# the user to specify whether to use one
+_unsupported_imgopts 'compat=0.10' data_file
for mode in off metadata falloc full; do
@@ -47,7 +51,7 @@ for mode in off metadata falloc full; do
echo "=== preallocation=$mode ==="
echo
- IMGOPTS="preallocation=$mode" _make_test_img 64M
+ _make_test_img -o "preallocation=$mode" 64M
printf "File size: "
du -b $TEST_IMG | cut -f1
@@ -64,7 +68,7 @@ for mode in off metadata falloc full; do
echo "=== External data file: preallocation=$mode ==="
echo
- IMGOPTS="data_file=$TEST_IMG.data,preallocation=$mode" _make_test_img 64M
+ _make_test_img -o "data_file=$TEST_IMG.data,preallocation=$mode" 64M
echo -n "qcow2 file size: "
du -b $TEST_IMG | cut -f1
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
index 13978f9..0d1efee 100755
--- a/tests/qemu-iotests/244
+++ b/tests/qemu-iotests/244
@@ -29,8 +29,8 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f $TEST_IMG.data
- rm -f $TEST_IMG.src
+ _rm_test_img "$TEST_IMG.data"
+ _rm_test_img "$TEST_IMG.src"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -41,13 +41,16 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
+# External data files do not work with compat=0.10, and because we use
+# our own external data file, we cannot let the user specify one
+_unsupported_imgopts 'compat=0.10' data_file
echo
echo "=== Create and open image with external data file ==="
echo
echo "With data file name in the image:"
-IMGOPTS="data_file=$TEST_IMG.data" _make_test_img 64M
+_make_test_img -o "data_file=$TEST_IMG.data" 64M
_check_test_img
$QEMU_IO -c "open $TEST_IMG" -c "read -P 0 0 64k" 2>&1 | _filter_qemu_io | _filter_testdir
@@ -104,7 +107,7 @@ echo
echo "=== Standalone image with external data file (efficient) ==="
echo
-IMGOPTS="data_file=$TEST_IMG.data" _make_test_img 64M
+_make_test_img -o "data_file=$TEST_IMG.data" 64M
echo -n "qcow2 file size before I/O: "
du -b $TEST_IMG | cut -f1
@@ -154,7 +157,7 @@ echo
echo "=== Standalone image with external data file (valid raw) ==="
echo
-IMGOPTS="data_file=$TEST_IMG.data,data_file_raw=on" _make_test_img 64M
+_make_test_img -o "data_file=$TEST_IMG.data,data_file_raw=on" 64M
echo -n "qcow2 file size before I/O: "
du -b $TEST_IMG | cut -f1
@@ -187,7 +190,7 @@ echo
echo "=== bdrv_co_block_status test for file and offset=0 ==="
echo
-IMGOPTS="data_file=$TEST_IMG.data" _make_test_img 64M
+_make_test_img -o "data_file=$TEST_IMG.data" 64M
$QEMU_IO -c 'write -P 0x11 0 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'read -P 0x11 0 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
diff --git a/tests/qemu-iotests/247 b/tests/qemu-iotests/247
index c853b73..87e37b3 100755
--- a/tests/qemu-iotests/247
+++ b/tests/qemu-iotests/247
@@ -29,7 +29,9 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f $TEST_IMG.[01234]
+ for img in "$TEST_IMG".[01234]; do
+ _rm_test_img "$img"
+ done
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/249 b/tests/qemu-iotests/249
index e4650ec..2b99c97 100755
--- a/tests/qemu-iotests/249
+++ b/tests/qemu-iotests/249
@@ -30,8 +30,8 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG.base"
- rm -f "$TEST_IMG.int"
+ _rm_test_img "$TEST_IMG.base"
+ _rm_test_img "$TEST_IMG.int"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/250 b/tests/qemu-iotests/250
index c9c0a84..9bb6b94 100755
--- a/tests/qemu-iotests/250
+++ b/tests/qemu-iotests/250
@@ -39,6 +39,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
+# This test does not make much sense with external data files
+_unsupported_imgopts data_file
# This test checks that qcow2_process_discards does not truncate a discard
# request > 2G.
@@ -55,9 +57,8 @@ disk_usage()
}
size=2100M
-IMGOPTS="cluster_size=1M,preallocation=metadata"
-_make_test_img $size
+_make_test_img -o "cluster_size=1M,preallocation=metadata" $size
$QEMU_IO -c 'discard 0 10M' -c 'discard 2090M 10M' \
-c 'write 2090M 10M' -c 'write 0 10M' "$TEST_IMG" | _filter_qemu_io
diff --git a/tests/qemu-iotests/252 b/tests/qemu-iotests/252
index f6c8f71..83280c1 100755
--- a/tests/qemu-iotests/252
+++ b/tests/qemu-iotests/252
@@ -29,7 +29,7 @@ status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
- rm -f "$TEST_IMG.base_new"
+ _rm_test_img "$TEST_IMG.base_new"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/qemu-iotests/255 b/tests/qemu-iotests/255
index 3632d50..0ba03d9 100755
--- a/tests/qemu-iotests/255
+++ b/tests/qemu-iotests/255
@@ -25,16 +25,6 @@ from iotests import imgfmt
iotests.verify_image_format(supported_fmts=['qcow2'])
-def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create',
- filters=[iotests.filter_qmp_testfiles],
- job_id='job0', options=options)
-
- if 'return' in result:
- assert result['return'] == {}
- vm.run_job('job0')
- iotests.log("")
-
iotests.log('Finishing a commit job with background reads')
iotests.log('============================================')
iotests.log('')
diff --git a/tests/qemu-iotests/261 b/tests/qemu-iotests/261
index fb96bcf..ddcb04f 100755
--- a/tests/qemu-iotests/261
+++ b/tests/qemu-iotests/261
@@ -40,14 +40,15 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
-# This tests qocw2-specific low-level functionality
+# This tests qcow2-specific low-level functionality
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
# (1) We create a v2 image that supports nothing but refcount_bits=16
# (2) We do some refcount management on our own which expects
# refcount_bits=16
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
+# As for data files, they do not support snapshots at all.
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
# Parameters:
# $1: image filename
diff --git a/tests/qemu-iotests/265 b/tests/qemu-iotests/265
index dce6f77..00f2ec7 100755
--- a/tests/qemu-iotests/265
+++ b/tests/qemu-iotests/265
@@ -41,7 +41,7 @@ _supported_os Linux
echo '--- Writing to the image ---'
# Reduce cluster size so we get more and quicker I/O
-IMGOPTS='cluster_size=4096' _make_test_img 1M
+_make_test_img -o 'cluster_size=4096' 1M
(for ((kb = 1024 - 4; kb >= 0; kb -= 4)); do \
echo "aio_write -P 42 $((kb + 1))k 2k"; \
done) \
diff --git a/tests/qemu-iotests/266 b/tests/qemu-iotests/266
index 5b35cd6..c353cf8 100755
--- a/tests/qemu-iotests/266
+++ b/tests/qemu-iotests/266
@@ -22,15 +22,6 @@ import iotests
from iotests import imgfmt
-def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
- filters=[iotests.filter_qmp_testfiles])
-
- if 'return' in result:
- assert result['return'] == {}
- vm.run_job('job0')
-
-
# Successful image creation (defaults)
def implicit_defaults(vm, file_path):
iotests.log("=== Successful image creation (defaults) ===")
@@ -40,9 +31,9 @@ def implicit_defaults(vm, file_path):
# (Close to 64 MB)
size = 8 * 964 * 17 * 512
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'protocol-node',
- 'size': size })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'protocol-node',
+ 'size': size })
# Successful image creation (explicit defaults)
@@ -54,11 +45,11 @@ def explicit_defaults(vm, file_path):
# (Close to 128 MB)
size = 16 * 964 * 17 * 512
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'protocol-node',
- 'size': size,
- 'subformat': 'dynamic',
- 'force-size': False })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'protocol-node',
+ 'size': size,
+ 'subformat': 'dynamic',
+ 'force-size': False })
# Successful image creation (non-default options)
@@ -69,11 +60,11 @@ def non_defaults(vm, file_path):
# Not representable in CHS (fine with force-size=True)
size = 1048576
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'protocol-node',
- 'size': size,
- 'subformat': 'fixed',
- 'force-size': True })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'protocol-node',
+ 'size': size,
+ 'subformat': 'fixed',
+ 'force-size': True })
# Size not representable in CHS with force-size=False
@@ -84,10 +75,10 @@ def non_chs_size_without_force(vm, file_path):
# Not representable in CHS (will not work with force-size=False)
size = 1048576
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'protocol-node',
- 'size': size,
- 'force-size': False })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'protocol-node',
+ 'size': size,
+ 'force-size': False })
# Zero size
@@ -95,9 +86,9 @@ def zero_size(vm, file_path):
iotests.log("=== Zero size===")
iotests.log("")
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'protocol-node',
- 'size': 0 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'protocol-node',
+ 'size': 0 })
# Maximum CHS size
@@ -105,9 +96,9 @@ def maximum_chs_size(vm, file_path):
iotests.log("=== Maximum CHS size===")
iotests.log("")
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'protocol-node',
- 'size': 16 * 65535 * 255 * 512 })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'protocol-node',
+ 'size': 16 * 65535 * 255 * 512 })
# Actual maximum size
@@ -115,10 +106,10 @@ def maximum_size(vm, file_path):
iotests.log("=== Actual maximum size===")
iotests.log("")
- blockdev_create(vm, { 'driver': imgfmt,
- 'file': 'protocol-node',
- 'size': 0xff000000 * 512,
- 'force-size': True })
+ vm.blockdev_create({ 'driver': imgfmt,
+ 'file': 'protocol-node',
+ 'size': 0xff000000 * 512,
+ 'force-size': True })
def main():
@@ -132,9 +123,9 @@ def main():
vm.launch()
iotests.log('--- Creating empty file ---')
- blockdev_create(vm, { 'driver': 'file',
- 'filename': file_path,
- 'size': 0 })
+ vm.blockdev_create({ 'driver': 'file',
+ 'filename': file_path,
+ 'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=file_path,
node_name='protocol-node',
diff --git a/tests/qemu-iotests/266.out b/tests/qemu-iotests/266.out
index b11953e..5a7d7d0 100644
--- a/tests/qemu-iotests/266.out
+++ b/tests/qemu-iotests/266.out
@@ -3,6 +3,7 @@
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
{"return": {}}
@@ -13,6 +14,7 @@
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
image: TEST_IMG
file format: IMGFMT
virtual size: 64 MiB (67125248 bytes)
@@ -23,6 +25,7 @@ cluster_size: 2097152
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
{"return": {}}
@@ -33,6 +36,7 @@ cluster_size: 2097152
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
image: TEST_IMG
file format: IMGFMT
virtual size: 128 MiB (134250496 bytes)
@@ -43,6 +47,7 @@ cluster_size: 2097152
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
{"return": {}}
@@ -53,6 +58,7 @@ cluster_size: 2097152
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
image: TEST_IMG
file format: IMGFMT
virtual size: 1 MiB (1048576 bytes)
@@ -62,6 +68,7 @@ virtual size: 1 MiB (1048576 bytes)
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
{"return": {}}
@@ -73,6 +80,7 @@ Job failed: The requested image size cannot be represented in CHS geometry
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
qemu-img: Could not open 'TEST_IMG': File too small for a VHD header
--- Creating empty file ---
@@ -80,6 +88,7 @@ qemu-img: Could not open 'TEST_IMG': File too small for a VHD header
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
{"return": {}}
@@ -90,6 +99,7 @@ qemu-img: Could not open 'TEST_IMG': File too small for a VHD header
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
image: TEST_IMG
file format: IMGFMT
virtual size: 0 B (0 bytes)
@@ -100,6 +110,7 @@ cluster_size: 2097152
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
{"return": {}}
@@ -110,6 +121,7 @@ cluster_size: 2097152
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
image: TEST_IMG
file format: IMGFMT
virtual size: 127 GiB (136899993600 bytes)
@@ -120,6 +132,7 @@ cluster_size: 2097152
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
{"return": {}}
@@ -130,6 +143,7 @@ cluster_size: 2097152
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
+
image: TEST_IMG
file format: IMGFMT
virtual size: 1.99 TiB (2190433320960 bytes)
diff --git a/tests/qemu-iotests/267 b/tests/qemu-iotests/267
index 170e173..c296877 100755
--- a/tests/qemu-iotests/267
+++ b/tests/qemu-iotests/267
@@ -40,9 +40,11 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
+_require_drivers copy-on-read
-# Internal snapshots are (currently) impossible with refcount_bits=1
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
+# Internal snapshots are (currently) impossible with refcount_bits=1,
+# and generally impossible with external data files
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
do_run_qemu()
{
@@ -68,7 +70,11 @@ size=128M
run_test()
{
- _make_test_img $size
+ if [ -n "$BACKING_FILE" ]; then
+ _make_test_img -b "$BACKING_FILE" $size
+ else
+ _make_test_img $size
+ fi
printf "savevm snap0\ninfo snapshots\nloadvm snap0\n" | run_qemu "$@" | _filter_date
}
@@ -119,12 +125,12 @@ echo
TEST_IMG="$TEST_IMG.base" _make_test_img $size
-IMGOPTS="backing_file=$TEST_IMG.base" \
+BACKING_FILE="$TEST_IMG.base" \
run_test -blockdev driver=file,filename="$TEST_IMG.base",node-name=backing-file \
-blockdev driver=file,filename="$TEST_IMG",node-name=file \
-blockdev driver=$IMGFMT,file=file,backing=backing-file,node-name=fmt
-IMGOPTS="backing_file=$TEST_IMG.base" \
+BACKING_FILE="$TEST_IMG.base" \
run_test -blockdev driver=file,filename="$TEST_IMG.base",node-name=backing-file \
-blockdev driver=$IMGFMT,file=backing-file,node-name=backing-fmt \
-blockdev driver=file,filename="$TEST_IMG",node-name=file \
@@ -141,7 +147,7 @@ echo
echo "=== -blockdev with NBD server on the backing file ==="
echo
-IMGOPTS="backing_file=$TEST_IMG.base" _make_test_img $size
+_make_test_img -b "$TEST_IMG.base" $size
cat <<EOF |
nbd_server_start unix:$SOCK_DIR/nbd
nbd_server_add -w backing-fmt
diff --git a/tests/qemu-iotests/273 b/tests/qemu-iotests/273
index 98a6725..00ff79b 100755
--- a/tests/qemu-iotests/273
+++ b/tests/qemu-iotests/273
@@ -37,6 +37,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
+# External data files would add nodes to the block graph, so it would
+# not match the reference output
+_unsupported_imgopts data_file
do_run_qemu()
{
@@ -48,7 +51,8 @@ do_run_qemu()
run_qemu()
{
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp |
- _filter_generated_node_ids | _filter_imgfmt | _filter_actual_image_size
+ _filter_generated_node_ids | _filter_imgfmt |
+ _filter_actual_image_size | _filter_img_info
}
TEST_IMG="$TEST_IMG.base" _make_test_img 64M
diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out
index c410fee..684b8d6 100644
--- a/tests/qemu-iotests/273.out
+++ b/tests/qemu-iotests/273.out
@@ -38,15 +38,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"cluster-size": 65536,
"format": "IMGFMT",
"actual-size": SIZE,
- "format-specific": {
- "type": "IMGFMT",
- "data": {
- "compat": "1.1",
- "lazy-refcounts": false,
- "refcount-bits": 16,
- "corrupt": false
- }
- },
"full-backing-filename": "TEST_DIR/t.IMGFMT.base",
"backing-filename": "TEST_DIR/t.IMGFMT.base",
"dirty-flag": false
@@ -57,15 +48,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"cluster-size": 65536,
"format": "IMGFMT",
"actual-size": SIZE,
- "format-specific": {
- "type": "IMGFMT",
- "data": {
- "compat": "1.1",
- "lazy-refcounts": false,
- "refcount-bits": 16,
- "corrupt": false
- }
- },
"full-backing-filename": "TEST_DIR/t.IMGFMT.mid",
"backing-filename": "TEST_DIR/t.IMGFMT.mid",
"dirty-flag": false
@@ -136,15 +118,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"cluster-size": 65536,
"format": "IMGFMT",
"actual-size": SIZE,
- "format-specific": {
- "type": "IMGFMT",
- "data": {
- "compat": "1.1",
- "lazy-refcounts": false,
- "refcount-bits": 16,
- "corrupt": false
- }
- },
"full-backing-filename": "TEST_DIR/t.IMGFMT.base",
"backing-filename": "TEST_DIR/t.IMGFMT.base",
"dirty-flag": false
diff --git a/tests/qemu-iotests/279 b/tests/qemu-iotests/279
new file mode 100755
index 0000000..6682376
--- /dev/null
+++ b/tests/qemu-iotests/279
@@ -0,0 +1,57 @@
+#!/usr/bin/env bash
+#
+# Test qemu-img --backing-chain --image-opts
+#
+# Copyright (C) 2019 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/>.
+#
+
+seq=$(basename "$0")
+echo "QA output created by $seq"
+
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+ rm -f "$TEST_IMG.mid"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# Backing files are required...
+_supported_fmt qcow qcow2 vmdk qed
+_supported_proto file
+_supported_os Linux
+
+TEST_IMG="$TEST_IMG.base" _make_test_img 64M
+TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base"
+_make_test_img -b "$TEST_IMG.mid"
+
+echo
+echo '== qemu-img info --backing-chain =='
+_img_info --backing-chain | _filter_img_info
+
+echo
+echo '== qemu-img info --backing-chain --image-opts =='
+TEST_IMG="driver=qcow2,file.driver=file,file.filename=$TEST_IMG" _img_info --backing-chain --image-opts | _filter_img_info
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/279.out b/tests/qemu-iotests/279.out
new file mode 100644
index 0000000..f4dc6c6
--- /dev/null
+++ b/tests/qemu-iotests/279.out
@@ -0,0 +1,35 @@
+QA output created by 279
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid
+
+== qemu-img info --backing-chain ==
+image: TEST_DIR/t.IMGFMT
+file format: IMGFMT
+virtual size: 64 MiB (67108864 bytes)
+backing file: TEST_DIR/t.IMGFMT.mid
+
+image: TEST_DIR/t.IMGFMT.mid
+file format: IMGFMT
+virtual size: 64 MiB (67108864 bytes)
+backing file: TEST_DIR/t.IMGFMT.base
+
+image: TEST_DIR/t.IMGFMT.base
+file format: IMGFMT
+virtual size: 64 MiB (67108864 bytes)
+
+== qemu-img info --backing-chain --image-opts ==
+image: TEST_DIR/t.IMGFMT
+file format: IMGFMT
+virtual size: 64 MiB (67108864 bytes)
+backing file: TEST_DIR/t.IMGFMT.mid
+
+image: TEST_DIR/t.IMGFMT.mid
+file format: IMGFMT
+virtual size: 64 MiB (67108864 bytes)
+backing file: TEST_DIR/t.IMGFMT.base
+
+image: TEST_DIR/t.IMGFMT.base
+file format: IMGFMT
+virtual size: 64 MiB (67108864 bytes)
+*** done
diff --git a/tests/qemu-iotests/280 b/tests/qemu-iotests/280
new file mode 100755
index 0000000..0b1fa8e
--- /dev/null
+++ b/tests/qemu-iotests/280
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2019 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: Kevin Wolf <kwolf@redhat.com>
+#
+# Test migration to file for taking an external snapshot with VM state.
+
+import iotests
+import os
+
+iotests.verify_image_format(supported_fmts=['qcow2'])
+iotests.verify_protocol(supported=['file'])
+iotests.verify_platform(['linux'])
+
+with iotests.FilePath('base') as base_path , \
+ iotests.FilePath('top') as top_path, \
+ iotests.VM() as vm:
+
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base_path, '64M')
+
+ iotests.log('=== Launch VM ===')
+ vm.add_object('iothread,id=iothread0')
+ vm.add_blockdev('file,filename=%s,node-name=base-file' % (base_path))
+ vm.add_blockdev('%s,file=base-file,node-name=base-fmt' % (iotests.imgfmt))
+ vm.add_device('virtio-blk,drive=base-fmt,iothread=iothread0,id=vda')
+ vm.launch()
+
+ vm.enable_migration_events('VM')
+
+ iotests.log('\n=== Migrate to file ===')
+ vm.qmp_log('migrate', uri='exec:cat > /dev/null')
+
+ with iotests.Timeout(3, 'Migration does not complete'):
+ vm.wait_migration()
+
+ iotests.log('\nVM is now stopped:')
+ iotests.log(vm.qmp('query-migrate')['return']['status'])
+ vm.qmp_log('query-status')
+
+ iotests.log('\n=== Create a snapshot of the disk image ===')
+ vm.blockdev_create({
+ 'driver': 'file',
+ 'filename': top_path,
+ 'size': 0,
+ })
+ vm.qmp_log('blockdev-add', node_name='top-file',
+ driver='file', filename=top_path,
+ filters=[iotests.filter_qmp_testfiles])
+
+ vm.blockdev_create({
+ 'driver': iotests.imgfmt,
+ 'file': 'top-file',
+ 'size': 1024 * 1024,
+ })
+ vm.qmp_log('blockdev-add', node_name='top-fmt',
+ driver=iotests.imgfmt, file='top-file')
+
+ vm.qmp_log('blockdev-snapshot', node='base-fmt', overlay='top-fmt')
+
+ iotests.log('\n=== Resume the VM and simulate a write request ===')
+ vm.qmp_log('cont')
+ iotests.log(vm.hmp_qemu_io('-d vda/virtio-backend', 'write 4k 4k'))
+
+ iotests.log('\n=== Commit it to the backing file ===')
+ result = vm.qmp_log('block-commit', job_id='job0', auto_dismiss=False,
+ device='top-fmt', top_node='top-fmt',
+ filters=[iotests.filter_qmp_testfiles])
+ if 'return' in result:
+ vm.run_job('job0')
diff --git a/tests/qemu-iotests/280.out b/tests/qemu-iotests/280.out
new file mode 100644
index 0000000..5d382fa
--- /dev/null
+++ b/tests/qemu-iotests/280.out
@@ -0,0 +1,50 @@
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+
+=== Launch VM ===
+Enabling migration QMP events on VM...
+{"return": {}}
+
+=== Migrate to file ===
+{"execute": "migrate", "arguments": {"uri": "exec:cat > /dev/null"}}
+{"return": {}}
+{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+
+VM is now stopped:
+completed
+{"execute": "query-status", "arguments": {}}
+{"return": {"running": false, "singlestep": false, "status": "postmigrate"}}
+
+=== Create a snapshot of the disk image ===
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-top", "size": 0}}}
+{"return": {}}
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
+{"return": {}}
+
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-top", "node-name": "top-file"}}
+{"return": {}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "top-file", "size": 1048576}}}
+{"return": {}}
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
+{"return": {}}
+
+{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": "top-file", "node-name": "top-fmt"}}
+{"return": {}}
+{"execute": "blockdev-snapshot", "arguments": {"node": "base-fmt", "overlay": "top-fmt"}}
+{"return": {}}
+
+=== Resume the VM and simulate a write request ===
+{"execute": "cont", "arguments": {}}
+{"return": {}}
+{"return": ""}
+
+=== Commit it to the backing file ===
+{"execute": "block-commit", "arguments": {"auto-dismiss": false, "device": "top-fmt", "job-id": "job0", "top-node": "top-fmt"}}
+{"return": {}}
+{"execute": "job-complete", "arguments": {"id": "job0"}}
+{"return": {}}
+{"data": {"device": "job0", "len": 65536, "offset": 65536, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"data": {"device": "job0", "len": 65536, "offset": 65536, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
+{"return": {}}
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
index 90970b0..2890785 100755
--- a/tests/qemu-iotests/check
+++ b/tests/qemu-iotests/check
@@ -587,13 +587,13 @@ export QEMU_PROG="$(type -p "$QEMU_PROG")"
case "$QEMU_PROG" in
*qemu-system-arm|*qemu-system-aarch64)
- export QEMU_OPTIONS="-nodefaults -display none -machine virt,accel=qtest"
+ export QEMU_OPTIONS="-nodefaults -display none -machine virt -accel qtest"
;;
*qemu-system-tricore)
- export QEMU_OPTIONS="-nodefaults -display none -machine tricore_testboard,accel=qtest"
+ export QEMU_OPTIONS="-nodefaults -display none -machine tricore_testboard -accel qtest"
;;
*)
- export QEMU_OPTIONS="-nodefaults -display none -machine accel=qtest"
+ export QEMU_OPTIONS="-nodefaults -display none -accel qtest"
;;
esac
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index 5367dee..3f8ee3e 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -122,7 +122,13 @@ _filter_actual_image_size()
# replace driver-specific options in the "Formatting..." line
_filter_img_create()
{
- $SED -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
+ data_file_filter=()
+ if data_file=$(_get_data_file "$TEST_IMG"); then
+ data_file_filter=(-e "s# data_file=$data_file##")
+ fi
+
+ $SED "${data_file_filter[@]}" \
+ -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
-e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
-e "s#$TEST_DIR#TEST_DIR#g" \
-e "s#$SOCK_DIR#SOCK_DIR#g" \
@@ -209,9 +215,22 @@ _filter_img_info()
# human and json output
_filter_qemu_img_map()
{
+ # Assuming the data_file value in $IMGOPTS contains a '$TEST_IMG',
+ # create a filter that replaces the data file name by $TEST_IMG.
+ # Example:
+ # In $IMGOPTS: 'data_file=$TEST_IMG.data_file'
+ # Then data_file_pattern == '\(.*\).data_file'
+ # And data_file_filter == -e 's#\(.*\).data_file#\1#
+ data_file_filter=()
+ if data_file_pattern=$(_get_data_file '\\(.*\\)'); then
+ data_file_filter=(-e "s#$data_file_pattern#\\1#")
+ fi
+
$SED -e 's/\([0-9a-fx]* *[0-9a-fx]* *\)[0-9a-fx]* */\1/g' \
-e 's/"offset": [0-9]\+/"offset": OFFSET/g' \
- -e 's/Mapped to *//' | _filter_testdir | _filter_imgfmt
+ -e 's/Mapped to *//' \
+ "${data_file_filter[@]}" \
+ | _filter_testdir | _filter_imgfmt
}
_filter_nbd()
@@ -232,5 +251,29 @@ _filter_qmp_empty_return()
grep -v '{"return": {}}'
}
+_filter_json_filename()
+{
+ $PYTHON -c 'import sys
+result, *fnames = sys.stdin.read().split("json:{")
+depth = 0
+for fname in fnames:
+ depth += 1 # For the opening brace in the split separator
+ for chr_i, chr in enumerate(fname):
+ if chr == "{":
+ depth += 1
+ elif chr == "}":
+ depth -= 1
+ if depth == 0:
+ break
+
+ # json:{} filenames may be nested; filter out everything from
+ # inside the outermost one
+ if depth == 0:
+ chr_i += 1 # First character past the filename
+ result += "json:{ /* filtered */ }" + fname[chr_i:]
+
+sys.stdout.write(result)'
+}
+
# make sure this script returns success
true
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 0cc8acc..d088392 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -217,7 +217,8 @@ if [ "$IMGOPTSSYNTAX" = "true" ]; then
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.type=unix,file.path=$SOCKDIR/nbd"
+ TEST_IMG="$DRIVER,file.driver=nbd,file.type=unix"
+ TEST_IMG="$TEST_IMG,file.path=$SOCK_DIR/nbd"
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"
@@ -297,17 +298,32 @@ _stop_nbd_server()
fi
}
+# Gets the data_file value from IMGOPTS and replaces the '$TEST_IMG'
+# pattern by '$1'
+# Caution: The replacement is done with sed, so $1 must be escaped
+# properly. (The delimiter is '#'.)
+_get_data_file()
+{
+ if ! echo "$IMGOPTS" | grep -q 'data_file='; then
+ return 1
+ fi
+
+ echo "$IMGOPTS" | sed -e 's/.*data_file=\([^,]*\).*/\1/' \
+ | sed -e "s#\\\$TEST_IMG#$1#"
+}
+
_make_test_img()
{
# extra qemu-img options can be added by tests
# at least one argument (the image size) needs to be added
local extra_img_options=""
- local image_size=$*
local optstr=""
local img_name=""
local use_backing=0
local backing_file=""
local object_options=""
+ local opts_param=false
+ local misc_params=()
if [ -n "$TEST_IMG_FILE" ]; then
img_name=$TEST_IMG_FILE
@@ -316,18 +332,43 @@ _make_test_img()
fi
if [ -n "$IMGOPTS" ]; then
- optstr=$(_optstr_add "$optstr" "$IMGOPTS")
+ imgopts_expanded=$(echo "$IMGOPTS" | sed -e "s#\\\$TEST_IMG#$img_name#")
+ optstr=$(_optstr_add "$optstr" "$imgopts_expanded")
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
- backing_file=$2
- image_size=$3
- fi
+ for param; do
+ if [ "$use_backing" = "1" -a -z "$backing_file" ]; then
+ backing_file=$param
+ continue
+ elif $opts_param; then
+ optstr=$(_optstr_add "$optstr" "$param")
+ opts_param=false
+ continue
+ fi
+
+ case "$param" in
+ -b)
+ use_backing=1
+ ;;
+
+ -o)
+ opts_param=true
+ ;;
+
+ --no-opts)
+ optstr=""
+ ;;
+
+ *)
+ misc_params=("${misc_params[@]}" "$param")
+ ;;
+ esac
+ done
+
if [ \( "$IMGFMT" = "qcow2" -o "$IMGFMT" = "qed" \) -a -n "$CLUSTER_SIZE" ]; then
optstr=$(_optstr_add "$optstr" "cluster_size=$CLUSTER_SIZE")
fi
@@ -343,9 +384,9 @@ _make_test_img()
# XXX(hch): have global image options?
(
if [ $use_backing = 1 ]; then
- $QEMU_IMG create $object_options -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" "${misc_params[@]}" 2>&1
else
- $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1
+ $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" "${misc_params[@]}" 2>&1
fi
) | _filter_img_create
@@ -374,6 +415,11 @@ _rm_test_img()
# Remove all the extents for vmdk
"$QEMU_IMG" info "$img" 2>/dev/null | grep 'filename:' | cut -f 2 -d: \
| xargs -I {} rm -f "{}"
+ elif [ "$IMGFMT" = "qcow2" ]; then
+ # Remove external data file
+ if data_file=$(_get_data_file "$img"); then
+ rm -f "$data_file"
+ fi
fi
rm -f "$img"
}
@@ -643,5 +689,15 @@ _require_drivers()
done
}
+# Check that we have a file system that allows huge (but very sparse) files
+#
+_require_large_file()
+{
+ if ! truncate --size="$1" "$TEST_IMG"; then
+ _notrun "file system on $TEST_DIR does not support large enough files"
+ fi
+ rm "$TEST_IMG"
+}
+
# make sure this script returns success
true
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 6b10a6a..cb2b789 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -286,3 +286,5 @@
272 rw
273 backing quick
277 rw quick
+279 rw backing quick
+280 rw migration quick
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index df07089..13fd8b5 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -162,6 +162,11 @@ def qemu_io(*args):
sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args)))
return subp.communicate()[0]
+def qemu_io_log(*args):
+ result = qemu_io(*args)
+ log(result, filters=[filter_testfiles, filter_qemu_io])
+ return result
+
def qemu_io_silent(*args):
'''Run qemu-io and return the exit code, suppressing stdout'''
args = qemu_io_args + list(args)
@@ -604,7 +609,7 @@ class VM(qtest.QEMUQtestMachine):
]
error = None
while True:
- ev = filter_qmp_event(self.events_wait(events))
+ ev = filter_qmp_event(self.events_wait(events, timeout=wait))
if ev['event'] != 'JOB_STATUS_CHANGE':
if use_log:
log(ev)
@@ -617,6 +622,8 @@ class VM(qtest.QEMUQtestMachine):
error = j['error']
if use_log:
log('Job failed: %s' % (j['error']))
+ elif status == 'ready':
+ self.qmp_log('job-complete', id=job)
elif status == 'pending' and not auto_finalize:
if pre_finalize:
pre_finalize()
@@ -636,6 +643,22 @@ class VM(qtest.QEMUQtestMachine):
elif status == 'null':
return error
+ # Returns None on success, and an error string on failure
+ def blockdev_create(self, options, job_id='job0', filters=None):
+ if filters is None:
+ filters = [filter_qmp_testfiles]
+ result = self.qmp_log('blockdev-create', filters=filters,
+ job_id=job_id, options=options)
+
+ if 'return' in result:
+ assert result['return'] == {}
+ job_result = self.run_job(job_id)
+ else:
+ job_result = result['error']
+
+ log("")
+ return job_result
+
def enable_migration_events(self, name):
log('Enabling migration QMP events on %s...' % name)
log(self.qmp('migrate-set-capabilities', capabilities=[
@@ -788,15 +811,20 @@ class QMPTestCase(unittest.TestCase):
self.assert_no_active_block_jobs()
return result
- def wait_until_completed(self, drive='drive0', check_offset=True, wait=60.0):
+ def wait_until_completed(self, drive='drive0', check_offset=True, wait=60.0,
+ error=None):
'''Wait for a block job to finish, returning the event'''
while True:
for event in self.vm.get_qmp_events(wait=wait):
if event['event'] == 'BLOCK_JOB_COMPLETED':
self.assert_qmp(event, 'data/device', drive)
- self.assert_qmp_absent(event, 'data/error')
- if check_offset:
- self.assert_qmp(event, 'data/offset', event['data']['len'])
+ if error is None:
+ self.assert_qmp_absent(event, 'data/error')
+ if check_offset:
+ self.assert_qmp(event, 'data/offset',
+ event['data']['len'])
+ else:
+ self.assert_qmp(event, 'data/error', error)
self.assert_no_active_block_jobs()
return event
elif event['event'] == 'JOB_STATUS_CHANGE':
@@ -814,7 +842,8 @@ class QMPTestCase(unittest.TestCase):
self.assert_qmp(event, 'data/type', 'mirror')
self.assert_qmp(event, 'data/offset', event['data']['len'])
- def complete_and_wait(self, drive='drive0', wait_ready=True):
+ def complete_and_wait(self, drive='drive0', wait_ready=True,
+ completion_error=None):
'''Complete a block job and wait for it to finish'''
if wait_ready:
self.wait_ready(drive=drive)
@@ -822,7 +851,7 @@ class QMPTestCase(unittest.TestCase):
result = self.vm.qmp('block-job-complete', device=drive)
self.assert_qmp(result, 'return', {})
- event = self.wait_until_completed(drive=drive)
+ event = self.wait_until_completed(drive=drive, error=completion_error)
self.assert_qmp(event, 'data/type', 'mirror')
def pause_wait(self, job_id='job0'):
diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
index b392972..91e4420 100755
--- a/tests/qemu-iotests/qcow2.py
+++ b/tests/qemu-iotests/qcow2.py
@@ -42,9 +42,9 @@ class QcowHeader:
[ uint64_t, '%#x', 'snapshot_offset' ],
# Version 3 header fields
- [ uint64_t, '%#x', 'incompatible_features' ],
- [ uint64_t, '%#x', 'compatible_features' ],
- [ uint64_t, '%#x', 'autoclear_features' ],
+ [ uint64_t, 'mask', 'incompatible_features' ],
+ [ uint64_t, 'mask', 'compatible_features' ],
+ [ uint64_t, 'mask', 'autoclear_features' ],
[ uint32_t, '%d', 'refcount_order' ],
[ uint32_t, '%d', 'header_length' ],
];
@@ -130,7 +130,17 @@ class QcowHeader:
def dump(self):
for f in QcowHeader.fields:
- print("%-25s" % f[2], f[1] % self.__dict__[f[2]])
+ value = self.__dict__[f[2]]
+ if f[1] == 'mask':
+ bits = []
+ for bit in range(64):
+ if value & (1 << bit):
+ bits.append(bit)
+ value_str = str(bits)
+ else:
+ value_str = f[1] % value
+
+ print("%-25s" % f[2], value_str)
print("")
def dump_extensions(self):
@@ -154,6 +164,10 @@ def cmd_dump_header(fd):
h.dump()
h.dump_extensions()
+def cmd_dump_header_exts(fd):
+ h = QcowHeader(fd)
+ h.dump_extensions()
+
def cmd_set_header(fd, name, value):
try:
value = int(value, 0)
@@ -230,6 +244,7 @@ def cmd_set_feature_bit(fd, group, bit):
cmds = [
[ 'dump-header', cmd_dump_header, 0, 'Dump image header and header extensions' ],
+ [ 'dump-header-exts', cmd_dump_header_exts, 0, 'Dump image header extensions' ],
[ 'set-header', cmd_set_header, 2, 'Set a field in the header'],
[ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ],
[ 'add-header-ext-stdio', cmd_add_header_ext_stdio, 1, 'Add a header extension, data from stdin' ],
diff --git a/tests/tcg/Makefile.prereqs b/tests/tcg/Makefile.prereqs
index 7494b31..9a29604 100644
--- a/tests/tcg/Makefile.prereqs
+++ b/tests/tcg/Makefile.prereqs
@@ -13,6 +13,6 @@ DOCKER_IMAGE:=
ifneq ($(DOCKER_IMAGE),)
build-tcg-tests-$(PROBE_TARGET): docker-image-$(DOCKER_IMAGE)
+endif
$(BUILD_DIR)/tests/tcg/config_$(PROBE_TARGET).mak: config-host.mak
config-host.mak: $(SRC_PATH)/tests/tcg/configure.sh
-endif
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
index 6c4a471..210e683 100755
--- a/tests/tcg/configure.sh
+++ b/tests/tcg/configure.sh
@@ -36,8 +36,10 @@ TMPC="${TMPDIR1}/qemu-conf.c"
TMPE="${TMPDIR1}/qemu-conf.exe"
container="no"
-if has "docker" || has "podman"; then
- container=$($python $source_path/tests/docker/docker.py probe)
+if test $use_containers = "yes"; then
+ if has "docker" || has "podman"; then
+ container=$($python $source_path/tests/docker/docker.py probe)
+ fi
fi
# cross compilers defaults, can be overridden with --cross-cc-ARCH
diff --git a/tests/test-keyval.c b/tests/test-keyval.c
index 09b0ae3..e331a84 100644
--- a/tests/test-keyval.c
+++ b/tests/test-keyval.c
@@ -478,7 +478,7 @@ static void test_keyval_visit_size(void)
visit_free(v);
/* Trailing crap */
- qdict = keyval_parse("sz1=16E,sz2=16Gi", NULL, &error_abort);
+ qdict = keyval_parse("sz1=0Z,sz2=16Gi", NULL, &error_abort);
v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
qobject_unref(qdict);
visit_start_struct(v, NULL, NULL, 0, &error_abort);
diff --git a/tests/test-logging.c b/tests/test-logging.c
index a12585f..1e646f0 100644
--- a/tests/test-logging.c
+++ b/tests/test-logging.c
@@ -108,6 +108,82 @@ static void test_parse_path(gconstpointer data)
error_free_or_abort(&err);
}
+static void test_logfile_write(gconstpointer data)
+{
+ QemuLogFile *logfile;
+ QemuLogFile *logfile2;
+ gchar const *dir = data;
+ Error *err = NULL;
+ g_autofree gchar *file_path;
+ g_autofree gchar *file_path1;
+ FILE *orig_fd;
+
+ /*
+ * Before starting test, set log flags, to ensure the file gets
+ * opened below with the call to qemu_set_log_filename().
+ * In cases where a logging backend other than log is used,
+ * this is needed.
+ */
+ qemu_set_log(CPU_LOG_TB_OUT_ASM);
+ file_path = g_build_filename(dir, "qemu_test_log_write0.log", NULL);
+ file_path1 = g_build_filename(dir, "qemu_test_log_write1.log", NULL);
+
+ /*
+ * Test that even if an open file handle is changed,
+ * our handle remains valid due to RCU.
+ */
+ qemu_set_log_filename(file_path, &err);
+ g_assert(!err);
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ orig_fd = logfile->fd;
+ g_assert(logfile && logfile->fd);
+ fprintf(logfile->fd, "%s 1st write to file\n", __func__);
+ fflush(logfile->fd);
+
+ /* Change the logfile and ensure that the handle is still valid. */
+ qemu_set_log_filename(file_path1, &err);
+ g_assert(!err);
+ logfile2 = atomic_rcu_read(&qemu_logfile);
+ g_assert(logfile->fd == orig_fd);
+ g_assert(logfile2->fd != logfile->fd);
+ fprintf(logfile->fd, "%s 2nd write to file\n", __func__);
+ fflush(logfile->fd);
+ rcu_read_unlock();
+}
+
+static void test_logfile_lock(gconstpointer data)
+{
+ FILE *logfile;
+ gchar const *dir = data;
+ Error *err = NULL;
+ g_autofree gchar *file_path;
+
+ file_path = g_build_filename(dir, "qemu_test_logfile_lock0.log", NULL);
+
+ /*
+ * Test the use of the logfile lock, such
+ * that even if an open file handle is closed,
+ * our handle remains valid for use due to RCU.
+ */
+ qemu_set_log_filename(file_path, &err);
+ logfile = qemu_log_lock();
+ g_assert(logfile);
+ fprintf(logfile, "%s 1st write to file\n", __func__);
+ fflush(logfile);
+
+ /*
+ * Initiate a close file and make sure our handle remains
+ * valid since we still have the logfile lock.
+ */
+ qemu_log_close();
+ fprintf(logfile, "%s 2nd write to file\n", __func__);
+ fflush(logfile);
+ qemu_log_unlock(logfile);
+
+ g_assert(!err);
+}
+
/* Remove a directory and all its entries (non-recursive). */
static void rmdir_full(gchar const *root)
{
@@ -134,6 +210,10 @@ int main(int argc, char **argv)
g_test_add_func("/logging/parse_range", test_parse_range);
g_test_add_data_func("/logging/parse_path", tmp_path, test_parse_path);
+ g_test_add_data_func("/logging/logfile_write_path",
+ tmp_path, test_logfile_write);
+ g_test_add_data_func("/logging/logfile_lock_path",
+ tmp_path, test_logfile_lock);
rc = g_test_run();
diff --git a/tests/test-util-filemonitor.c b/tests/test-util-filemonitor.c
index 301cd2d..45009c6 100644
--- a/tests/test-util-filemonitor.c
+++ b/tests/test-util-filemonitor.c
@@ -406,11 +406,22 @@ test_file_monitor_events(void)
char *pathdst = NULL;
QFileMonitorTestData data;
GHashTable *ids = g_hash_table_new(g_int64_hash, g_int64_equal);
+ char *travis_arch;
qemu_mutex_init(&data.lock);
data.records = NULL;
/*
+ * This test does not work on Travis LXD containers since some
+ * syscalls are blocked in that environment.
+ */
+ travis_arch = getenv("TRAVIS_ARCH");
+ if (travis_arch && !g_str_equal(travis_arch, "x86_64")) {
+ g_test_skip("Test does not work on non-x86 Travis containers.");
+ return;
+ }
+
+ /*
* The file monitor needs the main loop running in
* order to receive events from inotify. We must
* thus spawn a background thread to run an event
diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
index fea348e..9e7c46a 100644
--- a/tests/vm/Makefile.include
+++ b/tests/vm/Makefile.include
@@ -34,6 +34,7 @@ vm-help vm-test:
@echo " DEBUG=1 - Enable verbose output on host and interactive debugging"
@echo " V=1 - Enable verbose ouput on host and guest commands"
@echo " QEMU=/path/to/qemu - Change path to QEMU binary"
+ @echo " QEMU_IMG=/path/to/qemu-img - Change path to qemu-img tool"
vm-build-all: $(addprefix vm-build-, $(IMAGES))
diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index 53b9515..ed5dd4f 100755
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -152,6 +152,11 @@ class BaseVM(object):
def build_image(self, img):
raise NotImplementedError
+ def exec_qemu_img(self, *args):
+ cmd = [os.environ.get("QEMU_IMG", "qemu-img")]
+ cmd.extend(list(args))
+ subprocess.check_call(cmd)
+
def add_source_dir(self, src_dir):
name = "data-" + hashlib.sha1(src_dir.encode("utf-8")).hexdigest()[:5]
tarfile = os.path.join(self._tmpdir, name + ".tar")
diff --git a/tests/vm/centos b/tests/vm/centos
index b9e851f..f2f0bef 100755
--- a/tests/vm/centos
+++ b/tests/vm/centos
@@ -68,7 +68,7 @@ class CentosVM(basevm.BaseVM):
sys.stderr.write("Extracting the image...\n")
subprocess.check_call(["ln", "-f", cimg, img_tmp + ".xz"])
subprocess.check_call(["xz", "--keep", "-dvf", img_tmp + ".xz"])
- subprocess.check_call(["qemu-img", "resize", img_tmp, "50G"])
+ self.exec_qemu_img("resize", img_tmp, "50G")
self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()])
self.wait_ssh()
self.ssh_root_check("touch /etc/cloud/cloud-init.disabled")
diff --git a/tests/vm/fedora b/tests/vm/fedora
index 7fec147..8e270fc 100755
--- a/tests/vm/fedora
+++ b/tests/vm/fedora
@@ -74,9 +74,7 @@ class FedoraVM(basevm.BaseVM):
self.print_step("Preparing iso and disk image")
subprocess.check_call(["cp", "-f", cimg, iso])
- subprocess.check_call(["qemu-img", "create", "-f", "qcow2",
- img_tmp, self.size])
-
+ self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
self.print_step("Booting installer")
self.boot(img_tmp, extra_args = [
"-bios", "pc-bios/bios-256k.bin",
diff --git a/tests/vm/freebsd b/tests/vm/freebsd
index 2a19461..1825cc5 100755
--- a/tests/vm/freebsd
+++ b/tests/vm/freebsd
@@ -82,8 +82,7 @@ class FreeBSDVM(basevm.BaseVM):
self.print_step("Preparing iso and disk image")
subprocess.check_call(["cp", "-f", cimg, iso_xz])
subprocess.check_call(["xz", "-dvf", iso_xz])
- subprocess.check_call(["qemu-img", "create", "-f", "qcow2",
- img_tmp, self.size])
+ self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
self.print_step("Booting installer")
self.boot(img_tmp, extra_args = [
diff --git a/tests/vm/netbsd b/tests/vm/netbsd
index 611e6cc..ec6f356 100755
--- a/tests/vm/netbsd
+++ b/tests/vm/netbsd
@@ -77,8 +77,7 @@ class NetBSDVM(basevm.BaseVM):
self.print_step("Preparing iso and disk image")
subprocess.check_call(["ln", "-f", cimg, iso])
- subprocess.check_call(["qemu-img", "create", "-f", "qcow2",
- img_tmp, self.size])
+ self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
self.print_step("Booting installer")
self.boot(img_tmp, extra_args = [
diff --git a/tests/vm/openbsd b/tests/vm/openbsd
index b92c39f..6df5162 100755
--- a/tests/vm/openbsd
+++ b/tests/vm/openbsd
@@ -73,8 +73,7 @@ class OpenBSDVM(basevm.BaseVM):
self.print_step("Preparing iso and disk image")
subprocess.check_call(["cp", "-f", cimg, iso])
- subprocess.check_call(["qemu-img", "create", "-f", "qcow2",
- img_tmp, self.size])
+ self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
self.print_step("Booting installer")
self.boot(img_tmp, extra_args = [
diff --git a/tests/vm/ubuntu.i386 b/tests/vm/ubuntu.i386
index f611bebd..3834cd7 100755
--- a/tests/vm/ubuntu.i386
+++ b/tests/vm/ubuntu.i386
@@ -70,7 +70,7 @@ class UbuntuX86VM(basevm.BaseVM):
sha256sum="28969840626d1ea80bb249c08eef1a4533e8904aa51a327b40f37ac4b4ff04ef")
img_tmp = img + ".tmp"
subprocess.check_call(["cp", "-f", cimg, img_tmp])
- subprocess.check_call(["qemu-img", "resize", img_tmp, "50G"])
+ self.exec_qemu_img("resize", img_tmp, "50G")
self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()])
self.wait_ssh()
self.ssh_root_check("touch /etc/cloud/cloud-init.disabled")
diff --git a/trace/control.c b/trace/control.c
index d9cafc1..0fb8124 100644
--- a/trace/control.c
+++ b/trace/control.c
@@ -98,38 +98,6 @@ TraceEvent *trace_event_name(const char *name)
return NULL;
}
-static bool pattern_glob(const char *pat, const char *ev)
-{
- while (*pat != '\0' && *ev != '\0') {
- if (*pat == *ev) {
- pat++;
- ev++;
- }
- else if (*pat == '*') {
- if (pattern_glob(pat, ev+1)) {
- return true;
- } else if (pattern_glob(pat+1, ev)) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
- }
-
- while (*pat == '*') {
- pat++;
- }
-
- if (*pat == '\0' && *ev == '\0') {
- return true;
- } else {
- return false;
- }
-}
-
-
void trace_event_iter_init(TraceEventIter *iter, const char *pattern)
{
iter->event = 0;
@@ -148,8 +116,7 @@ TraceEvent *trace_event_iter_next(TraceEventIter *iter)
iter->group++;
}
if (!iter->pattern ||
- pattern_glob(iter->pattern,
- trace_event_get_name(ev))) {
+ g_pattern_match_simple(iter->pattern, trace_event_get_name(ev))) {
return ev;
}
}
diff --git a/ui/console.c b/ui/console.c
index 82d1dda..ac79d67 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -33,6 +33,7 @@
#include "chardev/char-fe.h"
#include "trace.h"
#include "exec/memory.h"
+#include "io/channel-file.h"
#define DEFAULT_BACKSCROLL 512
#define CONSOLE_CURSOR_PERIOD 500
@@ -193,6 +194,7 @@ static void dpy_refresh(DisplayState *s);
static DisplayState *get_alloc_displaystate(void);
static void text_console_update_cursor_timer(void);
static void text_console_update_cursor(void *opaque);
+static bool ppm_save(int fd, DisplaySurface *ds, Error **errp);
static void gui_update(void *opaque)
{
@@ -259,13 +261,22 @@ static void gui_setup_refresh(DisplayState *ds)
ds->have_text = have_text;
}
+void graphic_hw_update_done(QemuConsole *con)
+{
+}
+
void graphic_hw_update(QemuConsole *con)
{
+ bool async = false;
if (!con) {
con = active_console;
}
if (con && con->hw_ops->gfx_update) {
con->hw_ops->gfx_update(con->hw);
+ async = con->hw_ops->gfx_update_async;
+ }
+ if (!async) {
+ graphic_hw_update_done(con);
}
}
@@ -299,52 +310,34 @@ void graphic_hw_invalidate(QemuConsole *con)
}
}
-static void ppm_save(const char *filename, DisplaySurface *ds,
- Error **errp)
+static bool ppm_save(int fd, DisplaySurface *ds, Error **errp)
{
int width = pixman_image_get_width(ds->image);
int height = pixman_image_get_height(ds->image);
- int fd;
- FILE *f;
+ g_autoptr(Object) ioc = OBJECT(qio_channel_file_new_fd(fd));
+ g_autofree char *header = NULL;
+ g_autoptr(pixman_image_t) linebuf = NULL;
int y;
- int ret;
- pixman_image_t *linebuf;
- trace_ppm_save(filename, ds);
- fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
- if (fd == -1) {
- error_setg(errp, "failed to open file '%s': %s", filename,
- strerror(errno));
- return;
- }
- f = fdopen(fd, "wb");
- ret = fprintf(f, "P6\n%d %d\n%d\n", width, height, 255);
- if (ret < 0) {
- linebuf = NULL;
- goto write_err;
+ trace_ppm_save(fd, ds);
+
+ header = g_strdup_printf("P6\n%d %d\n%d\n", width, height, 255);
+ if (qio_channel_write_all(QIO_CHANNEL(ioc),
+ header, strlen(header), errp) < 0) {
+ return false;
}
+
linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width);
for (y = 0; y < height; y++) {
qemu_pixman_linebuf_fill(linebuf, ds->image, width, 0, y);
- clearerr(f);
- ret = fwrite(pixman_image_get_data(linebuf), 1,
- pixman_image_get_stride(linebuf), f);
- (void)ret;
- if (ferror(f)) {
- goto write_err;
+ if (qio_channel_write_all(QIO_CHANNEL(ioc),
+ (char *)pixman_image_get_data(linebuf),
+ pixman_image_get_stride(linebuf), errp) < 0) {
+ return false;
}
}
-out:
- qemu_pixman_image_unref(linebuf);
- fclose(f);
- return;
-
-write_err:
- error_setg(errp, "failed to write to file '%s': %s", filename,
- strerror(errno));
- unlink(filename);
- goto out;
+ return true;
}
void qmp_screendump(const char *filename, bool has_device, const char *device,
@@ -352,6 +345,7 @@ void qmp_screendump(const char *filename, bool has_device, const char *device,
{
QemuConsole *con;
DisplaySurface *surface;
+ int fd;
if (has_device) {
con = qemu_console_lookup_by_device_name(device, has_head ? head : 0,
@@ -378,7 +372,16 @@ void qmp_screendump(const char *filename, bool has_device, const char *device,
return;
}
- ppm_save(filename, surface, errp);
+ fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ if (fd == -1) {
+ error_setg(errp, "failed to open file '%s': %s", filename,
+ strerror(errno));
+ return;
+ }
+
+ if (!ppm_save(fd, surface, errp)) {
+ qemu_unlink(filename);
+ }
}
void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata)
diff --git a/ui/trace-events b/ui/trace-events
index 63de72a..0dcda39 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -15,7 +15,7 @@ displaysurface_create_pixman(void *display_surface) "surface=%p"
displaysurface_free(void *display_surface) "surface=%p"
displaychangelistener_register(void *dcl, const char *name) "%p [ %s ]"
displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]"
-ppm_save(const char *filename, void *display_surface) "%s surface=%p"
+ppm_save(int fd, void *display_surface) "fd=%d surface=%p"
# gtk.c
# gtk-gl-area.c
diff --git a/util/Makefile.objs b/util/Makefile.objs
index 63599d6..11262aa 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -56,3 +56,6 @@ util-obj-$(call lnot,$(CONFIG_INOTIFY1)) += filemonitor-stub.o
util-obj-$(CONFIG_LINUX) += vfio-helpers.o
util-obj-$(CONFIG_POSIX) += drm.o
util-obj-y += guest-random.o
+util-obj-$(CONFIG_GIO) += dbus.o
+dbus.o-cflags = $(GIO_CFLAGS)
+dbus.o-libs = $(GIO_LIBS)
diff --git a/util/cutils.c b/util/cutils.c
index 2380165..36ce712 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -542,7 +542,7 @@ int qemu_strtoul(const char *nptr, const char **endptr, int base,
* Convert string @nptr to an int64_t.
*
* Works like qemu_strtol(), except it stores INT64_MAX on overflow,
- * and INT_MIN on underflow.
+ * and INT64_MIN on underflow.
*/
int qemu_strtoi64(const char *nptr, const char **endptr, int base,
int64_t *result)
@@ -557,8 +557,9 @@ int qemu_strtoi64(const char *nptr, const char **endptr, int base,
return -EINVAL;
}
+ /* This assumes int64_t is long long TODO relax */
+ QEMU_BUILD_BUG_ON(sizeof(int64_t) != sizeof(long long));
errno = 0;
- /* FIXME This assumes int64_t is long long */
*result = strtoll(nptr, &ep, base);
return check_strtox_error(nptr, ep, endptr, errno);
}
@@ -581,8 +582,9 @@ int qemu_strtou64(const char *nptr, const char **endptr, int base,
return -EINVAL;
}
+ /* This assumes uint64_t is unsigned long long TODO relax */
+ QEMU_BUILD_BUG_ON(sizeof(uint64_t) != sizeof(unsigned long long));
errno = 0;
- /* FIXME This assumes uint64_t is unsigned long long */
*result = strtoull(nptr, &ep, base);
/* Windows returns 1 for negative out-of-range values. */
if (errno == ERANGE) {
diff --git a/util/dbus.c b/util/dbus.c
new file mode 100644
index 0000000..9099dc5
--- /dev/null
+++ b/util/dbus.c
@@ -0,0 +1,57 @@
+/*
+ * Helpers for using D-Bus
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/dbus.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+
+/*
+ * qemu_dbus_get_queued_owners() - return the list of queued unique names
+ * @connection: A GDBusConnection
+ * @name: a service name
+ *
+ * Return: a GStrv of unique names, or NULL on failure.
+ */
+GStrv
+qemu_dbus_get_queued_owners(GDBusConnection *connection, const char *name,
+ Error **errp)
+{
+ g_autoptr(GDBusProxy) proxy = NULL;
+ g_autoptr(GVariant) result = NULL;
+ g_autoptr(GVariant) child = NULL;
+ g_autoptr(GError) err = NULL;
+
+ proxy = g_dbus_proxy_new_sync(connection, G_DBUS_PROXY_FLAGS_NONE, NULL,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ NULL, &err);
+ if (!proxy) {
+ error_setg(errp, "Failed to create DBus proxy: %s", err->message);
+ return NULL;
+ }
+
+ result = g_dbus_proxy_call_sync(proxy, "ListQueuedOwners",
+ g_variant_new("(s)", name),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ -1, NULL, &err);
+ if (!result) {
+ if (g_error_matches(err,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_NAME_HAS_NO_OWNER)) {
+ return g_new0(char *, 1);
+ }
+ error_setg(errp, "Failed to call ListQueuedOwners: %s", err->message);
+ return NULL;
+ }
+
+ child = g_variant_get_child_value(result, 0);
+ return g_variant_dup_strv(child, NULL);
+}
diff --git a/util/log.c b/util/log.c
index 1ca1305..867264d 100644
--- a/util/log.c
+++ b/util/log.c
@@ -24,9 +24,11 @@
#include "qapi/error.h"
#include "qemu/cutils.h"
#include "trace/control.h"
+#include "qemu/thread.h"
static char *logfilename;
-FILE *qemu_logfile;
+static QemuMutex qemu_logfile_mutex;
+QemuLogFile *qemu_logfile;
int qemu_loglevel;
static int log_append = 0;
static GArray *debug_regions;
@@ -35,10 +37,14 @@ static GArray *debug_regions;
int qemu_log(const char *fmt, ...)
{
int ret = 0;
- if (qemu_logfile) {
+ QemuLogFile *logfile;
+
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
va_list ap;
va_start(ap, fmt);
- ret = vfprintf(qemu_logfile, fmt, ap);
+ ret = vfprintf(logfile->fd, fmt, ap);
va_end(ap);
/* Don't pass back error results. */
@@ -46,57 +52,91 @@ int qemu_log(const char *fmt, ...)
ret = 0;
}
}
+ rcu_read_unlock();
return ret;
}
+static void __attribute__((__constructor__)) qemu_logfile_init(void)
+{
+ qemu_mutex_init(&qemu_logfile_mutex);
+}
+
+static void qemu_logfile_free(QemuLogFile *logfile)
+{
+ g_assert(logfile);
+
+ if (logfile->fd != stderr) {
+ fclose(logfile->fd);
+ }
+ g_free(logfile);
+}
+
static bool log_uses_own_buffers;
/* enable or disable low levels log */
void qemu_set_log(int log_flags)
{
+ bool need_to_open_file = false;
+ QemuLogFile *logfile;
+
qemu_loglevel = log_flags;
#ifdef CONFIG_TRACE_LOG
qemu_loglevel |= LOG_TRACE;
#endif
- if (!qemu_logfile &&
- (is_daemonized() ? logfilename != NULL : qemu_loglevel)) {
+ /*
+ * In all cases we only log if qemu_loglevel is set.
+ * Also:
+ * If not daemonized we will always log either to stderr
+ * or to a file (if there is a logfilename).
+ * If we are daemonized,
+ * we will only log if there is a logfilename.
+ */
+ if (qemu_loglevel && (!is_daemonized() || logfilename)) {
+ need_to_open_file = true;
+ }
+ qemu_mutex_lock(&qemu_logfile_mutex);
+ if (qemu_logfile && !need_to_open_file) {
+ logfile = qemu_logfile;
+ atomic_rcu_set(&qemu_logfile, NULL);
+ call_rcu(logfile, qemu_logfile_free, rcu);
+ } else if (!qemu_logfile && need_to_open_file) {
+ logfile = g_new0(QemuLogFile, 1);
if (logfilename) {
- qemu_logfile = fopen(logfilename, log_append ? "a" : "w");
- if (!qemu_logfile) {
+ logfile->fd = fopen(logfilename, log_append ? "a" : "w");
+ if (!logfile->fd) {
+ g_free(logfile);
perror(logfilename);
_exit(1);
}
/* In case we are a daemon redirect stderr to logfile */
if (is_daemonized()) {
- dup2(fileno(qemu_logfile), STDERR_FILENO);
- fclose(qemu_logfile);
+ dup2(fileno(logfile->fd), STDERR_FILENO);
+ fclose(logfile->fd);
/* This will skip closing logfile in qemu_log_close() */
- qemu_logfile = stderr;
+ logfile->fd = stderr;
}
} else {
/* Default to stderr if no log file specified */
assert(!is_daemonized());
- qemu_logfile = stderr;
+ logfile->fd = stderr;
}
/* must avoid mmap() usage of glibc by setting a buffer "by hand" */
if (log_uses_own_buffers) {
static char logfile_buf[4096];
- setvbuf(qemu_logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
+ setvbuf(logfile->fd, logfile_buf, _IOLBF, sizeof(logfile_buf));
} else {
#if defined(_WIN32)
/* Win32 doesn't support line-buffering, so use unbuffered output. */
- setvbuf(qemu_logfile, NULL, _IONBF, 0);
+ setvbuf(logfile->fd, NULL, _IONBF, 0);
#else
- setvbuf(qemu_logfile, NULL, _IOLBF, 0);
+ setvbuf(logfile->fd, NULL, _IOLBF, 0);
#endif
log_append = 1;
}
+ atomic_rcu_set(&qemu_logfile, logfile);
}
- if (qemu_logfile &&
- (is_daemonized() ? logfilename == NULL : !qemu_loglevel)) {
- qemu_log_close();
- }
+ qemu_mutex_unlock(&qemu_logfile_mutex);
}
void qemu_log_needs_buffers(void)
@@ -113,6 +153,7 @@ void qemu_set_log_filename(const char *filename, Error **errp)
{
char *pidstr;
g_free(logfilename);
+ logfilename = NULL;
pidstr = strstr(filename, "%");
if (pidstr) {
@@ -224,18 +265,29 @@ out:
/* fflush() the log file */
void qemu_log_flush(void)
{
- fflush(qemu_logfile);
+ QemuLogFile *logfile;
+
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ fflush(logfile->fd);
+ }
+ rcu_read_unlock();
}
/* Close the log file */
void qemu_log_close(void)
{
- if (qemu_logfile) {
- if (qemu_logfile != stderr) {
- fclose(qemu_logfile);
- }
- qemu_logfile = NULL;
+ QemuLogFile *logfile;
+
+ qemu_mutex_lock(&qemu_logfile_mutex);
+ logfile = qemu_logfile;
+
+ if (logfile) {
+ atomic_rcu_set(&qemu_logfile, NULL);
+ call_rcu(logfile, qemu_logfile_free, rcu);
}
+ qemu_mutex_unlock(&qemu_logfile_mutex);
}
const QEMULogItem qemu_log_items[] = {
diff --git a/util/osdep.c b/util/osdep.c
index 3f04326..f7d0605 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -371,6 +371,21 @@ int qemu_close(int fd)
}
/*
+ * Delete a file from the filesystem, unless the filename is /dev/fdset/...
+ *
+ * Returns: On success, zero is returned. On error, -1 is returned,
+ * and errno is set appropriately.
+ */
+int qemu_unlink(const char *name)
+{
+ if (g_str_has_prefix(name, "/dev/fdset/")) {
+ return 0;
+ }
+
+ return unlink(name);
+}
+
+/*
* A variant of write(2) which handles partial write.
*
* Return the number of bytes transferred.