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.