mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
block: allow commit to unmap zero blocks
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> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> Message-Id: <20241026163010.2865002-5-libvirt-e6954efa@volkihar.be> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
This commit is contained in:
committed by
Vladimir Sementsov-Ogievskiy
parent
0648c76ad1
commit
6f3199f996
+29
-9
@@ -150,19 +150,39 @@ static int commit_iteration(CommitBlockJob *s, int64_t offset,
|
||||
}
|
||||
|
||||
if (ret & BDRV_BLOCK_ALLOCATED) {
|
||||
assert(bytes < 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, bytes,
|
||||
BDRV_REQ_MAY_UNMAP);
|
||||
if (ret < 0) {
|
||||
error_in_source = false;
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
assert(bytes < SIZE_MAX);
|
||||
|
||||
ret = blk_co_pread(s->top, offset, bytes, buf, 0);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
ret = blk_co_pread(s->top, offset, bytes, buf, 0);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = blk_co_pwrite(s->base, offset, bytes, buf, 0);
|
||||
if (ret < 0) {
|
||||
error_in_source = false;
|
||||
goto fail;
|
||||
ret = blk_co_pwrite(s->base, offset, bytes, buf, 0);
|
||||
if (ret < 0) {
|
||||
error_in_source = false;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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, bytes);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user