Add new interface, allowing use of existing node list. It will be used to fix bdrv_replace_node() in the further commit.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> --- block.c | 106 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 35 deletions(-) diff --git a/block.c b/block.c index 337b515034..31a4e4fa5c 100644 --- a/block.c +++ b/block.c @@ -2215,7 +2215,8 @@ static int bdrv_drv_set_perm(BlockDriverState *bs, uint64_t perm, static int bdrv_node_check_perm(BlockDriverState *bs, BlockReopenQueue *q, uint64_t cumulative_perms, uint64_t cumulative_shared_perms, - GSList *ignore_children, Error **errp) + GSList *ignore_children, + Transaction *tran, Error **errp) { BlockDriver *drv = bs->drv; BdrvChild *c; @@ -2263,7 +2264,7 @@ static int bdrv_node_check_perm(BlockDriverState *bs, BlockReopenQueue *q, return 0; } - ret = bdrv_drv_set_perm(bs, cumulative_perms, cumulative_shared_perms, NULL, + ret = bdrv_drv_set_perm(bs, cumulative_perms, cumulative_shared_perms, tran, errp); if (ret < 0) { return ret; @@ -2282,36 +2283,53 @@ static int bdrv_node_check_perm(BlockDriverState *bs, BlockReopenQueue *q, bdrv_child_perm(bs, c->bs, c, c->role, q, cumulative_perms, cumulative_shared_perms, &cur_perm, &cur_shared); - bdrv_child_set_perm_safe(c, cur_perm, cur_shared, NULL); + bdrv_child_set_perm_safe(c, cur_perm, cur_shared, tran); } return 0; } -static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q, - uint64_t cumulative_perms, - uint64_t cumulative_shared_perms, - GSList *ignore_children, Error **errp) +/* + * If use_cumulative_perms is true, use cumulative_perms and + * cumulative_shared_perms for first element of the list. Otherwise just refresh + * all permissions. + */ +static int bdrv_check_perm_common(GSList *list, BlockReopenQueue *q, + bool use_cumulative_perms, + uint64_t cumulative_perms, + uint64_t cumulative_shared_perms, + GSList *ignore_children, + Transaction *tran, Error **errp) { int ret; - BlockDriverState *root = bs; - g_autoptr(GSList) list = bdrv_topological_dfs(NULL, NULL, root); + BlockDriverState *bs; - for ( ; list; list = list->next) { + if (use_cumulative_perms) { bs = list->data; - if (bs != root) { - if (bdrv_parent_perms_conflict(bs, ignore_children, errp)) { - return -EINVAL; - } + ret = bdrv_node_check_perm(bs, q, cumulative_perms, + cumulative_shared_perms, + ignore_children, tran, errp); + if (ret < 0) { + return ret; + } - bdrv_get_cumulative_perm(bs, &cumulative_perms, - &cumulative_shared_perms); + list = list->next; + } + + for ( ; list; list = list->next) { + bs = list->data; + + if (bdrv_parent_perms_conflict(bs, ignore_children, errp)) { + return -EINVAL; } + bdrv_get_cumulative_perm(bs, &cumulative_perms, + &cumulative_shared_perms); + ret = bdrv_node_check_perm(bs, q, cumulative_perms, cumulative_shared_perms, - ignore_children, errp); + ignore_children, tran, errp); if (ret < 0) { return ret; } @@ -2320,6 +2338,23 @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q, return 0; } +static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q, + uint64_t cumulative_perms, + uint64_t cumulative_shared_perms, + GSList *ignore_children, Error **errp) +{ + g_autoptr(GSList) list = bdrv_topological_dfs(NULL, NULL, bs); + return bdrv_check_perm_common(list, q, true, cumulative_perms, + cumulative_shared_perms, ignore_children, + NULL, errp); +} + +static int bdrv_list_refresh_perms(GSList *list, BlockReopenQueue *q, + Transaction *tran, Error **errp) +{ + return bdrv_check_perm_common(list, q, false, 0, 0, NULL, tran, errp); +} + /* * Notifies drivers that after a previous bdrv_check_perm() call, the * permission update is not performed and any preparations made for it (e.g. @@ -2341,15 +2376,19 @@ static void bdrv_node_abort_perm_update(BlockDriverState *bs) } } -static void bdrv_abort_perm_update(BlockDriverState *bs) +static void bdrv_list_abort_perm_update(GSList *list) { - g_autoptr(GSList) list = bdrv_topological_dfs(NULL, NULL, bs); - for ( ; list; list = list->next) { bdrv_node_abort_perm_update((BlockDriverState *)list->data); } } +static void bdrv_abort_perm_update(BlockDriverState *bs) +{ + g_autoptr(GSList) list = bdrv_topological_dfs(NULL, NULL, bs); + return bdrv_list_abort_perm_update(list); +} + static void bdrv_node_set_perm(BlockDriverState *bs) { BlockDriver *drv = bs->drv; @@ -2373,15 +2412,19 @@ static void bdrv_node_set_perm(BlockDriverState *bs) } } -static void bdrv_set_perm(BlockDriverState *bs) +static void bdrv_list_set_perm(GSList *list) { - g_autoptr(GSList) list = bdrv_topological_dfs(NULL, NULL, bs); - for ( ; list; list = list->next) { bdrv_node_set_perm((BlockDriverState *)list->data); } } +static void bdrv_set_perm(BlockDriverState *bs) +{ + g_autoptr(GSList) list = bdrv_topological_dfs(NULL, NULL, bs); + return bdrv_list_set_perm(list); +} + void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm, uint64_t *shared_perm) { @@ -2489,20 +2532,13 @@ static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q, static int bdrv_refresh_perms(BlockDriverState *bs, Error **errp) { int ret; - uint64_t perm, shared_perm; + Transaction *tran = tran_new(); + g_autoptr(GSList) list = bdrv_topological_dfs(NULL, NULL, bs); - if (bdrv_parent_perms_conflict(bs, NULL, errp)) { - return -EPERM; - } - bdrv_get_cumulative_perm(bs, &perm, &shared_perm); - ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, errp); - if (ret < 0) { - bdrv_abort_perm_update(bs); - return ret; - } - bdrv_set_perm(bs); + ret = bdrv_list_refresh_perms(list, NULL, tran, errp); + tran_finalize(tran, ret); - return 0; + return ret; } int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared, -- 2.29.2