On Fri, 9 May 2025 15:40:28 -0500, Eric Blake wrote:
> @@ -847,8 +887,10 @@ static int coroutine_fn GRAPH_UNLOCKED 
> mirror_dirty_init(MirrorBlockJob *s)
>      bool punch_holes =
>          target_bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
>          bdrv_can_write_zeroes_with_unmap(target_bs);
> +    int64_t bitmap_length = DIV_ROUND_UP(s->bdev_length, s->granularity);
> 
>      /* Determine if the image is already zero, regardless of sync mode.  */
> +    s->zero_bitmap = bitmap_new(bitmap_length);
>      bdrv_graph_co_rdlock();
>      bs = s->mirror_top_bs->backing->bs;
>      if (s->target_is_zero) {
> @@ -862,7 +904,14 @@ static int coroutine_fn GRAPH_UNLOCKED 
> mirror_dirty_init(MirrorBlockJob *s)
>      if (ret < 0) {
>          return ret;
>      } else if (s->sync_mode == MIRROR_SYNC_MODE_TOP) {
> -        /* In TOP mode, there is no benefit to a pre-zeroing pass.  */
> +        /*
> +         * In TOP mode, there is no benefit to a pre-zeroing pass, but
> +         * the zero bitmap can be set if the destination already reads
> +         * as zero and we are not punching holes.
> +         */
> +        if (ret > 0 && !punch_holes) {
> +            bitmap_set(s->zero_bitmap, 0, bitmap_length);

It's ok when ret > 0 is obtained through bdrv_co_is_all_zeroes(target_bs). 
However,
if ret = 1 originates by target-is-zero == true from qmp_blockdev_mirror, this 
means
that target-is-zero also takes effect under sync=TOP. I am uncertain whether 
this
aligns with our intended behavior.

Under sync=TOP, target-is-zero could carry two distinct meanings:
[1] The top snapshot reads as fully zero.
[2] The entire destination snapshot chain reads as fully zero.

Currently, target-is-zero is designed to represent scenario [2] on sync=TOP.

> +        }
>      } else if (ret == 0 || punch_holes) {
>          /*
>           * Here, we are in FULL mode; our goal is to avoid writing
> @@ -871,8 +920,9 @@ static int coroutine_fn GRAPH_UNLOCKED 
> mirror_dirty_init(MirrorBlockJob *s)
>           * zeroing happened externally (ret > 0) or if we have a fast
>           * way to pre-zero the image (the dirty bitmap will be
>           * populated later by the non-zero portions, the same as for
> -         * TOP mode).  If pre-zeroing is not fast, or we need to punch
> -         * holes, then our only recourse is to write the entire image.
> +         * TOP mode).  If pre-zeroing is not fast, then our only
> +         * recourse is to mark the entire image dirty.  The act of
> +         * pre-zeroing will populate the zero bitmap.


Reply via email to