[sheepdog] [PATCH 09/17] block: Refactor bdrv_has_zero_init{, _truncate}
Eric Blake
eblake at redhat.com
Fri Jan 31 18:44:28 CET 2020
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 <eblake at 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
More information about the sheepdog
mailing list