bdrv_append is not very good for inserting filters: it does extra permission update as part of bdrv_set_backing_hd(). During this update filter may conflict with other parents of top_bs.
Instead, let's first do all graph modifications and after it update permissions. append-greedy-filter test-case in test-bdrv-graph-mod is now works, so move it out of debug option. Note: bdrv_append() is still only works for backing-child based filters. It's something to improve later. Note2: we use the fact that bdrv_append() is used to append new nodes, without backing child, so we don't need frozen check and inherits_from logic from bdrv_set_backing_hd(). Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> Reviewed-by: Kevin Wolf <kw...@redhat.com> --- block.c | 27 ++++++++++++++++++++------- tests/unit/test-bdrv-graph-mod.c | 17 ++--------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/block.c b/block.c index 9283c8d97b..5bb6a2bef9 100644 --- a/block.c +++ b/block.c @@ -5088,25 +5088,38 @@ int bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, * This will modify the BlockDriverState fields, and swap contents * between bs_new and bs_top. Both bs_new and bs_top are modified. * - * bs_new must not be attached to a BlockBackend. + * bs_new must not be attached to a BlockBackend and must not have backing + * child. * * This function does not create any image files. */ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top, Error **errp) { - int ret = bdrv_set_backing_hd(bs_new, bs_top, errp); + int ret; + Transaction *tran = tran_new(); + + assert(!bs_new->backing); + + ret = bdrv_attach_child_noperm(bs_new, bs_top, "backing", + &child_of_bds, bdrv_backing_role(bs_new), + &bs_new->backing, tran, errp); if (ret < 0) { - return ret; + goto out; } - ret = bdrv_replace_node(bs_top, bs_new, errp); + ret = bdrv_replace_node_noperm(bs_top, bs_new, true, tran, errp); if (ret < 0) { - bdrv_set_backing_hd(bs_new, NULL, &error_abort); - return ret; + goto out; } - return 0; + ret = bdrv_refresh_perms(bs_new, errp); +out: + tran_finalize(tran, ret); + + bdrv_refresh_limits(bs_top, NULL); + + return ret; } static void bdrv_delete(BlockDriverState *bs) diff --git a/tests/unit/test-bdrv-graph-mod.c b/tests/unit/test-bdrv-graph-mod.c index 7b3c8b437a..88f25c0cdb 100644 --- a/tests/unit/test-bdrv-graph-mod.c +++ b/tests/unit/test-bdrv-graph-mod.c @@ -388,16 +388,6 @@ static void test_append_greedy_filter(void) int main(int argc, char *argv[]) { - int i; - bool debug = false; - - for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "-d")) { - debug = true; - break; - } - } - bdrv_init(); qemu_init_main_loop(&error_abort); @@ -410,11 +400,8 @@ int main(int argc, char *argv[]) test_parallel_perm_update); g_test_add_func("/bdrv-graph-mod/parallel-exclusive-write", test_parallel_exclusive_write); - - if (debug) { - g_test_add_func("/bdrv-graph-mod/append-greedy-filter", - test_append_greedy_filter); - } + g_test_add_func("/bdrv-graph-mod/append-greedy-filter", + test_append_greedy_filter); return g_test_run(); } -- 2.29.2