mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2019-08-19' into staging
Block patches: - preallocation=falloc/full support for LUKS - Various minor fixes # gpg: Signature made Mon 19 Aug 2019 16:36:45 BST # gpg: using RSA key 91BEB60A30DB3E8857D11829F407DB0061D5CF40 # gpg: issuer "mreitz@redhat.com" # gpg: Good signature from "Max Reitz <mreitz@redhat.com>" [full] # Primary key fingerprint: 91BE B60A 30DB 3E88 57D1 1829 F407 DB00 61D5 CF40 * remotes/maxreitz/tags/pull-block-2019-08-19: doc: Preallocation does not require writing zeroes iotests: Fix 141 when run with qed vpc: Do not return RAW from block_status vmdk: Make block_status recurse for flat extents vdi: Make block_status recurse for fixed images iotests: Full mirror to existing non-zero image iotests: Test convert -n to pre-filled image iotests: Convert to preallocated encrypted qcow2 vhdx: Fix .bdrv_has_zero_init() vdi: Fix .bdrv_has_zero_init() qcow2: Fix .bdrv_has_zero_init() block: Use bdrv_has_zero_init_truncate() block: Implement .bdrv_has_zero_init_truncate() block: Add bdrv_has_zero_init_truncate() mirror: Fix bdrv_has_zero_init() use qemu-img: Fix bdrv_has_zero_init() use in convert LUKS: support preallocation Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -5078,6 +5078,27 @@ int bdrv_has_zero_init(BlockDriverState *bs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bdrv_has_zero_init_truncate(BlockDriverState *bs)
|
||||
{
|
||||
if (!bs->drv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bs->backing) {
|
||||
/* Depends on the backing image length, but better safe than sorry */
|
||||
return 0;
|
||||
}
|
||||
if (bs->drv->bdrv_has_zero_init_truncate) {
|
||||
return bs->drv->bdrv_has_zero_init_truncate(bs);
|
||||
}
|
||||
if (bs->file && bs->drv->is_filter) {
|
||||
return bdrv_has_zero_init_truncate(bs->file->bs);
|
||||
}
|
||||
|
||||
/* safe default */
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriverInfo bdi;
|
||||
|
||||
+27
-3
@@ -74,6 +74,7 @@ static ssize_t block_crypto_read_func(QCryptoBlock *block,
|
||||
struct BlockCryptoCreateData {
|
||||
BlockBackend *blk;
|
||||
uint64_t size;
|
||||
PreallocMode prealloc;
|
||||
};
|
||||
|
||||
|
||||
@@ -112,7 +113,7 @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
|
||||
* available to the guest, so we must take account of that
|
||||
* which will be used by the crypto header
|
||||
*/
|
||||
return blk_truncate(data->blk, data->size + headerlen, PREALLOC_MODE_OFF,
|
||||
return blk_truncate(data->blk, data->size + headerlen, data->prealloc,
|
||||
errp);
|
||||
}
|
||||
|
||||
@@ -251,6 +252,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
|
||||
static int block_crypto_co_create_generic(BlockDriverState *bs,
|
||||
int64_t size,
|
||||
QCryptoBlockCreateOptions *opts,
|
||||
PreallocMode prealloc,
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
@@ -266,9 +268,14 @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (prealloc == PREALLOC_MODE_METADATA) {
|
||||
prealloc = PREALLOC_MODE_OFF;
|
||||
}
|
||||
|
||||
data = (struct BlockCryptoCreateData) {
|
||||
.blk = blk,
|
||||
.size = size,
|
||||
.prealloc = prealloc,
|
||||
};
|
||||
|
||||
crypto = qcrypto_block_create(opts, NULL,
|
||||
@@ -500,6 +507,7 @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
|
||||
BlockdevCreateOptionsLUKS *luks_opts;
|
||||
BlockDriverState *bs = NULL;
|
||||
QCryptoBlockCreateOptions create_opts;
|
||||
PreallocMode preallocation = PREALLOC_MODE_OFF;
|
||||
int ret;
|
||||
|
||||
assert(create_options->driver == BLOCKDEV_DRIVER_LUKS);
|
||||
@@ -515,8 +523,12 @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
|
||||
.u.luks = *qapi_BlockdevCreateOptionsLUKS_base(luks_opts),
|
||||
};
|
||||
|
||||
if (luks_opts->has_preallocation) {
|
||||
preallocation = luks_opts->preallocation;
|
||||
}
|
||||
|
||||
ret = block_crypto_co_create_generic(bs, luks_opts->size, &create_opts,
|
||||
errp);
|
||||
preallocation, errp);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -534,12 +546,24 @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
|
||||
QCryptoBlockCreateOptions *create_opts = NULL;
|
||||
BlockDriverState *bs = NULL;
|
||||
QDict *cryptoopts;
|
||||
PreallocMode prealloc;
|
||||
char *buf = NULL;
|
||||
int64_t size;
|
||||
int ret;
|
||||
Error *local_err = NULL;
|
||||
|
||||
/* Parse options */
|
||||
size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
|
||||
|
||||
buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
||||
prealloc = qapi_enum_parse(&PreallocMode_lookup, buf,
|
||||
PREALLOC_MODE_OFF, &local_err);
|
||||
g_free(buf);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cryptoopts = qemu_opts_to_qdict_filtered(opts, NULL,
|
||||
&block_crypto_create_opts_luks,
|
||||
true);
|
||||
@@ -565,7 +589,7 @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
|
||||
}
|
||||
|
||||
/* Create format layer */
|
||||
ret = block_crypto_co_create_generic(bs, size, create_opts, errp);
|
||||
ret = block_crypto_co_create_generic(bs, size, create_opts, prealloc, errp);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -2938,6 +2938,7 @@ BlockDriver bdrv_file = {
|
||||
.bdrv_co_create = raw_co_create,
|
||||
.bdrv_co_create_opts = raw_co_create_opts,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
|
||||
.bdrv_co_block_status = raw_co_block_status,
|
||||
.bdrv_co_invalidate_cache = raw_co_invalidate_cache,
|
||||
.bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
|
||||
|
||||
@@ -635,6 +635,7 @@ BlockDriver bdrv_file = {
|
||||
.bdrv_close = raw_close,
|
||||
.bdrv_co_create_opts = raw_co_create_opts,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
|
||||
|
||||
.bdrv_aio_preadv = raw_aio_preadv,
|
||||
.bdrv_aio_pwritev = raw_aio_pwritev,
|
||||
|
||||
@@ -1567,6 +1567,7 @@ static BlockDriver bdrv_gluster = {
|
||||
.bdrv_co_writev = qemu_gluster_co_writev,
|
||||
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
|
||||
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
|
||||
.bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
|
||||
#ifdef CONFIG_GLUSTERFS_DISCARD
|
||||
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
|
||||
#endif
|
||||
@@ -1598,6 +1599,7 @@ static BlockDriver bdrv_gluster_tcp = {
|
||||
.bdrv_co_writev = qemu_gluster_co_writev,
|
||||
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
|
||||
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
|
||||
.bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
|
||||
#ifdef CONFIG_GLUSTERFS_DISCARD
|
||||
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
|
||||
#endif
|
||||
@@ -1629,6 +1631,7 @@ static BlockDriver bdrv_gluster_unix = {
|
||||
.bdrv_co_writev = qemu_gluster_co_writev,
|
||||
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
|
||||
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
|
||||
.bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
|
||||
#ifdef CONFIG_GLUSTERFS_DISCARD
|
||||
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
|
||||
#endif
|
||||
@@ -1666,6 +1669,7 @@ static BlockDriver bdrv_gluster_rdma = {
|
||||
.bdrv_co_writev = qemu_gluster_co_writev,
|
||||
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
|
||||
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
|
||||
.bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
|
||||
#ifdef CONFIG_GLUSTERFS_DISCARD
|
||||
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
|
||||
#endif
|
||||
|
||||
+8
-3
@@ -51,6 +51,8 @@ typedef struct MirrorBlockJob {
|
||||
Error *replace_blocker;
|
||||
bool is_none_mode;
|
||||
BlockMirrorBackingMode backing_mode;
|
||||
/* Whether the target image requires explicit zero-initialization */
|
||||
bool zero_target;
|
||||
MirrorCopyMode copy_mode;
|
||||
BlockdevOnError on_source_error, on_target_error;
|
||||
bool synced;
|
||||
@@ -767,7 +769,7 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
|
||||
int ret;
|
||||
int64_t count;
|
||||
|
||||
if (base == NULL && !bdrv_has_zero_init(target_bs)) {
|
||||
if (s->zero_target) {
|
||||
if (!bdrv_can_write_zeroes_with_unmap(target_bs)) {
|
||||
bdrv_set_dirty_bitmap(s->dirty_bitmap, 0, s->bdev_length);
|
||||
return 0;
|
||||
@@ -1515,6 +1517,7 @@ static BlockJob *mirror_start_job(
|
||||
const char *replaces, int64_t speed,
|
||||
uint32_t granularity, int64_t buf_size,
|
||||
BlockMirrorBackingMode backing_mode,
|
||||
bool zero_target,
|
||||
BlockdevOnError on_source_error,
|
||||
BlockdevOnError on_target_error,
|
||||
bool unmap,
|
||||
@@ -1643,6 +1646,7 @@ static BlockJob *mirror_start_job(
|
||||
s->on_target_error = on_target_error;
|
||||
s->is_none_mode = is_none_mode;
|
||||
s->backing_mode = backing_mode;
|
||||
s->zero_target = zero_target;
|
||||
s->copy_mode = copy_mode;
|
||||
s->base = base;
|
||||
s->granularity = granularity;
|
||||
@@ -1747,6 +1751,7 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
|
||||
int creation_flags, int64_t speed,
|
||||
uint32_t granularity, int64_t buf_size,
|
||||
MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
|
||||
bool zero_target,
|
||||
BlockdevOnError on_source_error,
|
||||
BlockdevOnError on_target_error,
|
||||
bool unmap, const char *filter_node_name,
|
||||
@@ -1764,7 +1769,7 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
|
||||
is_none_mode = mode == MIRROR_SYNC_MODE_NONE;
|
||||
base = mode == MIRROR_SYNC_MODE_TOP ? backing_bs(bs) : NULL;
|
||||
mirror_start_job(job_id, bs, creation_flags, target, replaces,
|
||||
speed, granularity, buf_size, backing_mode,
|
||||
speed, granularity, buf_size, backing_mode, zero_target,
|
||||
on_source_error, on_target_error, unmap, NULL, NULL,
|
||||
&mirror_job_driver, is_none_mode, base, false,
|
||||
filter_node_name, true, copy_mode, errp);
|
||||
@@ -1791,7 +1796,7 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
|
||||
|
||||
ret = mirror_start_job(
|
||||
job_id, bs, creation_flags, base, NULL, speed, 0, 0,
|
||||
MIRROR_LEAVE_BACKING_CHAIN,
|
||||
MIRROR_LEAVE_BACKING_CHAIN, false,
|
||||
on_error, on_error, true, cb, opaque,
|
||||
&commit_active_job_driver, false, base, auto_complete,
|
||||
filter_node_name, false, MIRROR_COPY_MODE_BACKGROUND,
|
||||
|
||||
@@ -863,6 +863,7 @@ static BlockDriver bdrv_nfs = {
|
||||
.create_opts = &nfs_create_opts,
|
||||
|
||||
.bdrv_has_zero_init = nfs_has_zero_init,
|
||||
.bdrv_has_zero_init_truncate = nfs_has_zero_init,
|
||||
.bdrv_get_allocated_file_size = nfs_get_allocated_file_size,
|
||||
.bdrv_co_truncate = nfs_file_co_truncate,
|
||||
|
||||
|
||||
+1
-1
@@ -835,7 +835,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail_options;
|
||||
}
|
||||
|
||||
if (!bdrv_has_zero_init(bs->file->bs)) {
|
||||
if (!bdrv_has_zero_init_truncate(bs->file->bs)) {
|
||||
s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
|
||||
}
|
||||
|
||||
|
||||
+29
-1
@@ -4632,6 +4632,33 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,
|
||||
return spec_info;
|
||||
}
|
||||
|
||||
static int qcow2_has_zero_init(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
bool preallocated;
|
||||
|
||||
if (qemu_in_coroutine()) {
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
}
|
||||
/*
|
||||
* Check preallocation status: Preallocated images have all L2
|
||||
* tables allocated, nonpreallocated images have none. It is
|
||||
* therefore enough to check the first one.
|
||||
*/
|
||||
preallocated = s->l1_size > 0 && s->l1_table[0] != 0;
|
||||
if (qemu_in_coroutine()) {
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
}
|
||||
|
||||
if (!preallocated) {
|
||||
return 1;
|
||||
} else if (bs->encrypted) {
|
||||
return 0;
|
||||
} else {
|
||||
return bdrv_has_zero_init(s->data_file->bs);
|
||||
}
|
||||
}
|
||||
|
||||
static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
|
||||
int64_t pos)
|
||||
{
|
||||
@@ -5187,7 +5214,8 @@ BlockDriver bdrv_qcow2 = {
|
||||
.bdrv_child_perm = bdrv_format_default_perms,
|
||||
.bdrv_co_create_opts = qcow2_co_create_opts,
|
||||
.bdrv_co_create = qcow2_co_create,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.bdrv_has_zero_init = qcow2_has_zero_init,
|
||||
.bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
|
||||
.bdrv_co_block_status = qcow2_co_block_status,
|
||||
|
||||
.bdrv_co_preadv = qcow2_co_preadv,
|
||||
|
||||
@@ -1669,6 +1669,7 @@ static BlockDriver bdrv_qed = {
|
||||
.bdrv_co_create = bdrv_qed_co_create,
|
||||
.bdrv_co_create_opts = bdrv_qed_co_create_opts,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
|
||||
.bdrv_co_block_status = bdrv_qed_co_block_status,
|
||||
.bdrv_co_readv = bdrv_qed_co_readv,
|
||||
.bdrv_co_writev = bdrv_qed_co_writev,
|
||||
|
||||
@@ -413,6 +413,11 @@ static int raw_has_zero_init(BlockDriverState *bs)
|
||||
return bdrv_has_zero_init(bs->file->bs);
|
||||
}
|
||||
|
||||
static int raw_has_zero_init_truncate(BlockDriverState *bs)
|
||||
{
|
||||
return bdrv_has_zero_init_truncate(bs->file->bs);
|
||||
}
|
||||
|
||||
static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
@@ -572,6 +577,7 @@ BlockDriver bdrv_raw = {
|
||||
.bdrv_co_ioctl = &raw_co_ioctl,
|
||||
.create_opts = &raw_create_opts,
|
||||
.bdrv_has_zero_init = &raw_has_zero_init,
|
||||
.bdrv_has_zero_init_truncate = &raw_has_zero_init_truncate,
|
||||
.strong_runtime_opts = raw_strong_runtime_opts,
|
||||
.mutable_opts = mutable_opts,
|
||||
};
|
||||
|
||||
@@ -1288,6 +1288,7 @@ static BlockDriver bdrv_rbd = {
|
||||
.bdrv_co_create = qemu_rbd_co_create,
|
||||
.bdrv_co_create_opts = qemu_rbd_co_create_opts,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
|
||||
.bdrv_get_info = qemu_rbd_getinfo,
|
||||
.create_opts = &qemu_rbd_create_opts,
|
||||
.bdrv_getlength = qemu_rbd_getlength,
|
||||
|
||||
@@ -3229,6 +3229,7 @@ static BlockDriver bdrv_sheepdog = {
|
||||
.bdrv_co_create = sd_co_create,
|
||||
.bdrv_co_create_opts = sd_co_create_opts,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
|
||||
.bdrv_getlength = sd_getlength,
|
||||
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
|
||||
.bdrv_co_truncate = sd_co_truncate,
|
||||
|
||||
@@ -1390,6 +1390,7 @@ static BlockDriver bdrv_ssh = {
|
||||
.bdrv_co_create_opts = ssh_co_create_opts,
|
||||
.bdrv_close = ssh_close,
|
||||
.bdrv_has_zero_init = ssh_has_zero_init,
|
||||
.bdrv_has_zero_init_truncate = ssh_has_zero_init,
|
||||
.bdrv_co_readv = ssh_co_readv,
|
||||
.bdrv_co_writev = ssh_co_writev,
|
||||
.bdrv_getlength = ssh_getlength,
|
||||
|
||||
+14
-2
@@ -542,7 +542,8 @@ static int coroutine_fn vdi_co_block_status(BlockDriverState *bs,
|
||||
*map = s->header.offset_data + (uint64_t)bmap_entry * s->block_size +
|
||||
index_in_block;
|
||||
*file = bs->file->bs;
|
||||
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
|
||||
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID |
|
||||
(s->header.image_type == VDI_TYPE_STATIC ? BDRV_BLOCK_RECURSE : 0);
|
||||
}
|
||||
|
||||
static int coroutine_fn
|
||||
@@ -988,6 +989,17 @@ static void vdi_close(BlockDriverState *bs)
|
||||
error_free(s->migration_blocker);
|
||||
}
|
||||
|
||||
static int vdi_has_zero_init(BlockDriverState *bs)
|
||||
{
|
||||
BDRVVdiState *s = bs->opaque;
|
||||
|
||||
if (s->header.image_type == VDI_TYPE_STATIC) {
|
||||
return bdrv_has_zero_init(bs->file->bs);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static QemuOptsList vdi_create_opts = {
|
||||
.name = "vdi-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(vdi_create_opts.head),
|
||||
@@ -1028,7 +1040,7 @@ static BlockDriver bdrv_vdi = {
|
||||
.bdrv_child_perm = bdrv_format_default_perms,
|
||||
.bdrv_co_create = vdi_co_create,
|
||||
.bdrv_co_create_opts = vdi_co_create_opts,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.bdrv_has_zero_init = vdi_has_zero_init,
|
||||
.bdrv_co_block_status = vdi_co_block_status,
|
||||
.bdrv_make_empty = vdi_make_empty,
|
||||
|
||||
|
||||
+26
-2
@@ -1282,7 +1282,7 @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
/* Queue another write of zero buffers if the underlying file
|
||||
* does not zero-fill on file extension */
|
||||
|
||||
if (bdrv_has_zero_init(bs->file->bs) == 0) {
|
||||
if (bdrv_has_zero_init_truncate(bs->file->bs) == 0) {
|
||||
use_zero_buffers = true;
|
||||
|
||||
/* zero fill the front, if any */
|
||||
@@ -2075,6 +2075,30 @@ static int coroutine_fn vhdx_co_check(BlockDriverState *bs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vhdx_has_zero_init(BlockDriverState *bs)
|
||||
{
|
||||
BDRVVHDXState *s = bs->opaque;
|
||||
int state;
|
||||
|
||||
/*
|
||||
* Check the subformat: Fixed images have all BAT entries present,
|
||||
* dynamic images have none (right after creation). It is
|
||||
* therefore enough to check the first BAT entry.
|
||||
*/
|
||||
if (!s->bat_entries) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
state = s->bat[0] & VHDX_BAT_STATE_BIT_MASK;
|
||||
if (state == PAYLOAD_BLOCK_FULLY_PRESENT) {
|
||||
/* Fixed subformat */
|
||||
return bdrv_has_zero_init(bs->file->bs);
|
||||
}
|
||||
|
||||
/* Dynamic subformat */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static QemuOptsList vhdx_create_opts = {
|
||||
.name = "vhdx-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(vhdx_create_opts.head),
|
||||
@@ -2128,7 +2152,7 @@ static BlockDriver bdrv_vhdx = {
|
||||
.bdrv_co_create_opts = vhdx_co_create_opts,
|
||||
.bdrv_get_info = vhdx_get_info,
|
||||
.bdrv_co_check = vhdx_co_check,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.bdrv_has_zero_init = vhdx_has_zero_init,
|
||||
|
||||
.create_opts = &vhdx_create_opts,
|
||||
};
|
||||
|
||||
@@ -1692,6 +1692,9 @@ static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
|
||||
if (!extent->compressed) {
|
||||
ret |= BDRV_BLOCK_OFFSET_VALID;
|
||||
*map = cluster_offset + index_in_cluster;
|
||||
if (extent->flat) {
|
||||
ret |= BDRV_BLOCK_RECURSE;
|
||||
}
|
||||
}
|
||||
*file = extent->file->bs;
|
||||
break;
|
||||
|
||||
+1
-1
@@ -737,7 +737,7 @@ static int coroutine_fn vpc_co_block_status(BlockDriverState *bs,
|
||||
*pnum = bytes;
|
||||
*map = offset;
|
||||
*file = bs->file->bs;
|
||||
return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
|
||||
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | BDRV_BLOCK_RECURSE;
|
||||
}
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
|
||||
+13
-3
@@ -3782,6 +3782,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
|
||||
bool has_replaces, const char *replaces,
|
||||
enum MirrorSyncMode sync,
|
||||
BlockMirrorBackingMode backing_mode,
|
||||
bool zero_target,
|
||||
bool has_speed, int64_t speed,
|
||||
bool has_granularity, uint32_t granularity,
|
||||
bool has_buf_size, int64_t buf_size,
|
||||
@@ -3890,7 +3891,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
|
||||
*/
|
||||
mirror_start(job_id, bs, target,
|
||||
has_replaces ? replaces : NULL, job_flags,
|
||||
speed, granularity, buf_size, sync, backing_mode,
|
||||
speed, granularity, buf_size, sync, backing_mode, zero_target,
|
||||
on_source_error, on_target_error, unmap, filter_node_name,
|
||||
copy_mode, errp);
|
||||
}
|
||||
@@ -3906,6 +3907,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
||||
int flags;
|
||||
int64_t size;
|
||||
const char *format = arg->format;
|
||||
bool zero_target;
|
||||
int ret;
|
||||
|
||||
bs = qmp_get_root_bs(arg->device, errp);
|
||||
@@ -4007,6 +4009,10 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
||||
goto out;
|
||||
}
|
||||
|
||||
zero_target = (arg->sync == MIRROR_SYNC_MODE_FULL &&
|
||||
(arg->mode == NEW_IMAGE_MODE_EXISTING ||
|
||||
!bdrv_has_zero_init(target_bs)));
|
||||
|
||||
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
||||
if (ret < 0) {
|
||||
bdrv_unref(target_bs);
|
||||
@@ -4015,7 +4021,8 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
||||
|
||||
blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs,
|
||||
arg->has_replaces, arg->replaces, arg->sync,
|
||||
backing_mode, arg->has_speed, arg->speed,
|
||||
backing_mode, zero_target,
|
||||
arg->has_speed, arg->speed,
|
||||
arg->has_granularity, arg->granularity,
|
||||
arg->has_buf_size, arg->buf_size,
|
||||
arg->has_on_source_error, arg->on_source_error,
|
||||
@@ -4055,6 +4062,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
|
||||
AioContext *aio_context;
|
||||
BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN;
|
||||
Error *local_err = NULL;
|
||||
bool zero_target;
|
||||
int ret;
|
||||
|
||||
bs = qmp_get_root_bs(device, errp);
|
||||
@@ -4067,6 +4075,8 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
|
||||
return;
|
||||
}
|
||||
|
||||
zero_target = (sync == MIRROR_SYNC_MODE_FULL);
|
||||
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
@@ -4077,7 +4087,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
|
||||
|
||||
blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs,
|
||||
has_replaces, replaces, sync, backing_mode,
|
||||
has_speed, speed,
|
||||
zero_target, has_speed, speed,
|
||||
has_granularity, granularity,
|
||||
has_buf_size, buf_size,
|
||||
has_on_source_error, on_source_error,
|
||||
|
||||
@@ -31,8 +31,8 @@ Supported options:
|
||||
@item preallocation
|
||||
Preallocation mode (allowed values: @code{off}, @code{falloc}, @code{full}).
|
||||
@code{falloc} mode preallocates space for image by calling posix_fallocate().
|
||||
@code{full} mode preallocates space for image by writing zeros to underlying
|
||||
storage.
|
||||
@code{full} mode preallocates space for image by writing data to underlying
|
||||
storage. This data may or may not be zero, depending on the storage location.
|
||||
@end table
|
||||
|
||||
@item qcow2
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user