block: Make it easier to learn which BDS support bitmaps

Upcoming patches will enhance bitmap support in qemu-img, but in doing
so, it turns out to be nice to suppress output when persistent bitmaps
make no sense (such as on a qcow2 v2 image).  Add a hook to make this
easier to query.

This patch adds a new callback .bdrv_supports_persistent_dirty_bitmap,
rather than trying to shoehorn the answer in via existing callbacks.
In particular, while it might have been possible to overload
.bdrv_co_can_store_new_dirty_bitmap to special-case a NULL input to
answer whether any persistent bitmaps are supported, that is at odds
with whether a particular bitmap can be stored (for example, even on
an image that supports persistent bitmaps but has currently filled up
the maximum number of bitmaps, attempts to store another one should
fail); and the new functionality doesn't require coroutine safety.
Similarly, we could have added one more piece of information to
.bdrv_get_info, but then again, most callers to that function tend to
already discard extraneous information, and making it a catch-all
rather than a series of dedicated scalar queries hasn't really
simplified life.

In the future, when we improve the ability to look up bitmaps through
a filter, we will probably also want to teach the block layer to
automatically let filters pass this request on through.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200513011648.166876-4-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
This commit is contained in:
Eric Blake 2020-05-12 20:16:42 -05:00
parent 0562adf517
commit ef893b5c84
6 changed files with 21 additions and 0 deletions

View File

@ -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 static bool coroutine_fn
bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name, bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
uint32_t granularity, Error **errp) uint32_t granularity, Error **errp)

View File

@ -1748,3 +1748,10 @@ fail:
name, bdrv_get_device_or_node_name(bs)); name, bdrv_get_device_or_node_name(bs));
return false; return false;
} }
bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs)
{
BDRVQcow2State *s = bs->opaque;
return s->qcow_version >= 3;
}

View File

@ -5791,6 +5791,8 @@ BlockDriver bdrv_qcow2 = {
.bdrv_detach_aio_context = qcow2_detach_aio_context, .bdrv_detach_aio_context = qcow2_detach_aio_context,
.bdrv_attach_aio_context = qcow2_attach_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_can_store_new_dirty_bitmap = qcow2_co_can_store_new_dirty_bitmap,
.bdrv_co_remove_persistent_dirty_bitmap = .bdrv_co_remove_persistent_dirty_bitmap =
qcow2_co_remove_persistent_dirty_bitmap, qcow2_co_remove_persistent_dirty_bitmap,

View File

@ -782,6 +782,7 @@ bool qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
const char *name, const char *name,
Error **errp); Error **errp);
bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs);
ssize_t coroutine_fn ssize_t coroutine_fn
qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size, qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size,

View File

@ -568,6 +568,7 @@ struct BlockDriver {
uint64_t parent_perm, uint64_t parent_shared, uint64_t parent_perm, uint64_t parent_shared,
uint64_t *nperm, uint64_t *nshared); uint64_t *nperm, uint64_t *nshared);
bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs);
bool (*bdrv_co_can_store_new_dirty_bitmap)(BlockDriverState *bs, bool (*bdrv_co_can_store_new_dirty_bitmap)(BlockDriverState *bs,
const char *name, const char *name,
uint32_t granularity, uint32_t granularity,

View File

@ -16,6 +16,7 @@ typedef enum BitmapCheckFlags {
#define BDRV_BITMAP_MAX_NAME_SIZE 1023 #define BDRV_BITMAP_MAX_NAME_SIZE 1023
bool bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs);
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
uint32_t granularity, uint32_t granularity,
const char *name, const char *name,