[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 10/10] qcow2: Add image locking
From: |
Kevin Wolf |
Subject: |
[Qemu-devel] [PATCH 10/10] qcow2: Add image locking |
Date: |
Tue, 22 Dec 2015 17:46:26 +0100 |
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 <address@hidden>
---
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
- Re: [Qemu-devel] [PATCH 07/10] qcow2: Implement .bdrv_inactivate, (continued)
- [Qemu-devel] [PATCH 06/10] qemu-img: Prepare for locked images, Kevin Wolf, 2015/12/22
- [Qemu-devel] [PATCH 08/10] qcow2: Fix BDRV_O_INCOMING handling in qcow2_invalidate_cache(), Kevin Wolf, 2015/12/22
- [Qemu-devel] [PATCH 09/10] qcow2: Make image inaccessible after failed qcow2_invalidate_cache(), Kevin Wolf, 2015/12/22
- [Qemu-devel] [PATCH 10/10] qcow2: Add image locking,
Kevin Wolf <=
- Re: [Qemu-devel] [PATCH 00/10] qcow2: Implement image locking, Fam Zheng, 2015/12/22
- [Qemu-devel] [PATCH 3/5] block: added check image option and callback bdrv_is_opened_unclean, Denis V. Lunev, 2015/12/23
- Re: [Qemu-devel] [PATCH 3/5] block: added check image option and callback bdrv_is_opened_unclean, Fam Zheng, 2015/12/23