From: Denis V. Lunev <[email protected]> Move the per-task block-status query and its skip_unallocated and BDRV_BLOCK_ZERO handling out of block_copy_dirty_clusters() into block_copy_set_task_method(). No behavior change. The next patch changes that decision, and having it in one place keeps that change to just the new logic.
The block-status result no longer lands in the caller's @ret, so drop the note saying @ret may be positive at the out: label. Reviewed-by: Andrey Drobyshev <[email protected]> Signed-off-by: Denis V. Lunev <[email protected]> CC: Vladimir Sementsov-Ogievskiy <[email protected]> CC: John Snow <[email protected]> CC: Andrey Drobyshev <[email protected]> --- block/block-copy.c | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/block/block-copy.c b/block/block-copy.c index 21ebe8aec2..d71d070dbd 100644 --- a/block/block-copy.c +++ b/block/block-copy.c @@ -741,6 +741,35 @@ int64_t coroutine_fn block_copy_reset_unallocated(BlockCopyState *s, return ret; } +/* + * Decide how @task is copied: COPY_WRITE_ZEROES if it reads as zero. May + * shrink @task. Returns false if @task is to be skipped (already ended, + * not freed). + */ +static bool coroutine_fn GRAPH_RDLOCK +block_copy_set_task_method(BlockCopyState *s, BlockCopyTask *task) +{ + int ret; + int64_t status_bytes; + + ret = block_copy_block_status(s, task->req.offset, task->req.bytes, + &status_bytes); + assert(ret >= 0); /* never fail */ + if (status_bytes < task->req.bytes) { + block_copy_task_shrink(task, status_bytes); + } + if (qatomic_read(&s->skip_unallocated) && !(ret & BDRV_BLOCK_ALLOCATED)) { + block_copy_task_end(task, 0); + trace_block_copy_skip_range(s, task->req.offset, task->req.bytes); + return false; + } + if (ret & BDRV_BLOCK_ZERO) { + task->method = COPY_WRITE_ZEROES; + } + + return true; +} + /* * block_copy_dirty_clusters * @@ -773,7 +802,6 @@ block_copy_dirty_clusters(BlockCopyCallState *call_state) while (bytes && aio_task_pool_status(aio) == 0 && !qatomic_read(&call_state->cancelled)) { BlockCopyTask *task; - int64_t status_bytes; task = block_copy_task_create(s, call_state, offset, bytes); if (!task) { @@ -787,24 +815,12 @@ block_copy_dirty_clusters(BlockCopyCallState *call_state) found_dirty = true; - ret = block_copy_block_status(s, task->req.offset, task->req.bytes, - &status_bytes); - assert(ret >= 0); /* never fail */ - if (status_bytes < task->req.bytes) { - block_copy_task_shrink(task, status_bytes); - } - if (qatomic_read(&s->skip_unallocated) && - !(ret & BDRV_BLOCK_ALLOCATED)) { - block_copy_task_end(task, 0); - trace_block_copy_skip_range(s, task->req.offset, task->req.bytes); + if (!block_copy_set_task_method(s, task)) { offset = task_end(task); bytes = end - offset; g_free(task); continue; } - if (ret & BDRV_BLOCK_ZERO) { - task->method = COPY_WRITE_ZEROES; - } if (!call_state->ignore_ratelimit) { uint64_t ns = ratelimit_calculate_delay(&s->rate_limit, 0); @@ -845,8 +861,6 @@ out: * block_copy_task_run. If it fails, it means some task already failed * for real reason, let's return first failure. * Still, assert that we don't rewrite failure by success. - * - * Note: ret may be positive here because of block-status result. */ assert(ret >= 0 || aio_task_pool_status(aio) < 0); ret = aio_task_pool_status(aio); -- 2.53.0
