Skip to content

Commit

Permalink
blk-mq-debugfs: allow schedulers to register debugfs attributes
Browse files Browse the repository at this point in the history
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>
Reviewed-by: Hannes Reinecke <hare@suse.com>

Add missing seq_file.h header in blk-mq-debugfs.h

Signed-off-by: Jens Axboe <axboe@fb.com>
  • Loading branch information
Omar Sandoval authored and Jens Axboe committed May 4, 2017
1 parent 9c1051a commit d332ce0
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 17 deletions.
74 changes: 65 additions & 9 deletions block/blk-mq-debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -725,6 +716,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;
Expand All @@ -737,6 +731,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;
}

Expand Down Expand Up @@ -791,6 +786,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;
}

Expand All @@ -815,3 +811,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;
}
37 changes: 37 additions & 0 deletions block/blk-mq-debugfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,31 @@
#define INT_BLK_MQ_DEBUGFS_H

#ifdef CONFIG_BLK_DEBUG_FS

#include <linux/seq_file.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;
};

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,
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);

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)
{
Expand Down Expand Up @@ -37,6 +55,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
24 changes: 16 additions & 8 deletions block/blk-mq-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -472,6 +473,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;
}

Expand All @@ -483,6 +486,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;
Expand Down Expand Up @@ -519,8 +524,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;
Expand All @@ -529,6 +536,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;
Expand All @@ -544,14 +552,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);
Expand Down
1 change: 1 addition & 0 deletions include/linux/blk-mq.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ struct blk_mq_hw_ctx {

#ifdef CONFIG_BLK_DEBUG_FS
struct dentry *debugfs_dir;
struct dentry *sched_debugfs_dir;
#endif
};

Expand Down
1 change: 1 addition & 0 deletions include/linux/blkdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions include/linux/elevator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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" */
Expand Down

0 comments on commit d332ce0

Please sign in to comment.