From patchwork Fri Aug 30 07:46:54 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Reitz X-Patchwork-Id: 271159 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 81B8A2C00B1 for ; Fri, 30 Aug 2013 17:49:55 +1000 (EST) Received: from localhost ([::1]:47840 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VFJSr-0008Uf-PB for incoming@patchwork.ozlabs.org; Fri, 30 Aug 2013 03:49:53 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57124) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VFJQY-0005GE-Im for qemu-devel@nongnu.org; Fri, 30 Aug 2013 03:47:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VFJQS-0004Kd-Ep for qemu-devel@nongnu.org; Fri, 30 Aug 2013 03:47:30 -0400 Received: from mx1.redhat.com ([209.132.183.28]:64274) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VFJQS-0004KZ-6Q for qemu-devel@nongnu.org; Fri, 30 Aug 2013 03:47:24 -0400 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 r7U7lMtV000617 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 30 Aug 2013 03:47:23 -0400 Received: from localhost (dhcp-200-247.str.redhat.com [10.33.200.247]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r7U7lKGa001166 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO); Fri, 30 Aug 2013 03:47:21 -0400 From: Max Reitz To: qemu-devel@nongnu.org Date: Fri, 30 Aug 2013 09:46:54 +0200 Message-Id: <1377848818-2623-5-git-send-email-mreitz@redhat.com> In-Reply-To: <1377848818-2623-1-git-send-email-mreitz@redhat.com> References: <1377848818-2623-1-git-send-email-mreitz@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 , Stefan Hajnoczi , Max Reitz Subject: [Qemu-devel] [PATCH v3 4/8] qcow2-refcount: Move OFLAG_COPIED checks 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 Move the OFLAG_COPIED checks out of check_refcounts_l1 and check_refcounts_l2 and after the actual refcount checks/fixes (since the refcounts might actually change there). Signed-off-by: Max Reitz --- block/qcow2-refcount.c | 99 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 34 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 310efcc..fdc0f86 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1035,7 +1035,7 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, BDRVQcowState *s = bs->opaque; uint64_t *l2_table, l2_entry; uint64_t next_contiguous_offset = 0; - int i, l2_size, nb_csectors, refcount; + int i, l2_size, nb_csectors; /* Read L2 table from disk */ l2_size = s->l2_size * sizeof(uint64_t); @@ -1087,23 +1087,8 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, case QCOW2_CLUSTER_NORMAL: { - /* QCOW_OFLAG_COPIED must be set iff refcount == 1 */ uint64_t offset = l2_entry & L2E_OFFSET_MASK; - if (flags & CHECK_OFLAG_COPIED) { - refcount = get_refcount(bs, offset >> s->cluster_bits); - if (refcount < 0) { - fprintf(stderr, "Can't get refcount for offset %" - PRIx64 ": %s\n", l2_entry, strerror(-refcount)); - goto fail; - } - if ((refcount == 1) != ((l2_entry & QCOW_OFLAG_COPIED) != 0)) { - fprintf(stderr, "ERROR OFLAG_COPIED: offset=%" - PRIx64 " refcount=%d\n", l2_entry, refcount); - res->corruptions++; - } - } - if (flags & CHECK_FRAG_INFO) { res->bfi.allocated_clusters++; if (next_contiguous_offset && @@ -1160,7 +1145,7 @@ static int check_refcounts_l1(BlockDriverState *bs, { BDRVQcowState *s = bs->opaque; uint64_t *l1_table, l2_offset, l1_size2; - int i, refcount, ret; + int i, ret; l1_size2 = l1_size * sizeof(uint64_t); @@ -1184,22 +1169,6 @@ static int check_refcounts_l1(BlockDriverState *bs, for(i = 0; i < l1_size; i++) { l2_offset = l1_table[i]; if (l2_offset) { - /* QCOW_OFLAG_COPIED must be set iff refcount == 1 */ - if (flags & CHECK_OFLAG_COPIED) { - refcount = get_refcount(bs, (l2_offset & ~QCOW_OFLAG_COPIED) - >> s->cluster_bits); - if (refcount < 0) { - fprintf(stderr, "Can't get refcount for l2_offset %" - PRIx64 ": %s\n", l2_offset, strerror(-refcount)); - goto fail; - } - if ((refcount == 1) != ((l2_offset & QCOW_OFLAG_COPIED) != 0)) { - fprintf(stderr, "ERROR OFLAG_COPIED: l2_offset=%" PRIx64 - " refcount=%d\n", l2_offset, refcount); - res->corruptions++; - } - } - /* Mark L2 table as used */ l2_offset &= L1E_OFFSET_MASK; inc_refcounts(bs, res, refcount_table, refcount_table_size, @@ -1241,7 +1210,8 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, { BDRVQcowState *s = bs->opaque; int64_t size, i, highest_cluster; - int nb_clusters, refcount1, refcount2; + uint64_t *l2_table = NULL; + int nb_clusters, refcount1, refcount2, j; QCowSnapshot *sn; uint16_t *refcount_table; int ret; @@ -1365,10 +1335,71 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, } } + l2_table = qemu_blockalign(bs, s->cluster_size); + + /* check OFLAG_COPIED */ + for (i = 0; i < s->l1_size; i++) { + uint64_t l1_entry = s->l1_table[i]; + uint64_t l2_offset = l1_entry & L1E_OFFSET_MASK; + int refcount; + + if (!l2_offset) { + continue; + } + + refcount = get_refcount(bs, l2_offset >> s->cluster_bits); + if (refcount < 0) { + /* don't print message nor increment check_errors, since the above + * loop will have done this already */ + continue; + } + if ((refcount == 1) != ((l1_entry & QCOW_OFLAG_COPIED) != 0)) { + fprintf(stderr, "ERROR OFLAG_COPIED L2 cluster: l1_entry=%" PRIx64 + " refcount=%d\n", + l1_entry, refcount); + res->corruptions++; + } + + ret = bdrv_pread(bs->file, l2_offset, l2_table, + s->l2_size * sizeof(uint64_t)); + if (ret < 0) { + fprintf(stderr, "ERROR: Could not read L2 table: %s\n", + strerror(-ret)); + res->check_errors++; + goto fail; + } + + for (j = 0; j < s->l2_size; j++) { + uint64_t l2_entry = be64_to_cpu(l2_table[j]); + uint64_t data_offset; + + if (qcow2_get_cluster_type(l2_entry) != QCOW2_CLUSTER_NORMAL) { + continue; + } + + data_offset = l2_entry & L2E_OFFSET_MASK; + + refcount = get_refcount(bs, data_offset >> s->cluster_bits); + if (refcount < 0) { + /* don't print message nor increment check_errors, since the + * above loop will have done this already */ + continue; + } + if ((refcount == 1) != ((l2_entry & QCOW_OFLAG_COPIED) != 0)) { + fprintf(stderr, "ERROR OFLAG_COPIED data cluster: l2_entry=%" + PRIx64 " refcount=%d\n", + l2_entry, refcount); + res->corruptions++; + } + } + } + + res->image_end_offset = (highest_cluster + 1) * s->cluster_size; ret = 0; fail: + qemu_vfree(l2_table); g_free(refcount_table); return ret;