aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@amazon.com>2013-11-19 12:59:09 -0800
committerAnthony Liguori <aliguori@amazon.com>2013-11-19 12:59:09 -0800
commit7af31519e220efc0572cacec5ac65dc54e73985d (patch)
treee078f066da8645430cf5ed0c9f0c07e823b10c30
parent88a47b9de2c01121e153b1feb24cdb2e033b2f04 (diff)
parent06d22aa36706a3d6051b74c8a183ab554a0cb808 (diff)
Merge remote-tracking branch 'kwolf/tags/for-anthony' into staging
Block fixes for 1.7.0 # gpg: Signature made Fri 15 Nov 2013 09:51:25 AM PST using RSA key ID C88F2FD6 # gpg: Can't check signature: public key not found # By Max Reitz (3) and others # Via Kevin Wolf * kwolf/tags/for-anthony: block: Fail if requested driver is not available MAINTAINERS: add block driver sub-maintainers qemu-img: Fix overwriting 'ret' before using qemu-iotests: Test qcow2 count_contiguous_clusters() qcow2: fix possible corruption when reading multiple clusters qmp: access the local QemuOptsLists for drive option MAINTAINERS: add block tree repo URLs qemu-iotests: Extend 041 for unbacked mirroring block/drive-mirror: Check for NULL backing_hd qapi-schema: Update description for NewImageMode block: Print its file name if backing file opening failed Message-id: 1384537999-5972-1-git-send-email-kwolf@redhat.com Signed-off-by: Anthony Liguori <aliguori@amazon.com>
-rw-r--r--MAINTAINERS42
-rw-r--r--block.c9
-rw-r--r--block/qcow2-cluster.c2
-rw-r--r--block/raw-posix.c1
-rw-r--r--block/raw-win32.c1
-rw-r--r--blockdev.c5
-rw-r--r--include/qemu/config-file.h1
-rw-r--r--include/sysemu/sysemu.h2
-rw-r--r--qapi-schema.json3
-rw-r--r--qemu-img.c6
-rwxr-xr-xtests/qemu-iotests/04125
-rw-r--r--tests/qemu-iotests/041.out4
-rwxr-xr-xtests/qemu-iotests/04834
-rw-r--r--tests/qemu-iotests/048.out27
-rwxr-xr-xtests/qemu-iotests/0517
-rw-r--r--tests/qemu-iotests/051.out11
-rw-r--r--tests/qemu-iotests/069.out2
-rwxr-xr-xtests/qemu-iotests/073166
-rw-r--r--tests/qemu-iotests/073.out118
-rw-r--r--tests/qemu-iotests/group1
-rw-r--r--util/qemu-config.c77
-rw-r--r--vl.c3
22 files changed, 531 insertions, 16 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 02b85ee4cd..c19133f1a3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -639,6 +639,8 @@ S: Supported
F: block*
F: block/
F: hw/block/
+T: git git://repo.or.cz/qemu/kevin.git block
+T: git git://github.com/stefanha/qemu.git block
Character Devices
M: Anthony Liguori <aliguori@amazon.com>
@@ -861,3 +863,43 @@ Stable 0.10
L: qemu-stable@nongnu.org
T: git git://git.qemu-project.org/qemu-stable-0.10.git
S: Orphan
+
+Block drivers
+-------------
+VMDK
+M: Fam Zheng <famz@redhat.com>
+S: Supported
+F: block/vmdk.c
+
+RBD
+M: Josh Durgin <josh.durgin@inktank.com>
+S: Supported
+F: block/rbd.c
+
+Sheepdog
+M: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
+M: Liu Yuan <namei.unix@gmail.com>
+S: Supported
+F: block/sheepdog.c
+
+VHDX
+M: Jeff Cody <jcody@redhat.com>
+S: Supported
+F: block/vhdx*
+
+VDI
+M: Stefan Weil <sw@weilnetz.de>
+S: Maintained
+F: block/vdi.c
+
+iSCSI
+M: Ronnie Sahlberg <ronniesahlberg@gmail.com>
+M: Paolo Bonzini <pbonzini@redhat.com>
+M: Peter Lieven <pl@kamp.de>
+S: Supported
+F: block/iscsi.c
+
+SSH
+M: Richard W.M. Jones <rjones@redhat.com>
+S: Supported
+F: block/ssh.c
diff --git a/block.c b/block.c
index 6d5c80475c..382ea71f4b 100644
--- a/block.c
+++ b/block.c
@@ -1009,7 +1009,9 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
bdrv_unref(bs->backing_hd);
bs->backing_hd = NULL;
bs->open_flags |= BDRV_O_NO_BACKING;
- error_propagate(errp, local_err);
+ error_setg(errp, "Could not open backing file: %s",
+ error_get_pretty(local_err));
+ error_free(local_err);
return ret;
}
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
@@ -1135,6 +1137,11 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
if (drvname) {
drv = bdrv_find_format(drvname);
qdict_del(options, "driver");
+ if (!drv) {
+ error_setg(errp, "Invalid driver: '%s'", drvname);
+ ret = -EINVAL;
+ goto unlink_and_fail;
+ }
}
if (!drv) {
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index f242244918..791083a0ef 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -290,7 +290,7 @@ static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
uint64_t *l2_table, uint64_t stop_flags)
{
int i;
- uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW2_CLUSTER_COMPRESSED;
+ uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW_OFLAG_COMPRESSED;
uint64_t first_entry = be64_to_cpu(l2_table[0]);
uint64_t offset = first_entry & mask;
diff --git a/block/raw-posix.c b/block/raw-posix.c
index ace5d962e8..f836c8e745 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -310,7 +310,6 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
if (ret == -EROFS) {
ret = -EACCES;
}
- error_setg_errno(errp, -ret, "Could not open file");
goto fail;
}
s->fd = fd;
diff --git a/block/raw-win32.c b/block/raw-win32.c
index 2741e4de10..2bad5a39b4 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -280,7 +280,6 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
} else {
ret = -EINVAL;
}
- error_setg_errno(errp, -ret, "Could not open file");
goto fail;
}
diff --git a/blockdev.c b/blockdev.c
index 86e6bffdc4..330aa4a3a4 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -47,7 +47,6 @@
#include "sysemu/arch_init.h"
static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
-extern QemuOptsList qemu_common_drive_opts;
static const char *const if_name[IF_COUNT] = {
[IF_NONE] = "none",
@@ -2029,7 +2028,9 @@ void qmp_drive_mirror(const char *device, const char *target,
return;
}
- if (sync == MIRROR_SYNC_MODE_FULL && mode != NEW_IMAGE_MODE_EXISTING) {
+ if ((sync == MIRROR_SYNC_MODE_FULL || !source)
+ && mode != NEW_IMAGE_MODE_EXISTING)
+ {
/* create new image w/o backing file */
assert(format && drv);
bdrv_img_create(target, format,
diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h
index ad4a9e5c3a..508428ff32 100644
--- a/include/qemu/config-file.h
+++ b/include/qemu/config-file.h
@@ -8,6 +8,7 @@
QemuOptsList *qemu_find_opts(const char *group);
QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
void qemu_add_opts(QemuOptsList *list);
+void qemu_add_drive_opts(QemuOptsList *list);
int qemu_set_option(const char *str);
int qemu_global_option(const char *str);
void qemu_add_globals(void);
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index cd5791eb74..495dae8c39 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -193,6 +193,8 @@ QemuOpts *qemu_get_machine_opts(void);
bool usb_enabled(bool default_usb);
+extern QemuOptsList qemu_legacy_drive_opts;
+extern QemuOptsList qemu_common_drive_opts;
extern QemuOptsList qemu_drive_opts;
extern QemuOptsList qemu_chardev_opts;
extern QemuOptsList qemu_device_opts;
diff --git a/qapi-schema.json b/qapi-schema.json
index 76c98a7265..83fa4852ce 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1736,7 +1736,8 @@
# @existing: QEMU should look for an existing image file.
#
# @absolute-paths: QEMU should create a new image with absolute paths
-# for the backing file.
+# for the backing file. If there is no backing file available, the new
+# image will not be backed either.
#
# Since: 1.1
##
diff --git a/qemu-img.c b/qemu-img.c
index bf3fb4f8a6..b6b5644cb6 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1020,10 +1020,10 @@ static int img_compare(int argc, char **argv)
}
ret = compare_sectors(buf1, buf2, nb_sectors, &pnum);
if (ret || pnum != nb_sectors) {
- ret = 1;
qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
sectors_to_bytes(
ret ? sector_num : sector_num + pnum));
+ ret = 1;
goto out;
}
}
@@ -1045,9 +1045,9 @@ static int img_compare(int argc, char **argv)
}
if (ret) {
if (ret < 0) {
- ret = 4;
error_report("Error while reading offset %" PRId64 ": %s",
sectors_to_bytes(sector_num), strerror(-ret));
+ ret = 4;
}
goto out;
}
@@ -1092,10 +1092,10 @@ static int img_compare(int argc, char **argv)
filename_over, buf1, quiet);
if (ret) {
if (ret < 0) {
- ret = 4;
error_report("Error while reading offset %" PRId64
" of %s: %s", sectors_to_bytes(sector_num),
filename_over, strerror(-ret));
+ ret = 4;
}
goto out;
}
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index 6661c0395d..5d40265fb3 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -677,5 +677,30 @@ class TestSetSpeed(ImageMirroringTestCase):
self.wait_ready_and_cancel()
+class TestUnbackedSource(ImageMirroringTestCase):
+ image_len = 2 * 1024 * 1024 # MB
+
+ def setUp(self):
+ qemu_img('create', '-f', iotests.imgfmt, test_img,
+ str(TestUnbackedSource.image_len))
+ self.vm = iotests.VM().add_drive(test_img)
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(test_img)
+ os.remove(target_img)
+
+ def test_absolute_paths(self):
+ self.assert_no_active_block_jobs()
+
+ for sync_mode in ['full', 'top', 'none']:
+ result = self.vm.qmp('drive-mirror', device='drive0',
+ sync=sync_mode, target=target_img,
+ mode='absolute-paths')
+ self.assert_qmp(result, 'return', {})
+ self.complete_and_wait()
+ self.assert_no_active_block_jobs()
+
if __name__ == '__main__':
iotests.main(supported_fmts=['qcow2', 'qed'])
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
index 42314e9c00..4fd1c2dcd2 100644
--- a/tests/qemu-iotests/041.out
+++ b/tests/qemu-iotests/041.out
@@ -1,5 +1,5 @@
-........................
+.........................
----------------------------------------------------------------------
-Ran 24 tests
+Ran 25 tests
OK
diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048
index 9b9d118ef3..9def7fcc8c 100755
--- a/tests/qemu-iotests/048
+++ b/tests/qemu-iotests/048
@@ -74,5 +74,39 @@ _compare
io_pattern write 0 $CLUSTER_SIZE 0 1 123
_compare
+# Test unaligned case of mismatch offsets in allocated clusters
+_make_test_img $size
+io_pattern write 0 512 0 1 100
+cp "$TEST_IMG" "$TEST_IMG2"
+io_pattern write 512 512 0 1 101
+_compare
+
+# Test cluster allocated in one, with IO error
+cat > "$TEST_DIR/blkdebug.conf"<<EOF
+[inject-error]
+event = "read_aio"
+errno = "5"
+once ="off"
+EOF
+_make_test_img $size
+cp "$TEST_IMG" "$TEST_IMG2"
+io_pattern write 512 512 0 1 102
+TEST_IMG="blkdebug:$TEST_DIR/blkdebug.conf:$TEST_IMG" _compare 2>&1 |\
+ _filter_testdir | _filter_imgfmt
+
+# Test cluster allocated in one, with different sizes and IO error in the part
+# that exists only in one image
+cat > "$TEST_DIR/blkdebug.conf"<<EOF
+[inject-error]
+event = "read_aio"
+errno = "5"
+once ="off"
+EOF
+_make_test_img $size
+TEST_IMG="$TEST_IMG2" _make_test_img 0
+io_pattern write 512 512 0 1 102
+TEST_IMG="blkdebug:$TEST_DIR/blkdebug.conf:$TEST_IMG" _compare 2>&1 |\
+ _filter_testdir | _filter_imgfmt
+
# Cleanup
status=0
diff --git a/tests/qemu-iotests/048.out b/tests/qemu-iotests/048.out
index 68f65d5e19..d141e0579f 100644
--- a/tests/qemu-iotests/048.out
+++ b/tests/qemu-iotests/048.out
@@ -1,5 +1,5 @@
QA output created by 048
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
=== IO: pattern 45
qemu-io> wrote 4096/4096 bytes at offset 524288
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -28,4 +28,29 @@ qemu-io> wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qemu-io> Content mismatch at offset 0!
1
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+=== IO: pattern 100
+qemu-io> wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> === IO: pattern 101
+qemu-io> wrote 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> Content mismatch at offset 512!
+1
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+=== IO: pattern 102
+qemu-io> wrote 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
+qemu-img: Error while reading offset 0: Input/output error
+4
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=0
+=== IO: pattern 102
+qemu-io> wrote 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
+qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
+Warning: Image size mismatch!
+4
Cleanup
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
index 0a4971d437..3a75bda5eb 100755
--- a/tests/qemu-iotests/051
+++ b/tests/qemu-iotests/051
@@ -78,6 +78,13 @@ run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=1234
run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=foo
echo
+echo === Invalid format ===
+echo
+
+run_qemu -drive file="$TEST_IMG",format=foo
+run_qemu -drive file="$TEST_IMG",driver=foo
+
+echo
echo === Overriding backing file ===
echo
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index 15deef6dc3..8769c8e66e 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -17,6 +17,15 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: could not open disk image TEST_DIR/t.qcow2: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt'
+=== Invalid format ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=foo
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=foo: 'foo' invalid format
+
+Testing: -drive file=TEST_DIR/t.qcow2,driver=foo
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=foo: could not open disk image TEST_DIR/t.qcow2: Invalid driver: 'foo'
+
+
=== Overriding backing file ===
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig -nodefaults
@@ -226,6 +235,6 @@ Testing: -drive file=foo:bar
QEMU_PROG: -drive file=foo:bar: could not open disk image foo:bar: Unknown protocol
Testing: -drive file.filename=foo:bar
-QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: Could not open file: No such file or directory
+QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: Could not open 'foo:bar': No such file or directory
*** done
diff --git a/tests/qemu-iotests/069.out b/tests/qemu-iotests/069.out
index 364881429c..b48306d5ab 100644
--- a/tests/qemu-iotests/069.out
+++ b/tests/qemu-iotests/069.out
@@ -4,5 +4,5 @@ QA output created by 069
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=131072
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file='TEST_DIR/t.IMGFMT.base'
-qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open file: No such file or directory
+qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open backing file: Could not open 'TEST_DIR/t.IMGFMT.base': No such file or directory
*** done
diff --git a/tests/qemu-iotests/073 b/tests/qemu-iotests/073
new file mode 100755
index 0000000000..392db54999
--- /dev/null
+++ b/tests/qemu-iotests/073
@@ -0,0 +1,166 @@
+#!/bin/bash
+#
+# Test count_contiguous_clusters in qcow2
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto generic
+_supported_os Linux
+
+CLUSTER_SIZE=64k
+size=128M
+
+echo
+echo "== creating backing file =="
+
+TEST_IMG="$TEST_IMG.base" _make_test_img $size
+
+_make_test_img -b "$TEST_IMG.base"
+$QEMU_IO -c "write -P 0xa5 0 $size" "$TEST_IMG.base" | _filter_qemu_io
+
+echo
+echo "== normal -> unallocated =="
+
+$QEMU_IO -c "write -P 0x11 0 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x11 0x10000 0x10000" "$TEST_IMG.base" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x11 0 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== normal -> compressed =="
+
+$QEMU_IO -c "write -P 0x22 0x20000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -c -P 0x22 0x30000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x22 0x20000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== normal -> zero =="
+
+$QEMU_IO -c "write -P 0x33 0x40000 0x20000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x33 0x40000 0x20000" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -P 0 0x40000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 0x50000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0 0x40000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo
+echo "== unallocated -> normal =="
+
+$QEMU_IO -c "write -P 0x44 0x60000 0x10000" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x44 0x70000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x44 0x60000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== unallocated -> compressed =="
+
+$QEMU_IO -c "write -P 0x55 0x80000 0x10000" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -c -P 0x55 0x90000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x55 0x80000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== unallocated -> zero =="
+
+$QEMU_IO -c "write -P 0x66 0xa0000 0x20000" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -P 0 0xa0000 0x10000" "$TEST_IMG.base" | _filter_qemu_io
+$QEMU_IO -c "write -z 0xb0000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0 0xa0000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo
+echo "== compressed -> normal =="
+
+$QEMU_IO -c "write -c -P 0x77 0xc0000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x77 0xd0000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x77 0xc0000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== compressed -> unallocated =="
+
+$QEMU_IO -c "write -c -P 0x88 0xe0000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x88 0xf0000 0x10000" "$TEST_IMG.base" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x88 0xe0000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== compressed -> zero =="
+
+$QEMU_IO -c "write -c -P 0 0x100000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -c -P 0x99 0x110000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 0x110000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0 0x100000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo
+echo "== zero -> normal =="
+
+$QEMU_IO -c "write -P 0xaa 0x120000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0 0x130000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 0x120000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0 0x120000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== zero -> unallocated =="
+
+$QEMU_IO -c "write -z 0x140000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0 0x150000 0x10000" "$TEST_IMG.base" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0 0x140000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== zero -> compressed =="
+
+$QEMU_IO -c "write -c -P 0 0x170000 0x10000" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -z 0x160000 0x10000" "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0 0x160000 0x20000" "$TEST_IMG" | _filter_qemu_io
+
+
+_check_test_img
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/073.out b/tests/qemu-iotests/073.out
new file mode 100644
index 0000000000..c9b00763b2
--- /dev/null
+++ b/tests/qemu-iotests/073.out
@@ -0,0 +1,118 @@
+QA output created by 073
+
+== creating backing file ==
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base'
+wrote 134217728/134217728 bytes at offset 0
+128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== normal -> unallocated ==
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 0
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== normal -> compressed ==
+wrote 65536/65536 bytes at offset 131072
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 196608
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 131072
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== normal -> zero ==
+wrote 131072/131072 bytes at offset 262144
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 131072/131072 bytes at offset 262144
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 262144
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 327680
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 262144
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+
+== unallocated -> normal ==
+wrote 65536/65536 bytes at offset 393216
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 458752
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 393216
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== unallocated -> compressed ==
+wrote 65536/65536 bytes at offset 524288
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 589824
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 524288
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== unallocated -> zero ==
+wrote 131072/131072 bytes at offset 655360
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 655360
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 720896
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 655360
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+
+== compressed -> normal ==
+wrote 65536/65536 bytes at offset 786432
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 851968
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 786432
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== compressed -> unallocated ==
+wrote 65536/65536 bytes at offset 917504
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 983040
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 917504
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== compressed -> zero ==
+wrote 65536/65536 bytes at offset 1048576
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1114112
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1114112
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 1048576
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+
+== zero -> normal ==
+wrote 65536/65536 bytes at offset 1179648
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1245184
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1179648
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 1179648
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== zero -> unallocated ==
+wrote 65536/65536 bytes at offset 1310720
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1376256
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 1310720
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== zero -> compressed ==
+wrote 65536/65536 bytes at offset 1507328
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 1441792
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 1441792
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+No errors were found on the image.
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index b18b241f8d..b63b18c7aa 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -76,3 +76,4 @@
068 rw auto
069 rw auto
070 rw auto
+073 rw auto
diff --git a/util/qemu-config.c b/util/qemu-config.c
index a59568d070..04da942a25 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -8,6 +8,7 @@
#include "qmp-commands.h"
static QemuOptsList *vm_config_groups[32];
+static QemuOptsList *drive_config_groups[4];
static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
Error **errp)
@@ -77,6 +78,59 @@ static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc)
return param_list;
}
+/* remove repeated entry from the info list */
+static void cleanup_infolist(CommandLineParameterInfoList *head)
+{
+ CommandLineParameterInfoList *pre_entry, *cur, *del_entry;
+
+ cur = head;
+ while (cur->next) {
+ pre_entry = head;
+ while (pre_entry != cur->next) {
+ if (!strcmp(pre_entry->value->name, cur->next->value->name)) {
+ del_entry = cur->next;
+ cur->next = cur->next->next;
+ g_free(del_entry);
+ break;
+ }
+ pre_entry = pre_entry->next;
+ }
+ cur = cur->next;
+ }
+}
+
+/* merge the description items of two parameter infolists */
+static void connect_infolist(CommandLineParameterInfoList *head,
+ CommandLineParameterInfoList *new)
+{
+ CommandLineParameterInfoList *cur;
+
+ cur = head;
+ while (cur->next) {
+ cur = cur->next;
+ }
+ cur->next = new;
+}
+
+/* access all the local QemuOptsLists for drive option */
+static CommandLineParameterInfoList *get_drive_infolist(void)
+{
+ CommandLineParameterInfoList *head = NULL, *cur;
+ int i;
+
+ for (i = 0; drive_config_groups[i] != NULL; i++) {
+ if (!head) {
+ head = query_option_descs(drive_config_groups[i]->desc);
+ } else {
+ cur = query_option_descs(drive_config_groups[i]->desc);
+ connect_infolist(head, cur);
+ }
+ }
+ cleanup_infolist(head);
+
+ return head;
+}
+
CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option,
const char *option,
Error **errp)
@@ -89,7 +143,12 @@ CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option,
if (!has_option || !strcmp(option, vm_config_groups[i]->name)) {
info = g_malloc0(sizeof(*info));
info->option = g_strdup(vm_config_groups[i]->name);
- info->parameters = query_option_descs(vm_config_groups[i]->desc);
+ if (!strcmp("drive", vm_config_groups[i]->name)) {
+ info->parameters = get_drive_infolist();
+ } else {
+ info->parameters =
+ query_option_descs(vm_config_groups[i]->desc);
+ }
entry = g_malloc0(sizeof(*entry));
entry->value = info;
entry->next = conf_list;
@@ -109,6 +168,22 @@ QemuOptsList *qemu_find_opts_err(const char *group, Error **errp)
return find_list(vm_config_groups, group, errp);
}
+void qemu_add_drive_opts(QemuOptsList *list)
+{
+ int entries, i;
+
+ entries = ARRAY_SIZE(drive_config_groups);
+ entries--; /* keep list NULL terminated */
+ for (i = 0; i < entries; i++) {
+ if (drive_config_groups[i] == NULL) {
+ drive_config_groups[i] = list;
+ return;
+ }
+ }
+ fprintf(stderr, "ran out of space in drive_config_groups");
+ abort();
+}
+
void qemu_add_opts(QemuOptsList *list)
{
int entries, i;
diff --git a/vl.c b/vl.c
index 4ad15b808c..a585257096 100644
--- a/vl.c
+++ b/vl.c
@@ -2867,6 +2867,9 @@ int main(int argc, char **argv, char **envp)
module_call_init(MODULE_INIT_QOM);
qemu_add_opts(&qemu_drive_opts);
+ qemu_add_drive_opts(&qemu_legacy_drive_opts);
+ qemu_add_drive_opts(&qemu_common_drive_opts);
+ qemu_add_drive_opts(&qemu_drive_opts);
qemu_add_opts(&qemu_chardev_opts);
qemu_add_opts(&qemu_device_opts);
qemu_add_opts(&qemu_netdev_opts);