@@ -146,19 +146,35 @@ static int commit_iteration(CommitBlockJob *s, int64_t offset, int64_t *n, void
trace_commit_one_iteration(s, offset, *n, ret);
if (ret & BDRV_BLOCK_ALLOCATED) {
- assert(*n < SIZE_MAX);
+ if (ret & BDRV_BLOCK_ZERO) {
+ /* If the top (sub)clusters are smaller than the base
+ * (sub)clusters, this will not unmap unless the underlying device
+ * does some tracking of these requests. Ideally, we would find
+ * the maximal extent of the zero clusters. */
+ ret = blk_co_pwrite_zeroes(s->base, offset, *n,
+ BDRV_REQ_MAY_UNMAP);
+ if (ret < 0) {
+ error_in_source = false;
+ goto handle_error;
+ }
+ } else {
+ assert(*n < SIZE_MAX);
- ret = blk_co_pread(s->top, offset, *n, buf, 0);
- if (ret < 0) {
- goto handle_error;
- }
+ ret = blk_co_pread(s->top, offset, *n, buf, 0);
+ if (ret < 0) {
+ goto handle_error;
+ }
- ret = blk_co_pwrite(s->base, offset, *n, buf, 0);
- if (ret < 0) {
- error_in_source = false;
- goto handle_error;
+ ret = blk_co_pwrite(s->base, offset, *n, buf, 0);
+ if (ret < 0) {
+ error_in_source = false;
+ goto handle_error;
+ }
}
+ /* Whether zeroes actually end up on disk depends on the details of
+ * the underlying driver. Therefore, this might rate limit more than
+ * is necessary. */
block_job_ratelimit_processed_bytes(&s->common, *n);
}
Non-active block commits do not discard blocks only containing zeros, causing images to lose sparseness after the commit. This commit fixes that by writing zero blocks using blk_co_pwrite_zeroes rather than writing them out as any other arbitrary data. Signed-off-by: Vincent Vanlaer <libvirt-e6954efa@volkihar.be> --- block/commit.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-)