From 74e8cfade30e514deecbeb3963b34a30ace84b58 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 31 Jan 2011 12:23:05 -0200 Subject: [PATCH 11/37] add support for protocol driver create_options RH-Author: Jes Sorensen Message-id: <1296476610-28514-2-git-send-email-Jes.Sorensen@redhat.com> Patchwork-id: 17296 O-Subject: [PATCH 01/26] add support for protocol driver create_options Bugzilla: 637701 RH-Acked-by: Alex Williamson RH-Acked-by: Marcelo Tosatti RH-Acked-by: Kevin Wolf From: MORITA Kazutaka This patch enables protocol drivers to use their create options which are not supported by the format. For example, protcol drivers can use a backing_file option with raw format. Signed-off-by: MORITA Kazutaka Signed-off-by: Kevin Wolf (cherry picked from commit b50cbabc1bc12e6b0082089c70015c1b97db86a1) --- block.c | 7 +++---- block.h | 1 + qemu-img.c | 49 ++++++++++++++++++++++++++++++++++--------------- qemu-option.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++------- qemu-option.h | 2 ++ 5 files changed, 86 insertions(+), 26 deletions(-) Signed-off-by: Luiz Capitulino --- block.c | 7 +++---- block.h | 1 + qemu-img.c | 49 ++++++++++++++++++++++++++++++++++--------------- qemu-option.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++------- qemu-option.h | 2 ++ 5 files changed, 86 insertions(+), 26 deletions(-) diff --git a/block.c b/block.c index b8f73f1..fe13c2e 100644 --- a/block.c +++ b/block.c @@ -57,7 +57,6 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors); static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors); -static BlockDriver *find_protocol(const char *filename); static QTAILQ_HEAD(, BlockDriverState) bdrv_states = QTAILQ_HEAD_INITIALIZER(bdrv_states); @@ -211,7 +210,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options) { BlockDriver *drv; - drv = find_protocol(filename); + drv = bdrv_find_protocol(filename); if (drv == NULL) { drv = bdrv_find_format("file"); } @@ -284,7 +283,7 @@ static BlockDriver *find_hdev_driver(const char *filename) return drv; } -static BlockDriver *find_protocol(const char *filename) +BlockDriver *bdrv_find_protocol(const char *filename) { BlockDriver *drv1; char protocol[128]; @@ -482,7 +481,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags) BlockDriver *drv; int ret; - drv = find_protocol(filename); + drv = bdrv_find_protocol(filename); if (!drv) { return -ENOENT; } diff --git a/block.h b/block.h index efa6ff5..705e78c 100644 --- a/block.h +++ b/block.h @@ -53,6 +53,7 @@ void bdrv_info_stats(Monitor *mon, QObject **ret_data); void bdrv_init(void); void bdrv_init_with_whitelist(void); +BlockDriver *bdrv_find_protocol(const char *filename); BlockDriver *bdrv_find_format(const char *format_name); BlockDriver *bdrv_find_whitelisted_format(const char *format_name); int bdrv_create(BlockDriver *drv, const char* filename, diff --git a/qemu-img.c b/qemu-img.c index 771016e..0744945 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -251,8 +251,8 @@ static int img_create(int argc, char **argv) const char *base_fmt = NULL; const char *filename; const char *base_filename = NULL; - BlockDriver *drv; - QEMUOptionParameter *param = NULL; + BlockDriver *drv, *proto_drv; + QEMUOptionParameter *param = NULL, *create_options = NULL; char *options = NULL; flags = 0; @@ -285,33 +285,42 @@ static int img_create(int argc, char **argv) } } + /* Get the filename */ + if (optind >= argc) + help(); + filename = argv[optind++]; + /* Find driver and parse its options */ drv = bdrv_find_format(fmt); if (!drv) error("Unknown file format '%s'", fmt); + proto_drv = bdrv_find_protocol(filename); + if (!proto_drv) + error("Unknown protocol '%s'", filename); + + create_options = append_option_parameters(create_options, + drv->create_options); + create_options = append_option_parameters(create_options, + proto_drv->create_options); + if (options && !strcmp(options, "?")) { - print_option_help(drv->create_options); + print_option_help(create_options); return 0; } /* Create parameter list with default values */ - param = parse_option_parameters("", drv->create_options, param); + param = parse_option_parameters("", create_options, param); set_option_parameter_int(param, BLOCK_OPT_SIZE, -1); /* Parse -o options */ if (options) { - param = parse_option_parameters(options, drv->create_options, param); + param = parse_option_parameters(options, create_options, param); if (param == NULL) { error("Invalid options for file format '%s'.", fmt); } } - /* Get the filename */ - if (optind >= argc) - help(); - filename = argv[optind++]; - /* Add size to parameters */ if (optind < argc) { set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]); @@ -361,6 +370,7 @@ static int img_create(int argc, char **argv) puts(""); ret = bdrv_create(drv, filename, param); + free_option_parameters(create_options); free_option_parameters(param); if (ret < 0) { @@ -577,14 +587,14 @@ static int img_convert(int argc, char **argv) { int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors; const char *fmt, *out_fmt, *out_baseimg, *out_filename; - BlockDriver *drv; + BlockDriver *drv, *proto_drv; BlockDriverState **bs, *out_bs; int64_t total_sectors, nb_sectors, sector_num, bs_offset; uint64_t bs_sectors; uint8_t * buf; const uint8_t *buf1; BlockDriverInfo bdi; - QEMUOptionParameter *param = NULL; + QEMUOptionParameter *param = NULL, *create_options = NULL; char *options = NULL; fmt = NULL; @@ -649,19 +659,27 @@ static int img_convert(int argc, char **argv) if (!drv) error("Unknown file format '%s'", out_fmt); + proto_drv = bdrv_find_protocol(out_filename); + if (!proto_drv) + error("Unknown protocol '%s'", out_filename); + + create_options = append_option_parameters(create_options, + drv->create_options); + create_options = append_option_parameters(create_options, + proto_drv->create_options); if (options && !strcmp(options, "?")) { - print_option_help(drv->create_options); + print_option_help(create_options); free(bs); return 0; } if (options) { - param = parse_option_parameters(options, drv->create_options, param); + param = parse_option_parameters(options, create_options, param); if (param == NULL) { error("Invalid options for file format '%s'.", out_fmt); } } else { - param = parse_option_parameters("", drv->create_options, param); + param = parse_option_parameters("", create_options, param); } set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512); @@ -683,6 +701,7 @@ static int img_convert(int argc, char **argv) /* Create the new image */ ret = bdrv_create(drv, out_filename, param); + free_option_parameters(create_options); free_option_parameters(param); if (ret < 0) { diff --git a/qemu-option.c b/qemu-option.c index c4e61b3..9512370 100644 --- a/qemu-option.c +++ b/qemu-option.c @@ -346,6 +346,51 @@ void free_option_parameters(QEMUOptionParameter *list) } /* + * Count valid options in list + */ +static size_t count_option_parameters(QEMUOptionParameter *list) +{ + size_t num_options = 0; + + while (list && list->name) { + num_options++; + list++; + } + + return num_options; +} + +/* + * Append an option list (list) to an option list (dest). + * + * If dest is NULL, a new copy of list is created. + * + * Returns a pointer to the first element of dest (or the newly allocated copy) + */ +QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest, + QEMUOptionParameter *list) +{ + size_t num_options, num_dest_options; + + num_options = count_option_parameters(dest); + num_dest_options = num_options; + + num_options += count_option_parameters(list); + + dest = qemu_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter)); + + while (list && list->name) { + if (get_option_parameter(dest, list->name) == NULL) { + dest[num_dest_options++] = *list; + dest[num_dest_options].name = NULL; + } + list++; + } + + return dest; +} + +/* * Parses a parameter string (param) into an option list (dest). * * list is the templace is. If dest is NULL, a new copy of list is created for @@ -365,7 +410,6 @@ void free_option_parameters(QEMUOptionParameter *list) QEMUOptionParameter *parse_option_parameters(const char *param, QEMUOptionParameter *list, QEMUOptionParameter *dest) { - QEMUOptionParameter *cur; QEMUOptionParameter *allocated = NULL; char name[256]; char value[256]; @@ -379,12 +423,7 @@ QEMUOptionParameter *parse_option_parameters(const char *param, if (dest == NULL) { // Count valid options - num_options = 0; - cur = list; - while (cur->name) { - num_options++; - cur++; - } + num_options = count_option_parameters(list); // Create a copy of the option list to fill in values dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter)); diff --git a/qemu-option.h b/qemu-option.h index a3bc061..02a1a86 100644 --- a/qemu-option.h +++ b/qemu-option.h @@ -70,6 +70,8 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name, const char *value); int set_option_parameter_int(QEMUOptionParameter *list, const char *name, uint64_t value); +QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest, + QEMUOptionParameter *list); QEMUOptionParameter *parse_option_parameters(const char *param, QEMUOptionParameter *list, QEMUOptionParameter *dest); void free_option_parameters(QEMUOptionParameter *list); -- 1.7.4.rc1.16.gd2f15e