From patchwork Mon Dec 13 07:32:57 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jes Sorensen X-Patchwork-Id: 75303 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 8C808B6F11 for ; Mon, 13 Dec 2010 18:41:03 +1100 (EST) Received: from localhost ([127.0.0.1]:49768 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PS31o-0000px-G7 for incoming@patchwork.ozlabs.org; Mon, 13 Dec 2010 02:41:00 -0500 Received: from [140.186.70.92] (port=42915 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PS2uG-00064N-TZ for qemu-devel@nongnu.org; Mon, 13 Dec 2010 02:33:18 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PS2uE-00041u-Jo for qemu-devel@nongnu.org; Mon, 13 Dec 2010 02:33:12 -0500 Received: from mx1.redhat.com ([209.132.183.28]:63551) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PS2uE-00041b-8z for qemu-devel@nongnu.org; Mon, 13 Dec 2010 02:33:10 -0500 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oBD7X2jN026787 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 13 Dec 2010 02:33:03 -0500 Received: from red-feather.redhat.com (ovpn-113-46.phx2.redhat.com [10.3.113.46]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id oBD7Wxow032332; Mon, 13 Dec 2010 02:33:01 -0500 From: Jes.Sorensen@redhat.com To: kwolf@redhat.com Date: Mon, 13 Dec 2010 08:32:57 +0100 Message-Id: <1292225579-27320-2-git-send-email-Jes.Sorensen@redhat.com> In-Reply-To: <1292225579-27320-1-git-send-email-Jes.Sorensen@redhat.com> References: <1292225579-27320-1-git-send-email-Jes.Sorensen@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Cc: qemu-devel@nongnu.org, armbru@redhat.com, stefanha@linux.vnet.ibm.com Subject: [Qemu-devel] [PATCH 1/3] qemu-img.c: Re-factor img_create() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Jes Sorensen This patch re-factors img_create() moving the code doing the actual work into block.c where it can be shared with QEMU. This is needed to be able to create images from QEMU to be used for live snapshots. Signed-off-by: Jes Sorensen --- block.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ block.h | 4 ++ qemu-img.c | 106 +-------------------------------------------- 3 files changed, 147 insertions(+), 104 deletions(-) diff --git a/block.c b/block.c index 63effd8..3ab062c 100644 --- a/block.c +++ b/block.c @@ -2742,3 +2742,144 @@ int64_t bdrv_get_dirty_count(BlockDriverState *bs) { return bs->dirty_count; } + +int bdrv_img_create(const char *filename, const char *fmt, + const char *base_filename, const char *base_fmt, + char *options, uint64_t img_size, int flags) +{ + QEMUOptionParameter *param = NULL, *create_options = NULL; + BlockDriverState *bs = NULL; + BlockDriver *drv, *proto_drv; + int ret = 0; + + /* Find driver and parse its options */ + drv = bdrv_find_format(fmt); + if (!drv) { + error_report("Unknown file format '%s'", fmt); + ret = -1; + goto out; + } + + proto_drv = bdrv_find_protocol(filename); + if (!proto_drv) { + error_report("Unknown protocol '%s'", filename); + ret = -1; + goto out; + } + + create_options = append_option_parameters(create_options, + drv->create_options); + create_options = append_option_parameters(create_options, + proto_drv->create_options); + + /* Create parameter list with default values */ + param = parse_option_parameters("", create_options, param); + + set_option_parameter_int(param, BLOCK_OPT_SIZE, img_size); + + /* Parse -o options */ + if (options) { + param = parse_option_parameters(options, create_options, param); + if (param == NULL) { + error_report("Invalid options for file format '%s'.", fmt); + ret = -1; + goto out; + } + } + + if (base_filename) { + if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE, + base_filename)) { + error_report("Backing file not supported for file format '%s'", + fmt); + ret = -1; + goto out; + } + } + if (base_fmt) { + if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) { + error_report("Backing file format not supported for file " + "format '%s'", fmt); + ret = -1; + goto out; + } + } + + // The size for the image must always be specified, with one exception: + // If we are using a backing file, we can obtain the size from there + if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) { + QEMUOptionParameter *backing_file = + get_option_parameter(param, BLOCK_OPT_BACKING_FILE); + QEMUOptionParameter *backing_fmt = + get_option_parameter(param, BLOCK_OPT_BACKING_FMT); + + if (backing_file && backing_file->value.s) { + uint64_t size; + const char *fmt = NULL; + char buf[32]; + + if (backing_fmt && backing_fmt->value.s) { + if (bdrv_find_format(backing_fmt->value.s)) { + fmt = backing_fmt->value.s; + } else { + error_report("Unknown backing file format '%s'", + backing_fmt->value.s); + ret = -1; + goto out; + } + } + + bs = bdrv_new(""); + if (!bs) { + error_report("Not enough memory to allocate BlockDriverState"); + ret = -1; + goto out; + } + ret = bdrv_open(bs, backing_file->value.s, flags, drv); + if (ret < 0) { + error_report("Could not open '%s'", filename); + ret = -1; + goto out; + } + bdrv_get_geometry(bs, &size); + size *= 512; + + snprintf(buf, sizeof(buf), "%" PRId64, size); + set_option_parameter(param, BLOCK_OPT_SIZE, buf); + } else { + error_report("Image creation needs a size parameter"); + ret = -1; + goto out; + } + } + + printf("Formatting '%s', fmt=%s ", filename, fmt); + print_option_parameters(param); + puts(""); + + ret = bdrv_create(drv, filename, param); + free_option_parameters(create_options); + free_option_parameters(param); + + if (ret < 0) { + if (ret == -ENOTSUP) { + error_report("Formatting or formatting option not supported for " + "file format '%s'", fmt); + } else if (ret == -EFBIG) { + error_report("The image size is too large for file format '%s'", + fmt); + } else { + error_report("%s: error while creating %s: %s", filename, fmt, + strerror(-ret)); + } + } + +out: + if (bs) { + bdrv_delete(bs); + } + if (ret) { + return 1; + } + return 0; +} diff --git a/block.h b/block.h index 78ecfac..b812172 100644 --- a/block.h +++ b/block.h @@ -227,6 +227,10 @@ int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size); +int bdrv_img_create(const char *filename, const char *fmt, + const char *base_filename, const char *base_fmt, + char *options, uint64_t img_size, int flags); + #define BDRV_SECTORS_PER_DIRTY_CHUNK 2048 void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable); diff --git a/qemu-img.c b/qemu-img.c index f078718..603bdb3 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -287,8 +287,6 @@ static int img_create(int argc, char **argv) const char *base_fmt = NULL; const char *filename; const char *base_filename = NULL; - BlockDriver *drv, *proto_drv; - QEMUOptionParameter *param = NULL, *create_options = NULL; char *options = NULL; for(;;) { @@ -349,108 +347,8 @@ static int img_create(int argc, char **argv) goto out; } - /* Find driver and parse its options */ - drv = bdrv_find_format(fmt); - if (!drv) { - error("Unknown file format '%s'", fmt); - ret = -1; - goto out; - } - - proto_drv = bdrv_find_protocol(filename); - if (!proto_drv) { - error("Unknown protocol '%s'", filename); - ret = -1; - goto out; - } - - create_options = append_option_parameters(create_options, - drv->create_options); - create_options = append_option_parameters(create_options, - proto_drv->create_options); - - /* Create parameter list with default values */ - param = parse_option_parameters("", create_options, param); - - set_option_parameter_int(param, BLOCK_OPT_SIZE, img_size); - - /* Parse -o options */ - if (options) { - param = parse_option_parameters(options, create_options, param); - if (param == NULL) { - error("Invalid options for file format '%s'.", fmt); - ret = -1; - goto out; - } - } - - /* Add old-style options to parameters */ - ret = add_old_style_options(fmt, param, base_filename, base_fmt); - if (ret < 0) { - goto out; - } - - // The size for the image must always be specified, with one exception: - // If we are using a backing file, we can obtain the size from there - if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) { - - QEMUOptionParameter *backing_file = - get_option_parameter(param, BLOCK_OPT_BACKING_FILE); - QEMUOptionParameter *backing_fmt = - get_option_parameter(param, BLOCK_OPT_BACKING_FMT); - - if (backing_file && backing_file->value.s) { - BlockDriverState *bs; - uint64_t size; - const char *fmt = NULL; - char buf[32]; - - if (backing_fmt && backing_fmt->value.s) { - if (bdrv_find_format(backing_fmt->value.s)) { - fmt = backing_fmt->value.s; - } else { - error("Unknown backing file format '%s'", - backing_fmt->value.s); - ret = -1; - goto out; - } - } - - bs = bdrv_new_open(backing_file->value.s, fmt, BDRV_O_FLAGS); - if (!bs) { - ret = -1; - goto out; - } - bdrv_get_geometry(bs, &size); - size *= 512; - bdrv_delete(bs); - - snprintf(buf, sizeof(buf), "%" PRId64, size); - set_option_parameter(param, BLOCK_OPT_SIZE, buf); - } else { - error("Image creation needs a size parameter"); - ret = -1; - goto out; - } - } - - printf("Formatting '%s', fmt=%s ", filename, fmt); - print_option_parameters(param); - puts(""); - - ret = bdrv_create(drv, filename, param); - free_option_parameters(create_options); - free_option_parameters(param); - - if (ret < 0) { - if (ret == -ENOTSUP) { - error("Formatting or formatting option not supported for file format '%s'", fmt); - } else if (ret == -EFBIG) { - error("The image size is too large for file format '%s'", fmt); - } else { - error("%s: error while creating %s: %s", filename, fmt, strerror(-ret)); - } - } + ret = bdrv_img_create(filename, fmt, base_filename, base_fmt, + options, img_size, BDRV_O_FLAGS); out: if (ret) { return 1;