From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id C3A061FF139 for ; Mon, 12 Jan 2026 17:00:33 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 4C101377E; Mon, 12 Jan 2026 17:00:19 +0100 (CET) From: Fiona Ebner To: pve-devel@lists.proxmox.com Date: Mon, 12 Jan 2026 16:59:25 +0100 Message-ID: <20260112155940.298273-2-f.ebner@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260112155940.298273-1-f.ebner@proxmox.com> References: <20260112155940.298273-1-f.ebner@proxmox.com> MIME-Version: 1.0 X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1768233540449 X-SPAM-LEVEL: Spam detection results: 0 AWL -0.016 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pve-devel] [PATCH qemu 1/2] fix #7222: add fix for crash caused by zero write during sync drive mirror X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox VE development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" Upstream submission [0]. [0]: https://lore.kernel.org/qemu-devel/20260112152544.261923-1-f.ebner@proxmox.com/T/ Signed-off-by: Fiona Ebner --- ...d-support-for-sync-bitmap-mode-never.patch | 20 +++---- ...-support-for-conditional-and-always-.patch | 6 +- ...-to-bdrv_dirty_bitmap_merge_internal.patch | 4 +- .../0006-mirror-move-some-checks-to-qmp.patch | 4 +- ...ck-range-when-setting-zero-bitmap-fo.patch | 58 +++++++++++++++++++ debian/patches/series | 1 + 6 files changed, 76 insertions(+), 17 deletions(-) create mode 100644 debian/patches/extra/0012-block-mirror-check-range-when-setting-zero-bitmap-fo.patch diff --git a/debian/patches/bitmap-mirror/0001-drive-mirror-add-support-for-sync-bitmap-mode-never.patch b/debian/patches/bitmap-mirror/0001-drive-mirror-add-support-for-sync-bitmap-mode-never.patch index 1a20886..6e93d4f 100644 --- a/debian/patches/bitmap-mirror/0001-drive-mirror-add-support-for-sync-bitmap-mode-never.patch +++ b/debian/patches/bitmap-mirror/0001-drive-mirror-add-support-for-sync-bitmap-mode-never.patch @@ -38,7 +38,7 @@ Signed-off-by: Fiona Ebner 5 files changed, 135 insertions(+), 21 deletions(-) diff --git a/block/mirror.c b/block/mirror.c -index b344182c74..a184e91478 100644 +index bc982cb99a..99805e7a9d 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -74,6 +74,8 @@ typedef struct MirrorBlockJob { @@ -93,7 +93,7 @@ index b344182c74..a184e91478 100644 .pause = mirror_pause, .complete = mirror_complete, .cancel = commit_active_cancel, -@@ -1835,6 +1850,8 @@ static BlockJob *mirror_start_job( +@@ -1838,6 +1853,8 @@ static BlockJob *mirror_start_job( BlockCompletionFunc *cb, void *opaque, const BlockJobDriver *driver, @@ -102,7 +102,7 @@ index b344182c74..a184e91478 100644 BlockDriverState *base, bool auto_complete, const char *filter_node_name, bool is_mirror, MirrorCopyMode copy_mode, -@@ -1850,10 +1867,39 @@ static BlockJob *mirror_start_job( +@@ -1853,10 +1870,39 @@ static BlockJob *mirror_start_job( GLOBAL_STATE_CODE(); @@ -144,7 +144,7 @@ index b344182c74..a184e91478 100644 assert(is_power_of_2(granularity)); if (buf_size < 0) { -@@ -1995,6 +2041,8 @@ static BlockJob *mirror_start_job( +@@ -1998,6 +2044,8 @@ static BlockJob *mirror_start_job( s->on_source_error = on_source_error; s->on_target_error = on_target_error; s->sync_mode = sync_mode; @@ -153,7 +153,7 @@ index b344182c74..a184e91478 100644 s->backing_mode = backing_mode; s->target_is_zero = target_is_zero; qatomic_set(&s->copy_mode, copy_mode); -@@ -2020,6 +2068,18 @@ static BlockJob *mirror_start_job( +@@ -2023,6 +2071,18 @@ static BlockJob *mirror_start_job( */ bdrv_disable_dirty_bitmap(s->dirty_bitmap); @@ -172,7 +172,7 @@ index b344182c74..a184e91478 100644 bdrv_graph_wrlock_drained(); ret = block_job_add_bdrv(&s->common, "source", bs, 0, BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE | -@@ -2102,6 +2162,9 @@ fail: +@@ -2105,6 +2165,9 @@ fail: if (s->dirty_bitmap) { bdrv_release_dirty_bitmap(s->dirty_bitmap); } @@ -182,7 +182,7 @@ index b344182c74..a184e91478 100644 job_early_fail(&s->common.job); } -@@ -2124,7 +2187,10 @@ void mirror_start(const char *job_id, BlockDriverState *bs, +@@ -2127,7 +2190,10 @@ void mirror_start(const char *job_id, BlockDriverState *bs, BlockDriverState *target, const char *replaces, int creation_flags, int64_t speed, uint32_t granularity, int64_t buf_size, @@ -194,7 +194,7 @@ index b344182c74..a184e91478 100644 bool target_is_zero, BlockdevOnError on_source_error, BlockdevOnError on_target_error, -@@ -2135,13 +2201,6 @@ void mirror_start(const char *job_id, BlockDriverState *bs, +@@ -2138,13 +2204,6 @@ void mirror_start(const char *job_id, BlockDriverState *bs, GLOBAL_STATE_CODE(); @@ -208,7 +208,7 @@ index b344182c74..a184e91478 100644 bdrv_graph_rdlock_main_loop(); base = mode == MIRROR_SYNC_MODE_TOP ? bdrv_backing_chain_next(bs) : NULL; bdrv_graph_rdunlock_main_loop(); -@@ -2149,8 +2208,8 @@ void mirror_start(const char *job_id, BlockDriverState *bs, +@@ -2152,8 +2211,8 @@ void mirror_start(const char *job_id, BlockDriverState *bs, mirror_start_job(job_id, bs, creation_flags, target, replaces, speed, granularity, buf_size, mode, backing_mode, target_is_zero, on_source_error, on_target_error, unmap, @@ -219,7 +219,7 @@ index b344182c74..a184e91478 100644 } BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs, -@@ -2177,7 +2236,7 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs, +@@ -2180,7 +2239,7 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs, job_id, bs, creation_flags, base, NULL, speed, 0, 0, MIRROR_SYNC_MODE_TOP, MIRROR_LEAVE_BACKING_CHAIN, false, on_error, on_error, true, cb, opaque, diff --git a/debian/patches/bitmap-mirror/0002-drive-mirror-add-support-for-conditional-and-always-.patch b/debian/patches/bitmap-mirror/0002-drive-mirror-add-support-for-conditional-and-always-.patch index 7771887..8258adc 100644 --- a/debian/patches/bitmap-mirror/0002-drive-mirror-add-support-for-conditional-and-always-.patch +++ b/debian/patches/bitmap-mirror/0002-drive-mirror-add-support-for-conditional-and-always-.patch @@ -24,7 +24,7 @@ Signed-off-by: Thomas Lamprecht 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/block/mirror.c b/block/mirror.c -index a184e91478..79b6f16d27 100644 +index 99805e7a9d..7dae4d6e8a 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -734,8 +734,6 @@ static int mirror_exit_common(Job *job) @@ -55,7 +55,7 @@ index a184e91478..79b6f16d27 100644 bs_opaque->job = NULL; bdrv_drained_end(src); -@@ -1877,10 +1887,6 @@ static BlockJob *mirror_start_job( +@@ -1880,10 +1890,6 @@ static BlockJob *mirror_start_job( " sync mode", MirrorSyncMode_str(sync_mode)); return NULL; @@ -66,7 +66,7 @@ index a184e91478..79b6f16d27 100644 } } else if (bitmap) { error_setg(errp, -@@ -1897,6 +1903,12 @@ static BlockJob *mirror_start_job( +@@ -1900,6 +1906,12 @@ static BlockJob *mirror_start_job( return NULL; } granularity = bdrv_dirty_bitmap_granularity(bitmap); diff --git a/debian/patches/bitmap-mirror/0004-mirror-switch-to-bdrv_dirty_bitmap_merge_internal.patch b/debian/patches/bitmap-mirror/0004-mirror-switch-to-bdrv_dirty_bitmap_merge_internal.patch index 9468058..4f9cdbd 100644 --- a/debian/patches/bitmap-mirror/0004-mirror-switch-to-bdrv_dirty_bitmap_merge_internal.patch +++ b/debian/patches/bitmap-mirror/0004-mirror-switch-to-bdrv_dirty_bitmap_merge_internal.patch @@ -16,7 +16,7 @@ Signed-off-by: Thomas Lamprecht 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/block/mirror.c b/block/mirror.c -index 79b6f16d27..4741930d9b 100644 +index 7dae4d6e8a..0f96c8b5ce 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -855,8 +855,8 @@ static int mirror_exit_common(Job *job) @@ -30,7 +30,7 @@ index 79b6f16d27..4741930d9b 100644 } } bdrv_release_dirty_bitmap(s->dirty_bitmap); -@@ -2085,11 +2085,8 @@ static BlockJob *mirror_start_job( +@@ -2088,11 +2088,8 @@ static BlockJob *mirror_start_job( } if (s->sync_mode == MIRROR_SYNC_MODE_BITMAP) { diff --git a/debian/patches/bitmap-mirror/0006-mirror-move-some-checks-to-qmp.patch b/debian/patches/bitmap-mirror/0006-mirror-move-some-checks-to-qmp.patch index 7014368..238f47b 100644 --- a/debian/patches/bitmap-mirror/0006-mirror-move-some-checks-to-qmp.patch +++ b/debian/patches/bitmap-mirror/0006-mirror-move-some-checks-to-qmp.patch @@ -21,10 +21,10 @@ Signed-off-by: Fiona Ebner 3 files changed, 70 insertions(+), 59 deletions(-) diff --git a/block/mirror.c b/block/mirror.c -index 4741930d9b..17f19ca015 100644 +index 0f96c8b5ce..5340a695b1 100644 --- a/block/mirror.c +++ b/block/mirror.c -@@ -1877,31 +1877,13 @@ static BlockJob *mirror_start_job( +@@ -1880,31 +1880,13 @@ static BlockJob *mirror_start_job( GLOBAL_STATE_CODE(); diff --git a/debian/patches/extra/0012-block-mirror-check-range-when-setting-zero-bitmap-fo.patch b/debian/patches/extra/0012-block-mirror-check-range-when-setting-zero-bitmap-fo.patch new file mode 100644 index 0000000..908d721 --- /dev/null +++ b/debian/patches/extra/0012-block-mirror-check-range-when-setting-zero-bitmap-fo.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fiona Ebner +Date: Mon, 12 Jan 2026 15:32:52 +0100 +Subject: [PATCH] block/mirror: check range when setting zero bitmap for sync + write + +Some Proxmox users reported an occasional assertion failure [0][1] in +busy VMs when using drive mirror with active mode. In particular, the +failure may occur for zero writes shorter than the job granularity: + +> #0 0x00007b421154b507 in abort () +> #1 0x00007b421154b420 in ?? () +> #2 0x0000641c582e061f in bitmap_set (map=0x7b4204014e00, start=14, nr=-1) +> #3 0x0000641c58062824 in do_sync_target_write (job=0x641c7e73d1e0, +> method=MIRROR_METHOD_ZERO, offset=852480, bytes=4096, qiov=0x0, flags=0) +> #4 0x0000641c58062250 in bdrv_mirror_top_do_write (bs=0x641c7e62e1f0, + method=MIRROR_METHOD_ZERO, copy_to_target=true, offset=852480, + bytes=4096, qiov=0x0, flags=0) +> #5 0x0000641c58061f31 in bdrv_mirror_top_pwrite_zeroes (bs=0x641c7e62e1f0, + offset=852480, bytes=4096, flags=0) + +The range for the dirty bitmap described by dirty_bitmap_offset and +dirty_bitmap_end is narrower than the original range and in fact, +dirty_bitmap_end might be smaller than dirty_bitmap_offset. There +already is a check for 'dirty_bitmap_offset < dirty_bitmap_end' before +resetting the dirty bitmap. Add such a check for setting the zero +bitmap too, which uses the same narrower range. + +[0]: https://forum.proxmox.com/threads/177981/ +[1]: https://bugzilla.proxmox.com/show_bug.cgi?id=7222 + +Cc: qemu-stable@nongnu.org +Fixes: 7e277545b9 ("mirror: Skip writing zeroes when target is already zero") +Signed-off-by: Fiona Ebner +--- + block/mirror.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/block/mirror.c b/block/mirror.c +index b344182c74..bc982cb99a 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -1514,9 +1514,12 @@ do_sync_target_write(MirrorBlockJob *job, MirrorMethod method, + assert(!qiov); + ret = blk_co_pwrite_zeroes(job->target, offset, bytes, flags); + if (job->zero_bitmap && ret >= 0) { +- bitmap_set(job->zero_bitmap, dirty_bitmap_offset / job->granularity, +- (dirty_bitmap_end - dirty_bitmap_offset) / +- job->granularity); ++ if (dirty_bitmap_offset < dirty_bitmap_end) { ++ bitmap_set(job->zero_bitmap, ++ dirty_bitmap_offset / job->granularity, ++ (dirty_bitmap_end - dirty_bitmap_offset) / ++ job->granularity); ++ } + } + break; + diff --git a/debian/patches/series b/debian/patches/series index 83e7f6d..99d9369 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -9,6 +9,7 @@ extra/0008-ui-vdagent-fix-windows-agent-regression.patch extra/0009-file-posix-populate-pwrite_zeroes_alignment.patch extra/0010-block-use-pwrite_zeroes_alignment-when-writing-first.patch extra/0011-block-io_uring-avoid-potentially-getting-stuck-after.patch +extra/0012-block-mirror-check-range-when-setting-zero-bitmap-fo.patch bitmap-mirror/0001-drive-mirror-add-support-for-sync-bitmap-mode-never.patch bitmap-mirror/0002-drive-mirror-add-support-for-conditional-and-always-.patch bitmap-mirror/0003-mirror-add-check-for-bitmap-mode-without-bitmap.patch -- 2.47.3 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel