From patchwork Mon Nov 26 13:05:20 2012 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: 201689 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 D128B2C007C for ; Tue, 27 Nov 2012 00:49:37 +1100 (EST) Received: from localhost ([::1]:39028 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tcz44-0006Jz-43 for incoming@patchwork.ozlabs.org; Mon, 26 Nov 2012 08:49:36 -0500 Received: from eggs.gnu.org ([208.118.235.92]:49324) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TcyP8-0006Om-9H for qemu-devel@nongnu.org; Mon, 26 Nov 2012 08:07:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TcyP2-0005H5-U5 for qemu-devel@nongnu.org; Mon, 26 Nov 2012 08:07:18 -0500 Received: from nodalink.pck.nerim.net ([62.212.105.220]:44878 helo=paradis.irqsave.net) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TcyP2-0005Gr-GZ for qemu-devel@nongnu.org; Mon, 26 Nov 2012 08:07:12 -0500 Received: by paradis.irqsave.net (Postfix, from userid 1002) id 04D08874305; Mon, 26 Nov 2012 14:20:09 +0100 (CET) Received: from localhost.localdomain (unknown [192.168.77.1]) by paradis.irqsave.net (Postfix) with ESMTP id 26BA4874312; Mon, 26 Nov 2012 14:18:15 +0100 (CET) From: =?UTF-8?q?Beno=C3=AEt=20Canet?= To: qemu-devel@nongnu.org Date: Mon, 26 Nov 2012 14:05:20 +0100 Message-Id: <1353935123-24199-22-git-send-email-benoit@irqsave.net> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1353935123-24199-1-git-send-email-benoit@irqsave.net> References: <1353935123-24199-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, =?UTF-8?q?Beno=C3=AEt=20Canet?= , stefanha@redhat.com Subject: [Qemu-devel] [RFC V3 21/24] 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 9b64e37..0cf4ad7 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1057,6 +1057,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 @@ -1070,7 +1107,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; @@ -1126,11 +1164,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; + } } } } @@ -1170,14 +1216,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; } @@ -1187,7 +1234,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; }