src/qemu/src-pmp/block.c
/*
 * Check whether permissions on this node can be changed in a way that
 * @cumulative_perms and @cumulative_shared_perms are the new cumulative
 * permissions of all its parents. This involves checking whether all necessary
 * permission changes to child nodes can be performed.
 *
 * A call to this function must always be followed by a call to bdrv_set_perm()
 * or bdrv_abort_perm_update().
 */
Check whether permissions on this node can be changed in a way that
@cumulative_perms and @cumulative_shared_perms are the new cumulative
permissions of all its parents. This involves checking whether all necessary
permission changes to child nodes can be performed.

A call to this function must always be followed by a call to bdrv_set_perm()
or bdrv_abort_perm_update().
Check whether permissions on this node can be changed in a way that @cumulative_perms and @cumulative_shared_perms are the new cumulative permissions of all its parents . This involves checking whether all necessary permission changes to child nodes can be performed . 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, Error **errp)
{
    BlockDriver *drv = bs->drv;
    BdrvChild *c;
    int ret;
    if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) &&
        !bdrv_is_writable_after_reopen(bs, q))
    {
        error_setg(errp, "Block node is read-only");
        return -EPERM;
    }
    if (!drv) {
        return 0;
    }
    if (drv->bdrv_check_perm) {
        return drv->bdrv_check_perm(bs, cumulative_perms,
                                    cumulative_shared_perms, errp);
    }
    if (!drv->bdrv_child_perm) {
        assert(QLIST_EMPTY(&bs->children));
        return 0;
    }
    QLIST_FOREACH(c, &bs->children, next) {
        uint64_t cur_perm, cur_shared;
        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, errp);
        if (ret < 0) {
            return ret;
        }
    }
    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 ) { BlockDriver * drv = bs -> drv ; BdrvChild * c ; int ret ; if ( ( cumulative_perms & ( BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED ) ) && ! bdrv_is_writable_after_reopen ( bs , q ) ) { error_setg ( errp , " " ) ; return - EPERM ; } if ( ! drv ) { return 0 ; } if ( drv -> bdrv_check_perm ) { return drv -> bdrv_check_perm ( bs , cumulative_perms , cumulative_shared_perms , errp ) ; } if ( ! drv -> bdrv_child_perm ) { assert ( QLIST_EMPTY ( & bs -> children ) ) ; return 0 ; } QLIST_FOREACH ( c , & bs -> children , next ) { uint64_t cur_perm , cur_shared ; 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 , errp ) ; if ( ret < 0 ) { return ret ; } } 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
 permissions of all its parents.
Check whether permissions on this node can be changed in a way that @cumulative_perms and @cumulative_shared_perms are the new cumulative permissions of all its parents .
/* Write permissions never work with read-only images */ /* Check this node */ /* Drivers that never have children can omit .bdrv_child_perm() */ /* Check all children */