qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH V12 3/4] Use QemuOpts support in block layer


From: Dong Xu Wang
Subject: Re: [Qemu-devel] [PATCH V12 3/4] Use QemuOpts support in block layer
Date: Mon, 25 Mar 2013 14:31:17 +0800

On Thu, Mar 21, 2013 at 11:31 PM, Markus Armbruster <address@hidden> wrote:
> Dong Xu Wang <address@hidden> writes:
>
>> This patch will use QemuOpts related functions in block layer, add
>> a member bdrv_create_opts to BlockDriver struct, it will return
>> a QemuOptsList pointer, which includes the image format's create
>> options.
>>
>> And create options's primary consumer is block creating related
>> functions, so modify them together.
>>
>> Signed-off-by: Dong Xu Wang <address@hidden>
>> ---
>>
>> v11->v12:
>> 1) create functions, such as qemu_opt_get_del  and qemu_opt_replace_set.
>> These functions works like origin code.
>> 2) use QEMU_OPT_SIZE, not QEMU_OPT_NUMBER.
>> 3) in bdrv_create, if opts is NULL, will create an empty one, so can
>> discard if(opts) code safely.
>>
>> v10->v11:
>> 1) qed.h move QED_DEFAULT_CLUSTER_SIZE from enum to macro, or
>> qemu_opts_print produce un-expanded cluster_size.
>> 2) In qcow2.c and qcow.c, bdrv_create_file(filename, NULL), NULL ->
>> opts,
>> or while using protocol, there will be an error.
>>
>> v8->v9:
>> 1) add qemu_ prefix to gluster_create_opts.
>> 2) fix bug: bdrv_gluster_unix and bdrv_gluster_rdma should also be
>>    converted.
>>
>> v7->v8:
>> 1) rebase to upstream source tree.
>> 2) add gluster.c, raw-win32.c, and rbd.c.
>>
>> v6->v7:
>> 1) use osdep.h:stringify(), not redefining new macro.
>> 2) preserve TODO comment.
>> 3) fix typo. BLOCK_OPT_ENCRYPT->BLOCK_OPT_STATIC.
>> 4) initialize disk_type even when opts is NULL.
>>
>> v5->v6:
>> 1) judge if opts == NULL in block layer create functions.
>> 2) use bdrv_create_file(filename, NULL) in qcow_create and cow_create
>> funtion.
>> 3) made more readable while using qemu_opt_get_number.
>>
>>
>>  block.c                   |  91 ++++++++++++------------
>>  block/cow.c               |  46 ++++++------
>>  block/gluster.c           |  37 +++++-----
>>  block/iscsi.c             |   8 +--
>>  block/qcow.c              |  61 ++++++++--------
>>  block/qcow2.c             | 173 
>> +++++++++++++++++++++++-----------------------
>>  block/qed.c               |  86 +++++++++++------------
>>  block/qed.h               |   2 +-
>>  block/raw-posix.c         |  59 +++++++---------
>>  block/raw-win32.c         |  31 +++++----
>>  block/raw.c               |  30 ++++----
>>  block/rbd.c               |  62 ++++++++---------
>>  block/sheepdog.c          |  75 ++++++++++----------
>>  block/vdi.c               |  70 +++++++++----------
>>  block/vmdk.c              |  90 ++++++++++++------------
>>  block/vpc.c               |  57 +++++++--------
>>  block/vvfat.c             |  11 +--
>>  include/block/block.h     |   4 +-
>>  include/block/block_int.h |   6 +-
>>  include/qemu/option.h     |  13 +++-
>>  qemu-img.c                |  61 ++++++++--------
>>  util/qemu-option.c        |  93 +++++++++++++++++++++++--
>>  22 files changed, 613 insertions(+), 553 deletions(-)
>
> *Ouch*
>
> Any chance to split this patch up some?  Its size makes it really hard
> to review...
>
I will split this patch into some small patches in next version.

