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.