Refactor common path to use BlockCopyCallState pointer as parameter, to prepare it for use in asynchronous block-copy (at least, we'll need to run block-copy in a coroutine, passing the whole parameters as one pointer).
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> --- block/block-copy.c | 50 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/block/block-copy.c b/block/block-copy.c index b2e7825b53..4b1a0cecbd 100644 --- a/block/block-copy.c +++ b/block/block-copy.c @@ -28,7 +28,15 @@ #define BLOCK_COPY_MAX_WORKERS 64 typedef struct BlockCopyCallState { + /* IN parameters */ + BlockCopyState *s; + int64_t offset; + int64_t bytes; + + /* State */ bool failed; + + /* OUT parameters */ bool error_is_read; } BlockCopyCallState; @@ -514,14 +522,16 @@ int64_t block_copy_reset_unallocated(BlockCopyState *s, * Returns 1 if dirty clusters found and successfully copied, 0 if no dirty * clusters found and -errno on failure. */ -static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, - int64_t offset, int64_t bytes, - bool *error_is_read) +static int coroutine_fn +block_copy_dirty_clusters(BlockCopyCallState *call_state) { + BlockCopyState *s = call_state->s; + int64_t offset = call_state->offset; + int64_t bytes = call_state->bytes; + int ret = 0; bool found_dirty = false; AioTaskPool *aio = NULL; - BlockCopyCallState call_state = {false, false}; /* * block_copy() user is responsible for keeping source and target in same @@ -546,7 +556,7 @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s, found_dirty = true; - task = block_copy_task_create(s, &call_state, offset, bytes); + task = block_copy_task_create(s, call_state, offset, bytes); ret = block_copy_block_status(s, offset, task->bytes, &status_bytes); block_copy_task_shrink(task, status_bytes); @@ -586,18 +596,14 @@ out: } g_free(aio); } - if (error_is_read && ret < 0) { - *error_is_read = call_state.error_is_read; - } return ret < 0 ? ret : found_dirty; } -int coroutine_fn block_copy(BlockCopyState *s, int64_t start, uint64_t bytes, - bool *error_is_read) +static int coroutine_fn block_copy_common(BlockCopyCallState *call_state) { while (true) { - int ret = block_copy_dirty_clusters(s, start, bytes, error_is_read); + int ret = block_copy_dirty_clusters(call_state); if (ret < 0) { /* @@ -620,7 +626,9 @@ int coroutine_fn block_copy(BlockCopyState *s, int64_t start, uint64_t bytes, * requested region. */ - if (!block_copy_wait_one(s, start, bytes)) { + if (!block_copy_wait_one(call_state->s, call_state->offset, + call_state->bytes)) + { /* No dirty bits and nothing to wait: the whole request is done */ break; } @@ -629,6 +637,24 @@ int coroutine_fn block_copy(BlockCopyState *s, int64_t start, uint64_t bytes, return 0; } +int coroutine_fn block_copy(BlockCopyState *s, int64_t start, uint64_t bytes, + bool *error_is_read) +{ + BlockCopyCallState call_state = { + .s = s, + .offset = start, + .bytes = bytes, + }; + + int ret = block_copy_common(&call_state); + + if (error_is_read && ret < 0) { + *error_is_read = call_state.error_is_read; + } + + return ret; +} + BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s) { return s->copy_bitmap; -- 2.21.0