qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Chunyan Liu <cyliu@suse.com>
To: Eric Blake <eblake@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>,
	Dong Xu Wang <wdongxu@linux.vnet.ibm.com>,
	qemu-devel@nongnu.org, stefanha@redhat.com
Subject: Re: [Qemu-devel] [PATCH v22 07/25] change block layer to support both QemuOpts and QEMUOptionParamter
Date: Wed, 12 Mar 2014 14:26:25 +0800	[thread overview]
Message-ID: <CAERYnoaChPGLb1ys7mbnx5Zw6sq=3LvKrt4VTE2b9MEbb_sdDg@mail.gmail.com> (raw)
In-Reply-To: <531F3FAC.3010606@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 12498 bytes --]

2014-03-12 0:54 GMT+08:00 Eric Blake <eblake@redhat.com>:

> On 03/10/2014 01:31 AM, Chunyan Liu wrote:
> > Change block layer to support both QemuOpts and QEMUOptionParameter.
> > After this patch, it will change backend drivers one by one. At the end,
> > QEMUOptionParameter will be removed and only QemuOpts is kept.
> >
> > Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
> > Signed-off-by: Chunyan Liu <cyliu@suse.com>
> > ---
>
> >  int bdrv_create(BlockDriver *drv, const char* filename,
> > -    QEMUOptionParameter *options, Error **errp)
> > +    QEMUOptionParameter *options, QemuOpts *opts, Error **errp)
> >  {
> >      int ret;
>
> In addition to my remarks last night:
>
> I wonder if you should add:
>
> assert(!(options && opts))
>
> to prove that all callers are passing at most one of the two supported
> option lists, while doing the conversion.
>
> > @@ -5248,28 +5266,31 @@ void bdrv_img_create(const char *filename, const
> char *fmt,
> >          return;
> >      }
> >
> > -    create_options = append_option_parameters(create_options,
> > -                                              drv->create_options);
> > -    create_options = append_option_parameters(create_options,
> > -
>  proto_drv->create_options);
> > +    if (drv->bdrv_create2) {
> > +        create_opts = qemu_opts_append(create_opts, drv->create_opts);
> > +        create_opts = qemu_opts_append(create_opts,
> proto_drv->create_opts);
>
> In addition to the memory leak I pointed out earlier,


Should use g_realloc in qemu_opts_append, realloc create_opts
to the desired space and append 2nd list to it. Saving the effort to free
memory while append many times.

I see another
> potential problem: What if drv has been converted to QemuOpts, but
> proto_drv is still on QEMUOptionParameter?
>

> > +    } else {
> > +        create_options = append_option_parameters(create_options,
> > +                                                  drv->create_options);
> > +        create_options = append_option_parameters(create_options,
> > +
>  proto_drv->create_options);
>
> Or the converse, if drv is still on QEMUOptionParameter, but proto_drv
> has been converted to QEMUOpts?
>
> Either way, you will be appending NULL for the proto_drv case, when what
> you really wanted to be doing was merging both the QemuOpts and
> QEMUOptionParameters into a single list.
>
> > +        create_opts = params_to_opts(create_options);
> > +    }
>
> I think a better path to conversion would be doing everything possible
> in QemuOpts, and only switching to QEMUOptionParameters at the last
> possible moment, rather than having two separate append code paths.
>
> My suggestion: until the conversion is complete, add a new function,
> something like:
>
> void qemu_opts_append_pair(QemuOpts *dst, QemuOpts *opts,
>                            QEMUOptionParameter *options) {
>     assert(!(opts && options));
>     ... modify dst in-place to have it cover the entries from opts or
> options
> }
>
> then in this code, you do:
>     create_options = /* generate empty QemuOpts */;
>     qemu_opts_append_pair(options, drv->create_opts,
>                           drv->create_options);
>     qemu_opts_append_pair(options, proto_drv->create_options,
>                           proto_drv->create_options);
>
>
Good. Together with always using QemuOpts and only converting to
QEMUOptionParameter until it calls .bdrv_create in specific driver,
the drv/proto_drv inconsistent problem could be solved.
Will update.

Thanks very much for all your suggestions!

Chunyan

>
> >      /* Create parameter list with default values */
> > -    param = parse_option_parameters("", create_options, param);
> > -
> > -    set_option_parameter_int(param, BLOCK_OPT_SIZE, img_size);
> > +    opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
> > +    qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size);
>
> This part worked nicely - once you convert both incoming styles to
> QemuOpts, it really is easier to have this part of the code just use
> QemuOpts functions for setting the size....
>
> > ...
> > @@ -5343,16 +5364,23 @@ 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);
> >          puts("");
> >      }
> > -    ret = bdrv_create(drv, filename, param, &local_err);
> > +
> > +    if (drv->bdrv_create2) {
> > +        ret = bdrv_create(drv, filename, NULL, opts, &local_err);
> > +    } else {
> > +        param = opts_to_params(opts);
> > +        ret = bdrv_create(drv, filename, param, NULL, &local_err);
> > +    }
>
> ...and finally convert back to QEMUOptionParameters at the last moment.
>  But wait a minute - why are you checking for drv->bdrv_create2 here?
> Isn't the last possible moment really inside bdrv_create() (that is, the
> actual function that decides whether to call drv->bdrv_create vs.
> drv->bdrv_create2)?  For the code to be as clean as possible, you want
> to use QemuOpts everywhere until the actual point where you are calling
> the unconverted callback.
>
>
> > -int bdrv_amend_options(BlockDriverState *bs, QEMUOptionParameter
> *options)
> > +int bdrv_amend_options(BlockDriverState *bs, QEMUOptionParameter
> *options,
> > +                       QemuOpts *opts)
> >  {
> > -    if (bs->drv->bdrv_amend_options == NULL) {
> > +    if (!bs->drv->bdrv_amend_options && !bs->drv->bdrv_amend_options2) {
> >          return -ENOTSUP;
> >      }
> > -    return bs->drv->bdrv_amend_options(bs, options);
> > +    if (bs->drv->bdrv_amend_options2) {
> > +        return bs->drv->bdrv_amend_options2(bs, opts);
> > +    } else {
> > +        return bs->drv->bdrv_amend_options(bs, options);
>
> Similar to the create/create2 situation, _this_ function is the last
> possible place to make the conversions.  You have a problem in that if
> the user passes you options but the callback expects opts, you are
> passing NULL to the callback.  I think this should look more like:
>
> int bdrv_amend_options(BlockDriverState *bs, QEMUOptionParameter *options,
>                        QemuOpts *opts)
> {
>     int ret;
>     assert(!(opts && options));
>     if (!bs->drv->bdrv_amend_options && !bs->drv->bdrv_amend_options2) {
>         return -ENOTSUP;
>     }
>     if (bs->drv->bdrv_amend_options2) {
>         if (options) {
>             opts = params_to_opts(options);
>         }
>         ret = bs->drv->bdrv_amend_options2(bs, opts);
>         if (options) {
>             g_free(opts); // or whatever correct spelling to avoid leak
>         }
>     } else {
>         if (opts) {
>             options = opts_to_params(opts);
>         }
>         ret = bs->drv->bdrv_amend_options(bs, options);
>         if (opts) {
>             g_free(options); // again, with correct spelling
>         }
>     }
>     return ret;
>
> > +++ b/include/block/block_int.h
> > @@ -118,6 +118,8 @@ struct BlockDriver {
> >      void (*bdrv_rebind)(BlockDriverState *bs);
> >      int (*bdrv_create)(const char *filename, QEMUOptionParameter
> *options,
> >                         Error **errp);
> > +    /* FIXME: will remove the duplicate and rename back to bdrv_create
> later */
> > +    int (*bdrv_create2)(const char *filename, QemuOpts *opts, Error
> **errp);
>
> I like the FIXME here; maybe also mention that bdrv_create and
> bdrv_create2 are mutually exclusive (at most one can be non-NULL).
>
> >      int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
> >      int (*bdrv_make_empty)(BlockDriverState *bs);
> >      /* aio */
> > @@ -217,7 +219,7 @@ struct BlockDriver {
> >
> >      /* List of options for creating images, terminated by name == NULL
> */
> >      QEMUOptionParameter *create_options;
> > -
> > +    QemuOptsList *create_opts;
>
> A similar FIXME comment here might be nice, likewise mentioning that at
> most one of these two fields should be non-NULL.
>
> > @@ -244,21 +245,34 @@ static int print_block_option_help(const char
> *filename, const char *fmt)
> >          return 1;
> >      }
> >
> > -    create_options = append_option_parameters(create_options,
> > -                                              drv->create_options);
> > -
> > +    if (drv->create_opts) {
> > +        create_opts = qemu_opts_append(create_opts, drv->create_opts);
> > +    } else {
> > +        create_options = append_option_parameters(create_options,
> > +                                                  drv->create_options);
> > +    }
> >      if (filename) {
> >          proto_drv = bdrv_find_protocol(filename, true);
> >          if (!proto_drv) {
> >              error_report("Unknown protocol '%s'", filename);
> >              return 1;
> >          }
> > -        create_options = append_option_parameters(create_options,
> > -
>  proto_drv->create_options);
> > +        if (drv->create_opts) {
> > +            create_opts = qemu_opts_append(create_opts,
> proto_drv->create_opts);
>
> Memory leak.
>
> > +        } else {
> > +            create_options =
> > +                append_option_parameters(create_options,
> > +                                         proto_drv->create_options);
> > +        }
> >      }
> >
> > -    print_option_help(create_options);
> > +    if (drv->create_opts) {
> > +        qemu_opts_print_help(create_opts);
> > +    } else {
> > +        print_option_help(create_options);
> > +    }
>
> Another case where if you add a new helper function that absorbs either
> style of options into a QemuOpts, then all you have to do here is print
> the QemuOpts, instead of trying to switch between print methods here.
>
>
> > @@ -1340,40 +1356,42 @@ static int img_convert(int argc, char **argv)
> >          goto out;
> >      }
>
> > -        }
> > +    if (drv->bdrv_create2) {
> > +        create_opts = qemu_opts_append(create_opts, drv->create_opts);
> > +        create_opts = qemu_opts_append(create_opts,
> proto_drv->create_opts);
>
> More memory leaks.
>
>
> > @@ -1400,7 +1418,12 @@ static int img_convert(int argc, char **argv)
> >
> >      if (!skip_create) {
> >          /* Create the new image */
> > -        ret = bdrv_create(drv, out_filename, param, &local_err);
> > +        if (drv->bdrv_create2) {
> > +            ret = bdrv_create(drv, out_filename, NULL, opts,
> &local_err);
> > +        } else {
> > +            param = opts_to_params(opts);
> > +            ret = bdrv_create(drv, out_filename, param, NULL,
> &local_err);
> > +        }
>
> Another case where you should just always pass opts to bdrv_create(),
> and let bdrv_create() do the last minute conversion to
> QEMUOptionParameters based on what callbacks drv supports, rather than
> trying to make decisions here based on contents of drv.
>
>
> > @@ -2721,17 +2748,26 @@ static int img_amend(int argc, char **argv)
> >          goto out;
> >      }
> >
> > -    create_options = append_option_parameters(create_options,
> > -            bs->drv->create_options);
> > -    options_param = parse_option_parameters(options, create_options,
> > -            options_param);
> > -    if (options_param == NULL) {
> > +    if (bs->drv->bdrv_amend_options2) {
>
> And again, you should not be making decisions on the contents of
> bs->drv, but just blindly setting up QemuOpts here...
>
> > +        create_opts = qemu_opts_append(create_opts,
> bs->drv->create_opts);
> > +    } else {
> > +        create_options = append_option_parameters(create_options,
> > +
>  bs->drv->create_options);
> > +        create_opts = params_to_opts(create_options);
> > +    }
> > +    opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
> > +    if (options && qemu_opts_do_parse(opts, options, NULL)) {
> >          error_report("Invalid options for file format '%s'", fmt);
> >          ret = -1;
> >          goto out;
> >      }
> >
> > -    ret = bdrv_amend_options(bs, options_param);
> > +    if (bs->drv->bdrv_amend_options2) {
> > +        ret = bdrv_amend_options(bs, NULL, opts);
> > +    } else {
> > +        options_param = opts_to_params(opts);
> > +        ret = bdrv_amend_options(bs, options_param, NULL);
>
> ...and blindly letting bdrv_amend_options() be the place that converts
> to QEMUOptionParameters as needed.
>
> Here's hoping v23 is nicer; I'm looking forward to ditching
> QEMUOptionParameters.
>

> --
> Eric Blake   eblake redhat com    +1-919-301-3266
> Libvirt virtualization library http://libvirt.org
>
>

[-- Attachment #2: Type: text/html, Size: 16909 bytes --]

  reply	other threads:[~2014-03-12  6:26 UTC|newest]

Thread overview: 105+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-10  7:31 [Qemu-devel] [PATCH v22 00/25] replace QEMUOptionParameter with QemuOpts Chunyan Liu
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 01/25] add def_value_str to QemuOptDesc Chunyan Liu
2014-03-10 19:52   ` Eric Blake
2014-03-11 13:29   ` Stefan Hajnoczi
2014-03-12  2:45     ` Chunyan Liu
2014-03-12  8:27       ` Stefan Hajnoczi
2014-03-13  2:46         ` Chunyan Liu
2014-03-13 12:13           ` Stefan Hajnoczi
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 02/25] qapi: output def_value_str when query command line options Chunyan Liu
2014-03-10 19:57   ` Eric Blake
2014-03-11  6:14   ` Hu Tao
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 03/25] improve some functions in qemu-option.c Chunyan Liu
2014-03-10 20:29   ` Eric Blake
2014-03-10 21:21     ` Eric Blake
2014-03-11  7:26       ` Chunyan Liu
2014-03-11 21:00         ` Leandro Dorileo
2014-03-16 21:19           ` Leandro Dorileo
2014-03-18  7:41             ` Chunyan Liu
2014-03-12  6:49       ` Chunyan Liu
2014-03-17 19:58   ` Leandro Dorileo
2014-03-18  7:49     ` Chunyan Liu
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 04/25] improve assertion in qemu_opt_get functions Chunyan Liu
2014-03-10 21:44   ` Eric Blake
2014-03-12  6:34     ` Chunyan Liu
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 05/25] add some QemuOpts functions for replace work Chunyan Liu
2014-03-10 23:28   ` Eric Blake
2014-03-11  5:29     ` Chunyan Liu
2014-03-11 11:59       ` Eric Blake
2014-03-12  3:10         ` Chunyan Liu
2014-03-12 12:40           ` Eric Blake
2014-03-13  5:16             ` Chunyan Liu
2014-03-18  5:34             ` Chunyan Liu
2014-03-17 19:35   ` Leandro Dorileo
2014-03-18  3:03     ` Chunyan Liu
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 06/25] add convert functions between QEMUOptionParameter to QemuOpts Chunyan Liu
2014-03-11  4:46   ` Eric Blake
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 07/25] change block layer to support both QemuOpts and QEMUOptionParamter Chunyan Liu
2014-03-11  4:34   ` Eric Blake
2014-03-11 16:54   ` Eric Blake
2014-03-12  6:26     ` Chunyan Liu [this message]
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 08/25] cow.c: replace QEMUOptionParameter with QemuOpts Chunyan Liu
2014-03-11 14:12   ` Stefan Hajnoczi
2014-03-11 15:28   ` Eric Blake
2014-03-20  6:56     ` Chunyan Liu
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 09/25] gluster.c: " Chunyan Liu
2014-03-11 14:15   ` Stefan Hajnoczi
2014-03-11 16:58   ` Eric Blake
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 10/25] iscsi.c: " Chunyan Liu
2014-03-11 14:17   ` Stefan Hajnoczi
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 11/25] qcow.c: " Chunyan Liu
2014-03-11 14:18   ` Stefan Hajnoczi
2014-03-11 17:05   ` Eric Blake
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 12/25] qcow2.c: " Chunyan Liu
2014-03-11 14:21   ` Stefan Hajnoczi
2014-03-11 14:22   ` Stefan Hajnoczi
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 13/25] qed.c: " Chunyan Liu
2014-03-11 14:24   ` Stefan Hajnoczi
2014-03-20  9:08     ` Chun Yan Liu
2014-03-20 14:14       ` Stefan Hajnoczi
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 14/25] raw-posix.c: " Chunyan Liu
2014-03-11 14:25   ` Stefan Hajnoczi
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 15/25] raw-win32.c: " Chunyan Liu
2014-03-11 14:41   ` Stefan Hajnoczi
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 16/25] raw_bsd.c: " Chunyan Liu
2014-03-11 14:44   ` Stefan Hajnoczi
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 17/25] rbd.c: " Chunyan Liu
2014-03-11 14:46   ` Stefan Hajnoczi
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 18/25] sheepdog.c: " Chunyan Liu
2014-03-11 16:01   ` Stefan Hajnoczi
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 19/25] ssh.c: " Chunyan Liu
2014-03-11 16:01   ` Stefan Hajnoczi
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 20/25] vdi.c: " Chunyan Liu
2014-03-11 17:50   ` Stefan Hajnoczi
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 21/25] vmdk.c: " Chunyan Liu
2014-03-11 17:51   ` Stefan Hajnoczi
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 22/25] vpc.c: " Chunyan Liu
2014-03-11 17:55   ` Stefan Hajnoczi
2014-03-10  7:31 ` [Qemu-devel] [PATCH v22 23/25] vhdx.c: " Chunyan Liu
2014-03-11 17:56   ` Stefan Hajnoczi
2014-03-10  7:32 ` [Qemu-devel] [PATCH v22 24/25] vvfat.c: " Chunyan Liu
2014-03-11 17:06   ` Eric Blake
2014-03-11 18:01   ` Stefan Hajnoczi
2014-03-10  7:32 ` [Qemu-devel] [PATCH v22 25/25] cleanup QEMUOptionParameter Chunyan Liu
2014-03-11 14:06   ` Stefan Hajnoczi
2014-03-17 19:29   ` Leandro Dorileo
2014-03-17 19:43     ` Leandro Dorileo
2014-03-10  7:36 ` [Qemu-devel] [PATCH v22 00/25] replace QEMUOptionParameter with QemuOpts Chun Yan Liu
2014-03-10  7:37 ` Chun Yan Liu
2014-03-10  7:37 ` Chun Yan Liu
2014-03-10  7:38 ` Chun Yan Liu
2014-03-10  7:39 ` Chun Yan Liu
2014-03-10  7:39 ` Chun Yan Liu
2014-03-10 20:22 ` Stefan Hajnoczi
2014-03-11  3:07   ` Chunyan Liu
2014-03-10 22:45 ` Eric Blake
2014-03-11 18:03 ` Stefan Hajnoczi
2014-03-21  0:07 ` Leandro Dorileo
2014-03-21 10:09   ` Chunyan Liu
2014-03-21 12:31     ` Leandro Dorileo
2014-03-24  3:02       ` Chunyan Liu
2014-03-24 15:00         ` Leandro Dorileo
2014-03-25  7:15           ` Chunyan Liu
2014-04-03  9:46             ` Chunyan Liu
2014-03-21 10:34   ` Kevin Wolf
2014-03-21 12:21     ` Leandro Dorileo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAERYnoaChPGLb1ys7mbnx5Zw6sq=3LvKrt4VTE2b9MEbb_sdDg@mail.gmail.com' \
    --to=cyliu@suse.com \
    --cc=eblake@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    --cc=wdongxu@linux.vnet.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).