From patchwork Wed Feb 6 10:58:35 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 218549 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 771D02C02C1 for ; Wed, 6 Feb 2013 21:59:28 +1100 (EST) Received: from localhost ([::1]:56176 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U32is-0006JI-Pf for incoming@patchwork.ozlabs.org; Wed, 06 Feb 2013 05:59:26 -0500 Received: from eggs.gnu.org ([208.118.235.92]:55556) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U32iK-0004sc-Dd for qemu-devel@nongnu.org; Wed, 06 Feb 2013 05:59:17 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1U32iG-0002fA-9e for qemu-devel@nongnu.org; Wed, 06 Feb 2013 05:58:52 -0500 Received: from mx1.redhat.com ([209.132.183.28]:26139) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U32iG-0002f5-1N for qemu-devel@nongnu.org; Wed, 06 Feb 2013 05:58:48 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r16Awla7016423 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 6 Feb 2013 05:58:47 -0500 Received: from localhost (ovpn-112-20.ams2.redhat.com [10.36.112.20]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r16Awkl6013699; Wed, 6 Feb 2013 05:58:46 -0500 From: Stefan Hajnoczi To: Date: Wed, 6 Feb 2013 11:58:35 +0100 Message-Id: <1360148318-26988-3-git-send-email-stefanha@redhat.com> In-Reply-To: <1360148318-26988-1-git-send-email-stefanha@redhat.com> References: <1360148318-26988-1-git-send-email-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Kevin Wolf , fsimonce@redhat.com, Stefan Hajnoczi , crobinso@redhat.com Subject: [Qemu-devel] [PATCH v2 2/5] qcow2: record fragmentation statistics during check X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The qemu-img check command can display fragmentation statistics: * Total number of clusters in virtual disk * Number of allocated clusters * Number of fragmented clusters This patch adds fragmentation statistics support to qcow2. Compressed and normal clusters count as allocated. Zero clusters are not counted as allocated unless their L2 entry has a non-zero offset (e.g. preallocation). Only the current L1 table counts towards the statistics - snapshots are ignored. Signed-off-by: Stefan Hajnoczi --- block/qcow2-refcount.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 26583c5..73690f8 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -917,6 +917,7 @@ static void inc_refcounts(BlockDriverState *bs, /* Flags for check_refcounts_l1() and check_refcounts_l2() */ enum { CHECK_OFLAG_COPIED = 0x1, /* check QCOW_OFLAG_COPIED matches refcount */ + CHECK_FRAG_INFO = 0x2, /* update BlockFragInfo counters */ }; /* @@ -932,7 +933,8 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, int flags) { BDRVQcowState *s = bs->opaque; - uint64_t *l2_table, l2_entry; + uint64_t *l2_table, l2_entry, sector_offset; + uint64_t next_contiguous_offset = 0; int i, l2_size, nb_csectors, refcount; /* Read L2 table from disk */ @@ -960,9 +962,23 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, /* Mark cluster as used */ nb_csectors = ((l2_entry >> s->csize_shift) & s->csize_mask) + 1; - l2_entry &= s->cluster_offset_mask; + sector_offset = l2_entry & s->cluster_offset_mask & ~511; inc_refcounts(bs, res, refcount_table, refcount_table_size, - l2_entry & ~511, nb_csectors * 512); + sector_offset, nb_csectors * 512); + + if (flags & CHECK_FRAG_INFO) { + res->bfi.allocated_clusters++; + if (next_contiguous_offset && + sector_offset != next_contiguous_offset) { + res->bfi.fragmented_clusters++; + } + + /* nb_csectors is rounded up, round it down since the next + * cluster starts within our last sector. + */ + next_contiguous_offset = sector_offset + + (nb_csectors - 1) * 512; + } break; case QCOW2_CLUSTER_ZERO: @@ -990,6 +1006,15 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, } } + if (flags & CHECK_FRAG_INFO) { + res->bfi.allocated_clusters++; + if (next_contiguous_offset && + offset != next_contiguous_offset) { + res->bfi.fragmented_clusters++; + } + next_contiguous_offset = offset + s->cluster_size; + } + /* Mark cluster as used */ inc_refcounts(bs, res, refcount_table,refcount_table_size, offset, s->cluster_size); @@ -1125,6 +1150,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, size = bdrv_getlength(bs->file); nb_clusters = size_to_clusters(s, size); + res->bfi.total_clusters = nb_clusters; refcount_table = g_malloc0(nb_clusters * sizeof(uint16_t)); /* header */ @@ -1134,7 +1160,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, /* current L1 table */ ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters, s->l1_table_offset, s->l1_size, - CHECK_OFLAG_COPIED); + CHECK_OFLAG_COPIED | CHECK_FRAG_INFO); if (ret < 0) { goto fail; }