qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

qcow2: Support BDRV_REQ_ZERO_WRITE for truncate

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 <kwolf@redhat.com>
Message-Id: <20200424125448.63318-5-kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>

+35 -1
+1 -1
block/qcow2-cluster.c
··· 1795 1795 /* Caller must pass aligned values, except at image end */ 1796 1796 assert(QEMU_IS_ALIGNED(offset, s->cluster_size)); 1797 1797 assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) || 1798 - end_offset == bs->total_sectors << BDRV_SECTOR_BITS); 1798 + end_offset >= bs->total_sectors << BDRV_SECTOR_BITS); 1799 1799 1800 1800 /* The zero flag is only supported by version 3 and newer */ 1801 1801 if (s->qcow_version < 3) {
+34
block/qcow2.c
··· 1726 1726 1727 1727 bs->supported_zero_flags = header.version >= 3 ? 1728 1728 BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0; 1729 + bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; 1729 1730 1730 1731 /* Repair image if dirty */ 1731 1732 if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only && ··· 4212 4213 4213 4214 default: 4214 4215 g_assert_not_reached(); 4216 + } 4217 + 4218 + if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) { 4219 + uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size); 4220 + 4221 + /* 4222 + * Use zero clusters as much as we can. qcow2_cluster_zeroize() 4223 + * requires a cluster-aligned start. The end may be unaligned if it is 4224 + * at the end of the image (which it is here). 4225 + */ 4226 + ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0); 4227 + if (ret < 0) { 4228 + error_setg_errno(errp, -ret, "Failed to zero out new clusters"); 4229 + goto fail; 4230 + } 4231 + 4232 + /* Write explicit zeros for the unaligned head */ 4233 + if (zero_start > old_length) { 4234 + uint64_t len = zero_start - old_length; 4235 + uint8_t *buf = qemu_blockalign0(bs, len); 4236 + QEMUIOVector qiov; 4237 + qemu_iovec_init_buf(&qiov, buf, len); 4238 + 4239 + qemu_co_mutex_unlock(&s->lock); 4240 + ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0); 4241 + qemu_co_mutex_lock(&s->lock); 4242 + 4243 + qemu_vfree(buf); 4244 + if (ret < 0) { 4245 + error_setg_errno(errp, -ret, "Failed to zero out the new area"); 4246 + goto fail; 4247 + } 4248 + } 4215 4249 } 4216 4250 4217 4251 if (prealloc != PREALLOC_MODE_OFF) {