Glauber Costa 3b07569
From 2d2431f03fc78b532f3a1c5f858cf78859d50fc3 Mon Sep 17 00:00:00 2001
Glauber Costa 3b07569
From: aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>
Glauber Costa 3b07569
Date: Sun, 5 Apr 2009 17:40:58 +0000
Glauber Costa 3b07569
Subject: [PATCH] qcow2: fix image creation for large, > ~2TB, images (Chris Wright)
Glauber Costa 3b07569
Glauber Costa 3b07569
When creating large disk images w/ qcow2 format, qcow2_create is hard
Glauber Costa 3b07569
coded to creating a single refcount block.  This is insufficient for
Glauber Costa 3b07569
large images, and will cause qemu-img to segfault as it walks off the
Glauber Costa 3b07569
end of the refcount block.  Keep track of the space needed during image
Glauber Costa 3b07569
create and create proper number of refcount blocks accordingly.
Glauber Costa 3b07569
Glauber Costa 3b07569
https://bugzilla.redhat.com/show_bug.cgi?id=491943
Glauber Costa 3b07569
Glauber Costa 3b07569
Signed-off-by: Chris Wright <chrisw@redhat.com>
Glauber Costa 3b07569
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Glauber Costa 3b07569
Glauber Costa 3b07569
Glauber Costa 3b07569
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6982 c046a42c-6fe2-441c-8c8c-71466251a162
Glauber Costa 3b07569
---
Glauber Costa 3b07569
 block-qcow2.c |   20 +++++++++++++-------
Glauber Costa 3b07569
 1 files changed, 13 insertions(+), 7 deletions(-)
Glauber Costa 3b07569
Glauber Costa 3b07569
Index: qemu-kvm-0.10/qemu/block-qcow2.c
Glauber Costa 3b07569
===================================================================
Glauber Costa 3b07569
--- qemu-kvm-0.10.orig/qemu/block-qcow2.c
Glauber Costa 3b07569
+++ qemu-kvm-0.10/qemu/block-qcow2.c
Glauber Costa 3b07569
@@ -1458,6 +1458,7 @@ static int qcow_create(const char *filen
Glauber Costa 3b07569
                       const char *backing_file, int flags)
Glauber Costa 3b07569
 {
Glauber Costa 3b07569
     int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
Glauber Costa 3b07569
+    int ref_clusters = 0;
Glauber Costa 3b07569
     QCowHeader header;
Glauber Costa 3b07569
     uint64_t tmp, offset;
Glauber Costa 3b07569
     QCowCreateState s1, *s = &s1;
Glauber Costa 3b07569
@@ -1498,22 +1499,28 @@ static int qcow_create(const char *filen
Glauber Costa 3b07569
     offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
Glauber Costa 3b07569
 
Glauber Costa 3b07569
     s->refcount_table = qemu_mallocz(s->cluster_size);
Glauber Costa 3b07569
-    s->refcount_block = qemu_mallocz(s->cluster_size);
Glauber Costa 3b07569
 
Glauber Costa 3b07569
     s->refcount_table_offset = offset;
Glauber Costa 3b07569
     header.refcount_table_offset = cpu_to_be64(offset);
Glauber Costa 3b07569
     header.refcount_table_clusters = cpu_to_be32(1);
Glauber Costa 3b07569
     offset += s->cluster_size;
Glauber Costa 3b07569
-
Glauber Costa 3b07569
-    s->refcount_table[0] = cpu_to_be64(offset);
Glauber Costa 3b07569
     s->refcount_block_offset = offset;
Glauber Costa 3b07569
-    offset += s->cluster_size;
Glauber Costa 3b07569
+
Glauber Costa 3b07569
+    /* count how many refcount blocks needed */
Glauber Costa 3b07569
+    tmp = offset >> s->cluster_bits;
Glauber Costa 3b07569
+    ref_clusters = (tmp >> (s->cluster_bits - REFCOUNT_SHIFT)) + 1;
Glauber Costa 3b07569
+    for (i=0; i < ref_clusters; i++) {
Glauber Costa 3b07569
+        s->refcount_table[i] = cpu_to_be64(offset);
Glauber Costa 3b07569
+        offset += s->cluster_size;
Glauber Costa 3b07569
+    }
Glauber Costa 3b07569
+
Glauber Costa 3b07569
+    s->refcount_block = qemu_mallocz(ref_clusters * s->cluster_size);
Glauber Costa 3b07569
 
Glauber Costa 3b07569
     /* update refcounts */
Glauber Costa 3b07569
     create_refcount_update(s, 0, header_size);
Glauber Costa 3b07569
     create_refcount_update(s, s->l1_table_offset, l1_size * sizeof(uint64_t));
Glauber Costa 3b07569
     create_refcount_update(s, s->refcount_table_offset, s->cluster_size);
Glauber Costa 3b07569
-    create_refcount_update(s, s->refcount_block_offset, s->cluster_size);
Glauber Costa 3b07569
+    create_refcount_update(s, s->refcount_block_offset, ref_clusters * s->cluster_size);
Glauber Costa 3b07569
 
Glauber Costa 3b07569
     /* write all the data */
Glauber Costa 3b07569
     write(fd, &header, sizeof(header));
Glauber Costa 3b07569
@@ -1529,7 +1536,7 @@ static int qcow_create(const char *filen
Glauber Costa 3b07569
     write(fd, s->refcount_table, s->cluster_size);
Glauber Costa 3b07569
 
Glauber Costa 3b07569
     lseek(fd, s->refcount_block_offset, SEEK_SET);
Glauber Costa 3b07569
-    write(fd, s->refcount_block, s->cluster_size);
Glauber Costa 3b07569
+    write(fd, s->refcount_block, ref_clusters * s->cluster_size);
Glauber Costa 3b07569
 
Glauber Costa 3b07569
     qemu_free(s->refcount_table);
Glauber Costa 3b07569
     qemu_free(s->refcount_block);