1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Configfs interface for the NVMe target.
4*4882a593Smuzhiyun * Copyright (c) 2015-2016 HGST, a Western Digital Company.
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7*4882a593Smuzhiyun #include <linux/kernel.h>
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/slab.h>
10*4882a593Smuzhiyun #include <linux/stat.h>
11*4882a593Smuzhiyun #include <linux/ctype.h>
12*4882a593Smuzhiyun #include <linux/pci.h>
13*4882a593Smuzhiyun #include <linux/pci-p2pdma.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include "nvmet.h"
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun static const struct config_item_type nvmet_host_type;
18*4882a593Smuzhiyun static const struct config_item_type nvmet_subsys_type;
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun static LIST_HEAD(nvmet_ports_list);
21*4882a593Smuzhiyun struct list_head *nvmet_ports = &nvmet_ports_list;
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun struct nvmet_type_name_map {
24*4882a593Smuzhiyun u8 type;
25*4882a593Smuzhiyun const char *name;
26*4882a593Smuzhiyun };
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun static struct nvmet_type_name_map nvmet_transport[] = {
29*4882a593Smuzhiyun { NVMF_TRTYPE_RDMA, "rdma" },
30*4882a593Smuzhiyun { NVMF_TRTYPE_FC, "fc" },
31*4882a593Smuzhiyun { NVMF_TRTYPE_TCP, "tcp" },
32*4882a593Smuzhiyun { NVMF_TRTYPE_LOOP, "loop" },
33*4882a593Smuzhiyun };
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun static const struct nvmet_type_name_map nvmet_addr_family[] = {
36*4882a593Smuzhiyun { NVMF_ADDR_FAMILY_PCI, "pcie" },
37*4882a593Smuzhiyun { NVMF_ADDR_FAMILY_IP4, "ipv4" },
38*4882a593Smuzhiyun { NVMF_ADDR_FAMILY_IP6, "ipv6" },
39*4882a593Smuzhiyun { NVMF_ADDR_FAMILY_IB, "ib" },
40*4882a593Smuzhiyun { NVMF_ADDR_FAMILY_FC, "fc" },
41*4882a593Smuzhiyun { NVMF_ADDR_FAMILY_LOOP, "loop" },
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun
nvmet_is_port_enabled(struct nvmet_port * p,const char * caller)44*4882a593Smuzhiyun static bool nvmet_is_port_enabled(struct nvmet_port *p, const char *caller)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun if (p->enabled)
47*4882a593Smuzhiyun pr_err("Disable port '%u' before changing attribute in %s\n",
48*4882a593Smuzhiyun le16_to_cpu(p->disc_addr.portid), caller);
49*4882a593Smuzhiyun return p->enabled;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /*
53*4882a593Smuzhiyun * nvmet_port Generic ConfigFS definitions.
54*4882a593Smuzhiyun * Used in any place in the ConfigFS tree that refers to an address.
55*4882a593Smuzhiyun */
nvmet_addr_adrfam_show(struct config_item * item,char * page)56*4882a593Smuzhiyun static ssize_t nvmet_addr_adrfam_show(struct config_item *item, char *page)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun u8 adrfam = to_nvmet_port(item)->disc_addr.adrfam;
59*4882a593Smuzhiyun int i;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun for (i = 1; i < ARRAY_SIZE(nvmet_addr_family); i++) {
62*4882a593Smuzhiyun if (nvmet_addr_family[i].type == adrfam)
63*4882a593Smuzhiyun return sprintf(page, "%s\n", nvmet_addr_family[i].name);
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun return sprintf(page, "\n");
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
nvmet_addr_adrfam_store(struct config_item * item,const char * page,size_t count)69*4882a593Smuzhiyun static ssize_t nvmet_addr_adrfam_store(struct config_item *item,
70*4882a593Smuzhiyun const char *page, size_t count)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
73*4882a593Smuzhiyun int i;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun if (nvmet_is_port_enabled(port, __func__))
76*4882a593Smuzhiyun return -EACCES;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun for (i = 1; i < ARRAY_SIZE(nvmet_addr_family); i++) {
79*4882a593Smuzhiyun if (sysfs_streq(page, nvmet_addr_family[i].name))
80*4882a593Smuzhiyun goto found;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun pr_err("Invalid value '%s' for adrfam\n", page);
84*4882a593Smuzhiyun return -EINVAL;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun found:
87*4882a593Smuzhiyun port->disc_addr.adrfam = nvmet_addr_family[i].type;
88*4882a593Smuzhiyun return count;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_, addr_adrfam);
92*4882a593Smuzhiyun
nvmet_addr_portid_show(struct config_item * item,char * page)93*4882a593Smuzhiyun static ssize_t nvmet_addr_portid_show(struct config_item *item,
94*4882a593Smuzhiyun char *page)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%d\n",
99*4882a593Smuzhiyun le16_to_cpu(port->disc_addr.portid));
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
nvmet_addr_portid_store(struct config_item * item,const char * page,size_t count)102*4882a593Smuzhiyun static ssize_t nvmet_addr_portid_store(struct config_item *item,
103*4882a593Smuzhiyun const char *page, size_t count)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
106*4882a593Smuzhiyun u16 portid = 0;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun if (kstrtou16(page, 0, &portid)) {
109*4882a593Smuzhiyun pr_err("Invalid value '%s' for portid\n", page);
110*4882a593Smuzhiyun return -EINVAL;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun if (nvmet_is_port_enabled(port, __func__))
114*4882a593Smuzhiyun return -EACCES;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun port->disc_addr.portid = cpu_to_le16(portid);
117*4882a593Smuzhiyun return count;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_, addr_portid);
121*4882a593Smuzhiyun
nvmet_addr_traddr_show(struct config_item * item,char * page)122*4882a593Smuzhiyun static ssize_t nvmet_addr_traddr_show(struct config_item *item,
123*4882a593Smuzhiyun char *page)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%s\n",
128*4882a593Smuzhiyun port->disc_addr.traddr);
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
nvmet_addr_traddr_store(struct config_item * item,const char * page,size_t count)131*4882a593Smuzhiyun static ssize_t nvmet_addr_traddr_store(struct config_item *item,
132*4882a593Smuzhiyun const char *page, size_t count)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun if (count > NVMF_TRADDR_SIZE) {
137*4882a593Smuzhiyun pr_err("Invalid value '%s' for traddr\n", page);
138*4882a593Smuzhiyun return -EINVAL;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun if (nvmet_is_port_enabled(port, __func__))
142*4882a593Smuzhiyun return -EACCES;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun if (sscanf(page, "%s\n", port->disc_addr.traddr) != 1)
145*4882a593Smuzhiyun return -EINVAL;
146*4882a593Smuzhiyun return count;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_, addr_traddr);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun static const struct nvmet_type_name_map nvmet_addr_treq[] = {
152*4882a593Smuzhiyun { NVMF_TREQ_NOT_SPECIFIED, "not specified" },
153*4882a593Smuzhiyun { NVMF_TREQ_REQUIRED, "required" },
154*4882a593Smuzhiyun { NVMF_TREQ_NOT_REQUIRED, "not required" },
155*4882a593Smuzhiyun };
156*4882a593Smuzhiyun
nvmet_addr_treq_show(struct config_item * item,char * page)157*4882a593Smuzhiyun static ssize_t nvmet_addr_treq_show(struct config_item *item, char *page)
158*4882a593Smuzhiyun {
159*4882a593Smuzhiyun u8 treq = to_nvmet_port(item)->disc_addr.treq &
160*4882a593Smuzhiyun NVME_TREQ_SECURE_CHANNEL_MASK;
161*4882a593Smuzhiyun int i;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(nvmet_addr_treq); i++) {
164*4882a593Smuzhiyun if (treq == nvmet_addr_treq[i].type)
165*4882a593Smuzhiyun return sprintf(page, "%s\n", nvmet_addr_treq[i].name);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun return sprintf(page, "\n");
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
nvmet_addr_treq_store(struct config_item * item,const char * page,size_t count)171*4882a593Smuzhiyun static ssize_t nvmet_addr_treq_store(struct config_item *item,
172*4882a593Smuzhiyun const char *page, size_t count)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
175*4882a593Smuzhiyun u8 treq = port->disc_addr.treq & ~NVME_TREQ_SECURE_CHANNEL_MASK;
176*4882a593Smuzhiyun int i;
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun if (nvmet_is_port_enabled(port, __func__))
179*4882a593Smuzhiyun return -EACCES;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(nvmet_addr_treq); i++) {
182*4882a593Smuzhiyun if (sysfs_streq(page, nvmet_addr_treq[i].name))
183*4882a593Smuzhiyun goto found;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun pr_err("Invalid value '%s' for treq\n", page);
187*4882a593Smuzhiyun return -EINVAL;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun found:
190*4882a593Smuzhiyun treq |= nvmet_addr_treq[i].type;
191*4882a593Smuzhiyun port->disc_addr.treq = treq;
192*4882a593Smuzhiyun return count;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_, addr_treq);
196*4882a593Smuzhiyun
nvmet_addr_trsvcid_show(struct config_item * item,char * page)197*4882a593Smuzhiyun static ssize_t nvmet_addr_trsvcid_show(struct config_item *item,
198*4882a593Smuzhiyun char *page)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%s\n",
203*4882a593Smuzhiyun port->disc_addr.trsvcid);
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
nvmet_addr_trsvcid_store(struct config_item * item,const char * page,size_t count)206*4882a593Smuzhiyun static ssize_t nvmet_addr_trsvcid_store(struct config_item *item,
207*4882a593Smuzhiyun const char *page, size_t count)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun if (count > NVMF_TRSVCID_SIZE) {
212*4882a593Smuzhiyun pr_err("Invalid value '%s' for trsvcid\n", page);
213*4882a593Smuzhiyun return -EINVAL;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun if (nvmet_is_port_enabled(port, __func__))
216*4882a593Smuzhiyun return -EACCES;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun if (sscanf(page, "%s\n", port->disc_addr.trsvcid) != 1)
219*4882a593Smuzhiyun return -EINVAL;
220*4882a593Smuzhiyun return count;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_, addr_trsvcid);
224*4882a593Smuzhiyun
nvmet_param_inline_data_size_show(struct config_item * item,char * page)225*4882a593Smuzhiyun static ssize_t nvmet_param_inline_data_size_show(struct config_item *item,
226*4882a593Smuzhiyun char *page)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%d\n", port->inline_data_size);
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
nvmet_param_inline_data_size_store(struct config_item * item,const char * page,size_t count)233*4882a593Smuzhiyun static ssize_t nvmet_param_inline_data_size_store(struct config_item *item,
234*4882a593Smuzhiyun const char *page, size_t count)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
237*4882a593Smuzhiyun int ret;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun if (nvmet_is_port_enabled(port, __func__))
240*4882a593Smuzhiyun return -EACCES;
241*4882a593Smuzhiyun ret = kstrtoint(page, 0, &port->inline_data_size);
242*4882a593Smuzhiyun if (ret) {
243*4882a593Smuzhiyun pr_err("Invalid value '%s' for inline_data_size\n", page);
244*4882a593Smuzhiyun return -EINVAL;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun return count;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_, param_inline_data_size);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun #ifdef CONFIG_BLK_DEV_INTEGRITY
nvmet_param_pi_enable_show(struct config_item * item,char * page)252*4882a593Smuzhiyun static ssize_t nvmet_param_pi_enable_show(struct config_item *item,
253*4882a593Smuzhiyun char *page)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%d\n", port->pi_enable);
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
nvmet_param_pi_enable_store(struct config_item * item,const char * page,size_t count)260*4882a593Smuzhiyun static ssize_t nvmet_param_pi_enable_store(struct config_item *item,
261*4882a593Smuzhiyun const char *page, size_t count)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
264*4882a593Smuzhiyun bool val;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun if (strtobool(page, &val))
267*4882a593Smuzhiyun return -EINVAL;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun if (port->enabled) {
270*4882a593Smuzhiyun pr_err("Disable port before setting pi_enable value.\n");
271*4882a593Smuzhiyun return -EACCES;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun port->pi_enable = val;
275*4882a593Smuzhiyun return count;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_, param_pi_enable);
279*4882a593Smuzhiyun #endif
280*4882a593Smuzhiyun
nvmet_addr_trtype_show(struct config_item * item,char * page)281*4882a593Smuzhiyun static ssize_t nvmet_addr_trtype_show(struct config_item *item,
282*4882a593Smuzhiyun char *page)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
285*4882a593Smuzhiyun int i;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(nvmet_transport); i++) {
288*4882a593Smuzhiyun if (port->disc_addr.trtype == nvmet_transport[i].type)
289*4882a593Smuzhiyun return sprintf(page, "%s\n", nvmet_transport[i].name);
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun return sprintf(page, "\n");
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
nvmet_port_init_tsas_rdma(struct nvmet_port * port)295*4882a593Smuzhiyun static void nvmet_port_init_tsas_rdma(struct nvmet_port *port)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun port->disc_addr.tsas.rdma.qptype = NVMF_RDMA_QPTYPE_CONNECTED;
298*4882a593Smuzhiyun port->disc_addr.tsas.rdma.prtype = NVMF_RDMA_PRTYPE_NOT_SPECIFIED;
299*4882a593Smuzhiyun port->disc_addr.tsas.rdma.cms = NVMF_RDMA_CMS_RDMA_CM;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
nvmet_addr_trtype_store(struct config_item * item,const char * page,size_t count)302*4882a593Smuzhiyun static ssize_t nvmet_addr_trtype_store(struct config_item *item,
303*4882a593Smuzhiyun const char *page, size_t count)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
306*4882a593Smuzhiyun int i;
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun if (nvmet_is_port_enabled(port, __func__))
309*4882a593Smuzhiyun return -EACCES;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(nvmet_transport); i++) {
312*4882a593Smuzhiyun if (sysfs_streq(page, nvmet_transport[i].name))
313*4882a593Smuzhiyun goto found;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun pr_err("Invalid value '%s' for trtype\n", page);
317*4882a593Smuzhiyun return -EINVAL;
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun found:
320*4882a593Smuzhiyun memset(&port->disc_addr.tsas, 0, NVMF_TSAS_SIZE);
321*4882a593Smuzhiyun port->disc_addr.trtype = nvmet_transport[i].type;
322*4882a593Smuzhiyun if (port->disc_addr.trtype == NVMF_TRTYPE_RDMA)
323*4882a593Smuzhiyun nvmet_port_init_tsas_rdma(port);
324*4882a593Smuzhiyun return count;
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_, addr_trtype);
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun /*
330*4882a593Smuzhiyun * Namespace structures & file operation functions below
331*4882a593Smuzhiyun */
nvmet_ns_device_path_show(struct config_item * item,char * page)332*4882a593Smuzhiyun static ssize_t nvmet_ns_device_path_show(struct config_item *item, char *page)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun return sprintf(page, "%s\n", to_nvmet_ns(item)->device_path);
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun
nvmet_ns_device_path_store(struct config_item * item,const char * page,size_t count)337*4882a593Smuzhiyun static ssize_t nvmet_ns_device_path_store(struct config_item *item,
338*4882a593Smuzhiyun const char *page, size_t count)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun struct nvmet_ns *ns = to_nvmet_ns(item);
341*4882a593Smuzhiyun struct nvmet_subsys *subsys = ns->subsys;
342*4882a593Smuzhiyun size_t len;
343*4882a593Smuzhiyun int ret;
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun mutex_lock(&subsys->lock);
346*4882a593Smuzhiyun ret = -EBUSY;
347*4882a593Smuzhiyun if (ns->enabled)
348*4882a593Smuzhiyun goto out_unlock;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun ret = -EINVAL;
351*4882a593Smuzhiyun len = strcspn(page, "\n");
352*4882a593Smuzhiyun if (!len)
353*4882a593Smuzhiyun goto out_unlock;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun kfree(ns->device_path);
356*4882a593Smuzhiyun ret = -ENOMEM;
357*4882a593Smuzhiyun ns->device_path = kmemdup_nul(page, len, GFP_KERNEL);
358*4882a593Smuzhiyun if (!ns->device_path)
359*4882a593Smuzhiyun goto out_unlock;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun mutex_unlock(&subsys->lock);
362*4882a593Smuzhiyun return count;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun out_unlock:
365*4882a593Smuzhiyun mutex_unlock(&subsys->lock);
366*4882a593Smuzhiyun return ret;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_ns_, device_path);
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun #ifdef CONFIG_PCI_P2PDMA
nvmet_ns_p2pmem_show(struct config_item * item,char * page)372*4882a593Smuzhiyun static ssize_t nvmet_ns_p2pmem_show(struct config_item *item, char *page)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun struct nvmet_ns *ns = to_nvmet_ns(item);
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun return pci_p2pdma_enable_show(page, ns->p2p_dev, ns->use_p2pmem);
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun
nvmet_ns_p2pmem_store(struct config_item * item,const char * page,size_t count)379*4882a593Smuzhiyun static ssize_t nvmet_ns_p2pmem_store(struct config_item *item,
380*4882a593Smuzhiyun const char *page, size_t count)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun struct nvmet_ns *ns = to_nvmet_ns(item);
383*4882a593Smuzhiyun struct pci_dev *p2p_dev = NULL;
384*4882a593Smuzhiyun bool use_p2pmem;
385*4882a593Smuzhiyun int ret = count;
386*4882a593Smuzhiyun int error;
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun mutex_lock(&ns->subsys->lock);
389*4882a593Smuzhiyun if (ns->enabled) {
390*4882a593Smuzhiyun ret = -EBUSY;
391*4882a593Smuzhiyun goto out_unlock;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun error = pci_p2pdma_enable_store(page, &p2p_dev, &use_p2pmem);
395*4882a593Smuzhiyun if (error) {
396*4882a593Smuzhiyun ret = error;
397*4882a593Smuzhiyun goto out_unlock;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun ns->use_p2pmem = use_p2pmem;
401*4882a593Smuzhiyun pci_dev_put(ns->p2p_dev);
402*4882a593Smuzhiyun ns->p2p_dev = p2p_dev;
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun out_unlock:
405*4882a593Smuzhiyun mutex_unlock(&ns->subsys->lock);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun return ret;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_ns_, p2pmem);
411*4882a593Smuzhiyun #endif /* CONFIG_PCI_P2PDMA */
412*4882a593Smuzhiyun
nvmet_ns_device_uuid_show(struct config_item * item,char * page)413*4882a593Smuzhiyun static ssize_t nvmet_ns_device_uuid_show(struct config_item *item, char *page)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun return sprintf(page, "%pUb\n", &to_nvmet_ns(item)->uuid);
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
nvmet_ns_device_uuid_store(struct config_item * item,const char * page,size_t count)418*4882a593Smuzhiyun static ssize_t nvmet_ns_device_uuid_store(struct config_item *item,
419*4882a593Smuzhiyun const char *page, size_t count)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun struct nvmet_ns *ns = to_nvmet_ns(item);
422*4882a593Smuzhiyun struct nvmet_subsys *subsys = ns->subsys;
423*4882a593Smuzhiyun int ret = 0;
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun mutex_lock(&subsys->lock);
426*4882a593Smuzhiyun if (ns->enabled) {
427*4882a593Smuzhiyun ret = -EBUSY;
428*4882a593Smuzhiyun goto out_unlock;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun if (uuid_parse(page, &ns->uuid))
432*4882a593Smuzhiyun ret = -EINVAL;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun out_unlock:
435*4882a593Smuzhiyun mutex_unlock(&subsys->lock);
436*4882a593Smuzhiyun return ret ? ret : count;
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_ns_, device_uuid);
440*4882a593Smuzhiyun
nvmet_ns_device_nguid_show(struct config_item * item,char * page)441*4882a593Smuzhiyun static ssize_t nvmet_ns_device_nguid_show(struct config_item *item, char *page)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun return sprintf(page, "%pUb\n", &to_nvmet_ns(item)->nguid);
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun
nvmet_ns_device_nguid_store(struct config_item * item,const char * page,size_t count)446*4882a593Smuzhiyun static ssize_t nvmet_ns_device_nguid_store(struct config_item *item,
447*4882a593Smuzhiyun const char *page, size_t count)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun struct nvmet_ns *ns = to_nvmet_ns(item);
450*4882a593Smuzhiyun struct nvmet_subsys *subsys = ns->subsys;
451*4882a593Smuzhiyun u8 nguid[16];
452*4882a593Smuzhiyun const char *p = page;
453*4882a593Smuzhiyun int i;
454*4882a593Smuzhiyun int ret = 0;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun mutex_lock(&subsys->lock);
457*4882a593Smuzhiyun if (ns->enabled) {
458*4882a593Smuzhiyun ret = -EBUSY;
459*4882a593Smuzhiyun goto out_unlock;
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun for (i = 0; i < 16; i++) {
463*4882a593Smuzhiyun if (p + 2 > page + count) {
464*4882a593Smuzhiyun ret = -EINVAL;
465*4882a593Smuzhiyun goto out_unlock;
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun if (!isxdigit(p[0]) || !isxdigit(p[1])) {
468*4882a593Smuzhiyun ret = -EINVAL;
469*4882a593Smuzhiyun goto out_unlock;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun nguid[i] = (hex_to_bin(p[0]) << 4) | hex_to_bin(p[1]);
473*4882a593Smuzhiyun p += 2;
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun if (*p == '-' || *p == ':')
476*4882a593Smuzhiyun p++;
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun memcpy(&ns->nguid, nguid, sizeof(nguid));
480*4882a593Smuzhiyun out_unlock:
481*4882a593Smuzhiyun mutex_unlock(&subsys->lock);
482*4882a593Smuzhiyun return ret ? ret : count;
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_ns_, device_nguid);
486*4882a593Smuzhiyun
nvmet_ns_ana_grpid_show(struct config_item * item,char * page)487*4882a593Smuzhiyun static ssize_t nvmet_ns_ana_grpid_show(struct config_item *item, char *page)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun return sprintf(page, "%u\n", to_nvmet_ns(item)->anagrpid);
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun
nvmet_ns_ana_grpid_store(struct config_item * item,const char * page,size_t count)492*4882a593Smuzhiyun static ssize_t nvmet_ns_ana_grpid_store(struct config_item *item,
493*4882a593Smuzhiyun const char *page, size_t count)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun struct nvmet_ns *ns = to_nvmet_ns(item);
496*4882a593Smuzhiyun u32 oldgrpid, newgrpid;
497*4882a593Smuzhiyun int ret;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun ret = kstrtou32(page, 0, &newgrpid);
500*4882a593Smuzhiyun if (ret)
501*4882a593Smuzhiyun return ret;
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun if (newgrpid < 1 || newgrpid > NVMET_MAX_ANAGRPS)
504*4882a593Smuzhiyun return -EINVAL;
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun down_write(&nvmet_ana_sem);
507*4882a593Smuzhiyun oldgrpid = ns->anagrpid;
508*4882a593Smuzhiyun nvmet_ana_group_enabled[newgrpid]++;
509*4882a593Smuzhiyun ns->anagrpid = newgrpid;
510*4882a593Smuzhiyun nvmet_ana_group_enabled[oldgrpid]--;
511*4882a593Smuzhiyun nvmet_ana_chgcnt++;
512*4882a593Smuzhiyun up_write(&nvmet_ana_sem);
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun nvmet_send_ana_event(ns->subsys, NULL);
515*4882a593Smuzhiyun return count;
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_ns_, ana_grpid);
519*4882a593Smuzhiyun
nvmet_ns_enable_show(struct config_item * item,char * page)520*4882a593Smuzhiyun static ssize_t nvmet_ns_enable_show(struct config_item *item, char *page)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun return sprintf(page, "%d\n", to_nvmet_ns(item)->enabled);
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun
nvmet_ns_enable_store(struct config_item * item,const char * page,size_t count)525*4882a593Smuzhiyun static ssize_t nvmet_ns_enable_store(struct config_item *item,
526*4882a593Smuzhiyun const char *page, size_t count)
527*4882a593Smuzhiyun {
528*4882a593Smuzhiyun struct nvmet_ns *ns = to_nvmet_ns(item);
529*4882a593Smuzhiyun bool enable;
530*4882a593Smuzhiyun int ret = 0;
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun if (strtobool(page, &enable))
533*4882a593Smuzhiyun return -EINVAL;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun if (enable)
536*4882a593Smuzhiyun ret = nvmet_ns_enable(ns);
537*4882a593Smuzhiyun else
538*4882a593Smuzhiyun nvmet_ns_disable(ns);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun return ret ? ret : count;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_ns_, enable);
544*4882a593Smuzhiyun
nvmet_ns_buffered_io_show(struct config_item * item,char * page)545*4882a593Smuzhiyun static ssize_t nvmet_ns_buffered_io_show(struct config_item *item, char *page)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun return sprintf(page, "%d\n", to_nvmet_ns(item)->buffered_io);
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun
nvmet_ns_buffered_io_store(struct config_item * item,const char * page,size_t count)550*4882a593Smuzhiyun static ssize_t nvmet_ns_buffered_io_store(struct config_item *item,
551*4882a593Smuzhiyun const char *page, size_t count)
552*4882a593Smuzhiyun {
553*4882a593Smuzhiyun struct nvmet_ns *ns = to_nvmet_ns(item);
554*4882a593Smuzhiyun bool val;
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun if (strtobool(page, &val))
557*4882a593Smuzhiyun return -EINVAL;
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun mutex_lock(&ns->subsys->lock);
560*4882a593Smuzhiyun if (ns->enabled) {
561*4882a593Smuzhiyun pr_err("disable ns before setting buffered_io value.\n");
562*4882a593Smuzhiyun mutex_unlock(&ns->subsys->lock);
563*4882a593Smuzhiyun return -EINVAL;
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun ns->buffered_io = val;
567*4882a593Smuzhiyun mutex_unlock(&ns->subsys->lock);
568*4882a593Smuzhiyun return count;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_ns_, buffered_io);
572*4882a593Smuzhiyun
nvmet_ns_revalidate_size_store(struct config_item * item,const char * page,size_t count)573*4882a593Smuzhiyun static ssize_t nvmet_ns_revalidate_size_store(struct config_item *item,
574*4882a593Smuzhiyun const char *page, size_t count)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun struct nvmet_ns *ns = to_nvmet_ns(item);
577*4882a593Smuzhiyun bool val;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun if (strtobool(page, &val))
580*4882a593Smuzhiyun return -EINVAL;
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun if (!val)
583*4882a593Smuzhiyun return -EINVAL;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun mutex_lock(&ns->subsys->lock);
586*4882a593Smuzhiyun if (!ns->enabled) {
587*4882a593Smuzhiyun pr_err("enable ns before revalidate.\n");
588*4882a593Smuzhiyun mutex_unlock(&ns->subsys->lock);
589*4882a593Smuzhiyun return -EINVAL;
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun nvmet_ns_revalidate(ns);
592*4882a593Smuzhiyun mutex_unlock(&ns->subsys->lock);
593*4882a593Smuzhiyun return count;
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun CONFIGFS_ATTR_WO(nvmet_ns_, revalidate_size);
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun static struct configfs_attribute *nvmet_ns_attrs[] = {
599*4882a593Smuzhiyun &nvmet_ns_attr_device_path,
600*4882a593Smuzhiyun &nvmet_ns_attr_device_nguid,
601*4882a593Smuzhiyun &nvmet_ns_attr_device_uuid,
602*4882a593Smuzhiyun &nvmet_ns_attr_ana_grpid,
603*4882a593Smuzhiyun &nvmet_ns_attr_enable,
604*4882a593Smuzhiyun &nvmet_ns_attr_buffered_io,
605*4882a593Smuzhiyun &nvmet_ns_attr_revalidate_size,
606*4882a593Smuzhiyun #ifdef CONFIG_PCI_P2PDMA
607*4882a593Smuzhiyun &nvmet_ns_attr_p2pmem,
608*4882a593Smuzhiyun #endif
609*4882a593Smuzhiyun NULL,
610*4882a593Smuzhiyun };
611*4882a593Smuzhiyun
nvmet_ns_release(struct config_item * item)612*4882a593Smuzhiyun static void nvmet_ns_release(struct config_item *item)
613*4882a593Smuzhiyun {
614*4882a593Smuzhiyun struct nvmet_ns *ns = to_nvmet_ns(item);
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun nvmet_ns_free(ns);
617*4882a593Smuzhiyun }
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun static struct configfs_item_operations nvmet_ns_item_ops = {
620*4882a593Smuzhiyun .release = nvmet_ns_release,
621*4882a593Smuzhiyun };
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun static const struct config_item_type nvmet_ns_type = {
624*4882a593Smuzhiyun .ct_item_ops = &nvmet_ns_item_ops,
625*4882a593Smuzhiyun .ct_attrs = nvmet_ns_attrs,
626*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
627*4882a593Smuzhiyun };
628*4882a593Smuzhiyun
nvmet_ns_make(struct config_group * group,const char * name)629*4882a593Smuzhiyun static struct config_group *nvmet_ns_make(struct config_group *group,
630*4882a593Smuzhiyun const char *name)
631*4882a593Smuzhiyun {
632*4882a593Smuzhiyun struct nvmet_subsys *subsys = namespaces_to_subsys(&group->cg_item);
633*4882a593Smuzhiyun struct nvmet_ns *ns;
634*4882a593Smuzhiyun int ret;
635*4882a593Smuzhiyun u32 nsid;
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun ret = kstrtou32(name, 0, &nsid);
638*4882a593Smuzhiyun if (ret)
639*4882a593Smuzhiyun goto out;
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun ret = -EINVAL;
642*4882a593Smuzhiyun if (nsid == 0 || nsid == NVME_NSID_ALL) {
643*4882a593Smuzhiyun pr_err("invalid nsid %#x", nsid);
644*4882a593Smuzhiyun goto out;
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun ret = -ENOMEM;
648*4882a593Smuzhiyun ns = nvmet_ns_alloc(subsys, nsid);
649*4882a593Smuzhiyun if (!ns)
650*4882a593Smuzhiyun goto out;
651*4882a593Smuzhiyun config_group_init_type_name(&ns->group, name, &nvmet_ns_type);
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun pr_info("adding nsid %d to subsystem %s\n", nsid, subsys->subsysnqn);
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun return &ns->group;
656*4882a593Smuzhiyun out:
657*4882a593Smuzhiyun return ERR_PTR(ret);
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun static struct configfs_group_operations nvmet_namespaces_group_ops = {
661*4882a593Smuzhiyun .make_group = nvmet_ns_make,
662*4882a593Smuzhiyun };
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun static const struct config_item_type nvmet_namespaces_type = {
665*4882a593Smuzhiyun .ct_group_ops = &nvmet_namespaces_group_ops,
666*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
667*4882a593Smuzhiyun };
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun #ifdef CONFIG_NVME_TARGET_PASSTHRU
670*4882a593Smuzhiyun
nvmet_passthru_device_path_show(struct config_item * item,char * page)671*4882a593Smuzhiyun static ssize_t nvmet_passthru_device_path_show(struct config_item *item,
672*4882a593Smuzhiyun char *page)
673*4882a593Smuzhiyun {
674*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(item->ci_parent);
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%s\n", subsys->passthru_ctrl_path);
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun
nvmet_passthru_device_path_store(struct config_item * item,const char * page,size_t count)679*4882a593Smuzhiyun static ssize_t nvmet_passthru_device_path_store(struct config_item *item,
680*4882a593Smuzhiyun const char *page, size_t count)
681*4882a593Smuzhiyun {
682*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(item->ci_parent);
683*4882a593Smuzhiyun size_t len;
684*4882a593Smuzhiyun int ret;
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun mutex_lock(&subsys->lock);
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun ret = -EBUSY;
689*4882a593Smuzhiyun if (subsys->passthru_ctrl)
690*4882a593Smuzhiyun goto out_unlock;
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun ret = -EINVAL;
693*4882a593Smuzhiyun len = strcspn(page, "\n");
694*4882a593Smuzhiyun if (!len)
695*4882a593Smuzhiyun goto out_unlock;
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun kfree(subsys->passthru_ctrl_path);
698*4882a593Smuzhiyun ret = -ENOMEM;
699*4882a593Smuzhiyun subsys->passthru_ctrl_path = kstrndup(page, len, GFP_KERNEL);
700*4882a593Smuzhiyun if (!subsys->passthru_ctrl_path)
701*4882a593Smuzhiyun goto out_unlock;
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun mutex_unlock(&subsys->lock);
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun return count;
706*4882a593Smuzhiyun out_unlock:
707*4882a593Smuzhiyun mutex_unlock(&subsys->lock);
708*4882a593Smuzhiyun return ret;
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_passthru_, device_path);
711*4882a593Smuzhiyun
nvmet_passthru_enable_show(struct config_item * item,char * page)712*4882a593Smuzhiyun static ssize_t nvmet_passthru_enable_show(struct config_item *item,
713*4882a593Smuzhiyun char *page)
714*4882a593Smuzhiyun {
715*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(item->ci_parent);
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun return sprintf(page, "%d\n", subsys->passthru_ctrl ? 1 : 0);
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun
nvmet_passthru_enable_store(struct config_item * item,const char * page,size_t count)720*4882a593Smuzhiyun static ssize_t nvmet_passthru_enable_store(struct config_item *item,
721*4882a593Smuzhiyun const char *page, size_t count)
722*4882a593Smuzhiyun {
723*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(item->ci_parent);
724*4882a593Smuzhiyun bool enable;
725*4882a593Smuzhiyun int ret = 0;
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun if (strtobool(page, &enable))
728*4882a593Smuzhiyun return -EINVAL;
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun if (enable)
731*4882a593Smuzhiyun ret = nvmet_passthru_ctrl_enable(subsys);
732*4882a593Smuzhiyun else
733*4882a593Smuzhiyun nvmet_passthru_ctrl_disable(subsys);
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun return ret ? ret : count;
736*4882a593Smuzhiyun }
737*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_passthru_, enable);
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun static struct configfs_attribute *nvmet_passthru_attrs[] = {
740*4882a593Smuzhiyun &nvmet_passthru_attr_device_path,
741*4882a593Smuzhiyun &nvmet_passthru_attr_enable,
742*4882a593Smuzhiyun NULL,
743*4882a593Smuzhiyun };
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun static const struct config_item_type nvmet_passthru_type = {
746*4882a593Smuzhiyun .ct_attrs = nvmet_passthru_attrs,
747*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
748*4882a593Smuzhiyun };
749*4882a593Smuzhiyun
nvmet_add_passthru_group(struct nvmet_subsys * subsys)750*4882a593Smuzhiyun static void nvmet_add_passthru_group(struct nvmet_subsys *subsys)
751*4882a593Smuzhiyun {
752*4882a593Smuzhiyun config_group_init_type_name(&subsys->passthru_group,
753*4882a593Smuzhiyun "passthru", &nvmet_passthru_type);
754*4882a593Smuzhiyun configfs_add_default_group(&subsys->passthru_group,
755*4882a593Smuzhiyun &subsys->group);
756*4882a593Smuzhiyun }
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun #else /* CONFIG_NVME_TARGET_PASSTHRU */
759*4882a593Smuzhiyun
nvmet_add_passthru_group(struct nvmet_subsys * subsys)760*4882a593Smuzhiyun static void nvmet_add_passthru_group(struct nvmet_subsys *subsys)
761*4882a593Smuzhiyun {
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun #endif /* CONFIG_NVME_TARGET_PASSTHRU */
765*4882a593Smuzhiyun
nvmet_port_subsys_allow_link(struct config_item * parent,struct config_item * target)766*4882a593Smuzhiyun static int nvmet_port_subsys_allow_link(struct config_item *parent,
767*4882a593Smuzhiyun struct config_item *target)
768*4882a593Smuzhiyun {
769*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(parent->ci_parent);
770*4882a593Smuzhiyun struct nvmet_subsys *subsys;
771*4882a593Smuzhiyun struct nvmet_subsys_link *link, *p;
772*4882a593Smuzhiyun int ret;
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun if (target->ci_type != &nvmet_subsys_type) {
775*4882a593Smuzhiyun pr_err("can only link subsystems into the subsystems dir.!\n");
776*4882a593Smuzhiyun return -EINVAL;
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun subsys = to_subsys(target);
779*4882a593Smuzhiyun link = kmalloc(sizeof(*link), GFP_KERNEL);
780*4882a593Smuzhiyun if (!link)
781*4882a593Smuzhiyun return -ENOMEM;
782*4882a593Smuzhiyun link->subsys = subsys;
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun down_write(&nvmet_config_sem);
785*4882a593Smuzhiyun ret = -EEXIST;
786*4882a593Smuzhiyun list_for_each_entry(p, &port->subsystems, entry) {
787*4882a593Smuzhiyun if (p->subsys == subsys)
788*4882a593Smuzhiyun goto out_free_link;
789*4882a593Smuzhiyun }
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun if (list_empty(&port->subsystems)) {
792*4882a593Smuzhiyun ret = nvmet_enable_port(port);
793*4882a593Smuzhiyun if (ret)
794*4882a593Smuzhiyun goto out_free_link;
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun list_add_tail(&link->entry, &port->subsystems);
798*4882a593Smuzhiyun nvmet_port_disc_changed(port, subsys);
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun up_write(&nvmet_config_sem);
801*4882a593Smuzhiyun return 0;
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun out_free_link:
804*4882a593Smuzhiyun up_write(&nvmet_config_sem);
805*4882a593Smuzhiyun kfree(link);
806*4882a593Smuzhiyun return ret;
807*4882a593Smuzhiyun }
808*4882a593Smuzhiyun
nvmet_port_subsys_drop_link(struct config_item * parent,struct config_item * target)809*4882a593Smuzhiyun static void nvmet_port_subsys_drop_link(struct config_item *parent,
810*4882a593Smuzhiyun struct config_item *target)
811*4882a593Smuzhiyun {
812*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(parent->ci_parent);
813*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(target);
814*4882a593Smuzhiyun struct nvmet_subsys_link *p;
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun down_write(&nvmet_config_sem);
817*4882a593Smuzhiyun list_for_each_entry(p, &port->subsystems, entry) {
818*4882a593Smuzhiyun if (p->subsys == subsys)
819*4882a593Smuzhiyun goto found;
820*4882a593Smuzhiyun }
821*4882a593Smuzhiyun up_write(&nvmet_config_sem);
822*4882a593Smuzhiyun return;
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun found:
825*4882a593Smuzhiyun list_del(&p->entry);
826*4882a593Smuzhiyun nvmet_port_del_ctrls(port, subsys);
827*4882a593Smuzhiyun nvmet_port_disc_changed(port, subsys);
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun if (list_empty(&port->subsystems))
830*4882a593Smuzhiyun nvmet_disable_port(port);
831*4882a593Smuzhiyun up_write(&nvmet_config_sem);
832*4882a593Smuzhiyun kfree(p);
833*4882a593Smuzhiyun }
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun static struct configfs_item_operations nvmet_port_subsys_item_ops = {
836*4882a593Smuzhiyun .allow_link = nvmet_port_subsys_allow_link,
837*4882a593Smuzhiyun .drop_link = nvmet_port_subsys_drop_link,
838*4882a593Smuzhiyun };
839*4882a593Smuzhiyun
840*4882a593Smuzhiyun static const struct config_item_type nvmet_port_subsys_type = {
841*4882a593Smuzhiyun .ct_item_ops = &nvmet_port_subsys_item_ops,
842*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
843*4882a593Smuzhiyun };
844*4882a593Smuzhiyun
nvmet_allowed_hosts_allow_link(struct config_item * parent,struct config_item * target)845*4882a593Smuzhiyun static int nvmet_allowed_hosts_allow_link(struct config_item *parent,
846*4882a593Smuzhiyun struct config_item *target)
847*4882a593Smuzhiyun {
848*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(parent->ci_parent);
849*4882a593Smuzhiyun struct nvmet_host *host;
850*4882a593Smuzhiyun struct nvmet_host_link *link, *p;
851*4882a593Smuzhiyun int ret;
852*4882a593Smuzhiyun
853*4882a593Smuzhiyun if (target->ci_type != &nvmet_host_type) {
854*4882a593Smuzhiyun pr_err("can only link hosts into the allowed_hosts directory!\n");
855*4882a593Smuzhiyun return -EINVAL;
856*4882a593Smuzhiyun }
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun host = to_host(target);
859*4882a593Smuzhiyun link = kmalloc(sizeof(*link), GFP_KERNEL);
860*4882a593Smuzhiyun if (!link)
861*4882a593Smuzhiyun return -ENOMEM;
862*4882a593Smuzhiyun link->host = host;
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun down_write(&nvmet_config_sem);
865*4882a593Smuzhiyun ret = -EINVAL;
866*4882a593Smuzhiyun if (subsys->allow_any_host) {
867*4882a593Smuzhiyun pr_err("can't add hosts when allow_any_host is set!\n");
868*4882a593Smuzhiyun goto out_free_link;
869*4882a593Smuzhiyun }
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun ret = -EEXIST;
872*4882a593Smuzhiyun list_for_each_entry(p, &subsys->hosts, entry) {
873*4882a593Smuzhiyun if (!strcmp(nvmet_host_name(p->host), nvmet_host_name(host)))
874*4882a593Smuzhiyun goto out_free_link;
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun list_add_tail(&link->entry, &subsys->hosts);
877*4882a593Smuzhiyun nvmet_subsys_disc_changed(subsys, host);
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun up_write(&nvmet_config_sem);
880*4882a593Smuzhiyun return 0;
881*4882a593Smuzhiyun out_free_link:
882*4882a593Smuzhiyun up_write(&nvmet_config_sem);
883*4882a593Smuzhiyun kfree(link);
884*4882a593Smuzhiyun return ret;
885*4882a593Smuzhiyun }
886*4882a593Smuzhiyun
nvmet_allowed_hosts_drop_link(struct config_item * parent,struct config_item * target)887*4882a593Smuzhiyun static void nvmet_allowed_hosts_drop_link(struct config_item *parent,
888*4882a593Smuzhiyun struct config_item *target)
889*4882a593Smuzhiyun {
890*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(parent->ci_parent);
891*4882a593Smuzhiyun struct nvmet_host *host = to_host(target);
892*4882a593Smuzhiyun struct nvmet_host_link *p;
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun down_write(&nvmet_config_sem);
895*4882a593Smuzhiyun list_for_each_entry(p, &subsys->hosts, entry) {
896*4882a593Smuzhiyun if (!strcmp(nvmet_host_name(p->host), nvmet_host_name(host)))
897*4882a593Smuzhiyun goto found;
898*4882a593Smuzhiyun }
899*4882a593Smuzhiyun up_write(&nvmet_config_sem);
900*4882a593Smuzhiyun return;
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun found:
903*4882a593Smuzhiyun list_del(&p->entry);
904*4882a593Smuzhiyun nvmet_subsys_disc_changed(subsys, host);
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun up_write(&nvmet_config_sem);
907*4882a593Smuzhiyun kfree(p);
908*4882a593Smuzhiyun }
909*4882a593Smuzhiyun
910*4882a593Smuzhiyun static struct configfs_item_operations nvmet_allowed_hosts_item_ops = {
911*4882a593Smuzhiyun .allow_link = nvmet_allowed_hosts_allow_link,
912*4882a593Smuzhiyun .drop_link = nvmet_allowed_hosts_drop_link,
913*4882a593Smuzhiyun };
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun static const struct config_item_type nvmet_allowed_hosts_type = {
916*4882a593Smuzhiyun .ct_item_ops = &nvmet_allowed_hosts_item_ops,
917*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
918*4882a593Smuzhiyun };
919*4882a593Smuzhiyun
nvmet_subsys_attr_allow_any_host_show(struct config_item * item,char * page)920*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_allow_any_host_show(struct config_item *item,
921*4882a593Smuzhiyun char *page)
922*4882a593Smuzhiyun {
923*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%d\n",
924*4882a593Smuzhiyun to_subsys(item)->allow_any_host);
925*4882a593Smuzhiyun }
926*4882a593Smuzhiyun
nvmet_subsys_attr_allow_any_host_store(struct config_item * item,const char * page,size_t count)927*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_allow_any_host_store(struct config_item *item,
928*4882a593Smuzhiyun const char *page, size_t count)
929*4882a593Smuzhiyun {
930*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(item);
931*4882a593Smuzhiyun bool allow_any_host;
932*4882a593Smuzhiyun int ret = 0;
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun if (strtobool(page, &allow_any_host))
935*4882a593Smuzhiyun return -EINVAL;
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun down_write(&nvmet_config_sem);
938*4882a593Smuzhiyun if (allow_any_host && !list_empty(&subsys->hosts)) {
939*4882a593Smuzhiyun pr_err("Can't set allow_any_host when explicit hosts are set!\n");
940*4882a593Smuzhiyun ret = -EINVAL;
941*4882a593Smuzhiyun goto out_unlock;
942*4882a593Smuzhiyun }
943*4882a593Smuzhiyun
944*4882a593Smuzhiyun if (subsys->allow_any_host != allow_any_host) {
945*4882a593Smuzhiyun subsys->allow_any_host = allow_any_host;
946*4882a593Smuzhiyun nvmet_subsys_disc_changed(subsys, NULL);
947*4882a593Smuzhiyun }
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun out_unlock:
950*4882a593Smuzhiyun up_write(&nvmet_config_sem);
951*4882a593Smuzhiyun return ret ? ret : count;
952*4882a593Smuzhiyun }
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_subsys_, attr_allow_any_host);
955*4882a593Smuzhiyun
nvmet_subsys_attr_version_show(struct config_item * item,char * page)956*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_version_show(struct config_item *item,
957*4882a593Smuzhiyun char *page)
958*4882a593Smuzhiyun {
959*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(item);
960*4882a593Smuzhiyun
961*4882a593Smuzhiyun if (NVME_TERTIARY(subsys->ver))
962*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%llu.%llu.%llu\n",
963*4882a593Smuzhiyun NVME_MAJOR(subsys->ver),
964*4882a593Smuzhiyun NVME_MINOR(subsys->ver),
965*4882a593Smuzhiyun NVME_TERTIARY(subsys->ver));
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%llu.%llu\n",
968*4882a593Smuzhiyun NVME_MAJOR(subsys->ver),
969*4882a593Smuzhiyun NVME_MINOR(subsys->ver));
970*4882a593Smuzhiyun }
971*4882a593Smuzhiyun
nvmet_subsys_attr_version_store(struct config_item * item,const char * page,size_t count)972*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_version_store(struct config_item *item,
973*4882a593Smuzhiyun const char *page, size_t count)
974*4882a593Smuzhiyun {
975*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(item);
976*4882a593Smuzhiyun int major, minor, tertiary = 0;
977*4882a593Smuzhiyun int ret;
978*4882a593Smuzhiyun
979*4882a593Smuzhiyun /* passthru subsystems use the underlying controller's version */
980*4882a593Smuzhiyun if (nvmet_passthru_ctrl(subsys))
981*4882a593Smuzhiyun return -EINVAL;
982*4882a593Smuzhiyun
983*4882a593Smuzhiyun ret = sscanf(page, "%d.%d.%d\n", &major, &minor, &tertiary);
984*4882a593Smuzhiyun if (ret != 2 && ret != 3)
985*4882a593Smuzhiyun return -EINVAL;
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun down_write(&nvmet_config_sem);
988*4882a593Smuzhiyun subsys->ver = NVME_VS(major, minor, tertiary);
989*4882a593Smuzhiyun up_write(&nvmet_config_sem);
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun return count;
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_subsys_, attr_version);
994*4882a593Smuzhiyun
nvmet_subsys_attr_serial_show(struct config_item * item,char * page)995*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_serial_show(struct config_item *item,
996*4882a593Smuzhiyun char *page)
997*4882a593Smuzhiyun {
998*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(item);
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%llx\n", subsys->serial);
1001*4882a593Smuzhiyun }
1002*4882a593Smuzhiyun
nvmet_subsys_attr_serial_store(struct config_item * item,const char * page,size_t count)1003*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_serial_store(struct config_item *item,
1004*4882a593Smuzhiyun const char *page, size_t count)
1005*4882a593Smuzhiyun {
1006*4882a593Smuzhiyun u64 serial;
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun if (sscanf(page, "%llx\n", &serial) != 1)
1009*4882a593Smuzhiyun return -EINVAL;
1010*4882a593Smuzhiyun
1011*4882a593Smuzhiyun down_write(&nvmet_config_sem);
1012*4882a593Smuzhiyun to_subsys(item)->serial = serial;
1013*4882a593Smuzhiyun up_write(&nvmet_config_sem);
1014*4882a593Smuzhiyun
1015*4882a593Smuzhiyun return count;
1016*4882a593Smuzhiyun }
1017*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_subsys_, attr_serial);
1018*4882a593Smuzhiyun
nvmet_subsys_attr_cntlid_min_show(struct config_item * item,char * page)1019*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_cntlid_min_show(struct config_item *item,
1020*4882a593Smuzhiyun char *page)
1021*4882a593Smuzhiyun {
1022*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%u\n", to_subsys(item)->cntlid_min);
1023*4882a593Smuzhiyun }
1024*4882a593Smuzhiyun
nvmet_subsys_attr_cntlid_min_store(struct config_item * item,const char * page,size_t cnt)1025*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_cntlid_min_store(struct config_item *item,
1026*4882a593Smuzhiyun const char *page, size_t cnt)
1027*4882a593Smuzhiyun {
1028*4882a593Smuzhiyun u16 cntlid_min;
1029*4882a593Smuzhiyun
1030*4882a593Smuzhiyun if (sscanf(page, "%hu\n", &cntlid_min) != 1)
1031*4882a593Smuzhiyun return -EINVAL;
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun if (cntlid_min == 0)
1034*4882a593Smuzhiyun return -EINVAL;
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun down_write(&nvmet_config_sem);
1037*4882a593Smuzhiyun if (cntlid_min >= to_subsys(item)->cntlid_max)
1038*4882a593Smuzhiyun goto out_unlock;
1039*4882a593Smuzhiyun to_subsys(item)->cntlid_min = cntlid_min;
1040*4882a593Smuzhiyun up_write(&nvmet_config_sem);
1041*4882a593Smuzhiyun return cnt;
1042*4882a593Smuzhiyun
1043*4882a593Smuzhiyun out_unlock:
1044*4882a593Smuzhiyun up_write(&nvmet_config_sem);
1045*4882a593Smuzhiyun return -EINVAL;
1046*4882a593Smuzhiyun }
1047*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_subsys_, attr_cntlid_min);
1048*4882a593Smuzhiyun
nvmet_subsys_attr_cntlid_max_show(struct config_item * item,char * page)1049*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_cntlid_max_show(struct config_item *item,
1050*4882a593Smuzhiyun char *page)
1051*4882a593Smuzhiyun {
1052*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%u\n", to_subsys(item)->cntlid_max);
1053*4882a593Smuzhiyun }
1054*4882a593Smuzhiyun
nvmet_subsys_attr_cntlid_max_store(struct config_item * item,const char * page,size_t cnt)1055*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_cntlid_max_store(struct config_item *item,
1056*4882a593Smuzhiyun const char *page, size_t cnt)
1057*4882a593Smuzhiyun {
1058*4882a593Smuzhiyun u16 cntlid_max;
1059*4882a593Smuzhiyun
1060*4882a593Smuzhiyun if (sscanf(page, "%hu\n", &cntlid_max) != 1)
1061*4882a593Smuzhiyun return -EINVAL;
1062*4882a593Smuzhiyun
1063*4882a593Smuzhiyun if (cntlid_max == 0)
1064*4882a593Smuzhiyun return -EINVAL;
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun down_write(&nvmet_config_sem);
1067*4882a593Smuzhiyun if (cntlid_max <= to_subsys(item)->cntlid_min)
1068*4882a593Smuzhiyun goto out_unlock;
1069*4882a593Smuzhiyun to_subsys(item)->cntlid_max = cntlid_max;
1070*4882a593Smuzhiyun up_write(&nvmet_config_sem);
1071*4882a593Smuzhiyun return cnt;
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun out_unlock:
1074*4882a593Smuzhiyun up_write(&nvmet_config_sem);
1075*4882a593Smuzhiyun return -EINVAL;
1076*4882a593Smuzhiyun }
1077*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_subsys_, attr_cntlid_max);
1078*4882a593Smuzhiyun
nvmet_subsys_attr_model_show(struct config_item * item,char * page)1079*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_model_show(struct config_item *item,
1080*4882a593Smuzhiyun char *page)
1081*4882a593Smuzhiyun {
1082*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(item);
1083*4882a593Smuzhiyun struct nvmet_subsys_model *subsys_model;
1084*4882a593Smuzhiyun char *model = NVMET_DEFAULT_CTRL_MODEL;
1085*4882a593Smuzhiyun int ret;
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun rcu_read_lock();
1088*4882a593Smuzhiyun subsys_model = rcu_dereference(subsys->model);
1089*4882a593Smuzhiyun if (subsys_model)
1090*4882a593Smuzhiyun model = subsys_model->number;
1091*4882a593Smuzhiyun ret = snprintf(page, PAGE_SIZE, "%s\n", model);
1092*4882a593Smuzhiyun rcu_read_unlock();
1093*4882a593Smuzhiyun
1094*4882a593Smuzhiyun return ret;
1095*4882a593Smuzhiyun }
1096*4882a593Smuzhiyun
1097*4882a593Smuzhiyun /* See Section 1.5 of NVMe 1.4 */
nvmet_is_ascii(const char c)1098*4882a593Smuzhiyun static bool nvmet_is_ascii(const char c)
1099*4882a593Smuzhiyun {
1100*4882a593Smuzhiyun return c >= 0x20 && c <= 0x7e;
1101*4882a593Smuzhiyun }
1102*4882a593Smuzhiyun
nvmet_subsys_attr_model_store(struct config_item * item,const char * page,size_t count)1103*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_model_store(struct config_item *item,
1104*4882a593Smuzhiyun const char *page, size_t count)
1105*4882a593Smuzhiyun {
1106*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(item);
1107*4882a593Smuzhiyun struct nvmet_subsys_model *new_model;
1108*4882a593Smuzhiyun char *new_model_number;
1109*4882a593Smuzhiyun int pos = 0, len;
1110*4882a593Smuzhiyun
1111*4882a593Smuzhiyun len = strcspn(page, "\n");
1112*4882a593Smuzhiyun if (!len)
1113*4882a593Smuzhiyun return -EINVAL;
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun for (pos = 0; pos < len; pos++) {
1116*4882a593Smuzhiyun if (!nvmet_is_ascii(page[pos]))
1117*4882a593Smuzhiyun return -EINVAL;
1118*4882a593Smuzhiyun }
1119*4882a593Smuzhiyun
1120*4882a593Smuzhiyun new_model_number = kmemdup_nul(page, len, GFP_KERNEL);
1121*4882a593Smuzhiyun if (!new_model_number)
1122*4882a593Smuzhiyun return -ENOMEM;
1123*4882a593Smuzhiyun
1124*4882a593Smuzhiyun new_model = kzalloc(sizeof(*new_model) + len + 1, GFP_KERNEL);
1125*4882a593Smuzhiyun if (!new_model) {
1126*4882a593Smuzhiyun kfree(new_model_number);
1127*4882a593Smuzhiyun return -ENOMEM;
1128*4882a593Smuzhiyun }
1129*4882a593Smuzhiyun memcpy(new_model->number, new_model_number, len);
1130*4882a593Smuzhiyun
1131*4882a593Smuzhiyun down_write(&nvmet_config_sem);
1132*4882a593Smuzhiyun mutex_lock(&subsys->lock);
1133*4882a593Smuzhiyun new_model = rcu_replace_pointer(subsys->model, new_model,
1134*4882a593Smuzhiyun mutex_is_locked(&subsys->lock));
1135*4882a593Smuzhiyun mutex_unlock(&subsys->lock);
1136*4882a593Smuzhiyun up_write(&nvmet_config_sem);
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun kfree_rcu(new_model, rcuhead);
1139*4882a593Smuzhiyun kfree(new_model_number);
1140*4882a593Smuzhiyun
1141*4882a593Smuzhiyun return count;
1142*4882a593Smuzhiyun }
1143*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_subsys_, attr_model);
1144*4882a593Smuzhiyun
1145*4882a593Smuzhiyun #ifdef CONFIG_BLK_DEV_INTEGRITY
nvmet_subsys_attr_pi_enable_show(struct config_item * item,char * page)1146*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_pi_enable_show(struct config_item *item,
1147*4882a593Smuzhiyun char *page)
1148*4882a593Smuzhiyun {
1149*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%d\n", to_subsys(item)->pi_support);
1150*4882a593Smuzhiyun }
1151*4882a593Smuzhiyun
nvmet_subsys_attr_pi_enable_store(struct config_item * item,const char * page,size_t count)1152*4882a593Smuzhiyun static ssize_t nvmet_subsys_attr_pi_enable_store(struct config_item *item,
1153*4882a593Smuzhiyun const char *page, size_t count)
1154*4882a593Smuzhiyun {
1155*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(item);
1156*4882a593Smuzhiyun bool pi_enable;
1157*4882a593Smuzhiyun
1158*4882a593Smuzhiyun if (strtobool(page, &pi_enable))
1159*4882a593Smuzhiyun return -EINVAL;
1160*4882a593Smuzhiyun
1161*4882a593Smuzhiyun subsys->pi_support = pi_enable;
1162*4882a593Smuzhiyun return count;
1163*4882a593Smuzhiyun }
1164*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_subsys_, attr_pi_enable);
1165*4882a593Smuzhiyun #endif
1166*4882a593Smuzhiyun
1167*4882a593Smuzhiyun static struct configfs_attribute *nvmet_subsys_attrs[] = {
1168*4882a593Smuzhiyun &nvmet_subsys_attr_attr_allow_any_host,
1169*4882a593Smuzhiyun &nvmet_subsys_attr_attr_version,
1170*4882a593Smuzhiyun &nvmet_subsys_attr_attr_serial,
1171*4882a593Smuzhiyun &nvmet_subsys_attr_attr_cntlid_min,
1172*4882a593Smuzhiyun &nvmet_subsys_attr_attr_cntlid_max,
1173*4882a593Smuzhiyun &nvmet_subsys_attr_attr_model,
1174*4882a593Smuzhiyun #ifdef CONFIG_BLK_DEV_INTEGRITY
1175*4882a593Smuzhiyun &nvmet_subsys_attr_attr_pi_enable,
1176*4882a593Smuzhiyun #endif
1177*4882a593Smuzhiyun NULL,
1178*4882a593Smuzhiyun };
1179*4882a593Smuzhiyun
1180*4882a593Smuzhiyun /*
1181*4882a593Smuzhiyun * Subsystem structures & folder operation functions below
1182*4882a593Smuzhiyun */
nvmet_subsys_release(struct config_item * item)1183*4882a593Smuzhiyun static void nvmet_subsys_release(struct config_item *item)
1184*4882a593Smuzhiyun {
1185*4882a593Smuzhiyun struct nvmet_subsys *subsys = to_subsys(item);
1186*4882a593Smuzhiyun
1187*4882a593Smuzhiyun nvmet_subsys_del_ctrls(subsys);
1188*4882a593Smuzhiyun nvmet_subsys_put(subsys);
1189*4882a593Smuzhiyun }
1190*4882a593Smuzhiyun
1191*4882a593Smuzhiyun static struct configfs_item_operations nvmet_subsys_item_ops = {
1192*4882a593Smuzhiyun .release = nvmet_subsys_release,
1193*4882a593Smuzhiyun };
1194*4882a593Smuzhiyun
1195*4882a593Smuzhiyun static const struct config_item_type nvmet_subsys_type = {
1196*4882a593Smuzhiyun .ct_item_ops = &nvmet_subsys_item_ops,
1197*4882a593Smuzhiyun .ct_attrs = nvmet_subsys_attrs,
1198*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
1199*4882a593Smuzhiyun };
1200*4882a593Smuzhiyun
nvmet_subsys_make(struct config_group * group,const char * name)1201*4882a593Smuzhiyun static struct config_group *nvmet_subsys_make(struct config_group *group,
1202*4882a593Smuzhiyun const char *name)
1203*4882a593Smuzhiyun {
1204*4882a593Smuzhiyun struct nvmet_subsys *subsys;
1205*4882a593Smuzhiyun
1206*4882a593Smuzhiyun if (sysfs_streq(name, NVME_DISC_SUBSYS_NAME)) {
1207*4882a593Smuzhiyun pr_err("can't create discovery subsystem through configfs\n");
1208*4882a593Smuzhiyun return ERR_PTR(-EINVAL);
1209*4882a593Smuzhiyun }
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun subsys = nvmet_subsys_alloc(name, NVME_NQN_NVME);
1212*4882a593Smuzhiyun if (IS_ERR(subsys))
1213*4882a593Smuzhiyun return ERR_CAST(subsys);
1214*4882a593Smuzhiyun
1215*4882a593Smuzhiyun config_group_init_type_name(&subsys->group, name, &nvmet_subsys_type);
1216*4882a593Smuzhiyun
1217*4882a593Smuzhiyun config_group_init_type_name(&subsys->namespaces_group,
1218*4882a593Smuzhiyun "namespaces", &nvmet_namespaces_type);
1219*4882a593Smuzhiyun configfs_add_default_group(&subsys->namespaces_group, &subsys->group);
1220*4882a593Smuzhiyun
1221*4882a593Smuzhiyun config_group_init_type_name(&subsys->allowed_hosts_group,
1222*4882a593Smuzhiyun "allowed_hosts", &nvmet_allowed_hosts_type);
1223*4882a593Smuzhiyun configfs_add_default_group(&subsys->allowed_hosts_group,
1224*4882a593Smuzhiyun &subsys->group);
1225*4882a593Smuzhiyun
1226*4882a593Smuzhiyun nvmet_add_passthru_group(subsys);
1227*4882a593Smuzhiyun
1228*4882a593Smuzhiyun return &subsys->group;
1229*4882a593Smuzhiyun }
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun static struct configfs_group_operations nvmet_subsystems_group_ops = {
1232*4882a593Smuzhiyun .make_group = nvmet_subsys_make,
1233*4882a593Smuzhiyun };
1234*4882a593Smuzhiyun
1235*4882a593Smuzhiyun static const struct config_item_type nvmet_subsystems_type = {
1236*4882a593Smuzhiyun .ct_group_ops = &nvmet_subsystems_group_ops,
1237*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
1238*4882a593Smuzhiyun };
1239*4882a593Smuzhiyun
nvmet_referral_enable_show(struct config_item * item,char * page)1240*4882a593Smuzhiyun static ssize_t nvmet_referral_enable_show(struct config_item *item,
1241*4882a593Smuzhiyun char *page)
1242*4882a593Smuzhiyun {
1243*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%d\n", to_nvmet_port(item)->enabled);
1244*4882a593Smuzhiyun }
1245*4882a593Smuzhiyun
nvmet_referral_enable_store(struct config_item * item,const char * page,size_t count)1246*4882a593Smuzhiyun static ssize_t nvmet_referral_enable_store(struct config_item *item,
1247*4882a593Smuzhiyun const char *page, size_t count)
1248*4882a593Smuzhiyun {
1249*4882a593Smuzhiyun struct nvmet_port *parent = to_nvmet_port(item->ci_parent->ci_parent);
1250*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
1251*4882a593Smuzhiyun bool enable;
1252*4882a593Smuzhiyun
1253*4882a593Smuzhiyun if (strtobool(page, &enable))
1254*4882a593Smuzhiyun goto inval;
1255*4882a593Smuzhiyun
1256*4882a593Smuzhiyun if (enable)
1257*4882a593Smuzhiyun nvmet_referral_enable(parent, port);
1258*4882a593Smuzhiyun else
1259*4882a593Smuzhiyun nvmet_referral_disable(parent, port);
1260*4882a593Smuzhiyun
1261*4882a593Smuzhiyun return count;
1262*4882a593Smuzhiyun inval:
1263*4882a593Smuzhiyun pr_err("Invalid value '%s' for enable\n", page);
1264*4882a593Smuzhiyun return -EINVAL;
1265*4882a593Smuzhiyun }
1266*4882a593Smuzhiyun
1267*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_referral_, enable);
1268*4882a593Smuzhiyun
1269*4882a593Smuzhiyun /*
1270*4882a593Smuzhiyun * Discovery Service subsystem definitions
1271*4882a593Smuzhiyun */
1272*4882a593Smuzhiyun static struct configfs_attribute *nvmet_referral_attrs[] = {
1273*4882a593Smuzhiyun &nvmet_attr_addr_adrfam,
1274*4882a593Smuzhiyun &nvmet_attr_addr_portid,
1275*4882a593Smuzhiyun &nvmet_attr_addr_treq,
1276*4882a593Smuzhiyun &nvmet_attr_addr_traddr,
1277*4882a593Smuzhiyun &nvmet_attr_addr_trsvcid,
1278*4882a593Smuzhiyun &nvmet_attr_addr_trtype,
1279*4882a593Smuzhiyun &nvmet_referral_attr_enable,
1280*4882a593Smuzhiyun NULL,
1281*4882a593Smuzhiyun };
1282*4882a593Smuzhiyun
nvmet_referral_notify(struct config_group * group,struct config_item * item)1283*4882a593Smuzhiyun static void nvmet_referral_notify(struct config_group *group,
1284*4882a593Smuzhiyun struct config_item *item)
1285*4882a593Smuzhiyun {
1286*4882a593Smuzhiyun struct nvmet_port *parent = to_nvmet_port(item->ci_parent->ci_parent);
1287*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
1288*4882a593Smuzhiyun
1289*4882a593Smuzhiyun nvmet_referral_disable(parent, port);
1290*4882a593Smuzhiyun }
1291*4882a593Smuzhiyun
nvmet_referral_release(struct config_item * item)1292*4882a593Smuzhiyun static void nvmet_referral_release(struct config_item *item)
1293*4882a593Smuzhiyun {
1294*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
1295*4882a593Smuzhiyun
1296*4882a593Smuzhiyun kfree(port);
1297*4882a593Smuzhiyun }
1298*4882a593Smuzhiyun
1299*4882a593Smuzhiyun static struct configfs_item_operations nvmet_referral_item_ops = {
1300*4882a593Smuzhiyun .release = nvmet_referral_release,
1301*4882a593Smuzhiyun };
1302*4882a593Smuzhiyun
1303*4882a593Smuzhiyun static const struct config_item_type nvmet_referral_type = {
1304*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
1305*4882a593Smuzhiyun .ct_attrs = nvmet_referral_attrs,
1306*4882a593Smuzhiyun .ct_item_ops = &nvmet_referral_item_ops,
1307*4882a593Smuzhiyun };
1308*4882a593Smuzhiyun
nvmet_referral_make(struct config_group * group,const char * name)1309*4882a593Smuzhiyun static struct config_group *nvmet_referral_make(
1310*4882a593Smuzhiyun struct config_group *group, const char *name)
1311*4882a593Smuzhiyun {
1312*4882a593Smuzhiyun struct nvmet_port *port;
1313*4882a593Smuzhiyun
1314*4882a593Smuzhiyun port = kzalloc(sizeof(*port), GFP_KERNEL);
1315*4882a593Smuzhiyun if (!port)
1316*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
1317*4882a593Smuzhiyun
1318*4882a593Smuzhiyun INIT_LIST_HEAD(&port->entry);
1319*4882a593Smuzhiyun config_group_init_type_name(&port->group, name, &nvmet_referral_type);
1320*4882a593Smuzhiyun
1321*4882a593Smuzhiyun return &port->group;
1322*4882a593Smuzhiyun }
1323*4882a593Smuzhiyun
1324*4882a593Smuzhiyun static struct configfs_group_operations nvmet_referral_group_ops = {
1325*4882a593Smuzhiyun .make_group = nvmet_referral_make,
1326*4882a593Smuzhiyun .disconnect_notify = nvmet_referral_notify,
1327*4882a593Smuzhiyun };
1328*4882a593Smuzhiyun
1329*4882a593Smuzhiyun static const struct config_item_type nvmet_referrals_type = {
1330*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
1331*4882a593Smuzhiyun .ct_group_ops = &nvmet_referral_group_ops,
1332*4882a593Smuzhiyun };
1333*4882a593Smuzhiyun
1334*4882a593Smuzhiyun static struct nvmet_type_name_map nvmet_ana_state[] = {
1335*4882a593Smuzhiyun { NVME_ANA_OPTIMIZED, "optimized" },
1336*4882a593Smuzhiyun { NVME_ANA_NONOPTIMIZED, "non-optimized" },
1337*4882a593Smuzhiyun { NVME_ANA_INACCESSIBLE, "inaccessible" },
1338*4882a593Smuzhiyun { NVME_ANA_PERSISTENT_LOSS, "persistent-loss" },
1339*4882a593Smuzhiyun { NVME_ANA_CHANGE, "change" },
1340*4882a593Smuzhiyun };
1341*4882a593Smuzhiyun
nvmet_ana_group_ana_state_show(struct config_item * item,char * page)1342*4882a593Smuzhiyun static ssize_t nvmet_ana_group_ana_state_show(struct config_item *item,
1343*4882a593Smuzhiyun char *page)
1344*4882a593Smuzhiyun {
1345*4882a593Smuzhiyun struct nvmet_ana_group *grp = to_ana_group(item);
1346*4882a593Smuzhiyun enum nvme_ana_state state = grp->port->ana_state[grp->grpid];
1347*4882a593Smuzhiyun int i;
1348*4882a593Smuzhiyun
1349*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(nvmet_ana_state); i++) {
1350*4882a593Smuzhiyun if (state == nvmet_ana_state[i].type)
1351*4882a593Smuzhiyun return sprintf(page, "%s\n", nvmet_ana_state[i].name);
1352*4882a593Smuzhiyun }
1353*4882a593Smuzhiyun
1354*4882a593Smuzhiyun return sprintf(page, "\n");
1355*4882a593Smuzhiyun }
1356*4882a593Smuzhiyun
nvmet_ana_group_ana_state_store(struct config_item * item,const char * page,size_t count)1357*4882a593Smuzhiyun static ssize_t nvmet_ana_group_ana_state_store(struct config_item *item,
1358*4882a593Smuzhiyun const char *page, size_t count)
1359*4882a593Smuzhiyun {
1360*4882a593Smuzhiyun struct nvmet_ana_group *grp = to_ana_group(item);
1361*4882a593Smuzhiyun enum nvme_ana_state *ana_state = grp->port->ana_state;
1362*4882a593Smuzhiyun int i;
1363*4882a593Smuzhiyun
1364*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(nvmet_ana_state); i++) {
1365*4882a593Smuzhiyun if (sysfs_streq(page, nvmet_ana_state[i].name))
1366*4882a593Smuzhiyun goto found;
1367*4882a593Smuzhiyun }
1368*4882a593Smuzhiyun
1369*4882a593Smuzhiyun pr_err("Invalid value '%s' for ana_state\n", page);
1370*4882a593Smuzhiyun return -EINVAL;
1371*4882a593Smuzhiyun
1372*4882a593Smuzhiyun found:
1373*4882a593Smuzhiyun down_write(&nvmet_ana_sem);
1374*4882a593Smuzhiyun ana_state[grp->grpid] = (enum nvme_ana_state) nvmet_ana_state[i].type;
1375*4882a593Smuzhiyun nvmet_ana_chgcnt++;
1376*4882a593Smuzhiyun up_write(&nvmet_ana_sem);
1377*4882a593Smuzhiyun nvmet_port_send_ana_event(grp->port);
1378*4882a593Smuzhiyun return count;
1379*4882a593Smuzhiyun }
1380*4882a593Smuzhiyun
1381*4882a593Smuzhiyun CONFIGFS_ATTR(nvmet_ana_group_, ana_state);
1382*4882a593Smuzhiyun
1383*4882a593Smuzhiyun static struct configfs_attribute *nvmet_ana_group_attrs[] = {
1384*4882a593Smuzhiyun &nvmet_ana_group_attr_ana_state,
1385*4882a593Smuzhiyun NULL,
1386*4882a593Smuzhiyun };
1387*4882a593Smuzhiyun
nvmet_ana_group_release(struct config_item * item)1388*4882a593Smuzhiyun static void nvmet_ana_group_release(struct config_item *item)
1389*4882a593Smuzhiyun {
1390*4882a593Smuzhiyun struct nvmet_ana_group *grp = to_ana_group(item);
1391*4882a593Smuzhiyun
1392*4882a593Smuzhiyun if (grp == &grp->port->ana_default_group)
1393*4882a593Smuzhiyun return;
1394*4882a593Smuzhiyun
1395*4882a593Smuzhiyun down_write(&nvmet_ana_sem);
1396*4882a593Smuzhiyun grp->port->ana_state[grp->grpid] = NVME_ANA_INACCESSIBLE;
1397*4882a593Smuzhiyun nvmet_ana_group_enabled[grp->grpid]--;
1398*4882a593Smuzhiyun up_write(&nvmet_ana_sem);
1399*4882a593Smuzhiyun
1400*4882a593Smuzhiyun nvmet_port_send_ana_event(grp->port);
1401*4882a593Smuzhiyun kfree(grp);
1402*4882a593Smuzhiyun }
1403*4882a593Smuzhiyun
1404*4882a593Smuzhiyun static struct configfs_item_operations nvmet_ana_group_item_ops = {
1405*4882a593Smuzhiyun .release = nvmet_ana_group_release,
1406*4882a593Smuzhiyun };
1407*4882a593Smuzhiyun
1408*4882a593Smuzhiyun static const struct config_item_type nvmet_ana_group_type = {
1409*4882a593Smuzhiyun .ct_item_ops = &nvmet_ana_group_item_ops,
1410*4882a593Smuzhiyun .ct_attrs = nvmet_ana_group_attrs,
1411*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
1412*4882a593Smuzhiyun };
1413*4882a593Smuzhiyun
nvmet_ana_groups_make_group(struct config_group * group,const char * name)1414*4882a593Smuzhiyun static struct config_group *nvmet_ana_groups_make_group(
1415*4882a593Smuzhiyun struct config_group *group, const char *name)
1416*4882a593Smuzhiyun {
1417*4882a593Smuzhiyun struct nvmet_port *port = ana_groups_to_port(&group->cg_item);
1418*4882a593Smuzhiyun struct nvmet_ana_group *grp;
1419*4882a593Smuzhiyun u32 grpid;
1420*4882a593Smuzhiyun int ret;
1421*4882a593Smuzhiyun
1422*4882a593Smuzhiyun ret = kstrtou32(name, 0, &grpid);
1423*4882a593Smuzhiyun if (ret)
1424*4882a593Smuzhiyun goto out;
1425*4882a593Smuzhiyun
1426*4882a593Smuzhiyun ret = -EINVAL;
1427*4882a593Smuzhiyun if (grpid <= 1 || grpid > NVMET_MAX_ANAGRPS)
1428*4882a593Smuzhiyun goto out;
1429*4882a593Smuzhiyun
1430*4882a593Smuzhiyun ret = -ENOMEM;
1431*4882a593Smuzhiyun grp = kzalloc(sizeof(*grp), GFP_KERNEL);
1432*4882a593Smuzhiyun if (!grp)
1433*4882a593Smuzhiyun goto out;
1434*4882a593Smuzhiyun grp->port = port;
1435*4882a593Smuzhiyun grp->grpid = grpid;
1436*4882a593Smuzhiyun
1437*4882a593Smuzhiyun down_write(&nvmet_ana_sem);
1438*4882a593Smuzhiyun nvmet_ana_group_enabled[grpid]++;
1439*4882a593Smuzhiyun up_write(&nvmet_ana_sem);
1440*4882a593Smuzhiyun
1441*4882a593Smuzhiyun nvmet_port_send_ana_event(grp->port);
1442*4882a593Smuzhiyun
1443*4882a593Smuzhiyun config_group_init_type_name(&grp->group, name, &nvmet_ana_group_type);
1444*4882a593Smuzhiyun return &grp->group;
1445*4882a593Smuzhiyun out:
1446*4882a593Smuzhiyun return ERR_PTR(ret);
1447*4882a593Smuzhiyun }
1448*4882a593Smuzhiyun
1449*4882a593Smuzhiyun static struct configfs_group_operations nvmet_ana_groups_group_ops = {
1450*4882a593Smuzhiyun .make_group = nvmet_ana_groups_make_group,
1451*4882a593Smuzhiyun };
1452*4882a593Smuzhiyun
1453*4882a593Smuzhiyun static const struct config_item_type nvmet_ana_groups_type = {
1454*4882a593Smuzhiyun .ct_group_ops = &nvmet_ana_groups_group_ops,
1455*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
1456*4882a593Smuzhiyun };
1457*4882a593Smuzhiyun
1458*4882a593Smuzhiyun /*
1459*4882a593Smuzhiyun * Ports definitions.
1460*4882a593Smuzhiyun */
nvmet_port_release(struct config_item * item)1461*4882a593Smuzhiyun static void nvmet_port_release(struct config_item *item)
1462*4882a593Smuzhiyun {
1463*4882a593Smuzhiyun struct nvmet_port *port = to_nvmet_port(item);
1464*4882a593Smuzhiyun
1465*4882a593Smuzhiyun /* Let inflight controllers teardown complete */
1466*4882a593Smuzhiyun flush_scheduled_work();
1467*4882a593Smuzhiyun list_del(&port->global_entry);
1468*4882a593Smuzhiyun
1469*4882a593Smuzhiyun kfree(port->ana_state);
1470*4882a593Smuzhiyun kfree(port);
1471*4882a593Smuzhiyun }
1472*4882a593Smuzhiyun
1473*4882a593Smuzhiyun static struct configfs_attribute *nvmet_port_attrs[] = {
1474*4882a593Smuzhiyun &nvmet_attr_addr_adrfam,
1475*4882a593Smuzhiyun &nvmet_attr_addr_treq,
1476*4882a593Smuzhiyun &nvmet_attr_addr_traddr,
1477*4882a593Smuzhiyun &nvmet_attr_addr_trsvcid,
1478*4882a593Smuzhiyun &nvmet_attr_addr_trtype,
1479*4882a593Smuzhiyun &nvmet_attr_param_inline_data_size,
1480*4882a593Smuzhiyun #ifdef CONFIG_BLK_DEV_INTEGRITY
1481*4882a593Smuzhiyun &nvmet_attr_param_pi_enable,
1482*4882a593Smuzhiyun #endif
1483*4882a593Smuzhiyun NULL,
1484*4882a593Smuzhiyun };
1485*4882a593Smuzhiyun
1486*4882a593Smuzhiyun static struct configfs_item_operations nvmet_port_item_ops = {
1487*4882a593Smuzhiyun .release = nvmet_port_release,
1488*4882a593Smuzhiyun };
1489*4882a593Smuzhiyun
1490*4882a593Smuzhiyun static const struct config_item_type nvmet_port_type = {
1491*4882a593Smuzhiyun .ct_attrs = nvmet_port_attrs,
1492*4882a593Smuzhiyun .ct_item_ops = &nvmet_port_item_ops,
1493*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
1494*4882a593Smuzhiyun };
1495*4882a593Smuzhiyun
nvmet_ports_make(struct config_group * group,const char * name)1496*4882a593Smuzhiyun static struct config_group *nvmet_ports_make(struct config_group *group,
1497*4882a593Smuzhiyun const char *name)
1498*4882a593Smuzhiyun {
1499*4882a593Smuzhiyun struct nvmet_port *port;
1500*4882a593Smuzhiyun u16 portid;
1501*4882a593Smuzhiyun u32 i;
1502*4882a593Smuzhiyun
1503*4882a593Smuzhiyun if (kstrtou16(name, 0, &portid))
1504*4882a593Smuzhiyun return ERR_PTR(-EINVAL);
1505*4882a593Smuzhiyun
1506*4882a593Smuzhiyun port = kzalloc(sizeof(*port), GFP_KERNEL);
1507*4882a593Smuzhiyun if (!port)
1508*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
1509*4882a593Smuzhiyun
1510*4882a593Smuzhiyun port->ana_state = kcalloc(NVMET_MAX_ANAGRPS + 1,
1511*4882a593Smuzhiyun sizeof(*port->ana_state), GFP_KERNEL);
1512*4882a593Smuzhiyun if (!port->ana_state) {
1513*4882a593Smuzhiyun kfree(port);
1514*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
1515*4882a593Smuzhiyun }
1516*4882a593Smuzhiyun
1517*4882a593Smuzhiyun for (i = 1; i <= NVMET_MAX_ANAGRPS; i++) {
1518*4882a593Smuzhiyun if (i == NVMET_DEFAULT_ANA_GRPID)
1519*4882a593Smuzhiyun port->ana_state[1] = NVME_ANA_OPTIMIZED;
1520*4882a593Smuzhiyun else
1521*4882a593Smuzhiyun port->ana_state[i] = NVME_ANA_INACCESSIBLE;
1522*4882a593Smuzhiyun }
1523*4882a593Smuzhiyun
1524*4882a593Smuzhiyun list_add(&port->global_entry, &nvmet_ports_list);
1525*4882a593Smuzhiyun
1526*4882a593Smuzhiyun INIT_LIST_HEAD(&port->entry);
1527*4882a593Smuzhiyun INIT_LIST_HEAD(&port->subsystems);
1528*4882a593Smuzhiyun INIT_LIST_HEAD(&port->referrals);
1529*4882a593Smuzhiyun port->inline_data_size = -1; /* < 0 == let the transport choose */
1530*4882a593Smuzhiyun
1531*4882a593Smuzhiyun port->disc_addr.portid = cpu_to_le16(portid);
1532*4882a593Smuzhiyun port->disc_addr.adrfam = NVMF_ADDR_FAMILY_MAX;
1533*4882a593Smuzhiyun port->disc_addr.treq = NVMF_TREQ_DISABLE_SQFLOW;
1534*4882a593Smuzhiyun config_group_init_type_name(&port->group, name, &nvmet_port_type);
1535*4882a593Smuzhiyun
1536*4882a593Smuzhiyun config_group_init_type_name(&port->subsys_group,
1537*4882a593Smuzhiyun "subsystems", &nvmet_port_subsys_type);
1538*4882a593Smuzhiyun configfs_add_default_group(&port->subsys_group, &port->group);
1539*4882a593Smuzhiyun
1540*4882a593Smuzhiyun config_group_init_type_name(&port->referrals_group,
1541*4882a593Smuzhiyun "referrals", &nvmet_referrals_type);
1542*4882a593Smuzhiyun configfs_add_default_group(&port->referrals_group, &port->group);
1543*4882a593Smuzhiyun
1544*4882a593Smuzhiyun config_group_init_type_name(&port->ana_groups_group,
1545*4882a593Smuzhiyun "ana_groups", &nvmet_ana_groups_type);
1546*4882a593Smuzhiyun configfs_add_default_group(&port->ana_groups_group, &port->group);
1547*4882a593Smuzhiyun
1548*4882a593Smuzhiyun port->ana_default_group.port = port;
1549*4882a593Smuzhiyun port->ana_default_group.grpid = NVMET_DEFAULT_ANA_GRPID;
1550*4882a593Smuzhiyun config_group_init_type_name(&port->ana_default_group.group,
1551*4882a593Smuzhiyun __stringify(NVMET_DEFAULT_ANA_GRPID),
1552*4882a593Smuzhiyun &nvmet_ana_group_type);
1553*4882a593Smuzhiyun configfs_add_default_group(&port->ana_default_group.group,
1554*4882a593Smuzhiyun &port->ana_groups_group);
1555*4882a593Smuzhiyun
1556*4882a593Smuzhiyun return &port->group;
1557*4882a593Smuzhiyun }
1558*4882a593Smuzhiyun
1559*4882a593Smuzhiyun static struct configfs_group_operations nvmet_ports_group_ops = {
1560*4882a593Smuzhiyun .make_group = nvmet_ports_make,
1561*4882a593Smuzhiyun };
1562*4882a593Smuzhiyun
1563*4882a593Smuzhiyun static const struct config_item_type nvmet_ports_type = {
1564*4882a593Smuzhiyun .ct_group_ops = &nvmet_ports_group_ops,
1565*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
1566*4882a593Smuzhiyun };
1567*4882a593Smuzhiyun
1568*4882a593Smuzhiyun static struct config_group nvmet_subsystems_group;
1569*4882a593Smuzhiyun static struct config_group nvmet_ports_group;
1570*4882a593Smuzhiyun
nvmet_host_release(struct config_item * item)1571*4882a593Smuzhiyun static void nvmet_host_release(struct config_item *item)
1572*4882a593Smuzhiyun {
1573*4882a593Smuzhiyun struct nvmet_host *host = to_host(item);
1574*4882a593Smuzhiyun
1575*4882a593Smuzhiyun kfree(host);
1576*4882a593Smuzhiyun }
1577*4882a593Smuzhiyun
1578*4882a593Smuzhiyun static struct configfs_item_operations nvmet_host_item_ops = {
1579*4882a593Smuzhiyun .release = nvmet_host_release,
1580*4882a593Smuzhiyun };
1581*4882a593Smuzhiyun
1582*4882a593Smuzhiyun static const struct config_item_type nvmet_host_type = {
1583*4882a593Smuzhiyun .ct_item_ops = &nvmet_host_item_ops,
1584*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
1585*4882a593Smuzhiyun };
1586*4882a593Smuzhiyun
nvmet_hosts_make_group(struct config_group * group,const char * name)1587*4882a593Smuzhiyun static struct config_group *nvmet_hosts_make_group(struct config_group *group,
1588*4882a593Smuzhiyun const char *name)
1589*4882a593Smuzhiyun {
1590*4882a593Smuzhiyun struct nvmet_host *host;
1591*4882a593Smuzhiyun
1592*4882a593Smuzhiyun host = kzalloc(sizeof(*host), GFP_KERNEL);
1593*4882a593Smuzhiyun if (!host)
1594*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
1595*4882a593Smuzhiyun
1596*4882a593Smuzhiyun config_group_init_type_name(&host->group, name, &nvmet_host_type);
1597*4882a593Smuzhiyun
1598*4882a593Smuzhiyun return &host->group;
1599*4882a593Smuzhiyun }
1600*4882a593Smuzhiyun
1601*4882a593Smuzhiyun static struct configfs_group_operations nvmet_hosts_group_ops = {
1602*4882a593Smuzhiyun .make_group = nvmet_hosts_make_group,
1603*4882a593Smuzhiyun };
1604*4882a593Smuzhiyun
1605*4882a593Smuzhiyun static const struct config_item_type nvmet_hosts_type = {
1606*4882a593Smuzhiyun .ct_group_ops = &nvmet_hosts_group_ops,
1607*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
1608*4882a593Smuzhiyun };
1609*4882a593Smuzhiyun
1610*4882a593Smuzhiyun static struct config_group nvmet_hosts_group;
1611*4882a593Smuzhiyun
1612*4882a593Smuzhiyun static const struct config_item_type nvmet_root_type = {
1613*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
1614*4882a593Smuzhiyun };
1615*4882a593Smuzhiyun
1616*4882a593Smuzhiyun static struct configfs_subsystem nvmet_configfs_subsystem = {
1617*4882a593Smuzhiyun .su_group = {
1618*4882a593Smuzhiyun .cg_item = {
1619*4882a593Smuzhiyun .ci_namebuf = "nvmet",
1620*4882a593Smuzhiyun .ci_type = &nvmet_root_type,
1621*4882a593Smuzhiyun },
1622*4882a593Smuzhiyun },
1623*4882a593Smuzhiyun };
1624*4882a593Smuzhiyun
nvmet_init_configfs(void)1625*4882a593Smuzhiyun int __init nvmet_init_configfs(void)
1626*4882a593Smuzhiyun {
1627*4882a593Smuzhiyun int ret;
1628*4882a593Smuzhiyun
1629*4882a593Smuzhiyun config_group_init(&nvmet_configfs_subsystem.su_group);
1630*4882a593Smuzhiyun mutex_init(&nvmet_configfs_subsystem.su_mutex);
1631*4882a593Smuzhiyun
1632*4882a593Smuzhiyun config_group_init_type_name(&nvmet_subsystems_group,
1633*4882a593Smuzhiyun "subsystems", &nvmet_subsystems_type);
1634*4882a593Smuzhiyun configfs_add_default_group(&nvmet_subsystems_group,
1635*4882a593Smuzhiyun &nvmet_configfs_subsystem.su_group);
1636*4882a593Smuzhiyun
1637*4882a593Smuzhiyun config_group_init_type_name(&nvmet_ports_group,
1638*4882a593Smuzhiyun "ports", &nvmet_ports_type);
1639*4882a593Smuzhiyun configfs_add_default_group(&nvmet_ports_group,
1640*4882a593Smuzhiyun &nvmet_configfs_subsystem.su_group);
1641*4882a593Smuzhiyun
1642*4882a593Smuzhiyun config_group_init_type_name(&nvmet_hosts_group,
1643*4882a593Smuzhiyun "hosts", &nvmet_hosts_type);
1644*4882a593Smuzhiyun configfs_add_default_group(&nvmet_hosts_group,
1645*4882a593Smuzhiyun &nvmet_configfs_subsystem.su_group);
1646*4882a593Smuzhiyun
1647*4882a593Smuzhiyun ret = configfs_register_subsystem(&nvmet_configfs_subsystem);
1648*4882a593Smuzhiyun if (ret) {
1649*4882a593Smuzhiyun pr_err("configfs_register_subsystem: %d\n", ret);
1650*4882a593Smuzhiyun return ret;
1651*4882a593Smuzhiyun }
1652*4882a593Smuzhiyun
1653*4882a593Smuzhiyun return 0;
1654*4882a593Smuzhiyun }
1655*4882a593Smuzhiyun
nvmet_exit_configfs(void)1656*4882a593Smuzhiyun void __exit nvmet_exit_configfs(void)
1657*4882a593Smuzhiyun {
1658*4882a593Smuzhiyun configfs_unregister_subsystem(&nvmet_configfs_subsystem);
1659*4882a593Smuzhiyun }
1660