Commit dcc98687 authored by Kevin Wolf's avatar Kevin Wolf
Browse files

qcow2: Creating images with external data file



This adds a .bdrv_create option to use an external data file.

Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
parent 0e8c08be
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -2880,6 +2880,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
     */
    BlockBackend *blk = NULL;
    BlockDriverState *bs = NULL;
    BlockDriverState *data_bs = NULL;
    QCowHeader *header;
    size_t cluster_size;
    int version;
@@ -2976,6 +2977,20 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
    }
    refcount_order = ctz32(qcow2_opts->refcount_bits);

    if (qcow2_opts->data_file) {
        if (version < 3) {
            error_setg(errp, "External data files are only supported with "
                       "compatibility level 1.1 and above (use version=v3 or "
                       "greater)");
            ret = -EINVAL;
            goto out;
        }
        data_bs = bdrv_open_blockdev_ref(qcow2_opts->data_file, errp);
        if (bs == NULL) {
            ret = -EIO;
            goto out;
        }
    }

    /* Create BlockBackend to write to the image */
    blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
@@ -3014,6 +3029,10 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
        header->compatible_features |=
            cpu_to_be64(QCOW2_COMPAT_LAZY_REFCOUNTS);
    }
    if (data_bs) {
        header->incompatible_features |=
            cpu_to_be64(QCOW2_INCOMPAT_DATA_FILE);
    }

    ret = blk_pwrite(blk, 0, header, cluster_size, 0);
    g_free(header);
@@ -3044,6 +3063,9 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
    options = qdict_new();
    qdict_put_str(options, "driver", "qcow2");
    qdict_put_str(options, "file", bs->node_name);
    if (data_bs) {
        qdict_put_str(options, "data-file", data_bs->node_name);
    }
    blk = blk_new_open(NULL, NULL, options,
                       BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_NO_FLUSH,
                       &local_err);
@@ -3116,6 +3138,9 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
    options = qdict_new();
    qdict_put_str(options, "driver", "qcow2");
    qdict_put_str(options, "file", bs->node_name);
    if (data_bs) {
        qdict_put_str(options, "data-file", data_bs->node_name);
    }
    blk = blk_new_open(NULL, NULL, options,
                       BDRV_O_RDWR | BDRV_O_NO_BACKING | BDRV_O_NO_IO,
                       &local_err);
@@ -3129,6 +3154,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
out:
    blk_unref(blk);
    bdrv_unref(bs);
    bdrv_unref(data_bs);
    return ret;
}

+1 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@
#define BLOCK_OPT_NOCOW             "nocow"
#define BLOCK_OPT_OBJECT_SIZE       "object_size"
#define BLOCK_OPT_REFCOUNT_BITS     "refcount_bits"
#define BLOCK_OPT_DATA_FILE         "data_file"

#define BLOCK_PROBE_BUF_SIZE        512

+4 −0
Original line number Diff line number Diff line
@@ -4135,6 +4135,9 @@
# Driver specific image creation options for qcow2.
#
# @file             Node to create the image format on
# @data-file        Node to use as an external data file in which all guest
#                   data is stored so that only metadata remains in the qcow2
#                   file (since: 4.0)
# @size             Size of the virtual disk in bytes
# @version          Compatibility level (default: v3)
# @backing-file     File name of the backing file if a backing file
@@ -4150,6 +4153,7 @@
##
{ 'struct': 'BlockdevCreateOptionsQcow2',
  'data': { 'file':             'BlockdevRef',
            '*data-file':       'BlockdevRef',
            'size':             'size',
            '*version':         'BlockdevQcow2Version',
            '*backing-file':    'str',