Block patches:
- preallocation=falloc/full support for LUKS - Various minor fixes -----BEGIN PGP SIGNATURE----- iQFGBAABCAAwFiEEkb62CjDbPohX0Rgp9AfbAGHVz0AFAl1awg0SHG1yZWl0ekBy ZWRoYXQuY29tAAoJEPQH2wBh1c9Au70H/jTfnZ5HGCnuMG9Qfz592b3OJzLxAUxy zRYZeYeQv2iBAJ8D3guJb4TIsvs9FgiZq6W+a+uXPZUfV2cPjHEcl2votnKuyWsx udzR5wyGEbZjeMIv5lhzWMf3oqWin5MVDFQ2xUSjt9rfNDiHH4pMHuLO6AGkVaRS MEOEs1/GEZ1mXPckG00YBJXMgmsk+7xWZ5cMjUI8Hsa1/nC2GLckh2j5y2rt3ppc dt2he6/etnK0d8Yt8yZXyNl8xSW95f0Z+a1RefgGX5n3kCV6K/9hkRIhCTdunzDd hULNummeZghjbn0HLyFjEnJlzSglWYprUsQj1HaXB4/LwMUwj3yNxHk= =dDid -----END PGP SIGNATURE----- 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:
commit
156d320349
21
block.c
21
block.c
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
16
block/vdi.c
16
block/vdi.c
@ -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,
|
||||
|
||||
|
28
block/vhdx.c
28
block/vhdx.c
@ -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;
|
||||
|
@ -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);
|
||||
|
16
blockdev.c
16
blockdev.c
@ -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
|
||||
|
@ -443,6 +443,7 @@ int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
|
||||
int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
|
||||
int bdrv_has_zero_init_1(BlockDriverState *bs);
|
||||
int bdrv_has_zero_init(BlockDriverState *bs);
|
||||
int bdrv_has_zero_init_truncate(BlockDriverState *bs);
|
||||
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
|
||||
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
|
||||
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
|
||||
|
@ -419,9 +419,16 @@ struct BlockDriver {
|
||||
/*
|
||||
* Returns 1 if newly created images are guaranteed to contain only
|
||||
* zeros, 0 otherwise.
|
||||
* Must return 0 if .bdrv_has_zero_init_truncate() returns 0.
|
||||
*/
|
||||
int (*bdrv_has_zero_init)(BlockDriverState *bs);
|
||||
|
||||
/*
|
||||
* Returns 1 if new areas added by growing the image with
|
||||
* PREALLOC_MODE_OFF contain only zeros, 0 otherwise.
|
||||
*/
|
||||
int (*bdrv_has_zero_init_truncate)(BlockDriverState *bs);
|
||||
|
||||
/* Remove fd handlers, timers, and other event loop callbacks so the event
|
||||
* loop is no longer in use. Called with no in-flight requests and in
|
||||
* depth-first traversal order with parents before child nodes.
|
||||
@ -1115,6 +1122,7 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
|
||||
* @buf_size: The amount of data that can be in flight at one time.
|
||||
* @mode: Whether to collapse all images in the chain to the target.
|
||||
* @backing_mode: How to establish the target's backing chain after completion.
|
||||
* @zero_target: Whether the target should be explicitly zero-initialized
|
||||
* @on_source_error: The action to take upon error reading from the source.
|
||||
* @on_target_error: The action to take upon error writing to the target.
|
||||
* @unmap: Whether to unmap target where source sectors only contain zeroes.
|
||||
@ -1134,6 +1142,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,
|
||||
|
@ -4212,13 +4212,17 @@
|
||||
#
|
||||
# @file Node to create the image format on
|
||||
# @size Size of the virtual disk in bytes
|
||||
# @preallocation Preallocation mode for the new image
|
||||
# (since: 4.2)
|
||||
# (default: off; allowed values: off, metadata, falloc, full)
|
||||
#
|
||||
# Since: 2.12
|
||||
##
|
||||
{ 'struct': 'BlockdevCreateOptionsLUKS',
|
||||
'base': 'QCryptoBlockCreateOptionsLUKS',
|
||||
'data': { 'file': 'BlockdevRef',
|
||||
'size': 'size' } }
|
||||
'size': 'size',
|
||||
'*preallocation': 'PreallocMode' } }
|
||||
|
||||
##
|
||||
# @BlockdevCreateOptionsNfs:
|
||||
@ -5174,10 +5178,11 @@
|
||||
# @off: no preallocation
|
||||
# @metadata: preallocate only for metadata
|
||||
# @falloc: like @full preallocation but allocate disk space by
|
||||
# posix_fallocate() rather than writing zeros.
|
||||
# @full: preallocate all data by writing zeros to device to ensure disk
|
||||
# space is really available. @full preallocation also sets up
|
||||
# metadata correctly.
|
||||
# posix_fallocate() rather than writing data.
|
||||
# @full: preallocate all data by writing it to the device to ensure
|
||||
# disk space is really available. This data may or may not be
|
||||
# zero, depending on the image format and storage.
|
||||
# @full preallocation also sets up metadata correctly.
|
||||
#
|
||||
# Since: 2.2
|
||||
##
|
||||
|
11
qemu-img.c
11
qemu-img.c
@ -1578,6 +1578,7 @@ typedef struct ImgConvertState {
|
||||
bool has_zero_init;
|
||||
bool compressed;
|
||||
bool unallocated_blocks_are_zero;
|
||||
bool target_is_new;
|
||||
bool target_has_backing;
|
||||
int64_t target_backing_sectors; /* negative if unknown */
|
||||
bool wr_in_order;
|
||||
@ -1975,9 +1976,11 @@ static int convert_do_copy(ImgConvertState *s)
|
||||
int64_t sector_num = 0;
|
||||
|
||||
/* Check whether we have zero initialisation or can get it efficiently */
|
||||
s->has_zero_init = s->min_sparse && !s->target_has_backing
|
||||
? bdrv_has_zero_init(blk_bs(s->target))
|
||||
: false;
|
||||
if (s->target_is_new && s->min_sparse && !s->target_has_backing) {
|
||||
s->has_zero_init = bdrv_has_zero_init(blk_bs(s->target));
|
||||
} else {
|
||||
s->has_zero_init = false;
|
||||
}
|
||||
|
||||
if (!s->has_zero_init && !s->target_has_backing &&
|
||||
bdrv_can_write_zeroes_with_unmap(blk_bs(s->target)))
|
||||
@ -2428,6 +2431,8 @@ static int img_convert(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
s.target_is_new = !skip_create;
|
||||
|
||||
flags = s.min_sparse ? (BDRV_O_RDWR | BDRV_O_UNMAP) : BDRV_O_RDWR;
|
||||
ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
|
||||
if (ret < 0) {
|
||||
|
@ -666,8 +666,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
|
||||
|
@ -741,8 +741,15 @@ class TestUnbackedSource(iotests.QMPTestCase):
|
||||
def setUp(self):
|
||||
qemu_img('create', '-f', iotests.imgfmt, test_img,
|
||||
str(TestUnbackedSource.image_len))
|
||||
self.vm = iotests.VM().add_drive(test_img)
|
||||
self.vm = iotests.VM()
|
||||
self.vm.launch()
|
||||
result = self.vm.qmp('blockdev-add', node_name='drive0',
|
||||
driver=iotests.imgfmt,
|
||||
file={
|
||||
'driver': 'file',
|
||||
'filename': test_img,
|
||||
})
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
def tearDown(self):
|
||||
self.vm.shutdown()
|
||||
@ -751,7 +758,7 @@ class TestUnbackedSource(iotests.QMPTestCase):
|
||||
|
||||
def test_absolute_paths_full(self):
|
||||
self.assert_no_active_block_jobs()
|
||||
result = self.vm.qmp('drive-mirror', device='drive0',
|
||||
result = self.vm.qmp('drive-mirror', job_id='drive0', device='drive0',
|
||||
sync='full', target=target_img,
|
||||
mode='absolute-paths')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
@ -760,7 +767,7 @@ class TestUnbackedSource(iotests.QMPTestCase):
|
||||
|
||||
def test_absolute_paths_top(self):
|
||||
self.assert_no_active_block_jobs()
|
||||
result = self.vm.qmp('drive-mirror', device='drive0',
|
||||
result = self.vm.qmp('drive-mirror', job_id='drive0', device='drive0',
|
||||
sync='top', target=target_img,
|
||||
mode='absolute-paths')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
@ -769,13 +776,60 @@ class TestUnbackedSource(iotests.QMPTestCase):
|
||||
|
||||
def test_absolute_paths_none(self):
|
||||
self.assert_no_active_block_jobs()
|
||||
result = self.vm.qmp('drive-mirror', device='drive0',
|
||||
result = self.vm.qmp('drive-mirror', job_id='drive0', device='drive0',
|
||||
sync='none', target=target_img,
|
||||
mode='absolute-paths')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
self.complete_and_wait()
|
||||
self.assert_no_active_block_jobs()
|
||||
|
||||
def test_existing_full(self):
|
||||
qemu_img('create', '-f', iotests.imgfmt, target_img,
|
||||
str(self.image_len))
|
||||
qemu_io('-c', 'write -P 42 0 64k', target_img)
|
||||
|
||||
self.assert_no_active_block_jobs()
|
||||
result = self.vm.qmp('drive-mirror', job_id='drive0', device='drive0',
|
||||
sync='full', target=target_img, mode='existing')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
self.complete_and_wait()
|
||||
self.assert_no_active_block_jobs()
|
||||
|
||||
result = self.vm.qmp('blockdev-del', node_name='drive0')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
self.assertTrue(iotests.compare_images(test_img, target_img),
|
||||
'target image does not match source after mirroring')
|
||||
|
||||
def test_blockdev_full(self):
|
||||
qemu_img('create', '-f', iotests.imgfmt, target_img,
|
||||
str(self.image_len))
|
||||
qemu_io('-c', 'write -P 42 0 64k', target_img)
|
||||
|
||||
result = self.vm.qmp('blockdev-add', node_name='target',
|
||||
driver=iotests.imgfmt,
|
||||
file={
|
||||
'driver': 'file',
|
||||
'filename': target_img,
|
||||
})
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
self.assert_no_active_block_jobs()
|
||||
result = self.vm.qmp('blockdev-mirror', job_id='drive0', device='drive0',
|
||||
sync='full', target='target')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
self.complete_and_wait()
|
||||
self.assert_no_active_block_jobs()
|
||||
|
||||
result = self.vm.qmp('blockdev-del', node_name='drive0')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
result = self.vm.qmp('blockdev-del', node_name='target')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
self.assertTrue(iotests.compare_images(test_img, target_img),
|
||||
'target image does not match source after mirroring')
|
||||
|
||||
class TestGranularity(iotests.QMPTestCase):
|
||||
image_len = 10 * 1024 * 1024 # MB
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
........................................................................................
|
||||
..........................................................................................
|
||||
----------------------------------------------------------------------
|
||||
Ran 88 tests
|
||||
Ran 90 tests
|
||||
|
||||
OK
|
||||
|
@ -257,6 +257,23 @@ for min_sparse in 4k 8k; do
|
||||
$QEMU_IMG map --output=json "$TEST_IMG".orig | _filter_qemu_img_map
|
||||
done
|
||||
|
||||
|
||||
echo
|
||||
echo '=== -n to a non-zero image ==='
|
||||
echo
|
||||
|
||||
# Keep source zero
|
||||
_make_test_img 64M
|
||||
|
||||
# Output is not zero, but has bdrv_has_zero_init() == 1
|
||||
TEST_IMG="$TEST_IMG".orig _make_test_img 64M
|
||||
$QEMU_IO -c "write -P 42 0 64k" "$TEST_IMG".orig | _filter_qemu_io
|
||||
|
||||
# Convert with -n, which should not assume that the target is zeroed
|
||||
$QEMU_IMG convert -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG".orig
|
||||
|
||||
$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG".orig
|
||||
|
||||
# success, all done
|
||||
echo '*** done'
|
||||
rm -f $seq.full
|
||||
|
@ -220,4 +220,12 @@ convert -c -S 8k
|
||||
{ "start": 9216, "length": 8192, "depth": 0, "zero": true, "data": false},
|
||||
{ "start": 17408, "length": 1024, "depth": 0, "zero": false, "data": true},
|
||||
{ "start": 18432, "length": 67090432, "depth": 0, "zero": true, "data": false}]
|
||||
|
||||
=== -n to a non-zero image ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864
|
||||
wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Images are identical.
|
||||
*** done
|
||||
|
@ -58,16 +58,21 @@ test_blockjob()
|
||||
}}}" \
|
||||
'return'
|
||||
|
||||
# If "$2" is an event, we may or may not see it before the
|
||||
# {"return": {}}. Therefore, filter the {"return": {}} out both
|
||||
# here and in the next command. (Naturally, if we do not see it
|
||||
# here, we will see it before the next command can be executed,
|
||||
# so it will appear in the next _send_qemu_cmd's output.)
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"$1" \
|
||||
"$2" \
|
||||
| _filter_img_create
|
||||
| _filter_img_create | _filter_qmp_empty_return
|
||||
|
||||
# We want this to return an error because the block job is still running
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{'execute': 'blockdev-del',
|
||||
'arguments': {'node-name': 'drv0'}}" \
|
||||
'error' | _filter_generated_node_ids
|
||||
'error' | _filter_generated_node_ids | _filter_qmp_empty_return
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{'execute': 'block-job-cancel',
|
||||
|
@ -10,7 +10,6 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.
|
||||
Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
|
||||
@ -27,7 +26,6 @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
|
||||
@ -42,7 +40,6 @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
|
||||
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
|
||||
@ -61,7 +58,6 @@ wrote 1048576/1048576 bytes at offset 0
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
|
||||
@ -77,7 +73,6 @@ wrote 1048576/1048576 bytes at offset 0
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
|
||||
|
@ -48,7 +48,7 @@ SECRETALT="secret,id=sec0,data=platypus"
|
||||
|
||||
_make_test_img --object $SECRET -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10" $size
|
||||
|
||||
IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0"
|
||||
IMGSPEC="driver=$IMGFMT,encrypt.key-secret=sec0,file.filename=$TEST_IMG"
|
||||
|
||||
QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
|
||||
|
||||
@ -68,6 +68,24 @@ echo
|
||||
echo "== verify open failure with wrong password =="
|
||||
$QEMU_IO --object $SECRETALT -c "read -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
|
||||
|
||||
_cleanup_test_img
|
||||
|
||||
echo
|
||||
echo "== verify that has_zero_init returns false when preallocating =="
|
||||
|
||||
# Empty source file
|
||||
if [ -n "$TEST_IMG_FILE" ]; then
|
||||
TEST_IMG_FILE="${TEST_IMG_FILE}.orig" _make_test_img $size
|
||||
else
|
||||
TEST_IMG="${TEST_IMG}.orig" _make_test_img $size
|
||||
fi
|
||||
|
||||
$QEMU_IMG convert -O "$IMGFMT" --object $SECRET \
|
||||
-o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10,preallocation=metadata" \
|
||||
"${TEST_IMG}.orig" "$TEST_IMG"
|
||||
|
||||
$QEMU_IMG compare --object $SECRET --image-opts "${IMGSPEC}.orig" "$IMGSPEC"
|
||||
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
|
@ -15,4 +15,8 @@ read 16777216/16777216 bytes at offset 0
|
||||
|
||||
== verify open failure with wrong password ==
|
||||
qemu-io: can't open: Invalid password, cannot unlock any keyslot
|
||||
|
||||
== verify that has_zero_init returns false when preallocating ==
|
||||
Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=16777216
|
||||
Images are identical.
|
||||
*** done
|
||||
|
@ -219,5 +219,10 @@ _filter_nbd()
|
||||
-e 's#\(foo\|PORT/\?\|.sock\): Failed to .*$#\1#'
|
||||
}
|
||||
|
||||
_filter_qmp_empty_return()
|
||||
{
|
||||
grep -v '{"return": {}}'
|
||||
}
|
||||
|
||||
# make sure this script returns success
|
||||
true
|
||||
|
@ -612,7 +612,7 @@ static void test_propagate_mirror(void)
|
||||
|
||||
/* Start a mirror job */
|
||||
mirror_start("job0", src, target, NULL, JOB_DEFAULT, 0, 0, 0,
|
||||
MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN,
|
||||
MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN, false,
|
||||
BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
|
||||
false, "filter_node", MIRROR_COPY_MODE_BACKGROUND,
|
||||
&error_abort);
|
||||
|
Loading…
Reference in New Issue
Block a user