78 lines
3.1 KiB
Diff
78 lines
3.1 KiB
Diff
From 2d2431f03fc78b532f3a1c5f858cf78859d50fc3 Mon Sep 17 00:00:00 2001
|
|
From: aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>
|
|
Date: Sun, 5 Apr 2009 17:40:58 +0000
|
|
Subject: [PATCH] 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
|
|
---
|
|
block-qcow2.c | 20 +++++++++++++-------
|
|
1 files changed, 13 insertions(+), 7 deletions(-)
|
|
|
|
Index: qemu-kvm-0.10/qemu/block-qcow2.c
|
|
===================================================================
|
|
--- qemu-kvm-0.10.orig/qemu/block-qcow2.c
|
|
+++ qemu-kvm-0.10/qemu/block-qcow2.c
|
|
@@ -1458,6 +1458,7 @@ static int qcow_create(const char *filen
|
|
const char *backing_file, int flags)
|
|
{
|
|
int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
|
|
+ int ref_clusters = 0;
|
|
QCowHeader header;
|
|
uint64_t tmp, offset;
|
|
QCowCreateState s1, *s = &s1;
|
|
@@ -1498,22 +1499,28 @@ static int qcow_create(const char *filen
|
|
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));
|
|
@@ -1529,7 +1536,7 @@ static int qcow_create(const char *filen
|
|
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);
|