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" 24d96b37c0SOmar Sandoval #include "blk-mq-tag.h" 2507e4feadSOmar Sandoval 2607e4feadSOmar Sandoval struct blk_mq_debugfs_attr { 2707e4feadSOmar Sandoval const char *name; 2807e4feadSOmar Sandoval umode_t mode; 2907e4feadSOmar Sandoval const struct file_operations *fops; 3007e4feadSOmar Sandoval }; 3107e4feadSOmar Sandoval 32950cd7e9SOmar Sandoval static int blk_mq_debugfs_seq_open(struct inode *inode, struct file *file, 33950cd7e9SOmar Sandoval const struct seq_operations *ops) 34950cd7e9SOmar Sandoval { 35950cd7e9SOmar Sandoval struct seq_file *m; 36950cd7e9SOmar Sandoval int ret; 37950cd7e9SOmar Sandoval 38950cd7e9SOmar Sandoval ret = seq_open(file, ops); 39950cd7e9SOmar Sandoval if (!ret) { 40950cd7e9SOmar Sandoval m = file->private_data; 41950cd7e9SOmar Sandoval m->private = inode->i_private; 42950cd7e9SOmar Sandoval } 43950cd7e9SOmar Sandoval return ret; 44950cd7e9SOmar Sandoval } 45950cd7e9SOmar Sandoval 4691d68905SBart Van Assche static int blk_flags_show(struct seq_file *m, const unsigned long flags, 4791d68905SBart Van Assche const char *const *flag_name, int flag_name_count) 4891d68905SBart Van Assche { 4991d68905SBart Van Assche bool sep = false; 5091d68905SBart Van Assche int i; 5191d68905SBart Van Assche 5291d68905SBart Van Assche for (i = 0; i < sizeof(flags) * BITS_PER_BYTE; i++) { 5391d68905SBart Van Assche if (!(flags & BIT(i))) 5491d68905SBart Van Assche continue; 5591d68905SBart Van Assche if (sep) 56bec03d6bSOmar Sandoval seq_puts(m, "|"); 5791d68905SBart Van Assche sep = true; 5891d68905SBart Van Assche if (i < flag_name_count && flag_name[i]) 5991d68905SBart Van Assche seq_puts(m, flag_name[i]); 6091d68905SBart Van Assche else 6191d68905SBart Van Assche seq_printf(m, "%d", i); 6291d68905SBart Van Assche } 6391d68905SBart Van Assche return 0; 6491d68905SBart Van Assche } 6591d68905SBart Van Assche 661a435111SOmar Sandoval #define QUEUE_FLAG_NAME(name) [QUEUE_FLAG_##name] = #name 6791d68905SBart Van Assche static const char *const blk_queue_flag_name[] = { 681a435111SOmar Sandoval QUEUE_FLAG_NAME(QUEUED), 691a435111SOmar Sandoval QUEUE_FLAG_NAME(STOPPED), 701a435111SOmar Sandoval QUEUE_FLAG_NAME(SYNCFULL), 711a435111SOmar Sandoval QUEUE_FLAG_NAME(ASYNCFULL), 721a435111SOmar Sandoval QUEUE_FLAG_NAME(DYING), 731a435111SOmar Sandoval QUEUE_FLAG_NAME(BYPASS), 741a435111SOmar Sandoval QUEUE_FLAG_NAME(BIDI), 751a435111SOmar Sandoval QUEUE_FLAG_NAME(NOMERGES), 761a435111SOmar Sandoval QUEUE_FLAG_NAME(SAME_COMP), 771a435111SOmar Sandoval QUEUE_FLAG_NAME(FAIL_IO), 781a435111SOmar Sandoval QUEUE_FLAG_NAME(STACKABLE), 791a435111SOmar Sandoval QUEUE_FLAG_NAME(NONROT), 801a435111SOmar Sandoval QUEUE_FLAG_NAME(IO_STAT), 811a435111SOmar Sandoval QUEUE_FLAG_NAME(DISCARD), 821a435111SOmar Sandoval QUEUE_FLAG_NAME(NOXMERGES), 831a435111SOmar Sandoval QUEUE_FLAG_NAME(ADD_RANDOM), 841a435111SOmar Sandoval QUEUE_FLAG_NAME(SECERASE), 851a435111SOmar Sandoval QUEUE_FLAG_NAME(SAME_FORCE), 861a435111SOmar Sandoval QUEUE_FLAG_NAME(DEAD), 871a435111SOmar Sandoval QUEUE_FLAG_NAME(INIT_DONE), 881a435111SOmar Sandoval QUEUE_FLAG_NAME(NO_SG_MERGE), 891a435111SOmar Sandoval QUEUE_FLAG_NAME(POLL), 901a435111SOmar Sandoval QUEUE_FLAG_NAME(WC), 911a435111SOmar Sandoval QUEUE_FLAG_NAME(FUA), 921a435111SOmar Sandoval QUEUE_FLAG_NAME(FLUSH_NQ), 931a435111SOmar Sandoval QUEUE_FLAG_NAME(DAX), 941a435111SOmar Sandoval QUEUE_FLAG_NAME(STATS), 951a435111SOmar Sandoval QUEUE_FLAG_NAME(POLL_STATS), 961a435111SOmar Sandoval QUEUE_FLAG_NAME(REGISTERED), 9791d68905SBart Van Assche }; 981a435111SOmar Sandoval #undef QUEUE_FLAG_NAME 9991d68905SBart Van Assche 10091d68905SBart Van Assche static int blk_queue_flags_show(struct seq_file *m, void *v) 10191d68905SBart Van Assche { 10291d68905SBart Van Assche struct request_queue *q = m->private; 10391d68905SBart Van Assche 10491d68905SBart Van Assche blk_flags_show(m, q->queue_flags, blk_queue_flag_name, 10591d68905SBart Van Assche ARRAY_SIZE(blk_queue_flag_name)); 106fd07dc81SBart Van Assche seq_puts(m, "\n"); 10791d68905SBart Van Assche return 0; 10891d68905SBart Van Assche } 10991d68905SBart Van Assche 110c7e4145aSOmar Sandoval static ssize_t blk_queue_flags_store(struct file *file, const char __user *buf, 111c7e4145aSOmar Sandoval size_t count, loff_t *ppos) 11291d68905SBart Van Assche { 11391d68905SBart Van Assche struct request_queue *q = file_inode(file)->i_private; 11471b90511SOmar Sandoval char opbuf[16] = { }, *op; 11591d68905SBart Van Assche 11671b90511SOmar Sandoval if (count >= sizeof(opbuf)) { 117c7e4145aSOmar Sandoval pr_err("%s: operation too long\n", __func__); 118c7e4145aSOmar Sandoval goto inval; 119c7e4145aSOmar Sandoval } 120c7e4145aSOmar Sandoval 12171b90511SOmar Sandoval if (copy_from_user(opbuf, buf, count)) 12291d68905SBart Van Assche return -EFAULT; 12371b90511SOmar Sandoval op = strstrip(opbuf); 12491d68905SBart Van Assche if (strcmp(op, "run") == 0) { 12591d68905SBart Van Assche blk_mq_run_hw_queues(q, true); 12691d68905SBart Van Assche } else if (strcmp(op, "start") == 0) { 12791d68905SBart Van Assche blk_mq_start_stopped_hw_queues(q, true); 12891d68905SBart Van Assche } else { 129c7e4145aSOmar Sandoval pr_err("%s: unsupported operation '%s'\n", __func__, op); 130c7e4145aSOmar Sandoval inval: 131c7e4145aSOmar Sandoval pr_err("%s: use either 'run' or 'start'\n", __func__); 13291d68905SBart Van Assche return -EINVAL; 13391d68905SBart Van Assche } 134c7e4145aSOmar Sandoval return count; 13591d68905SBart Van Assche } 13691d68905SBart Van Assche 13791d68905SBart Van Assche static int blk_queue_flags_open(struct inode *inode, struct file *file) 13891d68905SBart Van Assche { 13991d68905SBart Van Assche return single_open(file, blk_queue_flags_show, inode->i_private); 14091d68905SBart Van Assche } 14191d68905SBart Van Assche 14291d68905SBart Van Assche static const struct file_operations blk_queue_flags_fops = { 14391d68905SBart Van Assche .open = blk_queue_flags_open, 14491d68905SBart Van Assche .read = seq_read, 14591d68905SBart Van Assche .llseek = seq_lseek, 14691d68905SBart Van Assche .release = single_release, 14791d68905SBart Van Assche .write = blk_queue_flags_store, 14891d68905SBart Van Assche }; 14991d68905SBart Van Assche 15034dbad5dSOmar Sandoval static void print_stat(struct seq_file *m, struct blk_rq_stat *stat) 15134dbad5dSOmar Sandoval { 15234dbad5dSOmar Sandoval if (stat->nr_samples) { 15334dbad5dSOmar Sandoval seq_printf(m, "samples=%d, mean=%lld, min=%llu, max=%llu", 15434dbad5dSOmar Sandoval stat->nr_samples, stat->mean, stat->min, stat->max); 15534dbad5dSOmar Sandoval } else { 15634dbad5dSOmar Sandoval seq_puts(m, "samples=0"); 15734dbad5dSOmar Sandoval } 15834dbad5dSOmar Sandoval } 15934dbad5dSOmar Sandoval 16034dbad5dSOmar Sandoval static int queue_poll_stat_show(struct seq_file *m, void *v) 16134dbad5dSOmar Sandoval { 16234dbad5dSOmar Sandoval struct request_queue *q = m->private; 1630206319fSStephen Bates int bucket; 16434dbad5dSOmar Sandoval 1650206319fSStephen Bates for (bucket = 0; bucket < BLK_MQ_POLL_STATS_BKTS/2; bucket++) { 1660206319fSStephen Bates seq_printf(m, "read (%d Bytes): ", 1 << (9+bucket)); 1670206319fSStephen Bates print_stat(m, &q->poll_stat[2*bucket]); 16834dbad5dSOmar Sandoval seq_puts(m, "\n"); 16934dbad5dSOmar Sandoval 1700206319fSStephen Bates seq_printf(m, "write (%d Bytes): ", 1 << (9+bucket)); 1710206319fSStephen Bates print_stat(m, &q->poll_stat[2*bucket+1]); 17234dbad5dSOmar Sandoval seq_puts(m, "\n"); 1730206319fSStephen Bates } 17434dbad5dSOmar Sandoval return 0; 17534dbad5dSOmar Sandoval } 17634dbad5dSOmar Sandoval 17734dbad5dSOmar Sandoval static int queue_poll_stat_open(struct inode *inode, struct file *file) 17834dbad5dSOmar Sandoval { 17934dbad5dSOmar Sandoval return single_open(file, queue_poll_stat_show, inode->i_private); 18034dbad5dSOmar Sandoval } 18134dbad5dSOmar Sandoval 18234dbad5dSOmar Sandoval static const struct file_operations queue_poll_stat_fops = { 18334dbad5dSOmar Sandoval .open = queue_poll_stat_open, 18434dbad5dSOmar Sandoval .read = seq_read, 18534dbad5dSOmar Sandoval .llseek = seq_lseek, 18634dbad5dSOmar Sandoval .release = single_release, 18734dbad5dSOmar Sandoval }; 18834dbad5dSOmar Sandoval 1891a435111SOmar Sandoval #define HCTX_STATE_NAME(name) [BLK_MQ_S_##name] = #name 190f5c0b091SBart Van Assche static const char *const hctx_state_name[] = { 1911a435111SOmar Sandoval HCTX_STATE_NAME(STOPPED), 1921a435111SOmar Sandoval HCTX_STATE_NAME(TAG_ACTIVE), 1931a435111SOmar Sandoval HCTX_STATE_NAME(SCHED_RESTART), 1941a435111SOmar Sandoval HCTX_STATE_NAME(TAG_WAITING), 1951a435111SOmar Sandoval HCTX_STATE_NAME(START_ON_RUN), 196f5c0b091SBart Van Assche }; 1971a435111SOmar Sandoval #undef HCTX_STATE_NAME 1981a435111SOmar Sandoval 1999abb2ad2SOmar Sandoval static int hctx_state_show(struct seq_file *m, void *v) 2009abb2ad2SOmar Sandoval { 2019abb2ad2SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 2029abb2ad2SOmar Sandoval 203f5c0b091SBart Van Assche blk_flags_show(m, hctx->state, hctx_state_name, 204f5c0b091SBart Van Assche ARRAY_SIZE(hctx_state_name)); 205fd07dc81SBart Van Assche seq_puts(m, "\n"); 2069abb2ad2SOmar Sandoval return 0; 2079abb2ad2SOmar Sandoval } 2089abb2ad2SOmar Sandoval 2099abb2ad2SOmar Sandoval static int hctx_state_open(struct inode *inode, struct file *file) 2109abb2ad2SOmar Sandoval { 2119abb2ad2SOmar Sandoval return single_open(file, hctx_state_show, inode->i_private); 2129abb2ad2SOmar Sandoval } 2139abb2ad2SOmar Sandoval 2149abb2ad2SOmar Sandoval static const struct file_operations hctx_state_fops = { 2159abb2ad2SOmar Sandoval .open = hctx_state_open, 2169abb2ad2SOmar Sandoval .read = seq_read, 2179abb2ad2SOmar Sandoval .llseek = seq_lseek, 2189abb2ad2SOmar Sandoval .release = single_release, 2199abb2ad2SOmar Sandoval }; 2209abb2ad2SOmar Sandoval 2211a435111SOmar Sandoval #define BLK_TAG_ALLOC_NAME(name) [BLK_TAG_ALLOC_##name] = #name 222f5c0b091SBart Van Assche static const char *const alloc_policy_name[] = { 2231a435111SOmar Sandoval BLK_TAG_ALLOC_NAME(FIFO), 2241a435111SOmar Sandoval BLK_TAG_ALLOC_NAME(RR), 225f5c0b091SBart Van Assche }; 2261a435111SOmar Sandoval #undef BLK_TAG_ALLOC_NAME 227f5c0b091SBart Van Assche 2281a435111SOmar Sandoval #define HCTX_FLAG_NAME(name) [ilog2(BLK_MQ_F_##name)] = #name 229f5c0b091SBart Van Assche static const char *const hctx_flag_name[] = { 2301a435111SOmar Sandoval HCTX_FLAG_NAME(SHOULD_MERGE), 2311a435111SOmar Sandoval HCTX_FLAG_NAME(TAG_SHARED), 2321a435111SOmar Sandoval HCTX_FLAG_NAME(SG_MERGE), 2331a435111SOmar Sandoval HCTX_FLAG_NAME(BLOCKING), 2341a435111SOmar Sandoval HCTX_FLAG_NAME(NO_SCHED), 235f5c0b091SBart Van Assche }; 2361a435111SOmar Sandoval #undef HCTX_FLAG_NAME 237f5c0b091SBart Van Assche 2389abb2ad2SOmar Sandoval static int hctx_flags_show(struct seq_file *m, void *v) 2399abb2ad2SOmar Sandoval { 2409abb2ad2SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 241f5c0b091SBart Van Assche const int alloc_policy = BLK_MQ_FLAG_TO_ALLOC_POLICY(hctx->flags); 2429abb2ad2SOmar Sandoval 243f5c0b091SBart Van Assche seq_puts(m, "alloc_policy="); 244f5c0b091SBart Van Assche if (alloc_policy < ARRAY_SIZE(alloc_policy_name) && 245f5c0b091SBart Van Assche alloc_policy_name[alloc_policy]) 246f5c0b091SBart Van Assche seq_puts(m, alloc_policy_name[alloc_policy]); 247f5c0b091SBart Van Assche else 248f5c0b091SBart Van Assche seq_printf(m, "%d", alloc_policy); 249f5c0b091SBart Van Assche seq_puts(m, " "); 250f5c0b091SBart Van Assche blk_flags_show(m, 251f5c0b091SBart Van Assche hctx->flags ^ BLK_ALLOC_POLICY_TO_MQ_FLAG(alloc_policy), 252f5c0b091SBart Van Assche hctx_flag_name, ARRAY_SIZE(hctx_flag_name)); 253fd07dc81SBart Van Assche seq_puts(m, "\n"); 2549abb2ad2SOmar Sandoval return 0; 2559abb2ad2SOmar Sandoval } 2569abb2ad2SOmar Sandoval 2579abb2ad2SOmar Sandoval static int hctx_flags_open(struct inode *inode, struct file *file) 2589abb2ad2SOmar Sandoval { 2599abb2ad2SOmar Sandoval return single_open(file, hctx_flags_show, inode->i_private); 2609abb2ad2SOmar Sandoval } 2619abb2ad2SOmar Sandoval 2629abb2ad2SOmar Sandoval static const struct file_operations hctx_flags_fops = { 2639abb2ad2SOmar Sandoval .open = hctx_flags_open, 2649abb2ad2SOmar Sandoval .read = seq_read, 2659abb2ad2SOmar Sandoval .llseek = seq_lseek, 2669abb2ad2SOmar Sandoval .release = single_release, 2679abb2ad2SOmar Sandoval }; 2689abb2ad2SOmar Sandoval 2691a435111SOmar Sandoval #define REQ_OP_NAME(name) [REQ_OP_##name] = #name 2708658dca8SBart Van Assche static const char *const op_name[] = { 2711a435111SOmar Sandoval REQ_OP_NAME(READ), 2721a435111SOmar Sandoval REQ_OP_NAME(WRITE), 2731a435111SOmar Sandoval REQ_OP_NAME(FLUSH), 2741a435111SOmar Sandoval REQ_OP_NAME(DISCARD), 2751a435111SOmar Sandoval REQ_OP_NAME(ZONE_REPORT), 2761a435111SOmar Sandoval REQ_OP_NAME(SECURE_ERASE), 2771a435111SOmar Sandoval REQ_OP_NAME(ZONE_RESET), 2781a435111SOmar Sandoval REQ_OP_NAME(WRITE_SAME), 2791a435111SOmar Sandoval REQ_OP_NAME(WRITE_ZEROES), 2801a435111SOmar Sandoval REQ_OP_NAME(SCSI_IN), 2811a435111SOmar Sandoval REQ_OP_NAME(SCSI_OUT), 2821a435111SOmar Sandoval REQ_OP_NAME(DRV_IN), 2831a435111SOmar Sandoval REQ_OP_NAME(DRV_OUT), 2848658dca8SBart Van Assche }; 2851a435111SOmar Sandoval #undef REQ_OP_NAME 2868658dca8SBart Van Assche 2871a435111SOmar Sandoval #define CMD_FLAG_NAME(name) [__REQ_##name] = #name 2888658dca8SBart Van Assche static const char *const cmd_flag_name[] = { 2891a435111SOmar Sandoval CMD_FLAG_NAME(FAILFAST_DEV), 2901a435111SOmar Sandoval CMD_FLAG_NAME(FAILFAST_TRANSPORT), 2911a435111SOmar Sandoval CMD_FLAG_NAME(FAILFAST_DRIVER), 2921a435111SOmar Sandoval CMD_FLAG_NAME(SYNC), 2931a435111SOmar Sandoval CMD_FLAG_NAME(META), 2941a435111SOmar Sandoval CMD_FLAG_NAME(PRIO), 2951a435111SOmar Sandoval CMD_FLAG_NAME(NOMERGE), 2961a435111SOmar Sandoval CMD_FLAG_NAME(IDLE), 2971a435111SOmar Sandoval CMD_FLAG_NAME(INTEGRITY), 2981a435111SOmar Sandoval CMD_FLAG_NAME(FUA), 2991a435111SOmar Sandoval CMD_FLAG_NAME(PREFLUSH), 3001a435111SOmar Sandoval CMD_FLAG_NAME(RAHEAD), 3011a435111SOmar Sandoval CMD_FLAG_NAME(BACKGROUND), 3021a435111SOmar Sandoval CMD_FLAG_NAME(NOUNMAP), 3038658dca8SBart Van Assche }; 3041a435111SOmar Sandoval #undef CMD_FLAG_NAME 3058658dca8SBart Van Assche 3061a435111SOmar Sandoval #define RQF_NAME(name) [ilog2((__force u32)RQF_##name)] = #name 3078658dca8SBart Van Assche static const char *const rqf_name[] = { 3081a435111SOmar Sandoval RQF_NAME(SORTED), 3091a435111SOmar Sandoval RQF_NAME(STARTED), 3101a435111SOmar Sandoval RQF_NAME(QUEUED), 3111a435111SOmar Sandoval RQF_NAME(SOFTBARRIER), 3121a435111SOmar Sandoval RQF_NAME(FLUSH_SEQ), 3131a435111SOmar Sandoval RQF_NAME(MIXED_MERGE), 3141a435111SOmar Sandoval RQF_NAME(MQ_INFLIGHT), 3151a435111SOmar Sandoval RQF_NAME(DONTPREP), 3161a435111SOmar Sandoval RQF_NAME(PREEMPT), 3171a435111SOmar Sandoval RQF_NAME(COPY_USER), 3181a435111SOmar Sandoval RQF_NAME(FAILED), 3191a435111SOmar Sandoval RQF_NAME(QUIET), 3201a435111SOmar Sandoval RQF_NAME(ELVPRIV), 3211a435111SOmar Sandoval RQF_NAME(IO_STAT), 3221a435111SOmar Sandoval RQF_NAME(ALLOCED), 3231a435111SOmar Sandoval RQF_NAME(PM), 3241a435111SOmar Sandoval RQF_NAME(HASHED), 3251a435111SOmar Sandoval RQF_NAME(STATS), 3261a435111SOmar Sandoval RQF_NAME(SPECIAL_PAYLOAD), 3278658dca8SBart Van Assche }; 3281a435111SOmar Sandoval #undef RQF_NAME 3298658dca8SBart Van Assche 330950cd7e9SOmar Sandoval static int blk_mq_debugfs_rq_show(struct seq_file *m, void *v) 331950cd7e9SOmar Sandoval { 332950cd7e9SOmar Sandoval struct request *rq = list_entry_rq(v); 3332836ee4bSBart Van Assche const struct blk_mq_ops *const mq_ops = rq->q->mq_ops; 3348658dca8SBart Van Assche const unsigned int op = rq->cmd_flags & REQ_OP_MASK; 335950cd7e9SOmar Sandoval 3368658dca8SBart Van Assche seq_printf(m, "%p {.op=", rq); 3378658dca8SBart Van Assche if (op < ARRAY_SIZE(op_name) && op_name[op]) 3388658dca8SBart Van Assche seq_printf(m, "%s", op_name[op]); 3398658dca8SBart Van Assche else 3408658dca8SBart Van Assche seq_printf(m, "%d", op); 3418658dca8SBart Van Assche seq_puts(m, ", .cmd_flags="); 3428658dca8SBart Van Assche blk_flags_show(m, rq->cmd_flags & ~REQ_OP_MASK, cmd_flag_name, 3438658dca8SBart Van Assche ARRAY_SIZE(cmd_flag_name)); 3448658dca8SBart Van Assche seq_puts(m, ", .rq_flags="); 3458658dca8SBart Van Assche blk_flags_show(m, (__force unsigned int)rq->rq_flags, rqf_name, 3468658dca8SBart Van Assche ARRAY_SIZE(rqf_name)); 3472836ee4bSBart Van Assche seq_printf(m, ", .tag=%d, .internal_tag=%d", rq->tag, 3488658dca8SBart Van Assche rq->internal_tag); 3492836ee4bSBart Van Assche if (mq_ops->show_rq) 3502836ee4bSBart Van Assche mq_ops->show_rq(m, rq); 3512836ee4bSBart Van Assche seq_puts(m, "}\n"); 352950cd7e9SOmar Sandoval return 0; 353950cd7e9SOmar Sandoval } 354950cd7e9SOmar Sandoval 355950cd7e9SOmar Sandoval static void *hctx_dispatch_start(struct seq_file *m, loff_t *pos) 356f3bcb0e6SBart Van Assche __acquires(&hctx->lock) 357950cd7e9SOmar Sandoval { 358950cd7e9SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 359950cd7e9SOmar Sandoval 360950cd7e9SOmar Sandoval spin_lock(&hctx->lock); 361950cd7e9SOmar Sandoval return seq_list_start(&hctx->dispatch, *pos); 362950cd7e9SOmar Sandoval } 363950cd7e9SOmar Sandoval 364950cd7e9SOmar Sandoval static void *hctx_dispatch_next(struct seq_file *m, void *v, loff_t *pos) 365950cd7e9SOmar Sandoval { 366950cd7e9SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 367950cd7e9SOmar Sandoval 368950cd7e9SOmar Sandoval return seq_list_next(v, &hctx->dispatch, pos); 369950cd7e9SOmar Sandoval } 370950cd7e9SOmar Sandoval 371950cd7e9SOmar Sandoval static void hctx_dispatch_stop(struct seq_file *m, void *v) 372f3bcb0e6SBart Van Assche __releases(&hctx->lock) 373950cd7e9SOmar Sandoval { 374950cd7e9SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 375950cd7e9SOmar Sandoval 376950cd7e9SOmar Sandoval spin_unlock(&hctx->lock); 377950cd7e9SOmar Sandoval } 378950cd7e9SOmar Sandoval 379950cd7e9SOmar Sandoval static const struct seq_operations hctx_dispatch_seq_ops = { 380950cd7e9SOmar Sandoval .start = hctx_dispatch_start, 381950cd7e9SOmar Sandoval .next = hctx_dispatch_next, 382950cd7e9SOmar Sandoval .stop = hctx_dispatch_stop, 383950cd7e9SOmar Sandoval .show = blk_mq_debugfs_rq_show, 384950cd7e9SOmar Sandoval }; 385950cd7e9SOmar Sandoval 386950cd7e9SOmar Sandoval static int hctx_dispatch_open(struct inode *inode, struct file *file) 387950cd7e9SOmar Sandoval { 388950cd7e9SOmar Sandoval return blk_mq_debugfs_seq_open(inode, file, &hctx_dispatch_seq_ops); 389950cd7e9SOmar Sandoval } 390950cd7e9SOmar Sandoval 391950cd7e9SOmar Sandoval static const struct file_operations hctx_dispatch_fops = { 392950cd7e9SOmar Sandoval .open = hctx_dispatch_open, 393950cd7e9SOmar Sandoval .read = seq_read, 394950cd7e9SOmar Sandoval .llseek = seq_lseek, 395950cd7e9SOmar Sandoval .release = seq_release, 396950cd7e9SOmar Sandoval }; 397950cd7e9SOmar Sandoval 3980bfa5288SOmar Sandoval static int hctx_ctx_map_show(struct seq_file *m, void *v) 3990bfa5288SOmar Sandoval { 4000bfa5288SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 4010bfa5288SOmar Sandoval 4020bfa5288SOmar Sandoval sbitmap_bitmap_show(&hctx->ctx_map, m); 4030bfa5288SOmar Sandoval return 0; 4040bfa5288SOmar Sandoval } 4050bfa5288SOmar Sandoval 4060bfa5288SOmar Sandoval static int hctx_ctx_map_open(struct inode *inode, struct file *file) 4070bfa5288SOmar Sandoval { 4080bfa5288SOmar Sandoval return single_open(file, hctx_ctx_map_show, inode->i_private); 4090bfa5288SOmar Sandoval } 4100bfa5288SOmar Sandoval 4110bfa5288SOmar Sandoval static const struct file_operations hctx_ctx_map_fops = { 4120bfa5288SOmar Sandoval .open = hctx_ctx_map_open, 4130bfa5288SOmar Sandoval .read = seq_read, 4140bfa5288SOmar Sandoval .llseek = seq_lseek, 4150bfa5288SOmar Sandoval .release = single_release, 4160bfa5288SOmar Sandoval }; 4170bfa5288SOmar Sandoval 418d96b37c0SOmar Sandoval static void blk_mq_debugfs_tags_show(struct seq_file *m, 419d96b37c0SOmar Sandoval struct blk_mq_tags *tags) 420d96b37c0SOmar Sandoval { 421d96b37c0SOmar Sandoval seq_printf(m, "nr_tags=%u\n", tags->nr_tags); 422d96b37c0SOmar Sandoval seq_printf(m, "nr_reserved_tags=%u\n", tags->nr_reserved_tags); 423d96b37c0SOmar Sandoval seq_printf(m, "active_queues=%d\n", 424d96b37c0SOmar Sandoval atomic_read(&tags->active_queues)); 425d96b37c0SOmar Sandoval 426d96b37c0SOmar Sandoval seq_puts(m, "\nbitmap_tags:\n"); 427d96b37c0SOmar Sandoval sbitmap_queue_show(&tags->bitmap_tags, m); 428d96b37c0SOmar Sandoval 429d96b37c0SOmar Sandoval if (tags->nr_reserved_tags) { 430d96b37c0SOmar Sandoval seq_puts(m, "\nbreserved_tags:\n"); 431d96b37c0SOmar Sandoval sbitmap_queue_show(&tags->breserved_tags, m); 432d96b37c0SOmar Sandoval } 433d96b37c0SOmar Sandoval } 434d96b37c0SOmar Sandoval 435d96b37c0SOmar Sandoval static int hctx_tags_show(struct seq_file *m, void *v) 436d96b37c0SOmar Sandoval { 437d96b37c0SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 438d96b37c0SOmar Sandoval struct request_queue *q = hctx->queue; 4398c0f14eaSBart Van Assche int res; 440d96b37c0SOmar Sandoval 4418c0f14eaSBart Van Assche res = mutex_lock_interruptible(&q->sysfs_lock); 4428c0f14eaSBart Van Assche if (res) 4438c0f14eaSBart Van Assche goto out; 444d96b37c0SOmar Sandoval if (hctx->tags) 445d96b37c0SOmar Sandoval blk_mq_debugfs_tags_show(m, hctx->tags); 446d96b37c0SOmar Sandoval mutex_unlock(&q->sysfs_lock); 447d96b37c0SOmar Sandoval 4488c0f14eaSBart Van Assche out: 4498c0f14eaSBart Van Assche return res; 450d96b37c0SOmar Sandoval } 451d96b37c0SOmar Sandoval 452d96b37c0SOmar Sandoval static int hctx_tags_open(struct inode *inode, struct file *file) 453d96b37c0SOmar Sandoval { 454d96b37c0SOmar Sandoval return single_open(file, hctx_tags_show, inode->i_private); 455d96b37c0SOmar Sandoval } 456d96b37c0SOmar Sandoval 457d96b37c0SOmar Sandoval static const struct file_operations hctx_tags_fops = { 458d96b37c0SOmar Sandoval .open = hctx_tags_open, 459d96b37c0SOmar Sandoval .read = seq_read, 460d96b37c0SOmar Sandoval .llseek = seq_lseek, 461d96b37c0SOmar Sandoval .release = single_release, 462d96b37c0SOmar Sandoval }; 463d96b37c0SOmar Sandoval 464d7e3621aSOmar Sandoval static int hctx_tags_bitmap_show(struct seq_file *m, void *v) 465d7e3621aSOmar Sandoval { 466d7e3621aSOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 467d7e3621aSOmar Sandoval struct request_queue *q = hctx->queue; 4688c0f14eaSBart Van Assche int res; 469d7e3621aSOmar Sandoval 4708c0f14eaSBart Van Assche res = mutex_lock_interruptible(&q->sysfs_lock); 4718c0f14eaSBart Van Assche if (res) 4728c0f14eaSBart Van Assche goto out; 473d7e3621aSOmar Sandoval if (hctx->tags) 474d7e3621aSOmar Sandoval sbitmap_bitmap_show(&hctx->tags->bitmap_tags.sb, m); 475d7e3621aSOmar Sandoval mutex_unlock(&q->sysfs_lock); 4768c0f14eaSBart Van Assche 4778c0f14eaSBart Van Assche out: 4788c0f14eaSBart Van Assche return res; 479d7e3621aSOmar Sandoval } 480d7e3621aSOmar Sandoval 481d7e3621aSOmar Sandoval static int hctx_tags_bitmap_open(struct inode *inode, struct file *file) 482d7e3621aSOmar Sandoval { 483d7e3621aSOmar Sandoval return single_open(file, hctx_tags_bitmap_show, inode->i_private); 484d7e3621aSOmar Sandoval } 485d7e3621aSOmar Sandoval 486d7e3621aSOmar Sandoval static const struct file_operations hctx_tags_bitmap_fops = { 487d7e3621aSOmar Sandoval .open = hctx_tags_bitmap_open, 488d7e3621aSOmar Sandoval .read = seq_read, 489d7e3621aSOmar Sandoval .llseek = seq_lseek, 490d7e3621aSOmar Sandoval .release = single_release, 491d7e3621aSOmar Sandoval }; 492d7e3621aSOmar Sandoval 493d96b37c0SOmar Sandoval static int hctx_sched_tags_show(struct seq_file *m, void *v) 494d96b37c0SOmar Sandoval { 495d96b37c0SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 496d96b37c0SOmar Sandoval struct request_queue *q = hctx->queue; 4978c0f14eaSBart Van Assche int res; 498d96b37c0SOmar Sandoval 4998c0f14eaSBart Van Assche res = mutex_lock_interruptible(&q->sysfs_lock); 5008c0f14eaSBart Van Assche if (res) 5018c0f14eaSBart Van Assche goto out; 502d96b37c0SOmar Sandoval if (hctx->sched_tags) 503d96b37c0SOmar Sandoval blk_mq_debugfs_tags_show(m, hctx->sched_tags); 504d96b37c0SOmar Sandoval mutex_unlock(&q->sysfs_lock); 505d96b37c0SOmar Sandoval 5068c0f14eaSBart Van Assche out: 5078c0f14eaSBart Van Assche return res; 508d96b37c0SOmar Sandoval } 509d96b37c0SOmar Sandoval 510d96b37c0SOmar Sandoval static int hctx_sched_tags_open(struct inode *inode, struct file *file) 511d96b37c0SOmar Sandoval { 512d96b37c0SOmar Sandoval return single_open(file, hctx_sched_tags_show, inode->i_private); 513d96b37c0SOmar Sandoval } 514d96b37c0SOmar Sandoval 515d96b37c0SOmar Sandoval static const struct file_operations hctx_sched_tags_fops = { 516d96b37c0SOmar Sandoval .open = hctx_sched_tags_open, 517d96b37c0SOmar Sandoval .read = seq_read, 518d96b37c0SOmar Sandoval .llseek = seq_lseek, 519d96b37c0SOmar Sandoval .release = single_release, 520d96b37c0SOmar Sandoval }; 521d96b37c0SOmar Sandoval 522d7e3621aSOmar Sandoval static int hctx_sched_tags_bitmap_show(struct seq_file *m, void *v) 523d7e3621aSOmar Sandoval { 524d7e3621aSOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 525d7e3621aSOmar Sandoval struct request_queue *q = hctx->queue; 5268c0f14eaSBart Van Assche int res; 527d7e3621aSOmar Sandoval 5288c0f14eaSBart Van Assche res = mutex_lock_interruptible(&q->sysfs_lock); 5298c0f14eaSBart Van Assche if (res) 5308c0f14eaSBart Van Assche goto out; 531d7e3621aSOmar Sandoval if (hctx->sched_tags) 532d7e3621aSOmar Sandoval sbitmap_bitmap_show(&hctx->sched_tags->bitmap_tags.sb, m); 533d7e3621aSOmar Sandoval mutex_unlock(&q->sysfs_lock); 5348c0f14eaSBart Van Assche 5358c0f14eaSBart Van Assche out: 5368c0f14eaSBart Van Assche return res; 537d7e3621aSOmar Sandoval } 538d7e3621aSOmar Sandoval 539d7e3621aSOmar Sandoval static int hctx_sched_tags_bitmap_open(struct inode *inode, struct file *file) 540d7e3621aSOmar Sandoval { 541d7e3621aSOmar Sandoval return single_open(file, hctx_sched_tags_bitmap_show, inode->i_private); 542d7e3621aSOmar Sandoval } 543d7e3621aSOmar Sandoval 544d7e3621aSOmar Sandoval static const struct file_operations hctx_sched_tags_bitmap_fops = { 545d7e3621aSOmar Sandoval .open = hctx_sched_tags_bitmap_open, 546d7e3621aSOmar Sandoval .read = seq_read, 547d7e3621aSOmar Sandoval .llseek = seq_lseek, 548d7e3621aSOmar Sandoval .release = single_release, 549d7e3621aSOmar Sandoval }; 550d7e3621aSOmar Sandoval 551be215473SOmar Sandoval static int hctx_io_poll_show(struct seq_file *m, void *v) 552be215473SOmar Sandoval { 553be215473SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 554be215473SOmar Sandoval 555be215473SOmar Sandoval seq_printf(m, "considered=%lu\n", hctx->poll_considered); 556be215473SOmar Sandoval seq_printf(m, "invoked=%lu\n", hctx->poll_invoked); 557be215473SOmar Sandoval seq_printf(m, "success=%lu\n", hctx->poll_success); 558be215473SOmar Sandoval return 0; 559be215473SOmar Sandoval } 560be215473SOmar Sandoval 561be215473SOmar Sandoval static int hctx_io_poll_open(struct inode *inode, struct file *file) 562be215473SOmar Sandoval { 563be215473SOmar Sandoval return single_open(file, hctx_io_poll_show, inode->i_private); 564be215473SOmar Sandoval } 565be215473SOmar Sandoval 566be215473SOmar Sandoval static ssize_t hctx_io_poll_write(struct file *file, const char __user *buf, 567be215473SOmar Sandoval size_t count, loff_t *ppos) 568be215473SOmar Sandoval { 569be215473SOmar Sandoval struct seq_file *m = file->private_data; 570be215473SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 571be215473SOmar Sandoval 572be215473SOmar Sandoval hctx->poll_considered = hctx->poll_invoked = hctx->poll_success = 0; 573be215473SOmar Sandoval return count; 574be215473SOmar Sandoval } 575be215473SOmar Sandoval 576be215473SOmar Sandoval static const struct file_operations hctx_io_poll_fops = { 577be215473SOmar Sandoval .open = hctx_io_poll_open, 578be215473SOmar Sandoval .read = seq_read, 579be215473SOmar Sandoval .write = hctx_io_poll_write, 580be215473SOmar Sandoval .llseek = seq_lseek, 581be215473SOmar Sandoval .release = single_release, 582be215473SOmar Sandoval }; 583be215473SOmar Sandoval 584be215473SOmar Sandoval static int hctx_dispatched_show(struct seq_file *m, void *v) 585be215473SOmar Sandoval { 586be215473SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 587be215473SOmar Sandoval int i; 588be215473SOmar Sandoval 589be215473SOmar Sandoval seq_printf(m, "%8u\t%lu\n", 0U, hctx->dispatched[0]); 590be215473SOmar Sandoval 591be215473SOmar Sandoval for (i = 1; i < BLK_MQ_MAX_DISPATCH_ORDER - 1; i++) { 592be215473SOmar Sandoval unsigned int d = 1U << (i - 1); 593be215473SOmar Sandoval 594be215473SOmar Sandoval seq_printf(m, "%8u\t%lu\n", d, hctx->dispatched[i]); 595be215473SOmar Sandoval } 596be215473SOmar Sandoval 597be215473SOmar Sandoval seq_printf(m, "%8u+\t%lu\n", 1U << (i - 1), hctx->dispatched[i]); 598be215473SOmar Sandoval return 0; 599be215473SOmar Sandoval } 600be215473SOmar Sandoval 601be215473SOmar Sandoval static int hctx_dispatched_open(struct inode *inode, struct file *file) 602be215473SOmar Sandoval { 603be215473SOmar Sandoval return single_open(file, hctx_dispatched_show, inode->i_private); 604be215473SOmar Sandoval } 605be215473SOmar Sandoval 606be215473SOmar Sandoval static ssize_t hctx_dispatched_write(struct file *file, const char __user *buf, 607be215473SOmar Sandoval size_t count, loff_t *ppos) 608be215473SOmar Sandoval { 609be215473SOmar Sandoval struct seq_file *m = file->private_data; 610be215473SOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 611be215473SOmar Sandoval int i; 612be215473SOmar Sandoval 613be215473SOmar Sandoval for (i = 0; i < BLK_MQ_MAX_DISPATCH_ORDER; i++) 614be215473SOmar Sandoval hctx->dispatched[i] = 0; 615be215473SOmar Sandoval return count; 616be215473SOmar Sandoval } 617be215473SOmar Sandoval 618be215473SOmar Sandoval static const struct file_operations hctx_dispatched_fops = { 619be215473SOmar Sandoval .open = hctx_dispatched_open, 620be215473SOmar Sandoval .read = seq_read, 621be215473SOmar Sandoval .write = hctx_dispatched_write, 622be215473SOmar Sandoval .llseek = seq_lseek, 623be215473SOmar Sandoval .release = single_release, 624be215473SOmar Sandoval }; 625be215473SOmar Sandoval 6264a46f05eSOmar Sandoval static int hctx_queued_show(struct seq_file *m, void *v) 6274a46f05eSOmar Sandoval { 6284a46f05eSOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 6294a46f05eSOmar Sandoval 6304a46f05eSOmar Sandoval seq_printf(m, "%lu\n", hctx->queued); 6314a46f05eSOmar Sandoval return 0; 6324a46f05eSOmar Sandoval } 6334a46f05eSOmar Sandoval 6344a46f05eSOmar Sandoval static int hctx_queued_open(struct inode *inode, struct file *file) 6354a46f05eSOmar Sandoval { 6364a46f05eSOmar Sandoval return single_open(file, hctx_queued_show, inode->i_private); 6374a46f05eSOmar Sandoval } 6384a46f05eSOmar Sandoval 6394a46f05eSOmar Sandoval static ssize_t hctx_queued_write(struct file *file, const char __user *buf, 6404a46f05eSOmar Sandoval size_t count, loff_t *ppos) 6414a46f05eSOmar Sandoval { 6424a46f05eSOmar Sandoval struct seq_file *m = file->private_data; 6434a46f05eSOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 6444a46f05eSOmar Sandoval 6454a46f05eSOmar Sandoval hctx->queued = 0; 6464a46f05eSOmar Sandoval return count; 6474a46f05eSOmar Sandoval } 6484a46f05eSOmar Sandoval 6494a46f05eSOmar Sandoval static const struct file_operations hctx_queued_fops = { 6504a46f05eSOmar Sandoval .open = hctx_queued_open, 6514a46f05eSOmar Sandoval .read = seq_read, 6524a46f05eSOmar Sandoval .write = hctx_queued_write, 6534a46f05eSOmar Sandoval .llseek = seq_lseek, 6544a46f05eSOmar Sandoval .release = single_release, 6554a46f05eSOmar Sandoval }; 6564a46f05eSOmar Sandoval 6574a46f05eSOmar Sandoval static int hctx_run_show(struct seq_file *m, void *v) 6584a46f05eSOmar Sandoval { 6594a46f05eSOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 6604a46f05eSOmar Sandoval 6614a46f05eSOmar Sandoval seq_printf(m, "%lu\n", hctx->run); 6624a46f05eSOmar Sandoval return 0; 6634a46f05eSOmar Sandoval } 6644a46f05eSOmar Sandoval 6654a46f05eSOmar Sandoval static int hctx_run_open(struct inode *inode, struct file *file) 6664a46f05eSOmar Sandoval { 6674a46f05eSOmar Sandoval return single_open(file, hctx_run_show, inode->i_private); 6684a46f05eSOmar Sandoval } 6694a46f05eSOmar Sandoval 6704a46f05eSOmar Sandoval static ssize_t hctx_run_write(struct file *file, const char __user *buf, 6714a46f05eSOmar Sandoval size_t count, loff_t *ppos) 6724a46f05eSOmar Sandoval { 6734a46f05eSOmar Sandoval struct seq_file *m = file->private_data; 6744a46f05eSOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 6754a46f05eSOmar Sandoval 6764a46f05eSOmar Sandoval hctx->run = 0; 6774a46f05eSOmar Sandoval return count; 6784a46f05eSOmar Sandoval } 6794a46f05eSOmar Sandoval 6804a46f05eSOmar Sandoval static const struct file_operations hctx_run_fops = { 6814a46f05eSOmar Sandoval .open = hctx_run_open, 6824a46f05eSOmar Sandoval .read = seq_read, 6834a46f05eSOmar Sandoval .write = hctx_run_write, 6844a46f05eSOmar Sandoval .llseek = seq_lseek, 6854a46f05eSOmar Sandoval .release = single_release, 6864a46f05eSOmar Sandoval }; 6874a46f05eSOmar Sandoval 6884a46f05eSOmar Sandoval static int hctx_active_show(struct seq_file *m, void *v) 6894a46f05eSOmar Sandoval { 6904a46f05eSOmar Sandoval struct blk_mq_hw_ctx *hctx = m->private; 6914a46f05eSOmar Sandoval 6924a46f05eSOmar Sandoval seq_printf(m, "%d\n", atomic_read(&hctx->nr_active)); 6934a46f05eSOmar Sandoval return 0; 6944a46f05eSOmar Sandoval } 6954a46f05eSOmar Sandoval 6964a46f05eSOmar Sandoval static int hctx_active_open(struct inode *inode, struct file *file) 6974a46f05eSOmar Sandoval { 6984a46f05eSOmar Sandoval return single_open(file, hctx_active_show, inode->i_private); 6994a46f05eSOmar Sandoval } 7004a46f05eSOmar Sandoval 7014a46f05eSOmar Sandoval static const struct file_operations hctx_active_fops = { 7024a46f05eSOmar Sandoval .open = hctx_active_open, 7034a46f05eSOmar Sandoval .read = seq_read, 7044a46f05eSOmar Sandoval .llseek = seq_lseek, 7054a46f05eSOmar Sandoval .release = single_release, 7064a46f05eSOmar Sandoval }; 7074a46f05eSOmar Sandoval 708950cd7e9SOmar Sandoval static void *ctx_rq_list_start(struct seq_file *m, loff_t *pos) 709f3bcb0e6SBart Van Assche __acquires(&ctx->lock) 710950cd7e9SOmar Sandoval { 711950cd7e9SOmar Sandoval struct blk_mq_ctx *ctx = m->private; 712950cd7e9SOmar Sandoval 713950cd7e9SOmar Sandoval spin_lock(&ctx->lock); 714950cd7e9SOmar Sandoval return seq_list_start(&ctx->rq_list, *pos); 715950cd7e9SOmar Sandoval } 716950cd7e9SOmar Sandoval 717950cd7e9SOmar Sandoval static void *ctx_rq_list_next(struct seq_file *m, void *v, loff_t *pos) 718950cd7e9SOmar Sandoval { 719950cd7e9SOmar Sandoval struct blk_mq_ctx *ctx = m->private; 720950cd7e9SOmar Sandoval 721950cd7e9SOmar Sandoval return seq_list_next(v, &ctx->rq_list, pos); 722950cd7e9SOmar Sandoval } 723950cd7e9SOmar Sandoval 724950cd7e9SOmar Sandoval static void ctx_rq_list_stop(struct seq_file *m, void *v) 725f3bcb0e6SBart Van Assche __releases(&ctx->lock) 726950cd7e9SOmar Sandoval { 727950cd7e9SOmar Sandoval struct blk_mq_ctx *ctx = m->private; 728950cd7e9SOmar Sandoval 729950cd7e9SOmar Sandoval spin_unlock(&ctx->lock); 730950cd7e9SOmar Sandoval } 731950cd7e9SOmar Sandoval 732950cd7e9SOmar Sandoval static const struct seq_operations ctx_rq_list_seq_ops = { 733950cd7e9SOmar Sandoval .start = ctx_rq_list_start, 734950cd7e9SOmar Sandoval .next = ctx_rq_list_next, 735950cd7e9SOmar Sandoval .stop = ctx_rq_list_stop, 736950cd7e9SOmar Sandoval .show = blk_mq_debugfs_rq_show, 737950cd7e9SOmar Sandoval }; 738950cd7e9SOmar Sandoval 739950cd7e9SOmar Sandoval static int ctx_rq_list_open(struct inode *inode, struct file *file) 740950cd7e9SOmar Sandoval { 741950cd7e9SOmar Sandoval return blk_mq_debugfs_seq_open(inode, file, &ctx_rq_list_seq_ops); 742950cd7e9SOmar Sandoval } 743950cd7e9SOmar Sandoval 744950cd7e9SOmar Sandoval static const struct file_operations ctx_rq_list_fops = { 745950cd7e9SOmar Sandoval .open = ctx_rq_list_open, 746950cd7e9SOmar Sandoval .read = seq_read, 747950cd7e9SOmar Sandoval .llseek = seq_lseek, 748950cd7e9SOmar Sandoval .release = seq_release, 749950cd7e9SOmar Sandoval }; 750950cd7e9SOmar Sandoval 7514a46f05eSOmar Sandoval static int ctx_dispatched_show(struct seq_file *m, void *v) 7524a46f05eSOmar Sandoval { 7534a46f05eSOmar Sandoval struct blk_mq_ctx *ctx = m->private; 7544a46f05eSOmar Sandoval 7554a46f05eSOmar Sandoval seq_printf(m, "%lu %lu\n", ctx->rq_dispatched[1], ctx->rq_dispatched[0]); 7564a46f05eSOmar Sandoval return 0; 7574a46f05eSOmar Sandoval } 7584a46f05eSOmar Sandoval 7594a46f05eSOmar Sandoval static int ctx_dispatched_open(struct inode *inode, struct file *file) 7604a46f05eSOmar Sandoval { 7614a46f05eSOmar Sandoval return single_open(file, ctx_dispatched_show, inode->i_private); 7624a46f05eSOmar Sandoval } 7634a46f05eSOmar Sandoval 7644a46f05eSOmar Sandoval static ssize_t ctx_dispatched_write(struct file *file, const char __user *buf, 7654a46f05eSOmar Sandoval size_t count, loff_t *ppos) 7664a46f05eSOmar Sandoval { 7674a46f05eSOmar Sandoval struct seq_file *m = file->private_data; 7684a46f05eSOmar Sandoval struct blk_mq_ctx *ctx = m->private; 7694a46f05eSOmar Sandoval 7704a46f05eSOmar Sandoval ctx->rq_dispatched[0] = ctx->rq_dispatched[1] = 0; 7714a46f05eSOmar Sandoval return count; 7724a46f05eSOmar Sandoval } 7734a46f05eSOmar Sandoval 7744a46f05eSOmar Sandoval static const struct file_operations ctx_dispatched_fops = { 7754a46f05eSOmar Sandoval .open = ctx_dispatched_open, 7764a46f05eSOmar Sandoval .read = seq_read, 7774a46f05eSOmar Sandoval .write = ctx_dispatched_write, 7784a46f05eSOmar Sandoval .llseek = seq_lseek, 7794a46f05eSOmar Sandoval .release = single_release, 7804a46f05eSOmar Sandoval }; 7814a46f05eSOmar Sandoval 7824a46f05eSOmar Sandoval static int ctx_merged_show(struct seq_file *m, void *v) 7834a46f05eSOmar Sandoval { 7844a46f05eSOmar Sandoval struct blk_mq_ctx *ctx = m->private; 7854a46f05eSOmar Sandoval 7864a46f05eSOmar Sandoval seq_printf(m, "%lu\n", ctx->rq_merged); 7874a46f05eSOmar Sandoval return 0; 7884a46f05eSOmar Sandoval } 7894a46f05eSOmar Sandoval 7904a46f05eSOmar Sandoval static int ctx_merged_open(struct inode *inode, struct file *file) 7914a46f05eSOmar Sandoval { 7924a46f05eSOmar Sandoval return single_open(file, ctx_merged_show, inode->i_private); 7934a46f05eSOmar Sandoval } 7944a46f05eSOmar Sandoval 7954a46f05eSOmar Sandoval static ssize_t ctx_merged_write(struct file *file, const char __user *buf, 7964a46f05eSOmar Sandoval size_t count, loff_t *ppos) 7974a46f05eSOmar Sandoval { 7984a46f05eSOmar Sandoval struct seq_file *m = file->private_data; 7994a46f05eSOmar Sandoval struct blk_mq_ctx *ctx = m->private; 8004a46f05eSOmar Sandoval 8014a46f05eSOmar Sandoval ctx->rq_merged = 0; 8024a46f05eSOmar Sandoval return count; 8034a46f05eSOmar Sandoval } 8044a46f05eSOmar Sandoval 8054a46f05eSOmar Sandoval static const struct file_operations ctx_merged_fops = { 8064a46f05eSOmar Sandoval .open = ctx_merged_open, 8074a46f05eSOmar Sandoval .read = seq_read, 8084a46f05eSOmar Sandoval .write = ctx_merged_write, 8094a46f05eSOmar Sandoval .llseek = seq_lseek, 8104a46f05eSOmar Sandoval .release = single_release, 8114a46f05eSOmar Sandoval }; 8124a46f05eSOmar Sandoval 8134a46f05eSOmar Sandoval static int ctx_completed_show(struct seq_file *m, void *v) 8144a46f05eSOmar Sandoval { 8154a46f05eSOmar Sandoval struct blk_mq_ctx *ctx = m->private; 8164a46f05eSOmar Sandoval 8174a46f05eSOmar Sandoval seq_printf(m, "%lu %lu\n", ctx->rq_completed[1], ctx->rq_completed[0]); 8184a46f05eSOmar Sandoval return 0; 8194a46f05eSOmar Sandoval } 8204a46f05eSOmar Sandoval 8214a46f05eSOmar Sandoval static int ctx_completed_open(struct inode *inode, struct file *file) 8224a46f05eSOmar Sandoval { 8234a46f05eSOmar Sandoval return single_open(file, ctx_completed_show, inode->i_private); 8244a46f05eSOmar Sandoval } 8254a46f05eSOmar Sandoval 8264a46f05eSOmar Sandoval static ssize_t ctx_completed_write(struct file *file, const char __user *buf, 8274a46f05eSOmar Sandoval size_t count, loff_t *ppos) 8284a46f05eSOmar Sandoval { 8294a46f05eSOmar Sandoval struct seq_file *m = file->private_data; 8304a46f05eSOmar Sandoval struct blk_mq_ctx *ctx = m->private; 8314a46f05eSOmar Sandoval 8324a46f05eSOmar Sandoval ctx->rq_completed[0] = ctx->rq_completed[1] = 0; 8334a46f05eSOmar Sandoval return count; 8344a46f05eSOmar Sandoval } 8354a46f05eSOmar Sandoval 8364a46f05eSOmar Sandoval static const struct file_operations ctx_completed_fops = { 8374a46f05eSOmar Sandoval .open = ctx_completed_open, 8384a46f05eSOmar Sandoval .read = seq_read, 8394a46f05eSOmar Sandoval .write = ctx_completed_write, 8404a46f05eSOmar Sandoval .llseek = seq_lseek, 8414a46f05eSOmar Sandoval .release = single_release, 8424a46f05eSOmar Sandoval }; 8434a46f05eSOmar Sandoval 84434dbad5dSOmar Sandoval static const struct blk_mq_debugfs_attr blk_mq_debugfs_queue_attrs[] = { 84534dbad5dSOmar Sandoval {"poll_stat", 0400, &queue_poll_stat_fops}, 84665ca1ca3SBart Van Assche {"state", 0600, &blk_queue_flags_fops}, 84734dbad5dSOmar Sandoval {}, 84834dbad5dSOmar Sandoval }; 84934dbad5dSOmar Sandoval 85007e4feadSOmar Sandoval static const struct blk_mq_debugfs_attr blk_mq_debugfs_hctx_attrs[] = { 8519abb2ad2SOmar Sandoval {"state", 0400, &hctx_state_fops}, 8529abb2ad2SOmar Sandoval {"flags", 0400, &hctx_flags_fops}, 853950cd7e9SOmar Sandoval {"dispatch", 0400, &hctx_dispatch_fops}, 8540bfa5288SOmar Sandoval {"ctx_map", 0400, &hctx_ctx_map_fops}, 855d96b37c0SOmar Sandoval {"tags", 0400, &hctx_tags_fops}, 856d7e3621aSOmar Sandoval {"tags_bitmap", 0400, &hctx_tags_bitmap_fops}, 857d96b37c0SOmar Sandoval {"sched_tags", 0400, &hctx_sched_tags_fops}, 858d7e3621aSOmar Sandoval {"sched_tags_bitmap", 0400, &hctx_sched_tags_bitmap_fops}, 859be215473SOmar Sandoval {"io_poll", 0600, &hctx_io_poll_fops}, 860be215473SOmar Sandoval {"dispatched", 0600, &hctx_dispatched_fops}, 8614a46f05eSOmar Sandoval {"queued", 0600, &hctx_queued_fops}, 8624a46f05eSOmar Sandoval {"run", 0600, &hctx_run_fops}, 8634a46f05eSOmar Sandoval {"active", 0400, &hctx_active_fops}, 86472f2f8f6SBart Van Assche {}, 86507e4feadSOmar Sandoval }; 86607e4feadSOmar Sandoval 86707e4feadSOmar Sandoval static const struct blk_mq_debugfs_attr blk_mq_debugfs_ctx_attrs[] = { 868950cd7e9SOmar Sandoval {"rq_list", 0400, &ctx_rq_list_fops}, 8694a46f05eSOmar Sandoval {"dispatched", 0600, &ctx_dispatched_fops}, 8704a46f05eSOmar Sandoval {"merged", 0600, &ctx_merged_fops}, 8714a46f05eSOmar Sandoval {"completed", 0600, &ctx_completed_fops}, 87272f2f8f6SBart Van Assche {}, 87307e4feadSOmar Sandoval }; 87407e4feadSOmar Sandoval 8754c9e4019SBart Van Assche int blk_mq_debugfs_register(struct request_queue *q) 87607e4feadSOmar Sandoval { 87718fbda91SOmar Sandoval if (!blk_debugfs_root) 87807e4feadSOmar Sandoval return -ENOENT; 87907e4feadSOmar Sandoval 8804c9e4019SBart Van Assche q->debugfs_dir = debugfs_create_dir(kobject_name(q->kobj.parent), 8814c9e4019SBart Van Assche blk_debugfs_root); 88207e4feadSOmar Sandoval if (!q->debugfs_dir) 88307e4feadSOmar Sandoval goto err; 88407e4feadSOmar Sandoval 88562d6c949SBart Van Assche if (blk_mq_debugfs_register_mq(q)) 88607e4feadSOmar Sandoval goto err; 88707e4feadSOmar Sandoval 88807e4feadSOmar Sandoval return 0; 88907e4feadSOmar Sandoval 89007e4feadSOmar Sandoval err: 89107e4feadSOmar Sandoval blk_mq_debugfs_unregister(q); 89207e4feadSOmar Sandoval return -ENOMEM; 89307e4feadSOmar Sandoval } 89407e4feadSOmar Sandoval 89507e4feadSOmar Sandoval void blk_mq_debugfs_unregister(struct request_queue *q) 89607e4feadSOmar Sandoval { 89707e4feadSOmar Sandoval debugfs_remove_recursive(q->debugfs_dir); 89807e4feadSOmar Sandoval q->mq_debugfs_dir = NULL; 89907e4feadSOmar Sandoval q->debugfs_dir = NULL; 90007e4feadSOmar Sandoval } 90107e4feadSOmar Sandoval 90272f2f8f6SBart Van Assche static bool debugfs_create_files(struct dentry *parent, void *data, 90372f2f8f6SBart Van Assche const struct blk_mq_debugfs_attr *attr) 90472f2f8f6SBart Van Assche { 90572f2f8f6SBart Van Assche for (; attr->name; attr++) { 90672f2f8f6SBart Van Assche if (!debugfs_create_file(attr->name, attr->mode, parent, 90772f2f8f6SBart Van Assche data, attr->fops)) 90872f2f8f6SBart Van Assche return false; 90972f2f8f6SBart Van Assche } 91072f2f8f6SBart Van Assche return true; 91172f2f8f6SBart Van Assche } 91272f2f8f6SBart Van Assche 91307e4feadSOmar Sandoval static int blk_mq_debugfs_register_ctx(struct request_queue *q, 91407e4feadSOmar Sandoval struct blk_mq_ctx *ctx, 91507e4feadSOmar Sandoval struct dentry *hctx_dir) 91607e4feadSOmar Sandoval { 91707e4feadSOmar Sandoval struct dentry *ctx_dir; 91807e4feadSOmar Sandoval char name[20]; 91907e4feadSOmar Sandoval 92007e4feadSOmar Sandoval snprintf(name, sizeof(name), "cpu%u", ctx->cpu); 92107e4feadSOmar Sandoval ctx_dir = debugfs_create_dir(name, hctx_dir); 92207e4feadSOmar Sandoval if (!ctx_dir) 92307e4feadSOmar Sandoval return -ENOMEM; 92407e4feadSOmar Sandoval 92572f2f8f6SBart Van Assche if (!debugfs_create_files(ctx_dir, ctx, blk_mq_debugfs_ctx_attrs)) 92607e4feadSOmar Sandoval return -ENOMEM; 92707e4feadSOmar Sandoval 92807e4feadSOmar Sandoval return 0; 92907e4feadSOmar Sandoval } 93007e4feadSOmar Sandoval 93107e4feadSOmar Sandoval static int blk_mq_debugfs_register_hctx(struct request_queue *q, 93207e4feadSOmar Sandoval struct blk_mq_hw_ctx *hctx) 93307e4feadSOmar Sandoval { 93407e4feadSOmar Sandoval struct blk_mq_ctx *ctx; 93507e4feadSOmar Sandoval struct dentry *hctx_dir; 93607e4feadSOmar Sandoval char name[20]; 93707e4feadSOmar Sandoval int i; 93807e4feadSOmar Sandoval 939*88aabbd7SOmar Sandoval snprintf(name, sizeof(name), "hctx%u", hctx->queue_num); 94007e4feadSOmar Sandoval hctx_dir = debugfs_create_dir(name, q->mq_debugfs_dir); 94107e4feadSOmar Sandoval if (!hctx_dir) 94207e4feadSOmar Sandoval return -ENOMEM; 94307e4feadSOmar Sandoval 94472f2f8f6SBart Van Assche if (!debugfs_create_files(hctx_dir, hctx, blk_mq_debugfs_hctx_attrs)) 94507e4feadSOmar Sandoval return -ENOMEM; 94607e4feadSOmar Sandoval 94707e4feadSOmar Sandoval hctx_for_each_ctx(hctx, ctx, i) { 94807e4feadSOmar Sandoval if (blk_mq_debugfs_register_ctx(q, ctx, hctx_dir)) 94907e4feadSOmar Sandoval return -ENOMEM; 95007e4feadSOmar Sandoval } 95107e4feadSOmar Sandoval 95207e4feadSOmar Sandoval return 0; 95307e4feadSOmar Sandoval } 95407e4feadSOmar Sandoval 95562d6c949SBart Van Assche int blk_mq_debugfs_register_mq(struct request_queue *q) 95607e4feadSOmar Sandoval { 95707e4feadSOmar Sandoval struct blk_mq_hw_ctx *hctx; 95807e4feadSOmar Sandoval int i; 95907e4feadSOmar Sandoval 96007e4feadSOmar Sandoval if (!q->debugfs_dir) 96107e4feadSOmar Sandoval return -ENOENT; 96207e4feadSOmar Sandoval 96307e4feadSOmar Sandoval q->mq_debugfs_dir = debugfs_create_dir("mq", q->debugfs_dir); 96407e4feadSOmar Sandoval if (!q->mq_debugfs_dir) 96507e4feadSOmar Sandoval goto err; 96607e4feadSOmar Sandoval 96734dbad5dSOmar Sandoval if (!debugfs_create_files(q->mq_debugfs_dir, q, blk_mq_debugfs_queue_attrs)) 96834dbad5dSOmar Sandoval goto err; 96934dbad5dSOmar Sandoval 97007e4feadSOmar Sandoval queue_for_each_hw_ctx(q, hctx, i) { 97107e4feadSOmar Sandoval if (blk_mq_debugfs_register_hctx(q, hctx)) 97207e4feadSOmar Sandoval goto err; 97307e4feadSOmar Sandoval } 97407e4feadSOmar Sandoval 97507e4feadSOmar Sandoval return 0; 97607e4feadSOmar Sandoval 97707e4feadSOmar Sandoval err: 97862d6c949SBart Van Assche blk_mq_debugfs_unregister_mq(q); 97907e4feadSOmar Sandoval return -ENOMEM; 98007e4feadSOmar Sandoval } 98107e4feadSOmar Sandoval 98262d6c949SBart Van Assche void blk_mq_debugfs_unregister_mq(struct request_queue *q) 98307e4feadSOmar Sandoval { 98407e4feadSOmar Sandoval debugfs_remove_recursive(q->mq_debugfs_dir); 98507e4feadSOmar Sandoval q->mq_debugfs_dir = NULL; 98607e4feadSOmar Sandoval } 987