Although we cannot create these images with qemu-img it is still possible to do it using an external tool. QEMU should refuse to open them until the data-file-raw bit is cleared with 'qemu-img check'.
Signed-off-by: Alberto Garcia <be...@igalia.com> --- block/qcow2.c | 39 ++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/244 | 13 +++++++++++++ tests/qemu-iotests/244.out | 14 ++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/block/qcow2.c b/block/qcow2.c index b524b0c53f..fcc3810391 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -588,16 +588,49 @@ static void qcow2_add_check_result(BdrvCheckResult *out, } } +static int qcow2_check_header(BlockDriverState *bs, BdrvCheckResult *result, + BdrvCheckMode fix) +{ + BDRVQcow2State *s = bs->opaque; + int ret; + + if (bs->backing && data_file_is_raw(bs)) { + fprintf(stderr, "%s header: data-file-raw cannot be set " + "when there is a backing file.\n", + fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR in"); + if (fix & BDRV_FIX_ERRORS) { + s->autoclear_features &= ~QCOW2_AUTOCLEAR_DATA_FILE_RAW; + ret = qcow2_update_header(bs); + if (ret < 0) { + result->check_errors++; + return ret; + } + result->corruptions_fixed++; + } else { + result->corruptions++; + } + } + + return 0; +} + static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix) { + BdrvCheckResult header_res = {}; BdrvCheckResult snapshot_res = {}; BdrvCheckResult refcount_res = {}; int ret; memset(result, 0, sizeof(*result)); + ret = qcow2_check_header(bs, &header_res, fix); + qcow2_add_check_result(result, &header_res, false); + if (ret < 0) { + return ret; + } + ret = qcow2_check_read_snapshot_table(bs, &snapshot_res, fix); if (ret < 0) { qcow2_add_check_result(result, &snapshot_res, false); @@ -1604,6 +1637,12 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, /* read the backing file name */ if (header.backing_file_offset != 0) { + if (data_file_is_raw(bs) && (!(flags & BDRV_O_CHECK))) { + error_setg(errp, "data-file-raw cannot be set when " + "there is a backing file"); + ret = -EINVAL; + goto fail; + } len = header.backing_file_size; if (len > MIN(1023, s->cluster_size - header.backing_file_offset) || len >= sizeof(bs->backing_file)) { diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244 index 2ec1815e6f..159941acd4 100755 --- a/tests/qemu-iotests/244 +++ b/tests/qemu-iotests/244 @@ -211,6 +211,19 @@ $QEMU_IMG amend -f $IMGFMT -o "data_file=blkdebug::$TEST_IMG.data" "$TEST_IMG" $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG" $QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG" +echo +echo "=== Using and repairing an image with backing file and the data_file_raw bit ===" +echo + +# Create an image with a backing file and an external data file +TEST_IMG_FILE="$TEST_IMG.base" _make_test_img 1M +_make_test_img -o "data_file=$TEST_IMG.data" -b "$TEST_IMG.base" +# Set 'data_file_raw' directly on the header (qemu-img amend won't let us) +poke_file "$TEST_IMG" 95 "\x02" +# Trying to open the image should produce an error +$QEMU_IMG info "$TEST_IMG" 2>&1 | _filter_testdir +_check_test_img -r all + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/244.out b/tests/qemu-iotests/244.out index 56329deb4b..cab367dfb5 100644 --- a/tests/qemu-iotests/244.out +++ b/tests/qemu-iotests/244.out @@ -128,4 +128,18 @@ Offset Length Mapped to File Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data Images are identical. Images are identical. + +=== Using and repairing an image with backing file and the data_file_raw bit === + +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base data_file=TEST_DIR/t.IMGFMT.data +qemu-img: Could not open 'TEST_DIR/t.qcow2': data-file-raw cannot be set when there is a backing file +Repairing header: data-file-raw cannot be set when there is a backing file. +The following inconsistencies were found and repaired: + + 0 leaked clusters + 1 corruptions + +Double checking the fixed image now... +No errors were found on the image. *** done -- 2.20.1