mirror of https://github.com/xemu-project/xemu.git
qcow2: Creating images with external data file
This adds a .bdrv_create option to use an external data file. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
0e8c08be27
commit
dcc98687f8
|
@ -2880,6 +2880,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
|
||||||
*/
|
*/
|
||||||
BlockBackend *blk = NULL;
|
BlockBackend *blk = NULL;
|
||||||
BlockDriverState *bs = NULL;
|
BlockDriverState *bs = NULL;
|
||||||
|
BlockDriverState *data_bs = NULL;
|
||||||
QCowHeader *header;
|
QCowHeader *header;
|
||||||
size_t cluster_size;
|
size_t cluster_size;
|
||||||
int version;
|
int version;
|
||||||
|
@ -2976,6 +2977,20 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
|
||||||
}
|
}
|
||||||
refcount_order = ctz32(qcow2_opts->refcount_bits);
|
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 */
|
/* Create BlockBackend to write to the image */
|
||||||
blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
|
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 |=
|
header->compatible_features |=
|
||||||
cpu_to_be64(QCOW2_COMPAT_LAZY_REFCOUNTS);
|
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);
|
ret = blk_pwrite(blk, 0, header, cluster_size, 0);
|
||||||
g_free(header);
|
g_free(header);
|
||||||
|
@ -3044,6 +3063,9 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
|
||||||
options = qdict_new();
|
options = qdict_new();
|
||||||
qdict_put_str(options, "driver", "qcow2");
|
qdict_put_str(options, "driver", "qcow2");
|
||||||
qdict_put_str(options, "file", bs->node_name);
|
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,
|
blk = blk_new_open(NULL, NULL, options,
|
||||||
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_NO_FLUSH,
|
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_NO_FLUSH,
|
||||||
&local_err);
|
&local_err);
|
||||||
|
@ -3116,6 +3138,9 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
|
||||||
options = qdict_new();
|
options = qdict_new();
|
||||||
qdict_put_str(options, "driver", "qcow2");
|
qdict_put_str(options, "driver", "qcow2");
|
||||||
qdict_put_str(options, "file", bs->node_name);
|
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,
|
blk = blk_new_open(NULL, NULL, options,
|
||||||
BDRV_O_RDWR | BDRV_O_NO_BACKING | BDRV_O_NO_IO,
|
BDRV_O_RDWR | BDRV_O_NO_BACKING | BDRV_O_NO_IO,
|
||||||
&local_err);
|
&local_err);
|
||||||
|
@ -3129,6 +3154,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
|
||||||
out:
|
out:
|
||||||
blk_unref(blk);
|
blk_unref(blk);
|
||||||
bdrv_unref(bs);
|
bdrv_unref(bs);
|
||||||
|
bdrv_unref(data_bs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#define BLOCK_OPT_NOCOW "nocow"
|
#define BLOCK_OPT_NOCOW "nocow"
|
||||||
#define BLOCK_OPT_OBJECT_SIZE "object_size"
|
#define BLOCK_OPT_OBJECT_SIZE "object_size"
|
||||||
#define BLOCK_OPT_REFCOUNT_BITS "refcount_bits"
|
#define BLOCK_OPT_REFCOUNT_BITS "refcount_bits"
|
||||||
|
#define BLOCK_OPT_DATA_FILE "data_file"
|
||||||
|
|
||||||
#define BLOCK_PROBE_BUF_SIZE 512
|
#define BLOCK_PROBE_BUF_SIZE 512
|
||||||
|
|
||||||
|
|
|
@ -4135,6 +4135,9 @@
|
||||||
# Driver specific image creation options for qcow2.
|
# Driver specific image creation options for qcow2.
|
||||||
#
|
#
|
||||||
# @file Node to create the image format on
|
# @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
|
# @size Size of the virtual disk in bytes
|
||||||
# @version Compatibility level (default: v3)
|
# @version Compatibility level (default: v3)
|
||||||
# @backing-file File name of the backing file if a backing file
|
# @backing-file File name of the backing file if a backing file
|
||||||
|
@ -4150,6 +4153,7 @@
|
||||||
##
|
##
|
||||||
{ 'struct': 'BlockdevCreateOptionsQcow2',
|
{ 'struct': 'BlockdevCreateOptionsQcow2',
|
||||||
'data': { 'file': 'BlockdevRef',
|
'data': { 'file': 'BlockdevRef',
|
||||||
|
'*data-file': 'BlockdevRef',
|
||||||
'size': 'size',
|
'size': 'size',
|
||||||
'*version': 'BlockdevQcow2Version',
|
'*version': 'BlockdevQcow2Version',
|
||||||
'*backing-file': 'str',
|
'*backing-file': 'str',
|
||||||
|
|
Loading…
Reference in New Issue