block: move elevator tags into struct elevator_resources

This patch introduces a new structure, struct elevator_resources, to
group together all elevator-related resources that share the same
lifetime. As a first step, this change moves the elevator tag pointer
from struct elv_change_ctx into the new struct elevator_resources.

Additionally, rename blk_mq_alloc_sched_tags_batch() and
blk_mq_free_sched_tags_batch() to blk_mq_alloc_sched_res_batch() and
blk_mq_free_sched_res_batch(), respectively. Introduce two new wrapper
helpers, blk_mq_alloc_sched_res() and blk_mq_free_sched_res(), around
blk_mq_alloc_sched_tags() and blk_mq_free_sched_tags().

These changes pave the way for consolidating the allocation and freeing
of elevator-specific resources into common helper functions. This
refactoring improves encapsulation and prepares the code for future
extensions, allowing additional elevator-specific data to be added to
struct elevator_resources without cluttering struct elv_change_ctx.

Subsequent patches will extend struct elevator_resources to include
other elevator-related data.

Reviewed-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Yu Kuai <yukuai@fnnas.com>
Signed-off-by: Nilay Shroff <nilay@linux.ibm.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Nilay Shroff
2025-11-13 14:28:19 +05:30
committed by Jens Axboe
parent 232143b605
commit 04728ce909
5 changed files with 64 additions and 36 deletions

View File

