From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37092) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Vjs2Q-00028O-Vh for qemu-devel@nongnu.org; Fri, 22 Nov 2013 09:49:01 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Vjs2J-0006Va-2P for qemu-devel@nongnu.org; Fri, 22 Nov 2013 09:48:54 -0500 Received: from mx.ipv6.kamp.de ([2a02:248:0:51::16]:40489 helo=mx01.kamp.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Vjs2I-0006VV-NW for qemu-devel@nongnu.org; Fri, 22 Nov 2013 09:48:46 -0500 From: Peter Lieven Date: Fri, 22 Nov 2013 15:48:30 +0100 Message-Id: <1385131710-8978-1-git-send-email-pl@kamp.de> Subject: [Qemu-devel] [RFC][PATCH] qemu-img: add support for skipping zeroes in input during convert List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, pbonzini@redhat.com, Peter Lieven , stefanha@redhat.com Signed-off-by: Peter Lieven --- qemu-img.c | 52 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 22 deletions(-) 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", -- 1.7.9.5