>> diff --git a/block.c b/block.c
>> index 4582961..975c3d8 100644
>> --- a/block.c
>> +++ b/block.c
>> @@ -357,7 +357,7 @@ BlockDriver *bdrv_find_whitelisted_format(const char 
>> *format_name)
>>  typedef struct CreateCo {
>>      BlockDriver *drv;
>>      char *filename;
>> -    QEMUOptionParameter *options;
>> +    QemuOpts *opts;
>>      int ret;
>>  } CreateCo;
>>
>> @@ -366,11 +366,11 @@ static void coroutine_fn bdrv_create_co_entry(void 
>> *opaque)
>>      CreateCo *cco = opaque;
>>      assert(cco->drv);
>>
>> -    cco->ret = cco->drv->bdrv_create(cco->filename, cco->options);
>> +    cco->ret = cco->drv->bdrv_create(cco->filename, cco->opts);
>>  }
>>
>>  int bdrv_create(BlockDriver *drv, const char* filename,
>> -    QEMUOptionParameter *options)
>> +    QemuOpts *opts)
>
> Since you touch this anyway, consider unbreaking the line:
>
> int bdrv_create(BlockDriver *drv, const char* filename, QemuOpts *opts)
>
Okay.
>>  {
>>      int ret;
>>
>> @@ -378,7 +378,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
>>      CreateCo cco = {
>>          .drv = drv,
>>          .filename = g_strdup(filename),
>> -        .options = options,
>> +        .opts = opts ?: qemu_opts_create_nofail(drv->bdrv_create_opts),
>>          .ret = NOT_DONE,
>>      };
>>
>
> As discussed during review of v11, this avoids passing null opts to the
> bdrv_create() method.  Good.
>
>> @@ -405,7 +405,7 @@ out:
>    out:
>        g_free(cco.filename);
>>      return ret;
>>  }
>
> I suspect you need
>
>     if (!opts) {
>         qemu_opts_del(cco->opts);
>     }
>
> to avoid leaking the empty cco->opts you create in the previous hunk.
>
Okay.
>>
>> -int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
>> +int bdrv_create_file(const char *filename, QemuOpts *opts)
>>  {
>>      BlockDriver *drv;
>>
>> @@ -414,7 +414,7 @@ int bdrv_create_file(const char* filename, 
>> QEMUOptionParameter *options)
>>          return -ENOENT;
>>      }
>>
>> -    return bdrv_create(drv, filename, options);
>> +    return bdrv_create(drv, filename, opts);
>>  }
>>
>>  /*
>> @@ -814,7 +814,7 @@ int bdrv_open(BlockDriverState *bs, const char 
>> *filename, int flags,
>>          int64_t total_size;
>>          int is_protocol = 0;
>>          BlockDriver *bdrv_qcow2;
>> -        QEMUOptionParameter *options;
>> +        QemuOpts *opts;
>>          char backing_filename[PATH_MAX];
>>
>>          /* if snapshot, we create a temporary backing file and open it
>> @@ -847,17 +847,16 @@ int bdrv_open(BlockDriverState *bs, const char 
>> *filename, int flags,
>>              return -errno;
>>
>>          bdrv_qcow2 = bdrv_find_format("qcow2");
>> -        options = parse_option_parameters("", bdrv_qcow2->create_options, 
>> NULL);
>> +        opts = qemu_opts_create_nofail(bdrv_qcow2->bdrv_create_opts);
>>
>> -        set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size);
>> -        set_option_parameter(options, BLOCK_OPT_BACKING_FILE, 
>> backing_filename);
>> +        qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_size);
>> +        qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, backing_filename);
>>          if (drv) {
>> -            set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
>> -                drv->format_name);
>> +            qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, drv->format_name);
>>          }
>>
>> -        ret = bdrv_create(bdrv_qcow2, tmp_filename, options);
>> -        free_option_parameters(options);
>> +        ret = bdrv_create(bdrv_qcow2, tmp_filename, opts);
>> +        qemu_opts_del(opts);
>>          if (ret < 0) {
>>              return ret;
>>          }
>> @@ -4502,8 +4501,10 @@ void bdrv_img_create(const char *filename, const char 
>> *fmt,
>>                       char *options, uint64_t img_size, int flags,
>>                       Error **errp, bool quiet)
>>  {
>> -    QEMUOptionParameter *param = NULL, *create_options = NULL;
>> -    QEMUOptionParameter *backing_fmt, *backing_file, *size;
>> +    QemuOpts *opts = NULL;
>> +    QemuOptsList *create_opts = NULL;
>> +    const char *backing_fmt, *backing_file;
>> +    int64_t size;
>>      BlockDriverState *bs = NULL;
>>      BlockDriver *drv, *proto_drv;
>>      BlockDriver *backing_drv = NULL;
>> @@ -4521,28 +4522,23 @@ void bdrv_img_create(const char *filename, const 
>> char *fmt,
>>          error_setg(errp, "Unknown protocol '%s'", filename);
>>          return;
>>      }
>> -
>> -    create_options = append_option_parameters(create_options,
>> -                                              drv->create_options);
>> -    create_options = append_option_parameters(create_options,
>> -                                              proto_drv->create_options);
>> -
>> +    create_opts = qemu_opts_append(drv->bdrv_create_opts,
>> +                                   proto_drv->bdrv_create_opts);
>
> qemu_opts_append() dereferences its arguments to compute
>
>     dest->merge_lists = first->merge_lists || second->merge_lists;
>
> However, either of drv->create_opts and proto_drv->create_opts may be
> null, as far as I can see.  If I'm correct, you need a few more test
> cases :)
>
Okay, will check first and second.
> Before: format's options get appended first, then protocol's options.
> Because get_option_parameter() searches in order, format options shadow
> protocol options.
>
> After: append_opts_list() gives first argument's options precedence.
>
> Thus, no change.  Good.
>
> Should bdrv_create_options option name clashes be avoided?  Beyond the
> scope of this patch.
>
>>      /* Create parameter list with default values */
>> -    param = parse_option_parameters("", create_options, param);
>> +    opts = qemu_opts_create_nofail(create_opts);
>
> Before: param empty.
>
> After: opts empty.
>
> Good.
>
>>
>> -    set_option_parameter_int(param, BLOCK_OPT_SIZE, img_size);
>> +    qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size);
>
> Before: param contains exactly BLOCK_OPT_SIZE = img_size.
>
> After: opts contains exactly BLOCK_OPT_SIZE = img_size.
>
> Both old and new code seem to assume BLOCK_OPT_SIZE is always a valid
> option.  Beyond the scope of this patch.
>
> Good.
>
>>
>>      /* Parse -o options */
>>      if (options) {
>> -        param = parse_option_parameters(options, create_options, param);
>> -        if (param == NULL) {
>> +        if (qemu_opts_do_parse_replace(opts, options, NULL) != 0) {
>>              error_setg(errp, "Invalid options for file format '%s'.", fmt);
>>              goto out;
>>          }
>>      }
>
> Before: values from -o replace whatever is in param already.
>
> After: values from -o replace whatever is in opts already.
>
> In particular, size from -o replaces img_size before and after.
>
> Did you test it does?
>
>     $ qemu-img create -f raw -o size=1024 t.img 512
>     Formatting 't.img', fmt=raw size=1024
>     $ ls -l t.img
>     -rw-r--r--. 1 armbru armbru 1024 Mar 21 15:12 t.img
>
>>
>>      if (base_filename) {
>> -        if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE,
>> +        if (qemu_opt_replace_set(opts, BLOCK_OPT_BACKING_FILE,
>>                                   base_filename)) {
>>              error_setg(errp, "Backing file not supported for file format 
>> '%s'",
>>                         fmt);
>
> Before: base_filename replaces any backing_file from -o in param.
>
> After: base_filename replaces any backing_file from -o in opts.
>
> Did you test it does?
>
Oh, I did not test command line like this, my patch will fail here.
Will fix in next version.

>     $ qemu-img create -f qcow2 -b t.img -o backing_file=/dev/null t.qcow2
>     Formatting 't.qcow2', fmt=qcow2 size=1024 backing_file='t.img' 
> encryption=off cluster_size=65536 lazy_refcounts=off
>     $ qemu-img info t.qcow2image: t.qcow2
>     file format: qcow2
>     virtual size: 1.0K (1024 bytes)
>     disk size: 196K
>     cluster_size: 65536
>     backing file: t.img
>

I run this command using upstream QEMU code, but failed.
address@hidden@VM:~]$ qemu-img info t.qcow2image: t.qcow2
qemu-img: Could not open 't.qcow2image:': No such file or directory

Or did I type something wrong?

>> @@ -4551,39 +4547,37 @@ void bdrv_img_create(const char *filename, const 
>> char *fmt,
>>      }
>>
>>      if (base_fmt) {
>> -        if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) {
>> +        if (qemu_opt_replace_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt)) {
>>              error_setg(errp, "Backing file format not supported for file "
>>                               "format '%s'", fmt);
>>              goto out;
>>          }
>>      }
>
> Likewise.
>
> Did you test?
>
>     $ qemu-img create -f qcow2 -b t.img -F file -o 
> backing_file=/dev/null,backing_fmt=host_device t.qcow2
>     Formatting 't.qcow2', fmt=qcow2 size=1024 backing_file='t.img' 
> backing_fmt='file' encryption=off cluster_size=65536 lazy_refcounts=off
>     $ qemu-img info t.qcow2image: t.qcow2
>     file format: qcow2
>     virtual size: 1.0K (1024 bytes)
>     disk size: 196K
>     cluster_size: 65536
>     backing file: t.img
>     backing file format: file
>
>>
>> -    backing_file = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
>> -    if (backing_file && backing_file->value.s) {
>> -        if (!strcmp(filename, backing_file->value.s)) {
>> +    backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
>> +    if (backing_file) {
>> +        if (!strcmp(filename, backing_file)) {
>>              error_setg(errp, "Error: Trying to create an image with the "
>>                               "same filename as the backing file");
>>              goto out;
>>          }
>>      }
>>
>> -    backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
>> -    if (backing_fmt && backing_fmt->value.s) {
>> -        backing_drv = bdrv_find_format(backing_fmt->value.s);
>> +    backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
>> +    if (backing_fmt) {
>> +        backing_drv = bdrv_find_format(backing_fmt);
>>          if (!backing_drv) {
>> -            error_setg(errp, "Unknown backing file format '%s'",
>> -                       backing_fmt->value.s);
>> +            error_setg(errp, "Unknown backing file format '%s'", 
>> backing_fmt);
>>              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
>> -    size = get_option_parameter(param, BLOCK_OPT_SIZE);
>> -    if (size && size->value.n == -1) {
>> -        if (backing_file && backing_file->value.s) {
>> +    size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
>> +    if (size == -1) {
>> +        if (backing_file) {
>>              uint64_t size;
>> -            char buf[32];
>>              int back_flags;
>>
>>              /* backing files always opened read-only */
>> @@ -4592,17 +4586,16 @@ void bdrv_img_create(const char *filename, const 
>> char *fmt,
>>
>>              bs = bdrv_new("");
>>
>> -            ret = bdrv_open(bs, backing_file->value.s, back_flags, 
>> backing_drv);
>> +            ret = bdrv_open(bs, backing_file, back_flags, backing_drv);
>>              if (ret < 0) {
>>                  error_setg_errno(errp, -ret, "Could not open '%s'",
>> -                                 backing_file->value.s);
>> +                                 backing_file);
>>                  goto out;
>>              }
>>              bdrv_get_geometry(bs, &size);
>>              size *= 512;
>>
>> -            snprintf(buf, sizeof(buf), "%" PRId64, size);
>> -            set_option_parameter(param, BLOCK_OPT_SIZE, buf);
>> +            qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size);
>
> We get here only when opts doesn't have BLOCK_OPT_SIZE.
>
> Good.
>
>>          } else {
>>              error_setg(errp, "Image creation needs a size parameter");
>>              goto out;
>> @@ -4611,10 +4604,10 @@ void bdrv_img_create(const char *filename, const 
>> char *fmt,
>>
>>      if (!quiet) {
>>          printf("Formatting '%s', fmt=%s ", filename, fmt);
>> -        print_option_parameters(param);
>> +        qemu_opts_print(opts, NULL);
>>          puts("");
>>      }
>
> Before:
>
> param[] contains all valid options.  If the option in param[i] hasn't
> been set, param[i].value still has the default value defined in the
> .create_options[] where we got this option.
>
> print_option_parameters() iterates over all valid options, and prints
> NAME=VALUE.  Except it prints nothing for an option of type OPT_STRING
> when the value is null.  That's the case when the default is null and
> the option hasn't been set.
>
> After:
>
> opts contains only the options that have been set.  opts->list->desc[]
> contains all valid options (or is empty, which means "accept all", but
> that shouldn't happen here).
>
> qemu_opts_print() in master prints only the options that have been set.
> Differs from print_option_parameters() for unset options.  That's why
> you rewrite qemu_opts_print() in PATCH 1/4.
>
> The rewritten qemu_opts_print() prints all all valid options, except
> unset ones that have a null def_value_str.
>
> Therefore:
>
> * OPT_STRING parameters need to become QEMU_OPT_STRING options, and
>   their default value needs to go both into def_value_str *and* into
>   every caller's handling of qemu_opt_get() returning null.
>
> * OPT_FLAG, OPT_NUMBER, OPT_STRING parameters need to become
>   QEMU_OPT_BOOL, QEMU_OPT_NUMBER, QEMU_OPT_SIZE options, and their
>   default value needs to go both into def_value_str *and* into the last
>   argument of every qemu_opt_bool() getting it.
>
> I hate how the default value needs to go in multiple places now.  More
> on that in my forthcoming review of PATCH 1/4.
>
>> -    ret = bdrv_create(drv, filename, param);
>> +    ret = bdrv_create(drv, filename, opts);
>>      if (ret < 0) {
>>          if (ret == -ENOTSUP) {
>>              error_setg(errp,"Formatting or formatting option not supported 
>> for "
>> @@ -4629,8 +4622,10 @@ void bdrv_img_create(const char *filename, const char 
>> *fmt,
>>      }
>>
>>  out:
>> -    free_option_parameters(create_options);
>> -    free_option_parameters(param);
>> +    qemu_opts_free(create_opts);
>> +    if (opts) {
>> +        qemu_opts_del(opts);
>> +    }
>>
>>      if (bs) {
>>          bdrv_delete(bs);
>> diff --git a/block/cow.c b/block/cow.c
>> index 4baf904..135fa33 100644
>> --- a/block/cow.c
>> +++ b/block/cow.c
>> @@ -255,7 +255,7 @@ static void cow_close(BlockDriverState *bs)
>>  {
>>  }
>>
>> -static int cow_create(const char *filename, QEMUOptionParameter *options)
>> +static int cow_create(const char *filename, QemuOpts *opts)
>>  {
>>      struct cow_header_v2 cow_header;
>>      struct stat st;
>> @@ -264,17 +264,11 @@ static int cow_create(const char *filename, 
>> QEMUOptionParameter *options)
>>      int ret;
>>      BlockDriverState *cow_bs;
>>
>> -    /* Read out options */
>> -    while (options && options->name) {
>> -        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
>> -            image_sectors = options->value.n / 512;
>> -        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
>> -            image_filename = options->value.s;
>> -        }
>> -        options++;
>> -    }
>> +    /* Read out opts */
>> +    image_sectors = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512;
>> +    image_filename = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
>
> Why _del?
>

Before: after getting one parameter, then option++, so in my patches, I want to
delete the opt after using it. If I did not delete it, some parameters
will be passed
to "protocol", it will go wrong. Do you think it is acceptable?

>>
>> -    ret = bdrv_create_file(filename, options);
>> +    ret = bdrv_create_file(filename, opts);
>>      if (ret < 0) {
>>          return ret;
>>      }
>> @@ -318,18 +312,22 @@ exit:
>>      return ret;
>>  }
>>
>> -static QEMUOptionParameter cow_create_options[] = {
>> -    {
>> -        .name = BLOCK_OPT_SIZE,
>> -        .type = OPT_SIZE,
>> -        .help = "Virtual disk size"
>> -    },
>> -    {
>> -        .name = BLOCK_OPT_BACKING_FILE,
>> -        .type = OPT_STRING,
>> -        .help = "File name of a base image"
>> -    },
>> -    { NULL }
>> +static QemuOptsList cow_create_opts = {
>> +    .name = "cow-create-opts",
>> +    .head = QTAILQ_HEAD_INITIALIZER(cow_create_opts.head),
>> +    .desc = {
>> +        {
>> +            .name = BLOCK_OPT_SIZE,
>> +            .type = QEMU_OPT_SIZE,
>> +            .help = "Virtual disk size"
>> +        },
>> +        {
>> +            .name = BLOCK_OPT_BACKING_FILE,
>> +            .type = QEMU_OPT_STRING,
>> +            .help = "File name of a base image"
>> +        },
>> +        { /* end of list */ }
>> +    }
>>  };
>>
>>  static BlockDriver bdrv_cow = {
>> @@ -345,7 +343,7 @@ static BlockDriver bdrv_cow = {
>>      .bdrv_write             = cow_co_write,
>>      .bdrv_co_is_allocated   = cow_co_is_allocated,
>>
>> -    .create_options = cow_create_options,
>> +    .bdrv_create_opts       = &cow_create_opts,
>>  };
>>
>>  static void bdrv_cow_init(void)
> [Boatload of drivers snipped; not reviewed in this round]
>> diff --git a/include/block/block.h b/include/block/block.h
>> index 0f750d7..a477b7a 100644
>> --- a/include/block/block.h
>> +++ b/include/block/block.h
>> @@ -126,8 +126,8 @@ 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,
>> -    QEMUOptionParameter *options);
>> -int bdrv_create_file(const char* filename, QEMUOptionParameter *options);
>> +    QemuOpts *options);
>> +int bdrv_create_file(const char *filename, QemuOpts *options);
>
> QemuOpts *opts
>

Okay.

>>  BlockDriverState *bdrv_new(const char *device_name);
>>  void bdrv_make_anon(BlockDriverState *bs);
>>  void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
>> diff --git a/include/block/block_int.h b/include/block/block_int.h
>> index eaad53e..4f942ef 100644
>> --- a/include/block/block_int.h
>> +++ b/include/block/block_int.h
>> @@ -90,7 +90,7 @@ struct BlockDriver {
>>                        const uint8_t *buf, int nb_sectors);
>>      void (*bdrv_close)(BlockDriverState *bs);
>>      void (*bdrv_rebind)(BlockDriverState *bs);
>> -    int (*bdrv_create)(const char *filename, QEMUOptionParameter *options);
>> +    int (*bdrv_create)(const char *filename, QemuOpts *options);
>
> QemuOpts *opts
>
>>      int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
>>      int (*bdrv_make_empty)(BlockDriverState *bs);
>>      /* aio */
>> @@ -179,9 +179,7 @@ struct BlockDriver {
>>          unsigned long int req, void *buf,
>>          BlockDriverCompletionFunc *cb, void *opaque);
>>
>> -    /* List of options for creating images, terminated by name == NULL */
>> -    QEMUOptionParameter *create_options;
>> -
>> +    QemuOptsList *bdrv_create_opts;
>>
>>      /*
>>       * Returns 0 for completed check, -errno for internal errors.
>> diff --git a/include/qemu/option.h b/include/qemu/option.h
>> index c58db43..0d5fb66 100644
>> --- a/include/qemu/option.h
>> +++ b/include/qemu/option.h
>> @@ -108,6 +108,7 @@ struct QemuOptsList {
>>  };
>>
>>  const char *qemu_opt_get(QemuOpts *opts, const char *name);
>> +const char *qemu_opt_get_del(QemuOpts *opts, const char *name);
>>  /**
>>   * qemu_opt_has_help_opt:
>>   * @opts: options to search for a help request
>> @@ -121,9 +122,13 @@ const char *qemu_opt_get(QemuOpts *opts, const char 
>> *name);
>>   */
>>  bool qemu_opt_has_help_opt(QemuOpts *opts);
>>  bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
>> +bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval);
>>  uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t 
>> defval);
>>  uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t 
>> defval);
>> +uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
>> +                               uint64_t defval);
>>  int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
>> +int qemu_opt_replace_set(QemuOpts *opts, const char *name, const char 
>> *value);
>>  void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
>>                        Error **errp);
>>  int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val);
>> @@ -144,7 +149,10 @@ const char *qemu_opts_id(QemuOpts *opts);
>>  void qemu_opts_del(QemuOpts *opts);
>>  void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error 
>> **errp);
>>  int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char 
>> *firstname);
>> -QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int 
>> permit_abbrev);
>> +int qemu_opts_do_parse_replace(QemuOpts *opts, const char *params,
>> +                               const char *firstname);
>> +QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
>> +                          int permit_abbrev);
>>  void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
>>                              int permit_abbrev);
>>  QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
>
> Putting these new qemu_opt_*() functions in their own patch would reduce
> this patch's size a little.
>
>> @@ -156,8 +164,7 @@ int qemu_opts_print(QemuOpts *opts, void *dummy);
>>  int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void 
>> *opaque,
>>                        int abort_on_failure);
>>
>> -QemuOptsList *qemu_opts_append(QemuOptsList *first,
>> -                               QemuOptsList *second);
>> +QemuOptsList *qemu_opts_append(QemuOptsList *first, QemuOptsList *second);
>>  void qemu_opts_free(QemuOptsList *list);
>>  void qemu_opts_print_help(QemuOptsList *list);
>>  #endif
>> diff --git a/qemu-img.c b/qemu-img.c
>> index 471de7d..9339957 100644
>> --- a/qemu-img.c
>> +++ b/qemu-img.c
>> @@ -229,7 +229,7 @@ static int read_password(char *buf, int buf_size)
>>  static int print_block_option_help(const char *filename, const char *fmt)
>>  {
>>      BlockDriver *drv, *proto_drv;
>> -    QEMUOptionParameter *create_options = NULL;
>> +    QemuOptsList *create_opts = NULL;
>>
>>      /* Find driver and parse its options */
>>      drv = bdrv_find_format(fmt);
>> @@ -244,12 +244,10 @@ static int print_block_option_help(const char 
>> *filename, const char *fmt)
>>          return 1;
>>      }
>>
>> -    create_options = append_option_parameters(create_options,
>> -                                              drv->create_options);
>> -    create_options = append_option_parameters(create_options,
>> -                                              proto_drv->create_options);
>> -    print_option_help(create_options);
>> -    free_option_parameters(create_options);
>> +    create_opts = qemu_opts_append(drv->bdrv_create_opts,
>> +                                   proto_drv->bdrv_create_opts);
>> +    qemu_opts_print_help(create_opts);
>> +    qemu_opts_free(create_opts);
>>      return 0;
>>  }
>>
>
> Must merge options exactly like bdrv_img_create().  It does.  Good.
>
> I suspect the merge code should be factored out.  Beyond the scope of
> this patch.
>
> Running out of steam, review is becoming more superficial and less
> reliable.
>
>> @@ -301,19 +299,19 @@ fail:
>>      return NULL;
>>  }
>>
>> -static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
>> +static int add_old_style_options(const char *fmt, QemuOpts *list,
>>                                   const char *base_filename,
>>                                   const char *base_fmt)
>>  {
>>      if (base_filename) {
>> -        if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, 
>> base_filename)) {
>> +        if (qemu_opt_set(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
>>              error_report("Backing file not supported for file format '%s'",
>>                           fmt);
>>              return -1;
>>          }
>>      }
>>      if (base_fmt) {
>> -        if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
>> +        if (qemu_opt_set(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
>>              error_report("Backing file format not supported for file "
>>                           "format '%s'", fmt);
>>              return -1;
>
> Looks like this duplicates code in bdrv_img_create().  Cleanup beyond
> the scope of this patch.
>
>> @@ -1120,8 +1118,9 @@ static int img_convert(int argc, char **argv)
>>      uint8_t * buf = NULL;
>>      const uint8_t *buf1;
>>      BlockDriverInfo bdi;
>> -    QEMUOptionParameter *param = NULL, *create_options = NULL;
>> -    QEMUOptionParameter *out_baseimg_param;
>> +    QemuOpts *param = NULL;
>> +    QemuOptsList *create_opts = NULL;
>> +    const char *out_baseimg_param;
>>      char *options = NULL;
>>      const char *snapshot_name = NULL;
>>      float local_progress = 0;
>> @@ -1265,40 +1264,36 @@ static int img_convert(int argc, char **argv)
>>          goto out;
>>      }
>>
>> -    create_options = append_option_parameters(create_options,
>> -                                              drv->create_options);
>> -    create_options = append_option_parameters(create_options,
>> -                                              proto_drv->create_options);
>> +    create_opts = qemu_opts_append(drv->bdrv_create_opts,
>> +                                   proto_drv->bdrv_create_opts);
>>
>
> More duplicated option merge code.  Cleanup beyond the scope of this
> patch.
>
>>      if (options) {
>> -        param = parse_option_parameters(options, create_options, param);
>> -        if (param == NULL) {
>> +        if (qemu_opts_do_parse_replace(param, options, NULL) != 0) {
>>              error_report("Invalid options for file format '%s'.", out_fmt);
>>              ret = -1;
>>              goto out;
>>          }
>>      } else {
>> -        param = parse_option_parameters("", create_options, param);
>> +        param = qemu_opts_create_nofail(create_opts);
>>      }
>> -
>> -    set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
>> +    qemu_opt_set_number(param, BLOCK_OPT_SIZE, total_sectors * 512);
>>      ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
>>      if (ret < 0) {
>>          goto out;
>>      }
>>
>>      /* Get backing file name if -o backing_file was used */
>> -    out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
>> +    out_baseimg_param = qemu_opt_get(param, BLOCK_OPT_BACKING_FILE);
>>      if (out_baseimg_param) {
>> -        out_baseimg = out_baseimg_param->value.s;
>> +        out_baseimg = out_baseimg_param;
>>      }
>
> More copy/paste coding.  Cleanup beyond the scope of this patch.
>
>>
>>      /* Check if compression is supported */
>>      if (compress) {
>> -        QEMUOptionParameter *encryption =
>> -            get_option_parameter(param, BLOCK_OPT_ENCRYPT);
>> -        QEMUOptionParameter *preallocation =
>> -            get_option_parameter(param, BLOCK_OPT_PREALLOC);
>> +        bool encryption =
>> +            qemu_opt_get_bool(param, BLOCK_OPT_ENCRYPT, false);
>> +        const char *preallocation =
>> +            qemu_opt_get(param, BLOCK_OPT_PREALLOC);
>>
>>          if (!drv->bdrv_write_compressed) {
>>              error_report("Compression not supported for this file format");
>> @@ -1306,15 +1301,15 @@ static int img_convert(int argc, char **argv)
>>              goto out;
>>          }
>>
>> -        if (encryption && encryption->value.n) {
>> +        if (encryption) {
>>              error_report("Compression and encryption not supported at "
>>                           "the same time");
>>              ret = -1;
>>              goto out;
>>          }
>>
>> -        if (preallocation && preallocation->value.s
>> -            && strcmp(preallocation->value.s, "off"))
>> +        if (preallocation
>> +            && strcmp(preallocation, "off"))
>>          {
>>              error_report("Compression and preallocation not supported at "
>>                           "the same time");
>> @@ -1532,8 +1527,10 @@ static int img_convert(int argc, char **argv)
>>      }
>>  out:
>>      qemu_progress_end();
>> -    free_option_parameters(create_options);
>> -    free_option_parameters(param);
>> +    qemu_opts_free(create_opts);
>> +    if (param) {
>> +        qemu_opts_del(param);
>> +    }
>>      qemu_vfree(buf);
>>      if (out_bs) {
>>          bdrv_delete(out_bs);
>> diff --git a/util/qemu-option.c b/util/qemu-option.c
>> index 0e42452..dba82b4 100644
>> --- a/util/qemu-option.c
>> +++ b/util/qemu-option.c
>
> Changes to this file not reviewed in this round.
>
>> @@ -33,6 +33,8 @@
>>  #include "qapi/qmp/qerror.h"
>>  #include "qemu/option_int.h"
>>
>> +static void qemu_opt_del(QemuOpt *opt);
>> +
>>  /*
>>   * Extracts the name of an option from the parameter string (p points at the
>>   * first byte of the option name)
>> @@ -531,6 +533,16 @@ const char *qemu_opt_get(QemuOpts *opts, const char 
>> *name)
>>      return opt ? opt->str : NULL;
>>  }
>>
>> +const char *qemu_opt_get_del(QemuOpts *opts, const char *name)
>> +{
>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>> +    const char *str = opt ? opt->str : NULL;
>> +    if (opt) {
>> +        qemu_opt_del(opt);
>> +    }
>> +    return str;
>> +}
>> +
>>  bool qemu_opt_has_help_opt(QemuOpts *opts)
>>  {
>>      QemuOpt *opt;
>> @@ -553,6 +565,22 @@ bool qemu_opt_get_bool(QemuOpts *opts, const char 
>> *name, bool defval)
>>      return opt->value.boolean;
>>  }
>>
>> +bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval)
>> +{
>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>> +    bool ret;
>> +
>> +    if (opt == NULL) {
>> +        return defval;
>> +    }
>> +    ret = opt->value.boolean;
>> +    assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
>> +    if (opt) {
>> +        qemu_opt_del(opt);
>> +    }
>> +    return ret;
>> +}
>> +
>>  uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t 
>> defval)
>>  {
>>      QemuOpt *opt = qemu_opt_find(opts, name);
>> @@ -573,6 +601,23 @@ uint64_t qemu_opt_get_size(QemuOpts *opts, const char 
>> *name, uint64_t defval)
>>      return opt->value.uint;
>>  }
>>
>> +uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
>> +                               uint64_t defval)
>> +{
>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>> +    uint64_t ret;
>> +
>> +    if (opt == NULL) {
>> +        return defval;
>> +    }
>> +    ret = opt->value.uint;
>> +    assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
>> +    if (opt) {
>> +        qemu_opt_del(opt);
>> +    }
>> +    return ret;
>> +}
>> +
>>  static void qemu_opt_parse(QemuOpt *opt, Error **errp)
>>  {
>>      if (opt->desc == NULL)
>> @@ -624,7 +669,7 @@ static const QemuOptDesc *find_desc_by_name(const 
>> QemuOptDesc *desc,
>>  }
>>
>>  static void opt_set(QemuOpts *opts, const char *name, const char *value,
>> -                    bool prepend, Error **errp)
>> +                    bool prepend, bool replace, Error **errp)
>>  {
>>      QemuOpt *opt;
>>      const QemuOptDesc *desc;
>> @@ -636,6 +681,11 @@ static void opt_set(QemuOpts *opts, const char *name, 
>> const char *value,
>>          return;
>>      }
>>
>> +    opt = qemu_opt_find(opts, name);
>> +    if (replace && opt) {
>> +        qemu_opt_del(opt);
>> +    }
>> +
>>      opt = g_malloc0(sizeof(*opt));
>>      opt->name = g_strdup(name);
>>      opt->opts = opts;
>> @@ -658,7 +708,29 @@ int qemu_opt_set(QemuOpts *opts, const char *name, 
>> const char *value)
>>  {
>>      Error *local_err = NULL;
>>
>> -    opt_set(opts, name, value, false, &local_err);
>> +    opt_set(opts, name, value, false, false, &local_err);
>> +    if (error_is_set(&local_err)) {
>> +        qerror_report_err(local_err);
>> +        error_free(local_err);
>> +        return -1;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +/*
>> + * If name exists, the function will delete the opt first and then add a new
>> + * one.
>> + */
>> +int qemu_opt_replace_set(QemuOpts *opts, const char *name, const char 
>> *value)
>> +{
>> +    Error *local_err = NULL;
>> +    QemuOpt *opt = qemu_opt_find(opts, name);
>> +
>> +    if (opt) {
>> +        qemu_opt_del(opt);
>> +    }
>> +    opt_set(opts, name, value, false, true, &local_err);
>>      if (error_is_set(&local_err)) {
>>          qerror_report_err(local_err);
>>          error_free(local_err);
>> @@ -671,7 +743,7 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const 
>> char *value)
>>  void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
>>                        Error **errp)
>>  {
>> -    opt_set(opts, name, value, false, errp);
>> +    opt_set(opts, name, value, false, false, errp);
>>  }
>>
>>  int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
>> @@ -895,7 +967,7 @@ int qemu_opts_print(QemuOpts *opts, void *dummy)
>>  }
>>
>>  static int opts_do_parse(QemuOpts *opts, const char *params,
>> -                         const char *firstname, bool prepend)
>> +                         const char *firstname, bool prepend, bool replace)
>>  {
>>      char option[128], value[1024];
>>      const char *p,*pe,*pc;
>> @@ -931,7 +1003,7 @@ static int opts_do_parse(QemuOpts *opts, const char 
>> *params,
>>          }
>>          if (strcmp(option, "id") != 0) {
>>              /* store and parse */
>> -            opt_set(opts, option, value, prepend, &local_err);
>> +            opt_set(opts, option, value, prepend, replace, &local_err);
>>              if (error_is_set(&local_err)) {
>>                  qerror_report_err(local_err);
>>                  error_free(local_err);
>> @@ -947,9 +1019,16 @@ static int opts_do_parse(QemuOpts *opts, const char 
>> *params,
>>
>>  int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char 
>> *firstname)
>>  {
>> -    return opts_do_parse(opts, params, firstname, false);
>> +    return opts_do_parse(opts, params, firstname, false, false);
>> +}
>> +
>> +int qemu_opts_do_parse_replace(QemuOpts *opts, const char *params,
>> +                               const char *firstname)
>> +{
>> +    return opts_do_parse(opts, params, firstname, false, true);
>>  }
>>
>> +
>>  static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
>>                              int permit_abbrev, bool defaults)
>>  {
>> @@ -986,7 +1065,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const 
>> char *params,
>>          return NULL;
>>      }
>>
>> -    if (opts_do_parse(opts, params, firstname, defaults) != 0) {
>> +    if (opts_do_parse(opts, params, firstname, defaults, false) != 0) {
>>          qemu_opts_del(opts);
>>          return NULL;
>>      }
>

Really thanks for your reviewing, Markus.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]