[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 2/5] block/dirty-bitmap: Refactor bdrv_can_store
From: |
Vladimir Sementsov-Ogievskiy |
Subject: |
Re: [Qemu-devel] [PATCH 2/5] block/dirty-bitmap: Refactor bdrv_can_store_new_bitmap |
Date: |
Mon, 10 Jun 2019 09:29:05 +0000 |
08.06.2019 1:08, John Snow wrote:
>
>
> On 6/7/19 2:17 PM, Vladimir Sementsov-Ogievskiy wrote:
>> 07.06.2019 21:10, John Snow wrote:
>>>
>>>
>>> On 6/7/19 10:29 AM, Vladimir Sementsov-Ogievskiy wrote:
>>>> 06.06.2019 21:41, John Snow wrote:
>>>>> Instead of bdrv_can_store_new_bitmap, rework this as
>>>>> bdrv_add_persistent_dirty_bitmap. This makes a more obvious symmetry
>>>>> with bdrv_remove_persistent_dirty_bitmap. Most importantly, we are free
>>>>> to modify the driver state because we know we ARE adding a bitmap
>>>>> instead of simply being asked if we CAN store one.
>>>>>
>>>>> As part of this symmetry, move this function next to
>>>>> bdrv_remove_persistent_bitmap in block/dirty-bitmap.c.
>>>>>
>>>>> To cement this semantic distinction, use a bitmap object instead of the
>>>>> (name, granularity) pair as this allows us to set persistence as a
>>>>> condition of the "add" succeeding.
>>>>>
>>>>> Notably, the qcow2 implementation still does not actually store the new
>>>>> bitmap at add time, but merely ensures that it will be able to at store
>>>>> time.
>>>>>
>>>>> Signed-off-by: John Snow <address@hidden>
>>>>> ---
>>>>> block/qcow2.h | 5 ++---
>>>>> include/block/block.h | 2 --
>>>>> include/block/block_int.h | 5 ++---
>>>>> include/block/dirty-bitmap.h | 3 +++
>>>>> block.c | 22 ---------------------
>>>>> block/dirty-bitmap.c | 38 ++++++++++++++++++++++++++++++++++++
>>>>> block/qcow2-bitmap.c | 24 ++++++++++++++---------
>>>>> block/qcow2.c | 2 +-
>>>>> blockdev.c | 19 +++++++-----------
>>>>> 9 files changed, 68 insertions(+), 52 deletions(-)
>>>>>
>>>>> diff --git a/block/qcow2.h b/block/qcow2.h
>>>>> index fc1b0d3c1e..95d723d3c0 100644
>>>>> --- a/block/qcow2.h
>>>>> +++ b/block/qcow2.h
>>>>> @@ -742,9 +742,8 @@ int qcow2_reopen_bitmaps_rw(BlockDriverState *bs,
>>>>> Error **errp);
>>>>> int qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp);
>>>>> void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error
>>>>> **errp);
>>>>> int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
>>>>> -bool qcow2_can_store_new_dirty_bitmap(BlockDriverState *bs,
>>>>> - const char *name,
>>>>> - uint32_t granularity,
>>>>> +int qcow2_add_persistent_dirty_bitmap(BlockDriverState *bs,
>>>>> + BdrvDirtyBitmap *bitmap,
>>>>> Error **errp);
>>>>> void qcow2_remove_persistent_dirty_bitmap(BlockDriverState *bs,
>>>>> const char *name,
>>>>> diff --git a/include/block/block.h b/include/block/block.h
>>>>> index f9415ed740..6d520f3b59 100644
>>>>> --- a/include/block/block.h
>>>>> +++ b/include/block/block.h
>>>>> @@ -683,8 +683,6 @@ void bdrv_add_child(BlockDriverState *parent,
>>>>> BlockDriverState *child,
>>>>> Error **errp);
>>>>> void bdrv_del_child(BlockDriverState *parent, BdrvChild *child, Error
>>>>> **errp);
>>>>>
>>>>> -bool bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char
>>>>> *name,
>>>>> - uint32_t granularity, Error **errp);
>>>>> /**
>>>>> *
>>>>> * bdrv_register_buf/bdrv_unregister_buf:
>>>>> diff --git a/include/block/block_int.h b/include/block/block_int.h
>>>>> index 06df2bda1b..93bbb66cd0 100644
>>>>> --- a/include/block/block_int.h
>>>>> +++ b/include/block/block_int.h
>>>>> @@ -537,9 +537,8 @@ struct BlockDriver {
>>>>> * field of BlockDirtyBitmap's in case of success.
>>>>> */
>>>>> int (*bdrv_reopen_bitmaps_rw)(BlockDriverState *bs, Error **errp);
>>>>> - bool (*bdrv_can_store_new_dirty_bitmap)(BlockDriverState *bs,
>>>>> - const char *name,
>>>>> - uint32_t granularity,
>>>>> + int (*bdrv_add_persistent_dirty_bitmap)(BlockDriverState *bs,
>>>>> + BdrvDirtyBitmap *bitmap,
>>>>> Error **errp);
>>>>> void (*bdrv_remove_persistent_dirty_bitmap)(BlockDriverState *bs,
>>>>> const char *name,
>>>>> diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
>>>>> index 8044ace63e..c37edbe05f 100644
>>>>> --- a/include/block/dirty-bitmap.h
>>>>> +++ b/include/block/dirty-bitmap.h
>>>>> @@ -38,6 +38,9 @@ int bdrv_dirty_bitmap_check(const BdrvDirtyBitmap
>>>>> *bitmap, uint32_t flags,
>>>>> Error **errp);
>>>>> void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap
>>>>> *bitmap);
>>>>> void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs);
>>>>> +int bdrv_add_persistent_dirty_bitmap(BlockDriverState *bs,
>>>>> + BdrvDirtyBitmap *bitmap,
>>>>> + Error **errp);
>>>>> void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs,
>>>>> const char *name,
>>>>> Error **errp);
>>>>> diff --git a/block.c b/block.c
>>>>> index e3e77feee0..6aec36b7c9 100644
>>>>> --- a/block.c
>>>>> +++ b/block.c
>>>>> @@ -6379,25 +6379,3 @@ void bdrv_del_child(BlockDriverState *parent_bs,
>>>>> BdrvChild *child, Error **errp)
>>>>>
>>>>> parent_bs->drv->bdrv_del_child(parent_bs, child, errp);
>>>>> }
>>>>> -
>>>>> -bool bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char
>>>>> *name,
>>>>> - uint32_t granularity, Error **errp)
>>>>> -{
>>>>> - BlockDriver *drv = bs->drv;
>>>>> -
>>>>> - if (!drv) {
>>>>> - error_setg_errno(errp, ENOMEDIUM,
>>>>> - "Can't store persistent bitmaps to %s",
>>>>> - bdrv_get_device_or_node_name(bs));
>>>>> - return false;
>>>>> - }
>>>>> -
>>>>> - if (!drv->bdrv_can_store_new_dirty_bitmap) {
>>>>> - error_setg_errno(errp, ENOTSUP,
>>>>> - "Can't store persistent bitmaps to %s",
>>>>> - bdrv_get_device_or_node_name(bs));
>>>>> - return false;
>>>>> - }
>>>>> -
>>>>> - return drv->bdrv_can_store_new_dirty_bitmap(bs, name, granularity,
>>>>> errp);
>>>>> -}
>>>>> diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
>>>>> index 49646a30e6..615f8480b2 100644
>>>>> --- a/block/dirty-bitmap.c
>>>>> +++ b/block/dirty-bitmap.c
>>>>> @@ -466,6 +466,44 @@ void
>>>>> bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs,
>>>>> }
>>>>> }
>>>>>
>>>>> +int bdrv_add_persistent_dirty_bitmap(BlockDriverState *bs,
>>>>> + BdrvDirtyBitmap *bitmap,
>>>>> + Error **errp)
>>>>
>>>> strange thing for me: "bitmap" in function name is _not_ the same
>>>> thing as @bitmap argument.. as if it the same,
>>>> function adds "persistent bitmap", but @bitmap is not persistent yet,
>>>> so may be function, don't add persistent bitmap, but marks bitmap
>>>> persistent?
>>>>
>>>>
>>>> Ok, I can think of it like "add persistent dirty bitmap to driver. if
>>>> succeed, set
>>>> bitmap.persistent flag"
>>>>
>>>
>>> Yeah, I meant "Add bitmap to file", where the persistence is implied
>>> because it's part of the file. The bitmap is indeed not YET persistent,
>>> but becomes so as a condition of this call succeeding.
>>>
>>> Do you have a suggestion for a better name? I liked the symmetry with
>>> 'remove' so that there was an obvious "add bitmap" and "remove bitmap".
>>>
>>> Of course, when you remove, it is indeed persistent, so
>>> "remove_persistent_dirty_bitmap" makes sense there.
>>>
>>>>
>>>>> +{
>>>>> + BlockDriver *drv = bs->drv;
>>>>> + int ret;
>>>>> +
>>>>> + if (bdrv_dirty_bitmap_get_persistence(bitmap)) {
>>>>> + error_setg(errp, "Bitmap '%s' is already persistent, "
>>>>> + "and cannot be re-added to node '%s'",
>>>>> + bdrv_dirty_bitmap_name(bitmap),
>>>>> + bdrv_get_device_or_node_name(bs));
>>>>> + return -EINVAL;
>>>>> + }
>>>>> +
>>>>> + if (!drv) {
>>>>> + error_setg_errno(errp, ENOMEDIUM,
>>>>> + "Can't store persistent bitmaps to %s",
>>>>> + bdrv_get_device_or_node_name(bs));
>>>>> + return -ENOMEDIUM;
>>>>> + }
>>>>> +
>>>>> + if (!drv->bdrv_add_persistent_dirty_bitmap) {
>>>>> + error_setg_errno(errp, ENOTSUP,
>>>>> + "Can't store persistent bitmaps to %s",
>>>>> + bdrv_get_device_or_node_name(bs));
>>>>> + return -ENOTSUP;
>>>>> + }
>>>>> +
>>>>> + ret = drv->bdrv_add_persistent_dirty_bitmap(bs, bitmap, errp);
>>>>> + if (ret == 0) {
>>>>> + bdrv_dirty_bitmap_set_persistence(bitmap, true);
>>>>> + }
>>>>> +
>>>>> + return ret;
>>>>> +}
>>>>> +
>>>>> +
>>>>> void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
>>>>> {
>>>>> bdrv_dirty_bitmap_lock(bitmap);
>>>>> diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
>>>>> index 83aee1a42a..c3a72ca782 100644
>>>>> --- a/block/qcow2-bitmap.c
>>>>> +++ b/block/qcow2-bitmap.c
>>>>> @@ -1607,14 +1607,16 @@ int qcow2_reopen_bitmaps_ro(BlockDriverState *bs,
>>>>> Error **errp)
>>>>> return 0;
>>>>> }
>>>>>
>>>>> -bool qcow2_can_store_new_dirty_bitmap(BlockDriverState *bs,
>>>>> - const char *name,
>>>>> - uint32_t granularity,
>>>>> +int qcow2_add_persistent_dirty_bitmap(BlockDriverState *bs,
>>>>> + BdrvDirtyBitmap *bitmap,
>>>>> Error **errp)
>>>>> {
>>>>> BDRVQcow2State *s = bs->opaque;
>>>>> bool found;
>>>>> Qcow2BitmapList *bm_list;
>>>>> + const char *name = bdrv_dirty_bitmap_name(bitmap);
>>>>> + uint32_t granularity = bdrv_dirty_bitmap_granularity(bitmap);
>>>>> + int ret = 0;
>>>>
>>>> dead assignment
>>>>
>>>
>>> Will take care of.
>>>
>>>>>
>>>>> if (s->qcow_version < 3) {
>>>>> /* Without autoclear_features, we would always have to assume
>>>>> @@ -1623,20 +1625,23 @@ bool
>>>>> qcow2_can_store_new_dirty_bitmap(BlockDriverState *bs,
>>>>> * have to drop all dirty bitmaps (defeating their purpose).
>>>>> */
>>>>> error_setg(errp, "Cannot store dirty bitmaps in qcow2 v2
>>>>> files");
>>>>> + ret = -ENOTSUP;
>>>>> goto fail;
>>>>> }
>>>>>
>>>>> - if (check_constraints_on_bitmap(bs, name, granularity, errp) != 0) {
>>>>> + ret = check_constraints_on_bitmap(bs, name, granularity, errp);
>>>>> + if (ret) {
>>>>
>>>> hmm, in other places you prefere
>>>> if ((ret = ...)) {
>>>> syntax
>>>>
>>>
>>> I have to get rid of those anyway, they violate our coding style. I'll
>>> be replacing them all with this full style.
>>>
>>>>> goto fail;
>>>>> }
>>>>>
>>>>> if (s->nb_bitmaps == 0) {
>>>>> - return true;
>>>>> + return 0;
>>>>> }
>>>>>
>>>>> if (s->nb_bitmaps >= QCOW2_MAX_BITMAPS) {
>>>>> error_setg(errp,
>>>>> "Maximum number of persistent bitmaps is already
>>>>> reached");
>>>>> + ret = -EOVERFLOW;
>>>>> goto fail;
>>>>> }
>>>>>
>>>>> @@ -1644,24 +1649,25 @@ bool
>>>>> qcow2_can_store_new_dirty_bitmap(BlockDriverState *bs,
>>>>> QCOW2_MAX_BITMAP_DIRECTORY_SIZE)
>>>>> {
>>>>> error_setg(errp, "Not enough space in the bitmap directory");
>>>>> + ret = -EOVERFLOW;
>>>>> goto fail;
>>>>> }
>>>>>
>>>>> - if (bitmap_list_load(bs, &bm_list, errp)) {
>>>>> + if ((ret = bitmap_list_load(bs, &bm_list, errp))) {
>>>>
>>>> interesting, now we load all bitmaps, so, may be, we don't need to load
>>>> list every time,
>>>> but may use bs.dirty_bitmaps to check such things.. But it seems unsafe
>>>>
>>>
>>> Yeah, I would like to cache this list eventually, but I ran into a lot
>>> of hassle with it last time I tried and put it off for now.
>>>
>>> I think we should definitely be able to.
>>>
>>> And in fact, if we did, we could even add these bitmaps to the bm_list
>>> as soon as _add_ is called and drop the need for the queued counters.
>>
>> Personally I like the old _can_add_ :)
>>
>> But you want to make this function really do something with driver, so
>> "_can_" is not good
>> ofcourse and _add_ is better. And any kind of _mark_persistent_ or
>> _make_persistent_ will
>> be in a bad relation with simple setter _set_persistence() which we already
>> have and which
>> doesn't imply any complicated logic..
>>
>
> I think it's a simpler design to have "add" and "remove" callbacks and
> be more direct about it. Of course, the qcow2 implementation is free to
> avoid a write to disk on add if it wishes, but I don't like the idea of
> having to call "can_store" and then later a "do_store" or any such thing.
>
> You could say that can_store is the check and then mark persistent is
> the actual action, but then why keep them separate?
>
> I like the link between calling the driver and the later store to be
> obvious. I feel like marking the bitmap persistent without the knowledge
> or consent of the driver is bound to cause trouble sooner or later, so
> I'd rather make the persistent call a condition of the store check
> succeeding.
>
>> On the other hand I still not sure that we need track "queued" bitmaps in
>> qcow2 driver, as we
>> can calculate their number and needed size of directory in any moment, not
>> extending the qcow2
>> state..
>>
>
> Do we want to add an O(N) check because we don't want to spend 12 bytes?
We have O(N) check anyway, as we should check for existent bitmap name
--
Best regards,
Vladimir
- Re: [Qemu-devel] [PATCH 3/5] block/dirty-bitmap: rework bdrv_remove_persistent_dirty_bitmap, (continued)
- [Qemu-devel] [PATCH 2/5] block/dirty-bitmap: Refactor bdrv_can_store_new_bitmap, John Snow, 2019/06/06
- Re: [Qemu-devel] [PATCH 2/5] block/dirty-bitmap: Refactor bdrv_can_store_new_bitmap, Eric Blake, 2019/06/06
- Re: [Qemu-devel] [PATCH 2/5] block/dirty-bitmap: Refactor bdrv_can_store_new_bitmap, Vladimir Sementsov-Ogievskiy, 2019/06/07
- Re: [Qemu-devel] [PATCH 2/5] block/dirty-bitmap: Refactor bdrv_can_store_new_bitmap, John Snow, 2019/06/07
- Re: [Qemu-devel] [PATCH 2/5] block/dirty-bitmap: Refactor bdrv_can_store_new_bitmap, Eric Blake, 2019/06/07
- Re: [Qemu-devel] [PATCH 2/5] block/dirty-bitmap: Refactor bdrv_can_store_new_bitmap, Vladimir Sementsov-Ogievskiy, 2019/06/07
- Re: [Qemu-devel] [PATCH 2/5] block/dirty-bitmap: Refactor bdrv_can_store_new_bitmap, Vladimir Sementsov-Ogievskiy, 2019/06/07
- Re: [Qemu-devel] [PATCH 2/5] block/dirty-bitmap: Refactor bdrv_can_store_new_bitmap, John Snow, 2019/06/07
- Re: [Qemu-devel] [PATCH 2/5] block/dirty-bitmap: Refactor bdrv_can_store_new_bitmap,
Vladimir Sementsov-Ogievskiy <=
[Qemu-devel] [PATCH 4/5] block/qcow2-bitmap: Count queued bitmaps towards nb_bitmaps, John Snow, 2019/06/06
[Qemu-devel] [PATCH 5/5] block/qcow2-bitmap: Count queued bitmaps towards directory_size, John Snow, 2019/06/06
Re: [Qemu-devel] [PATCH 0/5] block/dirty-bitmap: check number and size constraints against queued bitmaps, no-reply, 2019/06/06