Re: [PATCH 2/4] md/md-llbitmap: mask sb->state on load to drop runtime-only bits
From: yu kuai
Date: Sun Jul 19 2026 - 22:01:04 EST
Hi,
在 2026/7/19 22:44, Mykola Marzhan 写道:
> llbitmap_read_sb() copies sb->state straight into llbitmap->flags
> with no mask, so any bit set in the on-disk state field becomes a
> runtime flag. With BITMAP_WRITE_ERROR (bit 2) on disk,
> llbitmap_enabled() returns false for the array's entire lifetime:
> llbitmap_update_sb() early-returns, the state machine returns
> BitNone, the bits attribute reports "bitmap io error", and on-disk
> sb->events stops advancing. The bitmap is silently disabled with no
> log line attributing the cause, and the next clean reassemble forces
> a full resync because sb->events is stale.
For llbitmap, it's using md_write_metadata(), if it's failed for one rdev,
md_error() is called directly for this rdev. So if BITMAP_WRITE_ERROR exist,
the array is already broken. And in this case, if array can still reassemble,
a full resync is the expected behavior.
>
> Runtime bits do reach disk: llbitmap_update_sb() writes the raw
> flags word, so BITMAP_DAEMON_BUSY is persisted whenever a superblock
> update coincides with a daemon-period overrun -- the condition that
> logs "daemon_work not finished". WRITE_ERROR itself has no
> reachable write-side path today (its only setter is update_sb's own
> read-failure branch, which returns before writing), but on-disk
> corruption or an external write plants it all the same.
>
> Mask the loaded state to the bits this loader consumes (STALE,
> FIRST_USE and CLEAN), as the previous patch did for the classic
> loader. Masking at load neutralises whatever is on disk and is the
> minimal backportable fix; masking the write side is left as a
> follow-up cleanup.
>
> Reproducer: write 0x04 into byte offset 48 (the state field) of the
> llbitmap superblock on every member (a forge on a single member can
> be masked by another member's clean copy), then assemble. Without this
> fix the bits attribute reports "bitmap io error" and sb->events is
> frozen; with it the bitmap is alive and sb->events advances
> normally.
>
> Fixes: 5ab829f1971d ("md/md-llbitmap: introduce new lockless bitmap")
> Cc: stable@xxxxxxxxxxxxxxx # v6.18+
> Assisted-by: Claude-Code:claude-opus-4-8
> Signed-off-by: Mykola Marzhan <mykola@xxxxxxxxxxx>
> ---
> drivers/md/md-llbitmap.c | 10 +++++++++-
> 1 file changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
> index e8f853e8461d..0b591124dc63 100644
> --- a/drivers/md/md-llbitmap.c
> +++ b/drivers/md/md-llbitmap.c
> @@ -981,7 +981,15 @@ static int llbitmap_read_sb(struct llbitmap *llbitmap)
> else
> mddev->bitmap_info.space = mddev->bitmap_info.default_space;
> }
> - llbitmap->flags = le32_to_cpu(sb->state);
> + /*
> + * Mask the loaded state to the bits this loader consumes.
> + * WRITE_ERROR and DAEMON_BUSY are kernel-runtime signals; a stray
> + * WRITE_ERROR trusted from disk silently disables the bitmap for
> + * the array's entire lifetime.
> + */
> + llbitmap->flags = le32_to_cpu(sb->state) &
> + (BIT(BITMAP_STALE) | BIT(BITMAP_FIRST_USE) |
> + BIT(BITMAP_CLEAN));
> if (test_and_clear_bit(BITMAP_FIRST_USE, &llbitmap->flags)) {
> ret = llbitmap_init(llbitmap);
> goto out_put_page;
--
Thanks,
Kuai