summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMing Lei <ming.lei@redhat.com>2018-12-16 20:46:00 -0500
committerJens Axboe <axboe@kernel.dk>2018-12-16 21:53:47 -0500
commitcc56694f132a8f5fa9334e3afe990de8c3378866 (patch)
treec67715ced5609fdcd34e95c3dcc24e6bc8ae494a
parentf9824952ee1cd02ae1a74e35e0e8653f8a4db772 (diff)
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>
-rw-r--r--block/blk-mq-debugfs.c54
-rw-r--r--block/blk-mq-debugfs.h17
-rw-r--r--block/blk-rq-qos.c2
-rw-r--r--block/blk-rq-qos.h24
-rw-r--r--include/linux/blkdev.h1
5 files changed, 98 insertions, 0 deletions
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index a32bb79d6c95..2793e91bc7a4 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -23,6 +23,7 @@
23#include "blk-mq.h" 23#include "blk-mq.h"
24#include "blk-mq-debugfs.h" 24#include "blk-mq-debugfs.h"
25#include "blk-mq-tag.h" 25#include "blk-mq-tag.h"
26#include "blk-rq-qos.h"
26 27
27static void print_stat(struct seq_file *m, struct blk_rq_stat *stat) 28static void print_stat(struct seq_file *m, struct blk_rq_stat *stat)
28{ 29{
@@ -856,6 +857,15 @@ int blk_mq_debugfs_register(struct request_queue *q)
856 goto err; 857 goto err;
857 } 858 }
858 859
860 if (q->rq_qos) {
861 struct rq_qos *rqos = q->rq_qos;
862
863 while (rqos) {
864 blk_mq_debugfs_register_rqos(rqos);
865 rqos = rqos->next;
866 }
867 }
868
859 return 0; 869 return 0;
860 870
861err: 871err:
@@ -978,6 +988,50 @@ void blk_mq_debugfs_unregister_sched(struct request_queue *q)
978 q->sched_debugfs_dir = NULL; 988 q->sched_debugfs_dir = NULL;
979} 989}
980 990
991void blk_mq_debugfs_unregister_rqos(struct rq_qos *rqos)
992{
993 debugfs_remove_recursive(rqos->debugfs_dir);
994 rqos->debugfs_dir = NULL;
995}
996
997int blk_mq_debugfs_register_rqos(struct rq_qos *rqos)
998{
999 struct request_queue *q = rqos->q;
1000 const char *dir_name = rq_qos_id_to_name(rqos->id);
1001
1002 if (!q->debugfs_dir)
1003 return -ENOENT;
1004
1005 if (rqos->debugfs_dir || !rqos->ops->debugfs_attrs)
1006 return 0;
1007
1008 if (!q->rqos_debugfs_dir) {
1009 q->rqos_debugfs_dir = debugfs_create_dir("rqos",
1010 q->debugfs_dir);
1011 if (!q->rqos_debugfs_dir)
1012 return -ENOMEM;
1013 }
1014
1015 rqos->debugfs_dir = debugfs_create_dir(dir_name,
1016 rqos->q->rqos_debugfs_dir);
1017 if (!rqos->debugfs_dir)
1018 return -ENOMEM;
1019
1020 if (!debugfs_create_files(rqos->debugfs_dir, rqos,
1021 rqos->ops->debugfs_attrs))
1022 goto err;
1023 return 0;
1024 err:
1025 blk_mq_debugfs_unregister_rqos(rqos);
1026 return -ENOMEM;
1027}
1028
1029void blk_mq_debugfs_unregister_queue_rqos(struct request_queue *q)
1030{
1031 debugfs_remove_recursive(q->rqos_debugfs_dir);
1032 q->rqos_debugfs_dir = NULL;
1033}
1034
981int blk_mq_debugfs_register_sched_hctx(struct request_queue *q, 1035int blk_mq_debugfs_register_sched_hctx(struct request_queue *q,
982 struct blk_mq_hw_ctx *hctx) 1036 struct blk_mq_hw_ctx *hctx)
983{ 1037{
diff --git a/block/blk-mq-debugfs.h b/block/blk-mq-debugfs.h
index a9160be12be0..8c9012a578c1 100644
--- a/block/blk-mq-debugfs.h
+++ b/block/blk-mq-debugfs.h
@@ -31,6 +31,10 @@ void blk_mq_debugfs_unregister_sched(struct request_queue *q);
31int blk_mq_debugfs_register_sched_hctx(struct request_queue *q, 31int blk_mq_debugfs_register_sched_hctx(struct request_queue *q,
32 struct blk_mq_hw_ctx *hctx); 32 struct blk_mq_hw_ctx *hctx);
33void blk_mq_debugfs_unregister_sched_hctx(struct blk_mq_hw_ctx *hctx); 33void blk_mq_debugfs_unregister_sched_hctx(struct blk_mq_hw_ctx *hctx);
34
35int blk_mq_debugfs_register_rqos(struct rq_qos *rqos);
36void blk_mq_debugfs_unregister_rqos(struct rq_qos *rqos);
37void blk_mq_debugfs_unregister_queue_rqos(struct request_queue *q);
34#else 38#else
35static inline int blk_mq_debugfs_register(struct request_queue *q) 39static inline int blk_mq_debugfs_register(struct request_queue *q)
36{ 40{
@@ -78,6 +82,19 @@ static inline int blk_mq_debugfs_register_sched_hctx(struct request_queue *q,
78static inline void blk_mq_debugfs_unregister_sched_hctx(struct blk_mq_hw_ctx *hctx) 82static inline void blk_mq_debugfs_unregister_sched_hctx(struct blk_mq_hw_ctx *hctx)
79{ 83{
80} 84}
85
86static inline int blk_mq_debugfs_register_rqos(struct rq_qos *rqos)
87{
88 return 0;
89}
90
91static inline void blk_mq_debugfs_unregister_rqos(struct rq_qos *rqos)
92{
93}
94
95static inline void blk_mq_debugfs_unregister_queue_rqos(struct request_queue *q)
96{
97}
81#endif 98#endif
82 99
83#ifdef CONFIG_BLK_DEBUG_FS_ZONED 100#ifdef CONFIG_BLK_DEBUG_FS_ZONED
diff --git a/block/blk-rq-qos.c b/block/blk-rq-qos.c
index e932ef9d2718..d169d7188fa6 100644
--- a/block/blk-rq-qos.c
+++ b/block/blk-rq-qos.c
@@ -264,6 +264,8 @@ void rq_qos_wait(struct rq_wait *rqw, void *private_data,
264 264
265void rq_qos_exit(struct request_queue *q) 265void rq_qos_exit(struct request_queue *q)
266{ 266{
267 blk_mq_debugfs_unregister_queue_rqos(q);
268
267 while (q->rq_qos) { 269 while (q->rq_qos) {
268 struct rq_qos *rqos = q->rq_qos; 270 struct rq_qos *rqos = q->rq_qos;
269 q->rq_qos = rqos->next; 271 q->rq_qos = rqos->next;
diff --git a/block/blk-rq-qos.h b/block/blk-rq-qos.h
index 8678875de420..3c85f26d3846 100644
--- a/block/blk-rq-qos.h
+++ b/block/blk-rq-qos.h
@@ -7,6 +7,10 @@
7#include <linux/atomic.h> 7#include <linux/atomic.h>
8#include <linux/wait.h> 8#include <linux/wait.h>
9 9
10#include "blk-mq-debugfs.h"
11
12struct blk_mq_debugfs_attr;
13
10enum rq_qos_id { 14enum rq_qos_id {
11 RQ_QOS_WBT, 15 RQ_QOS_WBT,
12 RQ_QOS_CGROUP, 16 RQ_QOS_CGROUP,
@@ -22,6 +26,9 @@ struct rq_qos {
22 struct request_queue *q; 26 struct request_queue *q;
23 enum rq_qos_id id; 27 enum rq_qos_id id;
24 struct rq_qos *next; 28 struct rq_qos *next;
29#ifdef CONFIG_BLK_DEBUG_FS
30 struct dentry *debugfs_dir;
31#endif
25}; 32};
26 33
27struct rq_qos_ops { 34struct rq_qos_ops {
@@ -33,6 +40,7 @@ struct rq_qos_ops {
33 void (*done_bio)(struct rq_qos *, struct bio *); 40 void (*done_bio)(struct rq_qos *, struct bio *);
34 void (*cleanup)(struct rq_qos *, struct bio *); 41 void (*cleanup)(struct rq_qos *, struct bio *);
35 void (*exit)(struct rq_qos *); 42 void (*exit)(struct rq_qos *);
43 const struct blk_mq_debugfs_attr *debugfs_attrs;
36}; 44};
37 45
38struct rq_depth { 46struct rq_depth {
@@ -66,6 +74,17 @@ static inline struct rq_qos *blkcg_rq_qos(struct request_queue *q)
66 return rq_qos_id(q, RQ_QOS_CGROUP); 74 return rq_qos_id(q, RQ_QOS_CGROUP);
67} 75}
68 76
77static inline const char *rq_qos_id_to_name(enum rq_qos_id id)
78{
79 switch (id) {
80 case RQ_QOS_WBT:
81 return "wbt";
82 case RQ_QOS_CGROUP:
83 return "cgroup";
84 }
85 return "unknown";
86}
87
69static inline void rq_wait_init(struct rq_wait *rq_wait) 88static inline void rq_wait_init(struct rq_wait *rq_wait)
70{ 89{
71 atomic_set(&rq_wait->inflight, 0); 90 atomic_set(&rq_wait->inflight, 0);
@@ -76,6 +95,9 @@ static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos)
76{ 95{
77 rqos->next = q->rq_qos; 96 rqos->next = q->rq_qos;
78 q->rq_qos = rqos; 97 q->rq_qos = rqos;
98
99 if (rqos->ops->debugfs_attrs)
100 blk_mq_debugfs_register_rqos(rqos);
79} 101}
80 102
81static inline void rq_qos_del(struct request_queue *q, struct rq_qos *rqos) 103static 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)
91 } 113 }
92 prev = cur; 114 prev = cur;
93 } 115 }
116
117 blk_mq_debugfs_unregister_rqos(rqos);
94} 118}
95 119
96typedef bool (acquire_inflight_cb_t)(struct rq_wait *rqw, void *private_data); 120typedef bool (acquire_inflight_cb_t)(struct rq_wait *rqw, void *private_data);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 81f1b105946b..45552e6eae1e 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -560,6 +560,7 @@ struct request_queue {
560#ifdef CONFIG_BLK_DEBUG_FS 560#ifdef CONFIG_BLK_DEBUG_FS
561 struct dentry *debugfs_dir; 561 struct dentry *debugfs_dir;
562 struct dentry *sched_debugfs_dir; 562 struct dentry *sched_debugfs_dir;
563 struct dentry *rqos_debugfs_dir;
563#endif 564#endif
564 565
565 bool mq_sysfs_init_done; 566 bool mq_sysfs_init_done;