Message ID | 20250417184133.105746-16-eblake@redhat.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Make blockdev-mirror dest sparse in more cases | expand |
On Thu, Apr 17, 2025 at 01:39:08PM -0500, Eric Blake wrote: > Some BDS drivers have a cap on how much block status they can supply > in one query (for example, NBD talking to an older server cannot > inspect more than 4G per query; and qcow2 tends to cap its answers > rather than cross a cluster boundary of an L1 table). Although the > existing callers of bdrv_co_is_zero_fast are not passing in that large > of a 'bytes' parameter, an upcoming caller wants to query the entire > image at once, and will thus benefit from being able to treat adjacent > zero regions in a coalesced manner, rather than claiming the region is > non-zero merely because pnum was truncated and didn't match the > incoming bytes. > > While refactoring this into a loop, note that there is no need to > assign pnum prior to calling bdrv_co_common_block_status_above() (it > is guaranteed to be assigned deeper in the callstack). > > Signed-off-by: Eric Blake <eblake@redhat.com> > --- > block/io.c | 27 +++++++++++++++------------ > 1 file changed, 15 insertions(+), 12 deletions(-) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
diff --git a/block/io.c b/block/io.c index 73c96084e62..6ef78070915 100644 --- a/block/io.c +++ b/block/io.c @@ -2757,22 +2757,25 @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes) { int ret; - int64_t pnum = bytes; + int64_t pnum; IO_CODE(); - if (!bytes) { - return 1; + while (bytes) { + ret = bdrv_co_common_block_status_above(bs, NULL, false, + BDRV_BSTAT_ZERO, offset, bytes, + &pnum, NULL, NULL, NULL); + + if (ret < 0) { + return ret; + } + if (!(ret & BDRV_BLOCK_ZERO)) { + return 0; + } + offset += pnum; + bytes -= pnum; } - ret = bdrv_co_common_block_status_above(bs, NULL, false, BDRV_BSTAT_ZERO, - offset, bytes, &pnum, NULL, NULL, - NULL); - - if (ret < 0) { - return ret; - } - - return (pnum == bytes) && (ret & BDRV_BLOCK_ZERO); + return 1; } int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset,
Some BDS drivers have a cap on how much block status they can supply in one query (for example, NBD talking to an older server cannot inspect more than 4G per query; and qcow2 tends to cap its answers rather than cross a cluster boundary of an L1 table). Although the existing callers of bdrv_co_is_zero_fast are not passing in that large of a 'bytes' parameter, an upcoming caller wants to query the entire image at once, and will thus benefit from being able to treat adjacent zero regions in a coalesced manner, rather than claiming the region is non-zero merely because pnum was truncated and didn't match the incoming bytes. While refactoring this into a loop, note that there is no need to assign pnum prior to calling bdrv_co_common_block_status_above() (it is guaranteed to be assigned deeper in the callstack). Signed-off-by: Eric Blake <eblake@redhat.com> --- block/io.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-)