* [PATCH 1/9] blk-mq-debugfs: separate flags with |
2017-05-03 19:18 [PATCH 0/9] blk-mq-debugfs: scheduler support and cleanups Omar Sandoval
@ 2017-05-03 19:18 ` Omar Sandoval
2017-05-03 19:18 ` [PATCH 2/9] blk-mq-debugfs: clean up flag definitions Omar Sandoval
` (8 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Omar Sandoval @ 2017-05-03 19:18 UTC (permalink / raw)
To: Jens Axboe, linux-block; +Cc: Bart Van Assche, kernel-team
From: Omar Sandoval <osandov@fb.com>
This reads more naturally than spaces.
Signed-off-by: Omar Sandoval <osandov@fb.com>
---
block/blk-mq-debugfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index bcd2a7d4a3a5..1ff3d726fb03 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -53,7 +53,7 @@ static int blk_flags_show(struct seq_file *m, const unsigned long flags,
if (!(flags & BIT(i)))
continue;
if (sep)
- seq_puts(m, " ");
+ seq_puts(m, "|");
sep = true;
if (i < flag_name_count && flag_name[i])
seq_puts(m, flag_name[i]);
--
2.12.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 2/9] blk-mq-debugfs: clean up flag definitions
2017-05-03 19:18 [PATCH 0/9] blk-mq-debugfs: scheduler support and cleanups Omar Sandoval
2017-05-03 19:18 ` [PATCH 1/9] blk-mq-debugfs: separate flags with | Omar Sandoval
@ 2017-05-03 19:18 ` Omar Sandoval
2017-05-03 19:18 ` [PATCH 3/9] blk-mq-debugfs: get rid of a bunch of boilerplate Omar Sandoval
` (7 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Omar Sandoval @ 2017-05-03 19:18 UTC (permalink / raw)
To: Jens Axboe, linux-block; +Cc: Bart Van Assche, kernel-team
From: Omar Sandoval <osandov@fb.com>
Make sure the spelled out flag names match the definition. This also
adds a missing hctx state, BLK_MQ_S_START_ON_RUN, and a missing
cmd_flag, __REQ_NOUNMAP.
Signed-off-by: Omar Sandoval <osandov@fb.com>
---
block/blk-mq-debugfs.c | 201 ++++++++++++++++++++++++++-----------------------
1 file changed, 108 insertions(+), 93 deletions(-)
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 1ff3d726fb03..f58a116d6cca 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -63,37 +63,39 @@ static int blk_flags_show(struct seq_file *m, const unsigned long flags,
return 0;
}
+#define QUEUE_FLAG_NAME(name) [QUEUE_FLAG_##name] = #name
static const char *const blk_queue_flag_name[] = {
- [QUEUE_FLAG_QUEUED] = "QUEUED",
- [QUEUE_FLAG_STOPPED] = "STOPPED",
- [QUEUE_FLAG_SYNCFULL] = "SYNCFULL",
- [QUEUE_FLAG_ASYNCFULL] = "ASYNCFULL",
- [QUEUE_FLAG_DYING] = "DYING",
- [QUEUE_FLAG_BYPASS] = "BYPASS",
- [QUEUE_FLAG_BIDI] = "BIDI",
- [QUEUE_FLAG_NOMERGES] = "NOMERGES",
- [QUEUE_FLAG_SAME_COMP] = "SAME_COMP",
- [QUEUE_FLAG_FAIL_IO] = "FAIL_IO",
- [QUEUE_FLAG_STACKABLE] = "STACKABLE",
- [QUEUE_FLAG_NONROT] = "NONROT",
- [QUEUE_FLAG_IO_STAT] = "IO_STAT",
- [QUEUE_FLAG_DISCARD] = "DISCARD",
- [QUEUE_FLAG_NOXMERGES] = "NOXMERGES",
- [QUEUE_FLAG_ADD_RANDOM] = "ADD_RANDOM",
- [QUEUE_FLAG_SECERASE] = "SECERASE",
- [QUEUE_FLAG_SAME_FORCE] = "SAME_FORCE",
- [QUEUE_FLAG_DEAD] = "DEAD",
- [QUEUE_FLAG_INIT_DONE] = "INIT_DONE",
- [QUEUE_FLAG_NO_SG_MERGE] = "NO_SG_MERGE",
- [QUEUE_FLAG_POLL] = "POLL",
- [QUEUE_FLAG_WC] = "WC",
- [QUEUE_FLAG_FUA] = "FUA",
- [QUEUE_FLAG_FLUSH_NQ] = "FLUSH_NQ",
- [QUEUE_FLAG_DAX] = "DAX",
- [QUEUE_FLAG_STATS] = "STATS",
- [QUEUE_FLAG_POLL_STATS] = "POLL_STATS",
- [QUEUE_FLAG_REGISTERED] = "REGISTERED",
-};
+ QUEUE_FLAG_NAME(QUEUED),
+ QUEUE_FLAG_NAME(STOPPED),
+ QUEUE_FLAG_NAME(SYNCFULL),
+ QUEUE_FLAG_NAME(ASYNCFULL),
+ QUEUE_FLAG_NAME(DYING),
+ QUEUE_FLAG_NAME(BYPASS),
+ QUEUE_FLAG_NAME(BIDI),
+ QUEUE_FLAG_NAME(NOMERGES),
+ QUEUE_FLAG_NAME(SAME_COMP),
+ QUEUE_FLAG_NAME(FAIL_IO),
+ QUEUE_FLAG_NAME(STACKABLE),
+ QUEUE_FLAG_NAME(NONROT),
+ QUEUE_FLAG_NAME(IO_STAT),
+ QUEUE_FLAG_NAME(DISCARD),
+ QUEUE_FLAG_NAME(NOXMERGES),
+ QUEUE_FLAG_NAME(ADD_RANDOM),
+ QUEUE_FLAG_NAME(SECERASE),
+ QUEUE_FLAG_NAME(SAME_FORCE),
+ QUEUE_FLAG_NAME(DEAD),
+ QUEUE_FLAG_NAME(INIT_DONE),
+ QUEUE_FLAG_NAME(NO_SG_MERGE),
+ QUEUE_FLAG_NAME(POLL),
+ QUEUE_FLAG_NAME(WC),
+ QUEUE_FLAG_NAME(FUA),
+ QUEUE_FLAG_NAME(FLUSH_NQ),
+ QUEUE_FLAG_NAME(DAX),
+ QUEUE_FLAG_NAME(STATS),
+ QUEUE_FLAG_NAME(POLL_STATS),
+ QUEUE_FLAG_NAME(REGISTERED),
+};
+#undef QUEUE_FLAG_NAME
static int blk_queue_flags_show(struct seq_file *m, void *v)
{
@@ -180,13 +182,16 @@ static const struct file_operations queue_poll_stat_fops = {
.release = single_release,
};
+#define HCTX_STATE_NAME(name) [BLK_MQ_S_##name] = #name
static const char *const hctx_state_name[] = {
- [BLK_MQ_S_STOPPED] = "STOPPED",
- [BLK_MQ_S_TAG_ACTIVE] = "TAG_ACTIVE",
- [BLK_MQ_S_SCHED_RESTART] = "SCHED_RESTART",
- [BLK_MQ_S_TAG_WAITING] = "TAG_WAITING",
-
+ HCTX_STATE_NAME(STOPPED),
+ HCTX_STATE_NAME(TAG_ACTIVE),
+ HCTX_STATE_NAME(SCHED_RESTART),
+ HCTX_STATE_NAME(TAG_WAITING),
+ HCTX_STATE_NAME(START_ON_RUN),
};
+#undef HCTX_STATE_NAME
+
static int hctx_state_show(struct seq_file *m, void *v)
{
struct blk_mq_hw_ctx *hctx = m->private;
@@ -209,18 +214,22 @@ static const struct file_operations hctx_state_fops = {
.release = single_release,
};
+#define BLK_TAG_ALLOC_NAME(name) [BLK_TAG_ALLOC_##name] = #name
static const char *const alloc_policy_name[] = {
- [BLK_TAG_ALLOC_FIFO] = "fifo",
- [BLK_TAG_ALLOC_RR] = "rr",
+ BLK_TAG_ALLOC_NAME(FIFO),
+ BLK_TAG_ALLOC_NAME(RR),
};
+#undef BLK_TAG_ALLOC_NAME
+#define HCTX_FLAG_NAME(name) [ilog2(BLK_MQ_F_##name)] = #name
static const char *const hctx_flag_name[] = {
- [ilog2(BLK_MQ_F_SHOULD_MERGE)] = "SHOULD_MERGE",
- [ilog2(BLK_MQ_F_TAG_SHARED)] = "TAG_SHARED",
- [ilog2(BLK_MQ_F_SG_MERGE)] = "SG_MERGE",
- [ilog2(BLK_MQ_F_BLOCKING)] = "BLOCKING",
- [ilog2(BLK_MQ_F_NO_SCHED)] = "NO_SCHED",
+ HCTX_FLAG_NAME(SHOULD_MERGE),
+ HCTX_FLAG_NAME(TAG_SHARED),
+ HCTX_FLAG_NAME(SG_MERGE),
+ HCTX_FLAG_NAME(BLOCKING),
+ HCTX_FLAG_NAME(NO_SCHED),
};
+#undef HCTX_FLAG_NAME
static int hctx_flags_show(struct seq_file *m, void *v)
{
@@ -253,60 +262,66 @@ static const struct file_operations hctx_flags_fops = {
.release = single_release,
};
+#define REQ_OP_NAME(name) [REQ_OP_##name] = #name
static const char *const op_name[] = {
- [REQ_OP_READ] = "READ",
- [REQ_OP_WRITE] = "WRITE",
- [REQ_OP_FLUSH] = "FLUSH",
- [REQ_OP_DISCARD] = "DISCARD",
- [REQ_OP_ZONE_REPORT] = "ZONE_REPORT",
- [REQ_OP_SECURE_ERASE] = "SECURE_ERASE",
- [REQ_OP_ZONE_RESET] = "ZONE_RESET",
- [REQ_OP_WRITE_SAME] = "WRITE_SAME",
- [REQ_OP_WRITE_ZEROES] = "WRITE_ZEROES",
- [REQ_OP_SCSI_IN] = "SCSI_IN",
- [REQ_OP_SCSI_OUT] = "SCSI_OUT",
- [REQ_OP_DRV_IN] = "DRV_IN",
- [REQ_OP_DRV_OUT] = "DRV_OUT",
-};
-
+ REQ_OP_NAME(READ),
+ REQ_OP_NAME(WRITE),
+ REQ_OP_NAME(FLUSH),
+ REQ_OP_NAME(DISCARD),
+ REQ_OP_NAME(ZONE_REPORT),
+ REQ_OP_NAME(SECURE_ERASE),
+ REQ_OP_NAME(ZONE_RESET),
+ REQ_OP_NAME(WRITE_SAME),
+ REQ_OP_NAME(WRITE_ZEROES),
+ REQ_OP_NAME(SCSI_IN),
+ REQ_OP_NAME(SCSI_OUT),
+ REQ_OP_NAME(DRV_IN),
+ REQ_OP_NAME(DRV_OUT),
+};
+#undef REQ_OP_NAME
+
+#define CMD_FLAG_NAME(name) [__REQ_##name] = #name
static const char *const cmd_flag_name[] = {
- [__REQ_FAILFAST_DEV] = "FAILFAST_DEV",
- [__REQ_FAILFAST_TRANSPORT] = "FAILFAST_TRANSPORT",
- [__REQ_FAILFAST_DRIVER] = "FAILFAST_DRIVER",
- [__REQ_SYNC] = "SYNC",
- [__REQ_META] = "META",
- [__REQ_PRIO] = "PRIO",
- [__REQ_NOMERGE] = "NOMERGE",
- [__REQ_IDLE] = "IDLE",
- [__REQ_INTEGRITY] = "INTEGRITY",
- [__REQ_FUA] = "FUA",
- [__REQ_PREFLUSH] = "PREFLUSH",
- [__REQ_RAHEAD] = "RAHEAD",
- [__REQ_BACKGROUND] = "BACKGROUND",
- [__REQ_NR_BITS] = "NR_BITS",
-};
-
+ CMD_FLAG_NAME(FAILFAST_DEV),
+ CMD_FLAG_NAME(FAILFAST_TRANSPORT),
+ CMD_FLAG_NAME(FAILFAST_DRIVER),
+ CMD_FLAG_NAME(SYNC),
+ CMD_FLAG_NAME(META),
+ CMD_FLAG_NAME(PRIO),
+ CMD_FLAG_NAME(NOMERGE),
+ CMD_FLAG_NAME(IDLE),
+ CMD_FLAG_NAME(INTEGRITY),
+ CMD_FLAG_NAME(FUA),
+ CMD_FLAG_NAME(PREFLUSH),
+ CMD_FLAG_NAME(RAHEAD),
+ CMD_FLAG_NAME(BACKGROUND),
+ CMD_FLAG_NAME(NOUNMAP),
+};
+#undef CMD_FLAG_NAME
+
+#define RQF_NAME(name) [ilog2((__force u32)RQF_##name)] = #name
static const char *const rqf_name[] = {
- [ilog2((__force u32)RQF_SORTED)] = "SORTED",
- [ilog2((__force u32)RQF_STARTED)] = "STARTED",
- [ilog2((__force u32)RQF_QUEUED)] = "QUEUED",
- [ilog2((__force u32)RQF_SOFTBARRIER)] = "SOFTBARRIER",
- [ilog2((__force u32)RQF_FLUSH_SEQ)] = "FLUSH_SEQ",
- [ilog2((__force u32)RQF_MIXED_MERGE)] = "MIXED_MERGE",
- [ilog2((__force u32)RQF_MQ_INFLIGHT)] = "MQ_INFLIGHT",
- [ilog2((__force u32)RQF_DONTPREP)] = "DONTPREP",
- [ilog2((__force u32)RQF_PREEMPT)] = "PREEMPT",
- [ilog2((__force u32)RQF_COPY_USER)] = "COPY_USER",
- [ilog2((__force u32)RQF_FAILED)] = "FAILED",
- [ilog2((__force u32)RQF_QUIET)] = "QUIET",
- [ilog2((__force u32)RQF_ELVPRIV)] = "ELVPRIV",
- [ilog2((__force u32)RQF_IO_STAT)] = "IO_STAT",
- [ilog2((__force u32)RQF_ALLOCED)] = "ALLOCED",
- [ilog2((__force u32)RQF_PM)] = "PM",
- [ilog2((__force u32)RQF_HASHED)] = "HASHED",
- [ilog2((__force u32)RQF_STATS)] = "STATS",
- [ilog2((__force u32)RQF_SPECIAL_PAYLOAD)] = "SPECIAL_PAYLOAD",
-};
+ RQF_NAME(SORTED),
+ RQF_NAME(STARTED),
+ RQF_NAME(QUEUED),
+ RQF_NAME(SOFTBARRIER),
+ RQF_NAME(FLUSH_SEQ),
+ RQF_NAME(MIXED_MERGE),
+ RQF_NAME(MQ_INFLIGHT),
+ RQF_NAME(DONTPREP),
+ RQF_NAME(PREEMPT),
+ RQF_NAME(COPY_USER),
+ RQF_NAME(FAILED),
+ RQF_NAME(QUIET),
+ RQF_NAME(ELVPRIV),
+ RQF_NAME(IO_STAT),
+ RQF_NAME(ALLOCED),
+ RQF_NAME(PM),
+ RQF_NAME(HASHED),
+ RQF_NAME(STATS),
+ RQF_NAME(SPECIAL_PAYLOAD),
+};
+#undef RQF_NAME
static int blk_mq_debugfs_rq_show(struct seq_file *m, void *v)
{
--
2.12.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 3/9] blk-mq-debugfs: get rid of a bunch of boilerplate
2017-05-03 19:18 [PATCH 0/9] blk-mq-debugfs: scheduler support and cleanups Omar Sandoval
2017-05-03 19:18 ` [PATCH 1/9] blk-mq-debugfs: separate flags with | Omar Sandoval
2017-05-03 19:18 ` [PATCH 2/9] blk-mq-debugfs: clean up flag definitions Omar Sandoval
@ 2017-05-03 19:18 ` Omar Sandoval
2017-05-03 20:51 ` Bart Van Assche
2017-05-03 19:18 ` [PATCH 4/9] blk-mq: Do not invoke queue operations on a dead queue Omar Sandoval
` (6 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Omar Sandoval @ 2017-05-03 19:18 UTC (permalink / raw)
To: Jens Axboe, linux-block; +Cc: Bart Van Assche, kernel-team
From: Omar Sandoval <osandov@fb.com>
A large part of blk-mq-debugfs.c is file_operations and seq_file
boilerplate. This sucks as is but will suck even more when schedulers
can define their own debugfs entries. Factor it all out into a single
blk_mq_debugfs_fops which multiplexes as needed. We store the
request_queue, blk_mq_hw_ctx, or blk_mq_ctx in the parent directory
dentry, which is kind of hacky, but it works.
Signed-off-by: Omar Sandoval <osandov@fb.com>
---
block/blk-mq-debugfs.c | 469 +++++++++++++++----------------------------------
1 file changed, 138 insertions(+), 331 deletions(-)
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index f58a116d6cca..00cc89c34590 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -26,23 +26,12 @@
struct blk_mq_debugfs_attr {
const char *name;
umode_t mode;
- const struct file_operations *fops;
+ int (*show)(void *, struct seq_file *);
+ ssize_t (*write)(void *, const char __user *, size_t, loff_t *);
+ /* Set either .show or .seq_ops. */
+ const struct seq_operations *seq_ops;
};
-static int blk_mq_debugfs_seq_open(struct inode *inode, struct file *file,
- const struct seq_operations *ops)
-{
- struct seq_file *m;
- int ret;
-
- ret = seq_open(file, ops);
- if (!ret) {
- m = file->private_data;
- m->private = inode->i_private;
- }
- return ret;
-}
-
static int blk_flags_show(struct seq_file *m, const unsigned long flags,
const char *const *flag_name, int flag_name_count)
{
@@ -97,9 +86,9 @@ static const char *const blk_queue_flag_name[] = {
};
#undef QUEUE_FLAG_NAME
-static int blk_queue_flags_show(struct seq_file *m, void *v)
+static int queue_state_show(void *data, struct seq_file *m)
{
- struct request_queue *q = m->private;
+ struct request_queue *q = data;
blk_flags_show(m, q->queue_flags, blk_queue_flag_name,
ARRAY_SIZE(blk_queue_flag_name));
@@ -107,14 +96,13 @@ static int blk_queue_flags_show(struct seq_file *m, void *v)
return 0;
}
-static ssize_t blk_queue_flags_store(struct file *file, const char __user *ubuf,
- size_t len, loff_t *offp)
+static ssize_t queue_state_write(void *data, const char __user *buf,
+ size_t count, loff_t *ppos)
{
- struct request_queue *q = file_inode(file)->i_private;
+ struct request_queue *q = data;
char op[16] = { }, *s;
- len = min(len, sizeof(op) - 1);
- if (copy_from_user(op, ubuf, len))
+ if (copy_from_user(op, buf, min(count, sizeof(op) - 1)))
return -EFAULT;
s = op;
strsep(&s, " \t\n"); /* strip trailing whitespace */
@@ -127,22 +115,9 @@ static ssize_t blk_queue_flags_store(struct file *file, const char __user *ubuf,
__func__, op);
return -EINVAL;
}
- return len;
-}
-
-static int blk_queue_flags_open(struct inode *inode, struct file *file)
-{
- return single_open(file, blk_queue_flags_show, inode->i_private);
+ return count;
}
-static const struct file_operations blk_queue_flags_fops = {
- .open = blk_queue_flags_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .write = blk_queue_flags_store,
-};
-
static void print_stat(struct seq_file *m, struct blk_rq_stat *stat)
{
if (stat->nr_samples) {
@@ -153,9 +128,9 @@ static void print_stat(struct seq_file *m, struct blk_rq_stat *stat)
}
}
-static int queue_poll_stat_show(struct seq_file *m, void *v)
+static int queue_poll_stat_show(void *data, struct seq_file *m)
{
- struct request_queue *q = m->private;
+ struct request_queue *q = data;
int bucket;
for (bucket = 0; bucket < BLK_MQ_POLL_STATS_BKTS/2; bucket++) {
@@ -170,18 +145,6 @@ static int queue_poll_stat_show(struct seq_file *m, void *v)
return 0;
}
-static int queue_poll_stat_open(struct inode *inode, struct file *file)
-{
- return single_open(file, queue_poll_stat_show, inode->i_private);
-}
-
-static const struct file_operations queue_poll_stat_fops = {
- .open = queue_poll_stat_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
#define HCTX_STATE_NAME(name) [BLK_MQ_S_##name] = #name
static const char *const hctx_state_name[] = {
HCTX_STATE_NAME(STOPPED),
@@ -192,9 +155,9 @@ static const char *const hctx_state_name[] = {
};
#undef HCTX_STATE_NAME
-static int hctx_state_show(struct seq_file *m, void *v)
+static int hctx_state_show(void *data, struct seq_file *m)
{
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
blk_flags_show(m, hctx->state, hctx_state_name,
ARRAY_SIZE(hctx_state_name));
@@ -202,18 +165,6 @@ static int hctx_state_show(struct seq_file *m, void *v)
return 0;
}
-static int hctx_state_open(struct inode *inode, struct file *file)
-{
- return single_open(file, hctx_state_show, inode->i_private);
-}
-
-static const struct file_operations hctx_state_fops = {
- .open = hctx_state_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
#define BLK_TAG_ALLOC_NAME(name) [BLK_TAG_ALLOC_##name] = #name
static const char *const alloc_policy_name[] = {
BLK_TAG_ALLOC_NAME(FIFO),
@@ -231,9 +182,9 @@ static const char *const hctx_flag_name[] = {
};
#undef HCTX_FLAG_NAME
-static int hctx_flags_show(struct seq_file *m, void *v)
+static int hctx_flags_show(void *data, struct seq_file *m)
{
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
const int alloc_policy = BLK_MQ_FLAG_TO_ALLOC_POLICY(hctx->flags);
seq_puts(m, "alloc_policy=");
@@ -250,18 +201,6 @@ static int hctx_flags_show(struct seq_file *m, void *v)
return 0;
}
-static int hctx_flags_open(struct inode *inode, struct file *file)
-{
- return single_open(file, hctx_flags_show, inode->i_private);
-}
-
-static const struct file_operations hctx_flags_fops = {
- .open = hctx_flags_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
#define REQ_OP_NAME(name) [REQ_OP_##name] = #name
static const char *const op_name[] = {
REQ_OP_NAME(READ),
@@ -379,38 +318,14 @@ static const struct seq_operations hctx_dispatch_seq_ops = {
.show = blk_mq_debugfs_rq_show,
};
-static int hctx_dispatch_open(struct inode *inode, struct file *file)
-{
- return blk_mq_debugfs_seq_open(inode, file, &hctx_dispatch_seq_ops);
-}
-
-static const struct file_operations hctx_dispatch_fops = {
- .open = hctx_dispatch_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-static int hctx_ctx_map_show(struct seq_file *m, void *v)
+static int hctx_ctx_map_show(void *data, struct seq_file *m)
{
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
sbitmap_bitmap_show(&hctx->ctx_map, m);
return 0;
}
-static int hctx_ctx_map_open(struct inode *inode, struct file *file)
-{
- return single_open(file, hctx_ctx_map_show, inode->i_private);
-}
-
-static const struct file_operations hctx_ctx_map_fops = {
- .open = hctx_ctx_map_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
static void blk_mq_debugfs_tags_show(struct seq_file *m,
struct blk_mq_tags *tags)
{
@@ -428,9 +343,9 @@ static void blk_mq_debugfs_tags_show(struct seq_file *m,
}
}
-static int hctx_tags_show(struct seq_file *m, void *v)
+static int hctx_tags_show(void *data, struct seq_file *m)
{
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
struct request_queue *q = hctx->queue;
int res;
@@ -445,21 +360,9 @@ static int hctx_tags_show(struct seq_file *m, void *v)
return res;
}
-static int hctx_tags_open(struct inode *inode, struct file *file)
-{
- return single_open(file, hctx_tags_show, inode->i_private);
-}
-
-static const struct file_operations hctx_tags_fops = {
- .open = hctx_tags_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int hctx_tags_bitmap_show(struct seq_file *m, void *v)
+static int hctx_tags_bitmap_show(void *data, struct seq_file *m)
{
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
struct request_queue *q = hctx->queue;
int res;
@@ -474,21 +377,9 @@ static int hctx_tags_bitmap_show(struct seq_file *m, void *v)
return res;
}
-static int hctx_tags_bitmap_open(struct inode *inode, struct file *file)
-{
- return single_open(file, hctx_tags_bitmap_show, inode->i_private);
-}
-
-static const struct file_operations hctx_tags_bitmap_fops = {
- .open = hctx_tags_bitmap_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int hctx_sched_tags_show(struct seq_file *m, void *v)
+static int hctx_sched_tags_show(void *data, struct seq_file *m)
{
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
struct request_queue *q = hctx->queue;
int res;
@@ -503,21 +394,9 @@ static int hctx_sched_tags_show(struct seq_file *m, void *v)
return res;
}
-static int hctx_sched_tags_open(struct inode *inode, struct file *file)
-{
- return single_open(file, hctx_sched_tags_show, inode->i_private);
-}
-
-static const struct file_operations hctx_sched_tags_fops = {
- .open = hctx_sched_tags_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int hctx_sched_tags_bitmap_show(struct seq_file *m, void *v)
+static int hctx_sched_tags_bitmap_show(void *data, struct seq_file *m)
{
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
struct request_queue *q = hctx->queue;
int res;
@@ -532,21 +411,9 @@ static int hctx_sched_tags_bitmap_show(struct seq_file *m, void *v)
return res;
}
-static int hctx_sched_tags_bitmap_open(struct inode *inode, struct file *file)
-{
- return single_open(file, hctx_sched_tags_bitmap_show, inode->i_private);
-}
-
-static const struct file_operations hctx_sched_tags_bitmap_fops = {
- .open = hctx_sched_tags_bitmap_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int hctx_io_poll_show(struct seq_file *m, void *v)
+static int hctx_io_poll_show(void *data, struct seq_file *m)
{
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
seq_printf(m, "considered=%lu\n", hctx->poll_considered);
seq_printf(m, "invoked=%lu\n", hctx->poll_invoked);
@@ -554,32 +421,18 @@ static int hctx_io_poll_show(struct seq_file *m, void *v)
return 0;
}
-static int hctx_io_poll_open(struct inode *inode, struct file *file)
-{
- return single_open(file, hctx_io_poll_show, inode->i_private);
-}
-
-static ssize_t hctx_io_poll_write(struct file *file, const char __user *buf,
+static ssize_t hctx_io_poll_write(void *data, const char __user *buf,
size_t count, loff_t *ppos)
{
- struct seq_file *m = file->private_data;
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
hctx->poll_considered = hctx->poll_invoked = hctx->poll_success = 0;
return count;
}
-static const struct file_operations hctx_io_poll_fops = {
- .open = hctx_io_poll_open,
- .read = seq_read,
- .write = hctx_io_poll_write,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int hctx_dispatched_show(struct seq_file *m, void *v)
+static int hctx_dispatched_show(void *data, struct seq_file *m)
{
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
int i;
seq_printf(m, "%8u\t%lu\n", 0U, hctx->dispatched[0]);
@@ -594,16 +447,10 @@ static int hctx_dispatched_show(struct seq_file *m, void *v)
return 0;
}
-static int hctx_dispatched_open(struct inode *inode, struct file *file)
-{
- return single_open(file, hctx_dispatched_show, inode->i_private);
-}
-
-static ssize_t hctx_dispatched_write(struct file *file, const char __user *buf,
+static ssize_t hctx_dispatched_write(void *data, const char __user *buf,
size_t count, loff_t *ppos)
{
- struct seq_file *m = file->private_data;
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
int i;
for (i = 0; i < BLK_MQ_MAX_DISPATCH_ORDER; i++)
@@ -611,96 +458,48 @@ static ssize_t hctx_dispatched_write(struct file *file, const char __user *buf,
return count;
}
-static const struct file_operations hctx_dispatched_fops = {
- .open = hctx_dispatched_open,
- .read = seq_read,
- .write = hctx_dispatched_write,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int hctx_queued_show(struct seq_file *m, void *v)
+static int hctx_queued_show(void *data, struct seq_file *m)
{
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
seq_printf(m, "%lu\n", hctx->queued);
return 0;
}
-static int hctx_queued_open(struct inode *inode, struct file *file)
-{
- return single_open(file, hctx_queued_show, inode->i_private);
-}
-
-static ssize_t hctx_queued_write(struct file *file, const char __user *buf,
+static ssize_t hctx_queued_write(void *data, const char __user *buf,
size_t count, loff_t *ppos)
{
- struct seq_file *m = file->private_data;
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
hctx->queued = 0;
return count;
}
-static const struct file_operations hctx_queued_fops = {
- .open = hctx_queued_open,
- .read = seq_read,
- .write = hctx_queued_write,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int hctx_run_show(struct seq_file *m, void *v)
+static int hctx_run_show(void *data, struct seq_file *m)
{
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
seq_printf(m, "%lu\n", hctx->run);
return 0;
}
-static int hctx_run_open(struct inode *inode, struct file *file)
+static ssize_t hctx_run_write(void *data, const char __user *buf, size_t count,
+ loff_t *ppos)
{
- return single_open(file, hctx_run_show, inode->i_private);
-}
-
-static ssize_t hctx_run_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct seq_file *m = file->private_data;
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
hctx->run = 0;
return count;
}
-static const struct file_operations hctx_run_fops = {
- .open = hctx_run_open,
- .read = seq_read,
- .write = hctx_run_write,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int hctx_active_show(struct seq_file *m, void *v)
+static int hctx_active_show(void *data, struct seq_file *m)
{
- struct blk_mq_hw_ctx *hctx = m->private;
+ struct blk_mq_hw_ctx *hctx = data;
seq_printf(m, "%d\n", atomic_read(&hctx->nr_active));
return 0;
}
-static int hctx_active_open(struct inode *inode, struct file *file)
-{
- return single_open(file, hctx_active_show, inode->i_private);
-}
-
-static const struct file_operations hctx_active_fops = {
- .open = hctx_active_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
static void *ctx_rq_list_start(struct seq_file *m, loff_t *pos)
__acquires(&ctx->lock)
{
@@ -731,140 +530,146 @@ static const struct seq_operations ctx_rq_list_seq_ops = {
.stop = ctx_rq_list_stop,
.show = blk_mq_debugfs_rq_show,
};
-
-static int ctx_rq_list_open(struct inode *inode, struct file *file)
-{
- return blk_mq_debugfs_seq_open(inode, file, &ctx_rq_list_seq_ops);
-}
-
-static const struct file_operations ctx_rq_list_fops = {
- .open = ctx_rq_list_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-static int ctx_dispatched_show(struct seq_file *m, void *v)
+static int ctx_dispatched_show(void *data, struct seq_file *m)
{
- struct blk_mq_ctx *ctx = m->private;
+ struct blk_mq_ctx *ctx = data;
seq_printf(m, "%lu %lu\n", ctx->rq_dispatched[1], ctx->rq_dispatched[0]);
return 0;
}
-static int ctx_dispatched_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ctx_dispatched_show, inode->i_private);
-}
-
-static ssize_t ctx_dispatched_write(struct file *file, const char __user *buf,
+static ssize_t ctx_dispatched_write(void *data, const char __user *buf,
size_t count, loff_t *ppos)
{
- struct seq_file *m = file->private_data;
- struct blk_mq_ctx *ctx = m->private;
+ struct blk_mq_ctx *ctx = data;
ctx->rq_dispatched[0] = ctx->rq_dispatched[1] = 0;
return count;
}
-static const struct file_operations ctx_dispatched_fops = {
- .open = ctx_dispatched_open,
- .read = seq_read,
- .write = ctx_dispatched_write,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int ctx_merged_show(struct seq_file *m, void *v)
+static int ctx_merged_show(void *data, struct seq_file *m)
{
- struct blk_mq_ctx *ctx = m->private;
+ struct blk_mq_ctx *ctx = data;
seq_printf(m, "%lu\n", ctx->rq_merged);
return 0;
}
-static int ctx_merged_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ctx_merged_show, inode->i_private);
-}
-
-static ssize_t ctx_merged_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t ctx_merged_write(void *data, const char __user *buf,
+ size_t count, loff_t *ppos)
{
- struct seq_file *m = file->private_data;
- struct blk_mq_ctx *ctx = m->private;
+ struct blk_mq_ctx *ctx = data;
ctx->rq_merged = 0;
return count;
}
-static const struct file_operations ctx_merged_fops = {
- .open = ctx_merged_open,
- .read = seq_read,
- .write = ctx_merged_write,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int ctx_completed_show(struct seq_file *m, void *v)
+static int ctx_completed_show(void *data, struct seq_file *m)
{
- struct blk_mq_ctx *ctx = m->private;
+ struct blk_mq_ctx *ctx = data;
seq_printf(m, "%lu %lu\n", ctx->rq_completed[1], ctx->rq_completed[0]);
return 0;
}
-static int ctx_completed_open(struct inode *inode, struct file *file)
+static ssize_t ctx_completed_write(void *data, const char __user *buf,
+ size_t count, loff_t *ppos)
{
- return single_open(file, ctx_completed_show, inode->i_private);
+ struct blk_mq_ctx *ctx = data;
+
+ ctx->rq_completed[0] = ctx->rq_completed[1] = 0;
+ return count;
}
-static ssize_t ctx_completed_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
+static int blk_mq_debugfs_show(struct seq_file *m, void *v)
+{
+ const struct blk_mq_debugfs_attr *attr = m->private;
+ void *data = d_inode(m->file->f_path.dentry->d_parent)->i_private;
+
+ return attr->show(data, m);
+}
+
+static ssize_t blk_mq_debugfs_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
{
struct seq_file *m = file->private_data;
- struct blk_mq_ctx *ctx = m->private;
+ const struct blk_mq_debugfs_attr *attr = m->private;
+ void *data = d_inode(file->f_path.dentry->d_parent)->i_private;
- ctx->rq_completed[0] = ctx->rq_completed[1] = 0;
- return count;
+ if (!attr->write)
+ return -EPERM;
+
+ return attr->write(data, buf, count, ppos);
+}
+
+static int blk_mq_debugfs_open(struct inode *inode, struct file *file)
+{
+ const struct blk_mq_debugfs_attr *attr = inode->i_private;
+ void *data = d_inode(file->f_path.dentry->d_parent)->i_private;
+ struct seq_file *m;
+ int ret;
+
+ if (attr->seq_ops) {
+ ret = seq_open(file, attr->seq_ops);
+ if (!ret) {
+ m = file->private_data;
+ m->private = data;
+ }
+ return ret;
+ }
+
+ if (WARN_ON_ONCE(!attr->show))
+ return -EPERM;
+
+ return single_open(file, blk_mq_debugfs_show, inode->i_private);
}
-static const struct file_operations ctx_completed_fops = {
- .open = ctx_completed_open,
+static int blk_mq_debugfs_release(struct inode *inode, struct file *file)
+{
+ const struct blk_mq_debugfs_attr *attr = inode->i_private;
+
+ if (attr->show)
+ return single_release(inode, file);
+ else
+ return seq_release(inode, file);
+}
+
+const struct file_operations blk_mq_debugfs_fops = {
+ .open = blk_mq_debugfs_open,
.read = seq_read,
- .write = ctx_completed_write,
+ .write = blk_mq_debugfs_write,
.llseek = seq_lseek,
- .release = single_release,
+ .release = blk_mq_debugfs_release,
};
static const struct blk_mq_debugfs_attr blk_mq_debugfs_queue_attrs[] = {
- {"poll_stat", 0400, &queue_poll_stat_fops},
- {"state", 0600, &blk_queue_flags_fops},
+ {"poll_stat", 0400, queue_poll_stat_show},
+ {"state", 0600, queue_state_show, queue_state_write},
{},
};
static const struct blk_mq_debugfs_attr blk_mq_debugfs_hctx_attrs[] = {
- {"state", 0400, &hctx_state_fops},
- {"flags", 0400, &hctx_flags_fops},
- {"dispatch", 0400, &hctx_dispatch_fops},
- {"ctx_map", 0400, &hctx_ctx_map_fops},
- {"tags", 0400, &hctx_tags_fops},
- {"tags_bitmap", 0400, &hctx_tags_bitmap_fops},
- {"sched_tags", 0400, &hctx_sched_tags_fops},
- {"sched_tags_bitmap", 0400, &hctx_sched_tags_bitmap_fops},
- {"io_poll", 0600, &hctx_io_poll_fops},
- {"dispatched", 0600, &hctx_dispatched_fops},
- {"queued", 0600, &hctx_queued_fops},
- {"run", 0600, &hctx_run_fops},
- {"active", 0400, &hctx_active_fops},
+ {"state", 0400, hctx_state_show},
+ {"flags", 0400, hctx_flags_show},
+ {"dispatch", 0400, .seq_ops = &hctx_dispatch_seq_ops},
+ {"ctx_map", 0400, hctx_ctx_map_show},
+ {"tags", 0400, hctx_tags_show},
+ {"tags_bitmap", 0400, hctx_tags_bitmap_show},
+ {"sched_tags", 0400, hctx_sched_tags_show},
+ {"sched_tags_bitmap", 0400, hctx_sched_tags_bitmap_show},
+ {"io_poll", 0600, hctx_io_poll_show, hctx_io_poll_write},
+ {"dispatched", 0600, hctx_dispatched_show, hctx_dispatched_write},
+ {"queued", 0600, hctx_queued_show, hctx_queued_write},
+ {"run", 0600, hctx_run_show, hctx_run_write},
+ {"active", 0400, hctx_active_show},
{},
};
static const struct blk_mq_debugfs_attr blk_mq_debugfs_ctx_attrs[] = {
- {"rq_list", 0400, &ctx_rq_list_fops},
- {"dispatched", 0600, &ctx_dispatched_fops},
- {"merged", 0600, &ctx_merged_fops},
- {"completed", 0600, &ctx_completed_fops},
+ {"rq_list", 0400, .seq_ops = &ctx_rq_list_seq_ops},
+ {"dispatched", 0600, ctx_dispatched_show, ctx_dispatched_write},
+ {"merged", 0600, ctx_merged_show, ctx_merged_write},
+ {"completed", 0600, ctx_completed_show, ctx_completed_write},
{},
};
@@ -896,11 +701,13 @@ void blk_mq_debugfs_unregister(struct request_queue *q)
}
static bool debugfs_create_files(struct dentry *parent, void *data,
- const struct blk_mq_debugfs_attr *attr)
+ const struct blk_mq_debugfs_attr *attr)
{
+ d_inode(parent)->i_private = data;
+
for (; attr->name; attr++) {
if (!debugfs_create_file(attr->name, attr->mode, parent,
- data, attr->fops))
+ (void *)attr, &blk_mq_debugfs_fops))
return false;
}
return true;
--
2.12.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 3/9] blk-mq-debugfs: get rid of a bunch of boilerplate
2017-05-03 19:18 ` [PATCH 3/9] blk-mq-debugfs: get rid of a bunch of boilerplate Omar Sandoval
@ 2017-05-03 20:51 ` Bart Van Assche
2017-05-03 23:22 ` Omar Sandoval
0 siblings, 1 reply; 13+ messages in thread
From: Bart Van Assche @ 2017-05-03 20:51 UTC (permalink / raw)
To: osandov@osandov.com, linux-block@vger.kernel.org, axboe@fb.com
Cc: kernel-team@fb.com
On Wed, 2017-05-03 at 12:18 -0700, Omar Sandoval wrote:
> From: Omar Sandoval <osandov@fb.com>
>=20
> A large part of blk-mq-debugfs.c is file_operations and seq_file
> boilerplate. This sucks as is but will suck even more when schedulers
> can define their own debugfs entries. Factor it all out into a single
> blk_mq_debugfs_fops which multiplexes as needed. We store the
> request_queue, blk_mq_hw_ctx, or blk_mq_ctx in the parent directory
> dentry, which is kind of hacky, but it works.
>=20
> Signed-off-by: Omar Sandoval <osandov@fb.com>
> ---
> block/blk-mq-debugfs.c | 469 +++++++++++++++----------------------------=
------
> 1 file changed, 138 insertions(+), 331 deletions(-)
>=20
> diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
> index f58a116d6cca..00cc89c34590 100644
> --- a/block/blk-mq-debugfs.c
> +++ b/block/blk-mq-debugfs.c
> @@ -26,23 +26,12 @@
> struct blk_mq_debugfs_attr {
> const char *name;
> umode_t mode;
> - const struct file_operations *fops;
> + int (*show)(void *, struct seq_file *);
Hello Omar,
The current show functions have the seq_file pointer as first argument
but for .show() it is the second argument. Please consider to keep that
pointer as the first argument.
> +static ssize_t queue_state_write(void *data, const char __user *buf,
> + size_t count, loff_t *ppos)
> {
> - struct request_queue *q =3D file_inode(file)->i_private;
> + struct request_queue *q =3D data;
> char op[16] =3D { }, *s;
> =20
> - len =3D min(len, sizeof(op) - 1);
> - if (copy_from_user(op, ubuf, len))
> + if (copy_from_user(op, buf, min(count, sizeof(op) - 1)))
> return -EFAULT;
> s =3D op;
> strsep(&s, " \t\n"); /* strip trailing whitespace */
> @@ -127,22 +115,9 @@ static ssize_t blk_queue_flags_store(struct file *fi=
le, const char __user *ubuf,
> __func__, op);
> return -EINVAL;
> }
> - return len;
> -}
> -
> -static int blk_queue_flags_open(struct inode *inode, struct file *file)
> -{
> - return single_open(file, blk_queue_flags_show, inode->i_private);
> + return count;
> }
Please move the return value changes of queue_state_write() into a separate
patch since these are a bug fix and not related to the removal of the
boilerplate code.
Thanks,
Bart.
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH 3/9] blk-mq-debugfs: get rid of a bunch of boilerplate
2017-05-03 20:51 ` Bart Van Assche
@ 2017-05-03 23:22 ` Omar Sandoval
0 siblings, 0 replies; 13+ messages in thread
From: Omar Sandoval @ 2017-05-03 23:22 UTC (permalink / raw)
To: Bart Van Assche
Cc: linux-block@vger.kernel.org, axboe@fb.com, kernel-team@fb.com
On Wed, May 03, 2017 at 08:51:11PM +0000, Bart Van Assche wrote:
> On Wed, 2017-05-03 at 12:18 -0700, Omar Sandoval wrote:
> > From: Omar Sandoval <osandov@fb.com>
> >
> > A large part of blk-mq-debugfs.c is file_operations and seq_file
> > boilerplate. This sucks as is but will suck even more when schedulers
> > can define their own debugfs entries. Factor it all out into a single
> > blk_mq_debugfs_fops which multiplexes as needed. We store the
> > request_queue, blk_mq_hw_ctx, or blk_mq_ctx in the parent directory
> > dentry, which is kind of hacky, but it works.
> >
> > Signed-off-by: Omar Sandoval <osandov@fb.com>
> > ---
> > block/blk-mq-debugfs.c | 469 +++++++++++++++----------------------------------
> > 1 file changed, 138 insertions(+), 331 deletions(-)
> >
> > diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
> > index f58a116d6cca..00cc89c34590 100644
> > --- a/block/blk-mq-debugfs.c
> > +++ b/block/blk-mq-debugfs.c
> > @@ -26,23 +26,12 @@
> > struct blk_mq_debugfs_attr {
> > const char *name;
> > umode_t mode;
> > - const struct file_operations *fops;
> > + int (*show)(void *, struct seq_file *);
>
> Hello Omar,
>
> The current show functions have the seq_file pointer as first argument
> but for .show() it is the second argument. Please consider to keep that
> pointer as the first argument.
The current show functions aren't the same thing, though. The void *
argument to those is meaningless, and the data is in m->private instead
of being passed in. I don't want to conflate the two calling
conventions.
Really what I wanted were strongly-typed show/write functions, i.e., one of
int (*show)(struct request_queue *, struct seq_file *);
int (*show)(struct blk_mq_hw_ctx *, struct seq_file *);
int (*show)(struct blk_mq_ctx *, struct seq_file *);
But I couldn't come up with a nice way to do that.
> > +static ssize_t queue_state_write(void *data, const char __user *buf,
> > + size_t count, loff_t *ppos)
> > {
> > - struct request_queue *q = file_inode(file)->i_private;
> > + struct request_queue *q = data;
> > char op[16] = { }, *s;
> >
> > - len = min(len, sizeof(op) - 1);
> > - if (copy_from_user(op, ubuf, len))
> > + if (copy_from_user(op, buf, min(count, sizeof(op) - 1)))
> > return -EFAULT;
> > s = op;
> > strsep(&s, " \t\n"); /* strip trailing whitespace */
> > @@ -127,22 +115,9 @@ static ssize_t blk_queue_flags_store(struct file *file, const char __user *ubuf,
> > __func__, op);
> > return -EINVAL;
> > }
> > - return len;
> > -}
> > -
> > -static int blk_queue_flags_open(struct inode *inode, struct file *file)
> > -{
> > - return single_open(file, blk_queue_flags_show, inode->i_private);
> > + return count;
> > }
>
> Please move the return value changes of queue_state_write() into a separate
> patch since these are a bug fix and not related to the removal of the
> boilerplate code.
Sure, I'll do that.
Thanks for the review.
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 4/9] blk-mq: Do not invoke queue operations on a dead queue
2017-05-03 19:18 [PATCH 0/9] blk-mq-debugfs: scheduler support and cleanups Omar Sandoval
` (2 preceding siblings ...)
2017-05-03 19:18 ` [PATCH 3/9] blk-mq-debugfs: get rid of a bunch of boilerplate Omar Sandoval
@ 2017-05-03 19:18 ` Omar Sandoval
2017-05-03 19:18 ` [PATCH 5/9] blk-mq: move debugfs declarations to a separate header file Omar Sandoval
` (5 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Omar Sandoval @ 2017-05-03 19:18 UTC (permalink / raw)
To: Jens Axboe, linux-block; +Cc: Bart Van Assche, kernel-team
From: Bart Van Assche <bart.vanassche@sandisk.com>
In commit e869b5462f83 ("blk-mq: Unregister debugfs attributes
earlier"), we shuffled the debugfs cleanup around so that the "state"
attribute was removed before we freed the blk-mq data structures.
However, later changes are going to undo that, so we need to explicitly
disallow running a dead queue.
[Omar: rebased and updated commit message]
Signed-off-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
block/blk-mq-debugfs.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 00cc89c34590..48b9f59acd91 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -102,6 +102,14 @@ static ssize_t queue_state_write(void *data, const char __user *buf,
struct request_queue *q = data;
char op[16] = { }, *s;
+ /*
+ * The "state" attribute is removed after blk_cleanup_queue() has called
+ * blk_mq_free_queue(). Return if QUEUE_FLAG_DEAD has been set to avoid
+ * triggering a use-after-free.
+ */
+ if (blk_queue_dead(q))
+ return -ENOENT;
+
if (copy_from_user(op, buf, min(count, sizeof(op) - 1)))
return -EFAULT;
s = op;
--
2.12.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 5/9] blk-mq: move debugfs declarations to a separate header file
2017-05-03 19:18 [PATCH 0/9] blk-mq-debugfs: scheduler support and cleanups Omar Sandoval
` (3 preceding siblings ...)
2017-05-03 19:18 ` [PATCH 4/9] blk-mq: Do not invoke queue operations on a dead queue Omar Sandoval
@ 2017-05-03 19:18 ` Omar Sandoval
2017-05-03 19:18 ` [PATCH 6/9] blk-mq: untangle debugfs and sysfs Omar Sandoval
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Omar Sandoval @ 2017-05-03 19:18 UTC (permalink / raw)
To: Jens Axboe, linux-block; +Cc: Bart Van Assche, kernel-team
From: Omar Sandoval <osandov@fb.com>
Preparation for adding more declarations.
Signed-off-by: Omar Sandoval <osandov@fb.com>
---
block/blk-core.c | 1 +
block/blk-mq-debugfs.c | 1 +
block/blk-mq-debugfs.h | 29 +++++++++++++++++++++++++++++
block/blk-mq-sysfs.c | 1 +
block/blk-mq.h | 28 ----------------------------
block/blk-sysfs.c | 1 +
6 files changed, 33 insertions(+), 28 deletions(-)
create mode 100644 block/blk-mq-debugfs.h
diff --git a/block/blk-core.c b/block/blk-core.c
index 24886b69690f..acdca6536562 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -40,6 +40,7 @@
#include "blk.h"
#include "blk-mq.h"
+#include "blk-mq-debugfs.h"
#include "blk-mq-sched.h"
#include "blk-wbt.h"
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 48b9f59acd91..6f98eb15e4f6 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -21,6 +21,7 @@
#include <linux/blk-mq.h>
#include "blk.h"
#include "blk-mq.h"
+#include "blk-mq-debugfs.h"
#include "blk-mq-tag.h"
struct blk_mq_debugfs_attr {
diff --git a/block/blk-mq-debugfs.h b/block/blk-mq-debugfs.h
new file mode 100644
index 000000000000..00b0f71d0ae9
--- /dev/null
+++ b/block/blk-mq-debugfs.h
@@ -0,0 +1,29 @@
+#ifndef INT_BLK_MQ_DEBUGFS_H
+#define INT_BLK_MQ_DEBUGFS_H
+
+#ifdef CONFIG_BLK_DEBUG_FS
+int blk_mq_debugfs_register(struct request_queue *q);
+void blk_mq_debugfs_unregister(struct request_queue *q);
+int blk_mq_debugfs_register_mq(struct request_queue *q);
+void blk_mq_debugfs_unregister_mq(struct request_queue *q);
+#else
+static inline int blk_mq_debugfs_register(struct request_queue *q)
+{
+ return 0;
+}
+
+static inline void blk_mq_debugfs_unregister(struct request_queue *q)
+{
+}
+
+static inline int blk_mq_debugfs_register_mq(struct request_queue *q)
+{
+ return 0;
+}
+
+static inline void blk_mq_debugfs_unregister_mq(struct request_queue *q)
+{
+}
+#endif
+
+#endif
diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c
index ec0afdf765e3..71a237a90d43 100644
--- a/block/blk-mq-sysfs.c
+++ b/block/blk-mq-sysfs.c
@@ -11,6 +11,7 @@
#include <linux/blk-mq.h>
#include "blk-mq.h"
+#include "blk-mq-debugfs.h"
#include "blk-mq-tag.h"
static void blk_mq_sysfs_release(struct kobject *kobj)
diff --git a/block/blk-mq.h b/block/blk-mq.h
index 2814a14e529c..cc67b48e3551 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -83,34 +83,6 @@ extern int blk_mq_sysfs_register(struct request_queue *q);
extern void blk_mq_sysfs_unregister(struct request_queue *q);
extern void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx);
-/*
- * debugfs helpers
- */
-#ifdef CONFIG_BLK_DEBUG_FS
-int blk_mq_debugfs_register(struct request_queue *q);
-void blk_mq_debugfs_unregister(struct request_queue *q);
-int blk_mq_debugfs_register_mq(struct request_queue *q);
-void blk_mq_debugfs_unregister_mq(struct request_queue *q);
-#else
-static inline int blk_mq_debugfs_register(struct request_queue *q)
-{
- return 0;
-}
-
-static inline void blk_mq_debugfs_unregister(struct request_queue *q)
-{
-}
-
-static inline int blk_mq_debugfs_register_mq(struct request_queue *q)
-{
- return 0;
-}
-
-static inline void blk_mq_debugfs_unregister_mq(struct request_queue *q)
-{
-}
-#endif
-
extern void blk_mq_rq_timed_out(struct request *req, bool reserved);
void blk_mq_release(struct request_queue *q);
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 3f37813ccbaf..9995355121d7 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -13,6 +13,7 @@
#include "blk.h"
#include "blk-mq.h"
+#include "blk-mq-debugfs.h"
#include "blk-wbt.h"
struct queue_sysfs_entry {
--
2.12.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 6/9] blk-mq: untangle debugfs and sysfs
2017-05-03 19:18 [PATCH 0/9] blk-mq-debugfs: scheduler support and cleanups Omar Sandoval
` (4 preceding siblings ...)
2017-05-03 19:18 ` [PATCH 5/9] blk-mq: move debugfs declarations to a separate header file Omar Sandoval
@ 2017-05-03 19:18 ` Omar Sandoval
2017-05-03 19:19 ` [PATCH 7/9] blk-mq-debugfs: allow schedulers to register debugfs attributes Omar Sandoval
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Omar Sandoval @ 2017-05-03 19:18 UTC (permalink / raw)
To: Jens Axboe, linux-block; +Cc: Bart Van Assche, kernel-team
From: Omar Sandoval <osandov@fb.com>
Originally, I tied debugfs registration/unregistration together with
sysfs. There's no reason to do this, and it's getting in the way of
letting schedulers define their own debugfs attributes. Instead, tie the
debugfs registration to the lifetime of the structures themselves.
The saner lifetimes mean we can also get rid of the extra mq directory
and move everything one level up. I.e., nvme0n1/mq/0/tags is now just
nvme0n1/0/tags.
Signed-off-by: Omar Sandoval <osandov@fb.com>
---
block/blk-core.c | 9 +---
block/blk-mq-debugfs.c | 110 ++++++++++++++++++++++++++++---------------------
block/blk-mq-debugfs.h | 21 ++++++++--
block/blk-mq-sysfs.c | 11 -----
block/blk-mq.c | 7 ++++
block/blk-sysfs.c | 2 +
include/linux/blk-mq.h | 4 ++
include/linux/blkdev.h | 1 -
8 files changed, 94 insertions(+), 71 deletions(-)
diff --git a/block/blk-core.c b/block/blk-core.c
index acdca6536562..c580b0138a7f 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -40,7 +40,6 @@
#include "blk.h"
#include "blk-mq.h"
-#include "blk-mq-debugfs.h"
#include "blk-mq-sched.h"
#include "blk-wbt.h"
@@ -562,13 +561,9 @@ void blk_cleanup_queue(struct request_queue *q)
* prevent that q->request_fn() gets invoked after draining finished.
*/
blk_freeze_queue(q);
- if (!q->mq_ops) {
- spin_lock_irq(lock);
+ spin_lock_irq(lock);
+ if (!q->mq_ops)
__blk_drain_queue(q, true);
- } else {
- blk_mq_debugfs_unregister_mq(q);
- spin_lock_irq(lock);
- }
queue_flag_set(QUEUE_FLAG_DEAD, q);
spin_unlock_irq(lock);
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 6f98eb15e4f6..5c9e870a2866 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -682,19 +682,46 @@ static const struct blk_mq_debugfs_attr blk_mq_debugfs_ctx_attrs[] = {
{},
};
+static bool debugfs_create_files(struct dentry *parent, void *data,
+ const struct blk_mq_debugfs_attr *attr)
+{
+ d_inode(parent)->i_private = data;
+
+ for (; attr->name; attr++) {
+ if (!debugfs_create_file(attr->name, attr->mode, parent,
+ (void *)attr, &blk_mq_debugfs_fops))
+ return false;
+ }
+ return true;
+}
+
int blk_mq_debugfs_register(struct request_queue *q)
{
+ struct blk_mq_hw_ctx *hctx;
+ int i;
+
if (!blk_debugfs_root)
return -ENOENT;
q->debugfs_dir = debugfs_create_dir(kobject_name(q->kobj.parent),
blk_debugfs_root);
if (!q->debugfs_dir)
- goto err;
+ return -ENOMEM;
- if (blk_mq_debugfs_register_mq(q))
+ if (!debugfs_create_files(q->debugfs_dir, q,
+ blk_mq_debugfs_queue_attrs))
goto err;
+ /*
+ * blk_mq_init_hctx() attempted to do this already, but q->debugfs_dir
+ * didn't exist yet (because we don't know what to name the directory
+ * until the queue is registered to a gendisk).
+ */
+ queue_for_each_hw_ctx(q, hctx, i) {
+ if (!hctx->debugfs_dir && blk_mq_debugfs_register_hctx(q, hctx))
+ goto err;
+ }
+
return 0;
err:
@@ -705,32 +732,17 @@ int blk_mq_debugfs_register(struct request_queue *q)
void blk_mq_debugfs_unregister(struct request_queue *q)
{
debugfs_remove_recursive(q->debugfs_dir);
- q->mq_debugfs_dir = NULL;
q->debugfs_dir = NULL;
}
-static bool debugfs_create_files(struct dentry *parent, void *data,
- const struct blk_mq_debugfs_attr *attr)
-{
- d_inode(parent)->i_private = data;
-
- for (; attr->name; attr++) {
- if (!debugfs_create_file(attr->name, attr->mode, parent,
- (void *)attr, &blk_mq_debugfs_fops))
- return false;
- }
- return true;
-}
-
-static int blk_mq_debugfs_register_ctx(struct request_queue *q,
- struct blk_mq_ctx *ctx,
- struct dentry *hctx_dir)
+static int blk_mq_debugfs_register_ctx(struct blk_mq_hw_ctx *hctx,
+ struct blk_mq_ctx *ctx)
{
struct dentry *ctx_dir;
char name[20];
snprintf(name, sizeof(name), "cpu%u", ctx->cpu);
- ctx_dir = debugfs_create_dir(name, hctx_dir);
+ ctx_dir = debugfs_create_dir(name, hctx->debugfs_dir);
if (!ctx_dir)
return -ENOMEM;
@@ -740,59 +752,61 @@ static int blk_mq_debugfs_register_ctx(struct request_queue *q,
return 0;
}
-static int blk_mq_debugfs_register_hctx(struct request_queue *q,
- struct blk_mq_hw_ctx *hctx)
+int blk_mq_debugfs_register_hctx(struct request_queue *q,
+ struct blk_mq_hw_ctx *hctx)
{
struct blk_mq_ctx *ctx;
- struct dentry *hctx_dir;
char name[20];
int i;
+ if (!q->debugfs_dir)
+ return -ENOENT;
+
snprintf(name, sizeof(name), "%u", hctx->queue_num);
- hctx_dir = debugfs_create_dir(name, q->mq_debugfs_dir);
- if (!hctx_dir)
+ hctx->debugfs_dir = debugfs_create_dir(name, q->debugfs_dir);
+ if (!hctx->debugfs_dir)
return -ENOMEM;
- if (!debugfs_create_files(hctx_dir, hctx, blk_mq_debugfs_hctx_attrs))
- return -ENOMEM;
+ if (!debugfs_create_files(hctx->debugfs_dir, hctx,
+ blk_mq_debugfs_hctx_attrs))
+ goto err;
hctx_for_each_ctx(hctx, ctx, i) {
- if (blk_mq_debugfs_register_ctx(q, ctx, hctx_dir))
- return -ENOMEM;
+ if (blk_mq_debugfs_register_ctx(hctx, ctx))
+ goto err;
}
return 0;
+
+err:
+ blk_mq_debugfs_unregister_hctx(hctx);
+ return -ENOMEM;
+}
+
+void blk_mq_debugfs_unregister_hctx(struct blk_mq_hw_ctx *hctx)
+{
+ debugfs_remove_recursive(hctx->debugfs_dir);
+ hctx->debugfs_dir = NULL;
}
-int blk_mq_debugfs_register_mq(struct request_queue *q)
+int blk_mq_debugfs_register_hctxs(struct request_queue *q)
{
struct blk_mq_hw_ctx *hctx;
int i;
- if (!q->debugfs_dir)
- return -ENOENT;
-
- q->mq_debugfs_dir = debugfs_create_dir("mq", q->debugfs_dir);
- if (!q->mq_debugfs_dir)
- goto err;
-
- if (!debugfs_create_files(q->mq_debugfs_dir, q, blk_mq_debugfs_queue_attrs))
- goto err;
-
queue_for_each_hw_ctx(q, hctx, i) {
if (blk_mq_debugfs_register_hctx(q, hctx))
- goto err;
+ return -ENOMEM;
}
return 0;
-
-err:
- blk_mq_debugfs_unregister_mq(q);
- return -ENOMEM;
}
-void blk_mq_debugfs_unregister_mq(struct request_queue *q)
+void blk_mq_debugfs_unregister_hctxs(struct request_queue *q)
{
- debugfs_remove_recursive(q->mq_debugfs_dir);
- q->mq_debugfs_dir = NULL;
+ struct blk_mq_hw_ctx *hctx;
+ int i;
+
+ queue_for_each_hw_ctx(q, hctx, i)
+ blk_mq_debugfs_unregister_hctx(hctx);
}
diff --git a/block/blk-mq-debugfs.h b/block/blk-mq-debugfs.h
index 00b0f71d0ae9..596e9b16d3d1 100644
--- a/block/blk-mq-debugfs.h
+++ b/block/blk-mq-debugfs.h
@@ -4,8 +4,11 @@
#ifdef CONFIG_BLK_DEBUG_FS
int blk_mq_debugfs_register(struct request_queue *q);
void blk_mq_debugfs_unregister(struct request_queue *q);
-int blk_mq_debugfs_register_mq(struct request_queue *q);
-void blk_mq_debugfs_unregister_mq(struct request_queue *q);
+int blk_mq_debugfs_register_hctx(struct request_queue *q,
+ struct blk_mq_hw_ctx *hctx);
+void blk_mq_debugfs_unregister_hctx(struct blk_mq_hw_ctx *hctx);
+int blk_mq_debugfs_register_hctxs(struct request_queue *q);
+void blk_mq_debugfs_unregister_hctxs(struct request_queue *q);
#else
static inline int blk_mq_debugfs_register(struct request_queue *q)
{
@@ -16,12 +19,22 @@ static inline void blk_mq_debugfs_unregister(struct request_queue *q)
{
}
-static inline int blk_mq_debugfs_register_mq(struct request_queue *q)
+static inline int blk_mq_debugfs_register_hctx(struct request_queue *q,
+ struct blk_mq_hw_ctx *hctx)
{
return 0;
}
-static inline void blk_mq_debugfs_unregister_mq(struct request_queue *q)
+static inline void blk_mq_debugfs_unregister_hctx(struct blk_mq_hw_ctx *hctx)
+{
+}
+
+static inline int blk_mq_debugfs_register_hctxs(struct request_queue *q)
+{
+ return 0;
+}
+
+static inline void blk_mq_debugfs_unregister_hctxs(struct request_queue *q)
{
}
#endif
diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c
index 71a237a90d43..79969c3c234f 100644
--- a/block/blk-mq-sysfs.c
+++ b/block/blk-mq-sysfs.c
@@ -11,7 +11,6 @@
#include <linux/blk-mq.h>
#include "blk-mq.h"
-#include "blk-mq-debugfs.h"
#include "blk-mq-tag.h"
static void blk_mq_sysfs_release(struct kobject *kobj)
@@ -259,8 +258,6 @@ static void __blk_mq_unregister_dev(struct device *dev, struct request_queue *q)
queue_for_each_hw_ctx(q, hctx, i)
blk_mq_unregister_hctx(hctx);
- blk_mq_debugfs_unregister_mq(q);
-
kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
kobject_del(&q->mq_kobj);
kobject_put(&dev->kobj);
@@ -319,8 +316,6 @@ int __blk_mq_register_dev(struct device *dev, struct request_queue *q)
kobject_uevent(&q->mq_kobj, KOBJ_ADD);
- blk_mq_debugfs_register(q);
-
queue_for_each_hw_ctx(q, hctx, i) {
ret = blk_mq_register_hctx(hctx);
if (ret)
@@ -336,8 +331,6 @@ int __blk_mq_register_dev(struct device *dev, struct request_queue *q)
while (--i >= 0)
blk_mq_unregister_hctx(q->queue_hw_ctx[i]);
- blk_mq_debugfs_unregister_mq(q);
-
kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
kobject_del(&q->mq_kobj);
kobject_put(&dev->kobj);
@@ -365,8 +358,6 @@ void blk_mq_sysfs_unregister(struct request_queue *q)
if (!q->mq_sysfs_init_done)
goto unlock;
- blk_mq_debugfs_unregister_mq(q);
-
queue_for_each_hw_ctx(q, hctx, i)
blk_mq_unregister_hctx(hctx);
@@ -383,8 +374,6 @@ int blk_mq_sysfs_register(struct request_queue *q)
if (!q->mq_sysfs_init_done)
goto unlock;
- blk_mq_debugfs_register_mq(q);
-
queue_for_each_hw_ctx(q, hctx, i) {
ret = blk_mq_register_hctx(hctx);
if (ret)
diff --git a/block/blk-mq.c b/block/blk-mq.c
index bf90684a007a..f54467a84d9a 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -31,6 +31,7 @@
#include <linux/blk-mq.h>
#include "blk.h"
#include "blk-mq.h"
+#include "blk-mq-debugfs.h"
#include "blk-mq-tag.h"
#include "blk-stat.h"
#include "blk-wbt.h"
@@ -1851,6 +1852,8 @@ static void blk_mq_exit_hctx(struct request_queue *q,
{
unsigned flush_start_tag = set->queue_depth;
+ blk_mq_debugfs_unregister_hctx(hctx);
+
blk_mq_tag_idle(hctx);
if (set->ops->exit_request)
@@ -1941,6 +1944,8 @@ static int blk_mq_init_hctx(struct request_queue *q,
if (hctx->flags & BLK_MQ_F_BLOCKING)
init_srcu_struct(&hctx->queue_rq_srcu);
+ blk_mq_debugfs_register_hctx(q, hctx);
+
return 0;
free_fq:
@@ -2378,6 +2383,7 @@ static void blk_mq_queue_reinit(struct request_queue *q,
{
WARN_ON_ONCE(!atomic_read(&q->mq_freeze_depth));
+ blk_mq_debugfs_unregister_hctxs(q);
blk_mq_sysfs_unregister(q);
/*
@@ -2389,6 +2395,7 @@ static void blk_mq_queue_reinit(struct request_queue *q,
blk_mq_map_swqueue(q, online_mask);
blk_mq_sysfs_register(q);
+ blk_mq_debugfs_register_hctxs(q);
}
/*
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 9995355121d7..504fee940052 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -890,6 +890,8 @@ int blk_register_queue(struct gendisk *disk)
if (q->mq_ops)
__blk_mq_register_dev(dev, q);
+ blk_mq_debugfs_register(q);
+
kobject_uevent(&q->kobj, KOBJ_ADD);
wbt_enable_default(q);
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index f3e5e1de1bdb..7c2fc881fe09 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -57,6 +57,10 @@ struct blk_mq_hw_ctx {
unsigned long poll_considered;
unsigned long poll_invoked;
unsigned long poll_success;
+
+#ifdef CONFIG_BLK_DEBUG_FS
+ struct dentry *debugfs_dir;
+#endif
};
struct blk_mq_tag_set {
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 83d28623645f..b49a79a29e58 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -579,7 +579,6 @@ struct request_queue {
#ifdef CONFIG_BLK_DEBUG_FS
struct dentry *debugfs_dir;
- struct dentry *mq_debugfs_dir;
#endif
bool mq_sysfs_init_done;
--
2.12.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 7/9] blk-mq-debugfs: allow schedulers to register debugfs attributes
2017-05-03 19:18 [PATCH 0/9] blk-mq-debugfs: scheduler support and cleanups Omar Sandoval
` (5 preceding siblings ...)
2017-05-03 19:18 ` [PATCH 6/9] blk-mq: untangle debugfs and sysfs Omar Sandoval
@ 2017-05-03 19:19 ` Omar Sandoval
2017-05-03 19:19 ` [PATCH 8/9] kyber: add " Omar Sandoval
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Omar Sandoval @ 2017-05-03 19:19 UTC (permalink / raw)
To: Jens Axboe, linux-block; +Cc: Bart Van Assche, kernel-team
From: Omar Sandoval <osandov@fb.com>
This provides the infrastructure for schedulers to expose their internal
state through debugfs. We add a list of queue attributes and a list of
hctx attributes to struct elevator_type and wire them up when switching
schedulers.
Signed-off-by: Omar Sandoval <osandov@fb.com>
---
block/blk-mq-debugfs.c | 74 ++++++++++++++++++++++++++++++++++++++++++------
block/blk-mq-debugfs.h | 34 ++++++++++++++++++++++
block/blk-mq-sched.c | 24 ++++++++++------
include/linux/blk-mq.h | 1 +
include/linux/blkdev.h | 1 +
include/linux/elevator.h | 7 +++++
6 files changed, 124 insertions(+), 17 deletions(-)
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 5c9e870a2866..53a37c467685 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -24,15 +24,6 @@
#include "blk-mq-debugfs.h"
#include "blk-mq-tag.h"
-struct blk_mq_debugfs_attr {
- const char *name;
- umode_t mode;
- int (*show)(void *, struct seq_file *);
- ssize_t (*write)(void *, const char __user *, size_t, loff_t *);
- /* Set either .show or .seq_ops. */
- const struct seq_operations *seq_ops;
-};
-
static int blk_flags_show(struct seq_file *m, const unsigned long flags,
const char *const *flag_name, int flag_name_count)
{
@@ -720,6 +711,9 @@ int blk_mq_debugfs_register(struct request_queue *q)
queue_for_each_hw_ctx(q, hctx, i) {
if (!hctx->debugfs_dir && blk_mq_debugfs_register_hctx(q, hctx))
goto err;
+ if (q->elevator && !hctx->sched_debugfs_dir &&
+ blk_mq_debugfs_register_sched_hctx(q, hctx))
+ goto err;
}
return 0;
@@ -732,6 +726,7 @@ int blk_mq_debugfs_register(struct request_queue *q)
void blk_mq_debugfs_unregister(struct request_queue *q)
{
debugfs_remove_recursive(q->debugfs_dir);
+ q->sched_debugfs_dir = NULL;
q->debugfs_dir = NULL;
}
@@ -786,6 +781,7 @@ int blk_mq_debugfs_register_hctx(struct request_queue *q,
void blk_mq_debugfs_unregister_hctx(struct blk_mq_hw_ctx *hctx)
{
debugfs_remove_recursive(hctx->debugfs_dir);
+ hctx->sched_debugfs_dir = NULL;
hctx->debugfs_dir = NULL;
}
@@ -810,3 +806,63 @@ void blk_mq_debugfs_unregister_hctxs(struct request_queue *q)
queue_for_each_hw_ctx(q, hctx, i)
blk_mq_debugfs_unregister_hctx(hctx);
}
+
+int blk_mq_debugfs_register_sched(struct request_queue *q)
+{
+ struct elevator_type *e = q->elevator->type;
+
+ if (!q->debugfs_dir)
+ return -ENOENT;
+
+ if (!e->queue_debugfs_attrs)
+ return 0;
+
+ q->sched_debugfs_dir = debugfs_create_dir("sched", q->debugfs_dir);
+ if (!q->sched_debugfs_dir)
+ return -ENOMEM;
+
+ if (!debugfs_create_files(q->sched_debugfs_dir, q,
+ e->queue_debugfs_attrs))
+ goto err;
+
+ return 0;
+
+err:
+ blk_mq_debugfs_unregister_sched(q);
+ return -ENOMEM;
+}
+
+void blk_mq_debugfs_unregister_sched(struct request_queue *q)
+{
+ debugfs_remove_recursive(q->sched_debugfs_dir);
+ q->sched_debugfs_dir = NULL;
+}
+
+int blk_mq_debugfs_register_sched_hctx(struct request_queue *q,
+ struct blk_mq_hw_ctx *hctx)
+{
+ struct elevator_type *e = q->elevator->type;
+
+ if (!hctx->debugfs_dir)
+ return -ENOENT;
+
+ if (!e->hctx_debugfs_attrs)
+ return 0;
+
+ hctx->sched_debugfs_dir = debugfs_create_dir("sched",
+ hctx->debugfs_dir);
+ if (!hctx->sched_debugfs_dir)
+ return -ENOMEM;
+
+ if (!debugfs_create_files(hctx->sched_debugfs_dir, hctx,
+ e->hctx_debugfs_attrs))
+ return -ENOMEM;
+
+ return 0;
+}
+
+void blk_mq_debugfs_unregister_sched_hctx(struct blk_mq_hw_ctx *hctx)
+{
+ debugfs_remove_recursive(hctx->sched_debugfs_dir);
+ hctx->sched_debugfs_dir = NULL;
+}
diff --git a/block/blk-mq-debugfs.h b/block/blk-mq-debugfs.h
index 596e9b16d3d1..29ecb43aa412 100644
--- a/block/blk-mq-debugfs.h
+++ b/block/blk-mq-debugfs.h
@@ -2,6 +2,15 @@
#define INT_BLK_MQ_DEBUGFS_H
#ifdef CONFIG_BLK_DEBUG_FS
+struct blk_mq_debugfs_attr {
+ const char *name;
+ umode_t mode;
+ int (*show)(void *, struct seq_file *);
+ ssize_t (*write)(void *, const char __user *, size_t, loff_t *);
+ /* Set either .show or .seq_ops. */
+ const struct seq_operations *seq_ops;
+};
+
int blk_mq_debugfs_register(struct request_queue *q);
void blk_mq_debugfs_unregister(struct request_queue *q);
int blk_mq_debugfs_register_hctx(struct request_queue *q,
@@ -9,6 +18,12 @@ int blk_mq_debugfs_register_hctx(struct request_queue *q,
void blk_mq_debugfs_unregister_hctx(struct blk_mq_hw_ctx *hctx);
int blk_mq_debugfs_register_hctxs(struct request_queue *q);
void blk_mq_debugfs_unregister_hctxs(struct request_queue *q);
+
+int blk_mq_debugfs_register_sched(struct request_queue *q);
+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);
#else
static inline int blk_mq_debugfs_register(struct request_queue *q)
{
@@ -37,6 +52,25 @@ static inline int blk_mq_debugfs_register_hctxs(struct request_queue *q)
static inline void blk_mq_debugfs_unregister_hctxs(struct request_queue *q)
{
}
+
+static inline int blk_mq_debugfs_register_sched(struct request_queue *q)
+{
+ return 0;
+}
+
+static inline void blk_mq_debugfs_unregister_sched(struct request_queue *q)
+{
+}
+
+static inline int blk_mq_debugfs_register_sched_hctx(struct request_queue *q,
+ struct blk_mq_hw_ctx *hctx)
+{
+ return 0;
+}
+
+static inline void blk_mq_debugfs_unregister_sched_hctx(struct blk_mq_hw_ctx *hctx)
+{
+}
#endif
#endif
diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c
index 8b361e192e8a..4a8f569f1d21 100644
--- a/block/blk-mq-sched.c
+++ b/block/blk-mq-sched.c
@@ -11,6 +11,7 @@
#include "blk.h"
#include "blk-mq.h"
+#include "blk-mq-debugfs.h"
#include "blk-mq-sched.h"
#include "blk-mq-tag.h"
#include "blk-wbt.h"
@@ -476,6 +477,8 @@ int blk_mq_sched_init_hctx(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
}
}
+ blk_mq_debugfs_register_sched_hctx(q, hctx);
+
return 0;
}
@@ -487,6 +490,8 @@ void blk_mq_sched_exit_hctx(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
if (!e)
return;
+ blk_mq_debugfs_unregister_sched_hctx(hctx);
+
if (e->type->ops.mq.exit_hctx && hctx->sched_data) {
e->type->ops.mq.exit_hctx(hctx, hctx_idx);
hctx->sched_data = NULL;
@@ -523,8 +528,10 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
if (ret)
goto err;
- if (e->ops.mq.init_hctx) {
- queue_for_each_hw_ctx(q, hctx, i) {
+ blk_mq_debugfs_register_sched(q);
+
+ queue_for_each_hw_ctx(q, hctx, i) {
+ if (e->ops.mq.init_hctx) {
ret = e->ops.mq.init_hctx(hctx, i);
if (ret) {
eq = q->elevator;
@@ -533,6 +540,7 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
return ret;
}
}
+ blk_mq_debugfs_register_sched_hctx(q, hctx);
}
return 0;
@@ -548,14 +556,14 @@ 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;
- }
+ queue_for_each_hw_ctx(q, hctx, i) {
+ blk_mq_debugfs_unregister_sched_hctx(hctx);
+ if (e->type->ops.mq.exit_hctx && hctx->sched_data) {
+ e->type->ops.mq.exit_hctx(hctx, i);
+ hctx->sched_data = NULL;
}
}
+ blk_mq_debugfs_unregister_sched(q);
if (e->type->ops.mq.exit_sched)
e->type->ops.mq.exit_sched(e);
blk_mq_sched_tags_teardown(q);
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 7c2fc881fe09..863409266eb7 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -60,6 +60,7 @@ struct blk_mq_hw_ctx {
#ifdef CONFIG_BLK_DEBUG_FS
struct dentry *debugfs_dir;
+ struct dentry *sched_debugfs_dir;
#endif
};
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index b49a79a29e58..80ae958717a1 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -579,6 +579,7 @@ struct request_queue {
#ifdef CONFIG_BLK_DEBUG_FS
struct dentry *debugfs_dir;
+ struct dentry *sched_debugfs_dir;
#endif
bool mq_sysfs_init_done;
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 3a216318ae73..baaa12cd4dd9 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -8,6 +8,9 @@
struct io_cq;
struct elevator_type;
+#ifdef CONFIG_BLK_DEBUG_FS
+struct blk_mq_debugfs_attr;
+#endif
/*
* Return values from elevator merger
@@ -144,6 +147,10 @@ struct elevator_type
char elevator_name[ELV_NAME_MAX];
struct module *elevator_owner;
bool uses_mq;
+#ifdef CONFIG_BLK_DEBUG_FS
+ const struct blk_mq_debugfs_attr *queue_debugfs_attrs;
+ const struct blk_mq_debugfs_attr *hctx_debugfs_attrs;
+#endif
/* managed by elevator core */
char icq_cache_name[ELV_NAME_MAX + 5]; /* elvname + "_io_cq" */
--
2.12.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 8/9] kyber: add debugfs attributes
2017-05-03 19:18 [PATCH 0/9] blk-mq-debugfs: scheduler support and cleanups Omar Sandoval
` (6 preceding siblings ...)
2017-05-03 19:19 ` [PATCH 7/9] blk-mq-debugfs: allow schedulers to register debugfs attributes Omar Sandoval
@ 2017-05-03 19:19 ` Omar Sandoval
2017-05-03 19:19 ` [PATCH 9/9] mq-deadline: " Omar Sandoval
2017-05-03 19:57 ` [PATCH 10/9] blk-mq-debugfs: rename hw queue directories from <n> to hctx<n> Omar Sandoval
9 siblings, 0 replies; 13+ messages in thread
From: Omar Sandoval @ 2017-05-03 19:19 UTC (permalink / raw)
To: Jens Axboe, linux-block; +Cc: Bart Van Assche, kernel-team
From: Omar Sandoval <osandov@fb.com>
Expose the domain token pools, asynchronous sbitmap depth, domain
request lists, and batching state.
Signed-off-by: Omar Sandoval <osandov@fb.com>
---
block/blk-mq-debugfs.c | 2 +-
block/blk-mq-debugfs.h | 2 +
block/kyber-iosched.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 133 insertions(+), 1 deletion(-)
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 53a37c467685..6c12b4dbc8ec 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -262,7 +262,7 @@ static const char *const rqf_name[] = {
};
#undef RQF_NAME
-static int blk_mq_debugfs_rq_show(struct seq_file *m, void *v)
+int blk_mq_debugfs_rq_show(struct seq_file *m, void *v)
{
struct request *rq = list_entry_rq(v);
const struct blk_mq_ops *const mq_ops = rq->q->mq_ops;
diff --git a/block/blk-mq-debugfs.h b/block/blk-mq-debugfs.h
index 29ecb43aa412..7c67f813a294 100644
--- a/block/blk-mq-debugfs.h
+++ b/block/blk-mq-debugfs.h
@@ -11,6 +11,8 @@ struct blk_mq_debugfs_attr {
const struct seq_operations *seq_ops;
};
+int blk_mq_debugfs_rq_show(struct seq_file *m, void *v);
+
int blk_mq_debugfs_register(struct request_queue *q);
void blk_mq_debugfs_unregister(struct request_queue *q);
int blk_mq_debugfs_register_hctx(struct request_queue *q,
diff --git a/block/kyber-iosched.c b/block/kyber-iosched.c
index 3b0090bc5dd1..b9faabc75fdb 100644
--- a/block/kyber-iosched.c
+++ b/block/kyber-iosched.c
@@ -26,6 +26,7 @@
#include "blk.h"
#include "blk-mq.h"
+#include "blk-mq-debugfs.h"
#include "blk-mq-sched.h"
#include "blk-mq-tag.h"
#include "blk-stat.h"
@@ -683,6 +684,131 @@ static struct elv_fs_entry kyber_sched_attrs[] = {
};
#undef KYBER_LAT_ATTR
+#ifdef CONFIG_BLK_DEBUG_FS
+#define KYBER_DEBUGFS_DOMAIN_ATTRS(domain, name) \
+static int kyber_##name##_tokens_show(void *data, struct seq_file *m) \
+{ \
+ struct request_queue *q = data; \
+ struct kyber_queue_data *kqd = q->elevator->elevator_data; \
+ \
+ sbitmap_queue_show(&kqd->domain_tokens[domain], m); \
+ return 0; \
+} \
+ \
+static void *kyber_##name##_rqs_start(struct seq_file *m, loff_t *pos) \
+ __acquires(&khd->lock) \
+{ \
+ struct blk_mq_hw_ctx *hctx = m->private; \
+ struct kyber_hctx_data *khd = hctx->sched_data; \
+ \
+ spin_lock(&khd->lock); \
+ return seq_list_start(&khd->rqs[domain], *pos); \
+} \
+ \
+static void *kyber_##name##_rqs_next(struct seq_file *m, void *v, \
+ loff_t *pos) \
+{ \
+ struct blk_mq_hw_ctx *hctx = m->private; \
+ struct kyber_hctx_data *khd = hctx->sched_data; \
+ \
+ return seq_list_next(v, &khd->rqs[domain], pos); \
+} \
+ \
+static void kyber_##name##_rqs_stop(struct seq_file *m, void *v) \
+ __releases(&khd->lock) \
+{ \
+ struct blk_mq_hw_ctx *hctx = m->private; \
+ struct kyber_hctx_data *khd = hctx->sched_data; \
+ \
+ spin_unlock(&khd->lock); \
+} \
+ \
+static const struct seq_operations kyber_##name##_rqs_seq_ops = { \
+ .start = kyber_##name##_rqs_start, \
+ .next = kyber_##name##_rqs_next, \
+ .stop = kyber_##name##_rqs_stop, \
+ .show = blk_mq_debugfs_rq_show, \
+}; \
+ \
+static int kyber_##name##_waiting_show(void *data, struct seq_file *m) \
+{ \
+ struct blk_mq_hw_ctx *hctx = data; \
+ struct kyber_hctx_data *khd = hctx->sched_data; \
+ wait_queue_t *wait = &khd->domain_wait[domain]; \
+ \
+ seq_printf(m, "%d\n", !list_empty_careful(&wait->task_list)); \
+ return 0; \
+}
+KYBER_DEBUGFS_DOMAIN_ATTRS(KYBER_READ, read)
+KYBER_DEBUGFS_DOMAIN_ATTRS(KYBER_SYNC_WRITE, sync_write)
+KYBER_DEBUGFS_DOMAIN_ATTRS(KYBER_OTHER, other)
+#undef KYBER_DEBUGFS_DOMAIN_ATTRS
+
+static int kyber_async_depth_show(void *data, struct seq_file *m)
+{
+ struct request_queue *q = data;
+ struct kyber_queue_data *kqd = q->elevator->elevator_data;
+
+ seq_printf(m, "%u\n", kqd->async_depth);
+ return 0;
+}
+
+static int kyber_cur_domain_show(void *data, struct seq_file *m)
+{
+ struct blk_mq_hw_ctx *hctx = data;
+ struct kyber_hctx_data *khd = hctx->sched_data;
+
+ switch (khd->cur_domain) {
+ case KYBER_READ:
+ seq_puts(m, "READ\n");
+ break;
+ case KYBER_SYNC_WRITE:
+ seq_puts(m, "SYNC_WRITE\n");
+ break;
+ case KYBER_OTHER:
+ seq_puts(m, "OTHER\n");
+ break;
+ default:
+ seq_printf(m, "%u\n", khd->cur_domain);
+ break;
+ }
+ return 0;
+}
+
+static int kyber_batching_show(void *data, struct seq_file *m)
+{
+ struct blk_mq_hw_ctx *hctx = data;
+ struct kyber_hctx_data *khd = hctx->sched_data;
+
+ seq_printf(m, "%u\n", khd->batching);
+ return 0;
+}
+
+#define KYBER_QUEUE_DOMAIN_ATTRS(name) \
+ {#name "_tokens", 0400, kyber_##name##_tokens_show}
+static const struct blk_mq_debugfs_attr kyber_queue_debugfs_attrs[] = {
+ KYBER_QUEUE_DOMAIN_ATTRS(read),
+ KYBER_QUEUE_DOMAIN_ATTRS(sync_write),
+ KYBER_QUEUE_DOMAIN_ATTRS(other),
+ {"async_depth", 0400, kyber_async_depth_show},
+ {},
+};
+#undef KYBER_QUEUE_DOMAIN_ATTRS
+
+#define KYBER_HCTX_DOMAIN_ATTRS(name) \
+ {#name "_rqs", 0400, .seq_ops = &kyber_##name##_rqs_seq_ops}, \
+ {#name "_waiting", 0400, kyber_##name##_waiting_show}
+static const struct blk_mq_debugfs_attr kyber_hctx_debugfs_attrs[] = {
+ KYBER_HCTX_DOMAIN_ATTRS(read),
+ KYBER_HCTX_DOMAIN_ATTRS(sync_write),
+ KYBER_HCTX_DOMAIN_ATTRS(other),
+ {"cur_domain", 0400, kyber_cur_domain_show},
+ {"batching", 0400, kyber_batching_show},
+ {},
+};
+#undef KYBER_HCTX_DOMAIN_ATTRS
+#endif
+
static struct elevator_type kyber_sched = {
.ops.mq = {
.init_sched = kyber_init_sched,
@@ -696,6 +822,10 @@ static struct elevator_type kyber_sched = {
.has_work = kyber_has_work,
},
.uses_mq = true,
+#ifdef CONFIG_BLK_DEBUG_FS
+ .queue_debugfs_attrs = kyber_queue_debugfs_attrs,
+ .hctx_debugfs_attrs = kyber_hctx_debugfs_attrs,
+#endif
.elevator_attrs = kyber_sched_attrs,
.elevator_name = "kyber",
.elevator_owner = THIS_MODULE,
--
2.12.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 9/9] mq-deadline: add debugfs attributes
2017-05-03 19:18 [PATCH 0/9] blk-mq-debugfs: scheduler support and cleanups Omar Sandoval
` (7 preceding siblings ...)
2017-05-03 19:19 ` [PATCH 8/9] kyber: add " Omar Sandoval
@ 2017-05-03 19:19 ` Omar Sandoval
2017-05-03 19:57 ` [PATCH 10/9] blk-mq-debugfs: rename hw queue directories from <n> to hctx<n> Omar Sandoval
9 siblings, 0 replies; 13+ messages in thread
From: Omar Sandoval @ 2017-05-03 19:19 UTC (permalink / raw)
To: Jens Axboe, linux-block; +Cc: Bart Van Assche, kernel-team
From: Omar Sandoval <osandov@fb.com>
Expose the fifo lists, cached next requests, batching state, and
dispatch list. It'd also be possible to add the sorted lists, but there
aren't already seq_file helpers for rbtrees.
Signed-off-by: Omar Sandoval <osandov@fb.com>
---
block/blk-mq-debugfs.c | 8 +++-
block/blk-mq-debugfs.h | 1 +
block/mq-deadline.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 130 insertions(+), 2 deletions(-)
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 6c12b4dbc8ec..3a33f7e2f68c 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -262,9 +262,8 @@ static const char *const rqf_name[] = {
};
#undef RQF_NAME
-int blk_mq_debugfs_rq_show(struct seq_file *m, void *v)
+int __blk_mq_debugfs_rq_show(struct seq_file *m, struct request *rq)
{
- struct request *rq = list_entry_rq(v);
const struct blk_mq_ops *const mq_ops = rq->q->mq_ops;
const unsigned int op = rq->cmd_flags & REQ_OP_MASK;
@@ -287,6 +286,11 @@ int blk_mq_debugfs_rq_show(struct seq_file *m, void *v)
return 0;
}
+int blk_mq_debugfs_rq_show(struct seq_file *m, void *v)
+{
+ return __blk_mq_debugfs_rq_show(m, list_entry_rq(v));
+}
+
static void *hctx_dispatch_start(struct seq_file *m, loff_t *pos)
__acquires(&hctx->lock)
{
diff --git a/block/blk-mq-debugfs.h b/block/blk-mq-debugfs.h
index 7c67f813a294..b72e5c5f065e 100644
--- a/block/blk-mq-debugfs.h
+++ b/block/blk-mq-debugfs.h
@@ -11,6 +11,7 @@ struct blk_mq_debugfs_attr {
const struct seq_operations *seq_ops;
};
+int __blk_mq_debugfs_rq_show(struct seq_file *m, struct request *rq);
int blk_mq_debugfs_rq_show(struct seq_file *m, void *v);
int blk_mq_debugfs_register(struct request_queue *q);
diff --git a/block/mq-deadline.c b/block/mq-deadline.c
index 236121633ca0..1b964a387afe 100644
--- a/block/mq-deadline.c
+++ b/block/mq-deadline.c
@@ -19,6 +19,7 @@
#include "blk.h"
#include "blk-mq.h"
+#include "blk-mq-debugfs.h"
#include "blk-mq-tag.h"
#include "blk-mq-sched.h"
@@ -517,6 +518,125 @@ static struct elv_fs_entry deadline_attrs[] = {
__ATTR_NULL
};
+#ifdef CONFIG_BLK_DEBUG_FS
+#define DEADLINE_DEBUGFS_DDIR_ATTRS(ddir, name) \
+static void *deadline_##name##_fifo_start(struct seq_file *m, \
+ loff_t *pos) \
+ __acquires(&dd->lock) \
+{ \
+ struct request_queue *q = m->private; \
+ struct deadline_data *dd = q->elevator->elevator_data; \
+ \
+ spin_lock(&dd->lock); \
+ return seq_list_start(&dd->fifo_list[ddir], *pos); \
+} \
+ \
+static void *deadline_##name##_fifo_next(struct seq_file *m, void *v, \
+ loff_t *pos) \
+{ \
+ struct request_queue *q = m->private; \
+ struct deadline_data *dd = q->elevator->elevator_data; \
+ \
+ return seq_list_next(v, &dd->fifo_list[ddir], pos); \
+} \
+ \
+static void deadline_##name##_fifo_stop(struct seq_file *m, void *v) \
+ __releases(&dd->lock) \
+{ \
+ struct request_queue *q = m->private; \
+ struct deadline_data *dd = q->elevator->elevator_data; \
+ \
+ spin_unlock(&dd->lock); \
+} \
+ \
+static const struct seq_operations deadline_##name##_fifo_seq_ops = { \
+ .start = deadline_##name##_fifo_start, \
+ .next = deadline_##name##_fifo_next, \
+ .stop = deadline_##name##_fifo_stop, \
+ .show = blk_mq_debugfs_rq_show, \
+}; \
+ \
+static int deadline_##name##_next_rq_show(void *data, \
+ struct seq_file *m) \
+{ \
+ struct request_queue *q = data; \
+ struct deadline_data *dd = q->elevator->elevator_data; \
+ struct request *rq = dd->next_rq[ddir]; \
+ \
+ if (rq) \
+ __blk_mq_debugfs_rq_show(m, rq); \
+ return 0; \
+}
+DEADLINE_DEBUGFS_DDIR_ATTRS(READ, read)
+DEADLINE_DEBUGFS_DDIR_ATTRS(WRITE, write)
+#undef DEADLINE_DEBUGFS_DDIR_ATTRS
+
+static int deadline_batching_show(void *data, struct seq_file *m)
+{
+ struct request_queue *q = data;
+ struct deadline_data *dd = q->elevator->elevator_data;
+
+ seq_printf(m, "%u\n", dd->batching);
+ return 0;
+}
+
+static int deadline_starved_show(void *data, struct seq_file *m)
+{
+ struct request_queue *q = data;
+ struct deadline_data *dd = q->elevator->elevator_data;
+
+ seq_printf(m, "%u\n", dd->starved);
+ return 0;
+}
+
+static void *deadline_dispatch_start(struct seq_file *m, loff_t *pos)
+ __acquires(&dd->lock)
+{
+ struct request_queue *q = m->private;
+ struct deadline_data *dd = q->elevator->elevator_data;
+
+ spin_lock(&dd->lock);
+ return seq_list_start(&dd->dispatch, *pos);
+}
+
+static void *deadline_dispatch_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ struct request_queue *q = m->private;
+ struct deadline_data *dd = q->elevator->elevator_data;
+
+ return seq_list_next(v, &dd->dispatch, pos);
+}
+
+static void deadline_dispatch_stop(struct seq_file *m, void *v)
+ __releases(&dd->lock)
+{
+ struct request_queue *q = m->private;
+ struct deadline_data *dd = q->elevator->elevator_data;
+
+ spin_unlock(&dd->lock);
+}
+
+static const struct seq_operations deadline_dispatch_seq_ops = {
+ .start = deadline_dispatch_start,
+ .next = deadline_dispatch_next,
+ .stop = deadline_dispatch_stop,
+ .show = blk_mq_debugfs_rq_show,
+};
+
+#define DEADLINE_QUEUE_DDIR_ATTRS(name) \
+ {#name "_fifo_list", 0400, .seq_ops = &deadline_##name##_fifo_seq_ops}, \
+ {#name "_next_rq", 0400, deadline_##name##_next_rq_show}
+static const struct blk_mq_debugfs_attr deadline_queue_debugfs_attrs[] = {
+ DEADLINE_QUEUE_DDIR_ATTRS(read),
+ DEADLINE_QUEUE_DDIR_ATTRS(write),
+ {"batching", 0400, deadline_batching_show},
+ {"starved", 0400, deadline_starved_show},
+ {"dispatch", 0400, .seq_ops = &deadline_dispatch_seq_ops},
+ {},
+};
+#undef DEADLINE_QUEUE_DDIR_ATTRS
+#endif
+
static struct elevator_type mq_deadline = {
.ops.mq = {
.insert_requests = dd_insert_requests,
@@ -533,6 +653,9 @@ static struct elevator_type mq_deadline = {
},
.uses_mq = true,
+#ifdef CONFIG_BLK_DEBUG_FS
+ .queue_debugfs_attrs = deadline_queue_debugfs_attrs,
+#endif
.elevator_attrs = deadline_attrs,
.elevator_name = "mq-deadline",
.elevator_owner = THIS_MODULE,
--
2.12.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 10/9] blk-mq-debugfs: rename hw queue directories from <n> to hctx<n>
2017-05-03 19:18 [PATCH 0/9] blk-mq-debugfs: scheduler support and cleanups Omar Sandoval
` (8 preceding siblings ...)
2017-05-03 19:19 ` [PATCH 9/9] mq-deadline: " Omar Sandoval
@ 2017-05-03 19:57 ` Omar Sandoval
9 siblings, 0 replies; 13+ messages in thread
From: Omar Sandoval @ 2017-05-03 19:57 UTC (permalink / raw)
To: Jens Axboe, linux-block; +Cc: Bart Van Assche, kernel-team
From: Omar Sandoval <osandov@fb.com>
Since we got rid of the intermediate "mq" directory, it's not completely
clear what these numbered directories represent. Rename them.
Signed-off-by: Omar Sandoval <osandov@fb.com>
---
One more bonus change.
block/blk-mq-debugfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 3a33f7e2f68c..115d73d99bb3 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -761,7 +761,7 @@ int blk_mq_debugfs_register_hctx(struct request_queue *q,
if (!q->debugfs_dir)
return -ENOENT;
- snprintf(name, sizeof(name), "%u", hctx->queue_num);
+ snprintf(name, sizeof(name), "hctx%u", hctx->queue_num);
hctx->debugfs_dir = debugfs_create_dir(name, q->debugfs_dir);
if (!hctx->debugfs_dir)
return -ENOMEM;
--
2.12.2
^ permalink raw reply related [flat|nested] 13+ messages in thread