提交 2d2431f0 编写于 作者: A aliguori

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=491943Signed-off-by: NChris Wright <chrisw@redhat.com>
Signed-off-by: NAnthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6982 c046a42c-6fe2-441c-8c8c-71466251a162
上级 8707ecca
...@@ -1555,7 +1555,7 @@ static int qcow_create2(const char *filename, int64_t total_size, ...@@ -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 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; QCowHeader header;
uint64_t tmp, offset; uint64_t tmp, offset;
QCowCreateState s1, *s = &s1; QCowCreateState s1, *s = &s1;
...@@ -1604,22 +1604,28 @@ static int qcow_create2(const char *filename, int64_t total_size, ...@@ -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); offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
s->refcount_table = qemu_mallocz(s->cluster_size); s->refcount_table = qemu_mallocz(s->cluster_size);
s->refcount_block = qemu_mallocz(s->cluster_size);
s->refcount_table_offset = offset; s->refcount_table_offset = offset;
header.refcount_table_offset = cpu_to_be64(offset); header.refcount_table_offset = cpu_to_be64(offset);
header.refcount_table_clusters = cpu_to_be32(1); header.refcount_table_clusters = cpu_to_be32(1);
offset += s->cluster_size; offset += s->cluster_size;
s->refcount_table[0] = cpu_to_be64(offset);
s->refcount_block_offset = offset; s->refcount_block_offset = offset;
/* 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; offset += s->cluster_size;
}
s->refcount_block = qemu_mallocz(ref_clusters * s->cluster_size);
/* update refcounts */ /* update refcounts */
create_refcount_update(s, 0, header_size); 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->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_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 all the data */
write(fd, &header, sizeof(header)); write(fd, &header, sizeof(header));
...@@ -1648,7 +1654,7 @@ static int qcow_create2(const char *filename, int64_t total_size, ...@@ -1648,7 +1654,7 @@ static int qcow_create2(const char *filename, int64_t total_size,
write(fd, s->refcount_table, s->cluster_size); write(fd, s->refcount_table, s->cluster_size);
lseek(fd, s->refcount_block_offset, SEEK_SET); 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_table);
qemu_free(s->refcount_block); qemu_free(s->refcount_block);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册