diff --git a/block/commit.c b/block/commit.c index 1e85c306cc..71db7ba747 100644 --- a/block/commit.c +++ b/block/commit.c @@ -156,7 +156,7 @@ static int coroutine_fn commit_run(Job *job, Error **errp) /* Copy if allocated above the base */ ret = bdrv_is_allocated_above(blk_bs(s->top), s->base_overlay, true, offset, COMMIT_BUFFER_SIZE, &n); - copy = (ret == 1); + copy = (ret > 0); trace_commit_one_iteration(s, offset, n, ret); if (copy) { assert(n < SIZE_MAX); diff --git a/block/coroutines.h b/block/coroutines.h index 1cb3128b94..4cfb4946e6 100644 --- a/block/coroutines.h +++ b/block/coroutines.h @@ -47,7 +47,8 @@ bdrv_co_common_block_status_above(BlockDriverState *bs, int64_t bytes, int64_t *pnum, int64_t *map, - BlockDriverState **file); + BlockDriverState **file, + int *depth); int generated_co_wrapper bdrv_common_block_status_above(BlockDriverState *bs, BlockDriverState *base, @@ -57,7 +58,8 @@ bdrv_common_block_status_above(BlockDriverState *bs, int64_t bytes, int64_t *pnum, int64_t *map, - BlockDriverState **file); + BlockDriverState **file, + int *depth); int coroutine_fn bdrv_co_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); diff --git a/block/io.c b/block/io.c index 9918f2499c..ec5e152bb7 100644 --- a/block/io.c +++ b/block/io.c @@ -2362,20 +2362,28 @@ bdrv_co_common_block_status_above(BlockDriverState *bs, int64_t bytes, int64_t *pnum, int64_t *map, - BlockDriverState **file) + BlockDriverState **file, + int *depth) { int ret; BlockDriverState *p; int64_t eof = 0; + int dummy; assert(!include_base || base); /* Can't include NULL base */ + if (!depth) { + depth = &dummy; + } + *depth = 0; + if (!include_base && bs == base) { *pnum = bytes; return 0; } ret = bdrv_co_block_status(bs, want_zero, offset, bytes, pnum, map, file); + ++*depth; if (ret < 0 || *pnum == 0 || ret & BDRV_BLOCK_ALLOCATED || bs == base) { return ret; } @@ -2392,6 +2400,7 @@ bdrv_co_common_block_status_above(BlockDriverState *bs, { ret = bdrv_co_block_status(p, want_zero, offset, bytes, pnum, map, file); + ++*depth; if (ret < 0) { return ret; } @@ -2450,7 +2459,7 @@ int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base, int64_t *map, BlockDriverState **file) { return bdrv_common_block_status_above(bs, base, false, true, offset, bytes, - pnum, map, file); + pnum, map, file, NULL); } int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes, @@ -2478,7 +2487,7 @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, } ret = bdrv_common_block_status_above(bs, NULL, false, false, offset, - bytes, &pnum, NULL, NULL); + bytes, &pnum, NULL, NULL, NULL); if (ret < 0) { return ret; @@ -2495,7 +2504,7 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset, ret = bdrv_common_block_status_above(bs, bs, true, false, offset, bytes, pnum ? pnum : &dummy, NULL, - NULL); + NULL, NULL); if (ret < 0) { return ret; } @@ -2505,8 +2514,9 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset, /* * Given an image chain: ... -> [BASE] -> [INTER1] -> [INTER2] -> [TOP] * - * Return 1 if (a prefix of) the given range is allocated in any image - * between BASE and TOP (BASE is only included if include_base is set). + * Return a positive depth if (a prefix of) the given range is allocated + * in any image between BASE and TOP (BASE is only included if include_base + * is set). Depth 1 is TOP, 2 is the first backing layer, and so forth. * BASE can be NULL to check if the given offset is allocated in any * image of the chain. Return 0 otherwise, or negative errno on * failure. @@ -2523,13 +2533,18 @@ int bdrv_is_allocated_above(BlockDriverState *top, bool include_base, int64_t offset, int64_t bytes, int64_t *pnum) { + int depth; int ret = bdrv_common_block_status_above(top, base, include_base, false, - offset, bytes, pnum, NULL, NULL); + offset, bytes, pnum, NULL, NULL, + &depth); if (ret < 0) { return ret; } - return !!(ret & BDRV_BLOCK_ALLOCATED); + if (ret & BDRV_BLOCK_ALLOCATED) { + return depth; + } + return 0; } int coroutine_fn diff --git a/block/mirror.c b/block/mirror.c index 26acf4af6f..8e1ad6eceb 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -846,7 +846,7 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s) } assert(count); - if (ret == 1) { + if (ret > 0) { bdrv_set_dirty_bitmap(s->dirty_bitmap, offset, count); } offset += count; diff --git a/block/stream.c b/block/stream.c index 8ce6729a33..236384f2f7 100644 --- a/block/stream.c +++ b/block/stream.c @@ -167,7 +167,7 @@ static int coroutine_fn stream_run(Job *job, Error **errp) n = len - offset; } - copy = (ret == 1); + copy = (ret > 0); } trace_stream_one_iteration(s, offset, n, ret); if (copy) {