diff --git a/block.c b/block.c index cbcc4c15a0..ab7a4d13d8 100644 --- a/block.c +++ b/block.c @@ -2189,6 +2189,54 @@ static void bdrv_child_set_perm_safe(BdrvChild *c, uint64_t perm, } } +static void bdrv_drv_set_perm_commit(void *opaque) +{ + BlockDriverState *bs = opaque; + uint64_t cumulative_perms, cumulative_shared_perms; + + if (bs->drv->bdrv_set_perm) { + bdrv_get_cumulative_perm(bs, &cumulative_perms, + &cumulative_shared_perms); + bs->drv->bdrv_set_perm(bs, cumulative_perms, cumulative_shared_perms); + } +} + +static void bdrv_drv_set_perm_abort(void *opaque) +{ + BlockDriverState *bs = opaque; + + if (bs->drv->bdrv_abort_perm_update) { + bs->drv->bdrv_abort_perm_update(bs); + } +} + +TransactionActionDrv bdrv_drv_set_perm_drv = { + .abort = bdrv_drv_set_perm_abort, + .commit = bdrv_drv_set_perm_commit, +}; + +static int bdrv_drv_set_perm(BlockDriverState *bs, uint64_t perm, + uint64_t shared_perm, Transaction *tran, + Error **errp) +{ + if (!bs->drv) { + return 0; + } + + if (bs->drv->bdrv_check_perm) { + int ret = bs->drv->bdrv_check_perm(bs, perm, shared_perm, errp); + if (ret < 0) { + return ret; + } + } + + if (tran) { + tran_add(tran, &bdrv_drv_set_perm_drv, bs); + } + + return 0; +} + /* * Check whether permissions on this node can be changed in a way that * @cumulative_perms and @cumulative_shared_perms are the new cumulative @@ -2249,12 +2297,10 @@ static int bdrv_node_check_perm(BlockDriverState *bs, BlockReopenQueue *q, return 0; } - if (drv->bdrv_check_perm) { - ret = drv->bdrv_check_perm(bs, cumulative_perms, - cumulative_shared_perms, errp); - if (ret < 0) { - return ret; - } + ret = bdrv_drv_set_perm(bs, cumulative_perms, cumulative_shared_perms, NULL, + errp); + if (ret < 0) { + return ret; } /* Drivers that never have children can omit .bdrv_child_perm() */ @@ -2322,9 +2368,7 @@ static void bdrv_node_abort_perm_update(BlockDriverState *bs) return; } - if (drv->bdrv_abort_perm_update) { - drv->bdrv_abort_perm_update(bs); - } + bdrv_drv_set_perm_abort(bs); QLIST_FOREACH(c, &bs->children, next) { bdrv_child_set_perm_abort(c); @@ -2342,7 +2386,6 @@ static void bdrv_abort_perm_update(BlockDriverState *bs) static void bdrv_node_set_perm(BlockDriverState *bs) { - uint64_t cumulative_perms, cumulative_shared_perms; BlockDriver *drv = bs->drv; BdrvChild *c; @@ -2350,12 +2393,7 @@ static void bdrv_node_set_perm(BlockDriverState *bs) return; } - bdrv_get_cumulative_perm(bs, &cumulative_perms, &cumulative_shared_perms); - - /* Update this node */ - if (drv->bdrv_set_perm) { - drv->bdrv_set_perm(bs, cumulative_perms, cumulative_shared_perms); - } + bdrv_drv_set_perm_commit(bs); /* Drivers that never have children can omit .bdrv_child_perm() */ if (!drv->bdrv_child_perm) {