Skip to content

Commit c2df6f3

Browse files
author
Ming Lei
committed
block: simplify elevator reattachment for updating nr_hw_queues
JIRA: https://issues.redhat.com/browse/RHEL-106845 commit 596dce1 Author: Ming Lei <ming.lei@redhat.com> Date: Mon May 5 22:17:51 2025 +0800 block: simplify elevator reattachment for updating nr_hw_queues In blk_mq_update_nr_hw_queues(), nr_hw_queues changes and elevator data depends on it, and elevator has to be reattached, so call elevator_switch() to force attachment. Add elv_update_nr_hw_queues() simply for blk_mq_update_nr_hw_queues() to reattach elevator, since elevator switch isn't likely when running blk_mq_update_nr_hw_queues(). This way removes the current switch none and switch back code. Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Nilay Shroff <nilay@linux.ibm.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Ming Lei <ming.lei@redhat.com> Link: https://lore.kernel.org/r/20250505141805.2751237-14-ming.lei@redhat.com Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Ming Lei <ming.lei@redhat.com>
1 parent 05b38a7 commit c2df6f3

File tree

3 files changed

+21
-92
lines changed

3 files changed

+21
-92
lines changed

block/blk-mq.c

Lines changed: 1 addition & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -4987,88 +4987,10 @@ int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr)
49874987
return ret;
49884988
}
49894989

4990-
/*
4991-
* request_queue and elevator_type pair.
4992-
* It is just used by __blk_mq_update_nr_hw_queues to cache
4993-
* the elevator_type associated with a request_queue.
4994-
*/
4995-
struct blk_mq_qe_pair {
4996-
struct list_head node;
4997-
struct request_queue *q;
4998-
struct elevator_type *type;
4999-
};
5000-
5001-
/*
5002-
* Cache the elevator_type in qe pair list and switch the
5003-
* io scheduler to 'none'
5004-
*/
5005-
static bool blk_mq_elv_switch_none(struct list_head *head,
5006-
struct request_queue *q)
5007-
{
5008-
struct blk_mq_qe_pair *qe;
5009-
5010-
qe = kmalloc(sizeof(*qe), GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY);
5011-
if (!qe)
5012-
return false;
5013-
5014-
/* Accessing q->elevator needs protection from ->elevator_lock. */
5015-
mutex_lock(&q->elevator_lock);
5016-
5017-
if (!q->elevator) {
5018-
kfree(qe);
5019-
goto unlock;
5020-
}
5021-
5022-
INIT_LIST_HEAD(&qe->node);
5023-
qe->q = q;
5024-
qe->type = q->elevator->type;
5025-
/* keep a reference to the elevator module as we'll switch back */
5026-
__elevator_get(qe->type);
5027-
list_add(&qe->node, head);
5028-
elevator_disable(q);
5029-
unlock:
5030-
mutex_unlock(&q->elevator_lock);
5031-
5032-
return true;
5033-
}
5034-
5035-
static struct blk_mq_qe_pair *blk_lookup_qe_pair(struct list_head *head,
5036-
struct request_queue *q)
5037-
{
5038-
struct blk_mq_qe_pair *qe;
5039-
5040-
list_for_each_entry(qe, head, node)
5041-
if (qe->q == q)
5042-
return qe;
5043-
5044-
return NULL;
5045-
}
5046-
5047-
static void blk_mq_elv_switch_back(struct list_head *head,
5048-
struct request_queue *q)
5049-
{
5050-
struct blk_mq_qe_pair *qe;
5051-
struct elevator_type *t;
5052-
5053-
qe = blk_lookup_qe_pair(head, q);
5054-
if (!qe)
5055-
return;
5056-
t = qe->type;
5057-
list_del(&qe->node);
5058-
kfree(qe);
5059-
5060-
mutex_lock(&q->elevator_lock);
5061-
elevator_switch(q, t->elevator_name);
5062-
/* drop the reference acquired in blk_mq_elv_switch_none */
5063-
elevator_put(t);
5064-
mutex_unlock(&q->elevator_lock);
5065-
}
5066-
50674990
static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
50684991
int nr_hw_queues)
50694992
{
50704993
struct request_queue *q;
5071-
LIST_HEAD(head);
50724994
int prev_nr_hw_queues = set->nr_hw_queues;
50734995
unsigned int memflags;
50744996
int i;
@@ -5086,15 +5008,6 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
50865008
list_for_each_entry(q, &set->tag_list, tag_set_list)
50875009
blk_mq_freeze_queue_nomemsave(q);
50885010

5089-
/*
5090-
* Switch IO scheduler to 'none', cleaning up the data associated
5091-
* with the previous scheduler. We will switch back once we are done
5092-
* updating the new sw to hw queue mappings.
5093-
*/
5094-
list_for_each_entry(q, &set->tag_list, tag_set_list)
5095-
if (!blk_mq_elv_switch_none(&head, q))
5096-
goto switch_back;
5097-
50985011
list_for_each_entry(q, &set->tag_list, tag_set_list) {
50995012
blk_mq_debugfs_unregister_hctxs(q);
51005013
blk_mq_sysfs_unregister_hctxs(q);
@@ -5128,9 +5041,8 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
51285041
blk_mq_debugfs_register_hctxs(q);
51295042
}
51305043

5131-
switch_back:
51325044
list_for_each_entry(q, &set->tag_list, tag_set_list)
5133-
blk_mq_elv_switch_back(&head, q);
5045+
elv_update_nr_hw_queues(q);
51345046

51355047
list_for_each_entry(q, &set->tag_list, tag_set_list)
51365048
blk_mq_unfreeze_queue_nomemrestore(q);

block/blk.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,7 @@ bool blk_bio_list_merge(struct request_queue *q, struct list_head *list,
322322

323323
bool blk_insert_flush(struct request *rq);
324324

325-
int elevator_switch(struct request_queue *q, const char *name);
326-
void elevator_disable(struct request_queue *q);
325+
void elv_update_nr_hw_queues(struct request_queue *q);
327326
void elevator_exit(struct request_queue *q);
328327
int elv_register_queue(struct request_queue *q, bool uevent);
329328
void elv_unregister_queue(struct request_queue *q);

block/elevator.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ void elevator_init_mq(struct request_queue *q)
621621
* If switching fails, we are most likely running out of memory and not able
622622
* to restore the old io scheduler, so leaving the io scheduler being none.
623623
*/
624-
int elevator_switch(struct request_queue *q, const char *name)
624+
static int elevator_switch(struct request_queue *q, const char *name)
625625
{
626626
struct elevator_type *new_e = NULL;
627627
int ret = 0;
@@ -682,6 +682,24 @@ static int elevator_change(struct request_queue *q, const char *elevator_name)
682682
return elevator_switch(q, elevator_name);
683683
}
684684

685+
/*
686+
* The I/O scheduler depends on the number of hardware queues, this forces a
687+
* reattachment when nr_hw_queues changes.
688+
*/
689+
void elv_update_nr_hw_queues(struct request_queue *q)
690+
{
691+
WARN_ON_ONCE(q->mq_freeze_depth == 0);
692+
693+
mutex_lock(&q->elevator_lock);
694+
if (q->elevator && !blk_queue_dying(q) && !blk_queue_registered(q)) {
695+
const char *name = q->elevator->type->elevator_name;
696+
697+
/* force to reattach elevator after nr_hw_queue is updated */
698+
elevator_switch(q, name);
699+
}
700+
mutex_unlock(&q->elevator_lock);
701+
}
702+
685703
static void elv_iosched_load_module(char *elevator_name)
686704
{
687705
struct elevator_type *found;

0 commit comments

Comments
 (0)