From: sashiko-bot@kernel.org
To: "Jack Wang" <jinpu.wang@ionos.com>
Cc: linux-raid@vger.kernel.org, yukuai@fygo.io
Subject: Re: [PATCH 2/6] md: pass a queue_limits down to ->hot_add_disk()
Date: Mon, 07 Sep 2026 13:56:03 +0000 [thread overview]
Message-ID: <20260907135604.280C41F00A3D@smtp.kernel.org> (raw)
In-Reply-To: <20260907133929.1081540-3-jinpu.wang@ionos.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
New issues:
- [High] `linear_add()` ignores the new `lim` argument and unconditionally calls `queue_limits_set()`, which will cause a deadlock.
Pre-existing issues:
- [High] Missing limit check and queue limit stacking for replacement disks in `raid1_add_disk()`.
- [High] Missing limits update and stacking when hot-adding a disk in `raid5_add_disk()`.
--
commit 37bd7159af00deb7b9d45549d34775a10b587170
Author: Jack Wang <jinpu.wang@cloud.ionos.com>
md: pass a queue_limits down to ->hot_add_disk()
Adding a leg stacks its queue limits, which mddev_stack_new_rdev() does
by taking q->limits_lock itself. Callers that hold reconfig_mutex, or
have the array suspended, must not do that: the lock's holder waits for
I/O they are blocking. They need to own the update instead.
Give ->hot_add_disk(), remove_and_add_spares() and
md_choose_sync_action() a queue_limits argument, and add
mddev_stack_rdev_into() to stack into a caller-owned update. Every
caller passes NULL, so no functional change; the users follow.
> diff --git a/drivers/md/md-linear.c b/drivers/md/md-linear.c
> index 73b367b61b873..1f44c2d7db93d 100644
> --- a/drivers/md/md-linear.c
> +++ b/drivers/md/md-linear.c
> @@ -186,7 +186,8 @@ static int linear_run(struct mddev *mddev)
> return ret;
> }
>
> -static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
> +static int linear_add(struct mddev *mddev, struct md_rdev *rdev,
> + struct queue_limits *lim)
> {
> /* Adding a drive to a linear array allows the array to grow.
> * It is permitted if the new drive has a matching superblock
[Severity: High]
Does linear_add() miss using the new lim argument?
Looking at the body of linear_add(), it unconditionally calls linear_conf()
without passing the limits down. In the final state of this patch series, when
the caller already holds q->limits_lock, linear_conf() will eventually call
queue_limits_set() which tries to take the lock again. Could this lead to a
deadlock on q->limits_lock when hot-adding a disk?
[ ... ]
> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
> index f0646fb24371f..dd348b5695d06 100644
> --- a/drivers/md/raid1.c
> +++ b/drivers/md/raid1.c
> @@ -1898,7 +1898,8 @@ static bool raid1_remove_conf(struct r1conf *conf, int disk)
> return true;
> }
>
> -static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
> +static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev,
> + struct queue_limits *lim)
> {
> struct r1conf *conf = mddev->private;
> int err = -EEXIST;
> @@ -1923,7 +1924,10 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
> for (mirror = first; mirror <= last; mirror++) {
> p = conf->mirrors + mirror;
> if (!p->rdev) {
> - err = mddev_stack_new_rdev(mddev, rdev);
> + if (lim)
> + err = mddev_stack_rdev_into(mddev, rdev, lim);
> + else
> + err = mddev_stack_new_rdev(mddev, rdev);
> if (err)
> return err;
[Severity: High]
This is a pre-existing issue, but I noticed that further down in
raid1_add_disk(), we add a replacement disk but omit any limit checks:
if (err && repl_slot >= 0) {
/* Add this device as a replacement */
clear_bit(In_sync, &rdev->flags);
set_bit(Replacement, &rdev->flags);
raid1_add_conf(conf, rdev, repl_slot, true);
err = 0;
conf->fullsync = 1;
}
Since mddev_stack_new_rdev() or mddev_stack_rdev_into() is skipped for this
path, could this allow a replacement disk with incompatible queue limits
(such as differing integrity profiles or larger logical block sizes) to join
the array, resulting in data corruption or I/O failures?
[ ... ]
> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
> index b91545ce090de..0ec555ada64a0 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -8441,7 +8441,8 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
> return err;
> }
>
> -static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev)
> +static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev,
> + struct queue_limits *lim)
> {
> struct r5conf *conf = mddev->private;
> int ret, err = -EEXIST;
[Severity: High]
This isn't a bug introduced by this patch, but I noticed that raid5_add_disk()
does not stack or check queue limits at all when hot-adding a disk:
for (disk = first; disk <= last; disk++) {
p = conf->disks + disk;
if (p->rdev == NULL) {
clear_bit(In_sync, &rdev->flags);
rdev->raid_disk = disk;
if (rdev->saved_raid_disk != disk)
conf->fullsync = 1;
WRITE_ONCE(p->rdev, rdev);
err = log_modify(conf, rdev, true);
goto out;
}
}
Because mddev_stack_new_rdev() or mddev_stack_rdev_into() are not called
here, and the new lim argument is ignored, could this allow disks with
incompatible limits to be successfully added to the array?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260907133929.1081540-1-jinpu.wang@ionos.com?part=2
next prev parent reply other threads:[~2026-09-07 13:56 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-07 13:39 [PATCH 0/6] md: don't wait for q->limits_lock while md holds back I/O Jack Wang
2026-09-07 13:39 ` [PATCH 1/6] block: add queue_limits_start_update_trylock() Jack Wang
2026-09-09 6:29 ` Christoph Hellwig
2026-09-09 10:35 ` Jinpu Wang
2026-09-07 13:39 ` [PATCH 2/6] md: pass a queue_limits down to ->hot_add_disk() Jack Wang
2026-09-07 13:56 ` sashiko-bot [this message]
2026-09-08 4:43 ` Jinpu Wang
2026-09-07 13:39 ` [PATCH 3/6] md: don't wait for q->limits_lock in check_sb_changes() Jack Wang
2026-09-07 13:56 ` sashiko-bot
2026-09-08 4:41 ` Jinpu Wang
2026-09-07 13:39 ` [PATCH 4/6] md: pass a queue_limits through the rdev sysfs stores Jack Wang
2026-09-07 13:39 ` [PATCH 5/6] md: don't wait for q->limits_lock in mddev_update_io_opt() Jack Wang
2026-09-07 13:39 ` [PATCH 6/6] md: take q->limits_lock before locking and suspending the array Jack Wang
2026-09-07 14:00 ` sashiko-bot
2026-09-08 4:44 ` Jinpu Wang
2026-09-08 11:15 ` [PATCH 0/6] md: don't wait for q->limits_lock while md holds back I/O Nilay Shroff
2026-09-08 12:09 ` Jinpu Wang
2026-09-08 18:25 ` Nilay Shroff
2026-09-09 4:25 ` Jinpu Wang
2026-09-08 18:37 ` Abd-Alrhman Masalkhi
2026-09-08 21:51 ` Abd-Alrhman Masalkhi
2026-09-09 4:28 ` Jinpu Wang
2026-09-08 17:00 ` Johannes Thumshirn
2026-09-09 6:30 ` Christoph Hellwig
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=20260907135604.280C41F00A3D@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=jinpu.wang@ionos.com \
--cc=linux-raid@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=yukuai@fygo.io \
/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