On 25.03.20 14:46, Vladimir Sementsov-Ogievskiy wrote:
> Comment "Called only on full-dirty region" without corresponding
> assertion is a very unsafe thing.

Not sure whether it’s that unsafe for a static function with a single
caller, but, well.

> Adding assertion means call
> bdrv_dirty_bitmap_next_zero twice. Instead, let's move
> bdrv_dirty_bitmap_next_zero call to block_copy_task_create. It also
> allows to drop cur_bytes variable which partly duplicate task->bytes.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com>
> ---
>  block/block-copy.c | 47 ++++++++++++++++++++++++----------------------
>  1 file changed, 25 insertions(+), 22 deletions(-)
> 
> diff --git a/block/block-copy.c b/block/block-copy.c
> index 63d8468b27..dd406eb4bb 100644
> --- a/block/block-copy.c
> +++ b/block/block-copy.c
> @@ -106,12 +106,23 @@ static bool coroutine_fn 
> block_copy_wait_one(BlockCopyState *s, int64_t offset,
>      return true;
>  }
>  
> -/* Called only on full-dirty region */
>  static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
>                                               int64_t offset, int64_t bytes)

A bit of documentation on the new interface might be nice.  For one
thing, that @offset must be dirty, although there is an assertion that,
well, checks it.  (An assertion doesn’t really check anything, it rather
verifies a contract.  And violation is fatal.)

For another, what the range [offset, offset + bytes) is; namely
basically the whole range of data that we might potentially copy, only
that the head must be dirty, but the tail may be clean.

Which makes me think that the interface is maybe less than intuitive.
It would make more sense if we could just call this function on the
whole region and it would figure out whether @offset is dirty by itself
(and return NULL if it isn’t).

OTOH I suppose the interface how it is here is more useful for
task-ification.  But maybe that should be documented.

>  {
> +    int64_t next_zero;
>      BlockCopyTask *task = g_new(BlockCopyTask, 1);
>  
> +    assert(bdrv_dirty_bitmap_get(s->copy_bitmap, offset));
> +
> +    bytes = MIN(bytes, s->copy_size);
> +    next_zero = bdrv_dirty_bitmap_next_zero(s->copy_bitmap, offset, bytes);
> +    if (next_zero >= 0) {
> +        assert(next_zero > offset); /* offset is dirty */
> +        assert(next_zero < offset + bytes); /* no need to do MIN() */
> +        bytes = next_zero - offset;
> +    }
> +
> +    /* region is dirty, so no existent tasks possible in it */

s/existent/existing/?

(The code movement and how you replaced cur_bytes by task->bytes looks
good.)

Max

>      assert(!find_conflicting_task(s, offset, bytes));
>  
>      bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to