@@ -44,8 +44,9 @@
#define BME_MAX_NAME_SIZE 1023
/* Bitmap directory entry flags */
-#define BME_RESERVED_FLAGS 0xfffffffe
+#define BME_RESERVED_FLAGS 0xfffffffc
#define BME_FLAG_IN_USE 1
+#define BME_FLAG_AUTO (1U << 1)
/* bits [1, 8] U [56, 63] are reserved */
#define BME_TABLE_ENTRY_RESERVED_MASK 0xff000000000001fe
@@ -68,6 +69,9 @@ static inline bool can_write(BlockDriverState *bs)
return !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE);
}
+static BdrvDirtyBitmap *load_bitmap(BlockDriverState *bs, QCow2BitmapHeader *h,
+ Error **errp);
+
void qcow2_free_bitmaps(BlockDriverState *bs)
{
BDRVQcow2State *s = bs->opaque;
@@ -214,8 +218,31 @@ fail:
return NULL;
}
+static int load_autoload_bitmaps(BlockDriverState *bs, Error **errp)
+{
+ BDRVQcow2State *s = bs->opaque;
+ QCow2BitmapHeader *h;
+
+ for_each_bitmap_header(h, s) {
+ uint32_t fl = h->flags;
+
+ if ((fl & BME_FLAG_AUTO) && !(fl & BME_FLAG_IN_USE)) {
+ BdrvDirtyBitmap *bitmap = load_bitmap(bs, h, errp);
+ if (bitmap == NULL) {
+ return -1;
+ }
+
+ bdrv_dirty_bitmap_set_persistance(bitmap, true);
+ bdrv_dirty_bitmap_set_autoload(bitmap, true);
+ }
+ }
+
+ return 0;
+}
+
int qcow2_read_bitmaps(BlockDriverState *bs, Error **errp)
{
+ int ret;
BDRVQcow2State *s = bs->opaque;
if (s->bitmap_directory != NULL) {
@@ -234,7 +261,18 @@ int qcow2_read_bitmaps(BlockDriverState *bs, Error **errp)
return -EINVAL;
}
+ ret = load_autoload_bitmaps(bs, errp);
+ if (ret < 0) {
+ goto fail;
+ }
+
return 0;
+
+fail:
+ g_free(s->bitmap_directory);
+ s->bitmap_directory = NULL;
+
+ return ret;
}
static QCow2BitmapHeader *find_bitmap_by_name(BlockDriverState *bs,
The bitmap should be auto-loaded if auto flag is set. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> --- block/qcow2-bitmap.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-)