@@ -427,7 +427,16 @@ void blk_mq_free_sched_tags(struct elevator_tags *et,
kfree(et);
}
void blk_mq_free_sched_tags_batch(struct xarray *elv_tbl,
void blk_mq_free_sched_res(struct elevator_resources *res,
struct blk_mq_tag_set *set)
{
if (res->et) {
blk_mq_free_sched_tags(res->et, set);
res->et = NULL;
}
}
void blk_mq_free_sched_res_batch(struct xarray *elv_tbl,
struct blk_mq_tag_set *set)
{
struct request_queue *q;
@@ -445,12 +454,11 @@ void blk_mq_free_sched_tags_batch(struct xarray *elv_tbl,
*/
if (q->elevator) {
ctx = xa_load(elv_tbl, q->id);
if (!ctx || !ctx->et) {
if (!ctx) {
WARN_ON_ONCE(1);
continue;
}
blk_mq_free_sched_tags(ctx->et, set);
ctx->et = NULL;
blk_mq_free_sched_res(&ctx->res, set);
}
}
}
@@ -531,12 +539,24 @@ out:
return NULL;
}
int blk_mq_alloc_sched_tags_batch(struct xarray *elv_tbl,
int blk_mq_alloc_sched_res(struct request_queue *q,
struct elevator_resources *res, unsigned int nr_hw_queues)
{
struct blk_mq_tag_set *set = q->tag_set;
res->et = blk_mq_alloc_sched_tags(set, nr_hw_queues,
blk_mq_default_nr_requests(set));
if (!res->et)
return -ENOMEM;
return 0;
}
int blk_mq_alloc_sched_res_batch(struct xarray *elv_tbl,
struct blk_mq_tag_set *set, unsigned int nr_hw_queues)
{
struct elv_change_ctx *ctx;
struct request_queue *q;
struct elevator_tags *et;
int ret = -ENOMEM;
lockdep_assert_held_write(&set->update_nr_hwq_lock);
@@ -556,11 +576,10 @@ int blk_mq_alloc_sched_tags_batch(struct xarray *elv_tbl,
goto out_unwind;
}
ctx->et = blk_mq_alloc_sched_tags(set, nr_hw_queues,
blk_mq_default_nr_requests(set));
if (!ctx->et)
ret = blk_mq_alloc_sched_res(q, &ctx->res,
nr_hw_queues);
if (ret)
goto out_unwind;
}
}
return 0;
@@ -568,10 +587,8 @@ out_unwind:
list_for_each_entry_continue_reverse(q, &set->tag_list, tag_set_list) {
if (q->elevator) {
ctx = xa_load(elv_tbl, q->id);
if (ctx && ctx->et) {
blk_mq_free_sched_tags(ctx->et, set);
ctx->et = NULL;
}
if (ctx)
blk_mq_free_sched_res(&ctx->res, set);
}
}
return ret;
@@ -579,9 +596,10 @@ out_unwind:
/* caller must have a reference to @e, will grab another one if successful */
int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e,
struct elevator_tags *et)
struct elevator_resources *res)
{
unsigned int flags = q->tag_set->flags;
struct elevator_tags *et = res->et;
struct blk_mq_hw_ctx *hctx;
struct elevator_queue *eq;
unsigned long i;

View File

@@ -19,20 +19,24 @@ void __blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx);
void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx);
int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e,
struct elevator_tags *et);
struct elevator_resources *res);
void blk_mq_exit_sched(struct request_queue *q, struct elevator_queue *e);
void blk_mq_sched_free_rqs(struct request_queue *q);
struct elevator_tags *blk_mq_alloc_sched_tags(struct blk_mq_tag_set *set,
unsigned int nr_hw_queues, unsigned int nr_requests);
int blk_mq_alloc_sched_tags_batch(struct xarray *et_table,
int blk_mq_alloc_sched_res(struct request_queue *q,
struct elevator_resources *res, unsigned int nr_hw_queues);
int blk_mq_alloc_sched_res_batch(struct xarray *elv_tbl,
struct blk_mq_tag_set *set, unsigned int nr_hw_queues);
int blk_mq_alloc_sched_ctx_batch(struct xarray *elv_tbl,
struct blk_mq_tag_set *set);
void blk_mq_free_sched_ctx_batch(struct xarray *elv_tbl);
void blk_mq_free_sched_tags(struct elevator_tags *et,
struct blk_mq_tag_set *set);
void blk_mq_free_sched_tags_batch(struct xarray *et_table,
void blk_mq_free_sched_res(struct elevator_resources *res,
struct blk_mq_tag_set *set);
void blk_mq_free_sched_res_batch(struct xarray *et_table,
struct blk_mq_tag_set *set);
static inline void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx)

View File

@@ -5072,7 +5072,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
if (blk_mq_alloc_sched_ctx_batch(&elv_tbl, set) < 0)
goto out_free_ctx;
if (blk_mq_alloc_sched_tags_batch(&elv_tbl, set, nr_hw_queues) < 0)
if (blk_mq_alloc_sched_res_batch(&elv_tbl, set, nr_hw_queues) < 0)
goto out_free_ctx;
list_for_each_entry(q, &set->tag_list, tag_set_list) {

View File

@@ -580,7 +580,7 @@ static int elevator_switch(struct request_queue *q, struct elv_change_ctx *ctx)
}
if (new_e) {
ret = blk_mq_init_sched(q, new_e, ctx->et);
ret = blk_mq_init_sched(q, new_e, &ctx->res);
if (ret)
goto out_unfreeze;
ctx->new = q->elevator;
@@ -604,7 +604,8 @@ out_unfreeze:
return ret;
}
static void elv_exit_and_release(struct request_queue *q)
static void elv_exit_and_release(struct elv_change_ctx *ctx,
struct request_queue *q)
{
struct elevator_queue *e;
unsigned memflags;
@@ -616,7 +617,7 @@ static void elv_exit_and_release(struct request_queue *q)
mutex_unlock(&q->elevator_lock);
blk_mq_unfreeze_queue(q, memflags);
if (e) {
blk_mq_free_sched_tags(e->et, q->tag_set);
blk_mq_free_sched_res(&ctx->res, q->tag_set);
kobject_put(&e->kobj);
}
}
@@ -627,11 +628,12 @@ static int elevator_change_done(struct request_queue *q,
int ret = 0;
if (ctx->old) {
struct elevator_resources res = {.et = ctx->old->et};
bool enable_wbt = test_bit(ELEVATOR_FLAG_ENABLE_WBT_ON_EXIT,
&ctx->old->flags);
elv_unregister_queue(q, ctx->old);
blk_mq_free_sched_tags(ctx->old->et, q->tag_set);
blk_mq_free_sched_res(&res, q->tag_set);
kobject_put(&ctx->old->kobj);
if (enable_wbt)
wbt_enable_default(q->disk);
@@ -639,7 +641,7 @@ static int elevator_change_done(struct request_queue *q,
if (ctx->new) {
ret = elv_register_queue(q, ctx->new, !ctx->no_uevent);
if (ret)
elv_exit_and_release(q);
elv_exit_and_release(ctx, q);
}
return ret;
}
@@ -656,10 +658,9 @@ static int elevator_change(struct request_queue *q, struct elv_change_ctx *ctx)
lockdep_assert_held(&set->update_nr_hwq_lock);
if (strncmp(ctx->name, "none", 4)) {
ctx->et = blk_mq_alloc_sched_tags(set, set->nr_hw_queues,
blk_mq_default_nr_requests(set));
if (!ctx->et)
return -ENOMEM;
ret = blk_mq_alloc_sched_res(q, &ctx->res, set->nr_hw_queues);
if (ret)
return ret;
}
memflags = blk_mq_freeze_queue(q);
@@ -681,10 +682,10 @@ static int elevator_change(struct request_queue *q, struct elv_change_ctx *ctx)
if (!ret)
ret = elevator_change_done(q, ctx);
/*
* Free sched tags if it's allocated but we couldn't switch elevator.
* Free sched resource if it's allocated but we couldn't switch elevator.
*/
if (ctx->et && !ctx->new)
blk_mq_free_sched_tags(ctx->et, set);
if (!ctx->new)
blk_mq_free_sched_res(&ctx->res, set);
return ret;
}
@@ -711,10 +712,10 @@ void elv_update_nr_hw_queues(struct request_queue *q,
if (!ret)
WARN_ON_ONCE(elevator_change_done(q, ctx));
/*
* Free sched tags if it's allocated but we couldn't switch elevator.
* Free sched resource if it's allocated but we couldn't switch elevator.
*/
if (ctx->et && !ctx->new)
blk_mq_free_sched_tags(ctx->et, set);
if (!ctx->new)
blk_mq_free_sched_res(&ctx->res, set);
}
/*

View File

@@ -32,6 +32,11 @@ struct elevator_tags {
struct blk_mq_tags *tags[];
};
struct elevator_resources {
/* holds elevator tags */
struct elevator_tags *et;
};
/* Holding context data for changing elevator */
struct elv_change_ctx {
const char *name;
@@ -43,8 +48,8 @@ struct elv_change_ctx {
struct elevator_queue *new;
/* store elevator type */
struct elevator_type *type;
/* holds sched tags data */
struct elevator_tags *et;
/* store elevator resources */
struct elevator_resources res;
};
struct elevator_mq_ops {