[Sheepdog] [PATCH] add support for protocol driver create_options

Kevin Wolf kwolf at redhat.com
Fri May 21 18:57:36 CEST 2010


Am 20.05.2010 07:36, schrieb 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 <morita.kazutaka at lab.ntt.co.jp>
> ---
>  block.c       |    7 +++----
>  block.h       |    1 +
>  qemu-img.c    |   49 ++++++++++++++++++++++++++++++++++---------------
>  qemu-option.c |   52 +++++++++++++++++++++++++++++++++++++++++++++-------
>  qemu-option.h |    2 ++
>  5 files changed, 85 insertions(+), 26 deletions(-)
> 
> diff --git a/block.c b/block.c
> index 48d8468..0ab9424 100644
> --- a/block.c
> +++ b/block.c
> @@ -56,7 +56,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);
> @@ -210,7 +209,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");
>      }
> @@ -283,7 +282,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];
> @@ -469,7 +468,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 24efeb6..9034ebb 100644
> --- a/block.h
> +++ b/block.h
> @@ -54,6 +54,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 d3c30a7..8ae7184 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -252,8 +252,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;
> @@ -286,33 +286,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++]);
> @@ -362,6 +371,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) {
> @@ -543,14 +553,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;
> @@ -615,19 +625,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);
> @@ -649,6 +667,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 076dddf..3ef4abc 100644
> --- a/qemu-option.c
> +++ b/qemu-option.c
> @@ -346,6 +346,50 @@ 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;

You need to add a dest[num_dest_options].name = NULL; here. Otherwise
the next loop iteration works on uninitialized memory and possibly an
unterminated list. I got a segfault for that reason.

Kevin



More information about the sheepdog mailing list