1 // SPDX-License-Identifier: GPL-2.0
3 * DebugFS interface for the NVMe target.
4 * Copyright (c) 2022-2024 Shadow
5 * Copyright (c) 2024 SUSE LLC
8 #include <linux/debugfs.h>
10 #include <linux/init.h>
11 #include <linux/kernel.h>
16 static struct dentry
*nvmet_debugfs
;
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); } \
22 static const struct file_operations field##_fops = { \
23 .open = field##_open, \
25 .release = single_release, \
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); } \
32 static const struct file_operations field##_fops = { \
33 .open = field##_open, \
35 .write = field##_write, \
36 .release = single_release, \
39 static int nvmet_ctrl_hostnqn_show(struct seq_file
*m
, void *p
)
41 struct nvmet_ctrl
*ctrl
= m
->private;
43 seq_puts(m
, ctrl
->hostnqn
);
46 NVMET_DEBUGFS_ATTR(nvmet_ctrl_hostnqn
);
48 static int nvmet_ctrl_kato_show(struct seq_file
*m
, void *p
)
50 struct nvmet_ctrl
*ctrl
= m
->private;
52 seq_printf(m
, "%d\n", ctrl
->kato
);
55 NVMET_DEBUGFS_ATTR(nvmet_ctrl_kato
);
57 static int nvmet_ctrl_port_show(struct seq_file
*m
, void *p
)
59 struct nvmet_ctrl
*ctrl
= m
->private;
61 seq_printf(m
, "%d\n", le16_to_cpu(ctrl
->port
->disc_addr
.portid
));
64 NVMET_DEBUGFS_ATTR(nvmet_ctrl_port
);
66 static 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",
75 static int nvmet_ctrl_state_show(struct seq_file
*m
, void *p
)
77 struct nvmet_ctrl
*ctrl
= m
->private;
81 for (i
= 0; i
< 7; i
++) {
84 if (!(ctrl
->csts
& state
))
89 if (csts_state_names
[state
])
90 seq_puts(m
, csts_state_names
[state
]);
92 seq_printf(m
, "%d", state
);
99 static ssize_t
nvmet_ctrl_state_write(struct file
*file
, const char __user
*buf
,
100 size_t count
, loff_t
*ppos
)
102 struct seq_file
*m
= file
->private_data
;
103 struct nvmet_ctrl
*ctrl
= m
->private;
106 if (count
>= sizeof(reset
))
108 if (copy_from_user(reset
, buf
, count
))
110 if (!memcmp(reset
, "fatal", 5))
111 nvmet_ctrl_fatal_error(ctrl
);
116 NVMET_DEBUGFS_RW_ATTR(nvmet_ctrl_state
);
118 static int nvmet_ctrl_host_traddr_show(struct seq_file
*m
, void *p
)
120 struct nvmet_ctrl
*ctrl
= m
->private;
122 char buf
[NVMF_TRADDR_SIZE
+ 1];
124 size
= nvmet_ctrl_host_traddr(ctrl
, buf
, NVMF_TRADDR_SIZE
);
130 seq_printf(m
, "%s\n", buf
);
133 NVMET_DEBUGFS_ATTR(nvmet_ctrl_host_traddr
);
135 int nvmet_debugfs_ctrl_setup(struct nvmet_ctrl
*ctrl
)
138 struct dentry
*parent
= ctrl
->subsys
->debugfs_dir
;
143 snprintf(name
, sizeof(name
), "ctrl%d", ctrl
->cntlid
);
144 ctrl
->debugfs_dir
= debugfs_create_dir(name
, parent
);
145 if (IS_ERR(ctrl
->debugfs_dir
)) {
146 ret
= PTR_ERR(ctrl
->debugfs_dir
);
147 ctrl
->debugfs_dir
= NULL
;
150 debugfs_create_file("port", S_IRUSR
, ctrl
->debugfs_dir
, ctrl
,
151 &nvmet_ctrl_port_fops
);
152 debugfs_create_file("hostnqn", S_IRUSR
, ctrl
->debugfs_dir
, ctrl
,
153 &nvmet_ctrl_hostnqn_fops
);
154 debugfs_create_file("kato", S_IRUSR
, ctrl
->debugfs_dir
, ctrl
,
155 &nvmet_ctrl_kato_fops
);
156 debugfs_create_file("state", S_IRUSR
| S_IWUSR
, ctrl
->debugfs_dir
, ctrl
,
157 &nvmet_ctrl_state_fops
);
158 debugfs_create_file("host_traddr", S_IRUSR
, ctrl
->debugfs_dir
, ctrl
,
159 &nvmet_ctrl_host_traddr_fops
);
163 void nvmet_debugfs_ctrl_free(struct nvmet_ctrl
*ctrl
)
165 debugfs_remove_recursive(ctrl
->debugfs_dir
);
168 int nvmet_debugfs_subsys_setup(struct nvmet_subsys
*subsys
)
172 subsys
->debugfs_dir
= debugfs_create_dir(subsys
->subsysnqn
,
174 if (IS_ERR(subsys
->debugfs_dir
)) {
175 ret
= PTR_ERR(subsys
->debugfs_dir
);
176 subsys
->debugfs_dir
= NULL
;
181 void nvmet_debugfs_subsys_free(struct nvmet_subsys
*subsys
)
183 debugfs_remove_recursive(subsys
->debugfs_dir
);
186 int __init
nvmet_init_debugfs(void)
188 struct dentry
*parent
;
190 parent
= debugfs_create_dir("nvmet", NULL
);
191 if (IS_ERR(parent
)) {
192 pr_warn("%s: failed to create debugfs directory\n", "nvmet");
193 return PTR_ERR(parent
);
195 nvmet_debugfs
= parent
;
199 void nvmet_exit_debugfs(void)
201 debugfs_remove_recursive(nvmet_debugfs
);