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>
24 #include "blk-mq-tag.h"
26 struct blk_mq_debugfs_attr
{
29 const struct file_operations
*fops
;
32 static int blk_mq_debugfs_seq_open(struct inode
*inode
, struct file
*file
,
33 const struct seq_operations
*ops
)
38 ret
= seq_open(file
, ops
);
40 m
= file
->private_data
;
41 m
->private = inode
->i_private
;
46 static void print_stat(struct seq_file
*m
, struct blk_rq_stat
*stat
)
48 if (stat
->nr_samples
) {
49 seq_printf(m
, "samples=%d, mean=%lld, min=%llu, max=%llu",
50 stat
->nr_samples
, stat
->mean
, stat
->min
, stat
->max
);
52 seq_puts(m
, "samples=0");
56 static int queue_poll_stat_show(struct seq_file
*m
, void *v
)
58 struct request_queue
*q
= m
->private;
60 seq_puts(m
, "read: ");
61 print_stat(m
, &q
->poll_stat
[READ
]);
64 seq_puts(m
, "write: ");
65 print_stat(m
, &q
->poll_stat
[WRITE
]);
70 static int queue_poll_stat_open(struct inode
*inode
, struct file
*file
)
72 return single_open(file
, queue_poll_stat_show
, inode
->i_private
);
75 static const struct file_operations queue_poll_stat_fops
= {
76 .open
= queue_poll_stat_open
,
79 .release
= single_release
,
82 static int hctx_state_show(struct seq_file
*m
, void *v
)
84 struct blk_mq_hw_ctx
*hctx
= m
->private;
86 seq_printf(m
, "0x%lx\n", hctx
->state
);
90 static int hctx_state_open(struct inode
*inode
, struct file
*file
)
92 return single_open(file
, hctx_state_show
, inode
->i_private
);
95 static const struct file_operations hctx_state_fops
= {
96 .open
= hctx_state_open
,
99 .release
= single_release
,
102 static int hctx_flags_show(struct seq_file
*m
, void *v
)
104 struct blk_mq_hw_ctx
*hctx
= m
->private;
106 seq_printf(m
, "0x%lx\n", hctx
->flags
);
110 static int hctx_flags_open(struct inode
*inode
, struct file
*file
)
112 return single_open(file
, hctx_flags_show
, inode
->i_private
);
115 static const struct file_operations hctx_flags_fops
= {
116 .open
= hctx_flags_open
,
119 .release
= single_release
,
122 static int blk_mq_debugfs_rq_show(struct seq_file
*m
, void *v
)
124 struct request
*rq
= list_entry_rq(v
);
126 seq_printf(m
, "%p {.cmd_flags=0x%x, .rq_flags=0x%x, .tag=%d, .internal_tag=%d}\n",
127 rq
, rq
->cmd_flags
, (__force
unsigned int)rq
->rq_flags
,
128 rq
->tag
, rq
->internal_tag
);
132 static void *hctx_dispatch_start(struct seq_file
*m
, loff_t
*pos
)
133 __acquires(&hctx
->lock
)
135 struct blk_mq_hw_ctx
*hctx
= m
->private;
137 spin_lock(&hctx
->lock
);
138 return seq_list_start(&hctx
->dispatch
, *pos
);
141 static void *hctx_dispatch_next(struct seq_file
*m
, void *v
, loff_t
*pos
)
143 struct blk_mq_hw_ctx
*hctx
= m
->private;
145 return seq_list_next(v
, &hctx
->dispatch
, pos
);
148 static void hctx_dispatch_stop(struct seq_file
*m
, void *v
)
149 __releases(&hctx
->lock
)
151 struct blk_mq_hw_ctx
*hctx
= m
->private;
153 spin_unlock(&hctx
->lock
);
156 static const struct seq_operations hctx_dispatch_seq_ops
= {
157 .start
= hctx_dispatch_start
,
158 .next
= hctx_dispatch_next
,
159 .stop
= hctx_dispatch_stop
,
160 .show
= blk_mq_debugfs_rq_show
,
163 static int hctx_dispatch_open(struct inode
*inode
, struct file
*file
)
165 return blk_mq_debugfs_seq_open(inode
, file
, &hctx_dispatch_seq_ops
);
168 static const struct file_operations hctx_dispatch_fops
= {
169 .open
= hctx_dispatch_open
,
172 .release
= seq_release
,
175 static int hctx_ctx_map_show(struct seq_file
*m
, void *v
)
177 struct blk_mq_hw_ctx
*hctx
= m
->private;
179 sbitmap_bitmap_show(&hctx
->ctx_map
, m
);
183 static int hctx_ctx_map_open(struct inode
*inode
, struct file
*file
)
185 return single_open(file
, hctx_ctx_map_show
, inode
->i_private
);
188 static const struct file_operations hctx_ctx_map_fops
= {
189 .open
= hctx_ctx_map_open
,
192 .release
= single_release
,
195 static void blk_mq_debugfs_tags_show(struct seq_file
*m
,
196 struct blk_mq_tags
*tags
)
198 seq_printf(m
, "nr_tags=%u\n", tags
->nr_tags
);
199 seq_printf(m
, "nr_reserved_tags=%u\n", tags
->nr_reserved_tags
);
200 seq_printf(m
, "active_queues=%d\n",
201 atomic_read(&tags
->active_queues
));
203 seq_puts(m
, "\nbitmap_tags:\n");
204 sbitmap_queue_show(&tags
->bitmap_tags
, m
);
206 if (tags
->nr_reserved_tags
) {
207 seq_puts(m
, "\nbreserved_tags:\n");
208 sbitmap_queue_show(&tags
->breserved_tags
, m
);
212 static int hctx_tags_show(struct seq_file
*m
, void *v
)
214 struct blk_mq_hw_ctx
*hctx
= m
->private;
215 struct request_queue
*q
= hctx
->queue
;
218 res
= mutex_lock_interruptible(&q
->sysfs_lock
);
222 blk_mq_debugfs_tags_show(m
, hctx
->tags
);
223 mutex_unlock(&q
->sysfs_lock
);
229 static int hctx_tags_open(struct inode
*inode
, struct file
*file
)
231 return single_open(file
, hctx_tags_show
, inode
->i_private
);
234 static const struct file_operations hctx_tags_fops
= {
235 .open
= hctx_tags_open
,
238 .release
= single_release
,
241 static int hctx_tags_bitmap_show(struct seq_file
*m
, void *v
)
243 struct blk_mq_hw_ctx
*hctx
= m
->private;
244 struct request_queue
*q
= hctx
->queue
;
247 res
= mutex_lock_interruptible(&q
->sysfs_lock
);
251 sbitmap_bitmap_show(&hctx
->tags
->bitmap_tags
.sb
, m
);
252 mutex_unlock(&q
->sysfs_lock
);
258 static int hctx_tags_bitmap_open(struct inode
*inode
, struct file
*file
)
260 return single_open(file
, hctx_tags_bitmap_show
, inode
->i_private
);
263 static const struct file_operations hctx_tags_bitmap_fops
= {
264 .open
= hctx_tags_bitmap_open
,
267 .release
= single_release
,
270 static int hctx_sched_tags_show(struct seq_file
*m
, void *v
)
272 struct blk_mq_hw_ctx
*hctx
= m
->private;
273 struct request_queue
*q
= hctx
->queue
;
276 res
= mutex_lock_interruptible(&q
->sysfs_lock
);
279 if (hctx
->sched_tags
)
280 blk_mq_debugfs_tags_show(m
, hctx
->sched_tags
);
281 mutex_unlock(&q
->sysfs_lock
);
287 static int hctx_sched_tags_open(struct inode
*inode
, struct file
*file
)
289 return single_open(file
, hctx_sched_tags_show
, inode
->i_private
);
292 static const struct file_operations hctx_sched_tags_fops
= {
293 .open
= hctx_sched_tags_open
,
296 .release
= single_release
,
299 static int hctx_sched_tags_bitmap_show(struct seq_file
*m
, void *v
)
301 struct blk_mq_hw_ctx
*hctx
= m
->private;
302 struct request_queue
*q
= hctx
->queue
;
305 res
= mutex_lock_interruptible(&q
->sysfs_lock
);
308 if (hctx
->sched_tags
)
309 sbitmap_bitmap_show(&hctx
->sched_tags
->bitmap_tags
.sb
, m
);
310 mutex_unlock(&q
->sysfs_lock
);
316 static int hctx_sched_tags_bitmap_open(struct inode
*inode
, struct file
*file
)
318 return single_open(file
, hctx_sched_tags_bitmap_show
, inode
->i_private
);
321 static const struct file_operations hctx_sched_tags_bitmap_fops
= {
322 .open
= hctx_sched_tags_bitmap_open
,
325 .release
= single_release
,
328 static int hctx_io_poll_show(struct seq_file
*m
, void *v
)
330 struct blk_mq_hw_ctx
*hctx
= m
->private;
332 seq_printf(m
, "considered=%lu\n", hctx
->poll_considered
);
333 seq_printf(m
, "invoked=%lu\n", hctx
->poll_invoked
);
334 seq_printf(m
, "success=%lu\n", hctx
->poll_success
);
338 static int hctx_io_poll_open(struct inode
*inode
, struct file
*file
)
340 return single_open(file
, hctx_io_poll_show
, inode
->i_private
);
343 static ssize_t
hctx_io_poll_write(struct file
*file
, const char __user
*buf
,
344 size_t count
, loff_t
*ppos
)
346 struct seq_file
*m
= file
->private_data
;
347 struct blk_mq_hw_ctx
*hctx
= m
->private;
349 hctx
->poll_considered
= hctx
->poll_invoked
= hctx
->poll_success
= 0;
353 static const struct file_operations hctx_io_poll_fops
= {
354 .open
= hctx_io_poll_open
,
356 .write
= hctx_io_poll_write
,
358 .release
= single_release
,
361 static int hctx_dispatched_show(struct seq_file
*m
, void *v
)
363 struct blk_mq_hw_ctx
*hctx
= m
->private;
366 seq_printf(m
, "%8u\t%lu\n", 0U, hctx
->dispatched
[0]);
368 for (i
= 1; i
< BLK_MQ_MAX_DISPATCH_ORDER
- 1; i
++) {
369 unsigned int d
= 1U << (i
- 1);
371 seq_printf(m
, "%8u\t%lu\n", d
, hctx
->dispatched
[i
]);
374 seq_printf(m
, "%8u+\t%lu\n", 1U << (i
- 1), hctx
->dispatched
[i
]);
378 static int hctx_dispatched_open(struct inode
*inode
, struct file
*file
)
380 return single_open(file
, hctx_dispatched_show
, inode
->i_private
);
383 static ssize_t
hctx_dispatched_write(struct file
*file
, const char __user
*buf
,
384 size_t count
, loff_t
*ppos
)
386 struct seq_file
*m
= file
->private_data
;
387 struct blk_mq_hw_ctx
*hctx
= m
->private;
390 for (i
= 0; i
< BLK_MQ_MAX_DISPATCH_ORDER
; i
++)
391 hctx
->dispatched
[i
] = 0;
395 static const struct file_operations hctx_dispatched_fops
= {
396 .open
= hctx_dispatched_open
,
398 .write
= hctx_dispatched_write
,
400 .release
= single_release
,
403 static int hctx_queued_show(struct seq_file
*m
, void *v
)
405 struct blk_mq_hw_ctx
*hctx
= m
->private;
407 seq_printf(m
, "%lu\n", hctx
->queued
);
411 static int hctx_queued_open(struct inode
*inode
, struct file
*file
)
413 return single_open(file
, hctx_queued_show
, inode
->i_private
);
416 static ssize_t
hctx_queued_write(struct file
*file
, const char __user
*buf
,
417 size_t count
, loff_t
*ppos
)
419 struct seq_file
*m
= file
->private_data
;
420 struct blk_mq_hw_ctx
*hctx
= m
->private;
426 static const struct file_operations hctx_queued_fops
= {
427 .open
= hctx_queued_open
,
429 .write
= hctx_queued_write
,
431 .release
= single_release
,
434 static int hctx_run_show(struct seq_file
*m
, void *v
)
436 struct blk_mq_hw_ctx
*hctx
= m
->private;
438 seq_printf(m
, "%lu\n", hctx
->run
);
442 static int hctx_run_open(struct inode
*inode
, struct file
*file
)
444 return single_open(file
, hctx_run_show
, inode
->i_private
);
447 static ssize_t
hctx_run_write(struct file
*file
, const char __user
*buf
,
448 size_t count
, loff_t
*ppos
)
450 struct seq_file
*m
= file
->private_data
;
451 struct blk_mq_hw_ctx
*hctx
= m
->private;
457 static const struct file_operations hctx_run_fops
= {
458 .open
= hctx_run_open
,
460 .write
= hctx_run_write
,
462 .release
= single_release
,
465 static int hctx_active_show(struct seq_file
*m
, void *v
)
467 struct blk_mq_hw_ctx
*hctx
= m
->private;
469 seq_printf(m
, "%d\n", atomic_read(&hctx
->nr_active
));
473 static int hctx_active_open(struct inode
*inode
, struct file
*file
)
475 return single_open(file
, hctx_active_show
, inode
->i_private
);
478 static const struct file_operations hctx_active_fops
= {
479 .open
= hctx_active_open
,
482 .release
= single_release
,
485 static void *ctx_rq_list_start(struct seq_file
*m
, loff_t
*pos
)
486 __acquires(&ctx
->lock
)
488 struct blk_mq_ctx
*ctx
= m
->private;
490 spin_lock(&ctx
->lock
);
491 return seq_list_start(&ctx
->rq_list
, *pos
);
494 static void *ctx_rq_list_next(struct seq_file
*m
, void *v
, loff_t
*pos
)
496 struct blk_mq_ctx
*ctx
= m
->private;
498 return seq_list_next(v
, &ctx
->rq_list
, pos
);
501 static void ctx_rq_list_stop(struct seq_file
*m
, void *v
)
502 __releases(&ctx
->lock
)
504 struct blk_mq_ctx
*ctx
= m
->private;
506 spin_unlock(&ctx
->lock
);
509 static const struct seq_operations ctx_rq_list_seq_ops
= {
510 .start
= ctx_rq_list_start
,
511 .next
= ctx_rq_list_next
,
512 .stop
= ctx_rq_list_stop
,
513 .show
= blk_mq_debugfs_rq_show
,
516 static int ctx_rq_list_open(struct inode
*inode
, struct file
*file
)
518 return blk_mq_debugfs_seq_open(inode
, file
, &ctx_rq_list_seq_ops
);
521 static const struct file_operations ctx_rq_list_fops
= {
522 .open
= ctx_rq_list_open
,
525 .release
= seq_release
,
528 static int ctx_dispatched_show(struct seq_file
*m
, void *v
)
530 struct blk_mq_ctx
*ctx
= m
->private;
532 seq_printf(m
, "%lu %lu\n", ctx
->rq_dispatched
[1], ctx
->rq_dispatched
[0]);
536 static int ctx_dispatched_open(struct inode
*inode
, struct file
*file
)
538 return single_open(file
, ctx_dispatched_show
, inode
->i_private
);
541 static ssize_t
ctx_dispatched_write(struct file
*file
, const char __user
*buf
,
542 size_t count
, loff_t
*ppos
)
544 struct seq_file
*m
= file
->private_data
;
545 struct blk_mq_ctx
*ctx
= m
->private;
547 ctx
->rq_dispatched
[0] = ctx
->rq_dispatched
[1] = 0;
551 static const struct file_operations ctx_dispatched_fops
= {
552 .open
= ctx_dispatched_open
,
554 .write
= ctx_dispatched_write
,
556 .release
= single_release
,
559 static int ctx_merged_show(struct seq_file
*m
, void *v
)
561 struct blk_mq_ctx
*ctx
= m
->private;
563 seq_printf(m
, "%lu\n", ctx
->rq_merged
);
567 static int ctx_merged_open(struct inode
*inode
, struct file
*file
)
569 return single_open(file
, ctx_merged_show
, inode
->i_private
);
572 static ssize_t
ctx_merged_write(struct file
*file
, const char __user
*buf
,
573 size_t count
, loff_t
*ppos
)
575 struct seq_file
*m
= file
->private_data
;
576 struct blk_mq_ctx
*ctx
= m
->private;
582 static const struct file_operations ctx_merged_fops
= {
583 .open
= ctx_merged_open
,
585 .write
= ctx_merged_write
,
587 .release
= single_release
,
590 static int ctx_completed_show(struct seq_file
*m
, void *v
)
592 struct blk_mq_ctx
*ctx
= m
->private;
594 seq_printf(m
, "%lu %lu\n", ctx
->rq_completed
[1], ctx
->rq_completed
[0]);
598 static int ctx_completed_open(struct inode
*inode
, struct file
*file
)
600 return single_open(file
, ctx_completed_show
, inode
->i_private
);
603 static ssize_t
ctx_completed_write(struct file
*file
, const char __user
*buf
,
604 size_t count
, loff_t
*ppos
)
606 struct seq_file
*m
= file
->private_data
;
607 struct blk_mq_ctx
*ctx
= m
->private;
609 ctx
->rq_completed
[0] = ctx
->rq_completed
[1] = 0;
613 static const struct file_operations ctx_completed_fops
= {
614 .open
= ctx_completed_open
,
616 .write
= ctx_completed_write
,
618 .release
= single_release
,
621 static const struct blk_mq_debugfs_attr blk_mq_debugfs_queue_attrs
[] = {
622 {"poll_stat", 0400, &queue_poll_stat_fops
},
626 static const struct blk_mq_debugfs_attr blk_mq_debugfs_hctx_attrs
[] = {
627 {"state", 0400, &hctx_state_fops
},
628 {"flags", 0400, &hctx_flags_fops
},
629 {"dispatch", 0400, &hctx_dispatch_fops
},
630 {"ctx_map", 0400, &hctx_ctx_map_fops
},
631 {"tags", 0400, &hctx_tags_fops
},
632 {"tags_bitmap", 0400, &hctx_tags_bitmap_fops
},
633 {"sched_tags", 0400, &hctx_sched_tags_fops
},
634 {"sched_tags_bitmap", 0400, &hctx_sched_tags_bitmap_fops
},
635 {"io_poll", 0600, &hctx_io_poll_fops
},
636 {"dispatched", 0600, &hctx_dispatched_fops
},
637 {"queued", 0600, &hctx_queued_fops
},
638 {"run", 0600, &hctx_run_fops
},
639 {"active", 0400, &hctx_active_fops
},
643 static const struct blk_mq_debugfs_attr blk_mq_debugfs_ctx_attrs
[] = {
644 {"rq_list", 0400, &ctx_rq_list_fops
},
645 {"dispatched", 0600, &ctx_dispatched_fops
},
646 {"merged", 0600, &ctx_merged_fops
},
647 {"completed", 0600, &ctx_completed_fops
},
651 int blk_mq_debugfs_register(struct request_queue
*q
, const char *name
)
653 if (!blk_debugfs_root
)
656 q
->debugfs_dir
= debugfs_create_dir(name
, blk_debugfs_root
);
660 if (blk_mq_debugfs_register_hctxs(q
))
666 blk_mq_debugfs_unregister(q
);
670 void blk_mq_debugfs_unregister(struct request_queue
*q
)
672 debugfs_remove_recursive(q
->debugfs_dir
);
673 q
->mq_debugfs_dir
= NULL
;
674 q
->debugfs_dir
= NULL
;
677 static bool debugfs_create_files(struct dentry
*parent
, void *data
,
678 const struct blk_mq_debugfs_attr
*attr
)
680 for (; attr
->name
; attr
++) {
681 if (!debugfs_create_file(attr
->name
, attr
->mode
, parent
,
688 static int blk_mq_debugfs_register_ctx(struct request_queue
*q
,
689 struct blk_mq_ctx
*ctx
,
690 struct dentry
*hctx_dir
)
692 struct dentry
*ctx_dir
;
695 snprintf(name
, sizeof(name
), "cpu%u", ctx
->cpu
);
696 ctx_dir
= debugfs_create_dir(name
, hctx_dir
);
700 if (!debugfs_create_files(ctx_dir
, ctx
, blk_mq_debugfs_ctx_attrs
))
706 static int blk_mq_debugfs_register_hctx(struct request_queue
*q
,
707 struct blk_mq_hw_ctx
*hctx
)
709 struct blk_mq_ctx
*ctx
;
710 struct dentry
*hctx_dir
;
714 snprintf(name
, sizeof(name
), "%u", hctx
->queue_num
);
715 hctx_dir
= debugfs_create_dir(name
, q
->mq_debugfs_dir
);
719 if (!debugfs_create_files(hctx_dir
, hctx
, blk_mq_debugfs_hctx_attrs
))
722 hctx_for_each_ctx(hctx
, ctx
, i
) {
723 if (blk_mq_debugfs_register_ctx(q
, ctx
, hctx_dir
))
730 int blk_mq_debugfs_register_hctxs(struct request_queue
*q
)
732 struct blk_mq_hw_ctx
*hctx
;
738 q
->mq_debugfs_dir
= debugfs_create_dir("mq", q
->debugfs_dir
);
739 if (!q
->mq_debugfs_dir
)
742 if (!debugfs_create_files(q
->mq_debugfs_dir
, q
, blk_mq_debugfs_queue_attrs
))
745 queue_for_each_hw_ctx(q
, hctx
, i
) {
746 if (blk_mq_debugfs_register_hctx(q
, hctx
))
753 blk_mq_debugfs_unregister_hctxs(q
);
757 void blk_mq_debugfs_unregister_hctxs(struct request_queue
*q
)
759 debugfs_remove_recursive(q
->mq_debugfs_dir
);
760 q
->mq_debugfs_dir
= NULL
;