107e4feadSOmar Sandoval /* 207e4feadSOmar Sandoval * Copyright (C) 2017 Facebook 307e4feadSOmar Sandoval * 407e4feadSOmar Sandoval * This program is free software; you can redistribute it and/or 507e4feadSOmar Sandoval * modify it under the terms of the GNU General Public 607e4feadSOmar Sandoval * License v2 as published by the Free Software Foundation. 707e4feadSOmar Sandoval * 807e4feadSOmar Sandoval * This program is distributed in the hope that it will be useful, 907e4feadSOmar Sandoval * but WITHOUT ANY WARRANTY; without even the implied warranty of 1007e4feadSOmar Sandoval * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1107e4feadSOmar Sandoval * General Public License for more details. 1207e4feadSOmar Sandoval * 1307e4feadSOmar Sandoval * You should have received a copy of the GNU General Public License 1407e4feadSOmar Sandoval * along with this program. If not, see <https://www.gnu.org/licenses/>. 1507e4feadSOmar Sandoval */ 1607e4feadSOmar Sandoval 1707e4feadSOmar Sandoval #include <linux/kernel.h> 1807e4feadSOmar Sandoval #include <linux/blkdev.h> 1907e4feadSOmar Sandoval #include <linux/debugfs.h> 2007e4feadSOmar Sandoval 2107e4feadSOmar Sandoval #include <linux/blk-mq.h> 2218fbda91SOmar Sandoval #include "blk.h" 2307e4feadSOmar Sandoval #include "blk-mq.h" 24d173a251SOmar Sandoval #include "blk-mq-debugfs.h" 25d96b37c0SOmar Sandoval #include "blk-mq-tag.h" 26cc56694fSMing Lei #include "blk-rq-qos.h" 2707e4feadSOmar Sandoval 281209cb7fSBart Van Assche static void print_stat(struct seq_file *m, struct blk_rq_stat *stat) 291209cb7fSBart Van Assche { 301209cb7fSBart Van Assche if (stat->nr_samples) { 311209cb7fSBart Van Assche seq_printf(m, "samples=%d, mean=%lld, min=%llu, max=%llu", 321209cb7fSBart Van Assche stat->nr_samples, stat->mean, stat->min, stat->max); 331209cb7fSBart Van Assche } else { 341209cb7fSBart Van Assche seq_puts(m, "samples=0"); 351209cb7fSBart Van Assche } 361209cb7fSBart Van Assche } 371209cb7fSBart Van Assche 381209cb7fSBart Van Assche static int queue_poll_stat_show(void *data, struct seq_file *m) 391209cb7fSBart Van Assche { 401209cb7fSBart Van Assche struct request_queue *q = data; 411209cb7fSBart Van Assche int bucket; 421209cb7fSBart Van Assche 431209cb7fSBart Van Assche for (bucket = 0; bucket < BLK_MQ_POLL_STATS_BKTS/2; bucket++) { 441209cb7fSBart Van Assche seq_printf(m, "read (%d Bytes): ", 1 << (9+bucket)); 451209cb7fSBart Van Assche print_stat(m, &q->poll_stat[2*bucket]); 461209cb7fSBart Van Assche seq_puts(m, "\n"); 471209cb7fSBart Van Assche 481209cb7fSBart Van Assche seq_printf(m, "write (%d Bytes): ", 1 << (9+bucket)); 491209cb7fSBart Van Assche print_stat(m, &q->poll_stat[2*bucket+1]); 501209cb7fSBart Van Assche seq_puts(m, "\n"); 511209cb7fSBart Van Assche } 521209cb7fSBart Van Assche return 0; 531209cb7fSBart Van Assche } 541209cb7fSBart Van Assche 551209cb7fSBart Van Assche static void *queue_requeue_list_start(struct seq_file *m, loff_t *pos) 561209cb7fSBart Van Assche __acquires(&q->requeue_lock) 571209cb7fSBart Van Assche { 581209cb7fSBart Van Assche struct request_queue *q = m->private; 591209cb7fSBart Van Assche 601209cb7fSBart Van Assche spin_lock_irq(&q->requeue_lock); 611209cb7fSBart Van Assche return seq_list_start(&q->requeue_list, *pos); 621209cb7fSBart Van Assche } 631209cb7fSBart Van Assche 641209cb7fSBart Van Assche static void *queue_requeue_list_next(struct seq_file *m, void *v, loff_t *pos) 651209cb7fSBart Van Assche { 661209cb7fSBart Van Assche struct request_queue *q = m->private; 671209cb7fSBart Van Assche 681209cb7fSBart Van Assche return seq_list_next(v, &q->requeue_list, pos); 691209cb7fSBart Van Assche } 701209cb7fSBart Van Assche 711209cb7fSBart Van Assche static void queue_requeue_list_stop(struct seq_file *m, void *v) 721209cb7fSBart Van Assche __releases(&q->requeue_lock) 731209cb7fSBart Van Assche { 741209cb7fSBart Van Assche struct request_queue *q = m->private; 751209cb7fSBart Van Assche 761209cb7fSBart Van Assche spin_unlock_irq(&q->requeue_lock); 771209cb7fSBart Van Assche } 781209cb7fSBart Van Assche 791209cb7fSBart Van Assche static const struct seq_operations queue_requeue_list_seq_ops = { 801209cb7fSBart Van Assche .start = queue_requeue_list_start, 811209cb7fSBart Van Assche .next = queue_requeue_list_next, 821209cb7fSBart Van Assche .stop = queue_requeue_list_stop, 831209cb7fSBart Van Assche .show = blk_mq_debugfs_rq_show, 841209cb7fSBart Van Assche }; 851209cb7fSBart Van Assche 8691d68905SBart Van Assche static int blk_flags_show(struct seq_file *m, const unsigned long flags, 8791d68905SBart Van Assche const char *const *flag_name, int flag_name_count) 8891d68905SBart Van Assche { 8991d68905SBart Van Assche bool sep = false; 9091d68905SBart Van Assche int i; 9191d68905SBart Van Assche 9291d68905SBart Van Assche for (i = 0; i < sizeof(flags) * BITS_PER_BYTE; i++) { 9391d68905SBart Van Assche if (!(flags & BIT(i))) 9491d68905SBart Van Assche continue; 9591d68905SBart Van Assche if (sep) 96bec03d6bSOmar Sandoval seq_puts(m, "|"); 9791d68905SBart Van Assche sep = true; 9891d68905SBart Van Assche if (i < flag_name_count && flag_name[i]) 9991d68905SBart Van Assche seq_puts(m, flag_name[i]); 10091d68905SBart Van Assche else 10191d68905SBart Van Assche seq_printf(m, "%d", i); 10291d68905SBart Van Assche } 10391d68905SBart Van Assche return 0; 10491d68905SBart Van Assche } 10591d68905SBart Van Assche 106cd84a62eSBart Van Assche static int queue_pm_only_show(void *data, struct seq_file *m) 107cd84a62eSBart Van Assche { 108cd84a62eSBart Van Assche struct request_queue *q = data; 109cd84a62eSBart Van Assche 110cd84a62eSBart Van Assche seq_printf(m, "%d\n", atomic_read(&q->pm_only)); 111cd84a62eSBart Van Assche return 0; 112cd84a62eSBart Van Assche } 113cd84a62eSBart Van Assche 1141a435111SOmar Sandoval #define QUEUE_FLAG_NAME(name) [QUEUE_FLAG_##name] = #name 11591d68905SBart Van Assche static const char *const blk_queue_flag_name[] = { 1161a435111SOmar Sandoval QUEUE_FLAG_NAME(STOPPED), 1171a435111SOmar Sandoval QUEUE_FLAG_NAME(DYING), 1181a435111SOmar Sandoval QUEUE_FLAG_NAME(BIDI), 1191a435111SOmar Sandoval QUEUE_FLAG_NAME(NOMERGES), 1201a435111SOmar Sandoval QUEUE_FLAG_NAME(SAME_COMP), 1211a435111SOmar Sandoval QUEUE_FLAG_NAME(FAIL_IO), 1221a435111SOmar Sandoval QUEUE_FLAG_NAME(NONROT), 1231a435111SOmar Sandoval QUEUE_FLAG_NAME(IO_STAT), 1241a435111SOmar Sandoval QUEUE_FLAG_NAME(DISCARD), 1251a435111SOmar Sandoval QUEUE_FLAG_NAME(NOXMERGES), 1261a435111SOmar Sandoval QUEUE_FLAG_NAME(ADD_RANDOM), 1271a435111SOmar Sandoval QUEUE_FLAG_NAME(SECERASE), 1281a435111SOmar Sandoval QUEUE_FLAG_NAME(SAME_FORCE), 1291a435111SOmar Sandoval QUEUE_FLAG_NAME(DEAD), 1301a435111SOmar Sandoval QUEUE_FLAG_NAME(INIT_DONE), 1311a435111SOmar Sandoval QUEUE_FLAG_NAME(NO_SG_MERGE), 1321a435111SOmar Sandoval QUEUE_FLAG_NAME(POLL), 1331a435111SOmar Sandoval QUEUE_FLAG_NAME(WC), 1341a435111SOmar Sandoval QUEUE_FLAG_NAME(FUA), 1351a435111SOmar Sandoval QUEUE_FLAG_NAME(FLUSH_NQ), 1361a435111SOmar Sandoval QUEUE_FLAG_NAME(DAX), 1371a435111SOmar Sandoval QUEUE_FLAG_NAME(STATS), 1381a435111SOmar Sandoval QUEUE_FLAG_NAME(POLL_STATS), 1391a435111SOmar Sandoval QUEUE_FLAG_NAME(REGISTERED), 14022d53821SBart Van Assche QUEUE_FLAG_NAME(SCSI_PASSTHROUGH), 14122d53821SBart Van Assche QUEUE_FLAG_NAME(QUIESCED), 14291d68905SBart Van Assche }; 1431a435111SOmar Sandoval #undef QUEUE_FLAG_NAME 14491d68905SBart Van Assche 145f57de23aSOmar Sandoval static int queue_state_show(void *data, struct seq_file *m) 14691d68905SBart Van Assche { 147f57de23aSOmar Sandoval struct request_queue *q = data; 14891d68905SBart Van Assche 14991d68905SBart Van Assche blk_flags_show(m, q->queue_flags, blk_queue_flag_name, 15091d68905SBart Van Assche ARRAY_SIZE(blk_queue_flag_name)); 151fd07dc81SBart Van Assche seq_puts(m, "\n"); 15291d68905SBart Van Assche return 0; 15391d68905SBart Van Assche } 15491d68905SBart Van Assche 155f57de23aSOmar Sandoval static ssize_t queue_state_write(void *data, const char __user *buf, 156c7e4145aSOmar Sandoval size_t count, loff_t *ppos) 15791d68905SBart Van Assche { 158f57de23aSOmar Sandoval struct request_queue *q = data; 15971b90511SOmar Sandoval char opbuf[16] = { }, *op; 16091d68905SBart Van Assche 16118d4d7d0SBart Van Assche /* 16218d4d7d0SBart Van Assche * The "state" attribute is removed after blk_cleanup_queue() has called 16318d4d7d0SBart Van Assche * blk_mq_free_queue(). Return if QUEUE_FLAG_DEAD has been set to avoid 16418d4d7d0SBart Van Assche * triggering a use-after-free. 16518d4d7d0SBart Van Assche */ 16618d4d7d0SBart Van Assche if (blk_queue_dead(q)) 16718d4d7d0SBart Van Assche return -ENOENT; 16818d4d7d0SBart Van Assche 16971b90511SOmar Sandoval if (count >= sizeof(opbuf)) { 170c7e4145aSOmar Sandoval pr_err("%s: operation too long\n", __func__); 171c7e4145aSOmar Sandoval goto inval; 172c7e4145aSOmar Sandoval } 173c7e4145aSOmar Sandoval 17471b90511SOmar Sandoval if (copy_from_user(opbuf, buf, count)) 17591d68905SBart Van Assche return -EFAULT; 17671b90511SOmar Sandoval op = strstrip(opbuf); 17791d68905SBart Van Assche if (strcmp(op, "run") == 0) { 17891d68905SBart Van Assche blk_mq_run_hw_queues(q, true); 17991d68905SBart Van Assche } else if (strcmp(op, "start") == 0) { 18091d68905SBart Van Assche blk_mq_start_stopped_hw_queues(q, true); 181edea55abSBart Van Assche } else if (strcmp(op, "kick") == 0) { 182edea55abSBart Van Assche blk_mq_kick_requeue_list(q); 18391d68905SBart Van Assche } else { 184c7e4145aSOmar Sandoval pr_err("%s: unsupported operation '%s'\n", __func__, op); 185c7e4145aSOmar Sandoval inval: 186edea55abSBart Van Assche pr_err("%s: use 'run', 'start' or 'kick'\n", __func__); 18791d68905SBart Van Assche return -EINVAL; 18891d68905SBart Van Assche } 189c7e4145aSOmar Sandoval return count; 19091d68905SBart Van Assche } 19191d68905SBart Van Assche 192f793dfd3SJens Axboe static int queue_write_hint_show(void *data, struct seq_file *m) 193f793dfd3SJens Axboe { 194f793dfd3SJens Axboe struct request_queue *q = data; 195f793dfd3SJens Axboe int i; 196f793dfd3SJens Axboe 197f793dfd3SJens Axboe for (i = 0; i < BLK_MAX_WRITE_HINTS; i++) 198f793dfd3SJens Axboe seq_printf(m, "hint%d: %llu\n", i, q->write_hints[i]); 199f793dfd3SJens Axboe 200f793dfd3SJens Axboe return 0; 201f793dfd3SJens Axboe } 202f793dfd3SJens Axboe 203f793dfd3SJens Axboe static ssize_t queue_write_hint_store(void *data, const char __user *buf, 204f793dfd3SJens Axboe size_t count, loff_t *ppos) 205f793dfd3SJens Axboe { 206f793dfd3SJens Axboe struct request_queue *q = data; 207f793dfd3SJens Axboe int i; 208f793dfd3SJens Axboe 209f793dfd3SJens Axboe for (i = 0; i < BLK_MAX_WRITE_HINTS; i++) 210f793dfd3SJens Axboe q->write_hints[i] = 0; 211f793dfd3SJens Axboe 212f793dfd3SJens Axboe return count; 213f793dfd3SJens Axboe } 214f793dfd3SJens Axboe 2151209cb7fSBart Van Assche static const struct blk_mq_debugfs_attr blk_mq_debugfs_queue_attrs[] = { 2161209cb7fSBart Van Assche { "poll_stat", 0400, queue_poll_stat_show }, 2171209cb7fSBart Van Assche { "requeue_list", 0400, .seq_ops = &queue_requeue_list_seq_ops }, 218cd84a62eSBart Van Assche { "pm_only", 0600, queue_pm_only_show, NULL }, 2191209cb7fSBart Van Assche { "state", 0600, queue_state_show, queue_state_write }, 2201209cb7fSBart Van Assche { "write_hints", 0600, queue_write_hint_show, queue_write_hint_store }, 22118bc4230SBart Van Assche { "zone_wlock", 0400, queue_zone_wlock_show, NULL }, 2221209cb7fSBart Van Assche { }, 2231209cb7fSBart Van Assche }; 22434dbad5dSOmar Sandoval 2251a435111SOmar Sandoval #define HCTX_STATE_NAME(name) [BLK_MQ_S_##name] = #name 226f5c0b091SBart Van Assche static const char *const hctx_state_name[] = { 2271a435111SOmar Sandoval HCTX_STATE_NAME(STOPPED), 2281a435111SOmar Sandoval HCTX_STATE_NAME(TAG_ACTIVE), 2291a435111SOmar Sandoval HCTX_STATE_NAME(SCHED_RESTART), 230f5c0b091SBart Van Assche }; 2311a435111SOmar Sandoval #undef HCTX_STATE_NAME 2321a435111SOmar Sandoval 233f57de23aSOmar Sandoval static int hctx_state_show(void *data, struct seq_file *m) 2349abb2ad2SOmar Sandoval { 235f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 2369abb2ad2SOmar Sandoval 237f5c0b091SBart Van Assche blk_flags_show(m, hctx->state, hctx_state_name, 238f5c0b091SBart Van Assche ARRAY_SIZE(hctx_state_name)); 239fd07dc81SBart Van Assche seq_puts(m, "\n"); 2409abb2ad2SOmar Sandoval return 0; 2419abb2ad2SOmar Sandoval } 2429abb2ad2SOmar Sandoval 2431a435111SOmar Sandoval #define BLK_TAG_ALLOC_NAME(name) [BLK_TAG_ALLOC_##name] = #name 244f5c0b091SBart Van Assche static const char *const alloc_policy_name[] = { 2451a435111SOmar Sandoval BLK_TAG_ALLOC_NAME(FIFO), 2461a435111SOmar Sandoval BLK_TAG_ALLOC_NAME(RR), 247f5c0b091SBart Van Assche }; 2481a435111SOmar Sandoval #undef BLK_TAG_ALLOC_NAME 249f5c0b091SBart Van Assche 2501a435111SOmar Sandoval #define HCTX_FLAG_NAME(name) [ilog2(BLK_MQ_F_##name)] = #name 251f5c0b091SBart Van Assche static const char *const hctx_flag_name[] = { 2521a435111SOmar Sandoval HCTX_FLAG_NAME(SHOULD_MERGE), 2531a435111SOmar Sandoval HCTX_FLAG_NAME(TAG_SHARED), 2541a435111SOmar Sandoval HCTX_FLAG_NAME(SG_MERGE), 2551a435111SOmar Sandoval HCTX_FLAG_NAME(BLOCKING), 2561a435111SOmar Sandoval HCTX_FLAG_NAME(NO_SCHED), 257f5c0b091SBart Van Assche }; 2581a435111SOmar Sandoval #undef HCTX_FLAG_NAME 259f5c0b091SBart Van Assche 260f57de23aSOmar Sandoval static int hctx_flags_show(void *data, struct seq_file *m) 2619abb2ad2SOmar Sandoval { 262f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 263f5c0b091SBart Van Assche const int alloc_policy = BLK_MQ_FLAG_TO_ALLOC_POLICY(hctx->flags); 2649abb2ad2SOmar Sandoval 265f5c0b091SBart Van Assche seq_puts(m, "alloc_policy="); 266f5c0b091SBart Van Assche if (alloc_policy < ARRAY_SIZE(alloc_policy_name) && 267f5c0b091SBart Van Assche alloc_policy_name[alloc_policy]) 268f5c0b091SBart Van Assche seq_puts(m, alloc_policy_name[alloc_policy]); 269f5c0b091SBart Van Assche else 270f5c0b091SBart Van Assche seq_printf(m, "%d", alloc_policy); 271f5c0b091SBart Van Assche seq_puts(m, " "); 272f5c0b091SBart Van Assche blk_flags_show(m, 273f5c0b091SBart Van Assche hctx->flags ^ BLK_ALLOC_POLICY_TO_MQ_FLAG(alloc_policy), 274f5c0b091SBart Van Assche hctx_flag_name, ARRAY_SIZE(hctx_flag_name)); 275fd07dc81SBart Van Assche seq_puts(m, "\n"); 2769abb2ad2SOmar Sandoval return 0; 2779abb2ad2SOmar Sandoval } 2789abb2ad2SOmar Sandoval 2791a435111SOmar Sandoval #define REQ_OP_NAME(name) [REQ_OP_##name] = #name 2808658dca8SBart Van Assche static const char *const op_name[] = { 2811a435111SOmar Sandoval REQ_OP_NAME(READ), 2821a435111SOmar Sandoval REQ_OP_NAME(WRITE), 2831a435111SOmar Sandoval REQ_OP_NAME(FLUSH), 2841a435111SOmar Sandoval REQ_OP_NAME(DISCARD), 2851a435111SOmar Sandoval REQ_OP_NAME(SECURE_ERASE), 2861a435111SOmar Sandoval REQ_OP_NAME(ZONE_RESET), 2871a435111SOmar Sandoval REQ_OP_NAME(WRITE_SAME), 2881a435111SOmar Sandoval REQ_OP_NAME(WRITE_ZEROES), 2891a435111SOmar Sandoval REQ_OP_NAME(SCSI_IN), 2901a435111SOmar Sandoval REQ_OP_NAME(SCSI_OUT), 2911a435111SOmar Sandoval REQ_OP_NAME(DRV_IN), 2921a435111SOmar Sandoval REQ_OP_NAME(DRV_OUT), 2938658dca8SBart Van Assche }; 2941a435111SOmar Sandoval #undef REQ_OP_NAME 2958658dca8SBart Van Assche 2961a435111SOmar Sandoval #define CMD_FLAG_NAME(name) [__REQ_##name] = #name 2978658dca8SBart Van Assche static const char *const cmd_flag_name[] = { 2981a435111SOmar Sandoval CMD_FLAG_NAME(FAILFAST_DEV), 2991a435111SOmar Sandoval CMD_FLAG_NAME(FAILFAST_TRANSPORT), 3001a435111SOmar Sandoval CMD_FLAG_NAME(FAILFAST_DRIVER), 3011a435111SOmar Sandoval CMD_FLAG_NAME(SYNC), 3021a435111SOmar Sandoval CMD_FLAG_NAME(META), 3031a435111SOmar Sandoval CMD_FLAG_NAME(PRIO), 3041a435111SOmar Sandoval CMD_FLAG_NAME(NOMERGE), 3051a435111SOmar Sandoval CMD_FLAG_NAME(IDLE), 3061a435111SOmar Sandoval CMD_FLAG_NAME(INTEGRITY), 3071a435111SOmar Sandoval CMD_FLAG_NAME(FUA), 3081a435111SOmar Sandoval CMD_FLAG_NAME(PREFLUSH), 3091a435111SOmar Sandoval CMD_FLAG_NAME(RAHEAD), 3101a435111SOmar Sandoval CMD_FLAG_NAME(BACKGROUND), 3111a435111SOmar Sandoval CMD_FLAG_NAME(NOUNMAP), 31222d53821SBart Van Assche CMD_FLAG_NAME(NOWAIT), 3138658dca8SBart Van Assche }; 3141a435111SOmar Sandoval #undef CMD_FLAG_NAME 3158658dca8SBart Van Assche 3161a435111SOmar Sandoval #define RQF_NAME(name) [ilog2((__force u32)RQF_##name)] = #name 3178658dca8SBart Van Assche static const char *const rqf_name[] = { 3181a435111SOmar Sandoval RQF_NAME(SORTED), 31985ba3effSJens Axboe RQF_NAME(STARTED), 3201a435111SOmar Sandoval RQF_NAME(SOFTBARRIER), 3211a435111SOmar Sandoval RQF_NAME(FLUSH_SEQ), 3221a435111SOmar Sandoval RQF_NAME(MIXED_MERGE), 3231a435111SOmar Sandoval RQF_NAME(MQ_INFLIGHT), 3241a435111SOmar Sandoval RQF_NAME(DONTPREP), 3251a435111SOmar Sandoval RQF_NAME(PREEMPT), 3261a435111SOmar Sandoval RQF_NAME(COPY_USER), 3271a435111SOmar Sandoval RQF_NAME(FAILED), 3281a435111SOmar Sandoval RQF_NAME(QUIET), 3291a435111SOmar Sandoval RQF_NAME(ELVPRIV), 3301a435111SOmar Sandoval RQF_NAME(IO_STAT), 3311a435111SOmar Sandoval RQF_NAME(ALLOCED), 3321a435111SOmar Sandoval RQF_NAME(PM), 3331a435111SOmar Sandoval RQF_NAME(HASHED), 3341a435111SOmar Sandoval RQF_NAME(STATS), 3351a435111SOmar Sandoval RQF_NAME(SPECIAL_PAYLOAD), 3365d75d3f2SJens Axboe RQF_NAME(ZONE_WRITE_LOCKED), 33776a86f9dSJens Axboe RQF_NAME(MQ_POLL_SLEPT), 3388658dca8SBart Van Assche }; 3391a435111SOmar Sandoval #undef RQF_NAME 3408658dca8SBart Van Assche 341ec6dcf63SBart Van Assche static const char *const blk_mq_rq_state_name_array[] = { 342ec6dcf63SBart Van Assche [MQ_RQ_IDLE] = "idle", 343ec6dcf63SBart Van Assche [MQ_RQ_IN_FLIGHT] = "in_flight", 344ec6dcf63SBart Van Assche [MQ_RQ_COMPLETE] = "complete", 345ec6dcf63SBart Van Assche }; 346ec6dcf63SBart Van Assche 347ec6dcf63SBart Van Assche static const char *blk_mq_rq_state_name(enum mq_rq_state rq_state) 348ec6dcf63SBart Van Assche { 349a1e79188SDan Carpenter if (WARN_ON_ONCE((unsigned int)rq_state >= 350ec6dcf63SBart Van Assche ARRAY_SIZE(blk_mq_rq_state_name_array))) 351ec6dcf63SBart Van Assche return "(?)"; 352ec6dcf63SBart Van Assche return blk_mq_rq_state_name_array[rq_state]; 353ec6dcf63SBart Van Assche } 354ec6dcf63SBart Van Assche 355daaadb3eSOmar Sandoval int __blk_mq_debugfs_rq_show(struct seq_file *m, struct request *rq) 356950cd7e9SOmar Sandoval { 3572836ee4bSBart Van Assche const struct blk_mq_ops *const mq_ops = rq->q->mq_ops; 3588658dca8SBart Van Assche const unsigned int op = rq->cmd_flags & REQ_OP_MASK; 359950cd7e9SOmar Sandoval 3608658dca8SBart Van Assche seq_printf(m, "%p {.op=", rq); 3618658dca8SBart Van Assche if (op < ARRAY_SIZE(op_name) && op_name[op]) 3628658dca8SBart Van Assche seq_printf(m, "%s", op_name[op]); 3638658dca8SBart Van Assche else 3648658dca8SBart Van Assche seq_printf(m, "%d", op); 3658658dca8SBart Van Assche seq_puts(m, ", .cmd_flags="); 3668658dca8SBart Van Assche blk_flags_show(m, rq->cmd_flags & ~REQ_OP_MASK, cmd_flag_name, 3678658dca8SBart Van Assche ARRAY_SIZE(cmd_flag_name)); 3688658dca8SBart Van Assche seq_puts(m, ", .rq_flags="); 3698658dca8SBart Van Assche blk_flags_show(m, (__force unsigned int)rq->rq_flags, rqf_name, 3708658dca8SBart Van Assche ARRAY_SIZE(rqf_name)); 371ec6dcf63SBart Van Assche seq_printf(m, ", .state=%s", blk_mq_rq_state_name(blk_mq_rq_state(rq))); 3722836ee4bSBart Van Assche seq_printf(m, ", .tag=%d, .internal_tag=%d", rq->tag, 3738658dca8SBart Van Assche rq->internal_tag); 3742836ee4bSBart Van Assche if (mq_ops->show_rq) 3752836ee4bSBart Van Assche mq_ops->show_rq(m, rq); 3762836ee4bSBart Van Assche seq_puts(m, "}\n"); 377950cd7e9SOmar Sandoval return 0; 378950cd7e9SOmar Sandoval } 379daaadb3eSOmar Sandoval EXPORT_SYMBOL_GPL(__blk_mq_debugfs_rq_show); 380daaadb3eSOmar Sandoval 381daaadb3eSOmar Sandoval int blk_mq_debugfs_rq_show(struct seq_file *m, void *v) 382daaadb3eSOmar Sandoval { 383daaadb3eSOmar Sandoval return __blk_mq_debugfs_rq_show(m, list_entry_rq(v)); 384daaadb3eSOmar Sandoval } 38516b738f6SOmar Sandoval EXPORT_SYMBOL_GPL(blk_mq_debugfs_rq_show); 386950cd7e9SOmar Sandoval 387950cd7e9SOmar Sandoval static void *hctx_dispatch_start(struct seq_file *m, loff_t *pos) 388f3bcb0e6SBart Van Assche __acquires(&hctx->lock) 389950cd7e9SOmar Sandoval { 390950cd7e9SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 391950cd7e9SOmar Sandoval 392950cd7e9SOmar Sandoval spin_lock(&hctx->lock); 393950cd7e9SOmar Sandoval return seq_list_start(&hctx->dispatch, *pos); 394950cd7e9SOmar Sandoval } 395950cd7e9SOmar Sandoval 396950cd7e9SOmar Sandoval static void *hctx_dispatch_next(struct seq_file *m, void *v, loff_t *pos) 397950cd7e9SOmar Sandoval { 398950cd7e9SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 399950cd7e9SOmar Sandoval 400950cd7e9SOmar Sandoval return seq_list_next(v, &hctx->dispatch, pos); 401950cd7e9SOmar Sandoval } 402950cd7e9SOmar Sandoval 403950cd7e9SOmar Sandoval static void hctx_dispatch_stop(struct seq_file *m, void *v) 404f3bcb0e6SBart Van Assche __releases(&hctx->lock) 405950cd7e9SOmar Sandoval { 406950cd7e9SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 407950cd7e9SOmar Sandoval 408950cd7e9SOmar Sandoval spin_unlock(&hctx->lock); 409950cd7e9SOmar Sandoval } 410950cd7e9SOmar Sandoval 411950cd7e9SOmar Sandoval static const struct seq_operations hctx_dispatch_seq_ops = { 412950cd7e9SOmar Sandoval .start = hctx_dispatch_start, 413950cd7e9SOmar Sandoval .next = hctx_dispatch_next, 414950cd7e9SOmar Sandoval .stop = hctx_dispatch_stop, 415950cd7e9SOmar Sandoval .show = blk_mq_debugfs_rq_show, 416950cd7e9SOmar Sandoval }; 417950cd7e9SOmar Sandoval 4182720bab5SBart Van Assche struct show_busy_params { 4192720bab5SBart Van Assche struct seq_file *m; 4202720bab5SBart Van Assche struct blk_mq_hw_ctx *hctx; 4212720bab5SBart Van Assche }; 4222720bab5SBart Van Assche 4232720bab5SBart Van Assche /* 4242720bab5SBart Van Assche * Note: the state of a request may change while this function is in progress, 4257baa8572SJens Axboe * e.g. due to a concurrent blk_mq_finish_request() call. Returns true to 4267baa8572SJens Axboe * keep iterating requests. 4272720bab5SBart Van Assche */ 4287baa8572SJens Axboe static bool hctx_show_busy_rq(struct request *rq, void *data, bool reserved) 4292720bab5SBart Van Assche { 4302720bab5SBart Van Assche const struct show_busy_params *params = data; 4312720bab5SBart Van Assche 432ea4f995eSJens Axboe if (rq->mq_hctx == params->hctx) 4332720bab5SBart Van Assche __blk_mq_debugfs_rq_show(params->m, 4342720bab5SBart Van Assche list_entry_rq(&rq->queuelist)); 4357baa8572SJens Axboe 4367baa8572SJens Axboe return true; 4372720bab5SBart Van Assche } 4382720bab5SBart Van Assche 4392720bab5SBart Van Assche static int hctx_busy_show(void *data, struct seq_file *m) 4402720bab5SBart Van Assche { 4412720bab5SBart Van Assche struct blk_mq_hw_ctx *hctx = data; 4422720bab5SBart Van Assche struct show_busy_params params = { .m = m, .hctx = hctx }; 4432720bab5SBart Van Assche 4442720bab5SBart Van Assche blk_mq_tagset_busy_iter(hctx->queue->tag_set, hctx_show_busy_rq, 4452720bab5SBart Van Assche ¶ms); 4462720bab5SBart Van Assche 4472720bab5SBart Van Assche return 0; 4482720bab5SBart Van Assche } 4492720bab5SBart Van Assche 450346fc108SMing Lei static const char *const hctx_types[] = { 451346fc108SMing Lei [HCTX_TYPE_DEFAULT] = "default", 452346fc108SMing Lei [HCTX_TYPE_READ] = "read", 453346fc108SMing Lei [HCTX_TYPE_POLL] = "poll", 454346fc108SMing Lei }; 455346fc108SMing Lei 456346fc108SMing Lei static int hctx_type_show(void *data, struct seq_file *m) 457346fc108SMing Lei { 458346fc108SMing Lei struct blk_mq_hw_ctx *hctx = data; 459346fc108SMing Lei 460346fc108SMing Lei BUILD_BUG_ON(ARRAY_SIZE(hctx_types) != HCTX_MAX_TYPES); 461346fc108SMing Lei seq_printf(m, "%s\n", hctx_types[hctx->type]); 462346fc108SMing Lei return 0; 463346fc108SMing Lei } 464346fc108SMing Lei 465f57de23aSOmar Sandoval static int hctx_ctx_map_show(void *data, struct seq_file *m) 466950cd7e9SOmar Sandoval { 467f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 4680bfa5288SOmar Sandoval 4690bfa5288SOmar Sandoval sbitmap_bitmap_show(&hctx->ctx_map, m); 4700bfa5288SOmar Sandoval return 0; 4710bfa5288SOmar Sandoval } 4720bfa5288SOmar Sandoval 473d96b37c0SOmar Sandoval static void blk_mq_debugfs_tags_show(struct seq_file *m, 474d96b37c0SOmar Sandoval struct blk_mq_tags *tags) 475d96b37c0SOmar Sandoval { 476d96b37c0SOmar Sandoval seq_printf(m, "nr_tags=%u\n", tags->nr_tags); 477d96b37c0SOmar Sandoval seq_printf(m, "nr_reserved_tags=%u\n", tags->nr_reserved_tags); 478d96b37c0SOmar Sandoval seq_printf(m, "active_queues=%d\n", 479d96b37c0SOmar Sandoval atomic_read(&tags->active_queues)); 480d96b37c0SOmar Sandoval 481d96b37c0SOmar Sandoval seq_puts(m, "\nbitmap_tags:\n"); 482d96b37c0SOmar Sandoval sbitmap_queue_show(&tags->bitmap_tags, m); 483d96b37c0SOmar Sandoval 484d96b37c0SOmar Sandoval if (tags->nr_reserved_tags) { 485d96b37c0SOmar Sandoval seq_puts(m, "\nbreserved_tags:\n"); 486d96b37c0SOmar Sandoval sbitmap_queue_show(&tags->breserved_tags, m); 487d96b37c0SOmar Sandoval } 488d96b37c0SOmar Sandoval } 489d96b37c0SOmar Sandoval 490f57de23aSOmar Sandoval static int hctx_tags_show(void *data, struct seq_file *m) 491d96b37c0SOmar Sandoval { 492f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 493d96b37c0SOmar Sandoval struct request_queue *q = hctx->queue; 4948c0f14eaSBart Van Assche int res; 495d96b37c0SOmar Sandoval 4968c0f14eaSBart Van Assche res = mutex_lock_interruptible(&q->sysfs_lock); 4978c0f14eaSBart Van Assche if (res) 4988c0f14eaSBart Van Assche goto out; 499d96b37c0SOmar Sandoval if (hctx->tags) 500d96b37c0SOmar Sandoval blk_mq_debugfs_tags_show(m, hctx->tags); 501d96b37c0SOmar Sandoval mutex_unlock(&q->sysfs_lock); 502d96b37c0SOmar Sandoval 5038c0f14eaSBart Van Assche out: 5048c0f14eaSBart Van Assche return res; 505d96b37c0SOmar Sandoval } 506d96b37c0SOmar Sandoval 507f57de23aSOmar Sandoval static int hctx_tags_bitmap_show(void *data, struct seq_file *m) 508d96b37c0SOmar Sandoval { 509f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 510d7e3621aSOmar Sandoval struct request_queue *q = hctx->queue; 5118c0f14eaSBart Van Assche int res; 512d7e3621aSOmar Sandoval 5138c0f14eaSBart Van Assche res = mutex_lock_interruptible(&q->sysfs_lock); 5148c0f14eaSBart Van Assche if (res) 5158c0f14eaSBart Van Assche goto out; 516d7e3621aSOmar Sandoval if (hctx->tags) 517d7e3621aSOmar Sandoval sbitmap_bitmap_show(&hctx->tags->bitmap_tags.sb, m); 518d7e3621aSOmar Sandoval mutex_unlock(&q->sysfs_lock); 5198c0f14eaSBart Van Assche 5208c0f14eaSBart Van Assche out: 5218c0f14eaSBart Van Assche return res; 522d7e3621aSOmar Sandoval } 523d7e3621aSOmar Sandoval 524f57de23aSOmar Sandoval static int hctx_sched_tags_show(void *data, struct seq_file *m) 525d7e3621aSOmar Sandoval { 526f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 527d96b37c0SOmar Sandoval struct request_queue *q = hctx->queue; 5288c0f14eaSBart Van Assche int res; 529d96b37c0SOmar Sandoval 5308c0f14eaSBart Van Assche res = mutex_lock_interruptible(&q->sysfs_lock); 5318c0f14eaSBart Van Assche if (res) 5328c0f14eaSBart Van Assche goto out; 533d96b37c0SOmar Sandoval if (hctx->sched_tags) 534d96b37c0SOmar Sandoval blk_mq_debugfs_tags_show(m, hctx->sched_tags); 535d96b37c0SOmar Sandoval mutex_unlock(&q->sysfs_lock); 536d96b37c0SOmar Sandoval 5378c0f14eaSBart Van Assche out: 5388c0f14eaSBart Van Assche return res; 539d96b37c0SOmar Sandoval } 540d96b37c0SOmar Sandoval 541f57de23aSOmar Sandoval static int hctx_sched_tags_bitmap_show(void *data, struct seq_file *m) 542d96b37c0SOmar Sandoval { 543f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 544d7e3621aSOmar Sandoval struct request_queue *q = hctx->queue; 5458c0f14eaSBart Van Assche int res; 546d7e3621aSOmar Sandoval 5478c0f14eaSBart Van Assche res = mutex_lock_interruptible(&q->sysfs_lock); 5488c0f14eaSBart Van Assche if (res) 5498c0f14eaSBart Van Assche goto out; 550d7e3621aSOmar Sandoval if (hctx->sched_tags) 551d7e3621aSOmar Sandoval sbitmap_bitmap_show(&hctx->sched_tags->bitmap_tags.sb, m); 552d7e3621aSOmar Sandoval mutex_unlock(&q->sysfs_lock); 5538c0f14eaSBart Van Assche 5548c0f14eaSBart Van Assche out: 5558c0f14eaSBart Van Assche return res; 556d7e3621aSOmar Sandoval } 557d7e3621aSOmar Sandoval 558f57de23aSOmar Sandoval static int hctx_io_poll_show(void *data, struct seq_file *m) 559d7e3621aSOmar Sandoval { 560f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 561be215473SOmar Sandoval 562be215473SOmar Sandoval seq_printf(m, "considered=%lu\n", hctx->poll_considered); 563be215473SOmar Sandoval seq_printf(m, "invoked=%lu\n", hctx->poll_invoked); 564be215473SOmar Sandoval seq_printf(m, "success=%lu\n", hctx->poll_success); 565be215473SOmar Sandoval return 0; 566be215473SOmar Sandoval } 567be215473SOmar Sandoval 568f57de23aSOmar Sandoval static ssize_t hctx_io_poll_write(void *data, const char __user *buf, 569be215473SOmar Sandoval size_t count, loff_t *ppos) 570be215473SOmar Sandoval { 571f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 572be215473SOmar Sandoval 573be215473SOmar Sandoval hctx->poll_considered = hctx->poll_invoked = hctx->poll_success = 0; 574be215473SOmar Sandoval return count; 575be215473SOmar Sandoval } 576be215473SOmar Sandoval 577f57de23aSOmar Sandoval static int hctx_dispatched_show(void *data, struct seq_file *m) 578be215473SOmar Sandoval { 579f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 580be215473SOmar Sandoval int i; 581be215473SOmar Sandoval 582be215473SOmar Sandoval seq_printf(m, "%8u\t%lu\n", 0U, hctx->dispatched[0]); 583be215473SOmar Sandoval 584be215473SOmar Sandoval for (i = 1; i < BLK_MQ_MAX_DISPATCH_ORDER - 1; i++) { 585be215473SOmar Sandoval unsigned int d = 1U << (i - 1); 586be215473SOmar Sandoval 587be215473SOmar Sandoval seq_printf(m, "%8u\t%lu\n", d, hctx->dispatched[i]); 588be215473SOmar Sandoval } 589be215473SOmar Sandoval 590be215473SOmar Sandoval seq_printf(m, "%8u+\t%lu\n", 1U << (i - 1), hctx->dispatched[i]); 591be215473SOmar Sandoval return 0; 592be215473SOmar Sandoval } 593be215473SOmar Sandoval 594f57de23aSOmar Sandoval static ssize_t hctx_dispatched_write(void *data, const char __user *buf, 595be215473SOmar Sandoval size_t count, loff_t *ppos) 596be215473SOmar Sandoval { 597f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 598be215473SOmar Sandoval int i; 599be215473SOmar Sandoval 600be215473SOmar Sandoval for (i = 0; i < BLK_MQ_MAX_DISPATCH_ORDER; i++) 601be215473SOmar Sandoval hctx->dispatched[i] = 0; 602be215473SOmar Sandoval return count; 603be215473SOmar Sandoval } 604be215473SOmar Sandoval 605f57de23aSOmar Sandoval static int hctx_queued_show(void *data, struct seq_file *m) 6064a46f05eSOmar Sandoval { 607f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 6084a46f05eSOmar Sandoval 6094a46f05eSOmar Sandoval seq_printf(m, "%lu\n", hctx->queued); 6104a46f05eSOmar Sandoval return 0; 6114a46f05eSOmar Sandoval } 6124a46f05eSOmar Sandoval 613f57de23aSOmar Sandoval static ssize_t hctx_queued_write(void *data, const char __user *buf, 6144a46f05eSOmar Sandoval size_t count, loff_t *ppos) 6154a46f05eSOmar Sandoval { 616f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 6174a46f05eSOmar Sandoval 6184a46f05eSOmar Sandoval hctx->queued = 0; 6194a46f05eSOmar Sandoval return count; 6204a46f05eSOmar Sandoval } 6214a46f05eSOmar Sandoval 622f57de23aSOmar Sandoval static int hctx_run_show(void *data, struct seq_file *m) 6234a46f05eSOmar Sandoval { 624f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 6254a46f05eSOmar Sandoval 6264a46f05eSOmar Sandoval seq_printf(m, "%lu\n", hctx->run); 6274a46f05eSOmar Sandoval return 0; 6284a46f05eSOmar Sandoval } 6294a46f05eSOmar Sandoval 630f57de23aSOmar Sandoval static ssize_t hctx_run_write(void *data, const char __user *buf, size_t count, 631f57de23aSOmar Sandoval loff_t *ppos) 6324a46f05eSOmar Sandoval { 633f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 6344a46f05eSOmar Sandoval 6354a46f05eSOmar Sandoval hctx->run = 0; 6364a46f05eSOmar Sandoval return count; 6374a46f05eSOmar Sandoval } 6384a46f05eSOmar Sandoval 639f57de23aSOmar Sandoval static int hctx_active_show(void *data, struct seq_file *m) 6404a46f05eSOmar Sandoval { 641f57de23aSOmar Sandoval struct blk_mq_hw_ctx *hctx = data; 6424a46f05eSOmar Sandoval 6434a46f05eSOmar Sandoval seq_printf(m, "%d\n", atomic_read(&hctx->nr_active)); 6444a46f05eSOmar Sandoval return 0; 6454a46f05eSOmar Sandoval } 6464a46f05eSOmar Sandoval 6476e768717SMing Lei static int hctx_dispatch_busy_show(void *data, struct seq_file *m) 6486e768717SMing Lei { 6496e768717SMing Lei struct blk_mq_hw_ctx *hctx = data; 6506e768717SMing Lei 6516e768717SMing Lei seq_printf(m, "%u\n", hctx->dispatch_busy); 6526e768717SMing Lei return 0; 6536e768717SMing Lei } 6546e768717SMing Lei 655c16d6b5aSMing Lei #define CTX_RQ_SEQ_OPS(name, type) \ 656c16d6b5aSMing Lei static void *ctx_##name##_rq_list_start(struct seq_file *m, loff_t *pos) \ 657c16d6b5aSMing Lei __acquires(&ctx->lock) \ 658c16d6b5aSMing Lei { \ 659c16d6b5aSMing Lei struct blk_mq_ctx *ctx = m->private; \ 660c16d6b5aSMing Lei \ 661c16d6b5aSMing Lei spin_lock(&ctx->lock); \ 662c16d6b5aSMing Lei return seq_list_start(&ctx->rq_lists[type], *pos); \ 663c16d6b5aSMing Lei } \ 664c16d6b5aSMing Lei \ 665c16d6b5aSMing Lei static void *ctx_##name##_rq_list_next(struct seq_file *m, void *v, \ 666c16d6b5aSMing Lei loff_t *pos) \ 667c16d6b5aSMing Lei { \ 668c16d6b5aSMing Lei struct blk_mq_ctx *ctx = m->private; \ 669c16d6b5aSMing Lei \ 670c16d6b5aSMing Lei return seq_list_next(v, &ctx->rq_lists[type], pos); \ 671c16d6b5aSMing Lei } \ 672c16d6b5aSMing Lei \ 673c16d6b5aSMing Lei static void ctx_##name##_rq_list_stop(struct seq_file *m, void *v) \ 674c16d6b5aSMing Lei __releases(&ctx->lock) \ 675c16d6b5aSMing Lei { \ 676c16d6b5aSMing Lei struct blk_mq_ctx *ctx = m->private; \ 677c16d6b5aSMing Lei \ 678c16d6b5aSMing Lei spin_unlock(&ctx->lock); \ 679c16d6b5aSMing Lei } \ 680c16d6b5aSMing Lei \ 681c16d6b5aSMing Lei static const struct seq_operations ctx_##name##_rq_list_seq_ops = { \ 682c16d6b5aSMing Lei .start = ctx_##name##_rq_list_start, \ 683c16d6b5aSMing Lei .next = ctx_##name##_rq_list_next, \ 684c16d6b5aSMing Lei .stop = ctx_##name##_rq_list_stop, \ 685c16d6b5aSMing Lei .show = blk_mq_debugfs_rq_show, \ 686950cd7e9SOmar Sandoval } 687950cd7e9SOmar Sandoval 688c16d6b5aSMing Lei CTX_RQ_SEQ_OPS(default, HCTX_TYPE_DEFAULT); 689c16d6b5aSMing Lei CTX_RQ_SEQ_OPS(read, HCTX_TYPE_READ); 690c16d6b5aSMing Lei CTX_RQ_SEQ_OPS(poll, HCTX_TYPE_POLL); 691950cd7e9SOmar Sandoval 692f57de23aSOmar Sandoval static int ctx_dispatched_show(void *data, struct seq_file *m) 693950cd7e9SOmar Sandoval { 694f57de23aSOmar Sandoval struct blk_mq_ctx *ctx = data; 6954a46f05eSOmar Sandoval 6964a46f05eSOmar Sandoval seq_printf(m, "%lu %lu\n", ctx->rq_dispatched[1], ctx->rq_dispatched[0]); 6974a46f05eSOmar Sandoval return 0; 6984a46f05eSOmar Sandoval } 6994a46f05eSOmar Sandoval 700f57de23aSOmar Sandoval static ssize_t ctx_dispatched_write(void *data, const char __user *buf, 7014a46f05eSOmar Sandoval size_t count, loff_t *ppos) 7024a46f05eSOmar Sandoval { 703f57de23aSOmar Sandoval struct blk_mq_ctx *ctx = data; 7044a46f05eSOmar Sandoval 7054a46f05eSOmar Sandoval ctx->rq_dispatched[0] = ctx->rq_dispatched[1] = 0; 7064a46f05eSOmar Sandoval return count; 7074a46f05eSOmar Sandoval } 7084a46f05eSOmar Sandoval 709f57de23aSOmar Sandoval static int ctx_merged_show(void *data, struct seq_file *m) 7104a46f05eSOmar Sandoval { 711f57de23aSOmar Sandoval struct blk_mq_ctx *ctx = data; 7124a46f05eSOmar Sandoval 7134a46f05eSOmar Sandoval seq_printf(m, "%lu\n", ctx->rq_merged); 7144a46f05eSOmar Sandoval return 0; 7154a46f05eSOmar Sandoval } 7164a46f05eSOmar Sandoval 717f57de23aSOmar Sandoval static ssize_t ctx_merged_write(void *data, const char __user *buf, 7184a46f05eSOmar Sandoval size_t count, loff_t *ppos) 7194a46f05eSOmar Sandoval { 720f57de23aSOmar Sandoval struct blk_mq_ctx *ctx = data; 7214a46f05eSOmar Sandoval 7224a46f05eSOmar Sandoval ctx->rq_merged = 0; 7234a46f05eSOmar Sandoval return count; 7244a46f05eSOmar Sandoval } 7254a46f05eSOmar Sandoval 726f57de23aSOmar Sandoval static int ctx_completed_show(void *data, struct seq_file *m) 7274a46f05eSOmar Sandoval { 728f57de23aSOmar Sandoval struct blk_mq_ctx *ctx = data; 7294a46f05eSOmar Sandoval 7304a46f05eSOmar Sandoval seq_printf(m, "%lu %lu\n", ctx->rq_completed[1], ctx->rq_completed[0]); 7314a46f05eSOmar Sandoval return 0; 7324a46f05eSOmar Sandoval } 7334a46f05eSOmar Sandoval 734f57de23aSOmar Sandoval static ssize_t ctx_completed_write(void *data, const char __user *buf, 7354a46f05eSOmar Sandoval size_t count, loff_t *ppos) 7364a46f05eSOmar Sandoval { 737f57de23aSOmar Sandoval struct blk_mq_ctx *ctx = data; 7384a46f05eSOmar Sandoval 7394a46f05eSOmar Sandoval ctx->rq_completed[0] = ctx->rq_completed[1] = 0; 7404a46f05eSOmar Sandoval return count; 7414a46f05eSOmar Sandoval } 7424a46f05eSOmar Sandoval 743f57de23aSOmar Sandoval static int blk_mq_debugfs_show(struct seq_file *m, void *v) 744f57de23aSOmar Sandoval { 745f57de23aSOmar Sandoval const struct blk_mq_debugfs_attr *attr = m->private; 746f57de23aSOmar Sandoval void *data = d_inode(m->file->f_path.dentry->d_parent)->i_private; 747f57de23aSOmar Sandoval 748f57de23aSOmar Sandoval return attr->show(data, m); 749f57de23aSOmar Sandoval } 750f57de23aSOmar Sandoval 751f57de23aSOmar Sandoval static ssize_t blk_mq_debugfs_write(struct file *file, const char __user *buf, 752f57de23aSOmar Sandoval size_t count, loff_t *ppos) 753f57de23aSOmar Sandoval { 754f57de23aSOmar Sandoval struct seq_file *m = file->private_data; 755f57de23aSOmar Sandoval const struct blk_mq_debugfs_attr *attr = m->private; 756f57de23aSOmar Sandoval void *data = d_inode(file->f_path.dentry->d_parent)->i_private; 757f57de23aSOmar Sandoval 7586b136a24SEryu Guan /* 7596b136a24SEryu Guan * Attributes that only implement .seq_ops are read-only and 'attr' is 7606b136a24SEryu Guan * the same with 'data' in this case. 7616b136a24SEryu Guan */ 7626b136a24SEryu Guan if (attr == data || !attr->write) 763f57de23aSOmar Sandoval return -EPERM; 764f57de23aSOmar Sandoval 765f57de23aSOmar Sandoval return attr->write(data, buf, count, ppos); 766f57de23aSOmar Sandoval } 767f57de23aSOmar Sandoval 768f57de23aSOmar Sandoval static int blk_mq_debugfs_open(struct inode *inode, struct file *file) 769f57de23aSOmar Sandoval { 770f57de23aSOmar Sandoval const struct blk_mq_debugfs_attr *attr = inode->i_private; 771f57de23aSOmar Sandoval void *data = d_inode(file->f_path.dentry->d_parent)->i_private; 772f57de23aSOmar Sandoval struct seq_file *m; 773f57de23aSOmar Sandoval int ret; 774f57de23aSOmar Sandoval 775f57de23aSOmar Sandoval if (attr->seq_ops) { 776f57de23aSOmar Sandoval ret = seq_open(file, attr->seq_ops); 777f57de23aSOmar Sandoval if (!ret) { 778f57de23aSOmar Sandoval m = file->private_data; 779f57de23aSOmar Sandoval m->private = data; 780f57de23aSOmar Sandoval } 781f57de23aSOmar Sandoval return ret; 782f57de23aSOmar Sandoval } 783f57de23aSOmar Sandoval 784f57de23aSOmar Sandoval if (WARN_ON_ONCE(!attr->show)) 785f57de23aSOmar Sandoval return -EPERM; 786f57de23aSOmar Sandoval 787f57de23aSOmar Sandoval return single_open(file, blk_mq_debugfs_show, inode->i_private); 788f57de23aSOmar Sandoval } 789f57de23aSOmar Sandoval 790f57de23aSOmar Sandoval static int blk_mq_debugfs_release(struct inode *inode, struct file *file) 791f57de23aSOmar Sandoval { 792f57de23aSOmar Sandoval const struct blk_mq_debugfs_attr *attr = inode->i_private; 793f57de23aSOmar Sandoval 794f57de23aSOmar Sandoval if (attr->show) 795f57de23aSOmar Sandoval return single_release(inode, file); 796f57de23aSOmar Sandoval else 797f57de23aSOmar Sandoval return seq_release(inode, file); 798f57de23aSOmar Sandoval } 799f57de23aSOmar Sandoval 800f8465933SBart Van Assche static const struct file_operations blk_mq_debugfs_fops = { 801f57de23aSOmar Sandoval .open = blk_mq_debugfs_open, 8024a46f05eSOmar Sandoval .read = seq_read, 803f57de23aSOmar Sandoval .write = blk_mq_debugfs_write, 8044a46f05eSOmar Sandoval .llseek = seq_lseek, 805f57de23aSOmar Sandoval .release = blk_mq_debugfs_release, 8064a46f05eSOmar Sandoval }; 8074a46f05eSOmar Sandoval 80807e4feadSOmar Sandoval static const struct blk_mq_debugfs_attr blk_mq_debugfs_hctx_attrs[] = { 809f57de23aSOmar Sandoval {"state", 0400, hctx_state_show}, 810f57de23aSOmar Sandoval {"flags", 0400, hctx_flags_show}, 811f57de23aSOmar Sandoval {"dispatch", 0400, .seq_ops = &hctx_dispatch_seq_ops}, 8122720bab5SBart Van Assche {"busy", 0400, hctx_busy_show}, 813f57de23aSOmar Sandoval {"ctx_map", 0400, hctx_ctx_map_show}, 814f57de23aSOmar Sandoval {"tags", 0400, hctx_tags_show}, 815f57de23aSOmar Sandoval {"tags_bitmap", 0400, hctx_tags_bitmap_show}, 816f57de23aSOmar Sandoval {"sched_tags", 0400, hctx_sched_tags_show}, 817f57de23aSOmar Sandoval {"sched_tags_bitmap", 0400, hctx_sched_tags_bitmap_show}, 818f57de23aSOmar Sandoval {"io_poll", 0600, hctx_io_poll_show, hctx_io_poll_write}, 819f57de23aSOmar Sandoval {"dispatched", 0600, hctx_dispatched_show, hctx_dispatched_write}, 820f57de23aSOmar Sandoval {"queued", 0600, hctx_queued_show, hctx_queued_write}, 821f57de23aSOmar Sandoval {"run", 0600, hctx_run_show, hctx_run_write}, 822f57de23aSOmar Sandoval {"active", 0400, hctx_active_show}, 8236e768717SMing Lei {"dispatch_busy", 0400, hctx_dispatch_busy_show}, 824346fc108SMing Lei {"type", 0400, hctx_type_show}, 82572f2f8f6SBart Van Assche {}, 82607e4feadSOmar Sandoval }; 82707e4feadSOmar Sandoval 82807e4feadSOmar Sandoval static const struct blk_mq_debugfs_attr blk_mq_debugfs_ctx_attrs[] = { 829c16d6b5aSMing Lei {"default_rq_list", 0400, .seq_ops = &ctx_default_rq_list_seq_ops}, 830c16d6b5aSMing Lei {"read_rq_list", 0400, .seq_ops = &ctx_read_rq_list_seq_ops}, 831c16d6b5aSMing Lei {"poll_rq_list", 0400, .seq_ops = &ctx_poll_rq_list_seq_ops}, 832f57de23aSOmar Sandoval {"dispatched", 0600, ctx_dispatched_show, ctx_dispatched_write}, 833f57de23aSOmar Sandoval {"merged", 0600, ctx_merged_show, ctx_merged_write}, 834f57de23aSOmar Sandoval {"completed", 0600, ctx_completed_show, ctx_completed_write}, 83572f2f8f6SBart Van Assche {}, 83607e4feadSOmar Sandoval }; 83707e4feadSOmar Sandoval 83872f2f8f6SBart Van Assche static bool debugfs_create_files(struct dentry *parent, void *data, 83972f2f8f6SBart Van Assche const struct blk_mq_debugfs_attr *attr) 84072f2f8f6SBart Van Assche { 841*36991ca6SGreg Kroah-Hartman if (IS_ERR_OR_NULL(parent)) 842*36991ca6SGreg Kroah-Hartman return false; 843*36991ca6SGreg Kroah-Hartman 844f57de23aSOmar Sandoval d_inode(parent)->i_private = data; 845f57de23aSOmar Sandoval 84672f2f8f6SBart Van Assche for (; attr->name; attr++) { 84772f2f8f6SBart Van Assche if (!debugfs_create_file(attr->name, attr->mode, parent, 848f57de23aSOmar Sandoval (void *)attr, &blk_mq_debugfs_fops)) 84972f2f8f6SBart Van Assche return false; 85072f2f8f6SBart Van Assche } 85172f2f8f6SBart Van Assche return true; 85272f2f8f6SBart Van Assche } 85372f2f8f6SBart Van Assche 8549c1051aaSOmar Sandoval int blk_mq_debugfs_register(struct request_queue *q) 8559c1051aaSOmar Sandoval { 8569c1051aaSOmar Sandoval struct blk_mq_hw_ctx *hctx; 8579c1051aaSOmar Sandoval int i; 8589c1051aaSOmar Sandoval 8599c1051aaSOmar Sandoval if (!blk_debugfs_root) 8609c1051aaSOmar Sandoval return -ENOENT; 8619c1051aaSOmar Sandoval 8629c1051aaSOmar Sandoval q->debugfs_dir = debugfs_create_dir(kobject_name(q->kobj.parent), 8639c1051aaSOmar Sandoval blk_debugfs_root); 8649c1051aaSOmar Sandoval if (!q->debugfs_dir) 8659c1051aaSOmar Sandoval return -ENOMEM; 8669c1051aaSOmar Sandoval 8679c1051aaSOmar Sandoval if (!debugfs_create_files(q->debugfs_dir, q, 8689c1051aaSOmar Sandoval blk_mq_debugfs_queue_attrs)) 8699c1051aaSOmar Sandoval goto err; 8709c1051aaSOmar Sandoval 8719c1051aaSOmar Sandoval /* 87270e62f4bSOmar Sandoval * blk_mq_init_sched() attempted to do this already, but q->debugfs_dir 8739c1051aaSOmar Sandoval * didn't exist yet (because we don't know what to name the directory 8749c1051aaSOmar Sandoval * until the queue is registered to a gendisk). 8759c1051aaSOmar Sandoval */ 87670e62f4bSOmar Sandoval if (q->elevator && !q->sched_debugfs_dir) 87770e62f4bSOmar Sandoval blk_mq_debugfs_register_sched(q); 87870e62f4bSOmar Sandoval 87970e62f4bSOmar Sandoval /* Similarly, blk_mq_init_hctx() couldn't do this previously. */ 8809c1051aaSOmar Sandoval queue_for_each_hw_ctx(q, hctx, i) { 8819c1051aaSOmar Sandoval if (!hctx->debugfs_dir && blk_mq_debugfs_register_hctx(q, hctx)) 8829c1051aaSOmar Sandoval goto err; 883d332ce09SOmar Sandoval if (q->elevator && !hctx->sched_debugfs_dir && 884d332ce09SOmar Sandoval blk_mq_debugfs_register_sched_hctx(q, hctx)) 885d332ce09SOmar Sandoval goto err; 8869c1051aaSOmar Sandoval } 8879c1051aaSOmar Sandoval 888cc56694fSMing Lei if (q->rq_qos) { 889cc56694fSMing Lei struct rq_qos *rqos = q->rq_qos; 890cc56694fSMing Lei 891cc56694fSMing Lei while (rqos) { 892cc56694fSMing Lei blk_mq_debugfs_register_rqos(rqos); 893cc56694fSMing Lei rqos = rqos->next; 894cc56694fSMing Lei } 895cc56694fSMing Lei } 896cc56694fSMing Lei 8979c1051aaSOmar Sandoval return 0; 8989c1051aaSOmar Sandoval 8999c1051aaSOmar Sandoval err: 9009c1051aaSOmar Sandoval blk_mq_debugfs_unregister(q); 9019c1051aaSOmar Sandoval return -ENOMEM; 9029c1051aaSOmar Sandoval } 9039c1051aaSOmar Sandoval 9049c1051aaSOmar Sandoval void blk_mq_debugfs_unregister(struct request_queue *q) 9059c1051aaSOmar Sandoval { 9069c1051aaSOmar Sandoval debugfs_remove_recursive(q->debugfs_dir); 907d332ce09SOmar Sandoval q->sched_debugfs_dir = NULL; 9089c1051aaSOmar Sandoval q->debugfs_dir = NULL; 9099c1051aaSOmar Sandoval } 9109c1051aaSOmar Sandoval 9119c1051aaSOmar Sandoval static int blk_mq_debugfs_register_ctx(struct blk_mq_hw_ctx *hctx, 9129c1051aaSOmar Sandoval struct blk_mq_ctx *ctx) 91307e4feadSOmar Sandoval { 91407e4feadSOmar Sandoval struct dentry *ctx_dir; 91507e4feadSOmar Sandoval char name[20]; 91607e4feadSOmar Sandoval 91707e4feadSOmar Sandoval snprintf(name, sizeof(name), "cpu%u", ctx->cpu); 9189c1051aaSOmar Sandoval ctx_dir = debugfs_create_dir(name, hctx->debugfs_dir); 91907e4feadSOmar Sandoval if (!ctx_dir) 92007e4feadSOmar Sandoval return -ENOMEM; 92107e4feadSOmar Sandoval 92272f2f8f6SBart Van Assche if (!debugfs_create_files(ctx_dir, ctx, blk_mq_debugfs_ctx_attrs)) 92307e4feadSOmar Sandoval return -ENOMEM; 92407e4feadSOmar Sandoval 92507e4feadSOmar Sandoval return 0; 92607e4feadSOmar Sandoval } 92707e4feadSOmar Sandoval 9289c1051aaSOmar Sandoval int blk_mq_debugfs_register_hctx(struct request_queue *q, 92907e4feadSOmar Sandoval struct blk_mq_hw_ctx *hctx) 93007e4feadSOmar Sandoval { 93107e4feadSOmar Sandoval struct blk_mq_ctx *ctx; 93207e4feadSOmar Sandoval char name[20]; 93307e4feadSOmar Sandoval int i; 93407e4feadSOmar Sandoval 93507e4feadSOmar Sandoval if (!q->debugfs_dir) 93607e4feadSOmar Sandoval return -ENOENT; 93707e4feadSOmar Sandoval 9389c1051aaSOmar Sandoval snprintf(name, sizeof(name), "hctx%u", hctx->queue_num); 9399c1051aaSOmar Sandoval hctx->debugfs_dir = debugfs_create_dir(name, q->debugfs_dir); 9409c1051aaSOmar Sandoval if (!hctx->debugfs_dir) 9419c1051aaSOmar Sandoval return -ENOMEM; 9429c1051aaSOmar Sandoval 9439c1051aaSOmar Sandoval if (!debugfs_create_files(hctx->debugfs_dir, hctx, 9449c1051aaSOmar Sandoval blk_mq_debugfs_hctx_attrs)) 94507e4feadSOmar Sandoval goto err; 94607e4feadSOmar Sandoval 9479c1051aaSOmar Sandoval hctx_for_each_ctx(hctx, ctx, i) { 9489c1051aaSOmar Sandoval if (blk_mq_debugfs_register_ctx(hctx, ctx)) 94907e4feadSOmar Sandoval goto err; 95007e4feadSOmar Sandoval } 95107e4feadSOmar Sandoval 95207e4feadSOmar Sandoval return 0; 95307e4feadSOmar Sandoval 95407e4feadSOmar Sandoval err: 9559c1051aaSOmar Sandoval blk_mq_debugfs_unregister_hctx(hctx); 95607e4feadSOmar Sandoval return -ENOMEM; 95707e4feadSOmar Sandoval } 95807e4feadSOmar Sandoval 9599c1051aaSOmar Sandoval void blk_mq_debugfs_unregister_hctx(struct blk_mq_hw_ctx *hctx) 96007e4feadSOmar Sandoval { 9619c1051aaSOmar Sandoval debugfs_remove_recursive(hctx->debugfs_dir); 962d332ce09SOmar Sandoval hctx->sched_debugfs_dir = NULL; 9639c1051aaSOmar Sandoval hctx->debugfs_dir = NULL; 9649c1051aaSOmar Sandoval } 9659c1051aaSOmar Sandoval 9669c1051aaSOmar Sandoval int blk_mq_debugfs_register_hctxs(struct request_queue *q) 9679c1051aaSOmar Sandoval { 9689c1051aaSOmar Sandoval struct blk_mq_hw_ctx *hctx; 9699c1051aaSOmar Sandoval int i; 9709c1051aaSOmar Sandoval 9719c1051aaSOmar Sandoval queue_for_each_hw_ctx(q, hctx, i) { 9729c1051aaSOmar Sandoval if (blk_mq_debugfs_register_hctx(q, hctx)) 9739c1051aaSOmar Sandoval return -ENOMEM; 9749c1051aaSOmar Sandoval } 9759c1051aaSOmar Sandoval 9769c1051aaSOmar Sandoval return 0; 9779c1051aaSOmar Sandoval } 9789c1051aaSOmar Sandoval 9799c1051aaSOmar Sandoval void blk_mq_debugfs_unregister_hctxs(struct request_queue *q) 9809c1051aaSOmar Sandoval { 9819c1051aaSOmar Sandoval struct blk_mq_hw_ctx *hctx; 9829c1051aaSOmar Sandoval int i; 9839c1051aaSOmar Sandoval 9849c1051aaSOmar Sandoval queue_for_each_hw_ctx(q, hctx, i) 9859c1051aaSOmar Sandoval blk_mq_debugfs_unregister_hctx(hctx); 98607e4feadSOmar Sandoval } 987d332ce09SOmar Sandoval 988d332ce09SOmar Sandoval int blk_mq_debugfs_register_sched(struct request_queue *q) 989d332ce09SOmar Sandoval { 990d332ce09SOmar Sandoval struct elevator_type *e = q->elevator->type; 991d332ce09SOmar Sandoval 992d332ce09SOmar Sandoval if (!q->debugfs_dir) 993d332ce09SOmar Sandoval return -ENOENT; 994d332ce09SOmar Sandoval 995d332ce09SOmar Sandoval if (!e->queue_debugfs_attrs) 996d332ce09SOmar Sandoval return 0; 997d332ce09SOmar Sandoval 998d332ce09SOmar Sandoval q->sched_debugfs_dir = debugfs_create_dir("sched", q->debugfs_dir); 999d332ce09SOmar Sandoval if (!q->sched_debugfs_dir) 1000d332ce09SOmar Sandoval return -ENOMEM; 1001d332ce09SOmar Sandoval 1002d332ce09SOmar Sandoval if (!debugfs_create_files(q->sched_debugfs_dir, q, 1003d332ce09SOmar Sandoval e->queue_debugfs_attrs)) 1004d332ce09SOmar Sandoval goto err; 1005d332ce09SOmar Sandoval 1006d332ce09SOmar Sandoval return 0; 1007d332ce09SOmar Sandoval 1008d332ce09SOmar Sandoval err: 1009d332ce09SOmar Sandoval blk_mq_debugfs_unregister_sched(q); 1010d332ce09SOmar Sandoval return -ENOMEM; 1011d332ce09SOmar Sandoval } 1012d332ce09SOmar Sandoval 1013d332ce09SOmar Sandoval void blk_mq_debugfs_unregister_sched(struct request_queue *q) 1014d332ce09SOmar Sandoval { 1015d332ce09SOmar Sandoval debugfs_remove_recursive(q->sched_debugfs_dir); 1016d332ce09SOmar Sandoval q->sched_debugfs_dir = NULL; 1017d332ce09SOmar Sandoval } 1018d332ce09SOmar Sandoval 1019cc56694fSMing Lei void blk_mq_debugfs_unregister_rqos(struct rq_qos *rqos) 1020cc56694fSMing Lei { 1021cc56694fSMing Lei debugfs_remove_recursive(rqos->debugfs_dir); 1022cc56694fSMing Lei rqos->debugfs_dir = NULL; 1023cc56694fSMing Lei } 1024cc56694fSMing Lei 1025cc56694fSMing Lei int blk_mq_debugfs_register_rqos(struct rq_qos *rqos) 1026cc56694fSMing Lei { 1027cc56694fSMing Lei struct request_queue *q = rqos->q; 1028cc56694fSMing Lei const char *dir_name = rq_qos_id_to_name(rqos->id); 1029cc56694fSMing Lei 1030cc56694fSMing Lei if (!q->debugfs_dir) 1031cc56694fSMing Lei return -ENOENT; 1032cc56694fSMing Lei 1033cc56694fSMing Lei if (rqos->debugfs_dir || !rqos->ops->debugfs_attrs) 1034cc56694fSMing Lei return 0; 1035cc56694fSMing Lei 1036cc56694fSMing Lei if (!q->rqos_debugfs_dir) { 1037cc56694fSMing Lei q->rqos_debugfs_dir = debugfs_create_dir("rqos", 1038cc56694fSMing Lei q->debugfs_dir); 1039cc56694fSMing Lei if (!q->rqos_debugfs_dir) 1040cc56694fSMing Lei return -ENOMEM; 1041cc56694fSMing Lei } 1042cc56694fSMing Lei 1043cc56694fSMing Lei rqos->debugfs_dir = debugfs_create_dir(dir_name, 1044cc56694fSMing Lei rqos->q->rqos_debugfs_dir); 1045cc56694fSMing Lei if (!rqos->debugfs_dir) 1046cc56694fSMing Lei return -ENOMEM; 1047cc56694fSMing Lei 1048cc56694fSMing Lei if (!debugfs_create_files(rqos->debugfs_dir, rqos, 1049cc56694fSMing Lei rqos->ops->debugfs_attrs)) 1050cc56694fSMing Lei goto err; 1051cc56694fSMing Lei return 0; 1052cc56694fSMing Lei err: 1053cc56694fSMing Lei blk_mq_debugfs_unregister_rqos(rqos); 1054cc56694fSMing Lei return -ENOMEM; 1055cc56694fSMing Lei } 1056cc56694fSMing Lei 1057cc56694fSMing Lei void blk_mq_debugfs_unregister_queue_rqos(struct request_queue *q) 1058cc56694fSMing Lei { 1059cc56694fSMing Lei debugfs_remove_recursive(q->rqos_debugfs_dir); 1060cc56694fSMing Lei q->rqos_debugfs_dir = NULL; 1061cc56694fSMing Lei } 1062cc56694fSMing Lei 1063d332ce09SOmar Sandoval int blk_mq_debugfs_register_sched_hctx(struct request_queue *q, 1064d332ce09SOmar Sandoval struct blk_mq_hw_ctx *hctx) 1065d332ce09SOmar Sandoval { 1066d332ce09SOmar Sandoval struct elevator_type *e = q->elevator->type; 1067d332ce09SOmar Sandoval 1068d332ce09SOmar Sandoval if (!hctx->debugfs_dir) 1069d332ce09SOmar Sandoval return -ENOENT; 1070d332ce09SOmar Sandoval 1071d332ce09SOmar Sandoval if (!e->hctx_debugfs_attrs) 1072d332ce09SOmar Sandoval return 0; 1073d332ce09SOmar Sandoval 1074d332ce09SOmar Sandoval hctx->sched_debugfs_dir = debugfs_create_dir("sched", 1075d332ce09SOmar Sandoval hctx->debugfs_dir); 1076d332ce09SOmar Sandoval if (!hctx->sched_debugfs_dir) 1077d332ce09SOmar Sandoval return -ENOMEM; 1078d332ce09SOmar Sandoval 1079d332ce09SOmar Sandoval if (!debugfs_create_files(hctx->sched_debugfs_dir, hctx, 1080d332ce09SOmar Sandoval e->hctx_debugfs_attrs)) 1081d332ce09SOmar Sandoval return -ENOMEM; 1082d332ce09SOmar Sandoval 1083d332ce09SOmar Sandoval return 0; 1084d332ce09SOmar Sandoval } 1085d332ce09SOmar Sandoval 1086d332ce09SOmar Sandoval void blk_mq_debugfs_unregister_sched_hctx(struct blk_mq_hw_ctx *hctx) 1087d332ce09SOmar Sandoval { 1088d332ce09SOmar Sandoval debugfs_remove_recursive(hctx->sched_debugfs_dir); 1089d332ce09SOmar Sandoval hctx->sched_debugfs_dir = NULL; 1090d332ce09SOmar Sandoval } 1091