We are going to use fleecing scheme for push-backup, so that copy-before-write filter does copy before write operations to temporary image and backup job copies data from (immutable from backup's point of view) temporary image to actual backup target. For this to work properly, backup job should unshare writes on immutable source node. copy-before-write filter should do write-unchanged operations for this (they are really unchanged, as source is a backing of temporary node).
So, let's detect fleecing scheme in block-copy and do write-unchanged operations in this case. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> --- block/block-copy.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/block/block-copy.c b/block/block-copy.c index 0a9c3692bf..1a9db5794a 100644 --- a/block/block-copy.c +++ b/block/block-copy.c @@ -418,6 +418,7 @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s, int ret; int64_t nbytes = MIN(offset + bytes, s->len) - offset; void *bounce_buffer = NULL; + BdrvRequestFlags write_flags = s->write_flags; assert(offset >= 0 && bytes > 0 && INT64_MAX - offset >= bytes); assert(QEMU_IS_ALIGNED(offset, s->cluster_size)); @@ -427,8 +428,15 @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s, offset + bytes == QEMU_ALIGN_UP(s->len, s->cluster_size)); assert(nbytes < INT_MAX); + /* Detect fleecing scheme */ + if (bdrv_backing_chain_next(s->target->bs) == + bdrv_skip_filters(s->source->bs)) + { + write_flags |= BDRV_REQ_WRITE_UNCHANGED; + } + if (zeroes) { - ret = bdrv_co_pwrite_zeroes(s->target, offset, nbytes, s->write_flags & + ret = bdrv_co_pwrite_zeroes(s->target, offset, nbytes, write_flags & ~BDRV_REQ_WRITE_COMPRESSED); if (ret < 0) { trace_block_copy_write_zeroes_fail(s, offset, ret); @@ -439,7 +447,7 @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s, if (s->use_copy_range) { ret = bdrv_co_copy_range(s->source, offset, s->target, offset, nbytes, - 0, s->write_flags); + 0, write_flags); if (ret < 0) { trace_block_copy_copy_range_fail(s, offset, ret); s->use_copy_range = false; @@ -485,7 +493,7 @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s, } ret = bdrv_co_pwrite(s->target, offset, nbytes, bounce_buffer, - s->write_flags); + write_flags); if (ret < 0) { trace_block_copy_write_fail(s, offset, ret); *error_is_read = false; -- 2.29.2