aboutsummaryrefslogtreecommitdiff
path: root/block/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/io.c')
-rw-r--r--block/io.c31
1 files changed, 23 insertions, 8 deletions
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