Skip to content

Commit

Permalink
block: Update open_flags after ->inactivate() callback
Browse files Browse the repository at this point in the history
In the ->inactivate() callbacks, permissions are updated, which
typically involves a recursive check of the whole graph. Setting
BDRV_O_INACTIVE right before doing that creates a state that
bdrv_is_writable() returns false, which causes permission update
failure.

Reorder them so the flag is updated after calling the function. Note
that this doesn't break the assert in bdrv_child_cb_inactivate() because
for any specific BDS, we still update its flags first before calling
->inactivate() on it one level deeper in the recursion.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <20170823134242.12080-5-famz@redhat.com>
Tested-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
  • Loading branch information
stefanhaRH authored and ebblake committed Aug 23, 2017
1 parent 045a2f8 commit 7d5b526
Showing 1 changed file with 3 additions and 4 deletions.
7 changes: 3 additions & 4 deletions block.c
Expand Up @@ -4085,21 +4085,20 @@ static int bdrv_inactivate_recurse(BlockDriverState *bs,
}
}

if (setting_flag) {
if (setting_flag && !(bs->open_flags & BDRV_O_INACTIVE)) {
uint64_t perm, shared_perm;

bs->open_flags |= BDRV_O_INACTIVE;

QLIST_FOREACH(parent, &bs->parents, next_parent) {
if (parent->role->inactivate) {
ret = parent->role->inactivate(parent);
if (ret < 0) {
bs->open_flags &= ~BDRV_O_INACTIVE;
return ret;
}
}
}

bs->open_flags |= BDRV_O_INACTIVE;

/* Update permissions, they may differ for inactive nodes */
bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
bdrv_check_perm(bs, perm, shared_perm, NULL, &error_abort);
Expand Down

0 comments on commit 7d5b526

Please sign in to comment.