xref: /openbmc/linux/block/blk-mq-debugfs.c (revision c0c74acb)
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.h"
23 #include "blk-mq.h"
24 #include "blk-mq-tag.h"
25 
26 struct blk_mq_debugfs_attr {
27 	const char *name;
28 	umode_t mode;
29 	const struct file_operations *fops;
30 };
31 
32 static int blk_mq_debugfs_seq_open(struct inode *inode, struct file *file,
33 				   const struct seq_operations *ops)
34 {
35 	struct seq_file *m;
36 	int ret;
37 
38 	ret = seq_open(file, ops);
39 	if (!ret) {
40 		m = file->private_data;
41 		m->private = inode->i_private;
42 	}
43 	return ret;
44 }
45 
46 static int hctx_state_show(struct seq_file *m, void *v)
47 {
48 	struct blk_mq_hw_ctx *hctx = m->private;
49 
50 	seq_printf(m, "0x%lx\n", hctx->state);
51 	return 0;
52 }
53 
54 static int hctx_state_open(struct inode *inode, struct file *file)
55 {
56 	return single_open(file, hctx_state_show, inode->i_private);
57 }
58 
59 static const struct file_operations hctx_state_fops = {
60 	.open		= hctx_state_open,
61 	.read		= seq_read,
62 	.llseek		= seq_lseek,
63 	.release	= single_release,
64 };
65 
66 static int hctx_flags_show(struct seq_file *m, void *v)
67 {
68 	struct blk_mq_hw_ctx *hctx = m->private;
69 
70 	seq_printf(m, "0x%lx\n", hctx->flags);
71 	return 0;
72 }
73 
74 static int hctx_flags_open(struct inode *inode, struct file *file)
75 {
76 	return single_open(file, hctx_flags_show, inode->i_private);
77 }
78 
79 static const struct file_operations hctx_flags_fops = {
80 	.open		= hctx_flags_open,
81 	.read		= seq_read,
82 	.llseek		= seq_lseek,
83 	.release	= single_release,
84 };
85 
86 static int blk_mq_debugfs_rq_show(struct seq_file *m, void *v)
87 {
88 	struct request *rq = list_entry_rq(v);
89 
90 	seq_printf(m, "%p {.cmd_flags=0x%x, .rq_flags=0x%x, .tag=%d, .internal_tag=%d}\n",
91 		   rq, rq->cmd_flags, (__force unsigned int)rq->rq_flags,
92 		   rq->tag, rq->internal_tag);
93 	return 0;
94 }
95 
96 static void *hctx_dispatch_start(struct seq_file *m, loff_t *pos)
97 	__acquires(&hctx->lock)
98 {
99 	struct blk_mq_hw_ctx *hctx = m->private;
100 
101 	spin_lock(&hctx->lock);
102 	return seq_list_start(&hctx->dispatch, *pos);
103 }
104 
105 static void *hctx_dispatch_next(struct seq_file *m, void *v, loff_t *pos)
106 {
107 	struct blk_mq_hw_ctx *hctx = m->private;
108 
109 	return seq_list_next(v, &hctx->dispatch, pos);
110 }
111 
112 static void hctx_dispatch_stop(struct seq_file *m, void *v)
113 	__releases(&hctx->lock)
114 {
115 	struct blk_mq_hw_ctx *hctx = m->private;
116 
117 	spin_unlock(&hctx->lock);
118 }
119 
120 static const struct seq_operations hctx_dispatch_seq_ops = {
121 	.start	= hctx_dispatch_start,
122 	.next	= hctx_dispatch_next,
123 	.stop	= hctx_dispatch_stop,
124 	.show	= blk_mq_debugfs_rq_show,
125 };
126 
127 static int hctx_dispatch_open(struct inode *inode, struct file *file)
128 {
129 	return blk_mq_debugfs_seq_open(inode, file, &hctx_dispatch_seq_ops);
130 }
131 
132 static const struct file_operations hctx_dispatch_fops = {
133 	.open		= hctx_dispatch_open,
134 	.read		= seq_read,
135 	.llseek		= seq_lseek,
136 	.release	= seq_release,
137 };
138 
139 static int hctx_ctx_map_show(struct seq_file *m, void *v)
140 {
141 	struct blk_mq_hw_ctx *hctx = m->private;
142 
143 	sbitmap_bitmap_show(&hctx->ctx_map, m);
144 	return 0;
145 }
146 
147 static int hctx_ctx_map_open(struct inode *inode, struct file *file)
148 {
149 	return single_open(file, hctx_ctx_map_show, inode->i_private);
150 }
151 
152 static const struct file_operations hctx_ctx_map_fops = {
153 	.open		= hctx_ctx_map_open,
154 	.read		= seq_read,
155 	.llseek		= seq_lseek,
156 	.release	= single_release,
157 };
158 
159 static void blk_mq_debugfs_tags_show(struct seq_file *m,
160 				     struct blk_mq_tags *tags)
161 {
162 	seq_printf(m, "nr_tags=%u\n", tags->nr_tags);
163 	seq_printf(m, "nr_reserved_tags=%u\n", tags->nr_reserved_tags);
164 	seq_printf(m, "active_queues=%d\n",
165 		   atomic_read(&tags->active_queues));
166 
167 	seq_puts(m, "\nbitmap_tags:\n");
168 	sbitmap_queue_show(&tags->bitmap_tags, m);
169 
170 	if (tags->nr_reserved_tags) {
171 		seq_puts(m, "\nbreserved_tags:\n");
172 		sbitmap_queue_show(&tags->breserved_tags, m);
173 	}
174 }
175 
176 static int hctx_tags_show(struct seq_file *m, void *v)
177 {
178 	struct blk_mq_hw_ctx *hctx = m->private;
179 	struct request_queue *q = hctx->queue;
180 	int res;
181 
182 	res = mutex_lock_interruptible(&q->sysfs_lock);
183 	if (res)
184 		goto out;
185 	if (hctx->tags)
186 		blk_mq_debugfs_tags_show(m, hctx->tags);
187 	mutex_unlock(&q->sysfs_lock);
188 
189 out:
190 	return res;
191 }
192 
193 static int hctx_tags_open(struct inode *inode, struct file *file)
194 {
195 	return single_open(file, hctx_tags_show, inode->i_private);
196 }
197 
198 static const struct file_operations hctx_tags_fops = {
199 	.open		= hctx_tags_open,
200 	.read		= seq_read,
201 	.llseek		= seq_lseek,
202 	.release	= single_release,
203 };
204 
205 static int hctx_tags_bitmap_show(struct seq_file *m, void *v)
206 {
207 	struct blk_mq_hw_ctx *hctx = m->private;
208 	struct request_queue *q = hctx->queue;
209 	int res;
210 
211 	res = mutex_lock_interruptible(&q->sysfs_lock);
212 	if (res)
213 		goto out;
214 	if (hctx->tags)
215 		sbitmap_bitmap_show(&hctx->tags->bitmap_tags.sb, m);
216 	mutex_unlock(&q->sysfs_lock);
217 
218 out:
219 	return res;
220 }
221 
222 static int hctx_tags_bitmap_open(struct inode *inode, struct file *file)
223 {
224 	return single_open(file, hctx_tags_bitmap_show, inode->i_private);
225 }
226 
227 static const struct file_operations hctx_tags_bitmap_fops = {
228 	.open		= hctx_tags_bitmap_open,
229 	.read		= seq_read,
230 	.llseek		= seq_lseek,
231 	.release	= single_release,
232 };
233 
234 static int hctx_sched_tags_show(struct seq_file *m, void *v)
235 {
236 	struct blk_mq_hw_ctx *hctx = m->private;
237 	struct request_queue *q = hctx->queue;
238 	int res;
239 
240 	res = mutex_lock_interruptible(&q->sysfs_lock);
241 	if (res)
242 		goto out;
243 	if (hctx->sched_tags)
244 		blk_mq_debugfs_tags_show(m, hctx->sched_tags);
245 	mutex_unlock(&q->sysfs_lock);
246 
247 out:
248 	return res;
249 }
250 
251 static int hctx_sched_tags_open(struct inode *inode, struct file *file)
252 {
253 	return single_open(file, hctx_sched_tags_show, inode->i_private);
254 }
255 
256 static const struct file_operations hctx_sched_tags_fops = {
257 	.open		= hctx_sched_tags_open,
258 	.read		= seq_read,
259 	.llseek		= seq_lseek,
260 	.release	= single_release,
261 };
262 
263 static int hctx_sched_tags_bitmap_show(struct seq_file *m, void *v)
264 {
265 	struct blk_mq_hw_ctx *hctx = m->private;
266 	struct request_queue *q = hctx->queue;
267 	int res;
268 
269 	res = mutex_lock_interruptible(&q->sysfs_lock);
270 	if (res)
271 		goto out;
272 	if (hctx->sched_tags)
273 		sbitmap_bitmap_show(&hctx->sched_tags->bitmap_tags.sb, m);
274 	mutex_unlock(&q->sysfs_lock);
275 
276 out:
277 	return res;
278 }
279 
280 static int hctx_sched_tags_bitmap_open(struct inode *inode, struct file *file)
281 {
282 	return single_open(file, hctx_sched_tags_bitmap_show, inode->i_private);
283 }
284 
285 static const struct file_operations hctx_sched_tags_bitmap_fops = {
286 	.open		= hctx_sched_tags_bitmap_open,
287 	.read		= seq_read,
288 	.llseek		= seq_lseek,
289 	.release	= single_release,
290 };
291 
292 static int hctx_io_poll_show(struct seq_file *m, void *v)
293 {
294 	struct blk_mq_hw_ctx *hctx = m->private;
295 
296 	seq_printf(m, "considered=%lu\n", hctx->poll_considered);
297 	seq_printf(m, "invoked=%lu\n", hctx->poll_invoked);
298 	seq_printf(m, "success=%lu\n", hctx->poll_success);
299 	return 0;
300 }
301 
302 static int hctx_io_poll_open(struct inode *inode, struct file *file)
303 {
304 	return single_open(file, hctx_io_poll_show, inode->i_private);
305 }
306 
307 static ssize_t hctx_io_poll_write(struct file *file, const char __user *buf,
308 				  size_t count, loff_t *ppos)
309 {
310 	struct seq_file *m = file->private_data;
311 	struct blk_mq_hw_ctx *hctx = m->private;
312 
313 	hctx->poll_considered = hctx->poll_invoked = hctx->poll_success = 0;
314 	return count;
315 }
316 
317 static const struct file_operations hctx_io_poll_fops = {
318 	.open		= hctx_io_poll_open,
319 	.read		= seq_read,
320 	.write		= hctx_io_poll_write,
321 	.llseek		= seq_lseek,
322 	.release	= single_release,
323 };
324 
325 static void print_stat(struct seq_file *m, struct blk_rq_stat *stat)
326 {
327 	seq_printf(m, "samples=%d, mean=%lld, min=%llu, max=%llu",
328 		   stat->nr_samples, stat->mean, stat->min, stat->max);
329 }
330 
331 static int hctx_stats_show(struct seq_file *m, void *v)
332 {
333 	struct blk_mq_hw_ctx *hctx = m->private;
334 	struct blk_rq_stat stat[2];
335 
336 	blk_stat_init(&stat[BLK_STAT_READ]);
337 	blk_stat_init(&stat[BLK_STAT_WRITE]);
338 
339 	blk_hctx_stat_get(hctx, stat);
340 
341 	seq_puts(m, "read: ");
342 	print_stat(m, &stat[BLK_STAT_READ]);
343 	seq_puts(m, "\n");
344 
345 	seq_puts(m, "write: ");
346 	print_stat(m, &stat[BLK_STAT_WRITE]);
347 	seq_puts(m, "\n");
348 	return 0;
349 }
350 
351 static int hctx_stats_open(struct inode *inode, struct file *file)
352 {
353 	return single_open(file, hctx_stats_show, inode->i_private);
354 }
355 
356 static ssize_t hctx_stats_write(struct file *file, const char __user *buf,
357 				size_t count, loff_t *ppos)
358 {
359 	struct seq_file *m = file->private_data;
360 	struct blk_mq_hw_ctx *hctx = m->private;
361 	struct blk_mq_ctx *ctx;
362 	int i;
363 
364 	hctx_for_each_ctx(hctx, ctx, i) {
365 		blk_stat_init(&ctx->stat[BLK_STAT_READ]);
366 		blk_stat_init(&ctx->stat[BLK_STAT_WRITE]);
367 	}
368 	return count;
369 }
370 
371 static const struct file_operations hctx_stats_fops = {
372 	.open		= hctx_stats_open,
373 	.read		= seq_read,
374 	.write		= hctx_stats_write,
375 	.llseek		= seq_lseek,
376 	.release	= single_release,
377 };
378 
379 static int hctx_dispatched_show(struct seq_file *m, void *v)
380 {
381 	struct blk_mq_hw_ctx *hctx = m->private;
382 	int i;
383 
384 	seq_printf(m, "%8u\t%lu\n", 0U, hctx->dispatched[0]);
385 
386 	for (i = 1; i < BLK_MQ_MAX_DISPATCH_ORDER - 1; i++) {
387 		unsigned int d = 1U << (i - 1);
388 
389 		seq_printf(m, "%8u\t%lu\n", d, hctx->dispatched[i]);
390 	}
391 
392 	seq_printf(m, "%8u+\t%lu\n", 1U << (i - 1), hctx->dispatched[i]);
393 	return 0;
394 }
395 
396 static int hctx_dispatched_open(struct inode *inode, struct file *file)
397 {
398 	return single_open(file, hctx_dispatched_show, inode->i_private);
399 }
400 
401 static ssize_t hctx_dispatched_write(struct file *file, const char __user *buf,
402 				     size_t count, loff_t *ppos)
403 {
404 	struct seq_file *m = file->private_data;
405 	struct blk_mq_hw_ctx *hctx = m->private;
406 	int i;
407 
408 	for (i = 0; i < BLK_MQ_MAX_DISPATCH_ORDER; i++)
409 		hctx->dispatched[i] = 0;
410 	return count;
411 }
412 
413 static const struct file_operations hctx_dispatched_fops = {
414 	.open		= hctx_dispatched_open,
415 	.read		= seq_read,
416 	.write		= hctx_dispatched_write,
417 	.llseek		= seq_lseek,
418 	.release	= single_release,
419 };
420 
421 static int hctx_queued_show(struct seq_file *m, void *v)
422 {
423 	struct blk_mq_hw_ctx *hctx = m->private;
424 
425 	seq_printf(m, "%lu\n", hctx->queued);
426 	return 0;
427 }
428 
429 static int hctx_queued_open(struct inode *inode, struct file *file)
430 {
431 	return single_open(file, hctx_queued_show, inode->i_private);
432 }
433 
434 static ssize_t hctx_queued_write(struct file *file, const char __user *buf,
435 				 size_t count, loff_t *ppos)
436 {
437 	struct seq_file *m = file->private_data;
438 	struct blk_mq_hw_ctx *hctx = m->private;
439 
440 	hctx->queued = 0;
441 	return count;
442 }
443 
444 static const struct file_operations hctx_queued_fops = {
445 	.open		= hctx_queued_open,
446 	.read		= seq_read,
447 	.write		= hctx_queued_write,
448 	.llseek		= seq_lseek,
449 	.release	= single_release,
450 };
451 
452 static int hctx_run_show(struct seq_file *m, void *v)
453 {
454 	struct blk_mq_hw_ctx *hctx = m->private;
455 
456 	seq_printf(m, "%lu\n", hctx->run);
457 	return 0;
458 }
459 
460 static int hctx_run_open(struct inode *inode, struct file *file)
461 {
462 	return single_open(file, hctx_run_show, inode->i_private);
463 }
464 
465 static ssize_t hctx_run_write(struct file *file, const char __user *buf,
466 				 size_t count, loff_t *ppos)
467 {
468 	struct seq_file *m = file->private_data;
469 	struct blk_mq_hw_ctx *hctx = m->private;
470 
471 	hctx->run = 0;
472 	return count;
473 }
474 
475 static const struct file_operations hctx_run_fops = {
476 	.open		= hctx_run_open,
477 	.read		= seq_read,
478 	.write		= hctx_run_write,
479 	.llseek		= seq_lseek,
480 	.release	= single_release,
481 };
482 
483 static int hctx_active_show(struct seq_file *m, void *v)
484 {
485 	struct blk_mq_hw_ctx *hctx = m->private;
486 
487 	seq_printf(m, "%d\n", atomic_read(&hctx->nr_active));
488 	return 0;
489 }
490 
491 static int hctx_active_open(struct inode *inode, struct file *file)
492 {
493 	return single_open(file, hctx_active_show, inode->i_private);
494 }
495 
496 static const struct file_operations hctx_active_fops = {
497 	.open		= hctx_active_open,
498 	.read		= seq_read,
499 	.llseek		= seq_lseek,
500 	.release	= single_release,
501 };
502 
503 static void *ctx_rq_list_start(struct seq_file *m, loff_t *pos)
504 	__acquires(&ctx->lock)
505 {
506 	struct blk_mq_ctx *ctx = m->private;
507 
508 	spin_lock(&ctx->lock);
509 	return seq_list_start(&ctx->rq_list, *pos);
510 }
511 
512 static void *ctx_rq_list_next(struct seq_file *m, void *v, loff_t *pos)
513 {
514 	struct blk_mq_ctx *ctx = m->private;
515 
516 	return seq_list_next(v, &ctx->rq_list, pos);
517 }
518 
519 static void ctx_rq_list_stop(struct seq_file *m, void *v)
520 	__releases(&ctx->lock)
521 {
522 	struct blk_mq_ctx *ctx = m->private;
523 
524 	spin_unlock(&ctx->lock);
525 }
526 
527 static const struct seq_operations ctx_rq_list_seq_ops = {
528 	.start	= ctx_rq_list_start,
529 	.next	= ctx_rq_list_next,
530 	.stop	= ctx_rq_list_stop,
531 	.show	= blk_mq_debugfs_rq_show,
532 };
533 
534 static int ctx_rq_list_open(struct inode *inode, struct file *file)
535 {
536 	return blk_mq_debugfs_seq_open(inode, file, &ctx_rq_list_seq_ops);
537 }
538 
539 static const struct file_operations ctx_rq_list_fops = {
540 	.open		= ctx_rq_list_open,
541 	.read		= seq_read,
542 	.llseek		= seq_lseek,
543 	.release	= seq_release,
544 };
545 
546 static int ctx_dispatched_show(struct seq_file *m, void *v)
547 {
548 	struct blk_mq_ctx *ctx = m->private;
549 
550 	seq_printf(m, "%lu %lu\n", ctx->rq_dispatched[1], ctx->rq_dispatched[0]);
551 	return 0;
552 }
553 
554 static int ctx_dispatched_open(struct inode *inode, struct file *file)
555 {
556 	return single_open(file, ctx_dispatched_show, inode->i_private);
557 }
558 
559 static ssize_t ctx_dispatched_write(struct file *file, const char __user *buf,
560 				    size_t count, loff_t *ppos)
561 {
562 	struct seq_file *m = file->private_data;
563 	struct blk_mq_ctx *ctx = m->private;
564 
565 	ctx->rq_dispatched[0] = ctx->rq_dispatched[1] = 0;
566 	return count;
567 }
568 
569 static const struct file_operations ctx_dispatched_fops = {
570 	.open		= ctx_dispatched_open,
571 	.read		= seq_read,
572 	.write		= ctx_dispatched_write,
573 	.llseek		= seq_lseek,
574 	.release	= single_release,
575 };
576 
577 static int ctx_merged_show(struct seq_file *m, void *v)
578 {
579 	struct blk_mq_ctx *ctx = m->private;
580 
581 	seq_printf(m, "%lu\n", ctx->rq_merged);
582 	return 0;
583 }
584 
585 static int ctx_merged_open(struct inode *inode, struct file *file)
586 {
587 	return single_open(file, ctx_merged_show, inode->i_private);
588 }
589 
590 static ssize_t ctx_merged_write(struct file *file, const char __user *buf,
591 				    size_t count, loff_t *ppos)
592 {
593 	struct seq_file *m = file->private_data;
594 	struct blk_mq_ctx *ctx = m->private;
595 
596 	ctx->rq_merged = 0;
597 	return count;
598 }
599 
600 static const struct file_operations ctx_merged_fops = {
601 	.open		= ctx_merged_open,
602 	.read		= seq_read,
603 	.write		= ctx_merged_write,
604 	.llseek		= seq_lseek,
605 	.release	= single_release,
606 };
607 
608 static int ctx_completed_show(struct seq_file *m, void *v)
609 {
610 	struct blk_mq_ctx *ctx = m->private;
611 
612 	seq_printf(m, "%lu %lu\n", ctx->rq_completed[1], ctx->rq_completed[0]);
613 	return 0;
614 }
615 
616 static int ctx_completed_open(struct inode *inode, struct file *file)
617 {
618 	return single_open(file, ctx_completed_show, inode->i_private);
619 }
620 
621 static ssize_t ctx_completed_write(struct file *file, const char __user *buf,
622 				   size_t count, loff_t *ppos)
623 {
624 	struct seq_file *m = file->private_data;
625 	struct blk_mq_ctx *ctx = m->private;
626 
627 	ctx->rq_completed[0] = ctx->rq_completed[1] = 0;
628 	return count;
629 }
630 
631 static const struct file_operations ctx_completed_fops = {
632 	.open		= ctx_completed_open,
633 	.read		= seq_read,
634 	.write		= ctx_completed_write,
635 	.llseek		= seq_lseek,
636 	.release	= single_release,
637 };
638 
639 static const struct blk_mq_debugfs_attr blk_mq_debugfs_hctx_attrs[] = {
640 	{"state", 0400, &hctx_state_fops},
641 	{"flags", 0400, &hctx_flags_fops},
642 	{"dispatch", 0400, &hctx_dispatch_fops},
643 	{"ctx_map", 0400, &hctx_ctx_map_fops},
644 	{"tags", 0400, &hctx_tags_fops},
645 	{"tags_bitmap", 0400, &hctx_tags_bitmap_fops},
646 	{"sched_tags", 0400, &hctx_sched_tags_fops},
647 	{"sched_tags_bitmap", 0400, &hctx_sched_tags_bitmap_fops},
648 	{"io_poll", 0600, &hctx_io_poll_fops},
649 	{"stats", 0600, &hctx_stats_fops},
650 	{"dispatched", 0600, &hctx_dispatched_fops},
651 	{"queued", 0600, &hctx_queued_fops},
652 	{"run", 0600, &hctx_run_fops},
653 	{"active", 0400, &hctx_active_fops},
654 	{},
655 };
656 
657 static const struct blk_mq_debugfs_attr blk_mq_debugfs_ctx_attrs[] = {
658 	{"rq_list", 0400, &ctx_rq_list_fops},
659 	{"dispatched", 0600, &ctx_dispatched_fops},
660 	{"merged", 0600, &ctx_merged_fops},
661 	{"completed", 0600, &ctx_completed_fops},
662 	{},
663 };
664 
665 int blk_mq_debugfs_register(struct request_queue *q, const char *name)
666 {
667 	if (!blk_debugfs_root)
668 		return -ENOENT;
669 
670 	q->debugfs_dir = debugfs_create_dir(name, blk_debugfs_root);
671 	if (!q->debugfs_dir)
672 		goto err;
673 
674 	if (blk_mq_debugfs_register_hctxs(q))
675 		goto err;
676 
677 	return 0;
678 
679 err:
680 	blk_mq_debugfs_unregister(q);
681 	return -ENOMEM;
682 }
683 
684 void blk_mq_debugfs_unregister(struct request_queue *q)
685 {
686 	debugfs_remove_recursive(q->debugfs_dir);
687 	q->mq_debugfs_dir = NULL;
688 	q->debugfs_dir = NULL;
689 }
690 
691 static bool debugfs_create_files(struct dentry *parent, void *data,
692 				const struct blk_mq_debugfs_attr *attr)
693 {
694 	for (; attr->name; attr++) {
695 		if (!debugfs_create_file(attr->name, attr->mode, parent,
696 					 data, attr->fops))
697 			return false;
698 	}
699 	return true;
700 }
701 
702 static int blk_mq_debugfs_register_ctx(struct request_queue *q,
703 				       struct blk_mq_ctx *ctx,
704 				       struct dentry *hctx_dir)
705 {
706 	struct dentry *ctx_dir;
707 	char name[20];
708 
709 	snprintf(name, sizeof(name), "cpu%u", ctx->cpu);
710 	ctx_dir = debugfs_create_dir(name, hctx_dir);
711 	if (!ctx_dir)
712 		return -ENOMEM;
713 
714 	if (!debugfs_create_files(ctx_dir, ctx, blk_mq_debugfs_ctx_attrs))
715 		return -ENOMEM;
716 
717 	return 0;
718 }
719 
720 static int blk_mq_debugfs_register_hctx(struct request_queue *q,
721 					struct blk_mq_hw_ctx *hctx)
722 {
723 	struct blk_mq_ctx *ctx;
724 	struct dentry *hctx_dir;
725 	char name[20];
726 	int i;
727 
728 	snprintf(name, sizeof(name), "%u", hctx->queue_num);
729 	hctx_dir = debugfs_create_dir(name, q->mq_debugfs_dir);
730 	if (!hctx_dir)
731 		return -ENOMEM;
732 
733 	if (!debugfs_create_files(hctx_dir, hctx, blk_mq_debugfs_hctx_attrs))
734 		return -ENOMEM;
735 
736 	hctx_for_each_ctx(hctx, ctx, i) {
737 		if (blk_mq_debugfs_register_ctx(q, ctx, hctx_dir))
738 			return -ENOMEM;
739 	}
740 
741 	return 0;
742 }
743 
744 int blk_mq_debugfs_register_hctxs(struct request_queue *q)
745 {
746 	struct blk_mq_hw_ctx *hctx;
747 	int i;
748 
749 	if (!q->debugfs_dir)
750 		return -ENOENT;
751 
752 	q->mq_debugfs_dir = debugfs_create_dir("mq", q->debugfs_dir);
753 	if (!q->mq_debugfs_dir)
754 		goto err;
755 
756 	queue_for_each_hw_ctx(q, hctx, i) {
757 		if (blk_mq_debugfs_register_hctx(q, hctx))
758 			goto err;
759 	}
760 
761 	return 0;
762 
763 err:
764 	blk_mq_debugfs_unregister_hctxs(q);
765 	return -ENOMEM;
766 }
767 
768 void blk_mq_debugfs_unregister_hctxs(struct request_queue *q)
769 {
770 	debugfs_remove_recursive(q->mq_debugfs_dir);
771 	q->mq_debugfs_dir = NULL;
772 }
773