block: Revert "block: Fix potential deadlock while freezing queue and acquiring sysfs_lock"

commit 224749be6c23efe7fb8a030854f4fc5d1dd813b3 upstream.

This reverts commit be26ba96421ab0a8fa2055ccf7db7832a13c44d2.

Commit be26ba96421a ("block: Fix potential deadlock while freezing queue and
acquiring sysfs_loc") actually reverts commit 22465bbac53c ("blk-mq: move cpuhp
callback registering out of q->sysfs_lock"), and causes the original resctrl
lockdep warning.

So revert it and we need to fix the issue in another way.

Cc: Nilay Shroff <nilay@linux.ibm.com>
Fixes: be26ba96421a ("block: Fix potential deadlock while freezing queue and acquiring sysfs_loc")
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20241218101617.3275704-2-ming.lei@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Ming Lei
2024-12-18 18:16:14 +08:00
committed by Greg Kroah-Hartman
parent b2b4eddf2f
commit 97701315e3
3 changed files with 23 additions and 26 deletions
+10 -6
View File
@@ -275,13 +275,15 @@ void blk_mq_sysfs_unregister_hctxs(struct request_queue *q)
struct blk_mq_hw_ctx *hctx; struct blk_mq_hw_ctx *hctx;
unsigned long i; unsigned long i;
lockdep_assert_held(&q->sysfs_dir_lock); mutex_lock(&q->sysfs_dir_lock);
if (!q->mq_sysfs_init_done) if (!q->mq_sysfs_init_done)
return; goto unlock;
queue_for_each_hw_ctx(q, hctx, i) queue_for_each_hw_ctx(q, hctx, i)
blk_mq_unregister_hctx(hctx); blk_mq_unregister_hctx(hctx);
unlock:
mutex_unlock(&q->sysfs_dir_lock);
} }
int blk_mq_sysfs_register_hctxs(struct request_queue *q) int blk_mq_sysfs_register_hctxs(struct request_queue *q)
@@ -290,10 +292,9 @@ int blk_mq_sysfs_register_hctxs(struct request_queue *q)
unsigned long i; unsigned long i;
int ret = 0; int ret = 0;
lockdep_assert_held(&q->sysfs_dir_lock); mutex_lock(&q->sysfs_dir_lock);
if (!q->mq_sysfs_init_done) if (!q->mq_sysfs_init_done)
return ret; goto unlock;
queue_for_each_hw_ctx(q, hctx, i) { queue_for_each_hw_ctx(q, hctx, i) {
ret = blk_mq_register_hctx(hctx); ret = blk_mq_register_hctx(hctx);
@@ -301,5 +302,8 @@ int blk_mq_sysfs_register_hctxs(struct request_queue *q)
break; break;
} }
unlock:
mutex_unlock(&q->sysfs_dir_lock);
return ret; return ret;
} }
+11 -18
View File
@@ -4462,8 +4462,7 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
unsigned long i, j; unsigned long i, j;
/* protect against switching io scheduler */ /* protect against switching io scheduler */
lockdep_assert_held(&q->sysfs_lock); mutex_lock(&q->sysfs_lock);
for (i = 0; i < set->nr_hw_queues; i++) { for (i = 0; i < set->nr_hw_queues; i++) {
int old_node; int old_node;
int node = blk_mq_get_hctx_node(set, i); int node = blk_mq_get_hctx_node(set, i);
@@ -4496,6 +4495,7 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
xa_for_each_start(&q->hctx_table, j, hctx, j) xa_for_each_start(&q->hctx_table, j, hctx, j)
blk_mq_exit_hctx(q, set, hctx, j); blk_mq_exit_hctx(q, set, hctx, j);
mutex_unlock(&q->sysfs_lock);
/* unregister cpuhp callbacks for exited hctxs */ /* unregister cpuhp callbacks for exited hctxs */
blk_mq_remove_hw_queues_cpuhp(q); blk_mq_remove_hw_queues_cpuhp(q);
@@ -4527,14 +4527,10 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
xa_init(&q->hctx_table); xa_init(&q->hctx_table);
mutex_lock(&q->sysfs_lock);
blk_mq_realloc_hw_ctxs(set, q); blk_mq_realloc_hw_ctxs(set, q);
if (!q->nr_hw_queues) if (!q->nr_hw_queues)
goto err_hctxs; goto err_hctxs;
mutex_unlock(&q->sysfs_lock);
INIT_WORK(&q->timeout_work, blk_mq_timeout_work); INIT_WORK(&q->timeout_work, blk_mq_timeout_work);
blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30 * HZ); blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30 * HZ);
@@ -4553,7 +4549,6 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
return 0; return 0;
err_hctxs: err_hctxs:
mutex_unlock(&q->sysfs_lock);
blk_mq_release(q); blk_mq_release(q);
err_exit: err_exit:
q->mq_ops = NULL; q->mq_ops = NULL;
@@ -4934,12 +4929,12 @@ static bool blk_mq_elv_switch_none(struct list_head *head,
return false; return false;
/* q->elevator needs protection from ->sysfs_lock */ /* q->elevator needs protection from ->sysfs_lock */
lockdep_assert_held(&q->sysfs_lock); mutex_lock(&q->sysfs_lock);
/* the check has to be done with holding sysfs_lock */ /* the check has to be done with holding sysfs_lock */
if (!q->elevator) { if (!q->elevator) {
kfree(qe); kfree(qe);
goto out; goto unlock;
} }
INIT_LIST_HEAD(&qe->node); INIT_LIST_HEAD(&qe->node);
@@ -4949,7 +4944,9 @@ static bool blk_mq_elv_switch_none(struct list_head *head,
__elevator_get(qe->type); __elevator_get(qe->type);
list_add(&qe->node, head); list_add(&qe->node, head);
elevator_disable(q); elevator_disable(q);
out: unlock:
mutex_unlock(&q->sysfs_lock);
return true; return true;
} }
@@ -4978,9 +4975,11 @@ static void blk_mq_elv_switch_back(struct list_head *head,
list_del(&qe->node); list_del(&qe->node);
kfree(qe); kfree(qe);
mutex_lock(&q->sysfs_lock);
elevator_switch(q, t); elevator_switch(q, t);
/* drop the reference acquired in blk_mq_elv_switch_none */ /* drop the reference acquired in blk_mq_elv_switch_none */
elevator_put(t); elevator_put(t);
mutex_unlock(&q->sysfs_lock);
} }
static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
@@ -5000,11 +4999,8 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
if (set->nr_maps == 1 && nr_hw_queues == set->nr_hw_queues) if (set->nr_maps == 1 && nr_hw_queues == set->nr_hw_queues)
return; return;
list_for_each_entry(q, &set->tag_list, tag_set_list) { list_for_each_entry(q, &set->tag_list, tag_set_list)
mutex_lock(&q->sysfs_dir_lock);
mutex_lock(&q->sysfs_lock);
blk_mq_freeze_queue(q); blk_mq_freeze_queue(q);
}
/* /*
* Switch IO scheduler to 'none', cleaning up the data associated * Switch IO scheduler to 'none', cleaning up the data associated
* with the previous scheduler. We will switch back once we are done * with the previous scheduler. We will switch back once we are done
@@ -5060,11 +5056,8 @@ switch_back:
list_for_each_entry(q, &set->tag_list, tag_set_list) list_for_each_entry(q, &set->tag_list, tag_set_list)
blk_mq_elv_switch_back(&head, q); blk_mq_elv_switch_back(&head, q);
list_for_each_entry(q, &set->tag_list, tag_set_list) { list_for_each_entry(q, &set->tag_list, tag_set_list)
blk_mq_unfreeze_queue(q); blk_mq_unfreeze_queue(q);
mutex_unlock(&q->sysfs_lock);
mutex_unlock(&q->sysfs_dir_lock);
}
/* Free the excess tags when nr_hw_queues shrink. */ /* Free the excess tags when nr_hw_queues shrink. */
for (i = set->nr_hw_queues; i < prev_nr_hw_queues; i++) for (i = set->nr_hw_queues; i < prev_nr_hw_queues; i++)
+2 -2
View File
@@ -690,11 +690,11 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
return res; return res;
} }
mutex_lock(&q->sysfs_lock);
blk_mq_freeze_queue(q); blk_mq_freeze_queue(q);
mutex_lock(&q->sysfs_lock);
res = entry->store(disk, page, length); res = entry->store(disk, page, length);
blk_mq_unfreeze_queue(q);
mutex_unlock(&q->sysfs_lock); mutex_unlock(&q->sysfs_lock);
blk_mq_unfreeze_queue(q);
return res; return res;
} }