block: Exclude nested options only for children in append_open_options()

Some drivers have nested options (e.g. blkdebug rule arrays), which
don't belong to a child node and shouldn't be removed. Don't remove all
options with "." in their name, but check for the complete prefixes of
actually existing child nodes.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
Kevin Wolf 2015-04-27 13:46:22 +02:00
parent 9e700c1ac6
commit 260fecf13b
2 changed files with 17 additions and 4 deletions

20
block.c
View File

@ -1101,11 +1101,13 @@ static int bdrv_fill_options(QDict **options, const char **pfilename,
static BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, static BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
BlockDriverState *child_bs, BlockDriverState *child_bs,
const char *child_name,
const BdrvChildRole *child_role) const BdrvChildRole *child_role)
{ {
BdrvChild *child = g_new(BdrvChild, 1); BdrvChild *child = g_new(BdrvChild, 1);
*child = (BdrvChild) { *child = (BdrvChild) {
.bs = child_bs, .bs = child_bs,
.name = g_strdup(child_name),
.role = child_role, .role = child_role,
}; };
@ -1119,6 +1121,7 @@ static void bdrv_detach_child(BdrvChild *child)
{ {
QLIST_REMOVE(child, next); QLIST_REMOVE(child, next);
QLIST_REMOVE(child, next_parent); QLIST_REMOVE(child, next_parent);
g_free(child->name);
g_free(child); g_free(child);
} }
@ -1165,7 +1168,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
bs->backing = NULL; bs->backing = NULL;
goto out; goto out;
} }
bs->backing = bdrv_attach_child(bs, backing_hd, &child_backing); bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing);
bs->open_flags &= ~BDRV_O_NO_BACKING; bs->open_flags &= ~BDRV_O_NO_BACKING;
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_hd->filename); pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_hd->filename);
pstrcpy(bs->backing_format, sizeof(bs->backing_format), pstrcpy(bs->backing_format, sizeof(bs->backing_format),
@ -1321,7 +1324,7 @@ BdrvChild *bdrv_open_child(const char *filename,
goto done; goto done;
} }
c = bdrv_attach_child(parent, bs, child_role); c = bdrv_attach_child(parent, bs, bdref_key, child_role);
done: done:
qdict_del(options, bdref_key); qdict_del(options, bdref_key);
@ -3951,13 +3954,22 @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
{ {
const QDictEntry *entry; const QDictEntry *entry;
QemuOptDesc *desc; QemuOptDesc *desc;
BdrvChild *child;
bool found_any = false; bool found_any = false;
const char *p;
for (entry = qdict_first(bs->options); entry; for (entry = qdict_first(bs->options); entry;
entry = qdict_next(bs->options, entry)) entry = qdict_next(bs->options, entry))
{ {
/* Only take options for this level */ /* Exclude options for children */
if (strchr(qdict_entry_key(entry), '.')) { QLIST_FOREACH(child, &bs->children, next) {
if (strstart(qdict_entry_key(entry), child->name, &p)
&& (!*p || *p == '.'))
{
break;
}
}
if (child) {
continue; continue;
} }

View File

@ -351,6 +351,7 @@ extern const BdrvChildRole child_format;
struct BdrvChild { struct BdrvChild {
BlockDriverState *bs; BlockDriverState *bs;
char *name;
const BdrvChildRole *role; const BdrvChildRole *role;
QLIST_ENTRY(BdrvChild) next; QLIST_ENTRY(BdrvChild) next;
QLIST_ENTRY(BdrvChild) next_parent; QLIST_ENTRY(BdrvChild) next_parent;