People have been keeping destroying their qcow2 images by using 'qemu-img snapshot' on images that were in use by a VM. This patch adds some image locking that protects them against this mistake.
In order to achieve this, a new compatible header flag is introduced that tells that the image is currently in use. It is (almost) always set when qcow2 considers the image to be active and in a read-write mode. During live migration, the source considers the image active until the VM stops on migration completion. The destination considers it active as soon as it starts running the VM. In cases where qemu wasn't shut down cleanly, images may incorrectly refuse to open. An option override-lock=on is provided to force opening the image (this is the option that qemu-img uses for 'force-unlock' and 'check --force'). A few test cases have to be adjusted, either to update error messages, to use read-only mode to avoid the check, or to override the lock where necessary. Signed-off-by: Kevin Wolf <kw...@redhat.com> --- block/qcow2.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++ block/qcow2.h | 7 +++- docs/specs/qcow2.txt | 7 +++- tests/qemu-iotests/026 | 2 +- tests/qemu-iotests/026.out | 60 ++++++++++++++++++++++++++++----- tests/qemu-iotests/031.out | 8 ++--- tests/qemu-iotests/036.out | 4 +-- tests/qemu-iotests/039 | 4 +-- tests/qemu-iotests/061 | 2 ++ tests/qemu-iotests/061.out | 16 ++++----- tests/qemu-iotests/071 | 7 ++++ tests/qemu-iotests/071.out | 4 +++ tests/qemu-iotests/089 | 2 +- tests/qemu-iotests/089.out | 2 -- tests/qemu-iotests/091 | 2 +- tests/qemu-iotests/098 | 2 +- 16 files changed, 181 insertions(+), 32 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 544c124..c07a078 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -307,6 +307,8 @@ int qcow2_mark_corrupt(BlockDriverState *bs) BDRVQcow2State *s = bs->opaque; s->incompatible_features |= QCOW2_INCOMPAT_CORRUPT; + s->compatible_features &= ~QCOW2_COMPAT_IN_USE; + return qcow2_update_header(bs); } @@ -472,6 +474,11 @@ static QemuOptsList qcow2_runtime_opts = { .type = QEMU_OPT_NUMBER, .help = "Clean unused cache entries after this time (in seconds)", }, + { + .name = BDRV_OPT_OVERRIDE_LOCK, + .type = QEMU_OPT_BOOL, + .help = "Open the image read-write even if it is locked", + }, { /* end of list */ } }, }; @@ -593,6 +600,7 @@ typedef struct Qcow2ReopenState { Qcow2Cache *l2_table_cache; Qcow2Cache *refcount_block_cache; bool use_lazy_refcounts; + bool override_lock; int overlap_check; bool discard_passthrough[QCOW2_DISCARD_MAX]; uint64_t cache_clean_interval; @@ -754,6 +762,9 @@ static int qcow2_update_options_prepare(BlockDriverState *bs, r->discard_passthrough[QCOW2_DISCARD_OTHER] = qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false); + r->override_lock = qemu_opt_get_bool(opts, BDRV_OPT_OVERRIDE_LOCK, + s->override_lock); + ret = 0; fail: qemu_opts_del(opts); @@ -788,6 +799,8 @@ static void qcow2_update_options_commit(BlockDriverState *bs, s->cache_clean_interval = r->cache_clean_interval; cache_clean_timer_init(bs, bdrv_get_aio_context(bs)); } + + s->override_lock = r->override_lock; } static void qcow2_update_options_abort(BlockDriverState *bs, @@ -1080,6 +1093,22 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, goto fail; } + /* Protect against opening the image r/w twice at the same time */ + if (!bs->read_only && (s->compatible_features & QCOW2_COMPAT_IN_USE)) { + /* Shared storage is expected during migration */ + bool migrating = (flags & BDRV_O_INCOMING); + + if (!migrating && !s->override_lock) { + error_set(errp, ERROR_CLASS_IMAGE_FILE_LOCKED, + "Image is already in use"); + error_append_hint(errp, "This check can be disabled " + "with override-lock=on. Caution: Opening an " + "image twice can cause corruption!"); + ret = -EBUSY; + goto fail; + } + } + s->cluster_cache = g_malloc(s->cluster_size); /* one more sector for decompressed data alignment */ s->cluster_data = qemu_try_blockalign(bs->file->bs, QCOW_MAX_CRYPT_CLUSTERS @@ -1164,6 +1193,17 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, } } + /* Set advisory lock in the header (do this as the final step so that + * failure doesn't leave a locked image around) */ + if (!bs->read_only && !(flags & BDRV_O_INCOMING) && s->qcow_version >= 3) { + s->compatible_features |= QCOW2_COMPAT_IN_USE; + ret = qcow2_update_header(bs); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not update qcow2 header"); + goto fail; + } + } + #ifdef DEBUG_ALLOC { BdrvCheckResult result = {0}; @@ -1260,6 +1300,15 @@ static int qcow2_reopen_prepare(BDRVReopenState *state, if (ret < 0) { goto fail; } + + if (!state->bs->read_only) { + BDRVQcow2State *s = state->bs->opaque; + s->compatible_features &= ~QCOW2_COMPAT_IN_USE; + ret = qcow2_update_header(state->bs); + if (ret < 0) { + goto fail; + } + } } return 0; @@ -1272,12 +1321,32 @@ fail: static void qcow2_reopen_commit(BDRVReopenState *state) { + /* We can't fail the commit, so if the header update fails, we may end up + * not protecting the image even though it is writable now. This is okay, + * the lock is a best-effort service to protect the user from shooting + * themselves into the foot. */ + if (state->bs->read_only && (state->flags & BDRV_O_RDWR)) { + BDRVQcow2State *s = state->bs->opaque; + s->compatible_features |= QCOW2_COMPAT_IN_USE; + (void) qcow2_update_header(state->bs); + } + qcow2_update_options_commit(state->bs, state->opaque); g_free(state->opaque); } static void qcow2_reopen_abort(BDRVReopenState *state) { + /* We can't fail the abort, so if the header update fails, we may end up + * not protecting the image any more. This is okay, the lock is a + * best-effort service to protect the user from shooting themselves into + * the foot. */ + if (!state->bs->read_only && !(state->flags & BDRV_O_RDWR)) { + BDRVQcow2State *s = state->bs->opaque; + s->compatible_features |= QCOW2_COMPAT_IN_USE; + (void) qcow2_update_header(state->bs); + } + qcow2_update_options_abort(state->bs, state->opaque); g_free(state->opaque); } @@ -1708,6 +1777,16 @@ static int qcow2_inactivate(BlockDriverState *bs) qcow2_mark_clean(bs); } + if (!bs->read_only) { + s->flags |= BDRV_O_INCOMING; + s->compatible_features &= ~QCOW2_COMPAT_IN_USE; + ret = qcow2_update_header(bs); + if (ret < 0) { + result = ret; + error_report("Could not update qcow2 header: %s", strerror(-ret)); + } + } + return result; } @@ -1926,6 +2005,11 @@ int qcow2_update_header(BlockDriverState *bs) .bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR, .name = "lazy refcounts", }, + { + .type = QCOW2_FEAT_TYPE_COMPATIBLE, + .bit = QCOW2_COMPAT_IN_USE_BITNR, + .name = "image is in use (locked)", + }, }; ret = header_ext_add(buf, QCOW2_EXT_MAGIC_FEATURE_TABLE, diff --git a/block/qcow2.h b/block/qcow2.h index a063a3c..7fc12f8 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -190,9 +190,12 @@ enum { /* Compatible feature bits */ enum { QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR = 0, + QCOW2_COMPAT_IN_USE_BITNR = 1, QCOW2_COMPAT_LAZY_REFCOUNTS = 1 << QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR, + QCOW2_COMPAT_IN_USE = 1 << QCOW2_COMPAT_IN_USE_BITNR, - QCOW2_COMPAT_FEAT_MASK = QCOW2_COMPAT_LAZY_REFCOUNTS, + QCOW2_COMPAT_FEAT_MASK = QCOW2_COMPAT_LAZY_REFCOUNTS + | QCOW2_COMPAT_IN_USE, }; enum qcow2_discard_type { @@ -293,6 +296,8 @@ typedef struct BDRVQcow2State { * override) */ char *image_backing_file; char *image_backing_format; + + bool override_lock; } BDRVQcow2State; typedef struct Qcow2COWRegion { diff --git a/docs/specs/qcow2.txt b/docs/specs/qcow2.txt index f236d8c..7732a23 100644 --- a/docs/specs/qcow2.txt +++ b/docs/specs/qcow2.txt @@ -96,7 +96,12 @@ in the description of a field. marking the image file dirty and postponing refcount metadata updates. - Bits 1-63: Reserved (set to 0) + Bit 1: Locking bit. If this bit is set, then the + image is supposedly in use by some process and + shouldn't be opened read-write by another + process. + + Bits 2-63: Reserved (set to 0) 88 - 95: autoclear_features Bitmask of auto-clear features. An implementation may only diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026 index ba1047c..32e1b0c 100755 --- a/tests/qemu-iotests/026 +++ b/tests/qemu-iotests/026 @@ -107,7 +107,7 @@ $QEMU_IO -c "write $vmstate 0 128k " "$BLKDBG_TEST_IMG" | _filter_qemu_io # Reads are another path to trigger l2_load, so do a read, too if [ "$event" == "l2_load" ]; then $QEMU_IO -c "write $vmstate 0 128k " "$BLKDBG_TEST_IMG" | _filter_qemu_io - $QEMU_IO -c "read $vmstate 0 128k " "$BLKDBG_TEST_IMG" | _filter_qemu_io + $QEMU_IO -r -c "read $vmstate 0 128k " "$BLKDBG_TEST_IMG" | _filter_qemu_io fi _check_test_img 2>&1 | grep -v "refcount=1 reference=0" diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out index d84d82c..86ae16f 100644 --- a/tests/qemu-iotests/026.out +++ b/tests/qemu-iotests/026.out @@ -16,6 +16,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: off; write Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error 1 leaked clusters were found on the image. @@ -25,6 +26,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: off; write -b Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error 1 leaked clusters were found on the image. @@ -44,6 +46,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: off; write Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 1 leaked clusters were found on the image. @@ -53,6 +56,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: off; write -b Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 1 leaked clusters were found on the image. @@ -80,9 +84,8 @@ wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error read failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -92,9 +95,8 @@ wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error read failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -120,9 +122,8 @@ wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device read failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -132,9 +133,8 @@ wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device read failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -152,6 +152,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 5; imm: off; once: off; write Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error 127 leaked clusters were found on the image. @@ -161,6 +162,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 5; imm: off; once: off; write -b Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error 127 leaked clusters were found on the image. @@ -180,6 +182,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 28; imm: off; once: off; write Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 127 leaked clusters were found on the image. @@ -189,6 +192,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 28; imm: off; once: off; write -b Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 127 leaked clusters were found on the image. @@ -208,6 +212,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc_write; errno: 5; imm: off; once: off; write Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -215,6 +220,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc_write; errno: 5; imm: off; once: off; write -b Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error 1 leaked clusters were found on the image. @@ -234,6 +240,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc_write; errno: 28; imm: off; once: off; write Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -241,6 +248,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc_write; errno: 28; imm: off; once: off; write -b Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 1 leaked clusters were found on the image. @@ -260,6 +268,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 5; imm: off; once: off; write Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -267,6 +276,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 5; imm: off; once: off; write -b Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -284,6 +294,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 28; imm: off; once: off; write Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -291,6 +302,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 28; imm: off; once: off; write -b Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -308,6 +320,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 5; imm: off; once: off; write Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -315,6 +328,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 5; imm: off; once: off; write -b Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -332,6 +346,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 28; imm: off; once: off; write Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -339,6 +354,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 28; imm: off; once: off; write -b Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -356,6 +372,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: off; write Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -363,6 +380,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: off; write -b Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -380,6 +398,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: off; write Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -387,6 +406,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: off; write -b Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -404,6 +424,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 5; imm: off; once: off; write Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -411,6 +432,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 5; imm: off; once: off; write -b Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -428,6 +450,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 28; imm: off; once: off; write Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -435,6 +458,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 28; imm: off; once: off; write -b Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -452,6 +476,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 5; imm: off; once: off; write Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -459,6 +484,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 5; imm: off; once: off; write -b Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -476,6 +502,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 28; imm: off; once: off; write Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -483,6 +510,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 28; imm: off; once: off; write -b Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. @@ -503,6 +531,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 55 leaked clusters were found on the image. @@ -512,6 +541,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write -b Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 251 leaked clusters were found on the image. @@ -531,6 +561,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write; errno: 28; imm: off; once: off; write Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -538,6 +569,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write; errno: 28; imm: off; once: off; write -b Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -555,6 +587,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 11 leaked clusters were found on the image. @@ -564,6 +597,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -b Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 23 leaked clusters were found on the image. @@ -583,6 +617,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 11 leaked clusters were found on the image. @@ -592,6 +627,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -b Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 23 leaked clusters were found on the image. @@ -611,6 +647,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 11 leaked clusters were found on the image. @@ -620,6 +657,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write -b Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 23 leaked clusters were found on the image. @@ -637,6 +675,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_alloc_table; errno: 5; imm: off; once: off Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -649,6 +688,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_alloc_table; errno: 28; imm: off; once: off Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -661,6 +701,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_write_table; errno: 5; imm: off; once: off Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -673,6 +714,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_write_table; errno: 28; imm: off; once: off Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -685,6 +727,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_activate_table; errno: 5; imm: off; once: off Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error write failed: Input/output error 96 leaked clusters were found on the image. @@ -699,6 +742,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_activate_table; errno: 28; imm: off; once: off Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device +Could not update qcow2 header: No space left on device write failed: No space left on device 96 leaked clusters were found on the image. diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out index 7f5050b..68a74d0 100644 --- a/tests/qemu-iotests/031.out +++ b/tests/qemu-iotests/031.out @@ -117,7 +117,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 144 +length 192 data <binary> Header extension: @@ -150,7 +150,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 144 +length 192 data <binary> Header extension: @@ -164,7 +164,7 @@ No errors were found on the image. magic 0x514649fb version 3 -backing_file_offset 0x148 +backing_file_offset 0x178 backing_file_size 0x17 cluster_bits 16 size 67108864 @@ -188,7 +188,7 @@ data 'host_device' Header extension: magic 0x6803f857 -length 144 +length 192 data <binary> Header extension: diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out index f443635..69c5756 100644 --- a/tests/qemu-iotests/036.out +++ b/tests/qemu-iotests/036.out @@ -58,7 +58,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 144 +length 192 data <binary> @@ -86,7 +86,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 144 +length 192 data <binary> *** done diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039 index 9e9b379..6f6f7c3 100755 --- a/tests/qemu-iotests/039 +++ b/tests/qemu-iotests/039 @@ -86,7 +86,7 @@ $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features echo echo "== Repairing the image file must succeed ==" -_check_test_img -r all +_check_test_img -r all --force # The dirty bit must not be set $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features @@ -109,7 +109,7 @@ $QEMU_IO -c "write -P 0x5a 0 512" \ # The dirty bit must be set $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features -$QEMU_IO -c "write 0 512" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c "open -o override-lock=on $TEST_IMG" -c "write 0 512" | _filter_qemu_io # The dirty bit must not be set $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061 index e191e65..9178e60 100755 --- a/tests/qemu-iotests/061 +++ b/tests/qemu-iotests/061 @@ -61,6 +61,7 @@ IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M $QEMU_IO -c "write -P 0x2a 0 128k" -c flush \ -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 | _filter_qemu_io $PYTHON qcow2.py "$TEST_IMG" dump-header +$QEMU_IMG force-unlock "$TEST_IMG" $QEMU_IMG amend -o "compat=0.10" "$TEST_IMG" $PYTHON qcow2.py "$TEST_IMG" dump-header $QEMU_IO -c "read -P 0x2a 0 128k" "$TEST_IMG" | _filter_qemu_io @@ -95,6 +96,7 @@ IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M $QEMU_IO -c "write -P 0x2a 0 128k" -c flush \ -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 | _filter_qemu_io $PYTHON qcow2.py "$TEST_IMG" dump-header +$QEMU_IMG force-unlock "$TEST_IMG" $QEMU_IMG amend -o "lazy_refcounts=off" "$TEST_IMG" $PYTHON qcow2.py "$TEST_IMG" dump-header $QEMU_IO -c "read -P 0x2a 0 128k" "$TEST_IMG" | _filter_qemu_io diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out index a03732e..41c9df9 100644 --- a/tests/qemu-iotests/061.out +++ b/tests/qemu-iotests/061.out @@ -26,7 +26,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 144 +length 192 data <binary> magic 0x514649fb @@ -76,14 +76,14 @@ refcount_table_clusters 1 nb_snapshots 0 snapshot_offset 0x0 incompatible_features 0x1 -compatible_features 0x1 +compatible_features 0x3 autoclear_features 0x0 refcount_order 4 header_length 104 Header extension: magic 0x6803f857 -length 144 +length 192 data <binary> ERROR cluster 5 refcount=0 reference=1 @@ -138,7 +138,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 144 +length 192 data <binary> magic 0x514649fb @@ -207,7 +207,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 144 +length 192 data <binary> read 65536/65536 bytes at offset 44040192 @@ -238,14 +238,14 @@ refcount_table_clusters 1 nb_snapshots 0 snapshot_offset 0x0 incompatible_features 0x1 -compatible_features 0x1 +compatible_features 0x3 autoclear_features 0x0 refcount_order 4 header_length 104 Header extension: magic 0x6803f857 -length 144 +length 192 data <binary> ERROR cluster 5 refcount=0 reference=1 @@ -274,7 +274,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 144 +length 192 data <binary> read 131072/131072 bytes at offset 0 diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071 index 92ab991..5ad48dd 100755 --- a/tests/qemu-iotests/071 +++ b/tests/qemu-iotests/071 @@ -85,6 +85,7 @@ $QEMU_IO -c 'write -P 42 0 512' "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \ -c 'read -P 42 0 512' | _filter_qemu_io +$QEMU_IMG force-unlock "$TEST_IMG" echo echo "=== Testing blkdebug through filename ===" @@ -92,6 +93,7 @@ echo $QEMU_IO -c "open -o file.driver=blkdebug,file.inject-error.event=l2_load $TEST_IMG" \ -c 'read -P 42 0x38000 512' +$QEMU_IMG force-unlock "$TEST_IMG" echo echo "=== Testing blkdebug through file blockref ===" @@ -99,6 +101,7 @@ echo $QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.inject-error.event=l2_load,file.image.filename=$TEST_IMG" \ -c 'read -P 42 0x38000 512' +$QEMU_IMG force-unlock "$TEST_IMG" echo echo "=== Testing blkdebug on existing block device ===" @@ -137,6 +140,7 @@ run_qemu <<EOF } { "execute": "quit" } EOF +$QEMU_IMG force-unlock "$TEST_IMG" echo echo "=== Testing blkverify on existing block device ===" @@ -176,6 +180,7 @@ run_qemu <<EOF } { "execute": "quit" } EOF +$QEMU_IMG force-unlock "$TEST_IMG" echo echo "=== Testing blkverify on existing raw block device ===" @@ -215,6 +220,7 @@ run_qemu <<EOF } { "execute": "quit" } EOF +$QEMU_IMG force-unlock "$TEST_IMG" echo echo "=== Testing blkdebug's set-state through QMP ===" @@ -268,6 +274,7 @@ run_qemu <<EOF } { "execute": "quit" } EOF +$QEMU_IMG force-unlock "$TEST_IMG" # success, all done echo "*** done" diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out index 2b40ead..b6afd6b 100644 --- a/tests/qemu-iotests/071.out +++ b/tests/qemu-iotests/071.out @@ -32,12 +32,14 @@ blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0 Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error read failed: Input/output error === Testing blkdebug through file blockref === Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error +Could not update qcow2 header: Input/output error read failed: Input/output error === Testing blkdebug on existing block device === @@ -53,6 +55,7 @@ read failed: Input/output error {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} QEMU_PROG: Failed to flush the L2 table cache: Input/output error QEMU_PROG: Failed to flush the refcount block cache: Input/output error +QEMU_PROG: Could not update qcow2 header: Input/output error === Testing blkverify on existing block device === @@ -94,5 +97,6 @@ read failed: Input/output error {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} QEMU_PROG: Failed to flush the L2 table cache: Input/output error QEMU_PROG: Failed to flush the refcount block cache: Input/output error +QEMU_PROG: Could not update qcow2 header: Input/output error *** done diff --git a/tests/qemu-iotests/089 b/tests/qemu-iotests/089 index 3e0038d..509ac9b 100755 --- a/tests/qemu-iotests/089 +++ b/tests/qemu-iotests/089 @@ -94,7 +94,7 @@ $QEMU_IO -c 'write -P 42 0x38000 512' "$TEST_IMG" | _filter_qemu_io # The "image.filename" part tests whether "a": { "b": "c" } and "a.b": "c" do # the same (which they should). -$QEMU_IO_PROG --cache $CACHEMODE \ +$QEMU_IO_PROG -r --cache $CACHEMODE \ -c 'read -P 42 0x38000 512' "json:{ \"driver\": \"$IMGFMT\", \"file\": { diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out index 5b541a3..18f5fdd 100644 --- a/tests/qemu-iotests/089.out +++ b/tests/qemu-iotests/089.out @@ -24,8 +24,6 @@ read 512/512 bytes at offset 0 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 512/512 bytes at offset 229376 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error read failed: Input/output error === Testing qemu-img info output === diff --git a/tests/qemu-iotests/091 b/tests/qemu-iotests/091 index 32bbd56..b7b0120 100755 --- a/tests/qemu-iotests/091 +++ b/tests/qemu-iotests/091 @@ -97,7 +97,7 @@ _send_qemu_cmd $h2 'qemu-io disk flush' "(qemu)" _send_qemu_cmd $h2 'quit' "" echo "Check image pattern" -${QEMU_IO} -c "read -P 0x22 0 4M" "${TEST_IMG}" | _filter_testdir | _filter_qemu_io +${QEMU_IO} -r -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 diff --git a/tests/qemu-iotests/098 b/tests/qemu-iotests/098 index e2230ad..71fbf524 100755 --- a/tests/qemu-iotests/098 +++ b/tests/qemu-iotests/098 @@ -67,7 +67,7 @@ $QEMU_IMG commit "blkdebug:$TEST_DIR/blkdebug.conf:$TEST_IMG" 2>&1 \ | _filter_testdir | _filter_imgfmt # There may be errors, but they should be fixed by opening the image -$QEMU_IO -c close "$TEST_IMG" +$QEMU_IO -c "open -o override-lock=on $TEST_IMG" -c close _check_test_img -- 1.8.3.1