Skip to content

Commit

Permalink
blk-mq: untangle debugfs and sysfs
Browse files Browse the repository at this point in the history
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/hctx0/tags is now
just nvme0n1/hctx0/tags.

Signed-off-by: Omar Sandoval <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
osandov authored and axboe committed May 4, 2017
1 parent d173a25 commit 9c1051a
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 71 deletions.
9 changes: 2 additions & 7 deletions block/blk-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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);

Expand Down
110 changes: 62 additions & 48 deletions block/blk-mq-debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -687,19 +687,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:
Expand All @@ -710,32 +737,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;

Expand All @@ -745,59 +757,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), "hctx%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);
}
21 changes: 17 additions & 4 deletions block/blk-mq-debugfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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
Expand Down
11 changes: 0 additions & 11 deletions block/blk-mq-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand Down Expand Up @@ -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);

Expand All @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions block/blk-mq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1862,6 +1863,8 @@ static void blk_mq_exit_hctx(struct request_queue *q,
struct blk_mq_tag_set *set,
struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx)
{
blk_mq_debugfs_unregister_hctx(hctx);

blk_mq_tag_idle(hctx);

if (set->ops->exit_request)
Expand Down Expand Up @@ -1948,6 +1951,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:
Expand Down Expand Up @@ -2385,6 +2390,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);

/*
Expand All @@ -2396,6 +2402,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);
}

/*
Expand Down
2 changes: 2 additions & 0 deletions block/blk-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions include/linux/blk-mq.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
1 change: 0 additions & 1 deletion include/linux/blkdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 9c1051a

Please sign in to comment.