From nobody Sat May 30 17:47:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=dupond.be ARC-Seal: i=1; a=rsa-sha256; t=1779355226; cv=none; d=zohomail.com; s=zohoarc; b=ksrA7O118hc+aVPgVat3BnLHqQeTXnkiJpjE1szTsZzxdjo5sVrj6uWdL019ebEjYfiB7ZTsFJB+nNtEhh+fOUzYXZ6sk31nnQqZ9RNv6w0SmSsAWYbzNDk51+ILDCflHQfQZuVVSLxn8d46fMbye1A7ppIc6h4CjrRgQ9IcS3s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779355226; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=/UZueQwEKSVCC9z0Ta2yndbxsEVnuw3VEoY91/2Rqek=; b=MyMx5lh4nq2dWdbwkKc5MkBSUVY/SVFUAQkpKx4OHf6dXt64Quusl9okONMtQiY4qFmuUD5cZXHU8omD8xIdP9hfEmglqaDnCmt8941Im0VEBuVfOuW7dHaAAvYRKLRJaWJjzYN5km1iSJNY8uzEhLmqS4sZoOdJbINOzMCJiQ0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177935522615221.660303306938545; Thu, 21 May 2026 02:20:26 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wPzZ3-000706-OU; Thu, 21 May 2026 05:19:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPzZ1-0006zP-TX; Thu, 21 May 2026 05:19:35 -0400 Received: from apollo.dupie.be ([51.159.20.238]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPzYz-00080m-Kr; Thu, 21 May 2026 05:19:35 -0400 Received: from lt-jeanlouis (unknown [IPv6:2a02:a03f:eaf9:5401:5fb3:a398:4351:5e57]) by apollo.dupie.be (Postfix) with ESMTPSA id C27DF1520E41; Thu, 21 May 2026 11:19:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dupond.be; s=dkim; t=1779355169; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/UZueQwEKSVCC9z0Ta2yndbxsEVnuw3VEoY91/2Rqek=; b=S/fxK9zR6LSJ3JDbjqU9JaUoiJP6gjGJE3eS90UHkWrG88eeksTFFn4QTvjrbnvHfbArk8 6rVQEk5g46q/LcrwEkoTTglVfDFtW5enzKWwTpgv0roxZaG8eExg/L/aJP/R9crz0ZC9J/ BV5h8fo2lqvtyUyFJHwomx9REU60wi/m7An9AJiHs7YRzG/4oxHiP+lQarVGtb0p++7gwc rbQPw8shBhoeq6ERrrmtw7x8GsiiUg+WW8HCL3kdh649uWtV0eDmjh4yjwKwNByCtNtt1A fu5IU/F96T4IagIYoo3hyVcrDRwh7dUsa2RUdihi5TvSshkW9WSIcC2UiEqtCg== From: Jean-Louis Dupond To: qemu-devel@nongnu.org Cc: Kevin Wolf , Eric Blake , Vladimir Sementsov-Ogievskiy , John Snow , Hanna Reitz , qemu-block@nongnu.org, Jean-Louis Dupond Subject: [PATCH v2 1/2] qcow2: move qcow2_check_bitmaps_refcounts func Date: Thu, 21 May 2026 11:19:17 +0200 Message-ID: <20260521091918.2366140-2-jean-louis@dupond.be> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521091918.2366140-1-jean-louis@dupond.be> References: <20260521091918.2366140-1-jean-louis@dupond.be> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=51.159.20.238; envelope-from=jean-louis@dupond.be; helo=apollo.dupie.be X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @dupond.be) X-ZM-MESSAGEID: 1779355231494158500 Content-Type: text/plain; charset="utf-8" Move the qcow2_check_bitmaps_refcounts function in order to be able to call update_ext_header_and_dir from this function in the following patch. Signed-off-by: Jean-Louis Dupond --- block/qcow2-bitmap.c | 154 +++++++++++++++++++++---------------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index 256ec99878..b87940bb43 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -652,83 +652,6 @@ fail: return NULL; } =20 -int coroutine_fn -qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, - void **refcount_table, - int64_t *refcount_table_size) -{ - int ret; - BDRVQcow2State *s =3D bs->opaque; - Qcow2BitmapList *bm_list; - Qcow2Bitmap *bm; - - if (s->nb_bitmaps =3D=3D 0) { - return 0; - } - - ret =3D qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_tab= le_size, - s->bitmap_directory_offset, - s->bitmap_directory_size); - if (ret < 0) { - return ret; - } - - bm_list =3D bitmap_list_load(bs, s->bitmap_directory_offset, - s->bitmap_directory_size, NULL); - if (bm_list =3D=3D NULL) { - res->corruptions++; - return -EINVAL; - } - - QSIMPLEQ_FOREACH(bm, bm_list, entry) { - uint64_t *bitmap_table =3D NULL; - int i; - - ret =3D qcow2_inc_refcounts_imrt(bs, res, - refcount_table, refcount_table_size, - bm->table.offset, - bm->table.size * BME_TABLE_ENTRY_SI= ZE); - if (ret < 0) { - goto out; - } - - ret =3D bitmap_table_load(bs, &bm->table, &bitmap_table); - if (ret < 0) { - res->corruptions++; - goto out; - } - - for (i =3D 0; i < bm->table.size; ++i) { - uint64_t entry =3D bitmap_table[i]; - uint64_t offset =3D entry & BME_TABLE_ENTRY_OFFSET_MASK; - - if (check_table_entry(entry, s->cluster_size) < 0) { - res->corruptions++; - continue; - } - - if (offset =3D=3D 0) { - continue; - } - - ret =3D qcow2_inc_refcounts_imrt(bs, res, - refcount_table, refcount_table_= size, - offset, s->cluster_size); - if (ret < 0) { - g_free(bitmap_table); - goto out; - } - } - - g_free(bitmap_table); - } - -out: - bitmap_list_free(bm_list); - - return ret; -} - /* bitmap_list_store * Store bitmap list to qcow2 image as a bitmap directory. * Everything is checked. @@ -1807,3 +1730,80 @@ uint64_t qcow2_get_persistent_dirty_bitmap_size(Bloc= kDriverState *in_bs, =20 return bitmaps_size; } + +int coroutine_fn +qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + void **refcount_table, + int64_t *refcount_table_size) +{ + int ret; + BDRVQcow2State *s =3D bs->opaque; + Qcow2BitmapList *bm_list; + Qcow2Bitmap *bm; + + if (s->nb_bitmaps =3D=3D 0) { + return 0; + } + + ret =3D qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_tab= le_size, + s->bitmap_directory_offset, + s->bitmap_directory_size); + if (ret < 0) { + return ret; + } + + bm_list =3D bitmap_list_load(bs, s->bitmap_directory_offset, + s->bitmap_directory_size, NULL); + if (bm_list =3D=3D NULL) { + res->corruptions++; + return -EINVAL; + } + + QSIMPLEQ_FOREACH(bm, bm_list, entry) { + uint64_t *bitmap_table =3D NULL; + int i; + + ret =3D qcow2_inc_refcounts_imrt(bs, res, + refcount_table, refcount_table_size, + bm->table.offset, + bm->table.size * BME_TABLE_ENTRY_SI= ZE); + if (ret < 0) { + goto out; + } + + ret =3D bitmap_table_load(bs, &bm->table, &bitmap_table); + if (ret < 0) { + res->corruptions++; + goto out; + } + + for (i =3D 0; i < bm->table.size; ++i) { + uint64_t entry =3D bitmap_table[i]; + uint64_t offset =3D entry & BME_TABLE_ENTRY_OFFSET_MASK; + + if (check_table_entry(entry, s->cluster_size) < 0) { + res->corruptions++; + continue; + } + + if (offset =3D=3D 0) { + continue; + } + + ret =3D qcow2_inc_refcounts_imrt(bs, res, + refcount_table, refcount_table_= size, + offset, s->cluster_size); + if (ret < 0) { + g_free(bitmap_table); + goto out; + } + } + + g_free(bitmap_table); + } + +out: + bitmap_list_free(bm_list); + + return ret; +} --=20 2.54.0 From nobody Sat May 30 17:47:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=dupond.be ARC-Seal: i=1; a=rsa-sha256; t=1779355227; cv=none; d=zohomail.com; s=zohoarc; b=jWJN2n5Op+vL63iEl8lf7LgfEM6jWR+F9gJ0TcAoWlV/7xe2HDHMNafc9vFft7j/j6SmLAkQDtwvHhwVRQCJk+2xKiz+E7qUAf9eYTsiqFtWLWZKut78rjsb8qxJxbZV4iQViUbJhAa6sH5sH/pCrwlQphZl0sW2fDynCyzijf4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779355227; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=12SoRCDB1RS02qM88GN7nYgdYvd+VCE11yxavWl8P8g=; b=UhcOm+hkBmrqx7K9+qptziggG7sNLCTtnGeRwsD/9oQCJUa6/s5CAb8/tB1c80C0mdoucfT5yOh5rKGWw8s0f00c9FCpZhJa2Utp26MJKTlDiS3ElzOEj5jRnxUevHYaPtn8h3K362+8LOGW9evccw3vrOCAMHTUJs9wDGUm4Gs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177935522735218.182893239954637; Thu, 21 May 2026 02:20:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wPzZ4-00070o-Db; Thu, 21 May 2026 05:19:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPzZ2-0006zX-5h; Thu, 21 May 2026 05:19:36 -0400 Received: from apollo.dupie.be ([2001:bc8:3f2a:101::1]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wPzYz-00080o-MI; Thu, 21 May 2026 05:19:35 -0400 Received: from lt-jeanlouis (unknown [IPv6:2a02:a03f:eaf9:5401:5fb3:a398:4351:5e57]) by apollo.dupie.be (Postfix) with ESMTPSA id 0DFFD1520E55; Thu, 21 May 2026 11:19:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dupond.be; s=dkim; t=1779355170; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=12SoRCDB1RS02qM88GN7nYgdYvd+VCE11yxavWl8P8g=; b=Wqcx/1sQWBzfEBRoYUV1/Qs2/dfuFLARfRG+BUI6oV5Ab32abwXgqCAfggBTSidNWxfpex 9gzQsV+cd/bpTuTfrLildaFk8YW2jX6OORnieiLJwPPPYJeCKxTxhgsS6dSplG/WTDVsh8 c4c92V8WM5A+hZgbskdNjFOnE87lpr30xsaSewxYGMGRuwSQoC5pJb91yXv1iBDKrNZ16S ZmgAANOfgru567FC0K8iN23vn9NgS1/EQU5mQuLNeYVLPbf16GaFGFXQZNjvxQr4QArxh4 IPKupH1jmymyxa4/J8WtwS0S6mYmf56pk+4F/C+uhhy9LRRqvvHLpdbOkC9Lkg== From: Jean-Louis Dupond To: qemu-devel@nongnu.org Cc: Kevin Wolf , Eric Blake , Vladimir Sementsov-Ogievskiy , John Snow , Hanna Reitz , qemu-block@nongnu.org, Jean-Louis Dupond Subject: [PATCH v2 2/2] qcow2: add functionality to repair bitmaps Date: Thu, 21 May 2026 11:19:18 +0200 Message-ID: <20260521091918.2366140-3-jean-louis@dupond.be> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521091918.2366140-1-jean-louis@dupond.be> References: <20260521091918.2366140-1-jean-louis@dupond.be> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2001:bc8:3f2a:101::1; envelope-from=jean-louis@dupond.be; helo=apollo.dupie.be X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @dupond.be) X-ZM-MESSAGEID: 1779355232701158500 Content-Type: text/plain; charset="utf-8" In some cases, it might happen that bitmaps become corrupt. For example when adding/removing bitmaps on a live image. Of course this should not happen, but in case this happens, the image is corrupt and even cannot be opened anymore. You'll get something like the following: qemu-img: Could not open 'disk.qcow2': Bitmap '' doesn't satisfy the constr= aints So the image becomes useless, and cannot be repaired. This while in fact only (one) bitmap entry is corrupt, and the rest of the data is just intact. This commit adds a way to fix this corruption, by just replacing the bitmap list in the qcow2 image with the valid bitmaps, and dropping the bitmaps that are corrupt. $ qemu-img check disk.qcow2 qemu-img: Check failed: Invalid argument qemu-img: Lost persistent bitmaps during inactivation of node '#block147': = Bitmap '' doesn't satisfy the constraints $ qemu-img check -r all disk.qcow2 qcow2_free_clusters failed: Invalid argument Leaked cluster 3 refcount=3D1 reference=3D0 Leaked cluster 26 refcount=3D1 reference=3D0 ERROR cluster 983214 refcount=3D0 reference=3D1 Rebuilding refcount structure Repairing cluster 1 refcount=3D1 reference=3D0 Repairing cluster 2 refcount=3D1 reference=3D0 Repairing cluster 32768 refcount=3D1 reference=3D0 Repairing cluster 65536 refcount=3D1 reference=3D0 Repairing cluster 98304 refcount=3D1 reference=3D0 Repairing cluster 131072 refcount=3D1 reference=3D0 Repairing cluster 163840 refcount=3D1 reference=3D0 Repairing cluster 196612 refcount=3D1 reference=3D0 Repairing cluster 229377 refcount=3D1 reference=3D0 Repairing cluster 262146 refcount=3D1 reference=3D0 Repairing cluster 294915 refcount=3D1 reference=3D0 Repairing cluster 327684 refcount=3D1 reference=3D0 Repairing cluster 360449 refcount=3D1 reference=3D0 Repairing cluster 393218 refcount=3D1 reference=3D0 Repairing cluster 425987 refcount=3D1 reference=3D0 Repairing cluster 458756 refcount=3D1 reference=3D0 Repairing cluster 491521 refcount=3D1 reference=3D0 Repairing cluster 524289 refcount=3D1 reference=3D0 Repairing cluster 557058 refcount=3D1 reference=3D0 Repairing cluster 589827 refcount=3D1 reference=3D0 Repairing cluster 622596 refcount=3D1 reference=3D0 Repairing cluster 655361 refcount=3D1 reference=3D0 Repairing cluster 688130 refcount=3D1 reference=3D0 Repairing cluster 720899 refcount=3D1 reference=3D0 Repairing cluster 753668 refcount=3D1 reference=3D0 Repairing cluster 786433 refcount=3D1 reference=3D0 Repairing cluster 819202 refcount=3D1 reference=3D0 Repairing cluster 851971 refcount=3D1 reference=3D0 Repairing cluster 884740 refcount=3D1 reference=3D0 Repairing cluster 917505 refcount=3D1 reference=3D0 Repairing cluster 950274 refcount=3D1 reference=3D0 Repairing cluster 983042 refcount=3D1 reference=3D0 Repairing cluster 983214 refcount=3D1 reference=3D0 The following inconsistencies were found and repaired: 2 leaked clusters 3 corruptions Double checking the fixed image now... No errors were found on the image. 983056/1048576 =3D 93.75% allocated, 0.05% fragmented, 0.00% compressed clu= sters Image end offset: 64437878784 And the image is valid again! Worst case you lose all bitmaps, but at least the image and the data itself is useable again. Signed-off-by: Jean-Louis Dupond --- block/qcow2-bitmap.c | 42 +++++++++++++++++++++++++++++++++++++++++- block/qcow2-refcount.c | 3 ++- block/qcow2.c | 15 +++++++++++---- block/qcow2.h | 3 ++- 4 files changed, 56 insertions(+), 7 deletions(-) diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index b87940bb43..bcc9462feb 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -1734,11 +1734,14 @@ uint64_t qcow2_get_persistent_dirty_bitmap_size(Blo= ckDriverState *in_bs, int coroutine_fn qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, void **refcount_table, - int64_t *refcount_table_size) + int64_t *refcount_table_size, + BdrvCheckMode fix) { int ret; BDRVQcow2State *s =3D bs->opaque; Qcow2BitmapList *bm_list; + Qcow2BitmapList *fixed_list =3D NULL; + int valid_bitmaps =3D 0; Qcow2Bitmap *bm; =20 if (s->nb_bitmaps =3D=3D 0) { @@ -1752,16 +1755,29 @@ qcow2_check_bitmaps_refcounts(BlockDriverState *bs,= BdrvCheckResult *res, return ret; } =20 + if (fix & BDRV_FIX_ERRORS) { + fixed_list =3D bitmap_list_new(); + } + bm_list =3D bitmap_list_load(bs, s->bitmap_directory_offset, s->bitmap_directory_size, NULL); if (bm_list =3D=3D NULL) { res->corruptions++; + + if (fix & BDRV_FIX_ERRORS) { + ret =3D update_ext_header_and_dir(bs, fixed_list); + if (ret >=3D 0) { + res->corruptions_fixed++; + } + goto out; + } return -EINVAL; } =20 QSIMPLEQ_FOREACH(bm, bm_list, entry) { uint64_t *bitmap_table =3D NULL; int i; + bool bitmap_valid =3D true; =20 ret =3D qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_table_size, @@ -1774,6 +1790,9 @@ qcow2_check_bitmaps_refcounts(BlockDriverState *bs, B= drvCheckResult *res, ret =3D bitmap_table_load(bs, &bm->table, &bitmap_table); if (ret < 0) { res->corruptions++; + if (fix & BDRV_FIX_ERRORS) { + continue; + } goto out; } =20 @@ -1783,6 +1802,7 @@ qcow2_check_bitmaps_refcounts(BlockDriverState *bs, B= drvCheckResult *res, =20 if (check_table_entry(entry, s->cluster_size) < 0) { res->corruptions++; + bitmap_valid =3D false; continue; } =20 @@ -1799,10 +1819,30 @@ qcow2_check_bitmaps_refcounts(BlockDriverState *bs,= BdrvCheckResult *res, } } =20 + if ((fix & BDRV_FIX_ERRORS) && bitmap_valid) { + valid_bitmaps++; + Qcow2Bitmap *bm_copy =3D g_new0(Qcow2Bitmap, 1); + *bm_copy =3D *bm; + bm_copy->name =3D g_strdup(bm->name); + QSIMPLEQ_INSERT_TAIL(fixed_list, bm_copy, entry); + } + g_free(bitmap_table); } =20 + /* If fixing, update the bitmap directory with the repaired list */ + if ((fix & BDRV_FIX_ERRORS) && s->nb_bitmaps !=3D valid_bitmaps) { + ret =3D update_ext_header_and_dir(bs, fixed_list); + if (ret >=3D 0) { + res->corruptions_fixed +=3D s->nb_bitmaps - valid_bitmaps; + } + } + out: + if (fix & BDRV_FIX_ERRORS) { + bitmap_list_free(fixed_list); + } + bitmap_list_free(bm_list); =20 return ret; diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 6512cda407..df7f6d2f23 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -2305,7 +2305,8 @@ calculate_refcounts(BlockDriverState *bs, BdrvCheckRe= sult *res, } =20 /* bitmaps */ - ret =3D qcow2_check_bitmaps_refcounts(bs, res, refcount_table, nb_clus= ters); + ret =3D qcow2_check_bitmaps_refcounts(bs, res, refcount_table, + nb_clusters, fix); if (ret < 0) { return ret; } diff --git a/block/qcow2.c b/block/qcow2.c index 81fd299b4c..dfb6b23932 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1927,11 +1927,18 @@ qcow2_do_open(BlockDriverState *bs, QDict *options,= int flags, if (!(bdrv_get_flags(bs) & BDRV_O_INACTIVE)) { /* It's case 1, 2 or 3.2. Or 3.1 which is BUG in management layer.= */ bool header_updated; - if (!qcow2_load_dirty_bitmaps(bs, &header_updated, errp)) { - ret =3D -EINVAL; - goto fail; + Error *local_err =3D NULL; + if (!qcow2_load_dirty_bitmaps(bs, &header_updated, &local_err)) { + /* Allow this to fail in check mode + * because otherwise we can't open the image at all. + */ + if (!(flags & BDRV_O_CHECK)) { + ret =3D -EINVAL; + error_propagate(errp, local_err); + goto fail; + } + error_free(local_err); } - update_header =3D update_header && !header_updated; } =20 diff --git a/block/qcow2.h b/block/qcow2.h index 192a45d596..2d9c6929a7 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -1034,7 +1034,8 @@ void qcow2_cache_discard(Qcow2Cache *c, void *table); int coroutine_fn GRAPH_RDLOCK qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, void **refcount_table, - int64_t *refcount_table_size); + int64_t *refcount_table_size, + BdrvCheckMode fix); =20 bool coroutine_fn GRAPH_RDLOCK qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated, --=20 2.54.0