Message ID | 1385131710-8978-1-git-send-email-pl@kamp.de |
---|---|
State | New |
Headers | show |
On Fri, Nov 22, 2013 at 03:48:30PM +0100, Peter Lieven wrote: > - /* If the output image is being created as a copy on write image, > - assume that sectors which are unallocated in the input image > - are present in both the output's and input's base images (no > - need to copy them). */ > - if (out_baseimg) { > - ret = bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, > - n, &n1); int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum) { int64_t ret = bdrv_get_block_status(bs, sector_num, nb_sectors, pnum); if (ret < 0) { return ret; } return (ret & BDRV_BLOCK_DATA) || ((ret & BDRV_BLOCK_ZERO) && !bdrv_has_zero_init(bs)); } bdrv_has_zero_init() returns false when bs->backing_hd != NULL. > + if (out_baseimg || has_zero_init) { > + n = nb_sectors > INT_MAX ? INT_MAX : nb_sectors; > + ret = bdrv_get_block_status(bs[bs_i], sector_num - bs_offset, > + n, &n1); > if (ret < 0) { > - error_report("error while reading metadata for sector " > - "%" PRId64 ": %s", > + error_report("error while reading block status of sector %" PRId64 ": %s", > sector_num - bs_offset, strerror(-ret)); > goto out; > } > - if (!ret) { > + /* If the output image is zero initialized, we are not working > + * on a shared base and the input is zero we can skip the next > + * n1 bytes */ > + if (!out_baseimg && has_zero_init && ret & BDRV_BLOCK_ZERO) { > + sector_num += n1; > + continue; > + } > + /* If the output image is being created as a copy on write image, > + assume that sectors which are unallocated in the input image > + are present in both the output's and input's base images (no > + need to copy them). */ > + if (out_baseimg && !(ret & BDRV_BLOCK_DATA)) { > sector_num += n1; > continue; > } How are these two if statements different from bdrv_is_allocated()? Stefan
Hi Stefan, please have a look at [PATCHv2 1.8 0/9] qemu-img convert optimizations This one here is obsolete. Peter Am 02.12.2013 um 15:13 schrieb Stefan Hajnoczi <stefanha@redhat.com>: > On Fri, Nov 22, 2013 at 03:48:30PM +0100, Peter Lieven wrote: >> - /* If the output image is being created as a copy on write image, >> - assume that sectors which are unallocated in the input image >> - are present in both the output's and input's base images (no >> - need to copy them). */ >> - if (out_baseimg) { >> - ret = bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, >> - n, &n1); > > int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, > int nb_sectors, int *pnum) > { > int64_t ret = bdrv_get_block_status(bs, sector_num, nb_sectors, pnum); > if (ret < 0) { > return ret; > } > return > (ret & BDRV_BLOCK_DATA) || > ((ret & BDRV_BLOCK_ZERO) && !bdrv_has_zero_init(bs)); > } > > bdrv_has_zero_init() returns false when bs->backing_hd != NULL. > >> + if (out_baseimg || has_zero_init) { >> + n = nb_sectors > INT_MAX ? INT_MAX : nb_sectors; >> + ret = bdrv_get_block_status(bs[bs_i], sector_num - bs_offset, >> + n, &n1); >> if (ret < 0) { >> - error_report("error while reading metadata for sector " >> - "%" PRId64 ": %s", >> + error_report("error while reading block status of sector %" PRId64 ": %s", >> sector_num - bs_offset, strerror(-ret)); >> goto out; >> } >> - if (!ret) { >> + /* If the output image is zero initialized, we are not working >> + * on a shared base and the input is zero we can skip the next >> + * n1 bytes */ >> + if (!out_baseimg && has_zero_init && ret & BDRV_BLOCK_ZERO) { >> + sector_num += n1; >> + continue; >> + } >> + /* If the output image is being created as a copy on write image, >> + assume that sectors which are unallocated in the input image >> + are present in both the output's and input's base images (no >> + need to copy them). */ >> + if (out_baseimg && !(ret & BDRV_BLOCK_DATA)) { >> sector_num += n1; >> continue; >> } > > How are these two if statements different from bdrv_is_allocated()? > > Stefan
diff --git a/qemu-img.c b/qemu-img.c index b6b5644..808f8f8 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1121,8 +1121,9 @@ out3: static int img_convert(int argc, char **argv) { - int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, + int c, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors, skip_create; + int64_t ret = 0; int progress = 0, flags; const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename; BlockDriver *drv, *proto_drv; @@ -1479,11 +1480,6 @@ static int img_convert(int argc, char **argv) if (nb_sectors <= 0) { break; } - if (nb_sectors >= (IO_BUF_SIZE / 512)) { - n = (IO_BUF_SIZE / 512); - } else { - n = nb_sectors; - } while (sector_num - bs_offset >= bs_sectors) { bs_i ++; @@ -1495,34 +1491,46 @@ static int img_convert(int argc, char **argv) sector_num, bs_i, bs_offset, bs_sectors); */ } - if (n > bs_offset + bs_sectors - sector_num) { - n = bs_offset + bs_sectors - sector_num; - } - - /* If the output image is being created as a copy on write image, - assume that sectors which are unallocated in the input image - are present in both the output's and input's base images (no - need to copy them). */ - if (out_baseimg) { - ret = bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, - n, &n1); + if (out_baseimg || has_zero_init) { + n = nb_sectors > INT_MAX ? INT_MAX : nb_sectors; + ret = bdrv_get_block_status(bs[bs_i], sector_num - bs_offset, + n, &n1); if (ret < 0) { - error_report("error while reading metadata for sector " - "%" PRId64 ": %s", + error_report("error while reading block status of sector %" PRId64 ": %s", sector_num - bs_offset, strerror(-ret)); goto out; } - if (!ret) { + /* If the output image is zero initialized, we are not working + * on a shared base and the input is zero we can skip the next + * n1 bytes */ + if (!out_baseimg && has_zero_init && ret & BDRV_BLOCK_ZERO) { + sector_num += n1; + continue; + } + /* If the output image is being created as a copy on write image, + assume that sectors which are unallocated in the input image + are present in both the output's and input's base images (no + need to copy them). */ + if (out_baseimg && !(ret & BDRV_BLOCK_DATA)) { sector_num += n1; continue; } /* The next 'n1' sectors are allocated in the input image. Copy only those as they may be followed by unallocated sectors. */ - n = n1; + nb_sectors = n1; + } + + if (nb_sectors >= (IO_BUF_SIZE / 512)) { + n = (IO_BUF_SIZE / 512); } else { - n1 = n; + n = nb_sectors; + } + + if (n > bs_offset + bs_sectors - sector_num) { + n = bs_offset + bs_sectors - sector_num; } + n1 = n; ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n); if (ret < 0) { error_report("error while reading sector %" PRId64 ": %s",
Signed-off-by: Peter Lieven <pl@kamp.de> --- qemu-img.c | 52 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 22 deletions(-)