From patchwork Tue Aug 21 05:15:14 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brad Campbell X-Patchwork-Id: 179001 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 772132C008B for ; Tue, 21 Aug 2012 18:44:26 +1000 (EST) Received: from localhost ([::1]:40786 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T3k4W-0005hT-7I for incoming@patchwork.ozlabs.org; Tue, 21 Aug 2012 04:44:24 -0400 Received: from eggs.gnu.org ([208.118.235.92]:42045) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T3hyi-0000sX-II for qemu-devel@nongnu.org; Tue, 21 Aug 2012 02:30:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1T3hyc-0000kf-CR for qemu-devel@nongnu.org; Tue, 21 Aug 2012 02:30:16 -0400 Received: from fnarfbargle.com ([93.93.131.67]:55869) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T3hyc-0000k0-3l for qemu-devel@nongnu.org; Tue, 21 Aug 2012 02:30:10 -0400 Received: from srv.homea ([10.8.0.1] helo=srv.home ident=heh23112) by fnarfbargle.com with esmtp (Exim 4.72) (envelope-from ) id 1T3goQ-0000NP-SO for qemu-devel@nongnu.org; Tue, 21 Aug 2012 06:15:35 +0100 Received: from brad by srv.home with local (Exim 4.72) (envelope-from ) id 1T3goM-00060Y-04; Tue, 21 Aug 2012 13:15:30 +0800 From: brad@fnarfbargle.com To: qemu-devel@nongnu.org Date: Tue, 21 Aug 2012 13:15:14 +0800 Message-Id: <1345526114-23046-1-git-send-email-brad@fnarfbargle.com> X-Mailer: git-send-email 1.7.2.5 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 93.93.131.67 X-Mailman-Approved-At: Tue, 21 Aug 2012 04:44:17 -0400 Cc: Brad Campbell Subject: [Qemu-devel] [PATCH] Properly use backing file argument to git-img convert X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Brad Campbell Converting to an image with an output backing file would write out the contents of the source image whether or not it was already contained in the new backing file. This commit ensures that the source file is checked against the new backing file and output is only allocated if it obsoletes or extends data already in the supplied backing file. Signed-off-by: Brad Campbell --- qemu-img.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 57 insertions(+), 17 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index c8a70ff..3fb6cbf 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -629,11 +629,12 @@ static int img_convert(int argc, char **argv) int progress = 0, flags; const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename; BlockDriver *drv, *proto_drv; - BlockDriverState **bs = NULL, *out_bs = NULL; + BlockDriverState **bs = NULL, *out_bs = NULL, *out_bf = NULL; int64_t total_sectors, nb_sectors, sector_num, bs_offset; - uint64_t bs_sectors; + uint64_t bf_sectors, bs_sectors; uint8_t * buf = NULL; const uint8_t *buf1; + uint8_t * bf_buf = NULL; BlockDriverInfo bdi; QEMUOptionParameter *param = NULL, *create_options = NULL; QEMUOptionParameter *out_baseimg_param; @@ -797,6 +798,16 @@ static int img_convert(int argc, char **argv) out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE); if (out_baseimg_param) { out_baseimg = out_baseimg_param->value.s; + + /* out_baseimg_parm != NULL even if there is no base img specified! */ + if (out_baseimg) { + out_bf = bdrv_new_open(out_baseimg, NULL, BDRV_O_FLAGS); + if (!out_bf) { + ret = -1; + goto out; + } + bdrv_get_geometry(out_bf, &bf_sectors); + } } /* Check if compression is supported */ @@ -862,6 +873,9 @@ static int img_convert(int argc, char **argv) bs_offset = 0; bdrv_get_geometry(bs[0], &bs_sectors); buf = qemu_blockalign(out_bs, IO_BUF_SIZE); + if (out_baseimg) { + bf_buf = qemu_blockalign(out_bs, IO_BUF_SIZE); + } if (compress) { ret = bdrv_get_info(out_bs, &bdi); @@ -979,31 +993,52 @@ static int img_convert(int argc, char **argv) n = bs_offset + bs_sectors - sector_num; } + ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n); + if (ret < 0) { + error_report("error while reading sector %" PRId64 ": %s", + sector_num - bs_offset, strerror(-ret)); + goto out; + } + if (has_zero_init) { /* 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). */ + check that sectors which are unallocated in the input image + are present in both the output's and input's base images (or + copy them). */ if (out_baseimg) { - if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, - n, &n1)) { - sector_num += n1; - continue; + if (sector_num < bf_sectors) { + /* Check if source sectors match those in the new backing file and + skip the copy if true. */ + n = MIN(n, bf_sectors - sector_num); + ret = bdrv_read(out_bf, sector_num - bs_offset, bf_buf, n); + if (ret < 0) { + error_report("error while reading backing file"); + goto out; + } + if (!compare_sectors(buf, bf_buf, n, &n1)) { + sector_num += n1; + continue; + } + + } else { + /* Source file(s) is larger than the backing file. Just check for + allocated sectors */ + if (!is_allocated_sectors_min(buf, n, &n1, min_sparse)) { + /* if we got zero, how many of the next ones are zero? */ + is_allocated_sectors(buf, n, &n1); + 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. */ + /* The next 'n1' sectors are allocated in the input image or the + backing files are different. Copy only those as they may be + followed by unallocated sectors. */ n = n1; } } else { 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", - sector_num - bs_offset, strerror(-ret)); - goto out; - } /* NOTE: at the same time we convert, we do not write zero sectors to have a chance to compress the image. Ideally, we should add a specific call to have the info to go faster */ @@ -1037,6 +1072,7 @@ out: free_option_parameters(create_options); free_option_parameters(param); qemu_vfree(buf); + qemu_vfree(bf_buf); if (out_bs) { bdrv_delete(out_bs); } @@ -1048,6 +1084,10 @@ out: } g_free(bs); } + if (out_bf) { + bdrv_delete(out_bf); + } + if (ret) { return 1; }