qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [6988] qcow2: fix image creation for large, > ~2TB, images


From: Anthony Liguori
Subject: [Qemu-devel] [6988] qcow2: fix image creation for large, > ~2TB, images (Chris Wright)
Date: Sun, 05 Apr 2009 18:16:11 +0000

Revision: 6988
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=6988
Author:   aliguori
Date:     2009-04-05 18:16:10 +0000 (Sun, 05 Apr 2009)
Log Message:
-----------
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 <address@hidden>
Signed-off-by: Anthony Liguori <address@hidden>

Modified Paths:
--------------
    branches/stable_0_10/block-qcow2.c

Modified: branches/stable_0_10/block-qcow2.c
===================================================================
--- branches/stable_0_10/block-qcow2.c  2009-04-05 18:16:04 UTC (rev 6987)
+++ branches/stable_0_10/block-qcow2.c  2009-04-05 18:16:10 UTC (rev 6988)
@@ -1462,6 +1462,7 @@
                       const char *backing_file, int flags)
 {
     int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
+    int ref_clusters;
     QCowHeader header;
     uint64_t tmp, offset;
     QCowCreateState s1, *s = &s1;
@@ -1502,22 +1503,28 @@
     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));
@@ -1533,7 +1540,7 @@
     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);





reply via email to

[Prev in Thread] Current Thread [Next in Thread]