2 * Copyright (C) 2017 Facebook
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.
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.
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/>.
17 #include <linux/kernel.h>
18 #include <linux/blkdev.h>
19 #include <linux/debugfs.h>
21 #include <linux/blk-mq.h>
23 #include "blk-mq-tag.h"
25 struct blk_mq_debugfs_attr
{
28 const struct file_operations
*fops
;
31 static struct dentry
*block_debugfs_root
;
33 static int blk_mq_debugfs_seq_open(struct inode
*inode
, struct file
*file
,
34 const struct seq_operations
*ops
)
39 ret
= seq_open(file
, ops
);
41 m
= file
->private_data
;
42 m
->private = inode
->i_private
;
47 static int hctx_state_show(struct seq_file
*m
, void *v
)
49 struct blk_mq_hw_ctx
*hctx
= m
->private;
51 seq_printf(m
, "0x%lx\n", hctx
->state
);
55 static int hctx_state_open(struct inode
*inode
, struct file
*file
)
57 return single_open(file
, hctx_state_show
, inode
->i_private
);
60 static const struct file_operations hctx_state_fops
= {
61 .open
= hctx_state_open
,
64 .release
= single_release
,
67 static int hctx_flags_show(struct seq_file
*m
, void *v
)
69 struct blk_mq_hw_ctx
*hctx
= m
->private;
71 seq_printf(m
, "0x%lx\n", hctx
->flags
);
75 static int hctx_flags_open(struct inode
*inode
, struct file
*file
)
77 return single_open(file
, hctx_flags_show
, inode
->i_private
);
80 static const struct file_operations hctx_flags_fops
= {
81 .open
= hctx_flags_open
,
84 .release
= single_release
,
87 static int blk_mq_debugfs_rq_show(struct seq_file
*m
, void *v
)
89 struct request
*rq
= list_entry_rq(v
);
91 seq_printf(m
, "%p {.cmd_type=%u, .cmd_flags=0x%x, .rq_flags=0x%x, .tag=%d, .internal_tag=%d}\n",
92 rq
, rq
->cmd_type
, rq
->cmd_flags
, (unsigned int)rq
->rq_flags
,
93 rq
->tag
, rq
->internal_tag
);
97 static void *hctx_dispatch_start(struct seq_file
*m
, loff_t
*pos
)
99 struct blk_mq_hw_ctx
*hctx
= m
->private;
101 spin_lock(&hctx
->lock
);
102 return seq_list_start(&hctx
->dispatch
, *pos
);
105 static void *hctx_dispatch_next(struct seq_file
*m
, void *v
, loff_t
*pos
)
107 struct blk_mq_hw_ctx
*hctx
= m
->private;
109 return seq_list_next(v
, &hctx
->dispatch
, pos
);
112 static void hctx_dispatch_stop(struct seq_file
*m
, void *v
)
114 struct blk_mq_hw_ctx
*hctx
= m
->private;
116 spin_unlock(&hctx
->lock
);
119 static const struct seq_operations hctx_dispatch_seq_ops
= {
120 .start
= hctx_dispatch_start
,
121 .next
= hctx_dispatch_next
,
122 .stop
= hctx_dispatch_stop
,
123 .show
= blk_mq_debugfs_rq_show
,
126 static int hctx_dispatch_open(struct inode
*inode
, struct file
*file
)
128 return blk_mq_debugfs_seq_open(inode
, file
, &hctx_dispatch_seq_ops
);
131 static const struct file_operations hctx_dispatch_fops
= {
132 .open
= hctx_dispatch_open
,
135 .release
= seq_release
,
138 static int hctx_ctx_map_show(struct seq_file
*m
, void *v
)
140 struct blk_mq_hw_ctx
*hctx
= m
->private;
142 sbitmap_bitmap_show(&hctx
->ctx_map
, m
);
146 static int hctx_ctx_map_open(struct inode
*inode
, struct file
*file
)
148 return single_open(file
, hctx_ctx_map_show
, inode
->i_private
);
151 static const struct file_operations hctx_ctx_map_fops
= {
152 .open
= hctx_ctx_map_open
,
155 .release
= single_release
,
158 static void blk_mq_debugfs_tags_show(struct seq_file
*m
,
159 struct blk_mq_tags
*tags
)
161 seq_printf(m
, "nr_tags=%u\n", tags
->nr_tags
);
162 seq_printf(m
, "nr_reserved_tags=%u\n", tags
->nr_reserved_tags
);
163 seq_printf(m
, "active_queues=%d\n",
164 atomic_read(&tags
->active_queues
));
166 seq_puts(m
, "\nbitmap_tags:\n");
167 sbitmap_queue_show(&tags
->bitmap_tags
, m
);
169 if (tags
->nr_reserved_tags
) {
170 seq_puts(m
, "\nbreserved_tags:\n");
171 sbitmap_queue_show(&tags
->breserved_tags
, m
);
175 static int hctx_tags_show(struct seq_file
*m
, void *v
)
177 struct blk_mq_hw_ctx
*hctx
= m
->private;
178 struct request_queue
*q
= hctx
->queue
;
180 mutex_lock(&q
->sysfs_lock
);
182 blk_mq_debugfs_tags_show(m
, hctx
->tags
);
183 mutex_unlock(&q
->sysfs_lock
);
188 static int hctx_tags_open(struct inode
*inode
, struct file
*file
)
190 return single_open(file
, hctx_tags_show
, inode
->i_private
);
193 static const struct file_operations hctx_tags_fops
= {
194 .open
= hctx_tags_open
,
197 .release
= single_release
,
200 static int hctx_tags_bitmap_show(struct seq_file
*m
, void *v
)
202 struct blk_mq_hw_ctx
*hctx
= m
->private;
203 struct request_queue
*q
= hctx
->queue
;
205 mutex_lock(&q
->sysfs_lock
);
207 sbitmap_bitmap_show(&hctx
->tags
->bitmap_tags
.sb
, m
);
208 mutex_unlock(&q
->sysfs_lock
);
212 static int hctx_tags_bitmap_open(struct inode
*inode
, struct file
*file
)
214 return single_open(file
, hctx_tags_bitmap_show
, inode
->i_private
);
217 static const struct file_operations hctx_tags_bitmap_fops
= {
218 .open
= hctx_tags_bitmap_open
,
221 .release
= single_release
,
224 static int hctx_sched_tags_show(struct seq_file
*m
, void *v
)
226 struct blk_mq_hw_ctx
*hctx
= m
->private;
227 struct request_queue
*q
= hctx
->queue
;
229 mutex_lock(&q
->sysfs_lock
);
230 if (hctx
->sched_tags
)
231 blk_mq_debugfs_tags_show(m
, hctx
->sched_tags
);
232 mutex_unlock(&q
->sysfs_lock
);
237 static int hctx_sched_tags_open(struct inode
*inode
, struct file
*file
)
239 return single_open(file
, hctx_sched_tags_show
, inode
->i_private
);
242 static const struct file_operations hctx_sched_tags_fops
= {
243 .open
= hctx_sched_tags_open
,
246 .release
= single_release
,
249 static int hctx_sched_tags_bitmap_show(struct seq_file
*m
, void *v
)
251 struct blk_mq_hw_ctx
*hctx
= m
->private;
252 struct request_queue
*q
= hctx
->queue
;
254 mutex_lock(&q
->sysfs_lock
);
255 if (hctx
->sched_tags
)
256 sbitmap_bitmap_show(&hctx
->sched_tags
->bitmap_tags
.sb
, m
);
257 mutex_unlock(&q
->sysfs_lock
);
261 static int hctx_sched_tags_bitmap_open(struct inode
*inode
, struct file
*file
)
263 return single_open(file
, hctx_sched_tags_bitmap_show
, inode
->i_private
);
266 static const struct file_operations hctx_sched_tags_bitmap_fops
= {
267 .open
= hctx_sched_tags_bitmap_open
,
270 .release
= single_release
,
273 static int hctx_io_poll_show(struct seq_file
*m
, void *v
)
275 struct blk_mq_hw_ctx
*hctx
= m
->private;
277 seq_printf(m
, "considered=%lu\n", hctx
->poll_considered
);
278 seq_printf(m
, "invoked=%lu\n", hctx
->poll_invoked
);
279 seq_printf(m
, "success=%lu\n", hctx
->poll_success
);
283 static int hctx_io_poll_open(struct inode
*inode
, struct file
*file
)
285 return single_open(file
, hctx_io_poll_show
, inode
->i_private
);
288 static ssize_t
hctx_io_poll_write(struct file
*file
, const char __user
*buf
,
289 size_t count
, loff_t
*ppos
)
291 struct seq_file
*m
= file
->private_data
;
292 struct blk_mq_hw_ctx
*hctx
= m
->private;
294 hctx
->poll_considered
= hctx
->poll_invoked
= hctx
->poll_success
= 0;
298 static const struct file_operations hctx_io_poll_fops
= {
299 .open
= hctx_io_poll_open
,
301 .write
= hctx_io_poll_write
,
303 .release
= single_release
,
306 static void print_stat(struct seq_file
*m
, struct blk_rq_stat
*stat
)
308 seq_printf(m
, "samples=%d, mean=%lld, min=%llu, max=%llu",
309 stat
->nr_samples
, stat
->mean
, stat
->min
, stat
->max
);
312 static int hctx_stats_show(struct seq_file
*m
, void *v
)
314 struct blk_mq_hw_ctx
*hctx
= m
->private;
315 struct blk_rq_stat stat
[2];
317 blk_stat_init(&stat
[BLK_STAT_READ
]);
318 blk_stat_init(&stat
[BLK_STAT_WRITE
]);
320 blk_hctx_stat_get(hctx
, stat
);
322 seq_puts(m
, "read: ");
323 print_stat(m
, &stat
[BLK_STAT_READ
]);
326 seq_puts(m
, "write: ");
327 print_stat(m
, &stat
[BLK_STAT_WRITE
]);
332 static int hctx_stats_open(struct inode
*inode
, struct file
*file
)
334 return single_open(file
, hctx_stats_show
, inode
->i_private
);
337 static ssize_t
hctx_stats_write(struct file
*file
, const char __user
*buf
,
338 size_t count
, loff_t
*ppos
)
340 struct seq_file
*m
= file
->private_data
;
341 struct blk_mq_hw_ctx
*hctx
= m
->private;
342 struct blk_mq_ctx
*ctx
;
345 hctx_for_each_ctx(hctx
, ctx
, i
) {
346 blk_stat_init(&ctx
->stat
[BLK_STAT_READ
]);
347 blk_stat_init(&ctx
->stat
[BLK_STAT_WRITE
]);
352 static const struct file_operations hctx_stats_fops
= {
353 .open
= hctx_stats_open
,
355 .write
= hctx_stats_write
,
357 .release
= single_release
,
360 static int hctx_dispatched_show(struct seq_file
*m
, void *v
)
362 struct blk_mq_hw_ctx
*hctx
= m
->private;
365 seq_printf(m
, "%8u\t%lu\n", 0U, hctx
->dispatched
[0]);
367 for (i
= 1; i
< BLK_MQ_MAX_DISPATCH_ORDER
- 1; i
++) {
368 unsigned int d
= 1U << (i
- 1);
370 seq_printf(m
, "%8u\t%lu\n", d
, hctx
->dispatched
[i
]);
373 seq_printf(m
, "%8u+\t%lu\n", 1U << (i
- 1), hctx
->dispatched
[i
]);
377 static int hctx_dispatched_open(struct inode
*inode
, struct file
*file
)
379 return single_open(file
, hctx_dispatched_show
, inode
->i_private
);
382 static ssize_t
hctx_dispatched_write(struct file
*file
, const char __user
*buf
,
383 size_t count
, loff_t
*ppos
)
385 struct seq_file
*m
= file
->private_data
;
386 struct blk_mq_hw_ctx
*hctx
= m
->private;
389 for (i
= 0; i
< BLK_MQ_MAX_DISPATCH_ORDER
; i
++)
390 hctx
->dispatched
[i
] = 0;
394 static const struct file_operations hctx_dispatched_fops
= {
395 .open
= hctx_dispatched_open
,
397 .write
= hctx_dispatched_write
,
399 .release
= single_release
,
402 static void *ctx_rq_list_start(struct seq_file
*m
, loff_t
*pos
)
404 struct blk_mq_ctx
*ctx
= m
->private;
406 spin_lock(&ctx
->lock
);
407 return seq_list_start(&ctx
->rq_list
, *pos
);
410 static void *ctx_rq_list_next(struct seq_file
*m
, void *v
, loff_t
*pos
)
412 struct blk_mq_ctx
*ctx
= m
->private;
414 return seq_list_next(v
, &ctx
->rq_list
, pos
);
417 static void ctx_rq_list_stop(struct seq_file
*m
, void *v
)
419 struct blk_mq_ctx
*ctx
= m
->private;
421 spin_unlock(&ctx
->lock
);
424 static const struct seq_operations ctx_rq_list_seq_ops
= {
425 .start
= ctx_rq_list_start
,
426 .next
= ctx_rq_list_next
,
427 .stop
= ctx_rq_list_stop
,
428 .show
= blk_mq_debugfs_rq_show
,
431 static int ctx_rq_list_open(struct inode
*inode
, struct file
*file
)
433 return blk_mq_debugfs_seq_open(inode
, file
, &ctx_rq_list_seq_ops
);
436 static const struct file_operations ctx_rq_list_fops
= {
437 .open
= ctx_rq_list_open
,
440 .release
= seq_release
,
443 static const struct blk_mq_debugfs_attr blk_mq_debugfs_hctx_attrs
[] = {
444 {"state", 0400, &hctx_state_fops
},
445 {"flags", 0400, &hctx_flags_fops
},
446 {"dispatch", 0400, &hctx_dispatch_fops
},
447 {"ctx_map", 0400, &hctx_ctx_map_fops
},
448 {"tags", 0400, &hctx_tags_fops
},
449 {"tags_bitmap", 0400, &hctx_tags_bitmap_fops
},
450 {"sched_tags", 0400, &hctx_sched_tags_fops
},
451 {"sched_tags_bitmap", 0400, &hctx_sched_tags_bitmap_fops
},
452 {"io_poll", 0600, &hctx_io_poll_fops
},
453 {"stats", 0600, &hctx_stats_fops
},
454 {"dispatched", 0600, &hctx_dispatched_fops
},
457 static const struct blk_mq_debugfs_attr blk_mq_debugfs_ctx_attrs
[] = {
458 {"rq_list", 0400, &ctx_rq_list_fops
},
461 int blk_mq_debugfs_register(struct request_queue
*q
, const char *name
)
463 if (!block_debugfs_root
)
466 q
->debugfs_dir
= debugfs_create_dir(name
, block_debugfs_root
);
470 if (blk_mq_debugfs_register_hctxs(q
))
476 blk_mq_debugfs_unregister(q
);
480 void blk_mq_debugfs_unregister(struct request_queue
*q
)
482 debugfs_remove_recursive(q
->debugfs_dir
);
483 q
->mq_debugfs_dir
= NULL
;
484 q
->debugfs_dir
= NULL
;
487 static int blk_mq_debugfs_register_ctx(struct request_queue
*q
,
488 struct blk_mq_ctx
*ctx
,
489 struct dentry
*hctx_dir
)
491 struct dentry
*ctx_dir
;
495 snprintf(name
, sizeof(name
), "cpu%u", ctx
->cpu
);
496 ctx_dir
= debugfs_create_dir(name
, hctx_dir
);
500 for (i
= 0; i
< ARRAY_SIZE(blk_mq_debugfs_ctx_attrs
); i
++) {
501 const struct blk_mq_debugfs_attr
*attr
;
503 attr
= &blk_mq_debugfs_ctx_attrs
[i
];
504 if (!debugfs_create_file(attr
->name
, attr
->mode
, ctx_dir
, ctx
,
512 static int blk_mq_debugfs_register_hctx(struct request_queue
*q
,
513 struct blk_mq_hw_ctx
*hctx
)
515 struct blk_mq_ctx
*ctx
;
516 struct dentry
*hctx_dir
;
520 snprintf(name
, sizeof(name
), "%u", hctx
->queue_num
);
521 hctx_dir
= debugfs_create_dir(name
, q
->mq_debugfs_dir
);
525 for (i
= 0; i
< ARRAY_SIZE(blk_mq_debugfs_hctx_attrs
); i
++) {
526 const struct blk_mq_debugfs_attr
*attr
;
528 attr
= &blk_mq_debugfs_hctx_attrs
[i
];
529 if (!debugfs_create_file(attr
->name
, attr
->mode
, hctx_dir
, hctx
,
534 hctx_for_each_ctx(hctx
, ctx
, i
) {
535 if (blk_mq_debugfs_register_ctx(q
, ctx
, hctx_dir
))
542 int blk_mq_debugfs_register_hctxs(struct request_queue
*q
)
544 struct blk_mq_hw_ctx
*hctx
;
550 q
->mq_debugfs_dir
= debugfs_create_dir("mq", q
->debugfs_dir
);
551 if (!q
->mq_debugfs_dir
)
554 queue_for_each_hw_ctx(q
, hctx
, i
) {
555 if (blk_mq_debugfs_register_hctx(q
, hctx
))
562 blk_mq_debugfs_unregister_hctxs(q
);
566 void blk_mq_debugfs_unregister_hctxs(struct request_queue
*q
)
568 debugfs_remove_recursive(q
->mq_debugfs_dir
);
569 q
->mq_debugfs_dir
= NULL
;
572 void blk_mq_debugfs_init(void)
574 block_debugfs_root
= debugfs_create_dir("block", NULL
);