qemu/block.c
/*
 * Adds a BlockDriverState to a simple queue for an atomic, transactional
 * reopen of multiple devices.
 *
 * bs_queue can either be an existing BlockReopenQueue that has had QSIMPLE_INIT
 * already performed, or alternatively may be NULL a new BlockReopenQueue will
 * be created and initialized. This newly created BlockReopenQueue should be
 * passed back in for subsequent calls that are intended to be of the same
 * atomic 'set'.
 *
 * bs is the BlockDriverState to add to the reopen queue.
 *
 * options contains the changed options for the associated bs
 * (the BlockReopenQueue takes ownership)
 *
 * flags contains the open flags for the associated bs
 *
 * returns a pointer to bs_queue, which is either the newly allocated
 * bs_queue, or the existing bs_queue being used.
 *
 * bs must be drained between bdrv_reopen_queue() and bdrv_reopen_multiple().
 */
Adds a BlockDriverState to a simple queue for an atomic, transactional
reopen of multiple devices.

bs_queue can either be an existing BlockReopenQueue that has had QSIMPLE_INIT
already performed, or alternatively may be NULL a new BlockReopenQueue will
be created and initialized. This newly created BlockReopenQueue should be
passed back in for subsequent calls that are intended to be of the same
atomic 'set'.

bs is the BlockDriverState to add to the reopen queue.

options contains the changed options for the associated bs
(the BlockReopenQueue takes ownership)

flags contains the open flags for the associated bs

returns a pointer to bs_queue, which is either the newly allocated
bs_queue, or the existing bs_queue being used.

