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 --]
next prev parent 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).