All of lore.kernel.org
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: kwolf@redhat.com, imammedo@redhat.com, qemu-devel@nongnu.org
Subject: Re: [PATCH 01/25] qemu-option: clean up id vs. list->merge_lists
Date: Tue, 19 Jan 2021 14:58:53 +0100	[thread overview]
Message-ID: <87y2gpxc2q.fsf@dusky.pond.sub.org> (raw)
In-Reply-To: <20210118163113.780171-2-pbonzini@redhat.com> (Paolo Bonzini's message of "Mon, 18 Jan 2021 11:30:49 -0500")

Paolo Bonzini <pbonzini@redhat.com> writes:

> Looking at all merge-lists QemuOptsList

outside tests/

>                                          here is how they access their
> QemuOpts:
>
> reopen_opts in qemu-io-cmds.c ("qemu-img reopen -o")
> 	qemu_opts_find(&reopen_opts, NULL)
>
> empty_opts in qemu-io.c ("qemu-io open -o")
> 	qemu_opts_find(&empty_opts, NULL)
>
> qemu_rtc_opts ("-rtc")
> 	qemu_find_opts_singleton("rtc")
>
> qemu_machine_opts ("-M")
> 	qemu_find_opts_singleton("machine")

Gone since your commit 4988a4ea4d "vl: switch -M parsing to keyval".
Did it change behavior when multiple -M are given, with various id=?  I
didn't look at the patch back then, and I'm not going to look at it
now.  Feel free to ignore the question.

>
> qemu_boot_opts ("-boot")
> 	QTAILQ_FIRST(&qemu_find_opts("bootopts")->head)

That one's in hw/nvram/fw_cfg.c and hw/s390x/ipl.c.  However,
softmmu/vl.c uses

        qemu_opts_find(qemu_find_opts("boot-opts"), NULL);

If the user passes multiple -boot with different ID, we merge the ones
with same ID, and then vl.c gets the (merged) one without ID, but the
other two get the (merged) one that contains the first -boot.  All three
silently ignore the ones they don't get.  Awesomely weird.  I'd call it
a bug.

Test case:

    $ upstream-qemu -S -display none -boot strict=on,id=id -boot strict=off

vl.c uses strict=off, but fw_cfg.c uses strinct=on,id=id.

Outlawing "id" with .merge_lists like this patch does turns the cases
where the two methods yield different results into errors.  A bug fix of
sorts.  Should the commit message should cover it?

I believe we could use qemu_find_opts_singleton() in all three spots.
Not this patch's job.

> qemu_name_opts ("-name")
> 	qemu_opts_foreach->parse_name

Funny way to explain qemu_opts_foreach(qemu_name_opts, parse_name, ...)

> 	parse_name does not use id

We first use .merge-lists = true to merge all -name with the same ID,
then we iterate over all the merges.  Combined effect is "merge ignoring
ID".

> qemu_mem_opts ("-m")
> 	qemu_find_opts_singleton("memory")
>
> qemu_icount_opts ("-icount")
> 	qemu_opts_foreach->do_configuree_icount
> 	do_configure_icount->icount_configure
> 	icount_configure does not use id

Just like qemu_name_opts.  My comments apply, plus one:
s/do_configuree_icount/do_configure_icount/.

A recent addition is missing:

  qemu_action_opts ("-action")

Again, just like qemu_name_opts; my comments apply, plus one aside: this
should not use QemuOpts at all.  Use of qmp_marshal_FOO() is an
anti-pattern.  Needs cleanup.  Not in this patch, and probably not even
in this series.

> qemu_smp_opts ("-smp")
> 	qemu_opts_find(qemu_find_opts("smp-opts"), NULL)

That's one access in vl.c.  There's another one that uses
qemu_find_opts_singleton().  Okay, I think.

> qemu_spice_opts ("-spice")
> 	QTAILQ_FIRST(&qemu_spice_opts.head)

There's also machine_opts in qemu-config.c, but that's only to make
query-command-line-options lie backward-compatibly.

> i.e. they don't need an id.  Sometimes its presence is ignored
> (e.g. when using qemu_opts_foreach), sometimes all the options
> with the id are skipped,

(when using qemu_find_opts_singleton() or qemu_opts_find(list, NULL))

>                          sometimes only the first option on the
> command line is considered.

(when using QTAILQ_FIRST)

> command line is considered.  With this patch we just forbid id
> on merge-lists QemuOptsLists; if the command line still works,
> it has the same semantics as before.

It can break working (if weird) command lines, such as ones relying on
"merge ignoring ID" behavior of -name, -icount, -action.  Okay.

> qemu_opts_create's fail_if_exists parameter is now unnecessary:
>
> - it is unused if id is NULL
>
> - opts_parse only passes false if reached from qemu_opts_set_defaults,
> in which case this patch enforces that id must be NULL
>
> - other callers that can pass a non-NULL id always set it to true
>
> Assert that it is true in the only case where "fail_if_exists" matters,
> i.e. "id && !lists->merge_lists".  This means that if an id is present,
> duplicates are always forbidden, which was already the status quo.

Hmm.

If ->merge_lists, id= is forbidden, and all (id-less) opts are merged
into one.

Else, if id= is specified, it must be unique, i.e. no prior opts with
the same id.

Else, we don't check for prior opts without id.

There's at most one opts with a certain id, but there could be any
number without id.  Is this what we want?

> Discounting the case that aborts as it's not user-controlled (it's
> "just" a matter of inspecting qemu_opts_create callers), the paths
> through qemu_opts_create can be summarized as:
>
> - merge_lists = true: singleton opts with NULL id; non-NULL id fails
>
> - merge_lists = false: always return new opts; non-NULL id fails if dup