bs must be drained between bdrv_reopen_queue() and bdrv_reopen_multiple().
Adds a BlockDriverState to a simple queue for an atomic transactional reopen of multiple devices . bs_queue can either be an existing BlockReopenQueue that has had QSIMPLE_INIT already performed or alternatively may be NULL a new BlockReopenQueue will be created and initialized . This newly created BlockReopenQueue should be passed back in for subsequent calls that are intended to be of the same atomic ' set ' . bs is the BlockDriverState to add to the reopen queue . options contains the changed options for the associated bs ( the BlockReopenQueue takes ownership ) flags contains the open flags for the associated bs returns a pointer to bs_queue which is either the newly allocated bs_queue or the existing bs_queue being used . bs must be drained between bdrv_reopen_queue () and bdrv_reopen_multiple () .
static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
                                                 BlockDriverState *bs,
                                                 QDict *options,
                                                 int flags,
                                                 const BdrvChildRole *role,
                                                 QDict *parent_options,
                                                 int parent_flags)
{
    assert(bs != NULL);
    BlockReopenQueueEntry *bs_entry;
    BdrvChild *child;
    QDict *old_options, *explicit_options;
    assert(bs->quiesce_counter > 0);
    if (bs_queue == NULL) {
        bs_queue = g_new0(BlockReopenQueue, 1);
        QSIMPLEQ_INIT(bs_queue);
    }
    if (!options) {
        options = qdict_new();
    }
    QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) {
        if (bs == bs_entry->state.bs) {
            break;
        }
    }
    if (!parent_options) {
        update_options_from_flags(options, flags);
    }
    if (bs_entry) {
        old_options = qdict_clone_shallow(bs_entry->state.explicit_options);
    } else {
        old_options = qdict_clone_shallow(bs->explicit_options);
    }
    bdrv_join_options(bs, options, old_options);
    qobject_unref(old_options);
    explicit_options = qdict_clone_shallow(options);
    if (parent_options) {
        QemuOpts *opts;
        QDict *options_copy;
        assert(!flags);
        role->inherit_options(&flags, options, parent_flags, parent_options);
        options_copy = qdict_clone_shallow(options);
        opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
        qemu_opts_absorb_qdict(opts, options_copy, NULL);
        update_flags_from_options(&flags, opts);
        qemu_opts_del(opts);
        qobject_unref(options_copy);
    }
    old_options = qdict_clone_shallow(bs->options);
    bdrv_join_options(bs, options, old_options);
    qobject_unref(old_options);
    flags &= ~BDRV_O_PROTOCOL;
    if (flags & BDRV_O_RDWR) {
        flags |= BDRV_O_ALLOW_RDWR;
    }
    if (!bs_entry) {
        bs_entry = g_new0(BlockReopenQueueEntry, 1);
        QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry);
    } else {
        qobject_unref(bs_entry->state.options);
        qobject_unref(bs_entry->state.explicit_options);
    }
    bs_entry->state.bs = bs;
    bs_entry->state.options = options;
    bs_entry->state.explicit_options = explicit_options;
    bs_entry->state.flags = flags;
    bs_entry->state.perm = UINT64_MAX;
    bs_entry->state.shared_perm = 0;
    QLIST_FOREACH(child, &bs->children, next) {
        QDict *new_child_options;
        char *child_key_dot;
        if (child->bs->inherits_from != bs) {
            continue;
        }
        child_key_dot = g_strdup_printf("%s.", child->name);
        qdict_extract_subqdict(explicit_options, NULL, child_key_dot);
        qdict_extract_subqdict(options, &new_child_options, child_key_dot);
        g_free(child_key_dot);
        bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options, 0,
                                child->role, options, flags);
    }
    return bs_queue;
}
static BlockReopenQueue * bdrv_reopen_queue_child ( BlockReopenQueue * bs_queue , BlockDriverState * bs , QDict * options , int flags , const BdrvChildRole * role , QDict * parent_options , int parent_flags ) { assert ( bs != NULL ) ; BlockReopenQueueEntry * bs_entry ; BdrvChild * child ; QDict * old_options , * explicit_options ; assert ( bs -> quiesce_counter > 0 ) ; if ( bs_queue == NULL ) { bs_queue = g_new0 ( BlockReopenQueue , 1 ) ; QSIMPLEQ_INIT ( bs_queue ) ; } if ( ! options ) { options = qdict_new ( ) ; } QSIMPLEQ_FOREACH ( bs_entry , bs_queue , entry ) { if ( bs == bs_entry -> state . bs ) { break ; } } if ( ! parent_options ) { update_options_from_flags ( options , flags ) ; } if ( bs_entry ) { old_options = qdict_clone_shallow ( bs_entry -> state . explicit_options ) ; } else { old_options = qdict_clone_shallow ( bs -> explicit_options ) ; } bdrv_join_options ( bs , options , old_options ) ; qobject_unref ( old_options ) ; explicit_options = qdict_clone_shallow ( options ) ; if ( parent_options ) { QemuOpts * opts ; QDict * options_copy ; assert ( ! flags ) ; role -> inherit_options ( & flags , options , parent_flags , parent_options ) ; options_copy = qdict_clone_shallow ( options ) ; opts = qemu_opts_create ( & bdrv_runtime_opts , NULL , 0 , & error_abort ) ; qemu_opts_absorb_qdict ( opts , options_copy , NULL ) ; update_flags_from_options ( & flags , opts ) ; qemu_opts_del ( opts ) ; qobject_unref ( options_copy ) ; } old_options = qdict_clone_shallow ( bs -> options ) ; bdrv_join_options ( bs , options , old_options ) ; qobject_unref ( old_options ) ; flags &= ~ BDRV_O_PROTOCOL ; if ( flags & BDRV_O_RDWR ) { flags |= BDRV_O_ALLOW_RDWR ; } if ( ! bs_entry ) { bs_entry = g_new0 ( BlockReopenQueueEntry , 1 ) ; QSIMPLEQ_INSERT_TAIL ( bs_queue , bs_entry , entry ) ; } else { qobject_unref ( bs_entry -> state . options ) ; qobject_unref ( bs_entry -> state . explicit_options ) ; } bs_entry -> state . bs = bs ; bs_entry -> state . options = options ; bs_entry -> state . explicit_options = explicit_options ; bs_entry -> state . flags = flags ; bs_entry -> state . perm = UINT64_MAX ; bs_entry -> state . shared_perm = 0 ; QLIST_FOREACH ( child , & bs -> children , next ) { QDict * new_child_options ; char * child_key_dot ; if ( child -> bs -> inherits_from != bs ) { continue ; } child_key_dot = g_strdup_printf ( " " , child -> name ) ; qdict_extract_subqdict ( explicit_options , NULL , child_key_dot ) ; qdict_extract_subqdict ( options , & new_child_options , child_key_dot ) ; g_free ( child_key_dot ) ; bdrv_reopen_queue_child ( bs_queue , child -> bs , new_child_options , 0 , child -> role , options , flags ) ; } return bs_queue ; }
Adds a BlockDriverState to a simple queue for an atomic, transactional
 reopen of multiple devices.
Adds a BlockDriverState to a simple queue for an atomic transactional reopen of multiple devices .
/* Make sure that the caller remembered to use a drained section. This is
     * important to avoid graph changes between the recursive queuing here and
     * bdrv_reopen_multiple(). */ /* Check if this BlockDriverState is already in the queue */ /*
     * Precedence of options:
     * 1. Explicitly passed in options (highest)
     * 2. Set in flags (only for top level)
     * 3. Retained from explicitly set options of bs
     * 4. Inherited from parent node
     * 5. Retained from effective options of bs
     */ /*
         * Any setting represented by flags is always updated. If the
         * corresponding QDict option is set, it takes precedence. Otherwise
         * the flag is translated into a QDict option. The old setting of bs is
         * not considered.
         */ /* Old explicitly set values (don't overwrite by inherited value) */ /* Inherit from parent node */ /* Old values are used for options that aren't set yet */ /* bdrv_open_inherit() sets and clears some additional flags internally */ /* This needs to be overwritten in bdrv_reopen_prepare() */ /* reopen can only change the options of block devices that were
         * implicitly created and inherited options. For other (referenced)
         * block devices, a syntax like "backing.foo" results in an error. */