summaryrefslogtreecommitdiff
path: root/block/blk-mq-debugfs.c
diff options
context:
space:
mode:
authorOmar Sandoval <osandov@fb.com>2017-05-04 08:17:21 -0600
committerJens Axboe <axboe@fb.com>2017-05-04 08:24:13 -0600
commit9c1051aacde828073dbbab5e8e59c0fc802efa9a (patch)
treec0e06f43aaf1c1fa908ebe2f196d24a0f42992f5 /block/blk-mq-debugfs.c
parentd173a25165c124442182f6b21d0c2ec381a0eebe (diff)
blk-mq: untangle debugfs and sysfs
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 <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block/blk-mq-debugfs.c')
-rw-r--r--block/blk-mq-debugfs.c110
1 files changed, 62 insertions, 48 deletions
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 1dc1847b5363..260cf76e0705 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -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:
@@ -710,32 +737,17 @@ err:
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;
@@ -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);
}