@@ -817,6 +817,11 @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options,
return ret;
}
+static bool qcow2_is_opened_unclean(BlockDriverState *bs)
+{
+ return ((BDRVQcow2State *)(bs->opaque))->header_unclean;
+}
+
static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
@@ -1156,7 +1161,6 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
if (!(flags & (BDRV_O_CHECK | BDRV_O_INCOMING)) && !bs->read_only &&
(s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) {
BdrvCheckResult result = {0};
-
ret = qcow2_check(bs, &result, BDRV_FIX_ERRORS | BDRV_FIX_LEAKS);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not repair dirty image");
@@ -1170,6 +1174,9 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
qcow2_check_refcounts(bs, &result, 0);
}
#endif
+ if (flags & BDRV_O_RDWR) {
+ s->header_unclean = true;
+ }
return ret;
fail:
@@ -1691,6 +1698,7 @@ static void qcow2_close(BlockDriverState *bs)
qemu_vfree(s->l1_table);
/* else pre-write overlap checks in cache_destroy may crash */
s->l1_table = NULL;
+ s->header_unclean = false;
if (!(bs->open_flags & BDRV_O_INCOMING)) {
int ret1, ret2;
@@ -3305,6 +3313,7 @@ BlockDriver bdrv_qcow2 = {
.bdrv_co_get_block_status = qcow2_co_get_block_status,
.bdrv_set_key = qcow2_set_key,
+ .bdrv_is_opened_unclean = qcow2_is_opened_unclean,
.bdrv_co_readv = qcow2_co_readv,
.bdrv_co_writev = qcow2_co_writev,
.bdrv_co_flush_to_os = qcow2_co_flush_to_os,
@@ -278,6 +278,7 @@ typedef struct BDRVQcow2State {
int overlap_check; /* bitmask of Qcow2MetadataOverlap values */
bool signaled_corruption;
+ bool header_unclean;
uint64_t incompatible_features;
uint64_t compatible_features;
uint64_t autoclear_features;