mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 09:43:56 -06:00
qcow2: Fix preallocation on images with unaligned sizes
When resizing an image with qcow2_co_truncate() using the falloc or full preallocation modes the code assumes that both the old and new sizes are cluster-aligned. There are two problems with this: 1) The calculation of how many clusters are involved does not always get the right result. Example: creating a 60KB image and resizing it (with preallocation=full) to 80KB won't allocate the second cluster. 2) No copy-on-write is performed, so in the previous example if there is a backing file then the first 60KB of the first cluster won't be filled with data from the backing file. This patch fixes both issues. Signed-off-by: Alberto Garcia <berto@igalia.com> Message-Id: <20200617140036.20311-1-berto@igalia.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
e8de7ba9ea
commit
a5675f3901
3 changed files with 47 additions and 3 deletions
|
@ -4239,8 +4239,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
|||
old_file_size = ROUND_UP(old_file_size, s->cluster_size);
|
||||
}
|
||||
|
||||
nb_new_data_clusters = DIV_ROUND_UP(offset - old_length,
|
||||
s->cluster_size);
|
||||
nb_new_data_clusters = (ROUND_UP(offset, s->cluster_size) -
|
||||
start_of_cluster(s, old_length)) >> s->cluster_bits;
|
||||
|
||||
/* This is an overestimation; we will not actually allocate space for
|
||||
* these in the file but just make sure the new refcount structures are
|
||||
|
@ -4317,10 +4317,21 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
|||
int64_t nb_clusters = MIN(
|
||||
nb_new_data_clusters,
|
||||
s->l2_slice_size - offset_to_l2_slice_index(s, guest_offset));
|
||||
QCowL2Meta allocation = {
|
||||
unsigned cow_start_length = offset_into_cluster(s, guest_offset);
|
||||
QCowL2Meta allocation;
|
||||
guest_offset = start_of_cluster(s, guest_offset);
|
||||
allocation = (QCowL2Meta) {
|
||||
.offset = guest_offset,
|
||||
.alloc_offset = host_offset,
|
||||
.nb_clusters = nb_clusters,
|
||||
.cow_start = {
|
||||
.offset = 0,
|
||||
.nb_bytes = cow_start_length,
|
||||
},
|
||||
.cow_end = {
|
||||
.offset = nb_clusters << s->cluster_bits,
|
||||
.nb_bytes = 0,
|
||||
},
|
||||
};
|
||||
qemu_co_queue_init(&allocation.dependent_requests);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue