util: Add qemu_opts_to_qdict_filtered()

This allows, given a QemuOpts for a QemuOptsList that was merged from
multiple QemuOptsList, to only consider those options that exist in one
specific list. Block drivers need this to separate format-layer create
options from protocol-level options.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
Kevin Wolf 2018-01-11 17:37:23 +01:00
parent e4b5dad826
commit 72215395b9
2 changed files with 39 additions and 5 deletions

View file

@ -124,6 +124,8 @@ void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
int permit_abbrev);
QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
Error **errp);
QDict *qemu_opts_to_qdict_filtered(QemuOpts *opts, QDict *qdict,
QemuOptsList *list, bool del);
QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict);
void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp);

View file

@ -1007,14 +1007,23 @@ void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp)
}
/*
* Convert from QemuOpts to QDict.
* The QDict values are of type QString.
* Convert from QemuOpts to QDict. The QDict values are of type QString.
*
* If @list is given, only add those options to the QDict that are contained in
* the list. If @del is true, any options added to the QDict are removed from
* the QemuOpts, otherwise they remain there.
*
* If two options in @opts have the same name, they are processed in order
* so that the last one wins (consistent with the reverse iteration in
* qemu_opt_find()), but all of them are deleted if @del is true.
*
* TODO We'll want to use types appropriate for opt->desc->type, but
* this is enough for now.
*/
QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
QDict *qemu_opts_to_qdict_filtered(QemuOpts *opts, QDict *qdict,
QemuOptsList *list, bool del)
{
QemuOpt *opt;
QemuOpt *opt, *next;
if (!qdict) {
qdict = qdict_new();
@ -1022,12 +1031,35 @@ QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
if (opts->id) {
qdict_put_str(qdict, "id", opts->id);
}
QTAILQ_FOREACH(opt, &opts->head, next) {
QTAILQ_FOREACH_SAFE(opt, &opts->head, next, next) {
if (list) {
QemuOptDesc *desc;
bool found = false;
for (desc = list->desc; desc->name; desc++) {
if (!strcmp(desc->name, opt->name)) {
found = true;
break;
}
}
if (!found) {
continue;
}
}
qdict_put_str(qdict, opt->name, opt->str);
if (del) {
qemu_opt_del(opt);
}
}
return qdict;
}
/* Copy all options in a QemuOpts to the given QDict. See
* qemu_opts_to_qdict_filtered() for details. */
QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
{
return qemu_opts_to_qdict_filtered(opts, qdict, NULL, false);
}
/* Validate parsed opts against descriptions where no
* descriptions were provided in the QemuOptsList.
*/