From patchwork Wed Jan 16 15:48:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Beno=C3=AEt_Canet?= X-Patchwork-Id: 212575 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 2525D2C0086 for ; Thu, 17 Jan 2013 02:51:08 +1100 (EST) Received: from localhost ([::1]:54940 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TvVGc-0006oW-4b for incoming@patchwork.ozlabs.org; Wed, 16 Jan 2013 10:51:06 -0500 Received: from eggs.gnu.org ([208.118.235.92]:59892) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TvVGQ-0006oL-OQ for qemu-devel@nongnu.org; Wed, 16 Jan 2013 10:50:58 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TvVGM-0005bt-RT for qemu-devel@nongnu.org; Wed, 16 Jan 2013 10:50:54 -0500 Received: from nodalink.pck.nerim.net ([62.212.105.220]:42926 helo=paradis.irqsave.net) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TvVGM-0005bC-Dj for qemu-devel@nongnu.org; Wed, 16 Jan 2013 10:50:50 -0500 Received: by paradis.irqsave.net (Postfix, from userid 1002) id 4BCA0874325; Wed, 16 Jan 2013 17:22:26 +0100 (CET) Received: from localhost.localdomain (unknown [192.168.77.1]) by paradis.irqsave.net (Postfix) with ESMTP id 13D81874334; Wed, 16 Jan 2013 17:19:48 +0100 (CET) From: =?UTF-8?q?Beno=C3=AEt=20Canet?= To: qemu-devel@nongnu.org Date: Wed, 16 Jan 2013 16:48:06 +0100 Message-Id: <1358351321-4891-28-git-send-email-benoit@irqsave.net> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1358351321-4891-1-git-send-email-benoit@irqsave.net> References: <1358351321-4891-1-git-send-email-benoit@irqsave.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 62.212.105.220 Cc: kwolf@redhat.com, pbonzini@redhat.com, =?UTF-8?q?Beno=C3=AEt=20Canet?= , stefanha@redhat.com Subject: [Qemu-devel] [RFC V5 27/62] qcow2: Add check_dedup_l2 in order to check l2 of dedup table. 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 Signed-off-by: Benoit Canet --- block/qcow2-refcount.c | 65 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index f7a283a..3077a9f 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1047,6 +1047,43 @@ fail: return -EIO; } +static int check_dedup_l2(BlockDriverState *bs, BdrvCheckResult *res, + int64_t l2_offset) +{ + BDRVQcowState *s = bs->opaque; + uint64_t *l2_table; + int i, l2_size; + + /* Read L2 table from disk */ + l2_size = s->cluster_size; + l2_table = g_malloc(l2_size); + + if (bdrv_pread(bs->file, l2_offset, l2_table, l2_size) != l2_size) { + goto fail; + } + + /* Do the actual checks */ + for (i = 0; i < (s->l2_size - 5); i += 5) { + uint64_t first_logical_offset = be64_to_cpu(l2_table[i + 4]) & + ~QCOW_FLAG_FIRST; + if (first_logical_offset > (bs->total_sectors * BDRV_SECTOR_SIZE)) { + fprintf(stderr, "ERROR: l2 deduplication first_logical_offset" + "=%" PRIi64 " outside of deduplicated volume in l2 table " + "with offset %" PRIi64 ".\n", first_logical_offset, + l2_offset); + res->corruptions++; + } + } + + g_free(l2_table); + return 0; + +fail: + fprintf(stderr, "ERROR: I/O error in check_dedup_l2\n"); + g_free(l2_table); + return -EIO; +} + /* * Increases the refcount for the L1 table, its L2 tables and all referenced * clusters in the given refcount table. While doing so, performs some checks @@ -1060,7 +1097,8 @@ static int check_refcounts_l1(BlockDriverState *bs, uint16_t *refcount_table, int refcount_table_size, int64_t l1_table_offset, int l1_size, - int check_copied) + int check_copied, + bool dedup) { BDRVQcowState *s = bs->opaque; uint64_t *l1_table, l2_offset, l1_size2; @@ -1116,11 +1154,19 @@ static int check_refcounts_l1(BlockDriverState *bs, res->corruptions++; } - /* Process and check L2 entries */ - ret = check_refcounts_l2(bs, res, refcount_table, - refcount_table_size, l2_offset, check_copied); - if (ret < 0) { - goto fail; + if (dedup) { + /* Process and check dedup l2 entries */ + ret = check_dedup_l2(bs, res, l2_offset); + if (ret < 0) { + goto fail; + } + } else { + /* Process and check L2 entries */ + ret = check_refcounts_l2(bs, res, refcount_table, + refcount_table_size, l2_offset, check_copied); + if (ret < 0) { + goto fail; + } } } } @@ -1160,14 +1206,15 @@ 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, 1); + s->l1_table_offset, s->l1_size, 1, false); if (ret < 0) { goto fail; } if (s->has_dedup) { ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters, - s->dedup_table_offset, s->dedup_table_size, 0); + s->dedup_table_offset, s->dedup_table_size, + 0, true); if (ret < 0) { goto fail; } @@ -1177,7 +1224,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, for(i = 0; i < s->nb_snapshots; i++) { sn = s->snapshots + i; ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters, - sn->l1_table_offset, sn->l1_size, 0); + sn->l1_table_offset, sn->l1_size, 0, false); if (ret < 0) { goto fail; }