mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
blk-mq: exit the hctxs of a queue under tag_list_lock
blk_mq_update_nr_hw_queues() exits and replaces the hctxs of every queue
on set->tag_list under tag_list_lock. blk_mq_exit_queue() exits its
hctxs without the lock and only then takes the queue off the list, so an
update running at the same time exits them again and sets up new ones
that nobody exits. del_gendisk() is kept away by update_nr_hwq_lock,
disk_release() of a never added disk and blk_mq_destroy_queue() are not,
and nvme_alloc_ns() drops such a disk when it finds the queues frozen by
a reset.
Hold tag_list_lock for both steps.
Fixes: 630ef623ed ("blk-mq: Swap two calls in blk_mq_exit_queue()")
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261028164415.1262013-38-axboe@kernel.dk
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
71ec3c7d6d
commit
89a2381482
|
|
@ -4338,7 +4338,8 @@ static void blk_mq_del_queue_tag_set(struct request_queue *q)
|
|||
{
|
||||
struct blk_mq_tag_set *set = q->tag_set;
|
||||
|
||||
mutex_lock(&set->tag_list_lock);
|
||||
lockdep_assert_held(&set->tag_list_lock);
|
||||
|
||||
list_del_rcu(&q->tag_set_list);
|
||||
if (list_is_singular(&set->tag_list)) {
|
||||
/* just transitioned to unshared */
|
||||
|
|
@ -4346,7 +4347,6 @@ static void blk_mq_del_queue_tag_set(struct request_queue *q)
|
|||
/* update existing queue */
|
||||
blk_mq_update_tag_set_shared(set, false);
|
||||
}
|
||||
mutex_unlock(&set->tag_list_lock);
|
||||
}
|
||||
|
||||
static void blk_mq_add_queue_tag_set(struct blk_mq_tag_set *set,
|
||||
|
|
@ -4710,10 +4710,16 @@ void blk_mq_exit_queue(struct request_queue *q)
|
|||
{
|
||||
struct blk_mq_tag_set *set = q->tag_set;
|
||||
|
||||
/*
|
||||
* As long as the queue is on set->tag_list, its hctxs belong to
|
||||
* blk_mq_update_nr_hw_queues() as well, which exits and replaces them.
|
||||
*/
|
||||
mutex_lock(&set->tag_list_lock);
|
||||
/* Checks hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED. */
|
||||
blk_mq_exit_hw_queues(q, set, set->nr_hw_queues);
|
||||
/* May clear BLK_MQ_F_TAG_QUEUE_SHARED in hctx->flags. */
|
||||
blk_mq_del_queue_tag_set(q);
|
||||
mutex_unlock(&set->tag_list_lock);
|
||||
}
|
||||
|
||||
static int __blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user