@@ -782,6 +782,7 @@ bool qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
const char *name,
Error **errp);
+bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs);
ssize_t coroutine_fn
qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size,
@@ -561,6 +561,7 @@ struct BlockDriver {
uint64_t parent_perm, uint64_t parent_shared,
uint64_t *nperm, uint64_t *nshared);
+ bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs);
bool (*bdrv_co_can_store_new_dirty_bitmap)(BlockDriverState *bs,
const char *name,
uint32_t granularity,
@@ -16,6 +16,7 @@ typedef enum BitmapCheckFlags {
#define BDRV_BITMAP_MAX_NAME_SIZE 1023
+bool bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs);
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
uint32_t granularity,
const char *name,
@@ -478,6 +478,15 @@ int bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
}
}
+bool
+bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs)
+{
+ if (bs->drv && bs->drv->bdrv_supports_persistent_dirty_bitmap) {
+ return bs->drv->bdrv_supports_persistent_dirty_bitmap(bs);
+ }
+ return false;
+}
+
static bool coroutine_fn
bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
uint32_t granularity, Error **errp)
@@ -1748,3 +1748,10 @@ fail:
name, bdrv_get_device_or_node_name(bs));
return false;
}
+
+bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs)
+{
+ BDRVQcow2State *s = bs->opaque;
+
+ return s->qcow_version >= 3;
+}
@@ -5783,6 +5783,8 @@ BlockDriver bdrv_qcow2 = {
.bdrv_detach_aio_context = qcow2_detach_aio_context,
.bdrv_attach_aio_context = qcow2_attach_aio_context,
+ .bdrv_supports_persistent_dirty_bitmap =
+ qcow2_supports_persistent_dirty_bitmap,
.bdrv_co_can_store_new_dirty_bitmap = qcow2_co_can_store_new_dirty_bitmap,
.bdrv_co_remove_persistent_dirty_bitmap =
qcow2_co_remove_persistent_dirty_bitmap,