blk-mq-debugfs: support rq_qos
blk-mq-debugfs has been proved as very helpful for debug some tough issues, such as IO hang. We have seen blk-wbt related IO hang several times, even inside Red Hat BZ, there is such report not sovled yet, so this patch adds support debugfs on rq_qos. Cc: Bart Van Assche <bart.vanassche@wdc.com> Cc: Omar Sandoval <osandov@fb.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
f9824952ee
commit
cc56694f13
|
@ -23,6 +23,7 @@
|
|||
#include "blk-mq.h"
|
||||
#include "blk-mq-debugfs.h"
|
||||
#include "blk-mq-tag.h"
|
||||
#include "blk-rq-qos.h"
|
||||
|
||||
static void print_stat(struct seq_file *m, struct blk_rq_stat *stat)
|
||||
{
|
||||
|
@ -856,6 +857,15 @@ int blk_mq_debugfs_register(struct request_queue *q)
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (q->rq_qos) {
|
||||
struct rq_qos *rqos = q->rq_qos;
|
||||
|
||||
while (rqos) {
|
||||
blk_mq_debugfs_register_rqos(rqos);
|
||||
rqos = rqos->next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
@ -978,6 +988,50 @@ void blk_mq_debugfs_unregister_sched(struct request_queue *q)
|
|||
q->sched_debugfs_dir = NULL;
|
||||
}
|
||||
|
||||
void blk_mq_debugfs_unregister_rqos(struct rq_qos *rqos)
|
||||
{
|
||||
debugfs_remove_recursive(rqos->debugfs_dir);
|
||||
rqos->debugfs_dir = NULL;
|
||||
}
|
||||
|
||||
int 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);
|
||||
|
||||
if (!q->debugfs_dir)
|
||||
return -ENOENT;
|
||||
|
||||
if (rqos->debugfs_dir || !rqos->ops->debugfs_attrs)
|
||||
return 0;
|
||||
|
||||
if (!q->rqos_debugfs_dir) {
|
||||
q->rqos_debugfs_dir = debugfs_create_dir("rqos",
|
||||
q->debugfs_dir);
|
||||
if (!q->rqos_debugfs_dir)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rqos->debugfs_dir = debugfs_create_dir(dir_name,
|
||||
rqos->q->rqos_debugfs_dir);
|
||||
if (!rqos->debugfs_dir)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!debugfs_create_files(rqos->debugfs_dir, rqos,
|
||||
rqos->ops->debugfs_attrs))
|
||||
goto err;
|
||||
return 0;
|
||||
err:
|
||||
blk_mq_debugfs_unregister_rqos(rqos);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void blk_mq_debugfs_unregister_queue_rqos(struct request_queue *q)
|
||||
{
|
||||
debugfs_remove_recursive(q->rqos_debugfs_dir);
|
||||
q->rqos_debugfs_dir = NULL;
|
||||
}
|
||||
|
||||
int blk_mq_debugfs_register_sched_hctx(struct request_queue *q,
|
||||
struct blk_mq_hw_ctx *hctx)
|
||||
{
|
||||
|
|
|
@ -31,6 +31,10 @@ void blk_mq_debugfs_unregister_sched(struct request_queue *q);
|
|||
int blk_mq_debugfs_register_sched_hctx(struct request_queue *q,
|
||||
struct blk_mq_hw_ctx *hctx);
|
||||
void blk_mq_debugfs_unregister_sched_hctx(struct blk_mq_hw_ctx *hctx);
|
||||
|
||||
int blk_mq_debugfs_register_rqos(struct rq_qos *rqos);
|
||||
void blk_mq_debugfs_unregister_rqos(struct rq_qos *rqos);
|
||||
void blk_mq_debugfs_unregister_queue_rqos(struct request_queue *q);
|
||||
#else
|
||||
static inline int blk_mq_debugfs_register(struct request_queue *q)
|
||||
{
|
||||
|
@ -78,6 +82,19 @@ static inline int blk_mq_debugfs_register_sched_hctx(struct request_queue *q,
|
|||
static inline void blk_mq_debugfs_unregister_sched_hctx(struct blk_mq_hw_ctx *hctx)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int blk_mq_debugfs_register_rqos(struct rq_qos *rqos)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void blk_mq_debugfs_unregister_rqos(struct rq_qos *rqos)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void blk_mq_debugfs_unregister_queue_rqos(struct request_queue *q)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BLK_DEBUG_FS_ZONED
|
||||
|
|
|
@ -264,6 +264,8 @@ void rq_qos_wait(struct rq_wait *rqw, void *private_data,
|
|||
|
||||
void rq_qos_exit(struct request_queue *q)
|
||||
{
|
||||
blk_mq_debugfs_unregister_queue_rqos(q);
|
||||
|
||||
while (q->rq_qos) {
|
||||
struct rq_qos *rqos = q->rq_qos;
|
||||
q->rq_qos = rqos->next;
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
#include <linux/atomic.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include "blk-mq-debugfs.h"
|
||||
|
||||
struct blk_mq_debugfs_attr;
|
||||
|
||||
enum rq_qos_id {
|
||||
RQ_QOS_WBT,
|
||||
RQ_QOS_CGROUP,
|
||||
|
@ -22,6 +26,9 @@ struct rq_qos {
|
|||
struct request_queue *q;
|
||||
enum rq_qos_id id;
|
||||
struct rq_qos *next;
|
||||
#ifdef CONFIG_BLK_DEBUG_FS
|
||||
struct dentry *debugfs_dir;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct rq_qos_ops {
|
||||
|
@ -33,6 +40,7 @@ struct rq_qos_ops {
|
|||
void (*done_bio)(struct rq_qos *, struct bio *);
|
||||
void (*cleanup)(struct rq_qos *, struct bio *);
|
||||
void (*exit)(struct rq_qos *);
|
||||
const struct blk_mq_debugfs_attr *debugfs_attrs;
|
||||
};
|
||||
|
||||
struct rq_depth {
|
||||
|
@ -66,6 +74,17 @@ static inline struct rq_qos *blkcg_rq_qos(struct request_queue *q)
|
|||
return rq_qos_id(q, RQ_QOS_CGROUP);
|
||||
}
|
||||
|
||||
static inline const char *rq_qos_id_to_name(enum rq_qos_id id)
|
||||
{
|
||||
switch (id) {
|
||||
case RQ_QOS_WBT:
|
||||
return "wbt";
|
||||
case RQ_QOS_CGROUP:
|
||||
return "cgroup";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static inline void rq_wait_init(struct rq_wait *rq_wait)
|
||||
{
|
||||
atomic_set(&rq_wait->inflight, 0);
|
||||
|
@ -76,6 +95,9 @@ static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos)
|
|||
{
|
||||
rqos->next = q->rq_qos;
|
||||
q->rq_qos = rqos;
|
||||
|
||||
if (rqos->ops->debugfs_attrs)
|
||||
blk_mq_debugfs_register_rqos(rqos);
|
||||
}
|
||||
|
||||
static inline void rq_qos_del(struct request_queue *q, struct rq_qos *rqos)
|
||||
|
@ -91,6 +113,8 @@ static inline void rq_qos_del(struct request_queue *q, struct rq_qos *rqos)
|
|||
}
|
||||
prev = cur;
|
||||
}
|
||||
|
||||
blk_mq_debugfs_unregister_rqos(rqos);
|
||||
}
|
||||
|
||||
typedef bool (acquire_inflight_cb_t)(struct rq_wait *rqw, void *private_data);
|
||||
|
|
|
@ -560,6 +560,7 @@ struct request_queue {
|
|||
#ifdef CONFIG_BLK_DEBUG_FS
|
||||
struct dentry *debugfs_dir;
|
||||
struct dentry *sched_debugfs_dir;
|
||||
struct dentry *rqos_debugfs_dir;
|
||||
#endif
|
||||
|
||||
bool mq_sysfs_init_done;
|
||||
|
|
Loading…
Reference in New Issue
Block a user