Commit da557aac authored by Max Reitz's avatar Max Reitz Committed by Kevin Wolf
Browse files

block: Add bdrv_open_image()



Add a common function for opening images to be used for block drivers
specified through BlockdevRefs in an option QDict. The difference from
bdrv_file_open() is that this function may invoke bdrv_open() instead,
allowing auto-detection of the driver to be used; and second, it
automatically extracts the BlockdevRef from the option QDict.

Signed-off-by: default avatarMax Reitz <mreitz@redhat.com>
Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
parent 2a05cbe4
Loading
Loading
Loading
Loading
+73 −0
Original line number Diff line number Diff line
@@ -1040,6 +1040,79 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
    return 0;
}

/*
 * Opens a disk image whose options are given as BlockdevRef in another block
 * device's options.
 *
 * If force_raw is true, bdrv_file_open() will be used, thereby preventing any
 * image format auto-detection. If it is false and a filename is given,
 * bdrv_open() will be used for auto-detection.
 *
 * If allow_none is true, no image will be opened if filename is false and no
 * BlockdevRef is given. *pbs will remain unchanged and 0 will be returned.
 *
 * bdrev_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.
 *
 * The BlockdevRef will be removed from the options QDict.
 */
int bdrv_open_image(BlockDriverState **pbs, const char *filename,
                    QDict *options, const char *bdref_key, int flags,
                    bool force_raw, bool allow_none, Error **errp)
{
    QDict *image_options;
    int ret;
    char *bdref_key_dot;
    const char *reference;

    bdref_key_dot = g_strdup_printf("%s.", bdref_key);
    qdict_extract_subqdict(options, &image_options, bdref_key_dot);
    g_free(bdref_key_dot);

    reference = qdict_get_try_str(options, bdref_key);
    if (!filename && !reference && !qdict_size(image_options)) {
        if (allow_none) {
            ret = 0;
        } else {
            error_setg(errp, "A block device must be specified for \"%s\"",
                       bdref_key);
            ret = -EINVAL;
        }
        goto done;
    }

    if (filename && !force_raw) {
        /* If a filename is given and the block driver should be detected
           automatically (instead of using none), use bdrv_open() in order to do
           that auto-detection. */
        BlockDriverState *bs;

        if (reference) {
            error_setg(errp, "Cannot reference an existing block device while "
                       "giving a filename");
            ret = -EINVAL;
            goto done;
        }

        bs = bdrv_new("");
        ret = bdrv_open(bs, filename, image_options, flags, NULL, errp);
        if (ret < 0) {
            bdrv_unref(bs);
        } else {
            *pbs = bs;
        }
    } else {
        ret = bdrv_file_open(pbs, filename, reference, image_options, flags,
                             errp);
    }

done:
    qdict_del(options, bdref_key);
    return ret;
}

/*
 * Opens a disk image (raw, qcow2, vmdk, ...)
 *
+3 −0
Original line number Diff line number Diff line
@@ -186,6 +186,9 @@ int bdrv_parse_discard_flags(const char *mode, int *flags);
int bdrv_file_open(BlockDriverState **pbs, const char *filename,
                   const char *reference, QDict *options, int flags,
                   Error **errp);
int bdrv_open_image(BlockDriverState **pbs, const char *filename,
                    QDict *options, const char *bdref_key, int flags,
                    bool force_raw, bool allow_none, Error **errp);
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp);
int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
              int flags, BlockDriver *drv, Error **errp);