From nobody Wed Nov 5 13:14:13 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1534508683479801.2160751602268; Fri, 17 Aug 2018 05:24:43 -0700 (PDT) Received: from localhost ([::1]:33498 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqdo2-0005W1-4V for importer@patchew.org; Fri, 17 Aug 2018 08:24:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34837) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqdlw-0004J9-JX for qemu-devel@nongnu.org; Fri, 17 Aug 2018 08:22:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fqdlv-0004W1-LH for qemu-devel@nongnu.org; Fri, 17 Aug 2018 08:22:32 -0400 Received: from relay.sw.ru ([185.231.240.75]:52226) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fqdlv-0004VU-9y; Fri, 17 Aug 2018 08:22:31 -0400 Received: from [10.28.8.145] (helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1fqdls-0006lJ-I4; Fri, 17 Aug 2018 15:22:29 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Fri, 17 Aug 2018 15:22:17 +0300 Message-Id: <20180817122219.16206-6-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180817122219.16206-1-vsementsov@virtuozzo.com> References: <20180817122219.16206-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v2 5/7] block/qcow2-refcount: check_refcounts_l2: split fix_l2_entry_to_zero X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, den@openvz.org, vsementsov@virtuozzo.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Split entry repairing to separate function, to be reused later. Note: entry in in-memory l2 table (local variable in check_refcounts_l2) is not updated after this patch. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/qcow2-refcount.c | 147 ++++++++++++++++++++++++++++++++++++---------= ---- 1 file changed, 109 insertions(+), 38 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 3b057b635d..d9c8cd666b 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1554,6 +1554,99 @@ enum { CHECK_FRAG_INFO =3D 0x2, /* update BlockFragInfo counters */ }; =20 +/* Update entry in L1 or L2 table + * + * Returns: -errno if overlap check failed + * 0 if write failed + * 1 on success + */ +static int write_table_entry(BlockDriverState *bs, const char *table_name, + uint64_t table_offset, int entry_index, + uint64_t new_val, int ign) +{ + int ret; + uint64_t entry_offset =3D + table_offset + (uint64_t)entry_index * sizeof(new_val); + + cpu_to_be64s(&new_val); + ret =3D qcow2_pre_write_overlap_check(bs, ign, entry_offset, sizeof(ne= w_val)); + if (ret < 0) { + fprintf(stderr, + "ERROR: Can't write %s table entry: overlap check failed: = %s\n", + table_name, strerror(-ret)); + return ret; + } + + ret =3D bdrv_pwrite_sync(bs->file, entry_offset, &new_val, sizeof(new_= val)); + if (ret < 0) { + fprintf(stderr, "ERROR: Failed to overwrite %s table entry: %s\n", + table_name, strerror(-ret)); + return 0; + } + + return 1; +} + +/* Try to fix (if allowed) entry in L1 or L2 table. Update @res correspond= ingly. + * + * Returns: -errno if overlap check failed + * 0 if entry was not updated for other reason + * (fixing disabled or write failed) + * 1 on success + */ +static int fix_table_entry(BlockDriverState *bs, BdrvCheckResult *res, + BdrvCheckMode fix, const char *table_name, + uint64_t table_offset, int entry_index, + uint64_t new_val, int ign, + const char *fmt, va_list args) +{ + int ret; + + fprintf(stderr, fix & BDRV_FIX_ERRORS ? "Repairing: " : "ERROR: "); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + + if (!(fix & BDRV_FIX_ERRORS)) { + res->corruptions++; + return 0; + } + + ret =3D write_table_entry(bs, table_name, table_offset, entry_index, n= ew_val, + ign); + + if (ret =3D=3D 1) { + res->corruptions_fixed++; + } else { + res->check_errors++; + } + + return ret; +} + +/* Make L2 entry to be QCOW2_CLUSTER_ZERO_PLAIN + * + * Returns: -errno if overlap check failed + * 0 if write failed + * 1 on success + */ +static int fix_l2_entry_to_zero(BlockDriverState *bs, BdrvCheckResult *res, + BdrvCheckMode fix, int64_t l2_offset, + int l2_index, bool active, + const char *fmt, ...) +{ + int ret; + int ign =3D active ? QCOW2_OL_ACTIVE_L2 : QCOW2_OL_INACTIVE_L2; + uint64_t l2_entry =3D QCOW_OFLAG_ZERO; + va_list args; + + va_start(args, fmt); + ret =3D fix_table_entry(bs, res, fix, "L2", l2_offset, l2_index, l2_en= try, + ign, fmt, args); + va_end(args); + + return ret; +} + /* * Increases the refcount in the given refcount table for the all clusters * referenced in the L2 table. While doing so, performs some checks on L2 @@ -1646,46 +1739,24 @@ static int check_refcounts_l2(BlockDriverState *bs,= BdrvCheckResult *res, if (qcow2_get_cluster_type(l2_entry) =3D=3D QCOW2_CLUSTER_ZERO_ALLOC) { - fprintf(stderr, "%s offset=3D%" PRIx64 ": Preallocated= zero " - "cluster is not properly aligned; L2 entry " - "corrupted.\n", - fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", + ret =3D fix_l2_entry_to_zero( + bs, res, fix, l2_offset, i, active, + "offset=3D%" PRIx64 ": Preallocated zero clust= er is " + "not properly aligned; L2 entry corrupted.", offset); - if (fix & BDRV_FIX_ERRORS) { - uint64_t l2e_offset =3D - l2_offset + (uint64_t)i * sizeof(uint64_t); - int ign =3D active ? QCOW2_OL_ACTIVE_L2 : - QCOW2_OL_INACTIVE_L2; - - l2_entry =3D QCOW_OFLAG_ZERO; - l2_table[i] =3D cpu_to_be64(l2_entry); - ret =3D qcow2_pre_write_overlap_check(bs, ign, - l2e_offset, sizeof(uint64_t)); - if (ret < 0) { - fprintf(stderr, "ERROR: Overlap check failed\n= "); - res->check_errors++; - /* Something is seriously wrong, so abort chec= king - * this L2 table */ - goto fail; - } - - ret =3D bdrv_pwrite_sync(bs->file, l2e_offset, - &l2_table[i], sizeof(uint64= _t)); - if (ret < 0) { - fprintf(stderr, "ERROR: Failed to overwrite L2= " - "table entry: %s\n", strerror(-ret)); - res->check_errors++; - /* Do not abort, continue checking the rest of= this - * L2 table's entries */ - } else { - res->corruptions_fixed++; - /* Skip marking the cluster as used - * (it is unused now) */ - continue; - } - } else { - res->corruptions++; + if (ret < 0) { + /* Something is seriously wrong, so abort checking + * this L2 table */ + goto fail; + } + if (ret =3D=3D 1) { + /* Skip marking the cluster as used + * (it is unused now) */ + continue; } + /* Entry was not updated, but do not abort, mark clust= er + * as used and continue checking the rest of this L2 + * table's entries */ } else { fprintf(stderr, "ERROR offset=3D%" PRIx64 ": Data clus= ter is " "not properly aligned; L2 entry corrupted.\n", off= set); --=20 2.11.1