Blame qemu-fix-qcow2-2TB.patch

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