qemu/block.c
/*
 * Opens the backing file for a BlockDriverState if not yet open
 *
 * bdref_key specifies the key for the image's BlockdevRef in the options QDict.
 * That QDict has to be flattened; therefore, if the BlockdevRef is a QDict
 * itself, all options starting with "${bdref_key}." are considered part of the
 * BlockdevRef.
 *
 * TODO Can this be unified with bdrv_open_image()?
 */
Opens the backing file for a BlockDriverState if not yet open
bdref_key specifies the key for the image's BlockdevRef in the options QDict.
That QDict has to be flattened; therefore, if the BlockdevRef is a QDict
itself, all options starting with "${bdref_key}." are considered part of the
BlockdevRef.


Opens the backing file for a BlockDriverState if not yet open bdref_key specifies the key for the image ' s BlockdevRef in the options QDict . That QDict has to be flattened ; therefore if the BlockdevRef is a QDict itself all options starting with " $ { bdref_key } . " are considered part of the BlockdevRef .
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
                           const char *bdref_key, Error **errp)
{
    char *backing_filename = g_malloc0(PATH_MAX);
    char *bdref_key_dot;
    const char *reference = NULL;
    int ret = 0;
    BlockDriverState *backing_hd;
    QDict *options;
    QDict *tmp_parent_options = NULL;
    Error *local_err = NULL;
    if (bs->backing != NULL) {
        goto free_exit;
    }
    if (parent_options == NULL) {
        tmp_parent_options = qdict_new();
        parent_options = tmp_parent_options;
    }
    bs->open_flags &= ~BDRV_O_NO_BACKING;
    bdref_key_dot = g_strdup_printf("%s.", bdref_key);
    qdict_extract_subqdict(parent_options, &options, bdref_key_dot);
    g_free(bdref_key_dot);
    reference = qdict_get_try_str(parent_options, bdref_key);
    if (reference || qdict_haskey(options, "file.filename")) {
        backing_filename[0] = '\0';
    } else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
        qobject_unref(options);
        goto free_exit;
    } else {
        bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX,
                                       &local_err);
        if (local_err) {
            ret = -EINVAL;
            error_propagate(errp, local_err);
            qobject_unref(options);
            goto free_exit;
        }
    }
    if (!bs->drv || !bs->drv->supports_backing) {
        ret = -EINVAL;
        error_setg(errp, "Driver doesn't support backing files");
        qobject_unref(options);
        goto free_exit;
    }
    if (!reference &&
        bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) {
        qdict_put_str(options, "driver", bs->backing_format);
    }
    backing_hd = bdrv_open_inherit(*backing_filename ? backing_filename : NULL,
                                   reference, options, 0, bs, &child_backing,
                                   errp);
    if (!backing_hd) {
        bs->open_flags |= BDRV_O_NO_BACKING;
        error_prepend(errp, "Could not open backing file: ");
        ret = -EINVAL;
        goto free_exit;
    }
    bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs));
    bdrv_set_backing_hd(bs, backing_hd, &local_err);
    bdrv_unref(backing_hd);
    if (local_err) {
        error_propagate(errp, local_err);
        ret = -EINVAL;
        goto free_exit;
    }
    qdict_del(parent_options, bdref_key);
free_exit:
    g_free(backing_filename);
    qobject_unref(tmp_parent_options);
    return ret;
}
int bdrv_open_backing_file ( BlockDriverState * bs , QDict * parent_options , const char * bdref_key , Error * * errp ) { char * backing_filename = g_malloc0 ( PATH_MAX ) ; char * bdref_key_dot ; const char * reference = NULL ; int ret = 0 ; BlockDriverState * backing_hd ; QDict * options ; QDict * tmp_parent_options = NULL ; Error * local_err = NULL ; if ( bs -> backing != NULL ) { goto free_exit ; } if ( parent_options == NULL ) { tmp_parent_options = qdict_new ( ) ; parent_options = tmp_parent_options ; } bs -> open_flags &= ~ BDRV_O_NO_BACKING ; bdref_key_dot = g_strdup_printf ( " " , bdref_key ) ; qdict_extract_subqdict ( parent_options , & options , bdref_key_dot ) ; g_free ( bdref_key_dot ) ; reference = qdict_get_try_str ( parent_options , bdref_key ) ; if ( reference || qdict_haskey ( options , " " ) ) { backing_filename [ 0 ] = ' \0 ' ; } else if ( bs -> backing_file [ 0 ] == ' \0 ' && qdict_size ( options ) == 0 ) { qobject_unref ( options ) ; goto free_exit ; } else { bdrv_get_full_backing_filename ( bs , backing_filename , PATH_MAX , & local_err ) ; if ( local_err ) { ret = - EINVAL ; error_propagate ( errp , local_err ) ; qobject_unref ( options ) ; goto free_exit ; } } if ( ! bs -> drv || ! bs -> drv -> supports_backing ) { ret = - EINVAL ; error_setg ( errp , " " ) ; qobject_unref ( options ) ; goto free_exit ; } if ( ! reference && bs -> backing_format [ 0 ] != ' \0 ' && ! qdict_haskey ( options , " " ) ) { qdict_put_str ( options , " " , bs -> backing_format ) ; } backing_hd = bdrv_open_inherit ( * backing_filename ? backing_filename : NULL , reference , options , 0 , bs , & child_backing , errp ) ; if ( ! backing_hd ) { bs -> open_flags |= BDRV_O_NO_BACKING ; error_prepend ( errp , " " ) ; ret = - EINVAL ; goto free_exit ; } bdrv_set_aio_context ( backing_hd , bdrv_get_aio_context ( bs ) ) ; bdrv_set_backing_hd ( bs , backing_hd , & local_err ) ; bdrv_unref ( backing_hd ) ; if ( local_err ) { error_propagate ( errp , local_err ) ; ret = - EINVAL ; goto free_exit ; } qdict_del ( parent_options , bdref_key ) ; free_exit : g_free ( backing_filename ) ; qobject_unref ( tmp_parent_options ) ; return ret ; }
Opens the backing file for a BlockDriverState if not yet open
 bdref_key specifies the key for the image's BlockdevRef in the options QDict.
Opens the backing file for a BlockDriverState if not yet open bdref_key specifies the key for the image ' s BlockdevRef in the options QDict .
/* NULL means an empty set of options */ /*
     * Caution: while qdict_get_try_str() is fine, getting non-string
     * types would require more care.  When @parent_options come from
     * -blockdev or blockdev_add, its members are typed according to
     * the QAPI schema, but when they come from -drive, they're all
     * QString.
     */ /* Hook up the backing file link; drop our reference, bs owns the
     * backing_hd reference now */