elv_update_nr_hw_queues is very different from the other elevator change cases, so open code the logic there. Move the lookup of the elevator type into elevator_switch to simplify this a bit. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- block/elevator.c | 73 ++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/block/elevator.c b/block/elevator.c index 71329a73bb44..e51f7b8bad16 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -56,7 +56,6 @@ static LIST_HEAD(elv_list); /* Holding context data for changing elevator */ struct elv_change_ctx { const char *name; - bool force; bool uevent; bool init; @@ -644,11 +643,15 @@ void elevator_set_none(struct request_queue *q) * If switching fails, we are most likely running out of memory and not able * to restore the old io scheduler, so leaving the io scheduler being none. */ -static int elevator_switch(struct request_queue *q, struct elevator_type *new_e, - struct elv_change_ctx *ctx) +static int elevator_switch(struct request_queue *q, struct elv_change_ctx *ctx) { + struct elevator_type *new_e; int ret; + new_e = elevator_find_get(ctx->name); + if (!new_e) + return -EINVAL; + WARN_ON_ONCE(q->mq_freeze_depth == 0); lockdep_assert_held(&q->elevator_lock); @@ -674,6 +677,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e, new_e->elevator_name); } + elevator_put(new_e); return ret; } @@ -723,38 +727,6 @@ static int elevator_change_done(struct request_queue *q, return 0; } -/* - * Switch this queue to the given IO scheduler. - */ -static int __elevator_change(struct request_queue *q, - struct elv_change_ctx *ctx) -{ - const char *elevator_name = ctx->name; - struct elevator_type *e; - int ret; - - /* Make sure queue is not in the middle of being removed */ - if (!ctx->init && !blk_queue_registered(q)) - return -ENOENT; - - if (!strncmp(elevator_name, "none", 4)) { - if (q->elevator) - elevator_disable(q, ctx); - return 0; - } - - if (!ctx->force && q->elevator && - elevator_match(q->elevator->type, elevator_name)) - return 0; - - e = elevator_find_get(elevator_name); - if (!e) - return -EINVAL; - ret = elevator_switch(q, e, ctx); - elevator_put(e); - return ret; -} - /* * The I/O scheduler depends on the number of hardware queues, this forces a * reattachment when nr_hw_queues changes. @@ -764,19 +736,25 @@ static int __elevator_change(struct request_queue *q, void elv_update_nr_hw_queues(struct request_queue *q) { struct elv_change_ctx ctx = { - .name = "none", - .force = true, .uevent = true, }; - int ret; + bool done = false; mutex_lock(&q->elevator_lock); - if (q->elevator && !blk_queue_dying(q)) + if (!blk_queue_registered(q)) + goto out_unlock; + + if (q->elevator) { ctx.name = q->elevator->type->elevator_name; - ret = __elevator_change(q, &ctx); + if (elevator_switch(q, &ctx) == 0) + done = true; + } + +out_unlock: mutex_unlock(&q->elevator_lock); blk_mq_unfreeze_queue_nomemrestore(q); - if (!ret) + + if (done) WARN_ON_ONCE(elevator_change_done(q, &ctx)); } @@ -785,7 +763,7 @@ static int elevator_change(struct request_queue *q, { struct blk_mq_tag_set *set = q->tag_set; unsigned int memflags; - int ret, idx; + int ret = 0, idx; idx = srcu_read_lock(&set->update_nr_hwq_srcu); if (set->updating_nr_hwq) { @@ -805,7 +783,16 @@ static int elevator_change(struct request_queue *q, */ blk_mq_cancel_work_sync(q); mutex_lock(&q->elevator_lock); - ret = __elevator_change(q, ctx); + /* Make sure queue is not in the middle of being removed */ + if (!ctx->init && !blk_queue_registered(q)) { + ret = -ENOENT; + } else if (!strncmp(ctx->name, "none", 4)) { + if (q->elevator) + elevator_disable(q, ctx); + } else if (!q->elevator || + !elevator_match(q->elevator->type, ctx->name)) { + ret = elevator_switch(q, ctx); + } mutex_unlock(&q->elevator_lock); blk_mq_unfreeze_queue(q, memflags); if (!ret) -- 2.47.2 --IS0zKkzwUGydFO0o--