at master 5.6 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * DebugFS interface for the NVMe target. 4 * Copyright (c) 2022-2024 Shadow 5 * Copyright (c) 2024 SUSE LLC 6 */ 7 8#include <linux/debugfs.h> 9#include <linux/fs.h> 10#include <linux/init.h> 11#include <linux/kernel.h> 12 13#include "nvmet.h" 14#include "debugfs.h" 15 16static struct dentry *nvmet_debugfs; 17 18#define NVMET_DEBUGFS_ATTR(field) \ 19 static int field##_open(struct inode *inode, struct file *file) \ 20 { return single_open(file, field##_show, inode->i_private); } \ 21 \ 22 static const struct file_operations field##_fops = { \ 23 .open = field##_open, \ 24 .read = seq_read, \ 25 .release = single_release, \ 26 } 27 28#define NVMET_DEBUGFS_RW_ATTR(field) \ 29 static int field##_open(struct inode *inode, struct file *file) \ 30 { return single_open(file, field##_show, inode->i_private); } \ 31 \ 32 static const struct file_operations field##_fops = { \ 33 .open = field##_open, \ 34 .read = seq_read, \ 35 .write = field##_write, \ 36 .release = single_release, \ 37 } 38 39static int nvmet_ctrl_hostnqn_show(struct seq_file *m, void *p) 40{ 41 struct nvmet_ctrl *ctrl = m->private; 42 43 seq_puts(m, ctrl->hostnqn); 44 return 0; 45} 46NVMET_DEBUGFS_ATTR(nvmet_ctrl_hostnqn); 47 48static int nvmet_ctrl_kato_show(struct seq_file *m, void *p) 49{ 50 struct nvmet_ctrl *ctrl = m->private; 51 52 seq_printf(m, "%d\n", ctrl->kato); 53 return 0; 54} 55NVMET_DEBUGFS_ATTR(nvmet_ctrl_kato); 56 57static int nvmet_ctrl_port_show(struct seq_file *m, void *p) 58{ 59 struct nvmet_ctrl *ctrl = m->private; 60 61 seq_printf(m, "%d\n", le16_to_cpu(ctrl->port->disc_addr.portid)); 62 return 0; 63} 64NVMET_DEBUGFS_ATTR(nvmet_ctrl_port); 65 66static const char *const csts_state_names[] = { 67 [NVME_CSTS_RDY] = "ready", 68 [NVME_CSTS_CFS] = "fatal", 69 [NVME_CSTS_NSSRO] = "reset", 70 [NVME_CSTS_SHST_OCCUR] = "shutdown", 71 [NVME_CSTS_SHST_CMPLT] = "completed", 72 [NVME_CSTS_PP] = "paused", 73}; 74 75static int nvmet_ctrl_state_show(struct seq_file *m, void *p) 76{ 77 struct nvmet_ctrl *ctrl = m->private; 78 bool sep = false; 79 int i; 80 81 for (i = 0; i < ARRAY_SIZE(csts_state_names); i++) { 82 int state = BIT(i); 83 84 if (!(ctrl->csts & state)) 85 continue; 86 if (sep) 87 seq_puts(m, "|"); 88 sep = true; 89 if (csts_state_names[state]) 90 seq_puts(m, csts_state_names[state]); 91 else 92 seq_printf(m, "%d", state); 93 } 94 if (sep) 95 seq_printf(m, "\n"); 96 return 0; 97} 98 99static ssize_t nvmet_ctrl_state_write(struct file *file, const char __user *buf, 100 size_t count, loff_t *ppos) 101{ 102 struct seq_file *m = file->private_data; 103 struct nvmet_ctrl *ctrl = m->private; 104 char reset[16]; 105 106 if (count >= sizeof(reset)) 107 return -EINVAL; 108 if (copy_from_user(reset, buf, count)) 109 return -EFAULT; 110 if (!memcmp(reset, "fatal", 5)) 111 nvmet_ctrl_fatal_error(ctrl); 112 else 113 return -EINVAL; 114 return count; 115} 116NVMET_DEBUGFS_RW_ATTR(nvmet_ctrl_state); 117 118static int nvmet_ctrl_host_traddr_show(struct seq_file *m, void *p) 119{ 120 struct nvmet_ctrl *ctrl = m->private; 121 ssize_t size; 122 char buf[NVMF_TRADDR_SIZE + 1]; 123 124 size = nvmet_ctrl_host_traddr(ctrl, buf, NVMF_TRADDR_SIZE); 125 if (size < 0) { 126 buf[0] = '\0'; 127 size = 0; 128 } 129 buf[size] = '\0'; 130 seq_printf(m, "%s\n", buf); 131 return 0; 132} 133NVMET_DEBUGFS_ATTR(nvmet_ctrl_host_traddr); 134 135#ifdef CONFIG_NVME_TARGET_TCP_TLS 136static int nvmet_ctrl_tls_key_show(struct seq_file *m, void *p) 137{ 138 struct nvmet_ctrl *ctrl = m->private; 139 key_serial_t keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]); 140 141 seq_printf(m, "%08x\n", keyid); 142 return 0; 143} 144NVMET_DEBUGFS_ATTR(nvmet_ctrl_tls_key); 145 146static int nvmet_ctrl_tls_concat_show(struct seq_file *m, void *p) 147{ 148 struct nvmet_ctrl *ctrl = m->private; 149 150 seq_printf(m, "%d\n", ctrl->concat); 151 return 0; 152} 153NVMET_DEBUGFS_ATTR(nvmet_ctrl_tls_concat); 154#endif 155 156int nvmet_debugfs_ctrl_setup(struct nvmet_ctrl *ctrl) 157{ 158 char name[32]; 159 struct dentry *parent = ctrl->subsys->debugfs_dir; 160 int ret; 161 162 if (!parent) 163 return -ENODEV; 164 snprintf(name, sizeof(name), "ctrl%d", ctrl->cntlid); 165 ctrl->debugfs_dir = debugfs_create_dir(name, parent); 166 if (IS_ERR(ctrl->debugfs_dir)) { 167 ret = PTR_ERR(ctrl->debugfs_dir); 168 ctrl->debugfs_dir = NULL; 169 return ret; 170 } 171 debugfs_create_file("port", S_IRUSR, ctrl->debugfs_dir, ctrl, 172 &nvmet_ctrl_port_fops); 173 debugfs_create_file("hostnqn", S_IRUSR, ctrl->debugfs_dir, ctrl, 174 &nvmet_ctrl_hostnqn_fops); 175 debugfs_create_file("kato", S_IRUSR, ctrl->debugfs_dir, ctrl, 176 &nvmet_ctrl_kato_fops); 177 debugfs_create_file("state", S_IRUSR | S_IWUSR, ctrl->debugfs_dir, ctrl, 178 &nvmet_ctrl_state_fops); 179 debugfs_create_file("host_traddr", S_IRUSR, ctrl->debugfs_dir, ctrl, 180 &nvmet_ctrl_host_traddr_fops); 181#ifdef CONFIG_NVME_TARGET_TCP_TLS 182 debugfs_create_file("tls_concat", S_IRUSR, ctrl->debugfs_dir, ctrl, 183 &nvmet_ctrl_tls_concat_fops); 184 debugfs_create_file("tls_key", S_IRUSR, ctrl->debugfs_dir, ctrl, 185 &nvmet_ctrl_tls_key_fops); 186#endif 187 return 0; 188} 189 190void nvmet_debugfs_ctrl_free(struct nvmet_ctrl *ctrl) 191{ 192 debugfs_remove_recursive(ctrl->debugfs_dir); 193} 194 195int nvmet_debugfs_subsys_setup(struct nvmet_subsys *subsys) 196{ 197 int ret = 0; 198 199 subsys->debugfs_dir = debugfs_create_dir(subsys->subsysnqn, 200 nvmet_debugfs); 201 if (IS_ERR(subsys->debugfs_dir)) { 202 ret = PTR_ERR(subsys->debugfs_dir); 203 subsys->debugfs_dir = NULL; 204 } 205 return ret; 206} 207 208void nvmet_debugfs_subsys_free(struct nvmet_subsys *subsys) 209{ 210 debugfs_remove_recursive(subsys->debugfs_dir); 211} 212 213int __init nvmet_init_debugfs(void) 214{ 215 struct dentry *parent; 216 217 parent = debugfs_create_dir("nvmet", NULL); 218 if (IS_ERR(parent)) { 219 pr_warn("%s: failed to create debugfs directory\n", "nvmet"); 220 return PTR_ERR(parent); 221 } 222 nvmet_debugfs = parent; 223 return 0; 224} 225 226void nvmet_exit_debugfs(void) 227{ 228 debugfs_remove_recursive(nvmet_debugfs); 229}