All of lore.kernel.org
 help / color / mirror / Atom feed
From: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
To: Jinpu Wang <jinpu.wang@cloud.ionos.com>,
	Nilay Shroff <nilay@linux.ibm.com>
Cc: linux-raid <linux-raid@vger.kernel.org>,
	linux-block <linux-block@vger.kernel.org>,
	Song Liu <song@kernel.org>, Jens Axboe <axboe@kernel.dk>,
	Christoph Hellwig <hch@lst.de>,
	Damien Le Moal <dlemoal@kernel.org>, Yu Kuai <yukuai@fygo.io>,
	tom.leiming@gmail.com
Subject: Re: [PATCH 0/6] md: don't wait for q->limits_lock while md holds back I/O
Date: Tue, 08 Sep 2026 20:37:56 +0200	[thread overview]
Message-ID: <m2bja7612z.fsf@gmail.com> (raw)
In-Reply-To: <CAMGffEmKrqcxYAtdTxg6GnwwFjJJg50wxpTfBobps-_QwQAoGg@mail.gmail.com>


Hi Jack and Nilay,

On Tue, Sep 08, 2026 at 14:09 +0200, Jinpu Wang wrote:
> On Tue, Sep 8, 2026 at 1:16 PM Nilay Shroff <nilay@linux.ibm.com> wrote:
>>
>> On 9/7/26 7:09 PM, Jack Wang wrote:
>> > From: Jack Wang<jinpu.wang@cloud.ionos.com>
>> >
>> > Writing to a queue limits attribute of an md array while a spare is
>> > being re-added deadlocks the array.  I reported this earlier here:
>> >
>> >    https://lore.kernel.org/linux-raid/CAMGffE=heGA3y8FjQ0Sm1jj-kd-=H9Y54WozKASSEZhc9UNKjA@mail.gmail.com/
>> >
>> > Four tasks, one array:
>> >
>> >    udev-worker    queue_attr_store() holds q->limits_lock, waits in
>> >                   blk_mq_freeze_queue() for q_usage_counter to drain
>> >    fio            holds a q_usage_counter reference, parked in
>> >                   md_handle_request()'s is_suspended() loop
>> >    mdadm          suspended the array, waits for reconfig_mutex
>> >    md_start_sync  holds reconfig_mutex, waits for q->limits_lock
>> >
>> > The last leg is mddev_stack_new_rdev() from ->hot_add_disk().  Since
>> > commit c99f66e4084a ("block: fix queue freeze vs limits lock order in
>> > sysfs store methods") the sysfs store holds q->limits_lock across the
>> > freeze, so md must not block on that lock while it is holding back the
>> > I/O the freeze waits for.  That is the same hazard mddev_suspend()
>> > already documents for reconfig_mutex.
>> >
>> > The rule this series applies is that q->limits_lock nests outside both
>> > reconfig_mutex and the suspend.  Where md cannot arrange that, because
>> > it is called with reconfig_mutex already held or from the sync thread,
>> > it takes the update with a trylock and does without one on a contended
>> > pass.
>> >
>> > Patches 1, 2 and 4 are plumbing with no functional change.  Patches 3
>> > and 5 convert the two callers that cannot own an update.  Patch 6 does
>> > the hoists, all in one patch because a mix of the two lock orders is an
>> > ABBA.
>> >
>> > Two callers still take q->limits_lock inside reconfig_mutex, both with
>> > the array suspended, and patch 6 says why: ->start_reshape() from
>> > action_store(), which suspends before flushing sync_work, and
>> > raid*_run() -> queue_limits_set() from level_store(), which already
>> > hangs on its own because it freezes the queue while suspended.  Both
>> > need more restructuring than belongs here.
>> >
>> > The patches are based on v7.3-rc2.
>> >
>> > Tested there with a raid1 of two ram devices, fio in flight and a loop
>> > writing queue/max_sectors_kb: 20 fail/remove/add cycles complete,
>> > where the same test wedges the array before the series.  Every patch
>> > builds on its own.  A reshape and a level change are not covered by that
>> > test.
>>
>> Overall, I think the direction looks good. With this series, we now have the
>> locking order where q->limits_lock is acquired before the suspend and
>> reconfig_mutex.
>>
>> However, when I ran these changes through blktests, I hit the lockdep splat[1],
>> which exposes an ABBA dependency between disk->open_mutex and q->limits_lock.
>>
>> Looking at the existing dependency chain, disk->open_mutex is expected to
>> be acquired before q->limits_lock. However, with this change, md_ioctl()
>> acquires q->limits_lock first and subsequently reaches md_import_device(),
>> which acquires disk->open_mutex. This reverses the existing lock ordering
>> and introduces the ABBA dependency, so I think this needs to be addressed.
>>
>
> Thanks for running this through blktests.
>
> You are right, and it is worse than the one path you hit.  The import is
> not the only offender: everything in the mddev->pers branch of
> md_add_new_disk() that opens or closes a component device runs with
> q->limits_lock held.  Besides md_import_device() there are four
> export_rdev() calls and one md_kick_rdev_from_array(), and export_rdev()
> ends in fput(rdev->bdev_file), so it takes disk->open_mutex too.
> rdev_attr_store() looks like a second instance: it starts the update for
> every state_store() write, and "remove" reaches
> md_kick_rdev_from_array().
>
> So the rule needs to be stronger than what I wrote: q->limits_lock nests
> outside reconfig_mutex and the suspend, and must not be held across any
> component device open or close.
>
> Two ways to get there, and I would rather hear which you prefer before
> respinning:
>
> 1) Keep the lock outermost, move the open and close out from under it.
>    md_ioctl() imports before taking q->limits_lock and releases after
>    committing and unlocking; md_add_new_disk() hands the rdev back
>    instead of exporting it.  The import then runs without
>    reconfig_mutex, so the superblock format fields need a snapshot and a
>    recheck under the lock.  Only the mddev->pers branch needs this, the
>    other two never reach add_bound_rdev().
>
> 2) Drop the hoist for ADD_NEW_DISK and stack the leg after resume, with
>    q->limits_lock on its own.  Much smaller, but the leg is live before
>    its limits are stacked and the integrity rejection lands after the
>    add rather than before it.
>
I am thinking about changeing the order of reconfig_mutex and the
suspention. we would suspend the array inside raid1_add_disk()
and raid1_remove_disk() when we add/remove the rdev from raid1 conf.

> Is there a better option?  If ->hot_add_disk() is meant to be callable
> with an update already in flight, that limits how far the open and close
> can move.
>
> Thanks,
> Jack

-- 
Best Regards,
Abd-Alrhman

  parent reply	other threads:[~2026-09-08 18:38 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
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 [this message]
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=m2bja7612z.fsf@gmail.com \
    --to=abd.masalkhi@gmail.com \
    --cc=axboe@kernel.dk \
    --cc=dlemoal@kernel.org \
    --cc=hch@lst.de \
    --cc=jinpu.wang@cloud.ionos.com \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-raid@vger.kernel.org \
    --cc=nilay@linux.ibm.com \
    --cc=song@kernel.org \
    --cc=tom.leiming@gmail.com \
    --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.