]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - block/blk-mq-debugfs.c
blk-mq: create debugfs directory tree
[mirror_ubuntu-bionic-kernel.git] / block / blk-mq-debugfs.c
CommitLineData
07e4fead
OS
1/*
2 * Copyright (C) 2017 Facebook
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <https://www.gnu.org/licenses/>.
15 */
16
17#include <linux/kernel.h>
18#include <linux/blkdev.h>
19#include <linux/debugfs.h>
20
21#include <linux/blk-mq.h>
22#include "blk-mq.h"
23
24struct blk_mq_debugfs_attr {
25 const char *name;
26 umode_t mode;
27 const struct file_operations *fops;
28};
29
30static struct dentry *block_debugfs_root;
31
32static const struct blk_mq_debugfs_attr blk_mq_debugfs_hctx_attrs[] = {
33};
34
35static const struct blk_mq_debugfs_attr blk_mq_debugfs_ctx_attrs[] = {
36};
37
38int blk_mq_debugfs_register(struct request_queue *q, const char *name)
39{
40 if (!block_debugfs_root)
41 return -ENOENT;
42
43 q->debugfs_dir = debugfs_create_dir(name, block_debugfs_root);
44 if (!q->debugfs_dir)
45 goto err;
46
47 if (blk_mq_debugfs_register_hctxs(q))
48 goto err;
49
50 return 0;
51
52err:
53 blk_mq_debugfs_unregister(q);
54 return -ENOMEM;
55}
56
57void blk_mq_debugfs_unregister(struct request_queue *q)
58{
59 debugfs_remove_recursive(q->debugfs_dir);
60 q->mq_debugfs_dir = NULL;
61 q->debugfs_dir = NULL;
62}
63
64static int blk_mq_debugfs_register_ctx(struct request_queue *q,
65 struct blk_mq_ctx *ctx,
66 struct dentry *hctx_dir)
67{
68 struct dentry *ctx_dir;
69 char name[20];
70 int i;
71
72 snprintf(name, sizeof(name), "cpu%u", ctx->cpu);
73 ctx_dir = debugfs_create_dir(name, hctx_dir);
74 if (!ctx_dir)
75 return -ENOMEM;
76
77 for (i = 0; i < ARRAY_SIZE(blk_mq_debugfs_ctx_attrs); i++) {
78 const struct blk_mq_debugfs_attr *attr;
79
80 attr = &blk_mq_debugfs_ctx_attrs[i];
81 if (!debugfs_create_file(attr->name, attr->mode, ctx_dir, ctx,
82 attr->fops))
83 return -ENOMEM;
84 }
85
86 return 0;
87}
88
89static int blk_mq_debugfs_register_hctx(struct request_queue *q,
90 struct blk_mq_hw_ctx *hctx)
91{
92 struct blk_mq_ctx *ctx;
93 struct dentry *hctx_dir;
94 char name[20];
95 int i;
96
97 snprintf(name, sizeof(name), "%u", hctx->queue_num);
98 hctx_dir = debugfs_create_dir(name, q->mq_debugfs_dir);
99 if (!hctx_dir)
100 return -ENOMEM;
101
102 for (i = 0; i < ARRAY_SIZE(blk_mq_debugfs_hctx_attrs); i++) {
103 const struct blk_mq_debugfs_attr *attr;
104
105 attr = &blk_mq_debugfs_hctx_attrs[i];
106 if (!debugfs_create_file(attr->name, attr->mode, hctx_dir, hctx,
107 attr->fops))
108 return -ENOMEM;
109 }
110
111 hctx_for_each_ctx(hctx, ctx, i) {
112 if (blk_mq_debugfs_register_ctx(q, ctx, hctx_dir))
113 return -ENOMEM;
114 }
115
116 return 0;
117}
118
119int blk_mq_debugfs_register_hctxs(struct request_queue *q)
120{
121 struct blk_mq_hw_ctx *hctx;
122 int i;
123
124 if (!q->debugfs_dir)
125 return -ENOENT;
126
127 q->mq_debugfs_dir = debugfs_create_dir("mq", q->debugfs_dir);
128 if (!q->mq_debugfs_dir)
129 goto err;
130
131 queue_for_each_hw_ctx(q, hctx, i) {
132 if (blk_mq_debugfs_register_hctx(q, hctx))
133 goto err;
134 }
135
136 return 0;
137
138err:
139 blk_mq_debugfs_unregister_hctxs(q);
140 return -ENOMEM;
141}
142
143void blk_mq_debugfs_unregister_hctxs(struct request_queue *q)
144{
145 debugfs_remove_recursive(q->mq_debugfs_dir);
146 q->mq_debugfs_dir = NULL;
147}
148
149void blk_mq_debugfs_init(void)
150{
151 block_debugfs_root = debugfs_create_dir("block", NULL);
152}