From 90940728924efc80532f97877d441316aff29d00 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 31 Jan 2011 12:23:19 -0200 Subject: [PATCH 25/37] qemu-img.c: Re-factor img_create() RH-Author: Jes Sorensen Message-id: <1296476610-28514-16-git-send-email-Jes.Sorensen@redhat.com> Patchwork-id: 17308 O-Subject: [PATCH 15/26] qemu-img.c: Re-factor img_create() Bugzilla: 637701 RH-Acked-by: Alex Williamson RH-Acked-by: Marcelo Tosatti RH-Acked-by: Kevin Wolf 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 Signed-off-by: Kevin Wolf (cherry-picked from commit f88e1a4201e31cac0438df395dfcdd45ac35c17d) --- block.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ block.h | 4 ++ qemu-img.c | 108 +--------------------------------------------- 3 files changed, 147 insertions(+), 106 deletions(-) Signed-off-by: Luiz Capitulino --- block.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ block.h | 4 ++ qemu-img.c | 108 +--------------------------------------------- 3 files changed, 147 insertions(+), 106 deletions(-) diff --git a/block.c b/block.c index fe13c2e..782aca2 100644 --- a/block.c +++ b/block.c @@ -2568,3 +2568,144 @@ void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, { set_dirty_bitmap(bs, cur_sector, nr_sectors, 0); } + +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; + QEMUOptionParameter *backing_fmt; + 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; + } + } + + backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT); + if (backing_fmt && backing_fmt->value.s) { + if (!bdrv_find_format(backing_fmt->value.s)) { + error_report("Unknown backing file format '%s'", + backing_fmt->value.s); + 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); + + if (backing_file && backing_file->value.s) { + uint64_t size; + const char *fmt = NULL; + char buf[32]; + + if (backing_fmt && backing_fmt->value.s) { + fmt = backing_fmt->value.s; + } + + bs = bdrv_new(""); + + 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); + + 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: + free_option_parameters(create_options); + free_option_parameters(param); + + if (bs) { + bdrv_delete(bs); + } + if (ret) { + return 1; + } + return 0; +} diff --git a/block.h b/block.h index 705e78c..9b082c0 100644 --- a/block.h +++ b/block.h @@ -213,6 +213,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 80084df..69f6270 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -285,9 +285,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; - QEMUOptionParameter *backing_fmt = NULL; char *options = NULL; for(;;) { @@ -348,110 +345,9 @@ 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; - } - - backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT); - if (backing_fmt && backing_fmt->value.s) { - if (!bdrv_find_format(backing_fmt->value.s)) { - error("Unknown backing file format '%s'", - backing_fmt->value.s); - 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); - - 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) { - fmt = backing_fmt->value.s; - } - - 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); - - 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: - free_option_parameters(create_options); - free_option_parameters(param); if (ret) { return 1; } -- 1.7.4.rc1.16.gd2f15e