mirror of https://gitee.com/openkylin/qemu.git
qcow2: fix image creation for large, > ~2TB, images (Chris Wright)
When creating large disk images w/ qcow2 format, qcow2_create is hard coded to creating a single refcount block. This is insufficient for large images, and will cause qemu-img to segfault as it walks off the end of the refcount block. Keep track of the space needed during image create and create proper number of refcount blocks accordingly. https://bugzilla.redhat.com/show_bug.cgi?id=491943 Signed-off-by: Chris Wright <chrisw@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6982 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
8707eccac8
commit
2d2431f03f
|
@ -1555,7 +1555,7 @@ static int qcow_create2(const char *filename, int64_t total_size,
|
|||
{
|
||||
|
||||
int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
|
||||
int backing_format_len = 0;
|
||||
int ref_clusters, backing_format_len = 0;
|
||||
QCowHeader header;
|
||||
uint64_t tmp, offset;
|
||||
QCowCreateState s1, *s = &s1;
|
||||
|
@ -1604,22 +1604,28 @@ static int qcow_create2(const char *filename, int64_t total_size,
|
|||
offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
|
||||
|
||||
s->refcount_table = qemu_mallocz(s->cluster_size);
|
||||
s->refcount_block = qemu_mallocz(s->cluster_size);
|
||||
|
||||
s->refcount_table_offset = offset;
|
||||
header.refcount_table_offset = cpu_to_be64(offset);
|
||||
header.refcount_table_clusters = cpu_to_be32(1);
|
||||
offset += s->cluster_size;
|
||||
|
||||
s->refcount_table[0] = cpu_to_be64(offset);
|
||||
s->refcount_block_offset = offset;
|
||||
offset += s->cluster_size;
|
||||
|
||||
/* count how many refcount blocks needed */
|
||||
tmp = offset >> s->cluster_bits;
|
||||
ref_clusters = (tmp >> (s->cluster_bits - REFCOUNT_SHIFT)) + 1;
|
||||
for (i=0; i < ref_clusters; i++) {
|
||||
s->refcount_table[i] = cpu_to_be64(offset);
|
||||
offset += s->cluster_size;
|
||||
}
|
||||
|
||||
s->refcount_block = qemu_mallocz(ref_clusters * s->cluster_size);
|
||||
|
||||
/* update refcounts */
|
||||
create_refcount_update(s, 0, header_size);
|
||||
create_refcount_update(s, s->l1_table_offset, l1_size * sizeof(uint64_t));
|
||||
create_refcount_update(s, s->refcount_table_offset, s->cluster_size);
|
||||
create_refcount_update(s, s->refcount_block_offset, s->cluster_size);
|
||||
create_refcount_update(s, s->refcount_block_offset, ref_clusters * s->cluster_size);
|
||||
|
||||
/* write all the data */
|
||||
write(fd, &header, sizeof(header));
|
||||
|
@ -1648,7 +1654,7 @@ static int qcow_create2(const char *filename, int64_t total_size,
|
|||
write(fd, s->refcount_table, s->cluster_size);
|
||||
|
||||
lseek(fd, s->refcount_block_offset, SEEK_SET);
|
||||
write(fd, s->refcount_block, s->cluster_size);
|
||||
write(fd, s->refcount_block, ref_clusters * s->cluster_size);
|
||||
|
||||
qemu_free(s->refcount_table);
|
||||
qemu_free(s->refcount_block);
|
||||
|
|
Loading…
Reference in New Issue