File Index
Files and directories
Sign in
FILE

debugfs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/nvme/target/debugfs.c C
  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}
~/ Read-only file preview.