all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Fiona Ebner <f.ebner@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH qemu 1/2] fix #7222: add fix for crash caused by zero write during sync drive mirror
Date: Mon, 12 Jan 2026 16:59:25 +0100	[thread overview]
Message-ID: <20260112155940.298273-2-f.ebner@proxmox.com> (raw)
In-Reply-To: <20260112155940.298273-1-f.ebner@proxmox.com>

Upstream submission [0].

[0]: https://lore.kernel.org/qemu-devel/20260112152544.261923-1-f.ebner@proxmox.com/T/

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
 ...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 <f.ebner@proxmox.com>
  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 <t.lamprecht@proxmox.com>
  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 <t.lamprecht@proxmox.com>
  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 <f.ebner@proxmox.com>
  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 <f.ebner@proxmox.com>
+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 <f.ebner@proxmox.com>
+---
+ 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


  reply	other threads:[~2026-01-12 16:00 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-12 15:59 [pve-devel] [PATCH-SERIES qemu 0/2] fix two completely different bugs both caused by non-aligned zero writes Fiona Ebner
2026-01-12 15:59 ` Fiona Ebner [this message]
2026-01-12 15:59 ` [pve-devel] [PATCH qemu 2/2] fix #7197: add fix to avoid misaligned BLKZEROOUT casuing a hard error Fiona Ebner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260112155940.298273-2-f.ebner@proxmox.com \
    --to=f.ebner@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal