aboutsummaryrefslogtreecommitdiff
path: root/block.c
diff options
context:
space:
mode:
Diffstat (limited to 'block.c')
-rw-r--r--block.c89
1 files changed, 17 insertions, 72 deletions
diff --git a/block.c b/block.c
index f66388b..b57421a 100644
--- a/block.c
+++ b/block.c
@@ -1900,8 +1900,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
uint64_t perm, uint64_t shared,
- GSList *ignore_children,
- bool *tighten_restrictions, Error **errp);
+ GSList *ignore_children, Error **errp);
static void bdrv_child_abort_perm_update(BdrvChild *c);
static void bdrv_child_set_perm(BdrvChild *c);
@@ -1974,43 +1973,18 @@ static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
* permissions of all its parents. This involves checking whether all necessary
* permission changes to child nodes can be performed.
*
- * Will set *tighten_restrictions to true if and only if new permissions have to
- * be taken or currently shared permissions are to be unshared. Otherwise,
- * errors are not fatal as long as the caller accepts that the restrictions
- * remain tighter than they need to be. The caller still has to abort the
- * transaction.
- * @tighten_restrictions cannot be used together with @q: When reopening, we may
- * encounter fatal errors even though no restrictions are to be tightened. For
- * example, changing a node from RW to RO will fail if the WRITE permission is
- * to be kept.
- *
* A call to this function must always be followed by a call to bdrv_set_perm()
* or bdrv_abort_perm_update().
*/
static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
uint64_t cumulative_perms,
uint64_t cumulative_shared_perms,
- GSList *ignore_children,
- bool *tighten_restrictions, Error **errp)
+ GSList *ignore_children, Error **errp)
{
BlockDriver *drv = bs->drv;
BdrvChild *c;
int ret;
- assert(!q || !tighten_restrictions);
-
- if (tighten_restrictions) {
- uint64_t current_perms, current_shared;
- uint64_t added_perms, removed_shared_perms;
-
- bdrv_get_cumulative_perm(bs, &current_perms, &current_shared);
-
- added_perms = cumulative_perms & ~current_perms;
- removed_shared_perms = current_shared & ~cumulative_shared_perms;
-
- *tighten_restrictions = added_perms || removed_shared_perms;
- }
-
/* Write permissions never work with read-only images */
if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) &&
!bdrv_is_writable_after_reopen(bs, q))
@@ -2067,18 +2041,12 @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
/* Check all children */
QLIST_FOREACH(c, &bs->children, next) {
uint64_t cur_perm, cur_shared;
- bool child_tighten_restr;
bdrv_child_perm(bs, c->bs, c, c->role, q,
cumulative_perms, cumulative_shared_perms,
&cur_perm, &cur_shared);
ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children,
- tighten_restrictions ? &child_tighten_restr
- : NULL,
errp);
- if (tighten_restrictions) {
- *tighten_restrictions |= child_tighten_restr;
- }
if (ret < 0) {
return ret;
}
@@ -2201,22 +2169,18 @@ char *bdrv_perm_names(uint64_t perm)
* set, the BdrvChild objects in this list are ignored in the calculations;
* this allows checking permission updates for an existing reference.
*
- * See bdrv_check_perm() for the semantics of @tighten_restrictions.
- *
* Needs to be followed by a call to either bdrv_set_perm() or
* bdrv_abort_perm_update(). */
static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
uint64_t new_used_perm,
uint64_t new_shared_perm,
GSList *ignore_children,
- bool *tighten_restrictions,
Error **errp)
{
BdrvChild *c;
uint64_t cumulative_perms = new_used_perm;
uint64_t cumulative_shared_perms = new_shared_perm;
- assert(!q || !tighten_restrictions);
/* There is no reason why anyone couldn't tolerate write_unchanged */
assert(new_shared_perm & BLK_PERM_WRITE_UNCHANGED);
@@ -2230,10 +2194,6 @@ static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
char *user = bdrv_child_user_desc(c);
char *perm_names = bdrv_perm_names(new_used_perm & ~c->shared_perm);
- if (tighten_restrictions) {
- *tighten_restrictions = true;
- }
-
error_setg(errp, "Conflicts with use by %s as '%s', which does not "
"allow '%s' on %s",
user, c->name, perm_names, bdrv_get_node_name(c->bs));
@@ -2246,10 +2206,6 @@ static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
char *user = bdrv_child_user_desc(c);
char *perm_names = bdrv_perm_names(c->perm & ~new_shared_perm);
- if (tighten_restrictions) {
- *tighten_restrictions = true;
- }
-
error_setg(errp, "Conflicts with use by %s as '%s', which uses "
"'%s' on %s",
user, c->name, perm_names, bdrv_get_node_name(c->bs));
@@ -2263,21 +2219,19 @@ static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
}
return bdrv_check_perm(bs, q, cumulative_perms, cumulative_shared_perms,
- ignore_children, tighten_restrictions, errp);
+ ignore_children, errp);
}
/* Needs to be followed by a call to either bdrv_child_set_perm() or
* bdrv_child_abort_perm_update(). */
static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
uint64_t perm, uint64_t shared,
- GSList *ignore_children,
- bool *tighten_restrictions, Error **errp)
+ GSList *ignore_children, Error **errp)
{
int ret;
ignore_children = g_slist_prepend(g_slist_copy(ignore_children), c);
- ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children,
- tighten_restrictions, errp);
+ ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children, errp);
g_slist_free(ignore_children);
if (ret < 0) {
@@ -2318,15 +2272,13 @@ static void bdrv_child_abort_perm_update(BdrvChild *c)
bdrv_abort_perm_update(c->bs);
}
-static int bdrv_refresh_perms(BlockDriverState *bs, bool *tighten_restrictions,
- Error **errp)
+static int bdrv_refresh_perms(BlockDriverState *bs, Error **errp)
{
int ret;
uint64_t perm, shared_perm;
bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
- ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL,
- tighten_restrictions, errp);
+ ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, errp);
if (ret < 0) {
bdrv_abort_perm_update(bs);
return ret;
@@ -2341,13 +2293,12 @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
{
Error *local_err = NULL;
int ret;
- bool tighten_restrictions;
- ret = bdrv_child_check_perm(c, NULL, perm, shared, NULL,
- &tighten_restrictions, &local_err);
+ ret = bdrv_child_check_perm(c, NULL, perm, shared, NULL, &local_err);
if (ret < 0) {
bdrv_child_abort_perm_update(c);
- if (tighten_restrictions) {
+ if ((perm & ~c->perm) || (c->shared_perm & ~shared)) {
+ /* tighten permissions */
error_propagate(errp, local_err);
} else {
/*
@@ -2649,15 +2600,12 @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
}
if (old_bs) {
- bool tighten_restrictions;
-
/*
* Update permissions for old node. We're just taking a parent away, so
* we're loosening restrictions. Errors of permission update are not
* fatal in this case, ignore them.
*/
- bdrv_refresh_perms(old_bs, &tighten_restrictions, NULL);
- assert(tighten_restrictions == false);
+ bdrv_refresh_perms(old_bs, NULL);
/* When the parent requiring a non-default AioContext is removed, the
* node moves back to the main AioContext */
@@ -2687,8 +2635,7 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
Error *local_err = NULL;
int ret;
- ret = bdrv_check_update_perm(child_bs, NULL, perm, shared_perm, NULL, NULL,
- errp);
+ ret = bdrv_check_update_perm(child_bs, NULL, perm, shared_perm, NULL, errp);
if (ret < 0) {
bdrv_abort_perm_update(child_bs);
bdrv_unref(child_bs);
@@ -3820,7 +3767,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
QTAILQ_FOREACH(bs_entry, bs_queue, entry) {
BDRVReopenState *state = &bs_entry->state;
ret = bdrv_check_perm(state->bs, bs_queue, state->perm,
- state->shared_perm, NULL, NULL, errp);
+ state->shared_perm, NULL, errp);
if (ret < 0) {
goto cleanup_perm;
}
@@ -3832,7 +3779,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
bs_queue, state->perm, state->shared_perm,
&nperm, &nshared);
ret = bdrv_check_update_perm(state->new_backing_bs, NULL,
- nperm, nshared, NULL, NULL, errp);
+ nperm, nshared, NULL, errp);
if (ret < 0) {
goto cleanup_perm;
}
@@ -4622,7 +4569,7 @@ static void bdrv_replace_node_common(BlockDriverState *from,
/* Check whether the required permissions can be granted on @to, ignoring
* all BdrvChild in @list so that they can't block themselves. */
- ret = bdrv_check_update_perm(to, NULL, perm, shared, list, NULL, errp);
+ ret = bdrv_check_update_perm(to, NULL, perm, shared, list, errp);
if (ret < 0) {
bdrv_abort_perm_update(to);
goto out;
@@ -5817,7 +5764,7 @@ int coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp)
*/
if (bs->open_flags & BDRV_O_INACTIVE) {
bs->open_flags &= ~BDRV_O_INACTIVE;
- ret = bdrv_refresh_perms(bs, NULL, errp);
+ ret = bdrv_refresh_perms(bs, errp);
if (ret < 0) {
bs->open_flags |= BDRV_O_INACTIVE;
return ret;
@@ -5896,7 +5843,6 @@ static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
static int bdrv_inactivate_recurse(BlockDriverState *bs)
{
BdrvChild *child, *parent;
- bool tighten_restrictions;
int ret;
if (!bs->drv) {
@@ -5935,8 +5881,7 @@ static int bdrv_inactivate_recurse(BlockDriverState *bs)
* We only tried to loosen restrictions, so errors are not fatal, ignore
* them.
*/
- bdrv_refresh_perms(bs, &tighten_restrictions, NULL);
- assert(tighten_restrictions == false);
+ bdrv_refresh_perms(bs, NULL);
/* Recursively inactivate children */
QLIST_FOREACH(child, &bs->children, next) {