This renders the qemu_opts_foreach() silly.  Cleanup is in order, not
necessarily in this patch.

> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  util/qemu-option.c | 27 ++++++++++++++-------------
>  1 file changed, 14 insertions(+), 13 deletions(-)
>
> diff --git a/util/qemu-option.c b/util/qemu-option.c
> index c88e159f18..91f4120ce1 100644
> --- a/util/qemu-option.c
> +++ b/util/qemu-option.c
> @@ -619,7 +619,17 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
>  {
>      QemuOpts *opts = NULL;
>  
> -    if (id) {
> +    if (list->merge_lists) {
> +        if (id) {
> +            error_setg(errp, QERR_INVALID_PARAMETER, "id");
> +            return NULL;
> +        }
> +        opts = qemu_opts_find(list, NULL);
> +        if (opts) {
> +            return opts;
> +        }
> +    } else if (id) {
> +        assert(fail_if_exists);
>          if (!id_wellformed(id)) {
>              error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id",
>                         "an identifier");
> @@ -629,17 +639,8 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
>          }
>          opts = qemu_opts_find(list, id);
>          if (opts != NULL) {
> -            if (fail_if_exists && !list->merge_lists) {
> -                error_setg(errp, "Duplicate ID '%s' for %s", id, list->name);
> -                return NULL;
> -            } else {
> -                return opts;
> -            }
> -        }
> -    } else if (list->merge_lists) {
> -        opts = qemu_opts_find(list, NULL);
> -        if (opts) {
> -            return opts;
> +            error_setg(errp, "Duplicate ID '%s' for %s", id, list->name);
> +            return NULL;
>          }
>      }
>      opts = g_malloc0(sizeof(*opts));
> @@ -893,7 +894,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
>       * (if unlikely) future misuse:
>       */
>      assert(!defaults || list->merge_lists);
> -    opts = qemu_opts_create(list, id, !defaults, errp);
> +    opts = qemu_opts_create(list, id, !list->merge_lists, errp);
>      g_free(id);
>      if (opts == NULL) {
>          return NULL;

My dread of QemuOpts has been refreshed to its nominal level.



  parent reply	other threads:[~2021-01-19 14:17 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-18 16:30 [PATCH 00/25] qemu-option, keyval, vl: switch -object/-M/-accel to keyval parsing Paolo Bonzini
2021-01-18 16:30 ` [PATCH 01/25] qemu-option: clean up id vs. list->merge_lists Paolo Bonzini
2021-01-19 12:33   ` Kevin Wolf
2021-01-19 13:58   ` Markus Armbruster [this message]
2021-01-19 14:20     ` Paolo Bonzini
2021-01-20  8:03       ` Markus Armbruster
2021-01-20 12:37         ` Paolo Bonzini
2021-01-20 12:50           ` Markus Armbruster
2021-01-18 16:30 ` [PATCH 02/25] qemu-option: move help handling to get_opt_name_value Paolo Bonzini
2021-01-19 15:10   ` Markus Armbruster
2021-01-18 16:30 ` [PATCH 03/25] qemu-option: warn for short-form boolean options Paolo Bonzini
2021-01-19 15:56   ` Markus Armbruster
2021-01-19 17:04     ` Paolo Bonzini
2021-01-20  8:42       ` Markus Armbruster
2021-01-20 12:40         ` Paolo Bonzini
2021-01-20 12:59           ` Markus Armbruster
2021-01-20 14:05             ` Paolo Bonzini
2021-01-18 16:30 ` [PATCH 04/25] keyval: accept escaped commas in implied option Paolo Bonzini
2021-01-21 12:58   ` Markus Armbruster
2021-01-22  8:39   ` Markus Armbruster
2021-01-18 16:30 ` [PATCH 05/25] keyval: simplify keyval_parse_one Paolo Bonzini
2021-01-22 13:48   ` Markus Armbruster
2021-01-22 15:00     ` Paolo Bonzini
2021-01-22 15:44       ` Markus Armbruster
2021-01-18 16:30 ` [PATCH 06/25] tests: convert check-qom-proplist to keyval Paolo Bonzini
2021-01-22 14:14   ` Markus Armbruster
2021-01-22 14:38     ` Paolo Bonzini
2021-01-22 14:48     ` Paolo Bonzini
2021-01-18 16:30 ` [PATCH 07/25] keyval: introduce keyval_parse_into Paolo Bonzini
2021-01-22 14:22   ` Markus Armbruster
2021-01-22 14:30     ` Paolo Bonzini
2021-01-18 16:30 ` [PATCH 08/25] hmp: replace "O" parser with keyval Paolo Bonzini
2021-01-25  9:00   ` Markus Armbruster
2021-02-26 11:25     ` Paolo Bonzini
2021-03-01 10:14       ` Markus Armbruster
2021-03-01 10:23         ` Paolo Bonzini
2021-03-01 13:35           ` Markus Armbruster
2021-03-01 10:43     ` Markus Armbruster
2021-03-01 11:54       ` Paolo Bonzini
2021-01-18 16:30 ` [PATCH 09/25] qom: use qemu_printf to print help for user-creatable objects Paolo Bonzini
2021-01-25 12:47   ` Markus Armbruster
2021-01-18 16:30 ` [PATCH 10/25] hmp: special case help options for object_add Paolo Bonzini
2021-01-25 12:48   ` Markus Armbruster
2021-01-25 12:49     ` Paolo Bonzini
2021-01-25 14:02       ` Markus Armbruster
2021-01-18 16:30 ` [PATCH 11/25] remove -writeconfig Paolo Bonzini
2021-01-25 12:53   ` Markus Armbruster
2021-01-25 14:01     ` Paolo Bonzini
2021-01-25 14:12       ` Daniel P. Berrangé
2021-01-18 16:31 ` [PATCH 12/25] qemu-config: add error propagation to qemu_config_parse Paolo Bonzini
2021-01-25 13:54   ` Markus Armbruster
2021-01-18 16:31 ` [PATCH 13/25] qemu-option: support accept-any QemuOptsList in qemu_opts_absorb_qdict Paolo Bonzini
2021-01-18 16:31 ` [PATCH 14/25] qemu-config: parse configuration files to a QDict Paolo Bonzini
2021-01-18 16:31 ` [PATCH 15/25] vl: plumb keyval-based options into -set and -readconfig Paolo Bonzini
2021-01-25 11:48   ` Markus Armbruster
2021-01-25 13:59     ` Paolo Bonzini
2021-01-18 16:31 ` [PATCH 16/25] qom: do not modify QDict argument in user_creatable_add_dict Paolo Bonzini
2021-01-18 16:31 ` [PATCH 17/25] qemu-io: use keyval for -object parsing Paolo Bonzini
2021-01-18 16:31 ` [PATCH 18/25] qemu-nbd: " Paolo Bonzini
2021-01-18 16:31 ` [PATCH 19/25] qemu-img: " Paolo Bonzini
2021-01-18 16:31 ` [PATCH 20/25] qemu: " Paolo Bonzini
2021-01-18 16:31 ` [PATCH 21/25] storage-daemon: do not register the "object" group with QemuOpts Paolo Bonzini
2021-01-18 16:31 ` [PATCH 22/25] qom: export more functions for use with non-UserCreatable objects Paolo Bonzini
2021-01-18 16:31 ` [PATCH 23/25] vl: switch -M parsing to keyval Paolo Bonzini
2021-01-18 16:31 ` [PATCH 24/25] qemu-option: remove now-dead code Paolo Bonzini
2021-01-18 16:31 ` [PATCH 25/25] vl: switch -accel parsing to keyval Paolo Bonzini
2021-01-18 17:18 ` [PATCH 00/25] qemu-option, keyval, vl: switch -object/-M/-accel to keyval parsing no-reply

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=87y2gpxc2q.fsf@dusky.pond.sub.org \
    --to=armbru@redhat.com \
    --cc=imammedo@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.