From nobody Sun Jan 25 10:15:19 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; arc=pass (i=1 dmarc=pass fromdomain=virtuozzo.com); dmarc=pass(p=quarantine dis=none) header.from=virtuozzo.com ARC-Seal: i=2; a=rsa-sha256; t=1769088822; cv=pass; d=zohomail.com; s=zohoarc; b=fJaKTEQ5pw//BMTBTO6/oxuAH5z5EpGksjOLFh72RyWkdUndSocHLd8J7bCkz3DxphC/0dfbtRYZ4qeHguIyebEZm177s6D7x7ZCyzEoW+Dj1rodr9TY7fJbe8WGrVT/7okCttHHUiIEil6frtpYG1qUV3jqLvahmNaXjzRAcdk= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769088822; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=U+m4+xM+GA0b5+4ScHeqvE9mZXzCFHO17fbJi8JeBgQ=; b=iU/TJQhaUJjSjJ1E2RUvMcwMX05FZPmrF+YhuLaoudnLhQ/+xLnXHzEdDaIPlCfsBQim1QmHnJAhmyHdbozTUvbKE5OTnxYMFuqKG02zSbzgNN/nHCIZYNp45JYVJSjjePRsecaPz0hN/ISBj7ZvO4aEPQYUHCv7MXmSgyaISPc= ARC-Authentication-Results: i=2; 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; arc=pass (i=1 dmarc=pass fromdomain=virtuozzo.com); dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 176908882277274.6287486346639; Thu, 22 Jan 2026 05:33:42 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1viuo8-0005aS-R4; Thu, 22 Jan 2026 08:33:08 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1viuo5-0005Uo-Uq; Thu, 22 Jan 2026 08:33:06 -0500 Received: from mail-swedencentralazlp170130007.outbound.protection.outlook.com ([2a01:111:f403:c202::7] helo=GVXPR05CU001.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1viuo1-0000MA-W2; Thu, 22 Jan 2026 08:33:05 -0500 Received: from DBBPR08MB10697.eurprd08.prod.outlook.com (2603:10a6:10:52a::5) by GV1PR08MB10806.eurprd08.prod.outlook.com (2603:10a6:150:162::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.10; Thu, 22 Jan 2026 13:32:52 +0000 Received: from DBBPR08MB10697.eurprd08.prod.outlook.com ([fe80::2318:7df7:a744:15d2]) by DBBPR08MB10697.eurprd08.prod.outlook.com ([fe80::2318:7df7:a744:15d2%4]) with mapi id 15.20.9542.009; Thu, 22 Jan 2026 13:32:52 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=kEZXIjsf0PlJHk94jxGdKjsPxFKYAfyXpQS4FjSdAEWVjYECpJFe7dE9J1+8HlAd5rP1atN3474WnLJfjA/7tIP5Ruwtw4VbdNp1+JdsVTp5OBA7OGh98adGGKizjCIaJUc2wNWmcT1ObeGN1UfwQ5aNkajFu3MNFdmq05axx9+L50eOFhNlIhI5EC6wtBUBS2C6ajwxDcM5Y1HiPW/bC7shtSocPX23key8MAPFVgF6yt0+IpFie/thVmkhpfO2Ss6B7yUAuB05Nf4ERlUKumX1jM1R/fTrRgWbPQAGA5VRxHwMGIcy5iU9TrpRgNsecg3iYN/LfQsK+3VUw9jlvw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=U+m4+xM+GA0b5+4ScHeqvE9mZXzCFHO17fbJi8JeBgQ=; b=GSdOM2nhORiSkQdPHa4f5GsmVnHO1o3A/uiQoqwXwVOo2kViR4F/QiySBMdBfpIsb4CzSZEFJya1Xx+cVy+X3Y56p39zn6MMsRLMDiZMM4FzBBx1WXnU9G+mmCdWAb+Zrg5VdVpiIWHKEzOIFR4uqCuXwovyjnGc1FQCD0zYHvVbEXWJj3NaIVpYlB66toCoPd/dOlgS5e+edzBnJ/cgK7LEES3vG1usekGANHiAY2fATQK0nvWY6RYy0IMc6bf+rM/AIwjwnxcbzzORhFEBf1ZOWG8DNAMs7FKhnQFOi3ETB6WdKkAVihcmAByic8xIEAQtEgqAI3nxuEoabjwwVw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=virtuozzo.com; dmarc=pass action=none header.from=virtuozzo.com; dkim=pass header.d=virtuozzo.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=virtuozzo.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=U+m4+xM+GA0b5+4ScHeqvE9mZXzCFHO17fbJi8JeBgQ=; b=mMT0r5AXCNf59cEZOG9JUdir624hiwPO0HQ/hzysEkquXJ5R5iMGPLay1JuvgSASxK6Gz3NzMevbX1NU7s8Mzd+PBTk3qtrNVc2QELuu6AifK+VpPzgJFd0MnrvL8YdPxm7ZWUV6Ji6AEV/36Gr50BQRaHdMb8TDTvkp0e2XtUhalS9CbMkEFGIOCPLZuXPl09r6zRPSfkUaVxC/KP9RqSuOxtVMcOGbrHTaAeRqzm1egi3jVlGzmwU5wC5uUJbElJCJdnSQ25pcM1GivqH5qPxWZuM2tHkS/eaRZ+pABpGajQifBZLbucmafEoB/EIOp8XUAhL7fRKSenhWwdKBjQ== From: Polina Vishneva To: "qemu-block@nongnu.org" CC: "qemu-devel@nongnu.org" , Polina Vishneva , John Snow , Vladimir Sementsov-Ogievskiy , Eric Blake , Hanna Reitz , Kevin Wolf , Den Lunev , Andrey Drobyshev Subject: [PATCH v2] block/qcow2-bitmap: remove inconsistent bitmaps when loading Thread-Topic: [PATCH v2] block/qcow2-bitmap: remove inconsistent bitmaps when loading Thread-Index: AQHci6ObvWJLEfkZz0WsXQllbrH0Fg== Date: Thu, 22 Jan 2026 13:32:51 +0000 Message-ID: <20260122133243.64909-1-polina.vishneva@virtuozzo.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=virtuozzo.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: DBBPR08MB10697:EE_|GV1PR08MB10806:EE_ x-ms-office365-filtering-correlation-id: edb0c786-7216-43ba-6e85-08de59babe09 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; ARA:13230040|366016|1800799024|376014|38070700021; x-microsoft-antispam-message-info: =?iso-8859-1?Q?nhCB5mjwRYPGnnXXQXc9JfGiyMv77/hQIHXyqjnEBARZKUoq+VZF51mOIS?= =?iso-8859-1?Q?UXvVClkOrUvE5CJ1XF9ANle7m/+mMOGELCAYL6PJ5Kjmpzq2LKHuFwvdCp?= =?iso-8859-1?Q?PbhykvTAKKWK5KljFtMCNQZ4Vui0yQlAAfXxiZ4QVcY92DGzAoBTsG+9th?= =?iso-8859-1?Q?Y/ifW8AXWosECDMcxAf5vDAkyfKEcILl9pp+yte8QSFQxBiwxx7mTTulf7?= =?iso-8859-1?Q?h95+2UskZo8mzKRs9BO6VHmfViaAnumLHqU/2DNHOHJtEgSE0msLToafP/?= =?iso-8859-1?Q?DQwp4AKy4/skHQWqFUA4JLGeZm7PbhzOn5f5A0jdACXrQCQ6hevx1ypwZN?= =?iso-8859-1?Q?H0Hi6gslScb6PWZmr+mDLzZ0j5ETsfCl4db1mPCy6FcXQllWi/ZBszcYGs?= =?iso-8859-1?Q?SeyZR3J9/+KA6Y+QjHPRvQrtkDXHf8+6ZRRNlBkJd5dgioWVK+h2Dwt4l4?= =?iso-8859-1?Q?PsYHKwMIyj0xEVJPbmc9SZWOsMe3l6munlwWdlTI3LknZrXCpuNmZnFm3G?= =?iso-8859-1?Q?uJs+fpWRag23zfKfs8sETxXXsq0CjP11OiH0qZJKfUQpWeQvoPxzFYCYeX?= =?iso-8859-1?Q?UcM4j77AVRSGbqSJAmKBtiO0RN3g5f5x9PpNzfKWDIYDB/uLJhScp81I9q?= =?iso-8859-1?Q?BVUsSy4r9qkTLhYwxZpSu/58vCBsH/HemNj4NS6biFj7dOtZjJnrWPQWrw?= =?iso-8859-1?Q?tgOgtBGsvZ/spmbSNWX1rb0f4npE2Xy5F6Nyg65P6P/MtM93Vd/dxmJ6Tl?= =?iso-8859-1?Q?/Zy+Ft7qDXc4qpbNBuBh+qS1wyuGU4nhuPyTrZeHO8Q/llxhWm0zoe+wwU?= =?iso-8859-1?Q?C2qM6GouJYKI++CghJcClGpDxA3tdIxAMCqT4JqDRkymAZbiaxCa6FRVXJ?= =?iso-8859-1?Q?2lHSV8qFFbePe6+Rj4Sp34GuqXH4R9j0VUmXiHq6eqiq43fncCuotZdjfm?= =?iso-8859-1?Q?zf40BMbRCK0Fn8mXi5GlewAxjdiqjKllFOYhi+sf3fVHMm7UFCfti+We1z?= =?iso-8859-1?Q?cYmQ0ZH4G1TgRmh5I0Y8Vh21mnlGrZ+LUoQGoYxPqzQV/uklqsOGfMMj5D?= =?iso-8859-1?Q?IXPCu8zqKM0CWFskZuzBJuDJoMyVty79M/Nfz9ABpmTSn5SGcyWCKQUuaV?= =?iso-8859-1?Q?UvcDfOCvmmpV8LC/dkmv/K9lei7LYe8WrOOhPoOLDs8nNLdUiJOWaT9BP+?= =?iso-8859-1?Q?HmjvW+eKx831qFjjTBk9tGfzOnadiXxcE0f9m6k41oWux2TXfV++0qR8+F?= =?iso-8859-1?Q?NzmTkesRIFCGCOLyxoWOmzBfYQgEzAkXCQoG4SAVTBzrvIINBVM5TM3LdU?= =?iso-8859-1?Q?CEiEwY53HDVq7aL9ZZaaW86/vXoItYONsN78CS/H0hxiPqTsnKzUm0xG+V?= =?iso-8859-1?Q?eLImfK3ifwlfqAE380TRdKvmA36ftJMTsn5sEbUXLBhgDjNOe7MtNG74jP?= =?iso-8859-1?Q?V2P3URn+VkP1YWzllulVGP1zkdUc69ftWVY9MrPqxQwMndYJd6yPYuKFxs?= =?iso-8859-1?Q?gQ3jsAGA79MUJcNDJIofZhnQiAQ8KDFo9ArbZVpNeNvPLLAYpn294IOd9E?= =?iso-8859-1?Q?VaZ4b/75M4Hr1jAOX3FHhwKauC66J7Q6vLoUpVWB/70NsKxdBRV+idE8Dh?= =?iso-8859-1?Q?B/MHEWTZ7ufx2LcDn7qLpzCDf78QojTYCnJQEhAGwgC+9GCudC45HoHF18?= =?iso-8859-1?Q?v32cs0oGzWbdO2l7Ubo=3D?= x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:DBBPR08MB10697.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(1800799024)(376014)(38070700021); DIR:OUT; SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?iso-8859-1?Q?Q/Y5tuQpCpjKFaHHGOt96YZhHv7n4UqQxs5ROwIBZiI2pTgKOPNVx5WW/A?= =?iso-8859-1?Q?CakwBLGaI0uhe0B5te8trnPFQuF0P5uqHWdPkbNS8mvKoqzHm5trEfEWdy?= =?iso-8859-1?Q?P4Cse9zucAUCQID3eYWbNvliCZF0aMUWvLiq0eKWME9n0ZeuBiPAkC9Qrr?= =?iso-8859-1?Q?e4iE1gVY2fQ8uaIkUfiD1ODa727fa9PbL9FrkNZ85jvvhHiGUMk0gBop6Z?= =?iso-8859-1?Q?gnaBJXNeWD4XTd73LyBjjP+rVbtEjUXAYrA6KE3KRcIZmFD6EzXD7Nelvj?= =?iso-8859-1?Q?paIMdarz2OPSxHeH1C99UCoNITku4oS5AJKUaTTPb1JBkO0c7qGby+WvXd?= =?iso-8859-1?Q?gIs6yFrIwBKbu9x8wT8pnTzQW16HMmIA/hsr6t/bhAaRyjTd19wpDO5zTB?= =?iso-8859-1?Q?bx0evGXcQhholr38TRyBVFPqp3UTY0Jm98f2DY4g1j9+taSmiKhXatZAyk?= =?iso-8859-1?Q?Bh0TjOoygKuctpIt3mtFY4CIIl23S+PuqksMqBEseD71ZV65HWsxarHRky?= =?iso-8859-1?Q?UG7Osnp0Ig9IzDXne42S23adyJTA+vSO+WHaal0lOtyP6ECb3xnGLNHttR?= =?iso-8859-1?Q?Q6wItrdYt6JaO76SChs+0U1XiIg7v77RdNM1G3S9WoE4SuGjjSTUt882tF?= =?iso-8859-1?Q?GEQZ7N0cL4Hdf+lSqz27Fj/nIU/94es90msRTxVDvs9EkdgePaN5eSuTyz?= =?iso-8859-1?Q?ZMmMQzfV8YWEmYH43KFL7z0CHIxMeJMOni1pItLnQZYQlbERMg2IHXbONr?= =?iso-8859-1?Q?T+KEZ2mXv5Q6qYrzIMWsGvNXcaGFI/6zz9Rj77y8QtolDrRKjQ1hPkf4dZ?= =?iso-8859-1?Q?rcBnGcDwB+pUpo92dtwIKH0/yni3TcEIzyxkkta+IyINwBDwjRhmFv5qyv?= =?iso-8859-1?Q?OcbbR0p+1FsI55mv6XC68CKZRsVvlr0n3LTGG63B/Zehe+4Ji+v4XH7KI9?= =?iso-8859-1?Q?/L9dQW7STyNDXfJWIj1jTvscKOR2pVSpU1rYdtZQ3+bBurpTCIRLvxH3nK?= =?iso-8859-1?Q?xmBKcX65z24LudiwOvtWP+TM5RoN2O+kJ3ggluyS2yx9uHqaqeiNwugEQY?= =?iso-8859-1?Q?LHfL6g34+rtvA8P823xfRXMAdEQC/1aHLvizXTKFvZpB6jYUktsinvK3Lr?= =?iso-8859-1?Q?s2sxLVr0B/w6TbO3pw2Dtvvqlf0L7G/igOq+T7VXzr6rO5XS61Ry8RR304?= =?iso-8859-1?Q?10XFPVbjLVIMlQqBZDdabh+g0tdTdrHpuuxI+fy8NtfnH8wcOj2V5r8pjW?= =?iso-8859-1?Q?LBAl8hW5Av8SaJUyyTwyf6f3rJhFT1J9Mk41MOrA7RVcw0R8Vh8zbncWr/?= =?iso-8859-1?Q?lQwJ+QYZhGjBQUti4LghL+Vlxp5tlPZm8fuKRQhB0hIXFtfkyA6mh3z5rF?= =?iso-8859-1?Q?Z9kdokTQ7Xc9s+irlhJpiDz5t/QY3gOKMKGQKA0T7NDELboyPrA+vI+WeH?= =?iso-8859-1?Q?r22h7PzoBZNOrXTtghYtKTEDWjYbK/IuZu+vdBiOJM5efr5AnX0/EIuAZn?= =?iso-8859-1?Q?lh4BoScyQPvsH7PV+/3tfHMCOKfRIf25cvBVxJp/8jrgp+6b9+Z4z42z9e?= =?iso-8859-1?Q?4rcWVj41WHzLzpxDRf4w2MN/A0xfEgN18YoxeBn1SrK0EZnED/V3A55QGW?= =?iso-8859-1?Q?Djk3PYSAg/N/a1UwEJQRc2l49/7oVl49bjR9qQ7fqnmJBSlZYLVPy9FLRx?= =?iso-8859-1?Q?JHwz7n/g+7bmTZsVhYjf4uirt49+fV5HpVQAzLn6LEutPl2I/benBFQEM+?= =?iso-8859-1?Q?MV9pAVcqJfiBFNC18VGl7T+jldknnRHyl9QwYy/48suDoYjhdZ74gAAEO1?= =?iso-8859-1?Q?d0v3M4MFVA=3D=3D?= Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: DBBPR08MB10697.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: edb0c786-7216-43ba-6e85-08de59babe09 X-MS-Exchange-CrossTenant-originalarrivaltime: 22 Jan 2026 13:32:51.9876 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 0bc7f26d-0264-416e-a6fc-8352af79c58f X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: 9sUUxsQE5wtWLyyVX2C5iy9Wj92k7hIv9WXRQXkuYY+Wb1QNEm/vmooOeP1Jvy8f36AfWX3a+Z1K9lahkCXzsaJ3ipFIZ8jxS69lX5cmjes= X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR08MB10806 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=lists.gnu.org; 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=lists.gnu.org; Received-SPF: pass client-ip=2a01:111:f403:c202::7; envelope-from=polina.vishneva@virtuozzo.com; helo=GVXPR05CU001.outbound.protection.outlook.com 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 @virtuozzo.com) X-ZM-MESSAGEID: 1769088825229158500 Content-Type: text/plain; charset="utf-8" Marking the bitmaps that are found in_use in the image as inconsistent works in the most cases. However, in some cases, like migration, it's critical for bdrv_dirty_bitmap_check() to always pass. Instead of asking the user to manually request the deletion of inconsistent bitmaps, delete them automatically if we can, while respecting the possible edge cases like repairing an image with overlaps. Originally-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Polina Vishneva --- Fixed a small typo. block/qcow2-bitmap.c | 111 ++++++++++++++++-- block/qcow2.c | 9 ++ block/qcow2.h | 2 + tests/qemu-iotests/tests/migrate-bitmaps-test | 2 + tests/qemu-iotests/tests/qemu-img-bitmaps | 2 +- tests/qemu-iotests/tests/qemu-img-bitmaps.out | 36 +++--- .../qemu-iotests/tests/qemu-img-close-errors | 3 +- 7 files changed, 132 insertions(+), 33 deletions(-) diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index 256ec99878..ccc6f731b4 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -30,6 +30,8 @@ #include "block/dirty-bitmap.h" #include "qapi/error.h" #include "qemu/cutils.h" +#include "qemu/log.h" +#include "qemu/error-report.h" =20 #include "qcow2.h" =20 @@ -958,6 +960,48 @@ static void set_readonly_helper(gpointer bitmap, gpoin= ter value) bdrv_dirty_bitmap_set_readonly(bitmap, (bool)value); } =20 +int qcow2_remove_in_use_bitmaps(BlockDriverState *bs) +{ + BDRVQcow2State *s =3D bs->opaque; + Qcow2BitmapList *bm_list; + Qcow2Bitmap *bm, *next; + bool removed_any =3D false; + + if (s->nb_bitmaps =3D=3D 0) { + return 0; + } + + bm_list =3D bitmap_list_load(bs, s->bitmap_directory_offset, + s->bitmap_directory_size, NULL); + if (bm_list =3D=3D NULL) { + return 0; + } + + QSIMPLEQ_FOREACH_SAFE(bm, bm_list, entry, next) { + if (bm->flags & BME_FLAG_IN_USE) { + qemu_log("Removing inconsistent bitmap '%s' at image '%s'\n", + bm->name, bs->filename); + + QSIMPLEQ_REMOVE(bm_list, bm, Qcow2Bitmap, entry); + free_bitmap_clusters(bs, &bm->table); + bitmap_free(bm); + removed_any =3D true; + } + } + + int ret =3D 0; + if (removed_any) { + ret =3D update_ext_header_and_dir(bs, bm_list); + if (ret < 0) { + error_report("Can't update bitmap directory after removing " + "inconsistent bitmaps"); + } + } + + bitmap_list_free(bm_list); + return ret; +} + /* * Return true on success, false on failure. * If header_updated is not NULL then it is set appropriately regardless of @@ -969,9 +1013,9 @@ qcow2_load_dirty_bitmaps(BlockDriverState *bs, { BDRVQcow2State *s =3D bs->opaque; Qcow2BitmapList *bm_list; - Qcow2Bitmap *bm; + Qcow2Bitmap *bm, *next; GSList *created_dirty_bitmaps =3D NULL; - bool needs_update =3D false; + bool needs_update =3D false, removed_persistent_bitmaps =3D false; =20 if (header_updated) { *header_updated =3D false; @@ -988,7 +1032,7 @@ qcow2_load_dirty_bitmaps(BlockDriverState *bs, return false; } =20 - QSIMPLEQ_FOREACH(bm, bm_list, entry) { + QSIMPLEQ_FOREACH_SAFE(bm, bm_list, entry, next) { BdrvDirtyBitmap *bitmap; =20 if ((bm->flags & BME_FLAG_IN_USE) && @@ -1008,6 +1052,32 @@ qcow2_load_dirty_bitmaps(BlockDriverState *bs, continue; } =20 + if ((bm->flags & BME_FLAG_IN_USE) && can_write(bs) && + !(s->flags & BDRV_O_CHECK)) + { + /* + * Remove inconsistent bitmaps. + * This is to avoid errors on migrations, when + * when bdrv_dirty_bitmap_check() could be called on a bitmap + * marked as inconsistent, causing an error and requiring the = user + * to manually request inconsistent bitmap deletion. + * + * In case we have a corrupted image, there's no guarantee that + * update_ext_header_and_dir() will succeed. + * This would render some images impossible to repair. + * Therefore, skip it on the image open if we're in the check = mode + * (and do it later when the image is successfully repaired). + */ + qemu_log("Removing inconsistent bitmap '%s' at image '%s'\n", + bm->name, bs->filename); + + QSIMPLEQ_REMOVE(bm_list, bm, Qcow2Bitmap, entry); + free_bitmap_clusters(bs, &bm->table); + bitmap_free(bm); + removed_persistent_bitmaps =3D true; + continue; + } + bitmap =3D load_bitmap(bs, bm, errp); if (bitmap =3D=3D NULL) { goto fail; @@ -1015,6 +1085,7 @@ qcow2_load_dirty_bitmaps(BlockDriverState *bs, =20 bdrv_dirty_bitmap_set_persistence(bitmap, true); if (bm->flags & BME_FLAG_IN_USE) { + /* Reached in check mode or readonly mode */ bdrv_dirty_bitmap_set_inconsistent(bitmap); } else { /* NB: updated flags only get written if can_write(bs) is true= . */ @@ -1028,15 +1099,31 @@ qcow2_load_dirty_bitmaps(BlockDriverState *bs, g_slist_append(created_dirty_bitmaps, bitmap); } =20 - if (needs_update && can_write(bs)) { - /* in_use flags must be updated */ - int ret =3D update_ext_header_and_dir_in_place(bs, bm_list); - if (ret < 0) { - error_setg_errno(errp, -ret, "Can't update bitmap directory"); - goto fail; - } - if (header_updated) { - *header_updated =3D true; + if (can_write(bs)) { + if (removed_persistent_bitmaps) { + /* + * Bitmaps must be removed + * (possibly along with updating in_use flags) + */ + int ret =3D update_ext_header_and_dir(bs, bm_list); + if (ret < 0) { + error_setg_errno(errp, -ret, "Can't update bitmap director= y " + "after removing inconsistent bitmaps"); + goto fail; + } + if (header_updated) { + *header_updated =3D true; + } + } else if (needs_update) { + /* Only in_use flags must be updated */ + int ret =3D update_ext_header_and_dir_in_place(bs, bm_list); + if (ret < 0) { + error_setg_errno(errp, -ret, "Can't update bitmap director= y"); + goto fail; + } + if (header_updated) { + *header_updated =3D true; + } } } =20 diff --git a/block/qcow2.c b/block/qcow2.c index e29810d86a..eb6da74d34 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -634,6 +634,15 @@ qcow2_co_check_locked(BlockDriverState *bs, BdrvCheckR= esult *result, } =20 if (fix && result->check_errors =3D=3D 0 && result->corruptions =3D=3D= 0) { + /* + * Run the removal of inconsistent bitmaps that we've skipped on + * qcow2_load_dirty_bitmaps(). + */ + ret =3D qcow2_remove_in_use_bitmaps(bs); + if (ret < 0) { + return ret; + } + ret =3D qcow2_mark_clean(bs); if (ret < 0) { return ret; diff --git a/block/qcow2.h b/block/qcow2.h index 96db7c51ec..542630bfbd 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -1039,6 +1039,8 @@ bool coroutine_fn GRAPH_RDLOCK qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated, Error **errp); =20 +int GRAPH_RDLOCK qcow2_remove_in_use_bitmaps(BlockDriverState *bs); + bool GRAPH_RDLOCK qcow2_get_bitmap_info_list(BlockDriverState *bs, Qcow2BitmapInfoList **info_list, Error **errp); diff --git a/tests/qemu-iotests/tests/migrate-bitmaps-test b/tests/qemu-iot= ests/tests/migrate-bitmaps-test index 8fb4099201..dc69bb9433 100755 --- a/tests/qemu-iotests/tests/migrate-bitmaps-test +++ b/tests/qemu-iotests/tests/migrate-bitmaps-test @@ -197,6 +197,8 @@ class TestDirtyBitmapMigration(iotests.QMPTestCase): log =3D self.vm_b.get_log() log =3D re.sub(r'^\[I \d+\.\d+\] OPENED\n', '', log) log =3D re.sub(r'\[I \+\d+\.\d+\] CLOSED\n?$', '', log) + if persistent and shared_storage and pre_shutdown: + log =3D re.sub(r'Removed inconsistent bitmap.*\n', '', log) self.assertEqual(log, '') =20 # recreate vm_b, as we don't want -incoming option (this will = lead diff --git a/tests/qemu-iotests/tests/qemu-img-bitmaps b/tests/qemu-iotests= /tests/qemu-img-bitmaps index 7a3fe8c3d3..90743d4eb9 100755 --- a/tests/qemu-iotests/tests/qemu-img-bitmaps +++ b/tests/qemu-iotests/tests/qemu-img-bitmaps @@ -137,7 +137,7 @@ echo =20 # Prepare image with corrupted bitmap $QEMU_IO -c abort "$TEST_IMG" 2>/dev/null -$QEMU_IMG bitmap --add "$TEST_IMG" b4 +$QEMU_IMG bitmap --add "$TEST_IMG" b4 2>&1 | _filter_testdir $QEMU_IMG bitmap --remove "$TEST_IMG" b1 _img_info --format-specific | _filter_irrelevant_img_info # Proof that we fail fast if bitmaps can't be copied diff --git a/tests/qemu-iotests/tests/qemu-img-bitmaps.out b/tests/qemu-iot= ests/tests/qemu-img-bitmaps.out index 74b81f703b..8062ae1114 100644 --- a/tests/qemu-iotests/tests/qemu-img-bitmaps.out +++ b/tests/qemu-iotests/tests/qemu-img-bitmaps.out @@ -118,6 +118,10 @@ Format specific information: =20 =3D=3D=3D Check handling of inconsistent bitmap =3D=3D=3D =20 +Removing inconsistent bitmap 'b1' at image 'TEST_DIR/t.qcow2' +Removing inconsistent bitmap 'b2' at image 'TEST_DIR/t.qcow2' +Removing inconsistent bitmap 'b0' at image 'TEST_DIR/t.qcow2' +qemu-img: Operation remove on bitmap b1 failed: Dirty bitmap 'b1' not found image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 10 MiB (10485760 bytes) @@ -127,29 +131,13 @@ backing file format: IMGFMT Format specific information: bitmaps: [0]: - flags: - [0]: in-use - [1]: auto - name: b2 - granularity: 65536 - [1]: - flags: - [0]: in-use - name: b0 - granularity: 65536 - [2]: flags: [0]: auto name: b4 granularity: 65536 corrupt: false =20 -qemu-img: Cannot copy inconsistent bitmap 'b0' -Try --skip-broken-bitmaps, or use 'qemu-img bitmap --remove' to delete it -qemu-img: Could not open 'TEST_DIR/t.IMGFMT.copy': Could not open 'TEST_DI= R/t.IMGFMT.copy': No such file or directory - -qemu-img: warning: Skipping inconsistent bitmap 'b0' -qemu-img: warning: Skipping inconsistent bitmap 'b2' +unexpected success image: TEST_DIR/t.IMGFMT.copy file format: IMGFMT virtual size: 10 MiB (10485760 bytes) @@ -174,10 +162,20 @@ Format specific information: [0]: auto name: b4 granularity: 65536 - [1]: + corrupt: false + +qemu-img: Operation remove on bitmap b0 failed: Dirty bitmap 'b0' not found +qemu-img: Operation remove on bitmap b2 failed: Dirty bitmap 'b2' not found +image: TEST_DIR/t.IMGFMT.copy +file format: IMGFMT +virtual size: 10 MiB (10485760 bytes) +cluster_size: 65536 +Format specific information: + bitmaps: + [0]: flags: [0]: auto - name: b2 + name: b4 granularity: 65536 corrupt: false *** done diff --git a/tests/qemu-iotests/tests/qemu-img-close-errors b/tests/qemu-io= tests/tests/qemu-img-close-errors index 50bfb6cfa2..d72567171d 100755 --- a/tests/qemu-iotests/tests/qemu-img-close-errors +++ b/tests/qemu-iotests/tests/qemu-img-close-errors @@ -81,7 +81,8 @@ for max_bitmap in 6 7; do $QEMU_IMG commit -d "$TEST_IMG" 2>&1 | _filter_generated_node_ids echo "qemu-img commit exit code: ${PIPESTATUS[0]}" =20 - $QEMU_IMG bitmap --add "$BASE_JSON" "good-bitmap" + $QEMU_IMG bitmap --add "$BASE_JSON" "good-bitmap" 2>&1 | \ + sed '/^Removing inconsistent bitmap.*/d' echo "qemu-img bitmap --add exit code: $?" =20 $QEMU_IMG bitmap --merge "good-bitmap" -b "$TEST_IMG" "$BASE_JSON" \ --=20 2.52.0