Skip to content
Permalink
Browse files
blk: make blk-rq-qos support pluggable and modular policy
blk-rq-qos is a standalone framework out of io-sched and can be
used to control or observe the IO progress in block-layer with
hooks. blk-rq-qos is a great design but right now, it is totally
fixed and built-in and shut out peoples who want to use it with
external module.

This patch make blk-rq-qos policies pluggable and modular.
(1) Add code to maintain the rq_qos_ops. A rq-qos module need to
    register itself with rq_qos_register(). The original enum
    rq_qos_id will be removed in following patch. They will use
    a dynamic id maintained by rq_qos_ida.
(2) Add .init callback into rq_qos_ops. We use it to initialize the
    resource.
(3) Add /sys/block/x/queue/qos
    We can use '+name' or "-name" to open or close the blk-rq-qos
    policy.

Because the rq-qos list can be modified at anytime, rq_qos_id()
which has been renamed to rq_qos_by_id() has to iterate the list
under sysfs_lock or queue_lock. This patch adapts the code for this.
More details, please refer to the comment above rq_qos_get(), And
the rq_qos_exit() is moved to blk_cleanup_queue. Except for these
modification, there is no other functional change here. Following
patches will adpat the code of wbt, iolatency, iocost and ioprio
to make them pluggable and modular one by one.

Signed-off-by: Wang Jianchao <wangjianchao@kuaishou.com>
  • Loading branch information
Wang Jianchao authored and intel-lab-lkp committed Jan 10, 2022
1 parent 12ab2b5 commit 8bef9fba59d8d47ecaebbeff3e62ee550d89b017
Show file tree
Hide file tree
Showing 10 changed files with 394 additions and 17 deletions.
@@ -51,6 +51,7 @@
#include "blk-mq-sched.h"
#include "blk-pm.h"
#include "blk-throttle.h"
#include "blk-rq-qos.h"

struct dentry *blk_debugfs_root;

@@ -377,6 +378,7 @@ void blk_cleanup_queue(struct request_queue *q)
* it is safe to free requests now.
*/
mutex_lock(&q->sysfs_lock);
rq_qos_exit(q);
if (q->elevator)
blk_mq_sched_free_rqs(q);
mutex_unlock(&q->sysfs_lock);
@@ -662,7 +662,7 @@ static struct ioc *rqos_to_ioc(struct rq_qos *rqos)

static struct ioc *q_to_ioc(struct request_queue *q)
{
return rqos_to_ioc(rq_qos_id(q, RQ_QOS_COST));
return rqos_to_ioc(rq_qos_by_id(q, RQ_QOS_COST));
}

static const char *q_name(struct request_queue *q)
@@ -3162,6 +3162,7 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
size_t nbytes, loff_t off)
{
struct block_device *bdev;
struct rq_qos *rqos;
struct ioc *ioc;
u32 qos[NR_QOS_PARAMS];
bool enable, user;
@@ -3172,14 +3173,15 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
if (IS_ERR(bdev))
return PTR_ERR(bdev);

ioc = q_to_ioc(bdev_get_queue(bdev));
if (!ioc) {
rqos = rq_qos_get(bdev_get_queue(bdev), RQ_QOS_COST);
if (!rqos) {
ret = blk_iocost_init(bdev_get_queue(bdev));
if (ret)
goto err;
ioc = q_to_ioc(bdev_get_queue(bdev));
rqos = rq_qos_get(bdev_get_queue(bdev), RQ_QOS_COST);
}

ioc = rqos_to_ioc(rqos);
spin_lock_irq(&ioc->lock);
memcpy(qos, ioc->params.qos, sizeof(qos));
enable = ioc->enabled;
@@ -3272,10 +3274,12 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
ioc_refresh_params(ioc, true);
spin_unlock_irq(&ioc->lock);

rq_qos_put(rqos);
blkdev_put_no_open(bdev);
return nbytes;
einval:
ret = -EINVAL;
rq_qos_put(rqos);
err:
blkdev_put_no_open(bdev);
return ret;
@@ -3329,6 +3333,7 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
size_t nbytes, loff_t off)
{
struct block_device *bdev;
struct rq_qos *rqos;
struct ioc *ioc;
u64 u[NR_I_LCOEFS];
bool user;
@@ -3339,14 +3344,15 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
if (IS_ERR(bdev))
return PTR_ERR(bdev);

ioc = q_to_ioc(bdev_get_queue(bdev));
rqos = rq_qos_get(bdev_get_queue(bdev), RQ_QOS_COST);
if (!ioc) {
ret = blk_iocost_init(bdev_get_queue(bdev));
if (ret)
goto err;
ioc = q_to_ioc(bdev_get_queue(bdev));
rqos = rq_qos_get(bdev_get_queue(bdev), RQ_QOS_COST);
}

ioc = rqos_to_ioc(rqos);
spin_lock_irq(&ioc->lock);
memcpy(u, ioc->params.i_lcoefs, sizeof(u));
user = ioc->user_cost_model;
@@ -3397,11 +3403,13 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
ioc_refresh_params(ioc, true);
spin_unlock_irq(&ioc->lock);

rq_qos_put(rqos);
blkdev_put_no_open(bdev);
return nbytes;

einval:
ret = -EINVAL;
rq_qos_put(rqos);
err:
blkdev_put_no_open(bdev);
return ret;
@@ -841,7 +841,9 @@ void blk_mq_debugfs_unregister_rqos(struct rq_qos *rqos)
void blk_mq_debugfs_register_rqos(struct rq_qos *rqos)
{
struct request_queue *q = rqos->q;
const char *dir_name = rq_qos_id_to_name(rqos->id);
const char *dir_name;

dir_name = rqos->ops->name ? rqos->ops->name : rq_qos_id_to_name(rqos->id);

if (rqos->debugfs_dir || !rqos->ops->debugfs_attrs)
return;

0 comments on commit 8bef9fb

Please sign in to comment.