From: "yu kuai" <yukuai@fygo.io>
To: "Doug V Johnson" <me@dougvj.me>, <linux-raid@vger.kernel.org>,
"yu kuai" <yukuai@fygo.io>
Cc: <song@kernel.org>, <magiclinan@didiglobal.com>, <xiao@kernel.org>,
<chencheng@fnnas.com>, <linux-kernel@vger.kernel.org>,
"Yu Kuai" <yukuai1@huaweicloud.com>
Subject: Re: [PATCH v4 2/3] md/raid5: do not reshape if overlapping rdev bad block ranges prevent it
Date: Sat, 24 Oct 2026 14:37:45 +0800 [thread overview]
Message-ID: <34c07a33-808b-48c8-b749-54e0d81bb3ca@fygo.io> (raw)
In-Reply-To: <010101a142f581e5-36ad5604-721c-4ad0-86f3-62ca283b6133-000000@us-west-2.amazonses.com>
Hi,
在 2026/10/16 12:25, Doug V Johnson 写道:
> Ensure that a reshape is not started if there are more than max_degraded
> devices in the array that are either out of sync, faulty, missing,
> or have overlapping bad blocks such that a read is not recoverable.
>
> Cheaply verify that the number of bad or unavailable devices exceeds
> the max number of degraded drives and if so sweep the bad block lists
> on each device for overlaps using a new function array_has_badblock().
>
> Invoke this function in raid5_start_reshape() and if the array has
> unreadable blocks, return -EIO to report it to userspace.
>
> Leave in place the existing functionality to handle a failed reshape
> in progress because it's possible for bad blocks to be discovered or
> placed in metadata after a reshape has already been initiated.
>
> Link: https://lore.kernel.org/r/21f250f9-04b5-76f6-84c9-1fd245b748c6@huaweicloud.com
> Link: https://lore.kernel.org/r/a9119707-4fa1-58cb-377c-63df67f88957@huaweicloud.com
> Suggested-by: Yu Kuai <yukuai1@huaweicloud.com>
> Assisted-by: LLM
> Signed-off-by: Doug V Johnson <me@dougvj.me>
> ---
> drivers/md/raid5.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 88 insertions(+)
I think we can be more extreme here, by refusing to reshape if any rdev has badblocks,
this is much simpler and if any disk already have badblocks, it's possible new badblocks
can happen during reshape.
>
> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
> index 86ea65559576..23ff549fa363 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -8636,6 +8636,89 @@ static int check_reshape(struct mddev *mddev)
> + mddev->delta_disks));
> }
>
> +static int rdev_is_unavailable(struct md_rdev *rdev)
> +{
> + return !rdev || test_bit(Faulty, &rdev->flags) ||
> + !test_bit(In_sync, &rdev->flags);
> +}
> +
> +static int array_has_badblock(struct r5conf *conf)
> +{
> + sector_t dev_sectors = conf->mddev->dev_sectors;
> + sector_t stripe_sectors = RAID5_STRIPE_SECTORS(conf);
> + sector_t max_sectors = round_down((sector_t)INT_MAX, stripe_sectors);
> + sector_t offset = 0;
> + int num_bad_devs = 0;
> + int i;
> +
> + /* Check if there are even enough bad disks for a bad block condition */
> + for (i = 0; i < conf->raid_disks; i++) {
> + struct md_rdev *rdev = conf->disks[i].rdev;
> +
> + if (rdev_is_unavailable(rdev) || rdev->badblocks.count)
> + num_bad_devs++;
> + }
> + if (num_bad_devs <= conf->max_degraded)
> + return 0;
> +
> + /*
> + * Sweep the sectors of the array for bad blocks in constituent devices.
> + * Within a stripe if there are more bad disks than can be recoverable
> + * (max degraded) then the array has bad blocks.
> + *
> + * The offset tracks the sweep. We advance to the first bad stripe
> + * boundary found in any device.
> + */
> + while (offset < dev_sectors) {
> + sector_t len = min(dev_sectors - offset, max_sectors);
> + int bad_disks = 0;
> +
> + for (i = 0; i < conf->raid_disks; i++) {
> + struct md_rdev *rdev = conf->disks[i].rdev;
> + sector_t first_bad, bad_sectors, end;
> +
> + if (rdev_is_unavailable(rdev)) {
> + bad_disks++;
> + continue;
> + }
> + if (!rdev->badblocks.count)
> + continue;
> + if (!badblocks_check(&rdev->badblocks,
> + rdev->data_offset + offset, len,
> + &first_bad, &bad_sectors))
> + continue;
> +
> + /*
> + * Rebase the bad blocks start and end to the device's data
> + * offset for consistent comparision
> + */
> + end = first_bad + bad_sectors - rdev->data_offset;
> + first_bad = max(first_bad, rdev->data_offset) -
> + rdev->data_offset;
> +
> + /* Snap the range to the stripe boundary extent */
> + first_bad = round_down(first_bad, stripe_sectors);
> + end = round_up(end, stripe_sectors);
> +
> + /*
> + * This device has a bad block at or overlapping the current
> + * sweep position, so it's a bad disk
> + */
> + if (first_bad <= offset) {
> + len = min(len, end - offset);
> + bad_disks++;
> + } else {
> + len = min(len, first_bad - offset);
> + }
> + }
> + if (bad_disks > conf->max_degraded)
> + return 1;
> + offset += len;
> + cond_resched();
> + }
> + return 0;
> +}
> +
> static int raid5_start_reshape(struct mddev *mddev)
> {
> struct r5conf *conf = mddev->private;
> @@ -8685,6 +8768,11 @@ static int raid5_start_reshape(struct mddev *mddev)
> mdname(mddev));
> return -EINVAL;
> }
> + if (array_has_badblock(conf)) {
> + pr_warn("md/raid:%s: reshape not possible due to bad block list\n",
> + mdname(mddev));
> + return -EIO;
> + }
> if (md_bitmap_enabled(mddev, false) &&
> mddev->bitmap_id == ID_LLBITMAP) {
> i = mddev->bitmap_ops->resize(mddev, mddev->dev_sectors, 0);
--
Thanks,
Kuai
prev parent reply other threads:[~2026-10-24 6:37 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20261016042537.277516-1-me@dougvj.me>
2026-10-16 4:25 ` [PATCH v4 1/3] md/raid5: freeze and interrupt reshape when handling failed reshape Doug V Johnson
2026-10-16 4:36 ` sashiko-bot
2026-10-22 7:36 ` Chen Cheng
2026-10-24 6:32 ` yu kuai
2026-10-16 4:25 ` [PATCH v4 3/3] md/raid5: warn when a read fails due in some part to bad-block metadata Doug V Johnson
2026-10-16 4:25 ` [PATCH v4 2/3] md/raid5: do not reshape if overlapping rdev bad block ranges prevent it Doug V Johnson
2026-10-24 6:37 ` yu kuai [this message]
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=34c07a33-808b-48c8-b749-54e0d81bb3ca@fygo.io \
--to=yukuai@fygo.io \
--cc=chencheng@fnnas.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-raid@vger.kernel.org \
--cc=magiclinan@didiglobal.com \
--cc=me@dougvj.me \
--cc=song@kernel.org \
--cc=xiao@kernel.org \
--cc=yukuai1@huaweicloud.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox