All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Jack Wang" <jinpu.wang@ionos.com>
Cc: linux-raid@vger.kernel.org, yukuai@fygo.io
Subject: Re: [PATCH 6/6] md: take q->limits_lock before locking and suspending the array
Date: Mon, 07 Sep 2026 14:00:31 +0000	[thread overview]
Message-ID: <20260907140031.C781F1F00A3D@smtp.kernel.org> (raw)
In-Reply-To: <20260907133929.1081540-7-jinpu.wang@ionos.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Medium] queue_limits_commit_update() return value is ignored and called unconditionally on error paths instead of queue_limits_cancel_update()

Pre-existing issues:
- [High] ABBA deadlock between q->limits_lock and mddev_suspend in level_store()
--

commit ecb6e260e45c52011fdf103645ad33814409ccd9
Author: Jack Wang <jinpu.wang@cloud.ionos.com>

md: take q->limits_lock before locking and suspending the array

This commit updates the block layer limits locking order for MD devices to
prevent a deadlock when writing queue limits attributes during disk operations.
It takes the limits update before locking and suspending the array, passing it
down into personality stacks.

> Two callers still take the lock inside reconfig_mutex, both with the
> array suspended: ->start_reshape() from action_store(), which suspends
> before flushing sync_work so the update cannot be held across it, and
> raid*_run() -> queue_limits_set() from level_store(), which already
> hangs on its own because it freezes the queue while suspended.

[Severity: High]
This is a pre-existing issue, but is there a plan to address the ABBA
deadlock in level_store()? When the array is suspended and locked, normal
I/O parks on the queue usage counter. Concurrently, a udev sysfs write can
take q->limits_lock and wait in blk_mq_freeze_queue() for the counter to
drain, while level_store() holds the suspend lock and waits for
q->limits_lock via pers->run() -> queue_limits_set(), causing a system
hang.

> diff --git a/drivers/md/md.c b/drivers/md/md.c
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -3780,15 +3783,37 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr,
[ ... ]
>  	rv = suspend ? mddev_suspend_and_lock(mddev) : mddev_lock(mddev);
>  	if (!rv) {
>  		if (rdev->mddev == NULL)
>  			rv = -ENODEV;
>  		else
> -			rv = entry->store(rdev, page, length, NULL);
> +			rv = entry->store(rdev, page, length, limp);
> +		/* apply the limits before the array takes I/O again */
> +		if (limp) {
> +			queue_limits_commit_update(q, limp);
> +			limp = NULL;
> +		}

[Severity: Medium]
Are we missing a check for the return value of queue_limits_commit_update()
here? If the block layer rejects the new limits because blk_validate_limits()
fails, the return value is ignored. This could allow the array to proceed
using the new disk with old limits, risking I/O errors if requests exceed
the disk's hardware limits.

>  		suspend ? mddev_unlock_and_resume(mddev) : mddev_unlock(mddev);
>  	}
>  
> +	if (limp)
> +		queue_limits_commit_update(q, limp);
> +

[Severity: Medium]
Does this code incorrectly call queue_limits_commit_update() unconditionally
on error paths? If mddev_suspend_and_lock() or mddev_lock() failed, rv will
be non-zero but limp will still be set. In this situation, the code will
commit unchanged limits instead of cancelling them via
queue_limits_cancel_update().

[ ... ]
> @@ -8618,6 +8673,9 @@ static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
>  	    err != -EINVAL)
>  		mddev->hold_active = 0;
>  
> +	if (limp)
> +		queue_limits_commit_update(q, limp);
> +

[Severity: Medium]
Similar to the rdev_attr_store() issue above, should this use
queue_limits_cancel_update() on error paths? If an inner ioctl command
fails, this will erroneously commit the unchanged limits rather than
cancelling the update.

[ ... ]
> @@ -10419,6 +10497,8 @@ static void md_start_sync(struct work_struct *ws)
>  	 *     https://bugzilla.kernel.org/show_bug.cgi?id=218200
>  	 * Therefore, use __mddev_resume(mddev, false).
>  	 */
> +	if (limp)
> +		queue_limits_commit_update(q, limp);

[Severity: Medium]
Does this safely handle limit validation failures when adding spares? The
return value is ignored, which could leave the array with outdated limits if
the limits fail to stack correctly.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260907133929.1081540-1-jinpu.wang@ionos.com?part=6

  reply	other threads:[~2026-09-07 14:00 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
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 [this message]
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=20260907140031.C781F1F00A3D@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 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.