Having two slightly-different function names for related purposes is unwieldy, especially since I envision adding yet another notion of zero support in an upcoming patch. It doesn't help that bdrv_has_zero_init() is a misleading name (I originally thought that a driver could only return 1 when opening an already-existing image known to be all zeroes; but in reality many drivers always return 1 because it only applies to a just-created image). Refactor all uses to instead have a single function that returns multiple bits of information, with better naming and documentation.
No semantic change, although some of the changes (such as to qcow2.c) require a careful reading to see how it remains the same. Signed-off-by: Eric Blake <ebl...@redhat.com> --- block.c | 49 ++++++++++++++------------------------ block/file-posix.c | 3 +-- block/file-win32.c | 3 +-- block/nfs.c | 7 +++--- block/parallels.c | 4 ++-- block/qcow.c | 2 +- block/qcow2.c | 10 ++++---- block/qed.c | 3 +-- block/raw-format.c | 12 +++------- block/rbd.c | 3 +-- block/sheepdog.c | 9 +++---- block/ssh.c | 7 +++--- block/vdi.c | 8 +++---- block/vhdx.c | 16 ++++++------- block/vmdk.c | 9 +++---- block/vpc.c | 8 +++---- blockdev.c | 2 +- include/block/block.h | 28 +++++++++++++++++++--- include/block/block_int.h | 15 ++---------- qemu-img.c | 3 ++- tests/qemu-iotests/122 | 2 +- tests/qemu-iotests/188 | 2 +- tests/qemu-iotests/188.out | 2 +- 23 files changed, 96 insertions(+), 111 deletions(-) diff --git a/block.c b/block.c index d132662f3103..fac0813140aa 100644 --- a/block.c +++ b/block.c @@ -5066,38 +5066,20 @@ int bdrv_get_flags(BlockDriverState *bs) return bs->open_flags; } -int bdrv_has_zero_init_1(BlockDriverState *bs) +int bdrv_known_zeroes_create(BlockDriverState *bs) { - return 1; + return BDRV_ZERO_CREATE; } -int bdrv_has_zero_init(BlockDriverState *bs) +int bdrv_known_zeroes_truncate(BlockDriverState *bs) { - if (!bs->drv) { - return 0; - } - - /* - * If BS is a copy on write image, it is initialized to the - * contents of the base image, which may not be zeroes. Likewise, - * encrypted images do not read as zero. - */ - if (bs->backing || bs->encrypted) { - return 0; - } - if (bs->drv->bdrv_has_zero_init) { - return bs->drv->bdrv_has_zero_init(bs); - } - if (bs->file && bs->drv->is_filter) { - return bdrv_has_zero_init(bs->file->bs); - } - - /* safe default */ - return 0; + return BDRV_ZERO_CREATE | BDRV_ZERO_TRUNCATE; } -int bdrv_has_zero_init_truncate(BlockDriverState *bs) +int bdrv_known_zeroes(BlockDriverState *bs) { + int mask = BDRV_ZERO_CREATE | BDRV_ZERO_TRUNCATE; + if (!bs->drv) { return 0; } @@ -5113,9 +5095,12 @@ int bdrv_has_zero_init_truncate(BlockDriverState *bs) } /* - * If the current layer is smaller than the backing layer, - * truncation may expose backing data; treat failure to query size - * in the same manner. Otherwise, we can trust the driver. + * If BS is a copy on write image, it is initialized to the + * contents of the base image, which may not be zeroes, so + * ZERO_CREATE is not viable. If the current layer is smaller + * than the backing layer, truncation may expose backing data, + * restricting ZERO_TRUNCATE; treat failure to query size in the + * same manner. Otherwise, we can trust the driver. */ if (bs->backing) { @@ -5125,12 +5110,14 @@ int bdrv_has_zero_init_truncate(BlockDriverState *bs) if (back < 0 || curr < back) { return 0; } + mask = BDRV_ZERO_TRUNCATE; } - if (bs->drv->bdrv_has_zero_init_truncate) { - return bs->drv->bdrv_has_zero_init_truncate(bs); + + if (bs->drv->bdrv_known_zeroes) { + return bs->drv->bdrv_known_zeroes(bs) & mask; } if (bs->file && bs->drv->is_filter) { - return bdrv_has_zero_init_truncate(bs->file->bs); + return bdrv_known_zeroes(bs->file->bs) & mask; } /* safe default */ diff --git a/block/file-posix.c b/block/file-posix.c index ab82ee1a6718..ff9e39ab882f 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -3071,8 +3071,7 @@ BlockDriver bdrv_file = { .bdrv_close = raw_close, .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_known_zeroes = bdrv_known_zeroes_truncate, .bdrv_co_block_status = raw_co_block_status, .bdrv_co_invalidate_cache = raw_co_invalidate_cache, .bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes, diff --git a/block/file-win32.c b/block/file-win32.c index 77e8ff7b68ae..e9b8f3b2370b 100644 --- a/block/file-win32.c +++ b/block/file-win32.c @@ -635,8 +635,7 @@ BlockDriver bdrv_file = { .bdrv_refresh_limits = raw_probe_alignment, .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_known_zeroes = bdrv_known_zeroes_truncate, .bdrv_aio_preadv = raw_aio_preadv, .bdrv_aio_pwritev = raw_aio_pwritev, diff --git a/block/nfs.c b/block/nfs.c index 9a6311e27066..34ebe91d5b39 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -702,10 +702,10 @@ out: return ret; } -static int nfs_has_zero_init(BlockDriverState *bs) +static int nfs_known_zeroes(BlockDriverState *bs) { NFSClient *client = bs->opaque; - return client->has_zero_init; + return client->has_zero_init ? BDRV_ZERO_CREATE | BDRV_ZERO_TRUNCATE : 0; } /* Called (via nfs_service) with QemuMutex held. */ @@ -869,8 +869,7 @@ static BlockDriver bdrv_nfs = { .bdrv_parse_filename = nfs_parse_filename, .create_opts = &nfs_create_opts, - .bdrv_has_zero_init = nfs_has_zero_init, - .bdrv_has_zero_init_truncate = nfs_has_zero_init, + .bdrv_known_zeroes = nfs_known_zeroes, .bdrv_get_allocated_file_size = nfs_get_allocated_file_size, .bdrv_co_truncate = nfs_file_co_truncate, diff --git a/block/parallels.c b/block/parallels.c index 7a01997659b0..dad6389c8481 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -835,7 +835,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, goto fail_options; } - if (!bdrv_has_zero_init_truncate(bs->file->bs)) { + if (!(bdrv_known_zeroes(bs->file->bs) & BDRV_ZERO_TRUNCATE)) { s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE; } @@ -906,7 +906,7 @@ static BlockDriver bdrv_parallels = { .bdrv_close = parallels_close, .bdrv_child_perm = bdrv_format_default_perms, .bdrv_co_block_status = parallels_co_block_status, - .bdrv_has_zero_init = bdrv_has_zero_init_1, + .bdrv_known_zeroes = bdrv_known_zeroes_create, .bdrv_co_flush_to_os = parallels_co_flush_to_os, .bdrv_co_readv = parallels_co_readv, .bdrv_co_writev = parallels_co_writev, diff --git a/block/qcow.c b/block/qcow.c index fce89898681f..b0c9e212fdb1 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -1183,7 +1183,7 @@ static BlockDriver bdrv_qcow = { .bdrv_reopen_prepare = qcow_reopen_prepare, .bdrv_co_create = qcow_co_create, .bdrv_co_create_opts = qcow_co_create_opts, - .bdrv_has_zero_init = bdrv_has_zero_init_1, + .bdrv_known_zeroes = bdrv_known_zeroes_create, .supports_backing = true, .bdrv_refresh_limits = qcow_refresh_limits, diff --git a/block/qcow2.c b/block/qcow2.c index 40aa751d1de7..9f2371925737 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -4914,10 +4914,11 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs, return spec_info; } -static int qcow2_has_zero_init(BlockDriverState *bs) +static int qcow2_known_zeroes(BlockDriverState *bs) { BDRVQcow2State *s = bs->opaque; bool preallocated; + int r = BDRV_ZERO_TRUNCATE; if (qemu_in_coroutine()) { qemu_co_mutex_lock(&s->lock); @@ -4933,9 +4934,9 @@ static int qcow2_has_zero_init(BlockDriverState *bs) } if (!preallocated) { - return 1; + return r | BDRV_ZERO_CREATE; } else { - return bdrv_has_zero_init(s->data_file->bs); + return r | bdrv_known_zeroes(s->data_file->bs); } } @@ -5559,8 +5560,7 @@ 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 = qcow2_has_zero_init, - .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1, + .bdrv_known_zeroes = qcow2_known_zeroes, .bdrv_co_block_status = qcow2_co_block_status, .bdrv_co_preadv_part = qcow2_co_preadv_part, diff --git a/block/qed.c b/block/qed.c index d8c4e5fb1e85..b00cef2035b3 100644 --- a/block/qed.c +++ b/block/qed.c @@ -1672,8 +1672,7 @@ static BlockDriver bdrv_qed = { .bdrv_child_perm = bdrv_format_default_perms, .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_known_zeroes = bdrv_known_zeroes_truncate, .bdrv_co_block_status = bdrv_qed_co_block_status, .bdrv_co_readv = bdrv_qed_co_readv, .bdrv_co_writev = bdrv_qed_co_writev, diff --git a/block/raw-format.c b/block/raw-format.c index 3a76ec7dd21b..1334a7a2c224 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -409,14 +409,9 @@ static int raw_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) return bdrv_co_ioctl(bs->file->bs, req, buf); } -static int raw_has_zero_init(BlockDriverState *bs) +static int raw_known_zeroes(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); + return bdrv_known_zeroes(bs->file->bs); } static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts, @@ -577,8 +572,7 @@ BlockDriver bdrv_raw = { .bdrv_lock_medium = &raw_lock_medium, .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, + .bdrv_known_zeroes = &raw_known_zeroes, .strong_runtime_opts = raw_strong_runtime_opts, .mutable_opts = mutable_opts, }; diff --git a/block/rbd.c b/block/rbd.c index 027cbcc69520..6cd8e86bccec 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -1289,8 +1289,7 @@ static BlockDriver bdrv_rbd = { .bdrv_reopen_prepare = qemu_rbd_reopen_prepare, .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_known_zeroes = bdrv_known_zeroes_truncate, .bdrv_get_info = qemu_rbd_getinfo, .create_opts = &qemu_rbd_create_opts, .bdrv_getlength = qemu_rbd_getlength, diff --git a/block/sheepdog.c b/block/sheepdog.c index 522c16a93676..916e64abdd74 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -3229,8 +3229,7 @@ static BlockDriver bdrv_sheepdog = { .bdrv_close = sd_close, .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_known_zeroes = bdrv_known_zeroes_truncate, .bdrv_getlength = sd_getlength, .bdrv_get_allocated_file_size = sd_get_allocated_file_size, .bdrv_co_truncate = sd_co_truncate, @@ -3268,8 +3267,7 @@ static BlockDriver bdrv_sheepdog_tcp = { .bdrv_close = sd_close, .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_known_zeroes = bdrv_known_zeroes_truncate, .bdrv_getlength = sd_getlength, .bdrv_get_allocated_file_size = sd_get_allocated_file_size, .bdrv_co_truncate = sd_co_truncate, @@ -3307,8 +3305,7 @@ static BlockDriver bdrv_sheepdog_unix = { .bdrv_close = sd_close, .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_known_zeroes = bdrv_known_zeroes_truncate, .bdrv_getlength = sd_getlength, .bdrv_get_allocated_file_size = sd_get_allocated_file_size, .bdrv_co_truncate = sd_co_truncate, diff --git a/block/ssh.c b/block/ssh.c index b4375cf7d2e5..e89dae39800c 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -1007,14 +1007,14 @@ static void ssh_close(BlockDriverState *bs) ssh_state_free(s); } -static int ssh_has_zero_init(BlockDriverState *bs) +static int ssh_known_zeroes(BlockDriverState *bs) { BDRVSSHState *s = bs->opaque; /* Assume false, unless we can positively prove it's true. */ int has_zero_init = 0; if (s->attrs->type == SSH_FILEXFER_TYPE_REGULAR) { - has_zero_init = 1; + has_zero_init = BDRV_ZERO_CREATE | BDRV_ZERO_TRUNCATE; } return has_zero_init; @@ -1390,8 +1390,7 @@ static BlockDriver bdrv_ssh = { .bdrv_co_create = ssh_co_create, .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_known_zeroes = ssh_known_zeroes, .bdrv_co_readv = ssh_co_readv, .bdrv_co_writev = ssh_co_writev, .bdrv_getlength = ssh_getlength, diff --git a/block/vdi.c b/block/vdi.c index 0142da723315..df8f62624ccf 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -989,14 +989,14 @@ static void vdi_close(BlockDriverState *bs) error_free(s->migration_blocker); } -static int vdi_has_zero_init(BlockDriverState *bs) +static int vdi_known_zeroes(BlockDriverState *bs) { BDRVVdiState *s = bs->opaque; if (s->header.image_type == VDI_TYPE_STATIC) { - return bdrv_has_zero_init(bs->file->bs); + return bdrv_known_zeroes(bs->file->bs) & BDRV_ZERO_CREATE; } else { - return 1; + return BDRV_ZERO_CREATE; } } @@ -1040,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 = vdi_has_zero_init, + .bdrv_known_zeroes = vdi_known_zeroes, .bdrv_co_block_status = vdi_co_block_status, .bdrv_make_empty = vdi_make_empty, diff --git a/block/vhdx.c b/block/vhdx.c index f02d2611bef8..4e8320c1b855 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -1365,7 +1365,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_truncate(bs->file->bs) == 0) { + if (!(bdrv_known_zeroes(bs->file->bs) & BDRV_ZERO_TRUNCATE)) { use_zero_buffers = true; /* zero fill the front, if any */ @@ -1720,8 +1720,8 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s, } if (type == VHDX_TYPE_FIXED || - use_zero_blocks || - bdrv_has_zero_init(blk_bs(blk)) == 0) { + use_zero_blocks || + !(bdrv_known_zeroes(blk_bs(blk)) & BDRV_ZERO_CREATE)) { /* for a fixed file, the default BAT entry is not zero */ s->bat = g_try_malloc0(length); if (length && s->bat == NULL) { @@ -2162,7 +2162,7 @@ static int coroutine_fn vhdx_co_check(BlockDriverState *bs, return 0; } -static int vhdx_has_zero_init(BlockDriverState *bs) +static int vhdx_known_zeroes(BlockDriverState *bs) { BDRVVHDXState *s = bs->opaque; int state; @@ -2173,17 +2173,17 @@ static int vhdx_has_zero_init(BlockDriverState *bs) * therefore enough to check the first BAT entry. */ if (!s->bat_entries) { - return 1; + return BDRV_ZERO_CREATE; } 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); + return bdrv_known_zeroes(bs->file->bs) & BDRV_ZERO_CREATE; } /* Dynamic subformat */ - return 1; + return BDRV_ZERO_CREATE; } static QemuOptsList vhdx_create_opts = { @@ -2239,7 +2239,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 = vhdx_has_zero_init, + .bdrv_known_zeroes = vhdx_known_zeroes, .create_opts = &vhdx_create_opts, }; diff --git a/block/vmdk.c b/block/vmdk.c index 20e909d99794..ca59f50413d2 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -2815,7 +2815,7 @@ static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs) return ret; } -static int vmdk_has_zero_init(BlockDriverState *bs) +static int vmdk_known_zeroes(BlockDriverState *bs) { int i; BDRVVmdkState *s = bs->opaque; @@ -2824,12 +2824,13 @@ static int vmdk_has_zero_init(BlockDriverState *bs) * return 0. */ for (i = 0; i < s->num_extents; i++) { if (s->extents[i].flat) { - if (!bdrv_has_zero_init(s->extents[i].file->bs)) { + if (!(bdrv_known_zeroes(s->extents[i].file->bs) & + BDRV_ZERO_CREATE)) { return 0; } } } - return 1; + return BDRV_ZERO_CREATE; } static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent) @@ -3052,7 +3053,7 @@ static BlockDriver bdrv_vmdk = { .bdrv_co_flush_to_disk = vmdk_co_flush, .bdrv_co_block_status = vmdk_co_block_status, .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size, - .bdrv_has_zero_init = vmdk_has_zero_init, + .bdrv_known_zeroes = vmdk_known_zeroes, .bdrv_get_specific_info = vmdk_get_specific_info, .bdrv_refresh_limits = vmdk_refresh_limits, .bdrv_get_info = vmdk_get_info, diff --git a/block/vpc.c b/block/vpc.c index a65550298e19..f4741e07bfb2 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -1173,15 +1173,15 @@ fail: } -static int vpc_has_zero_init(BlockDriverState *bs) +static int vpc_known_zeroes(BlockDriverState *bs) { BDRVVPCState *s = bs->opaque; VHDFooter *footer = (VHDFooter *) s->footer_buf; if (be32_to_cpu(footer->type) == VHD_FIXED) { - return bdrv_has_zero_init(bs->file->bs); + return bdrv_known_zeroes(bs->file->bs) & BDRV_ZERO_CREATE; } else { - return 1; + return BDRV_ZERO_CREATE; } } @@ -1249,7 +1249,7 @@ static BlockDriver bdrv_vpc = { .bdrv_get_info = vpc_get_info, .create_opts = &vpc_create_opts, - .bdrv_has_zero_init = vpc_has_zero_init, + .bdrv_known_zeroes = vpc_known_zeroes, .strong_runtime_opts = vpc_strong_runtime_opts, }; diff --git a/blockdev.c b/blockdev.c index c6a727cca99d..90a17e7f7bce 100644 --- a/blockdev.c +++ b/blockdev.c @@ -4001,7 +4001,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) zero_target = (arg->sync == MIRROR_SYNC_MODE_FULL && (arg->mode == NEW_IMAGE_MODE_EXISTING || - !bdrv_has_zero_init(target_bs))); + !(bdrv_known_zeroes(target_bs) & BDRV_ZERO_CREATE))); /* Honor bdrv_try_set_aio_context() context acquisition requirements. */ diff --git a/include/block/block.h b/include/block/block.h index 6cd566324d95..a6a227f50678 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -85,6 +85,28 @@ typedef enum { BDRV_REQ_MASK = 0x3ff, } BdrvRequestFlags; +typedef enum { + /* + * bdrv_known_zeroes() should include this bit if the contents of + * a freshly-created image with no backing file reads as all + * zeroes without any additional effort. If .bdrv_co_truncate is + * set, then this must be clear if BDRV_ZERO_TRUNCATE is clear. + * Since this bit is only reliable at image creation, a driver may + * return this bit even for existing images that do not currently + * read as zero. + */ + BDRV_ZERO_CREATE = 0x1, + + /* + * bdrv_known_zeroes() should include this bit if growing an image + * with PREALLOC_MODE_OFF (either with no backing file, or beyond + * the size of the backing file) will read the new data as all + * zeroes without any additional effort. This bit only matters + * for drivers that set .bdrv_co_truncate. + */ + BDRV_ZERO_TRUNCATE = 0x2, +} BdrvZeroFlags; + typedef struct BlockSizes { uint32_t phys; uint32_t log; @@ -430,9 +452,9 @@ void bdrv_drain_all(void); 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); +int bdrv_known_zeroes_create(BlockDriverState *bs); +int bdrv_known_zeroes_truncate(BlockDriverState *bs); +int bdrv_known_zeroes(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, diff --git a/include/block/block_int.h b/include/block/block_int.h index 77ab45dc87cf..47b34860bf95 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -441,19 +441,8 @@ struct BlockDriver { void (*bdrv_refresh_limits)(BlockDriverState *bs, Error **errp); - /* - * Returns 1 if newly created images are guaranteed to contain only - * zeros, 0 otherwise. - * Must return 0 if .bdrv_co_truncate is set and - * .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); + /* Returns bitwise-OR of BdrvZeroFlags. */ + int (*bdrv_known_zeroes)(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 diff --git a/qemu-img.c b/qemu-img.c index e0bfc33ef4f6..e60217e6c382 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1987,7 +1987,8 @@ static int convert_do_copy(ImgConvertState *s) /* Check whether we have zero initialisation or can get it efficiently */ if (!s->has_zero_init && s->target_is_new && s->min_sparse && !s->target_has_backing) { - s->has_zero_init = bdrv_has_zero_init(blk_bs(s->target)); + s->has_zero_init = !!(bdrv_known_zeroes(blk_bs(s->target)) & + BDRV_ZERO_CREATE); } if (!s->has_zero_init && !s->target_has_backing && diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122 index dfa350936fe6..7cb09309948f 100755 --- a/tests/qemu-iotests/122 +++ b/tests/qemu-iotests/122 @@ -267,7 +267,7 @@ echo # Keep source zero _make_test_img 64M -# Output is not zero, but has bdrv_has_zero_init() == 1 +# Output is not zero, but has bdrv_known_zeroes() including BDRV_ZERO_CREATE TEST_IMG="$TEST_IMG".orig _make_test_img 64M $QEMU_IO -c "write -P 42 0 64k" "$TEST_IMG".orig | _filter_qemu_io diff --git a/tests/qemu-iotests/188 b/tests/qemu-iotests/188 index afca44df5427..9656969fef4a 100755 --- a/tests/qemu-iotests/188 +++ b/tests/qemu-iotests/188 @@ -71,7 +71,7 @@ $QEMU_IO --object $SECRETALT -c "read -P 0xa 0 $size" --image-opts $IMGSPEC | _f _cleanup_test_img echo -echo "== verify that has_zero_init returns false when preallocating ==" +echo "== verify that known_zeroes returns 0 when preallocating ==" # Empty source file if [ -n "$TEST_IMG_FILE" ]; then diff --git a/tests/qemu-iotests/188.out b/tests/qemu-iotests/188.out index c568ef370145..f7da30440c65 100644 --- a/tests/qemu-iotests/188.out +++ b/tests/qemu-iotests/188.out @@ -16,7 +16,7 @@ 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 == +== verify that known_zeroes returns 0 when preallocating == Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=16777216 Images are identical. *** done -- 2.24.1