Re: [PATCH 1/4] md/md-bitmap: mask sb->state on load to drop runtime-only bits
From: yu kuai
Date: Sun Jul 19 2026 - 21:56:33 EST
Hi,
在 2026/7/19 22:44, Mykola Marzhan 写道:
> md_bitmap_read_sb() does `bitmap->flags |= le32_to_cpu(sb->state)`
> with no mask, so any bit set in the on-disk state field becomes a
> runtime flag. With BITMAP_WRITE_ERROR (bit 2) set on disk,
> md_bitmap_create() fails with -EIO and the array refuses to assemble
> until the bitmap superblock is rewritten externally.
>
> That bit can genuinely be on disk: kernels before v4.15 wrote
> sb->state unmasked -- commit 97f0eb9f0fec ("md/bitmap: clear
> BITMAP_WRITE_ERROR bit before writing it to sb") added the
> write-side clear -- so an array that hit a transient bitmap write
> error under an older kernel carries the bit forever. On-disk
> corruption or an external write plants it today.
>
> The write side has masked WRITE_ERROR out since v4.15; the load side
> is the missing half. Mask the loaded state to BITMAP_STALE, the
> only bit this loader consumes: WRITE_ERROR and DAEMON_BUSY are
> kernel-runtime signals, FIRST_USE and CLEAN are used only by the
> llbitmap loader (a superblock this loader accepts cannot carry
> them, since versions above BITMAP_MAJOR_CLUSTERED are rejected),
> and HOSTENDIAN is derived from sb->version, not sb->state.
>
> Reproducer: write 0x04 into byte offset 48 (the state field) of the
> bitmap superblock on every member (a single forged member can be
> masked by another member's clean copy), then assemble: RUN_ARRAY
> fails with -EIO. With this fix the array starts and sb->events
> advances normally.
This is not a reproducer, BITMAP_WRITE_ERROR indicate that bitmap to all member disks
failed, and bitmap no longer works for the array, so it's not safe to assemble with this
bitmap.
I think it's reasonable to assemble this array with bitmap=none.
>
> Fixes: 32a7627cf3a3 ("[PATCH] md: optimised resync using Bitmap based intent logging")
> Cc: stable@xxxxxxxxxxxxxxx
> Assisted-by: Claude-Code:claude-opus-4-8
> Signed-off-by: Mykola Marzhan <mykola@xxxxxxxxxxx>
> ---
> drivers/md/md-bitmap.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
> index 0f02e2956398..4dd3fc2a9e15 100644
> --- a/drivers/md/md-bitmap.c
> +++ b/drivers/md/md-bitmap.c
> @@ -931,8 +931,13 @@ static int md_bitmap_read_sb(struct bitmap *bitmap)
> }
> }
>
> - /* assign fields using values from superblock */
> - bitmap->flags |= le32_to_cpu(sb->state);
> + /*
> + * Only BITMAP_STALE is meaningful to this loader from sb->state:
> + * WRITE_ERROR and DAEMON_BUSY are kernel-runtime signals (kernels
> + * before v4.15 persisted WRITE_ERROR), FIRST_USE/CLEAN are
> + * llbitmap-only, and HOSTENDIAN is derived from sb->version below.
> + */
> + bitmap->flags |= le32_to_cpu(sb->state) & BIT(BITMAP_STALE);
> if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN)
> set_bit(BITMAP_HOSTENDIAN, &bitmap->flags);
> bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
--
Thanks,
Kuai