From patchwork Tue Sep 15 10:30:43 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 33635 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by bilbo.ozlabs.org (Postfix) with ESMTPS id 029A4B7BC6 for ; Tue, 15 Sep 2009 20:32:48 +1000 (EST) Received: from localhost ([127.0.0.1]:39500 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MnVL3-00010J-48 for incoming@patchwork.ozlabs.org; Tue, 15 Sep 2009 06:32:45 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MnVKG-0000zD-3G for qemu-devel@nongnu.org; Tue, 15 Sep 2009 06:31:56 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MnVKB-0000xk-UB for qemu-devel@nongnu.org; Tue, 15 Sep 2009 06:31:55 -0400 Received: from [199.232.76.173] (port=49691 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MnVKB-0000xZ-BZ for qemu-devel@nongnu.org; Tue, 15 Sep 2009 06:31:51 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37399) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MnVKA-0002wl-Eo for qemu-devel@nongnu.org; Tue, 15 Sep 2009 06:31:50 -0400 Received: from int-mx05.intmail.prod.int.phx2.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.18]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id n8FAVmWg025625 for ; Tue, 15 Sep 2009 06:31:48 -0400 Received: from localhost.localdomain (dhcp-5-175.str.redhat.com [10.32.5.175]) by int-mx05.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id n8FAVlMb004486; Tue, 15 Sep 2009 06:31:48 -0400 From: Kevin Wolf To: qemu-devel@nongnu.org Date: Tue, 15 Sep 2009 12:30:43 +0200 Message-Id: <1253010643-12696-1-git-send-email-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.18 X-detected-operating-system: by monty-python.gnu.org: Genre and OS details not recognized. Cc: Kevin Wolf Subject: [Qemu-devel] [PATCH] qcow2: Increase maximum cluster size to 2 MB X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch increases the maximum qcow2 cluster size to 2 MB. Starting with 128k clusters, L2 tables span 2 GB or more of virtual disk space, causing 32 bit truncation and wraparound of signed integers. Therefore some variables need to use a larger data type. While being at reviewing data types, change some integers that are used for array indices to unsigned. In some places they were checked against some upper limit but not for negative values. This could avoid potential segfaults with corrupted qcow2 images. Signed-off-by: Kevin Wolf --- block/qcow2-cluster.c | 14 ++++++++------ block/qcow2-refcount.c | 3 ++- block/qcow2.h | 2 +- qemu-img.c | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 54e505c..e444e53 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -264,7 +264,7 @@ static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size, return 0; for (i = start; i < start + nb_clusters; i++) - if (offset + i * cluster_size != (be64_to_cpu(l2_table[i]) & ~mask)) + if (offset + (uint64_t) i * cluster_size != (be64_to_cpu(l2_table[i]) & ~mask)) break; return (i - start); @@ -395,10 +395,11 @@ uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, int *num) { BDRVQcowState *s = bs->opaque; - int l1_index, l2_index; + unsigned int l1_index, l2_index; uint64_t l2_offset, *l2_table, cluster_offset; int l1_bits, c; - int index_in_cluster, nb_available, nb_needed, nb_clusters; + unsigned int index_in_cluster, nb_clusters; + uint64_t nb_available, nb_needed; index_in_cluster = (offset >> 9) & (s->cluster_sectors - 1); nb_needed = *num + index_in_cluster; @@ -409,7 +410,7 @@ uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, * the end of the l1 entry */ - nb_available = (1 << l1_bits) - (offset & ((1 << l1_bits) - 1)); + nb_available = (1ULL << l1_bits) - (offset & ((1ULL << l1_bits) - 1)); /* compute the number of available sectors */ @@ -483,8 +484,9 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset, int *new_l2_index) { BDRVQcowState *s = bs->opaque; - int l1_index, l2_index, ret; + unsigned int l1_index, l2_index; uint64_t l2_offset, *l2_table; + int ret; /* seek the the l2 offset in the l1 table */ @@ -683,7 +685,7 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs, BDRVQcowState *s = bs->opaque; int l2_index, ret; uint64_t l2_offset, *l2_table, cluster_offset; - int nb_clusters, i = 0; + unsigned int nb_clusters, i = 0; QCowL2Meta *old_alloc; ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index); diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 0aac2ed..609eee1 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -192,7 +192,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) { BDRVQcowState *s = bs->opaque; int64_t offset, refcount_block_offset; - int ret, refcount_table_index; + unsigned int refcount_table_index; + int ret; uint64_t data64; int cache = cache_refcount_updates; diff --git a/block/qcow2.h b/block/qcow2.h index ecc94cb..26ab5d9 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -47,7 +47,7 @@ #define REFCOUNT_SHIFT 1 /* refcount size is 2 bytes */ #define MIN_CLUSTER_BITS 9 -#define MAX_CLUSTER_BITS 16 +#define MAX_CLUSTER_BITS 21 #define L2_CACHE_SIZE 16 diff --git a/qemu-img.c b/qemu-img.c index 070fe2e..204f618 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -530,7 +530,7 @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum) return v; } -#define IO_BUF_SIZE 65536 +#define IO_BUF_SIZE (2 * 1024 * 1024) static int img_convert(int argc, char **argv) {