On 4/23/20 10:01 AM, Kevin Wolf wrote:
If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling
qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't
undo any previous preallocation, but just adds the zero flag to all
relevant L2 entries. If an external data file is in use, a write_zeroes
request to the data file is made instead.
Signed-off-by: Kevin Wolf <kw...@redhat.com>
Reviewed-by: Max Reitz <mre...@redhat.com>
---
block/qcow2-cluster.c | 2 +-
block/qcow2.c | 33 +++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 1 deletion(-)
+ if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
+ uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size);
+
+ /*
+ * Use zero clusters as much as we can. qcow2_cluster_zeroize()
+ * requires a cluster-aligned start. The end may be unaligned if it is
+ * at the end of the image (which it is here).
+ */
+ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "Failed to zero out new clusters");
+ goto fail;
+ }
+
+ /* Write explicit zeros for the unaligned head */
+ if (zero_start > old_length) {
+ uint8_t *buf = qemu_blockalign0(bs, s->cluster_size);
+ QEMUIOVector qiov;
+ qemu_iovec_init_buf(&qiov, buf, zero_start - old_length);
+
+ qemu_co_mutex_unlock(&s->lock);
+ ret = qcow2_co_pwritev_part(bs, old_length, qiov.size, &qiov, 0,
0);
This works, but would it be any more efficient to use
qcow2_co_pwrite_zeroes? If the head of the cluster is already zero,
then qcow2_co_pwrite_zeroes can turn into qcow2_cluster_zeroize for this
cluster, while qcow2_co_pwritev_part cannot.
Because what you have works, and because we can use
qcow2_co_pwrite_zeroes as an optimization in a later patch,
Reviewed-by: Eric Blake <ebl...@redhat.com>
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3226
Virtualization: qemu.org | libvirt.org