blk-mq-sched: provide hooks for initializing hardware queue data
Schedulers need to be informed when a hardware queue is added or removed at runtime so they can allocate/free per-hardware queue data. So, replace the blk_mq_sched_init_hctx_data() helper, which only makes sense at init time, with .init_hctx() and .exit_hctx() hooks. Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@fb.com>hifive-unleashed-5.1
parent
65f619d253
commit
ee056f9812
|
@ -30,43 +30,6 @@ void blk_mq_sched_free_hctx_data(struct request_queue *q,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(blk_mq_sched_free_hctx_data);
|
EXPORT_SYMBOL_GPL(blk_mq_sched_free_hctx_data);
|
||||||
|
|
||||||
int blk_mq_sched_init_hctx_data(struct request_queue *q, size_t size,
|
|
||||||
int (*init)(struct blk_mq_hw_ctx *),
|
|
||||||
void (*exit)(struct blk_mq_hw_ctx *))
|
|
||||||
{
|
|
||||||
struct blk_mq_hw_ctx *hctx;
|
|
||||||
int ret;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
queue_for_each_hw_ctx(q, hctx, i) {
|
|
||||||
hctx->sched_data = kmalloc_node(size, GFP_KERNEL, hctx->numa_node);
|
|
||||||
if (!hctx->sched_data) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (init) {
|
|
||||||
ret = init(hctx);
|
|
||||||
if (ret) {
|
|
||||||
/*
|
|
||||||
* We don't want to give exit() a partially
|
|
||||||
* initialized sched_data. init() must clean up
|
|
||||||
* if it fails.
|
|
||||||
*/
|
|
||||||
kfree(hctx->sched_data);
|
|
||||||
hctx->sched_data = NULL;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
error:
|
|
||||||
blk_mq_sched_free_hctx_data(q, exit);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(blk_mq_sched_init_hctx_data);
|
|
||||||
|
|
||||||
static void __blk_mq_sched_assign_ioc(struct request_queue *q,
|
static void __blk_mq_sched_assign_ioc(struct request_queue *q,
|
||||||
struct request *rq,
|
struct request *rq,
|
||||||
struct bio *bio,
|
struct bio *bio,
|
||||||
|
@ -508,11 +471,24 @@ int blk_mq_sched_init_hctx(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
|
||||||
unsigned int hctx_idx)
|
unsigned int hctx_idx)
|
||||||
{
|
{
|
||||||
struct elevator_queue *e = q->elevator;
|
struct elevator_queue *e = q->elevator;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!e)
|
if (!e)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return blk_mq_sched_alloc_tags(q, hctx, hctx_idx);
|
ret = blk_mq_sched_alloc_tags(q, hctx, hctx_idx);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (e->type->ops.mq.init_hctx) {
|
||||||
|
ret = e->type->ops.mq.init_hctx(hctx, hctx_idx);
|
||||||
|
if (ret) {
|
||||||
|
blk_mq_sched_free_tags(q->tag_set, hctx, hctx_idx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void blk_mq_sched_exit_hctx(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
|
void blk_mq_sched_exit_hctx(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
|
||||||
|
@ -523,12 +499,18 @@ void blk_mq_sched_exit_hctx(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
|
||||||
if (!e)
|
if (!e)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (e->type->ops.mq.exit_hctx && hctx->sched_data) {
|
||||||
|
e->type->ops.mq.exit_hctx(hctx, hctx_idx);
|
||||||
|
hctx->sched_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
blk_mq_sched_free_tags(q->tag_set, hctx, hctx_idx);
|
blk_mq_sched_free_tags(q->tag_set, hctx, hctx_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
|
int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
|
||||||
{
|
{
|
||||||
struct blk_mq_hw_ctx *hctx;
|
struct blk_mq_hw_ctx *hctx;
|
||||||
|
struct elevator_queue *eq;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -553,6 +535,18 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
if (e->ops.mq.init_hctx) {
|
||||||
|
queue_for_each_hw_ctx(q, hctx, i) {
|
||||||
|
ret = e->ops.mq.init_hctx(hctx, i);
|
||||||
|
if (ret) {
|
||||||
|
eq = q->elevator;
|
||||||
|
blk_mq_exit_sched(q, eq);
|
||||||
|
kobject_put(&eq->kobj);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
@ -563,6 +557,17 @@ err:
|
||||||
|
|
||||||
void blk_mq_exit_sched(struct request_queue *q, struct elevator_queue *e)
|
void blk_mq_exit_sched(struct request_queue *q, struct elevator_queue *e)
|
||||||
{
|
{
|
||||||
|
struct blk_mq_hw_ctx *hctx;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (e->type->ops.mq.exit_hctx) {
|
||||||
|
queue_for_each_hw_ctx(q, hctx, i) {
|
||||||
|
if (hctx->sched_data) {
|
||||||
|
e->type->ops.mq.exit_hctx(hctx, i);
|
||||||
|
hctx->sched_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (e->type->ops.mq.exit_sched)
|
if (e->type->ops.mq.exit_sched)
|
||||||
e->type->ops.mq.exit_sched(e);
|
e->type->ops.mq.exit_sched(e);
|
||||||
blk_mq_sched_tags_teardown(q);
|
blk_mq_sched_tags_teardown(q);
|
||||||
|
|
|
@ -4,10 +4,6 @@
|
||||||
#include "blk-mq.h"
|
#include "blk-mq.h"
|
||||||
#include "blk-mq-tag.h"
|
#include "blk-mq-tag.h"
|
||||||
|
|
||||||
int blk_mq_sched_init_hctx_data(struct request_queue *q, size_t size,
|
|
||||||
int (*init)(struct blk_mq_hw_ctx *),
|
|
||||||
void (*exit)(struct blk_mq_hw_ctx *));
|
|
||||||
|
|
||||||
void blk_mq_sched_free_hctx_data(struct request_queue *q,
|
void blk_mq_sched_free_hctx_data(struct request_queue *q,
|
||||||
void (*exit)(struct blk_mq_hw_ctx *));
|
void (*exit)(struct blk_mq_hw_ctx *));
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,8 @@ struct blk_mq_hw_ctx;
|
||||||
struct elevator_mq_ops {
|
struct elevator_mq_ops {
|
||||||
int (*init_sched)(struct request_queue *, struct elevator_type *);
|
int (*init_sched)(struct request_queue *, struct elevator_type *);
|
||||||
void (*exit_sched)(struct elevator_queue *);
|
void (*exit_sched)(struct elevator_queue *);
|
||||||
|
int (*init_hctx)(struct blk_mq_hw_ctx *, unsigned int);
|
||||||
|
void (*exit_hctx)(struct blk_mq_hw_ctx *, unsigned int);
|
||||||
|
|
||||||
bool (*allow_merge)(struct request_queue *, struct request *, struct bio *);
|
bool (*allow_merge)(struct request_queue *, struct request *, struct bio *);
|
||||||
bool (*bio_merge)(struct blk_mq_hw_ctx *, struct bio *);
|
bool (*bio_merge)(struct blk_mq_hw_ctx *, struct bio *);
|
||||||
|
|
Loading…
Reference in New Issue