From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from MI9PR08MB890576.eurprd08.prod.outlook.com (2603:10a6:290:c3::22) by PAXPR08MB6942.eurprd08.prod.outlook.com with HTTPS; Wed, 16 Sep 2026 15:25:10 +0000 Received: from MI1P293CA0010.ITAP293.PROD.OUTLOOK.COM (2603:10a6:290:2::7) by MI9PR08MB890576.eurprd08.prod.outlook.com (2603:10a6:290:c3::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.451.5; Wed, 16 Sep 2026 15:25:04 +0000 Received: from MI3PEPF0000855C.eurprd05.prod.outlook.com (2603:10a6:290:2:cafe::50) by MI1P293CA0010.outlook.office365.com (2603:10a6:290:2::7) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.406.12 via Frontend Transport; Wed, 16 Sep 2026 15:25:04 +0000 Authentication-Results: spf=softfail (sender IP is 99.81.216.78) smtp.mailfrom=openvz.org; dkim=pass (signature was verified) header.d=openvz.org;dmarc=pass action=none header.from=openvz.org;compauth=pass reason=100 Received-SPF: SoftFail (protection.outlook.com: domain of transitioning openvz.org discourages use of 99.81.216.78 as permitted sender) Received: from nat.eu.perception-point.io (99.81.216.78) by MI3PEPF0000855C.mail.protection.outlook.com (10.167.240.24) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Wed, 16 Sep 2026 15:25:01 +0000 X-PERCEPTION-POINT-VERDICT: CLN X-PERCEPTION-POINT-SPF: X-PERCEPTION-POINT-SPAM: PASS X-PERCEPTION-POINT-SENDER-IP: 2a00:1450:4864:31::10 X-PP-Forefront-Antispam-Report: CIP:2a00:1450:4864:31::10;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail-wm2-x10.google.com;PTR:mail-wm2-x10.google.com;CAT:NONE;SFS:(13230040)(82310400026)(6059299003)(2092899012)(12012899012)(43022699015)(3072899012)(19002099009)(6133799003)(10067099003)(5063699009)(5023799004)(55112099003)(22082099003)(18002099003)(57112099003)(3023799007)(16102099003);DIR:INB; Received: from DUZPR08CU001.outbound.protection.outlook.com (mail-duzpr08cu00107.outbound.protection.outlook.com [40.93.64.71]) by inbound-smtp.eu-west-1.amazonaws.com with SMTP id fi24qi4rn1lvfdcm4n2l00b7dq7h6dhf0hgv3jo1; Wed, 16 Sep 2026 15:24:59 +0000 (UTC) X-SES-Spam-Verdict: PASS X-SES-Virus-Verdict: PASS Received-SPF: softfail (spfCheck: transitioning domain of openvz.org does not designate 40.93.64.71 as permitted sender) client-ip=40.93.64.71; envelope-from=den@openvz.org; helo=DUZPR08CU001.outbound.protection.outlook.com; Authentication-Results-Original: amazonses.com; spf=softfail (spfCheck: transitioning domain of openvz.org does not designate 40.93.64.71 as permitted sender) client-ip=40.93.64.71; envelope-from=den@openvz.org; helo=DUZPR08CU001.outbound.protection.outlook.com; dkim=pass header.i=@openvz.org; dmarc=pass header.from=openvz.org; X-SES-RECEIPT: AEFBQUFBQUFBQUFFUnFpaUtNeG5jOW1LMWRqRHFpbmZ3VklrMStoanZuNXJuZ0wvVEZzTi9lQmZmNGhPRzhlc1hLSnhVSUxNMmt3Ky9TOXFlZXFXK0dWaWdkMDI0WW9Za2Yzd2NGQ1N5S3lmdHBpMXVQQVFqUEF1Z3UrRGIvd0dQaC9iN3ZpQmFoTVpQdW8xck9xTjV1eUtBK1NvTkxmemZPL0JOLzZBVnhxTlBxTXhKeGUrZTlYT3poM0VOak5wWHJTRUltZmFmRmRja3BEYXRQcWhqTHFPOEhmVnhXVGJpVVhVK01QZ1Y2U1JoWGh4TjRlQXZXY3ZxdTlLSzczalR5Rm5zWGlFdDFKVGF5MGVGeHFQODdyQ2tJZVVlbUpVYklseE15Rno0UzFrYTZlL2NONitBa3c9PQ== X-SES-DKIM-SIGNATURE: a=rsa-sha256; q=dns/txt; b=VMDOogDgzlzXttcOz+MM+Di9ZsIJa/qK1fOCQVRFCwk87DV+HjR+oVUoOgMW741IEMXpqkUd0gjJ4V5tkDDdl3kH+MC+iseWC5gD3GMBzcjmvvIiIKfYQLVw8KL9W3iJTwYDwTOLsVUwjyFjrjlHtBIOseBE21J7qo9ExVcmG6I=; c=relaxed/simple; s=shh3fegwg5fppqsuzphvschd53n6ihuv; d=amazonses.com; t=1789572299; v=1; bh=tLd6OgWk0F+e1mY41i8tKD7aHvif6TUKKyTxdTRZhSc=; h=From:To:Cc:Bcc:Subject:Date:Message-ID:MIME-Version:Content-Type:X-SES-RECEIPT; Received: from AS8PR04CA0141.eurprd04.prod.outlook.com (2603:10a6:20b:127::26) by GV2PR08MB11492.eurprd08.prod.outlook.com (2603:10a6:150:2a5::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.9; Wed, 16 Sep 2026 15:24:51 +0000 Received: from AMS1EPF0000009B.eurprd02.prod.outlook.com (2603:10a6:20b:127:cafe::61) by AS8PR04CA0141.outlook.office365.com (2603:10a6:20b:127::26) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.428.11 via Frontend Transport; Wed, 16 Sep 2026 15:24:51 +0000 Authentication-Results-Original: spf=pass (sender IP is 2a00:1450:4864:31::10) smtp.mailfrom=openvz.org; dkim=pass (signature was verified) header.d=openvz.org;dmarc=pass action=none header.from=openvz.org;compauth=pass reason=100 Received-SPF: Pass (protection.outlook.com: domain of openvz.org designates 2a00:1450:4864:31::10 as permitted sender) receiver=protection.outlook.com; client-ip=2a00:1450:4864:31::10; helo=mail-wm2-x10.google.com; pr=C Received: from mail-wm2-x10.google.com (2a00:1450:4864:31::10) by AMS1EPF0000009B.mail.protection.outlook.com (2603:10a6:20f:fff8::208) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Wed, 16 Sep 2026 15:24:50 +0000 Received: by mail-wm2-x10.google.com with SMTP id 5b1f17b1804b1-49cd4ba9f68so13700455e9.1 for ; Wed, 16 Sep 2026 08:24:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvz.org; s=google; t=1789572290; x=1790177090; darn=virtuozzo.com; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=v00jIQhbM8/XZvr7Z+pn63xvWgZQ9bcJ7eFV5TAz1RA=; b=r26BpsR87FlJ6JdsZrOd7fKhGDvzd0k8nKjche5LlK1m+91aOSr7psv4ETjQJRF8KP xkERVpCmp2gi/+ez6hWEwXQL5AQCOU8lAlsaW0SP1I+z3GMyGuz8hYMIBBG9DR0iP302 ONHqBQtEiuP/l8g+cjkXnXijSUwQdS+pvX76TJKG9woCo7LetAMZgeOWxOUznK9WYatD n0O7Gdjt0+tv7MN+YfRZrtdu2ZR6UGz2+jweOfNZZkVmv9tO+DDrTaNVY7yNK9hwYpEQ 7fzGslDFsMKQrprzWbZMW4oqzvNupxJWyaMEpVTeolH19Zq2k55yAwAm72UcefX+4/nu 7o/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789572290; x=1790177090; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=v00jIQhbM8/XZvr7Z+pn63xvWgZQ9bcJ7eFV5TAz1RA=; b=VfiZNLSiEp0o65wO9RWKgE0DIz/Ai4HgYSBaBb0EvxR0bGqGJZdbFM3ioNFR1//IPl ZHWLUs7YmeIT46RDPbeedBh/bvpUTJianAw4863IPXygDrjb1bruPZnp8iYDrX09grmH ybnBjMvLF/fihh8tTbfyRCGYYMEYxCZjH8BssuelZlfczkPTkdTcrG40fn25GILbvMYr W1JBgm2OSoNCAR2rw5lE8LGTm907oag9ROVEelF/itO81SOld4L+fYas8p61J3bs120h 2RhdVrlJjpI2X4/NqjJGi43ULnir4hqdloIWHFTy5dwpEpOcIuZadCyGc/wYPbLMAxKx JVTw== X-Gm-Message-State: AFuF++kuMeRJ4i9+XYTk5x5GB+3hv1uEuQ93exCgxRRfkYD5MBqTaMxQ Es8rFCafcy/rBRAt9CRZJE+0WaSVguDlzVH0s7TyxN+sJ0ly2XALFpsYA+VlrprsFPKh1RIAk4J NNnOBdJE= X-Gm-Gg: AYBFou3SQnNuf6RuU/yMUaFchi/pTf/HikA4YcHm8gTJza+3oohvTE3p3DzyCSkI7uE 9t1bvMjdf2eq18xQ5o7f/WRs5K3z/Vyovp16fNQ7SmJTuoQvcHiAQoii3TDC5vhMBaDGUvq1i4d a9LlmhnhtesvkZB2kdpnB8jb+xWRZZjyAMEwR10W8NTnAzaRovCboP/qqPq4mQ4ZTBz9nRE1cUi mJb10rbxiuTI4FqHBPaEWYlL79XolKDRTMlm//dRgh/Uou9L1/HymE1I/q2EvHwBiTNLc7AE1Z5 wQvqixfii1MM3pJ2ACAH2I/AYzLKqbnXMsNikUU5zl8ouVho4CE5pjg48MOOcZBOwY3o5qCdiWq I7e9D96EJQWmADosL4cy8ROoNyP0xHgnTv7CrkQXcoJidPWEYEmu2drUBQoRZ79Hy+4LFPS1OtZ bOaWWa2P8d259V0Hm1FQxERolZb9KGxyM9eqzaLi0dmj5vCqkJirYODypfTGnkwH7Fn7jd X-Received: by 2002:a05:600c:190e:b0:49c:f4ff:e872 with SMTP id 5b1f17b1804b1-49eb7314d54mr35379475e9.5.1789572290351; Wed, 16 Sep 2026 08:24:50 -0700 (PDT) Return-Path: den@openvz.org Received: from athena.sw.ru ([2a06:5b06:b600:300:f56f:c51e:c53f:b1ce]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49fbd0c39dcsm1836415e9.12.2026.09.16.08.24.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Sep 2026 08:24:49 -0700 (PDT) From: "Denis V. Lunev" To: svt-core@virtuozzo.com Cc: andrey.drobyshev@virtuozzo.com, den@openvz.org Subject: [PATCH hci-8.0 5/5] qcow2: repair a dirty image when it becomes writable #VSTOR-140073 Date: Wed, 16 Sep 2026 17:24:37 +0200 Message-ID: <20260916152437.1787889-6-den@openvz.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260916152437.1787889-1-den@openvz.org> References: <20260916152437.1787889-1-den@openvz.org> Content-Transfer-Encoding: 8bit X-EOPAttributedMessage: 1 X-EOPTenantAttributedMessage: 0bc7f26d-0264-416e-a6fc-8352af79c58f:1 X-MS-TrafficTypeDiagnostic: AMS1EPF0000009B:EE_|GV2PR08MB11492:EE_|MI3PEPF0000855C:EE_|MI9PR08MB890576:EE_|PAXPR08MB6942:EE_ X-MS-Office365-Filtering-Correlation-Id: d65623ce-cff7-4ce7-a499-08df1406adb0 X-MS-Exchange-AtpMessageProperties: SA|SL X-PERCEPTION-POINT-CUSTOM: vzpp X-Microsoft-Antispam-Untrusted: BCL:0;ARA:13230040|82310400026|6059299003|2092899012|12012899012|43022699015|3072899012|19002099009|6133799003|10067099003|5063699009|5023799004|55112099003|22082099003|18002099003|57112099003|3023799007|16102099003; X-Microsoft-Antispam-Message-Info-Original: =?us-ascii?Q?UoGgGxwC/yIrSg1ipH+lnfp36k4Wd+4zSlhuN98QBhuQ8U6leMVcOhPFQg/l?= =?us-ascii?Q?bTBjxwwZhU3GhPcabS3njILstIt6NCbumJ+TrV7I5a9gidYu//SWBzHL/FKr?= =?us-ascii?Q?amaZ1s1zQ5vXa1JF11eEtFl0Vg/Jv0oWi8OFoXJp2D6tHREkD8Uxey/XdFF5?= =?us-ascii?Q?u5CiEZsyHlfIMyyVglvdPWnqTl761Ptwnq3t0O4/+78Im/t96cmDwm8Ttm3S?= =?us-ascii?Q?PALuLm/hiI7Z4tP3oPdL8xt5FiEpT6YGmya8u3ejSyqM1m7Nj2QZ/iVOy5NA?= =?us-ascii?Q?ZOdEIJ0wwgnHy8WGytitFt0NE0OqZ/wnY3h4lfZGvmbyPx8g+3YXH0Y/ftAO?= =?us-ascii?Q?T4wJv77KEzuGj6M9h2Q8cYR7UEoeyD/3bhTbLjTGu//0dKfs9IjIZmRl9j+t?= =?us-ascii?Q?8rJrwL/hy0um13lENTA2vtV3nfx/6Asy9508y0qqVL2UTlMCP9dzdZzIAW6d?= =?us-ascii?Q?uqpuaV6dmKyWzGIg9EC+lQkzPFm/s0Ptz66Jg58sSPDFaEOufKOCyCVrFXTl?= =?us-ascii?Q?4yTj6m2mnr106B9EYI391J646HdFlozugzQV03LxkBXpHPJWvL0e7wujoxgE?= =?us-ascii?Q?PC6Aovcehlou1i7ZQ4bz1H0hTt2kZSl4l6IvaOEmLlo0u6lNsULq2fkw8u4L?= =?us-ascii?Q?VSaA8Ql0PydAUT6BgSLUCvIfCC/E0qg4eVUQG9vBMUMYj9+q6rVVyJpL8c7j?= =?us-ascii?Q?BYwTgKLdH3ZKsvwlnsXMJqVkM+ty6P+n3yrmER66RBhSOs7wnJzyrgZ22GwO?= =?us-ascii?Q?4d9OnaiMxT4S7U1aZUJR9YLWJ0MWhwB/Pv5Lpmj8dYiWX1YPl+mNRbBPShmO?= =?us-ascii?Q?HtLx4n4/QIq7gJ/UBxqf2UKZhQbNsZm6ncPvmhoGrtfdeohqua20GHaePPI5?= =?us-ascii?Q?EnpQ9HIhbhqhKr6q1NoLlHwTd05cqLPRzKO56BknOpiQgvvAjlIIr699zixt?= =?us-ascii?Q?SPxD0VnYLgCEhYeYmLOaSyLm9Zt7/sjgOWtcZGO2IZ8EGkXAsbPT67Ozc+8v?= =?us-ascii?Q?DvVeXxJyDMrC+GQwdx1p4FNHj4lGxVSGU7OtyzhcbOKvUaSfVrUI1IALrXnI?= =?us-ascii?Q?7ct+p1VYY+3EsxYUdIC2N/1c8R7NgYMdoOCEXH/9KSlODhZtSFxk8JJqYjKw?= =?us-ascii?Q?oTHj+yee26gLpjRTAJWm0BXy8BuhLjMz/uiMmwgz4n5csNOcQje9woJNbsAG?= =?us-ascii?Q?gHVBFClYR7B9mjyPS7N2y27mn95f0VpFsq6EOHhIlkAhJIGnzA81Bil5WVhK?= =?us-ascii?Q?7MRLgTG9LpCSVlDJxvh6xGOHIrFL3at7jjWFyAjarSz68Q3j/5uu4L0GWEU9?= =?us-ascii?Q?5wNo7fQqSxZiI3xJQoHjut3kCfMF70ssPHBRK2d8vQQ4VDBQGQs4+fQGghZZ?= =?us-ascii?Q?+pMrhS0+XGuzfhfWEQqlE7i2M1+sDpo4DFDxbdDhVRCxrzKkMOS1IVFMLAOZ?= =?us-ascii?Q?HnN4JXzSY4YdgGg9MsGniAeWuufaauN2czhpyPeZDYRBCP+pTm9ZyJIc7xwW?= =?us-ascii?Q?HvrN90Dju3Uqrqt4vY0wJ4rg8ipGh7/NSMJIcb9AnlndLwIHNxS2wqoQJjVi?= =?us-ascii?Q?J1qXSxgnvL9lyjfX8vlmDXHeiYWsSaPLzYGuyoz0x43FwZGP5FPAwUcdVpmc?= =?us-ascii?Q?DXIee87eAl6ECGzwxcmLNN3nE5PM40EczRY+mxv9/mDChYgwjAtMGX0qFHQI?= =?us-ascii?Q?Inoej9uuKfil+O/r+1vJtqrJQu6HKaQ0Jy5m7JEs/UmMhLCbCfWqaI9Zbstb?= =?us-ascii?Q?vmzyfoQf1AXteVVhcySBffasyQCYRCtQVerR3Y8XviHxVo1jqCJhqYrWRHRr?= =?us-ascii?Q?cHx2RbFbztnK9gqIts/XlHr+i9ChX8SbV51GZ82EJZ8yQ+KDQr0RoneP1fCO?= =?us-ascii?Q?zYQVyLOiyTNJJYxQ5fv1hWQBlx2PmJaIVSq6TyOqLH/eCIhxYbNWRfFcHI/y?= =?us-ascii?Q?dcfMhjnvIifCTqYAmnPweCkCYSeOEwLmVqvGuMDH0Rcaz3NgEKywA3dh8eDf?= =?us-ascii?Q?u5fWfyfXsV+dCxXZedbsSPgLwjoNst9+Qj7eIQPPV86llBlGPeXNeH3w/dsS?= =?us-ascii?Q?UW63AQU4YkuNzUvkj2qaCQxtrnQUnVyx/t2J/dkhpoTjzT/ytHWxwN0Rv/Yi?= =?us-ascii?Q?9nGlAtsxhjQb9UHfmn/xOUsPJCquIJsaxx0Duour1hTNDhIieFX8xPQPYdnz?= =?us-ascii?Q?AddqEtUq/hkTxX830aXOCQ7gbyIUnp11iHE1wSCwHUO3cMnfpGYU900hCd4?= =?us-ascii?Q?=3D?= X-Forefront-Antispam-Report-Untrusted: CIP:2a00:1450:4864:31::10;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail-wm2-x10.google.com;PTR:mail-wm2-x10.google.com;CAT:NONE;SFS:(13230040)(82310400026)(6059299003)(2092899012)(12012899012)(43022699015)(3072899012)(19002099009)(6133799003)(10067099003)(5063699009)(5023799004)(55112099003)(22082099003)(18002099003)(57112099003)(3023799007)(16102099003);DIR:INB; X-Auto-Response-Suppress: DR, OOF, AutoReply X-Exchange-RoutingPolicyChecked: V/mAJBeO3mcqg6MZVBl9kMU3BVY3XJzm3WpzZtnotF+2hMJURiCxtBLvmbZN7IfUPTv4Z6zV0YdpXVkNvEntft/IMzfE2XEPuiKtdMW/NBqBnNyeb8G1tA1mHCAvxmocKDKKpWKYZCgTQkMCmNKwRdMai8DstooU+AGKYmJh61OI5MSVQuWDQi2F8ksguweU0y7NsOV7gfE8sx16sb8RLFuBtlheE4G96ZZ4XgnvD9xTId4+ON4sixKU+aVgRkzqcu0oXsI54DNS1ZpS5kqh4n2Es1L5lnVVuLAoyvC9ROuuA3kRPWViU2ApNHne+iQDWGko1KCMzrXvhB7ExUwoMA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV2PR08MB11492 X-MS-Exchange-Organization-ExpirationStartTime: 16 Sep 2026 15:25:02.6293 (UTC) X-MS-Exchange-Organization-ExpirationStartTimeReason: OriginalSubmit X-MS-Exchange-Organization-ExpirationInterval: 1:00:00:00.0000000 X-MS-Exchange-Organization-ExpirationIntervalReason: OriginalSubmit X-MS-Exchange-Organization-Network-Message-Id: d65623ce-cff7-4ce7-a499-08df1406adb0 X-MS-Exchange-Organization-MessageDirectionality: Incoming X-MS-Exchange-Transport-CrossTenantHeadersStripped: MI3PEPF0000855C.eurprd05.prod.outlook.com X-MS-PublicTrafficType: Email X-MS-Exchange-Organization-AuthSource: MI3PEPF0000855C.eurprd05.prod.outlook.com X-MS-Exchange-Organization-AuthAs: Anonymous X-MS-Office365-Filtering-Correlation-Id-Prvs: 8ce76c63-693a-4fcf-3f7f-08df1406a6c7 X-MS-Exchange-Organization-SCL: -1 X-Microsoft-Antispam: BCL:0;ARA:13230040|82310400026|43022699015|6059299003|12012899012|2092899012|3072899012|35042699022|18003699003|10067099003|19002099009|3023799007|5133699003|6133799003|5023799004|5063699009|55112099003|57112099003|16102099003|22082099003; X-Forefront-Antispam-Report: CIP:99.81.216.78;CTRY:IE;LANG:en;SCL:-1;SRV:;IPV:CAL;SFV:SKN;H:nat.eu.perception-point.io;PTR:nat2.eu.perception-point.io;CAT:NONE;SFS:(13230040)(82310400026)(43022699015)(6059299003)(12012899012)(2092899012)(3072899012)(35042699022)(18003699003)(10067099003)(19002099009)(3023799007)(5133699003)(6133799003)(5023799004)(5063699009)(55112099003)(57112099003)(16102099003)(22082099003);DIR:INB; X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Sep 2026 15:25:01.9024 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: d65623ce-cff7-4ce7-a499-08df1406adb0 X-MS-Exchange-CrossTenant-Id: 0bc7f26d-0264-416e-a6fc-8352af79c58f X-MS-Exchange-CrossTenant-AuthSource: MI3PEPF0000855C.eurprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: Internet X-MS-Exchange-Transport-CrossTenantHeadersStamped: MI9PR08MB890576 X-MS-Exchange-Transport-EndToEndLatency: 00:00:08.5668676 X-MS-Exchange-Processed-By-BccFoldering: 15.21.0451.004 Content-Type: text/plain X-Microsoft-Antispam-Mailbox-Delivery: ucf:0;jmr:0;auth:0;dest:I;ENG:(910005)(944506478)(944626604)(920097)(930201)(20251009189)(140003); X-Microsoft-Antispam-Message-Info: =?iso-8859-1?Q?IFmUs6Kq8hdb+saj7IkO7oiEjTF+QnuziQ0BbXjnYp8ruYHlcLjq/4Uqcn?= =?iso-8859-1?Q?z1JcB2gl3COpJWiOOFONn+b8+EzL/aFSRmUQiznQZSqr3PsCBFkkTfs+ib?= =?iso-8859-1?Q?ZfrC/zIlZVOtTLYvErsSyVQIvj/7IJdDkdUZVVN6Jv7cd1tYKibevslqOV?= =?iso-8859-1?Q?iz4l6gm677tdbpdHdO8EqTlLkNRHwhT50tZ/97DW2fR3QxKCz5RLaBPSAK?= =?iso-8859-1?Q?NxrNyA6wOplMaFrEPFo6DPcBQl4QrxV3OJbQjjkwXYoeNRQbCpIYxJQGWk?= =?iso-8859-1?Q?WSNECZs3XUg2ZB8wm4pCzrGgZaZ6apC1A2VJY8GFUjK+pX8oDdUVyTCdEH?= =?iso-8859-1?Q?bNqT/4/Q+So6tsMqSHzYYqTgDzEPp43EyYbQyu+iOLuNoFAnjBAB3vSEsY?= =?iso-8859-1?Q?GiJzDqb/1wUE/TcHcpySZPO6U4UFfHf02brEcErZDGrfm41e9Zkc2Oyg8m?= =?iso-8859-1?Q?jkOJ76ipRpophjUDAK7icm9bogrdQsReEejg6DojSEJyqN96YtDCoBUyyX?= =?iso-8859-1?Q?5WNr3JIRCwAlSeRVl2PSdaSGZX3yXZ9qpVubNE2quAPDVr3b2pCFHYgKhQ?= =?iso-8859-1?Q?5h3DhX/i8rzPKXrIIC5h45b4gwVPicw9HCb/g4SRQAO9TDNPzVR1MoH2Z2?= =?iso-8859-1?Q?jcB8d7GOobf8r1Ggt/JtaYsJTxVErbk+CDnc19dH8a2Bu4y9DLCucpFeLm?= =?iso-8859-1?Q?ql1ZJZwOgQw8MTHTt0b3w6TAHfSxCMsmftQrl1xURgcjhzBy7GhbLgoqpi?= =?iso-8859-1?Q?38UK/W2ImKv3JcDAXk1lxiT/SzW8cG6pOrP3rkIywU4liaGYYGOMpIkmU0?= =?iso-8859-1?Q?AnqFj9ezHYBd/+bq0O1GyJ8uCW3icZEh5E7WFHnn/IOABGMCOC31gkla8e?= =?iso-8859-1?Q?VAci+t5CK3bk1oBAm2X65asEZ7FKjShNXxqRgLQTTk4oCVQp8jQdlC/8mI?= =?iso-8859-1?Q?K3WqRE7Oe42vlPs1HWasDC0gb6RV4bYKqkJZ0x7pM/3Q6AHmfPaLsOLl7L?= =?iso-8859-1?Q?u17wRE8mwhITy4zxrLnSyl73GngXnju2OlI6FYXQiQqXysWMZ7AR+Tn5UQ?= =?iso-8859-1?Q?FZg+fuIk04uhnk9RKuYt/gYoR/a0ZgSbUmQDb2i4dmrD10ZSQDYF9z4JKX?= =?iso-8859-1?Q?mPxVsXyWxDaoTKg8TWNf0Hz0M4kYvQyL7w+zGboQ/6YTKrC8YyL6zui3r0?= =?iso-8859-1?Q?gO4BD16UPGywzfGuNMgs8zLO2f3SepOQk1pi4SesGV4b1CN/46MXEUCsgm?= =?iso-8859-1?Q?I6JEk6SGUkj1i1BbCblBcx8GCBMO7aG+lXq14KJTLv9ykpeWfdvUhU8xan?= =?iso-8859-1?Q?w5bI3k8aQ60kbE83mGoYwsoqbIVTDZWF0R9pUcYIn0AX5zArdVFq0MCOQk?= =?iso-8859-1?Q?gyOkMZXqK+ivLHNfknpho7TPXOUmQUUOkO3GVaQvBhyy5E353/zRrcBE9h?= =?iso-8859-1?Q?VOnNEYfXv0A2EoJsPHs+y8HrOuAHbFTwE3bfzmh+J7Kh78FX5HjIMMK7fl?= =?iso-8859-1?Q?4q7pSCP4S29j5ZlyL2IyB38gnKs8VW9tJQRCJ0snKRj3Z3OcBuKTqwZVjR?= =?iso-8859-1?Q?RWXvqYLhi+Pu0deVlqu042mMBudt83lKN+ybIIZ1R6y5QpF8aveV2Ivv4G?= =?iso-8859-1?Q?JG0rHv5xLo/zweNyFxEp2vduCNOJqZAdgDzLgKKkNF9wpthJmNHjqn/Vt2?= =?iso-8859-1?Q?m3vVWhJKJm3PPav7qu4lKKk+xEDfSsWeHKj/GRq/rArmuq1nt8FKK4Xf8X?= =?iso-8859-1?Q?w5TMSLLwPj56T9xEqbp0nGy8EqnifD0RF5HXTYTVogDmR0P2NgWmWD8w7A?= =?iso-8859-1?Q?ozKtBIIjq2+Q/fW8Jqx6kHxixEBf7zZ9Oruy9UngSPg+Tb8tf9D3x2bfNN?= =?iso-8859-1?Q?XpSfu8rtE+C3DY0U6Kxnf83sico4fuuJATHKEZf5dMth/oXNSNe/eBk2OT?= =?iso-8859-1?Q?8p8urTaKvIQ360Fy6muIIMT68rjxEKr0KkT1vCnd59lD6NZKjx6KD+iWyB?= =?iso-8859-1?Q?xMWYOvOqWelzt74oGjBeBq2wFfv6USK1Q4a40EgCa3LA8/AdWdaULU20Jr?= =?iso-8859-1?Q?9IFDTykYom4FnzFb+y7RAgcDhss2yTHWQWEsMunRbPg2YhZjrik61ooOmC?= =?iso-8859-1?Q?Oiu95PlzKWjremueULpTnF1WWtdJeiUf8+6BZqOeNYCel9GLZLR7vMOIF3?= =?iso-8859-1?Q?g0hEXgstnlqB9VUxIfwh8qhYZhg4inG4qpI/lzuWNm6n3MsO4AtoMwiURr?= =?iso-8859-1?Q?DTtmLXihPK+jMvKQXGMJ0DokOy8fQW9vy556RJttFHmVsotVCJXfXjUnip?= =?iso-8859-1?Q?TK5NHakxiyBSwIqxROvfOgyUOWYtrnk3sEtN2GhM5E80G5TMT3/U4cy1Ry?= =?iso-8859-1?Q?HaALqMVCOMUoJXzPxq9e+n/E1w11F/wQ/Ez+cCLy3fokMm6VwdGbrPV2yp?= =?iso-8859-1?Q?bCQA22P1JQsRrOwwolkvJptqu9/VzpEp4GydhrKJSDefuA6O6k00DY8bTs?= =?iso-8859-1?Q?F/Q4ueH8Iu/yBhfCpJPkXTSIktOFxuEQqiPwa0r0nAXQ+TK6zaHr9jbPYd?= =?iso-8859-1?Q?ovltbarX4oOLEG+DDJIXVZ8PH6So9hJJlfoubUa03ChTzKRtothEyl1/1y?= =?iso-8859-1?Q?b4F56Ao8pS2f7hLsuWAYEk2T/q951ClCYr8XgwrB0NvHSwYx9vgY/5xGrn?= =?iso-8859-1?Q?yJ/kYK5ZAmylEUEAMoDhTOBZzkbdDsLJGreWhkpumId3cN8v7w/Rd4VSyl?= =?iso-8859-1?Q?rs/h6vUgmBJdQZ?= MIME-Version: 1.0 List-Id: From: Denis V. Lunev A dirty image must be repaired before anything allocates a cluster in it. qcow2_do_open() does that, but only for a node that is writable from the start. A node opened read-only skips it, and nothing revisits the question once that node becomes writable, which block-commit does routinely: commit_active_start() and commit_start() reopen the base read-write for the duration of the job. With lazy refcounts the on-disk refcount block then still accounts for the metadata clusters only, so the allocator restarts at the front of the image and hands out clusters that L2 entries point at. Two guest offsets end up sharing one host cluster. Nothing fails, the corrupt bit stays clear, and a clean close clears the dirty bit, so no later open repairs the image either. The bit also stays set for the whole writable session, so a node which is merely writable says nothing. Refusing the reopen instead is simpler and keeps it atomic, but it leaves nowhere to go: the base belongs to a chain the VM has open, so the qemu-img check -r such an error would ask for cannot take the write lock it needs. The repair does the trick in most cases anyway. Do the repair in qcow2_reopen_commit_post(), the earliest point where the node is writable. An inactive node is skipped: bdrv_activate() calls qcow2_do_open() again through qcow2_co_invalidate_cache(). commit_post cannot reject the reopen, so a failed repair takes the driver away from the node instead, which is what stops writes from aliasing live clusters. qcow2_signal_corruption() does that as well, but it also sends BLOCK_IMAGE_CORRUPTED and sets the corrupt bit, which qcow2_do_open() honours by refusing every later read-write open. The image is dirty and unrepaired, not corrupt, and qemu-img check -r still fixes it, so neither belongs here. Return the error and skip the bitmaps. Signed-off-by: Denis V. Lunev Reviewed-by: Andrey Drobyshev CC: Kevin Wolf CC: Hanna Reitz CC: Eric Blake CC: Markus Armbruster CC: Andrey Drobyshev Cc: qemu-stable@nongnu.org --- block/qcow2.c | 21 +++++++ qapi/block-core.json | 19 ++++++ tests/qemu-iotests/039 | 60 ++++++++++++++++++ tests/qemu-iotests/039.out | 36 +++++++++++ tests/qemu-iotests/040 | 123 +++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/040.out | 4 +- 6 files changed, 261 insertions(+), 2 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index ddad39a3084..be346f0339b 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2235,8 +2235,29 @@ static void qcow2_reopen_commit(BDRVReopenState *state) static int qcow2_reopen_commit_post(BDRVReopenState *state, Error **errp) { + ERRP_GUARD(); + BDRVQcow2State *s = state->bs->opaque; + GRAPH_RDLOCK_GUARD_MAINLOOP(); + if (!bdrv_reopen_was_writable(state) && bdrv_is_writable(state->bs) && + (s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) { + BdrvCheckResult result = {0}; + int ret; + + ret = bdrv_check(state->bs, &result, BDRV_FIX_ERRORS | BDRV_FIX_LEAKS); + if (ret < 0 || result.check_errors || !state->bs->drv) { + ret = ret < 0 ? ret : -EIO; + /* No write may reach an image whose refcounts are unaccounted */ + state->bs->drv = NULL; + error_setg_errno(errp, -ret, "Could not repair dirty image '%s'", + bdrv_get_device_or_node_name(state->bs)); + error_append_hint(errp, "The image is left dirty and this node " + "holds it open until the node is removed\n"); + return ret; + } + } + if (state->flags & BDRV_O_RDWR) { Error *local_err = NULL; diff --git a/qapi/block-core.json b/qapi/block-core.json index c036a3a8858..6fb8c31210a 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1843,6 +1843,9 @@ # r/w -> r/o, if needed). The new backing file string is written into # the image file metadata, and the QEMU internal strings are updated. # +# A dirty qcow2 image is repaired during that reopen, which blocks +# other requests and can fail the command. +# # @image-node-name: The name of the block driver state node of the # image to modify. The "device" argument is used to verify # "image-node-name" is in the chain described by "device". @@ -1882,6 +1885,9 @@ # size to match the size of the smaller top, you can safely truncate # it yourself once the commit operation successfully completes. # +# The base is opened read-write. A dirty qcow2 base is repaired +# first, which blocks other requests and can fail the command. +# # @job-id: identifier for the newly-created block job. If omitted, # the device name will be used. (Since 2.7) # @@ -2919,6 +2925,9 @@ # On successful completion the image file is updated to drop the # backing file and the `BLOCK_JOB_COMPLETED` event is emitted. # +# The top image is opened read-write. A dirty qcow2 image is repaired +# first, which blocks other requests and can fail the command. +# # In case @device is a filter node, `block-stream` modifies the first # non-filter overlay node below it to point to the new backing node # instead of modifying @device itself. @@ -5070,6 +5079,16 @@ # transaction, so if one of them fails then the whole transaction is # cancelled. # +# An error is also returned when a device cannot be used once it has +# been reopened. Such a reopen is not undone, so an error does not +# always mean that nothing has changed. A node the driver gave up on +# serves nothing at all: it keeps its image open, makes +# `query-named-block-nodes` fail for as long as it is in the graph, +# and `blockdev-del` removes it only once nothing refers to it. +# +# Reopening a dirty qcow2 image read-write repairs it first, which +# blocks other requests and can fail the command. +# # The command receives a list of block devices to reopen. For each # one of them, the top-level @node-name option (from `BlockdevOptions`) # must be specified and is used to select the block device to be diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039 index 3d0c073d65d..3f37c36ca86 100755 --- a/tests/qemu-iotests/039 +++ b/tests/qemu-iotests/039 @@ -33,6 +33,7 @@ status=1 # failure is the default! _cleanup() { _cleanup_test_img + rm -f "$TEST_DIR/blkdebug.conf" } trap "_cleanup; exit \$status" 0 1 2 3 15 @@ -176,6 +177,65 @@ $QEMU_IO -c "write 0 512" "$TEST_IMG" | _filter_qemu_io # The dirty bit must not be set _qcow2_dump_header | grep incompatible_features +echo +echo "== Reopening a dirty image read/write should repair it ==" + +_make_test_img -o "compat=1.1,lazy_refcounts=on" $size + +_NO_VALGRIND \ +$QEMU_IO -c "write -P 0x5a 0 512" \ + -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \ + | _filter_qemu_io + +# The dirty bit must be set +_qcow2_dump_header | grep incompatible_features + +# Without the repair this write would alias the cluster at offset 0 +$QEMU_IO -r -c "reopen -w" \ + -c "write -P 0xb1 1M 512" \ + -c "read -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io + +_check_test_img + +echo +echo "== A read/write reopen must not check the image ==" + +_make_test_img -o "compat=1.1,lazy_refcounts=on" $size + +_NO_VALGRIND \ +$QEMU_IO -c "write -P 0x5a 0 512" \ + -c "reopen -o l2-cache-size=1M" \ + -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \ + | _filter_qemu_io + +# The dirty bit must still be set, it belongs to the running session +_qcow2_dump_header | grep incompatible_features + +echo +echo "== A failed repair must fail the reopen ==" + +_make_test_img -o "compat=1.1,lazy_refcounts=on" $size + +_NO_VALGRIND \ +$QEMU_IO -c "write -P 0x5a 0 512" \ + -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \ + | _filter_qemu_io + +cat > "$TEST_DIR/blkdebug.conf" <&1 \ + | _filter_testdir | _filter_qemu_io | _filter_generated_node_ids + +# The corrupt bit needs a write of its own, so the image is only left dirty +_qcow2_dump_header | grep incompatible_features + echo echo "== Creating an image file with lazy_refcounts=off ==" diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out index ce8ee577216..cc6ca3ab95b 100644 --- a/tests/qemu-iotests/039.out +++ b/tests/qemu-iotests/039.out @@ -79,6 +79,42 @@ wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) incompatible_features [] +== Reopening a dirty image read/write should repair it == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) +incompatible_features [0] +ERROR cluster 5 refcount=0 reference=1 +Rebuilding refcount structure +Repairing cluster 1 refcount=1 reference=0 +Repairing cluster 2 refcount=1 reference=0 +wrote 512/512 bytes at offset 1048576 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +No errors were found on the image. + +== A read/write reopen must not check the image == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) +incompatible_features [0] + +== A failed repair must fail the reopen == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) +ERROR cluster 5 refcount=0 reference=1 +Rebuilding refcount structure +qemu-io: ERROR writing refblock: Input/output error +qemu-io: Could not repair dirty image 'NODE_NAME': Input/output error +The image is left dirty and this node holds it open until the node is removed +read failed: No medium found +incompatible_features [0] + == Creating an image file with lazy_refcounts=off == Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 index 5c18e413ec9..b25c76183a1 100755 --- a/tests/qemu-iotests/040 +++ b/tests/qemu-iotests/040 @@ -951,6 +951,129 @@ class TestCommitWithOverriddenBacking(iotests.QMPTestCase): self.vm.qmp('block-job-complete', device='commit') self.vm.event_wait('BLOCK_JOB_COMPLETED') +QCOW2_INCOMPAT_FEATURES_OFFSET = 72 +QCOW2_INCOMPAT_DIRTY = 1 << 0 + +image_size = 4 * 1024 * 1024 +dirty_base = os.path.join(iotests.test_dir, 'dirty-base.img') +mid = os.path.join(iotests.test_dir, 'dirty-mid.img') +top = os.path.join(iotests.test_dir, 'dirty-top.img') + + +class TestCommitDirtyBase(iotests.QMPTestCase): + def setUp(self) -> None: + if iotests.imgfmt != 'qcow2': + self.case_skip('the dirty bit is a qcow2 feature') + iotests.qemu_img_create('-f', iotests.imgfmt, '-o', + 'compat=1.1,lazy_refcounts=on', dirty_base, + str(image_size)) + # Killing the process leaves the refcounts of the written cluster stale + iotests.qemu_io_popen('-t', 'writethrough', + '-c', 'write -P 0x5a 0 512', + '-c', 'sigraise 9', dirty_base).communicate() + iotests.qemu_img_create('-f', iotests.imgfmt, '-b', dirty_base, + '-F', iotests.imgfmt, mid) + iotests.qemu_img_create('-f', iotests.imgfmt, '-b', mid, + '-F', iotests.imgfmt, top) + # The commit has to allocate for this, which is where the stale + # refcounts hand out the cluster holding the data written above + qemu_io('-c', 'write -P 0xb1 1M 512', mid) + + self.vm = iotests.VM() + self.vm.launch() + self.vm.cmd('blockdev-add', driver='file', filename=dirty_base, + node_name='base-file') + + self.assertTrue(self.is_dirty()) + + def tearDown(self) -> None: + if self.vm.is_running(): + self.vm.shutdown() + for image in (dirty_base, mid, top): + os.remove(image) + + def add_chain(self, base_file: str) -> None: + self.vm.cmd('blockdev-add', driver=iotests.imgfmt, file=base_file, + node_name='base', read_only=True) + self.vm.cmd('blockdev-add', driver='file', filename=mid, + node_name='mid-file') + self.vm.cmd('blockdev-add', driver=iotests.imgfmt, file='mid-file', + node_name='mid', backing='base') + self.vm.cmd('blockdev-add', driver='file', filename=top, + node_name='top-file') + self.vm.cmd('blockdev-add', driver=iotests.imgfmt, file='top-file', + node_name='top', backing='mid') + + def check_base(self) -> None: + result = iotests.qemu_img_check(dirty_base) + self.assertEqual(result['check-errors'], 0) + self.assertEqual(result.get('corruptions', 0), 0) + # Without the repair the commit would have aliased this cluster + qemu_io('-c', 'read -P 0x5a 0 512', '-c', 'read -P 0xb1 1M 512', + dirty_base) + + def is_dirty(self) -> bool: + with open(dirty_base, 'rb') as img: + img.seek(QCOW2_INCOMPAT_FEATURES_OFFSET) + features = struct.unpack('>Q', img.read(8))[0] + return bool(features & QCOW2_INCOMPAT_DIRTY) + + def test_commit_repairs_base(self) -> None: + self.add_chain('base-file') + + self.vm.cmd('block-commit', job_id='job0', device='top', + top_node='mid', base_node='base') + self.wait_until_completed(drive='job0') + + self.vm.shutdown() + self.assertFalse(self.is_dirty()) + self.check_base() + + def test_active_commit_repairs_base(self) -> None: + self.add_chain('base-file') + + # Without top-node the whole chain commits, through + # commit_active_start() rather than commit_start() + self.vm.cmd('block-commit', job_id='job0', device='top', + base_node='base') + self.complete_and_wait(drive='job0') + + self.vm.shutdown() + self.assertFalse(self.is_dirty()) + self.check_base() + + def test_failed_repair_fails_the_commit(self) -> None: + self.vm.cmd('blockdev-add', driver='blkdebug', image='base-file', + node_name='base-blkdebug', + inject_error=[{'event': 'none', 'iotype': 'write', + 'errno': 5}]) + self.add_chain('base-blkdebug') + + result = self.vm.qmp('block-commit', job_id='job0', device='top', + top_node='mid', base_node='base') + self.assert_qmp(result, 'error/class', 'GenericError') + self.assertIn("Could not repair dirty image 'base'", + result['error']['desc']) + + # The base is left in the graph, and nothing can be queried while + # it is there + result = self.vm.qmp('query-named-block-nodes', flat=True) + self.assert_qmp(result, 'error/desc', 'Block device base is ejected') + + # It only goes away once nothing refers to it + result = self.vm.qmp('blockdev-del', node_name='base') + self.assert_qmp(result, 'error/desc', + "Node 'base' is busy: node is used as backing hd of " + "'mid'") + + # Marking the image corrupt needs a write of its own, which fails too + self.assertTrue(self.is_dirty()) + + # Nothing can use the base any more, and that is what is reported + result = self.vm.qmp('block-commit', job_id='job1', device='top', + top_node='mid', base_node='base') + self.assert_qmp(result, 'error/desc', 'Device has no medium') + if __name__ == '__main__': iotests.main(supported_fmts=['qcow2', 'qed'], supported_protocols=['file']) diff --git a/tests/qemu-iotests/040.out b/tests/qemu-iotests/040.out index 1bb1dc5f0ea..f3cbf73a01d 100644 --- a/tests/qemu-iotests/040.out +++ b/tests/qemu-iotests/040.out @@ -1,5 +1,5 @@ -................................................................. +.................................................................... ---------------------------------------------------------------------- -Ran 65 tests +Ran 68 tests OK -- 2.53.0