From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1M8vu9-0001j8-HA for qemu-devel@nongnu.org; Tue, 26 May 2009 08:37:17 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1M8vu4-0001g2-3P for qemu-devel@nongnu.org; Tue, 26 May 2009 08:37:16 -0400 Received: from [199.232.76.173] (port=39062 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1M8vu3-0001fx-V9 for qemu-devel@nongnu.org; Tue, 26 May 2009 08:37:11 -0400 Received: from mx2.redhat.com ([66.187.237.31]:53237) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1M8vu3-0007Wn-Fh for qemu-devel@nongnu.org; Tue, 26 May 2009 08:37:11 -0400 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n4QCbAxI031149 for ; Tue, 26 May 2009 08:37:10 -0400 From: Kevin Wolf Date: Tue, 26 May 2009 14:36:03 +0200 Message-Id: <1243341363-6507-3-git-send-email-kwolf@redhat.com> In-Reply-To: <1243341363-6507-1-git-send-email-kwolf@redhat.com> References: <1243341363-6507-1-git-send-email-kwolf@redhat.com> Subject: [Qemu-devel] [PATCH 2/2] qcow2: Update multiple refcounts at once List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Kevin Wolf Don't write each single changed refcount block entry to the disk after it is written, but update all entries of the block and write all of them at once. Signed-off-by: Kevin Wolf --- block/qcow2.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 files changed, 36 insertions(+), 4 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 28f7ffe..b6f7003 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2618,6 +2618,9 @@ static int update_refcount(BlockDriverState *bs, { BDRVQcowState *s = bs->opaque; int64_t start, last, cluster_offset; + int64_t refcount_block_offset = 0; + int64_t table_index = -1, old_table_index; + int first_index = -1, last_index = -1; #ifdef DEBUG_ALLOC2 printf("update_refcount: offset=%lld size=%lld addend=%d\n", @@ -2630,10 +2633,25 @@ static int update_refcount(BlockDriverState *bs, for(cluster_offset = start; cluster_offset <= last; cluster_offset += s->cluster_size) { - int64_t refcount_block_offset; int block_index, refcount; int64_t cluster_index = cluster_offset >> s->cluster_bits; + /* Only write refcount block to disk when we are done with it */ + old_table_index = table_index; + table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); + if ((old_table_index >= 0) && (table_index != old_table_index)) { + size_t size = (last_index - first_index + 1) << REFCOUNT_SHIFT; + if (bdrv_pwrite(s->hd, + refcount_block_offset + (first_index << REFCOUNT_SHIFT), + &s->refcount_block_cache[first_index], size) != size) + { + return -EIO; + } + + first_index = -1; + last_index = -1; + } + /* Load the refcount block and allocate it if needed */ refcount_block_offset = alloc_refcount_block(bs, cluster_index); if (refcount_block_offset < 0) { @@ -2643,6 +2661,13 @@ static int update_refcount(BlockDriverState *bs, /* we can update the count and save it */ block_index = cluster_index & ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); + if (first_index == -1 || block_index < first_index) { + first_index = block_index; + } + if (block_index > last_index) { + last_index = block_index; + } + refcount = be16_to_cpu(s->refcount_block_cache[block_index]); refcount += addend; if (refcount < 0 || refcount > 0xffff) @@ -2651,12 +2676,19 @@ static int update_refcount(BlockDriverState *bs, s->free_cluster_index = cluster_index; } s->refcount_block_cache[block_index] = cpu_to_be16(refcount); + } + + /* Write last changed block to disk */ + if (refcount_block_offset != 0) { + size_t size = (last_index - first_index + 1) << REFCOUNT_SHIFT; if (bdrv_pwrite(s->hd, - refcount_block_offset + (block_index << REFCOUNT_SHIFT), - &s->refcount_block_cache[block_index], 2) != 2) + refcount_block_offset + (first_index << REFCOUNT_SHIFT), + &s->refcount_block_cache[first_index], size) != size) + { return -EIO; - + } } + return 0; } -- 1.6.0.6