qemu-devel
[Top][All Lists]
Advanced

[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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]