From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LqWL6-0002iX-TT for qemu-devel@nongnu.org; Sun, 05 Apr 2009 13:41:00 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LqWL6-0002hl-7I for qemu-devel@nongnu.org; Sun, 05 Apr 2009 13:41:00 -0400 Received: from [199.232.76.173] (port=34527 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LqWL6-0002hg-3K for qemu-devel@nongnu.org; Sun, 05 Apr 2009 13:41:00 -0400 Received: from savannah.gnu.org ([199.232.41.3]:40639 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LqWL5-00048j-PZ for qemu-devel@nongnu.org; Sun, 05 Apr 2009 13:40:59 -0400 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1LqWL5-0006BJ-91 for qemu-devel@nongnu.org; Sun, 05 Apr 2009 17:40:59 +0000 Received: from aliguori by cvs.savannah.gnu.org with local (Exim 4.69) (envelope-from ) id 1LqWL5-0006BF-1e for qemu-devel@nongnu.org; Sun, 05 Apr 2009 17:40:59 +0000 MIME-Version: 1.0 Errors-To: aliguori Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Anthony Liguori Message-Id: Date: Sun, 05 Apr 2009 17:40:59 +0000 Subject: [Qemu-devel] [6982] qcow2: fix image creation for large, > ~2TB, images (Chris Wright) Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Revision: 6982 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=6982 Author: aliguori Date: 2009-04-05 17:40:58 +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 Signed-off-by: Anthony Liguori Modified Paths: -------------- trunk/block-qcow2.c Modified: trunk/block-qcow2.c =================================================================== --- trunk/block-qcow2.c 2009-04-05 17:40:55 UTC (rev 6981) +++ trunk/block-qcow2.c 2009-04-05 17:40:58 UTC (rev 6982) @@ -1555,7 +1555,7 @@ { 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; uint64_t tmp, offset; QCowCreateState s1, *s = &s1; @@ -1604,22 +1604,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)); @@ -1648,7 +1654,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);