aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-07-18 13:47:22 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-07-18 13:47:22 +0100
commite0097ea371a647651f6c89c3091c4962fdde26fd (patch)
treef5d9229f30a7f07ff36ac482fabab094a176e342
parent4d121a549869b93475ccf8b9a0d3e693011d1abb (diff)
parent8283c5c316333fb9d2540167f3e22bd91404ecee (diff)
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
Block pull request # gpg: Signature made Fri 18 Jul 2014 13:39:43 BST using RSA key ID 81AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" * remotes/stefanha/tags/block-pull-request: qemu-iotests: fix 028 failure due to disk image path raw-posix: Fail gracefully if no working alignment is found block: Add Error argument to bdrv_refresh_limits() qcow2: Fix error path for unknown incompatible features Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--block.c33
-rw-r--r--block/iscsi.c3
-rw-r--r--block/qcow2.c25
-rw-r--r--block/qed.c4
-rw-r--r--block/raw-posix.c39
-rw-r--r--block/raw_bsd.c3
-rw-r--r--block/stream.c2
-rw-r--r--block/vmdk.c4
-rw-r--r--include/block/block.h2
-rw-r--r--include/block/block_int.h2
-rwxr-xr-xtests/qemu-iotests/0284
-rw-r--r--tests/qemu-iotests/028.out2
-rwxr-xr-xtests/qemu-iotests/03652
-rw-r--r--tests/qemu-iotests/036.out35
-rwxr-xr-xtests/qemu-iotests/qcow2.py15
15 files changed, 174 insertions, 51 deletions
diff --git a/block.c b/block.c
index 3e252a26c2..8cf519ba3a 100644
--- a/block.c
+++ b/block.c
@@ -508,19 +508,24 @@ int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp)
return ret;
}
-int bdrv_refresh_limits(BlockDriverState *bs)
+void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
{
BlockDriver *drv = bs->drv;
+ Error *local_err = NULL;
memset(&bs->bl, 0, sizeof(bs->bl));
if (!drv) {
- return 0;
+ return;
}
/* Take some limits from the children as a default */
if (bs->file) {
- bdrv_refresh_limits(bs->file);
+ bdrv_refresh_limits(bs->file, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
bs->bl.opt_transfer_length = bs->file->bl.opt_transfer_length;
bs->bl.opt_mem_alignment = bs->file->bl.opt_mem_alignment;
} else {
@@ -528,7 +533,11 @@ int bdrv_refresh_limits(BlockDriverState *bs)
}
if (bs->backing_hd) {
- bdrv_refresh_limits(bs->backing_hd);
+ bdrv_refresh_limits(bs->backing_hd, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
bs->bl.opt_transfer_length =
MAX(bs->bl.opt_transfer_length,
bs->backing_hd->bl.opt_transfer_length);
@@ -539,10 +548,8 @@ int bdrv_refresh_limits(BlockDriverState *bs)
/* Then let the driver override it */
if (drv->bdrv_refresh_limits) {
- return drv->bdrv_refresh_limits(bs);
+ drv->bdrv_refresh_limits(bs, errp);
}
-
- return 0;
}
/*
@@ -993,7 +1000,13 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
goto free_and_fail;
}
- bdrv_refresh_limits(bs);
+ bdrv_refresh_limits(bs, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ goto free_and_fail;
+ }
+
assert(bdrv_opt_mem_align(bs) != 0);
assert((bs->request_alignment != 0) || bs->sg);
return 0;
@@ -1154,7 +1167,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
bdrv_op_unblock(bs->backing_hd, BLOCK_OP_TYPE_COMMIT,
bs->backing_blocker);
out:
- bdrv_refresh_limits(bs);
+ bdrv_refresh_limits(bs, NULL);
}
/*
@@ -1778,7 +1791,7 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
BDRV_O_CACHE_WB);
reopen_state->bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
- bdrv_refresh_limits(reopen_state->bs);
+ bdrv_refresh_limits(reopen_state->bs, NULL);
}
/*
diff --git a/block/iscsi.c b/block/iscsi.c
index f3e83e2332..a7bb6970ac 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1450,7 +1450,7 @@ static void iscsi_close(BlockDriverState *bs)
memset(iscsilun, 0, sizeof(IscsiLun));
}
-static int iscsi_refresh_limits(BlockDriverState *bs)
+static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
{
IscsiLun *iscsilun = bs->opaque;
@@ -1475,7 +1475,6 @@ static int iscsi_refresh_limits(BlockDriverState *bs)
}
bs->bl.opt_transfer_length = sector_lun2qemu(iscsilun->bl.opt_xfer_len,
iscsilun);
- return 0;
}
/* Since iscsi_open() ignores bdrv_flags, there is nothing to do here in
diff --git a/block/qcow2.c b/block/qcow2.c
index b0faa6917b..1e3ab6bd02 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -210,20 +210,31 @@ static void GCC_FMT_ATTR(3, 4) report_unsupported(BlockDriverState *bs,
static void report_unsupported_feature(BlockDriverState *bs,
Error **errp, Qcow2Feature *table, uint64_t mask)
{
+ char *features = g_strdup("");
+ char *old;
+
while (table && table->name[0] != '\0') {
if (table->type == QCOW2_FEAT_TYPE_INCOMPATIBLE) {
- if (mask & (1 << table->bit)) {
- report_unsupported(bs, errp, "%.46s", table->name);
- mask &= ~(1 << table->bit);
+ if (mask & (1ULL << table->bit)) {
+ old = features;
+ features = g_strdup_printf("%s%s%.46s", old, *old ? ", " : "",
+ table->name);
+ g_free(old);
+ mask &= ~(1ULL << table->bit);
}
}
table++;
}
if (mask) {
- report_unsupported(bs, errp, "Unknown incompatible feature: %" PRIx64,
- mask);
+ old = features;
+ features = g_strdup_printf("%s%sUnknown incompatible feature: %" PRIx64,
+ old, *old ? ", " : "", mask);
+ g_free(old);
}
+
+ report_unsupported(bs, errp, "%s", features);
+ g_free(features);
}
/*
@@ -855,13 +866,11 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
}
-static int qcow2_refresh_limits(BlockDriverState *bs)
+static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
{
BDRVQcowState *s = bs->opaque;
bs->bl.write_zeroes_alignment = s->cluster_sectors;
-
- return 0;
}
static int qcow2_set_key(BlockDriverState *bs, const char *key)
diff --git a/block/qed.c b/block/qed.c
index cd4872b529..7944832181 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -528,13 +528,11 @@ out:
return ret;
}
-static int bdrv_qed_refresh_limits(BlockDriverState *bs)
+static void bdrv_qed_refresh_limits(BlockDriverState *bs, Error **errp)
{
BDRVQEDState *s = bs->opaque;
bs->bl.write_zeroes_alignment = s->header.cluster_size >> BDRV_SECTOR_BITS;
-
- return 0;
}
/* We have nothing to do for QED reopen, stubs just return
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 2bcc73dc37..8e9758e920 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -221,7 +221,7 @@ static int raw_normalize_devicepath(const char **filename)
}
#endif
-static void raw_probe_alignment(BlockDriverState *bs)
+static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
{
BDRVRawState *s = bs->opaque;
char *buf;
@@ -240,24 +240,24 @@ static void raw_probe_alignment(BlockDriverState *bs)
s->buf_align = 0;
#ifdef BLKSSZGET
- if (ioctl(s->fd, BLKSSZGET, &sector_size) >= 0) {
+ if (ioctl(fd, BLKSSZGET, &sector_size) >= 0) {
bs->request_alignment = sector_size;
}
#endif
#ifdef DKIOCGETBLOCKSIZE
- if (ioctl(s->fd, DKIOCGETBLOCKSIZE, &sector_size) >= 0) {
+ if (ioctl(fd, DKIOCGETBLOCKSIZE, &sector_size) >= 0) {
bs->request_alignment = sector_size;
}
#endif
#ifdef DIOCGSECTORSIZE
- if (ioctl(s->fd, DIOCGSECTORSIZE, &sector_size) >= 0) {
+ if (ioctl(fd, DIOCGSECTORSIZE, &sector_size) >= 0) {
bs->request_alignment = sector_size;
}
#endif
#ifdef CONFIG_XFS
if (s->is_xfs) {
struct dioattr da;
- if (xfsctl(NULL, s->fd, XFS_IOC_DIOINFO, &da) >= 0) {
+ if (xfsctl(NULL, fd, XFS_IOC_DIOINFO, &da) >= 0) {
bs->request_alignment = da.d_miniosz;
/* The kernel returns wrong information for d_mem */
/* s->buf_align = da.d_mem; */
@@ -270,7 +270,7 @@ static void raw_probe_alignment(BlockDriverState *bs)
size_t align;
buf = qemu_memalign(MAX_BLOCKSIZE, 2 * MAX_BLOCKSIZE);
for (align = 512; align <= MAX_BLOCKSIZE; align <<= 1) {
- if (pread(s->fd, buf + align, MAX_BLOCKSIZE, 0) >= 0) {
+ if (pread(fd, buf + align, MAX_BLOCKSIZE, 0) >= 0) {
s->buf_align = align;
break;
}
@@ -282,13 +282,18 @@ static void raw_probe_alignment(BlockDriverState *bs)
size_t align;
buf = qemu_memalign(s->buf_align, MAX_BLOCKSIZE);
for (align = 512; align <= MAX_BLOCKSIZE; align <<= 1) {
- if (pread(s->fd, buf, align, 0) >= 0) {
+ if (pread(fd, buf, align, 0) >= 0) {
bs->request_alignment = align;
break;
}
}
qemu_vfree(buf);
}
+
+ if (!s->buf_align || !bs->request_alignment) {
+ error_setg(errp, "Could not find working O_DIRECT alignment. "
+ "Try cache.direct=off.");
+ }
}
static void raw_parse_flags(int bdrv_flags, int *open_flags)
@@ -505,6 +510,7 @@ static int raw_reopen_prepare(BDRVReopenState *state,
BDRVRawState *s;
BDRVRawReopenState *raw_s;
int ret = 0;
+ Error *local_err = NULL;
assert(state != NULL);
assert(state->bs != NULL);
@@ -577,6 +583,19 @@ static int raw_reopen_prepare(BDRVReopenState *state,
ret = -1;
}
}
+
+ /* Fail already reopen_prepare() if we can't get a working O_DIRECT
+ * alignment with the new fd. */
+ if (raw_s->fd != -1) {
+ raw_probe_alignment(state->bs, raw_s->fd, &local_err);
+ if (local_err) {
+ qemu_close(raw_s->fd);
+ raw_s->fd = -1;
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ }
+ }
+
return ret;
}
@@ -615,14 +634,12 @@ static void raw_reopen_abort(BDRVReopenState *state)
state->opaque = NULL;
}
-static int raw_refresh_limits(BlockDriverState *bs)
+static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
{
BDRVRawState *s = bs->opaque;
- raw_probe_alignment(bs);
+ raw_probe_alignment(bs, s->fd, errp);
bs->bl.opt_mem_alignment = s->buf_align;
-
- return 0;
}
static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb)
diff --git a/block/raw_bsd.c b/block/raw_bsd.c
index 492f58de69..f82f4c25df 100644
--- a/block/raw_bsd.c
+++ b/block/raw_bsd.c
@@ -94,10 +94,9 @@ static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
return bdrv_get_info(bs->file, bdi);
}
-static int raw_refresh_limits(BlockDriverState *bs)
+static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
{
bs->bl = bs->file->bl;
- return 0;
}
static int raw_truncate(BlockDriverState *bs, int64_t offset)
diff --git a/block/stream.c b/block/stream.c
index 34de8ba0d9..cdea3e8d0c 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -76,7 +76,7 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base,
bdrv_unref(unused);
}
- bdrv_refresh_limits(top);
+ bdrv_refresh_limits(top, NULL);
}
static void coroutine_fn stream_run(void *opaque)
diff --git a/block/vmdk.c b/block/vmdk.c
index 27a78daa02..0517bbaf91 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -938,7 +938,7 @@ fail:
}
-static int vmdk_refresh_limits(BlockDriverState *bs)
+static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp)
{
BDRVVmdkState *s = bs->opaque;
int i;
@@ -950,8 +950,6 @@ static int vmdk_refresh_limits(BlockDriverState *bs)
s->extents[i].cluster_sectors);
}
}
-
- return 0;
}
static int get_whole_cluster(BlockDriverState *bs,
diff --git a/include/block/block.h b/include/block/block.h
index 32d36760fd..f08471d7e1 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -278,7 +278,7 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset);
int64_t bdrv_getlength(BlockDriverState *bs);
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
-int bdrv_refresh_limits(BlockDriverState *bs);
+void bdrv_refresh_limits(BlockDriverState *bs, Error **errp);
int bdrv_commit(BlockDriverState *bs);
int bdrv_commit_all(void);
int bdrv_change_backing_file(BlockDriverState *bs,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index f6c3befed8..7b541a0691 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -240,7 +240,7 @@ struct BlockDriver {
int (*bdrv_debug_resume)(BlockDriverState *bs, const char *tag);
bool (*bdrv_debug_is_suspended)(BlockDriverState *bs, const char *tag);
- int (*bdrv_refresh_limits)(BlockDriverState *bs);
+ void (*bdrv_refresh_limits)(BlockDriverState *bs, Error **errp);
/*
* Returns 1 if newly created images are guaranteed to contain only
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
index d5718c5594..9e701e1c2b 100755
--- a/tests/qemu-iotests/028
+++ b/tests/qemu-iotests/028
@@ -110,7 +110,9 @@ _launch_qemu -drive file="${TEST_IMG}",cache=${CACHEMODE},id=disk
h=$QEMU_HANDLE
QEMU_COMM_TIMEOUT=1
-_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)"
+# Silence output since it contains the disk image path and QEMU's readline
+# character echoing makes it very hard to filter the output
+_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)" >/dev/null
qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs"
_send_qemu_cmd $h 'quit' ""
diff --git a/tests/qemu-iotests/028.out b/tests/qemu-iotests/028.out
index 38099e44c9..0e1a5ae65d 100644
--- a/tests/qemu-iotests/028.out
+++ b/tests/qemu-iotests/028.out
@@ -468,8 +468,6 @@ No errors were found on the image.
block-backup
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) ddrdridrivdrivedrive_drive_bdrive_badrive_bacdrive_backdrive_backudrive_backupdrive_backup drive_backup ddrive_backup didrive_backup disdrive_backup diskdrive_backup disk drive_backup disk /drive_backup disk /hdrive_backup disk /hodrive_backup disk /homdrive_backup disk /homedrive_backup disk /home/drive_backup disk /home/kdrive_backup disk /home/kwdrive_backup disk /home/kwodrive_backup disk /home/kwoldrive_backup disk /home/kwolfdrive_backup disk /home/kwolf/drive_backup disk /home/kwolf/sdrive_backup disk /home/kwolf/sodrive_backup disk /home/kwolf/soudrive_backup disk /home/kwolf/sourdrive_backup disk /home/kwolf/sourcdrive_backup disk /home/kwolf/sourcedrive_backup disk /home/kwolf/source/drive_backup disk /home/kwolf/source/qdrive_backup disk /home/kwolf/source/qedrive_backup disk /home/kwolf/source/qemdrive_backup disk /home/kwolf/source/qemudrive_backup disk /home/kwolf/source/qemu/drive_backup disk /home/kwolf/source/qemu/tdrive_backup disk /home/kwolf/source/qemu/tedrive_backup disk /home/kwolf/source/qemu/tesdrive_backup disk /home/kwolf/source/qemu/testdrive_backup disk /home/kwolf/source/qemu/testsdrive_backup disk /home/kwolf/source/qemu/tests/drive_backup disk /home/kwolf/source/qemu/tests/qdrive_backup disk /home/kwolf/source/qemu/tests/qedrive_backup disk /home/kwolf/source/qemu/tests/qemdrive_backup disk /home/kwolf/source/qemu/tests/qemudrive_backup disk /home/kwolf/source/qemu/tests/qemu-drive_backup disk /home/kwolf/source/qemu/tests/qemu-idrive_backup disk /home/kwolf/source/qemu/tests/qemu-iodrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotedrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotesdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotestdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotestsdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/drive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/sdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scrdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scradrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scratdrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scratcdrive_backup disk TEST_DIRdrive_backup disk TEST_DIR/drive_backup disk TEST_DIR/tdrive_backup disk TEST_DIR/t.drive_backup disk TEST_DIR/t.qdrive_backup disk TEST_DIR/t.qcdrive_backup disk TEST_DIR/t.qcodrive_backup disk TEST_DIR/t.qcowdrive_backup disk TEST_DIR/t.qcow2drive_backup disk TEST_DIR/t.qcow2.drive_backup disk TEST_DIR/t.qcow2.cdrive_backup disk TEST_DIR/t.qcow2.codrive_backup disk TEST_DIR/t.qcow2.copdrive_backup disk TEST_DIR/t.qcow2.copy
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=4294968832 backing_file='TEST_DIR/t.qcow2.base' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block-info block-jinfo block-joinfo block-jobinfo block-jobs
Type backup, device disk: Completed 0 of 4294968832 bytes, speed limit 0 bytes/s
diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036
index a77365347d..392f1ef3e6 100755
--- a/tests/qemu-iotests/036
+++ b/tests/qemu-iotests/036
@@ -1,6 +1,6 @@
#!/bin/bash
#
-# Test that qcow2 unknown autoclear feature bits are cleared
+# Test qcow2 feature bits
#
# Copyright (C) 2011 Red Hat, Inc.
# Copyright IBM, Corp. 2010
@@ -50,6 +50,56 @@ _supported_os Linux
# Only qcow2v3 and later supports feature bits
IMGOPTS="compat=1.1"
+echo
+echo === Image with unknown incompatible feature bit ===
+echo
+_make_test_img 64M
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
+
+# Without feature table
+$PYTHON qcow2.py "$TEST_IMG" dump-header
+_img_info
+
+# With feature table containing bit 63
+printf "\x00\x3f%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+echo
+echo === Image with multiple incompatible feature bits ===
+echo
+_make_test_img 64M
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 61
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 62
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
+
+# Without feature table
+_img_info
+
+# With feature table containing bit 63
+printf "\x00\x3f%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+# With feature table containing bit 61
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
+printf "\x00\x3d%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+# With feature table containing bits 61 and 62
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
+printf "\x00\x3d%s\x00%40s\x00\x3e%s\x00%40s" "test1" "" "test2" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+# With feature table containing all bits
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
+printf "\x00\x3d%s\x00%40s\x00\x3e%s\x00%40s\x00\x3f%s\x00%40s" "test1" "" "test2" "" "test3" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+# With feature table containing unrelated bits, including compatible/autoclear
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
+printf "\x01\x3d%s\x00%40s\x00\x3e%s\x00%40s\x02\x3f%s\x00%40s\x00\x3c%s\x00%40s" "test1" "" "test2" "" "test3" "" "test4" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+
echo === Create image with unknown autoclear feature bit ===
echo
_make_test_img 64M
diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out
index 55a3e6e441..720bd89161 100644
--- a/tests/qemu-iotests/036.out
+++ b/tests/qemu-iotests/036.out
@@ -1,4 +1,39 @@
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
+
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Unknown incompatible feature: 8000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature
+
+=== Image with multiple incompatible feature bits ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Unknown incompatible feature: e000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature, Unknown incompatible feature: 6000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature, Unknown incompatible feature: c000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test1, test2, Unknown incompatible feature: 8000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test1, test2, test3
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test2, Unknown incompatible feature: a000000000000000
=== Create image with unknown autoclear feature bit ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
index 44a2b45641..2058596964 100755
--- a/tests/qemu-iotests/qcow2.py
+++ b/tests/qemu-iotests/qcow2.py
@@ -176,6 +176,10 @@ def cmd_add_header_ext(fd, magic, data):
h.extensions.append(QcowHeaderExtension.create(magic, data))
h.update(fd)
+def cmd_add_header_ext_stdio(fd, magic):
+ data = sys.stdin.read()
+ cmd_add_header_ext(fd, magic, data)
+
def cmd_del_header_ext(fd, magic):
try:
magic = int(magic, 0)
@@ -220,11 +224,12 @@ def cmd_set_feature_bit(fd, group, bit):
h.update(fd)
cmds = [
- [ 'dump-header', cmd_dump_header, 0, 'Dump image header and 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' ],
- [ 'del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension' ],
- [ 'set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
+ [ 'dump-header', cmd_dump_header, 0, 'Dump image header and 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' ],
+ [ 'del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension' ],
+ [ 'set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
]
def main(filename, cmd, args):