Signed-off-by: Anton Nefedov <anton.nefe...@virtuozzo.com> Signed-off-by: Denis V. Lunev <d...@openvz.org> --- block/qcow2-cluster.c | 2 ++ block/qcow2.c | 8 +++++++- block/qcow2.h | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index c39e825..ed65961 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1143,6 +1143,7 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m) { BDRVQcow2State *s = bs->opaque; + const uint64_t old_data_end = s->data_end; int l2_index; uint64_t *l2_table; uint64_t entry; @@ -1264,6 +1265,7 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset, .alloc_offset = alloc_cluster_offset, .offset = start_of_cluster(s, guest_offset), .nb_clusters = nb_clusters, + .clusters_are_trailing = alloc_cluster_offset >= old_data_end, .keep_old_clusters = keep_old_clusters, diff --git a/block/qcow2.c b/block/qcow2.c index 809102a..92d0af6 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1686,7 +1686,13 @@ restart: if (end <= bdrv_getlength(file)) { /* No need to care, file size will not be changed */ - return false; + + /* We're safe to assume that the area is zeroes if the area + * was allocated at the end of data (s->data_end). + * In this case, the only way for file length to be bigger is that + * the area was preallocated by another request. + */ + return m->clusters_are_trailing; } meta = g_alloca(sizeof(*meta)); diff --git a/block/qcow2.h b/block/qcow2.h index e28c54a..2fd8510 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -333,6 +333,10 @@ typedef struct QCowL2Meta /** Do not free the old clusters */ bool keep_old_clusters; + /** True if the area is allocated after the end of data area + * (i.e. >= s->data_end), which means that it is zeroed */ + bool clusters_are_trailing; + /** * Requests that overlap with this allocation and wait to be restarted * when the allocating request has completed. -- 2.7.4