And add a helper for the nr_hw_queues update instead. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- block/blk-mq.c | 23 ++--------------------- block/blk.h | 4 +--- block/elevator.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- block/elevator.h | 13 ------------- 4 files changed, 45 insertions(+), 39 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 5c9f7391af92..61d3349b3bb3 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -4968,27 +4968,8 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, blk_mq_map_swqueue(q); } - list_for_each_entry(q, &set->tag_list, tag_set_list) { - /* - * nr_hw_queues is changed and elevator data depends on - * it, so we have to force to rebuild elevator - */ - struct elv_change_ctx ctx = { - .name = "none", - .force = true, - .uevent = true, - }; - int ret = -ENODEV; - - mutex_lock(&q->elevator_lock); - if (q->elevator && !blk_queue_dying(q)) - ctx.name = q->elevator->type->elevator_name; - ret = __elevator_change(q, &ctx); - mutex_unlock(&q->elevator_lock); - blk_mq_unfreeze_queue_nomemrestore(q); - if (!ret) - WARN_ON_ONCE(elevator_change_done(q, &ctx)); - } + list_for_each_entry(q, &set->tag_list, tag_set_list) + elv_update_nr_hw_queues(q); memalloc_noio_restore(memflags); reregister: diff --git a/block/blk.h b/block/blk.h index 48cf6b1c36fe..6ba674d1ceba 100644 --- a/block/blk.h +++ b/block/blk.h @@ -12,7 +12,6 @@ #include "blk-crypto-internal.h" struct elevator_type; -struct elv_change_ctx; #define BLK_DEV_MAX_SECTORS (LLONG_MAX >> 9) #define BLK_MIN_SEGMENT_SIZE 4096 @@ -320,10 +319,9 @@ bool blk_bio_list_merge(struct request_queue *q, struct list_head *list, bool blk_insert_flush(struct request *rq); -int __elevator_change(struct request_queue *q, struct elv_change_ctx *ctx); +void elv_update_nr_hw_queues(struct request_queue *q); void elevator_set_default(struct request_queue *q); void elevator_set_none(struct request_queue *q); -int elevator_change_done(struct request_queue *q, struct elv_change_ctx *ctx); ssize_t part_size_show(struct device *dev, struct device_attribute *attr, char *buf); diff --git a/block/elevator.c b/block/elevator.c index 378553fce5d8..71329a73bb44 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -53,6 +53,19 @@ static LIST_HEAD(elv_list); */ #define rq_hash_key(rq) (blk_rq_pos(rq) + blk_rq_sectors(rq)) +/* Holding context data for changing elevator */ +struct elv_change_ctx { + const char *name; + bool force; + bool uevent; + bool init; + + /* for unregistering old elevator */ + struct elevator_queue *old; + /* for registering new elevator */ + struct elevator_queue *new; +}; + static int elevator_change(struct request_queue *q, struct elv_change_ctx *ctx); @@ -682,7 +695,8 @@ static void elevator_disable(struct request_queue *q, blk_mq_unquiesce_queue(q); } -int elevator_change_done(struct request_queue *q, struct elv_change_ctx *ctx) +static int elevator_change_done(struct request_queue *q, + struct elv_change_ctx *ctx) { int ret = 0; @@ -712,7 +726,8 @@ int elevator_change_done(struct request_queue *q, struct elv_change_ctx *ctx) /* * Switch this queue to the given IO scheduler. */ -int __elevator_change(struct request_queue *q, struct elv_change_ctx *ctx) +static int __elevator_change(struct request_queue *q, + struct elv_change_ctx *ctx) { const char *elevator_name = ctx->name; struct elevator_type *e; @@ -740,6 +755,31 @@ int __elevator_change(struct request_queue *q, struct elv_change_ctx *ctx) return ret; } +/* + * The I/O scheduler depends on the number of hardware queues, this forces a + * reattachment when nr_hw_queues changes. + * + * Note that this unfreezes the passed in queue. + */ +void elv_update_nr_hw_queues(struct request_queue *q) +{ + struct elv_change_ctx ctx = { + .name = "none", + .force = true, + .uevent = true, + }; + int ret; + + mutex_lock(&q->elevator_lock); + if (q->elevator && !blk_queue_dying(q)) + ctx.name = q->elevator->type->elevator_name; + ret = __elevator_change(q, &ctx); + mutex_unlock(&q->elevator_lock); + blk_mq_unfreeze_queue_nomemrestore(q); + if (!ret) + WARN_ON_ONCE(elevator_change_done(q, &ctx)); +} + static int elevator_change(struct request_queue *q, struct elv_change_ctx *ctx) { diff --git a/block/elevator.h b/block/elevator.h index b14c611c74b6..a07ce773a38f 100644 --- a/block/elevator.h +++ b/block/elevator.h @@ -124,19 +124,6 @@ struct elevator_queue #define ELEVATOR_FLAG_DYING 1 #define ELEVATOR_FLAG_ENABLE_WBT_ON_EXIT 2 -/* Holding context data for changing elevator */ -struct elv_change_ctx { - const char *name; - bool force; - bool uevent; - bool init; - - /* for unregistering old elevator */ - struct elevator_queue *old; - /* for registering new elevator */ - struct elevator_queue *new; -}; - /* * block elevator interface */ -- 2.47.2 --IS0zKkzwUGydFO0o Content-Type: text/x-patch; charset=us-ascii Content-Disposition: attachment; filename="0002-block-remove-__elevator_change.patch"