@@ -417,6 +417,7 @@ static int directory_push_entry(BlockDriverState *bs, QCow2BitmapHeader *header)
int64_t new_offset = 0, old_offset = 0;
uint64_t new_size = s->bitmap_directory_size + entry_size, old_size = 0;
void *p;
+ uint64_t old_autocl;
int64_t nb_sectors = bdrv_nb_sectors(bs);
if (nb_sectors < 0) {
@@ -435,6 +436,7 @@ static int directory_push_entry(BlockDriverState *bs, QCow2BitmapHeader *header)
old_offset = s->bitmap_directory_offset;
old_size = s->bitmap_directory_size;
+ old_autocl = s->autoclear_features;
uint8_t *new_dir = g_try_malloc(new_size);
if (new_dir == NULL) {
@@ -456,6 +458,7 @@ static int directory_push_entry(BlockDriverState *bs, QCow2BitmapHeader *header)
s->bitmap_directory_offset = new_offset;
s->bitmap_directory_size = new_size;
+ s->autoclear_features |= QCOW2_AUTOCLEAR_DIRTY_BITMAPS;
ret = update_header_sync(bs);
if (ret < 0) {
@@ -477,6 +480,7 @@ fail:
qcow2_free_clusters(bs, new_offset, new_size, QCOW2_DISCARD_ALWAYS);
s->bitmap_directory_offset = old_offset;
s->bitmap_directory_size = old_size;
+ s->autoclear_features = old_autocl;
}
p = g_try_realloc(s->bitmap_directory, s->bitmap_directory_size);
@@ -163,6 +163,13 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
break;
case QCOW2_EXT_MAGIC_DIRTY_BITMAPS:
+ if (!(s->autoclear_features & QCOW2_AUTOCLEAR_DIRTY_BITMAPS)) {
+ fprintf(stderr,
+ "WARNING: bitmaps_ext: autoclear flag is not "
+ "set, all bitmaps will be considered as inconsistent");
+ break;
+ }
+
ret = bdrv_pread(bs->file->bs, offset, &bitmaps_ext, ext.len);
if (ret < 0) {
error_setg_errno(errp, -ret, "ERROR: bitmaps_ext: "
@@ -1204,8 +1211,9 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
}
/* Clear unknown autoclear feature bits */
- if (!bs->read_only && !(flags & BDRV_O_INACTIVE) && s->autoclear_features) {
- s->autoclear_features = 0;
+ if (!bs->read_only && !(flags & BDRV_O_INACTIVE) &&
+ (s->autoclear_features & ~QCOW2_AUTOCLEAR_MASK)) {
+ s->autoclear_features &= QCOW2_AUTOCLEAR_MASK;
ret = qcow2_update_header(bs);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not update qcow2 header");
@@ -220,6 +220,15 @@ enum {
QCOW2_COMPAT_FEAT_MASK = QCOW2_COMPAT_LAZY_REFCOUNTS,
};
+/* Autoclear feature bits */
+enum {
+ QCOW2_AUTOCLEAR_DIRTY_BITMAPS_BITNR = 0,
+ QCOW2_AUTOCLEAR_DIRTY_BITMAPS =
+ 1 << QCOW2_AUTOCLEAR_DIRTY_BITMAPS_BITNR,
+
+ QCOW2_AUTOCLEAR_MASK = QCOW2_AUTOCLEAR_DIRTY_BITMAPS,
+};
+
enum qcow2_discard_type {
QCOW2_DISCARD_NEVER = 0,
QCOW2_DISCARD_ALWAYS,
Add autoclear bit for handling rewriting image by old qemu version. If autoclear bit is not set, but bitmaps extension is found it would not be loaded and warning will be generated. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> --- block/qcow2-dirty-bitmap.c | 4 ++++ block/qcow2.c | 12 ++++++++++-- block/qcow2.h | 9 +++++++++ 3 files changed, 23 insertions(+), 2 deletions(-)