aboutsummaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2020-10-27 00:05:53 -0500
committerEric Blake <eblake@redhat.com>2020-10-30 15:21:23 -0500
commita92b1b065eed385d9077be735eb8e92f5a6e150a (patch)
tree7c08e4904f939ec6e4ba8ffe1cd0d0a35daab1bf /block
parent3b1f244c59b7045680e615d50dc444a316abd891 (diff)
downloadqemu-a92b1b065eed385d9077be735eb8e92f5a6e150a.zip
qemu-a92b1b065eed385d9077be735eb8e92f5a6e150a.tar.gz
qemu-a92b1b065eed385d9077be735eb8e92f5a6e150a.tar.bz2
block: Return depth level during bdrv_is_allocated_above
When checking for allocation across a chain, it's already easy to count the depth within the chain at which the allocation is found. Instead of throwing that information away, return it to the caller. Existing callers only cared about allocated/non-allocated, but having a depth available will be used by NBD in the next patch. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <20201027050556.269064-9-eblake@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> [eblake: rebase to master] Signed-off-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'block')
-rw-r--r--block/commit.c2
-rw-r--r--block/coroutines.h6
-rw-r--r--block/io.c31
-rw-r--r--block/mirror.c2
-rw-r--r--block/stream.c2
5 files changed, 30 insertions, 13 deletions
diff --git a/block/commit.c b/block/commit.c
index 1e85c30..71db7ba 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 1cb3128..4cfb494 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 9918f24..ec5e152 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 26acf4a..8e1ad6e 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 8ce6729..236384f 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) {