diff --git a/block/blk-mq.c b/block/blk-mq.c index fe7ff041bd6d..6418c2a7cd2c 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -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)