xref: /openbmc/linux/drivers/nvme/target/configfs.c (revision bc5aa3a0)
1 /*
2  * Configfs interface for the NVMe target.
3  * Copyright (c) 2015-2016 HGST, a Western Digital Company.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  */
14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/slab.h>
18 #include <linux/stat.h>
19 #include <linux/ctype.h>
20 
21 #include "nvmet.h"
22 
23 static struct config_item_type nvmet_host_type;
24 static struct config_item_type nvmet_subsys_type;
25 
26 /*
27  * nvmet_port Generic ConfigFS definitions.
28  * Used in any place in the ConfigFS tree that refers to an address.
29  */
30 static ssize_t nvmet_addr_adrfam_show(struct config_item *item,
31 		char *page)
32 {
33 	switch (to_nvmet_port(item)->disc_addr.adrfam) {
34 	case NVMF_ADDR_FAMILY_IP4:
35 		return sprintf(page, "ipv4\n");
36 	case NVMF_ADDR_FAMILY_IP6:
37 		return sprintf(page, "ipv6\n");
38 	case NVMF_ADDR_FAMILY_IB:
39 		return sprintf(page, "ib\n");
40 	default:
41 		return sprintf(page, "\n");
42 	}
43 }
44 
45 static ssize_t nvmet_addr_adrfam_store(struct config_item *item,
46 		const char *page, size_t count)
47 {
48 	struct nvmet_port *port = to_nvmet_port(item);
49 
50 	if (port->enabled) {
51 		pr_err("Cannot modify address while enabled\n");
52 		pr_err("Disable the address before modifying\n");
53 		return -EACCES;
54 	}
55 
56 	if (sysfs_streq(page, "ipv4")) {
57 		port->disc_addr.adrfam = NVMF_ADDR_FAMILY_IP4;
58 	} else if (sysfs_streq(page, "ipv6")) {
59 		port->disc_addr.adrfam = NVMF_ADDR_FAMILY_IP6;
60 	} else if (sysfs_streq(page, "ib")) {
61 		port->disc_addr.adrfam = NVMF_ADDR_FAMILY_IB;
62 	} else {
63 		pr_err("Invalid value '%s' for adrfam\n", page);
64 		return -EINVAL;
65 	}
66 
67 	return count;
68 }
69 
70 CONFIGFS_ATTR(nvmet_, addr_adrfam);
71 
72 static ssize_t nvmet_addr_portid_show(struct config_item *item,
73 		char *page)
74 {
75 	struct nvmet_port *port = to_nvmet_port(item);
76 
77 	return snprintf(page, PAGE_SIZE, "%d\n",
78 			le16_to_cpu(port->disc_addr.portid));
79 }
80 
81 static ssize_t nvmet_addr_portid_store(struct config_item *item,
82 		const char *page, size_t count)
83 {
84 	struct nvmet_port *port = to_nvmet_port(item);
85 	u16 portid = 0;
86 
87 	if (kstrtou16(page, 0, &portid)) {
88 		pr_err("Invalid value '%s' for portid\n", page);
89 		return -EINVAL;
90 	}
91 
92 	if (port->enabled) {
93 		pr_err("Cannot modify address while enabled\n");
94 		pr_err("Disable the address before modifying\n");
95 		return -EACCES;
96 	}
97 	port->disc_addr.portid = cpu_to_le16(portid);
98 	return count;
99 }
100 
101 CONFIGFS_ATTR(nvmet_, addr_portid);
102 
103 static ssize_t nvmet_addr_traddr_show(struct config_item *item,
104 		char *page)
105 {
106 	struct nvmet_port *port = to_nvmet_port(item);
107 
108 	return snprintf(page, PAGE_SIZE, "%s\n",
109 			port->disc_addr.traddr);
110 }
111 
112 static ssize_t nvmet_addr_traddr_store(struct config_item *item,
113 		const char *page, size_t count)
114 {
115 	struct nvmet_port *port = to_nvmet_port(item);
116 
117 	if (count > NVMF_TRADDR_SIZE) {
118 		pr_err("Invalid value '%s' for traddr\n", page);
119 		return -EINVAL;
120 	}
121 
122 	if (port->enabled) {
123 		pr_err("Cannot modify address while enabled\n");
124 		pr_err("Disable the address before modifying\n");
125 		return -EACCES;
126 	}
127 	return snprintf(port->disc_addr.traddr,
128 			sizeof(port->disc_addr.traddr), "%s", page);
129 }
130 
131 CONFIGFS_ATTR(nvmet_, addr_traddr);
132 
133 static ssize_t nvmet_addr_treq_show(struct config_item *item,
134 		char *page)
135 {
136 	switch (to_nvmet_port(item)->disc_addr.treq) {
137 	case NVMF_TREQ_NOT_SPECIFIED:
138 		return sprintf(page, "not specified\n");
139 	case NVMF_TREQ_REQUIRED:
140 		return sprintf(page, "required\n");
141 	case NVMF_TREQ_NOT_REQUIRED:
142 		return sprintf(page, "not required\n");
143 	default:
144 		return sprintf(page, "\n");
145 	}
146 }
147 
148 static ssize_t nvmet_addr_treq_store(struct config_item *item,
149 		const char *page, size_t count)
150 {
151 	struct nvmet_port *port = to_nvmet_port(item);
152 
153 	if (port->enabled) {
154 		pr_err("Cannot modify address while enabled\n");
155 		pr_err("Disable the address before modifying\n");
156 		return -EACCES;
157 	}
158 
159 	if (sysfs_streq(page, "not specified")) {
160 		port->disc_addr.treq = NVMF_TREQ_NOT_SPECIFIED;
161 	} else if (sysfs_streq(page, "required")) {
162 		port->disc_addr.treq = NVMF_TREQ_REQUIRED;
163 	} else if (sysfs_streq(page, "not required")) {
164 		port->disc_addr.treq = NVMF_TREQ_NOT_REQUIRED;
165 	} else {
166 		pr_err("Invalid value '%s' for treq\n", page);
167 		return -EINVAL;
168 	}
169 
170 	return count;
171 }
172 
173 CONFIGFS_ATTR(nvmet_, addr_treq);
174 
175 static ssize_t nvmet_addr_trsvcid_show(struct config_item *item,
176 		char *page)
177 {
178 	struct nvmet_port *port = to_nvmet_port(item);
179 
180 	return snprintf(page, PAGE_SIZE, "%s\n",
181 			port->disc_addr.trsvcid);
182 }
183 
184 static ssize_t nvmet_addr_trsvcid_store(struct config_item *item,
185 		const char *page, size_t count)
186 {
187 	struct nvmet_port *port = to_nvmet_port(item);
188 
189 	if (count > NVMF_TRSVCID_SIZE) {
190 		pr_err("Invalid value '%s' for trsvcid\n", page);
191 		return -EINVAL;
192 	}
193 	if (port->enabled) {
194 		pr_err("Cannot modify address while enabled\n");
195 		pr_err("Disable the address before modifying\n");
196 		return -EACCES;
197 	}
198 	return snprintf(port->disc_addr.trsvcid,
199 			sizeof(port->disc_addr.trsvcid), "%s", page);
200 }
201 
202 CONFIGFS_ATTR(nvmet_, addr_trsvcid);
203 
204 static ssize_t nvmet_addr_trtype_show(struct config_item *item,
205 		char *page)
206 {
207 	switch (to_nvmet_port(item)->disc_addr.trtype) {
208 	case NVMF_TRTYPE_RDMA:
209 		return sprintf(page, "rdma\n");
210 	case NVMF_TRTYPE_LOOP:
211 		return sprintf(page, "loop\n");
212 	default:
213 		return sprintf(page, "\n");
214 	}
215 }
216 
217 static void nvmet_port_init_tsas_rdma(struct nvmet_port *port)
218 {
219 	port->disc_addr.trtype = NVMF_TRTYPE_RDMA;
220 	memset(&port->disc_addr.tsas.rdma, 0, NVMF_TSAS_SIZE);
221 	port->disc_addr.tsas.rdma.qptype = NVMF_RDMA_QPTYPE_CONNECTED;
222 	port->disc_addr.tsas.rdma.prtype = NVMF_RDMA_PRTYPE_NOT_SPECIFIED;
223 	port->disc_addr.tsas.rdma.cms = NVMF_RDMA_CMS_RDMA_CM;
224 }
225 
226 static void nvmet_port_init_tsas_loop(struct nvmet_port *port)
227 {
228 	port->disc_addr.trtype = NVMF_TRTYPE_LOOP;
229 	memset(&port->disc_addr.tsas, 0, NVMF_TSAS_SIZE);
230 }
231 
232 static ssize_t nvmet_addr_trtype_store(struct config_item *item,
233 		const char *page, size_t count)
234 {
235 	struct nvmet_port *port = to_nvmet_port(item);
236 
237 	if (port->enabled) {
238 		pr_err("Cannot modify address while enabled\n");
239 		pr_err("Disable the address before modifying\n");
240 		return -EACCES;
241 	}
242 
243 	if (sysfs_streq(page, "rdma")) {
244 		nvmet_port_init_tsas_rdma(port);
245 	} else if (sysfs_streq(page, "loop")) {
246 		nvmet_port_init_tsas_loop(port);
247 	} else {
248 		pr_err("Invalid value '%s' for trtype\n", page);
249 		return -EINVAL;
250 	}
251 
252 	return count;
253 }
254 
255 CONFIGFS_ATTR(nvmet_, addr_trtype);
256 
257 /*
258  * Namespace structures & file operation functions below
259  */
260 static ssize_t nvmet_ns_device_path_show(struct config_item *item, char *page)
261 {
262 	return sprintf(page, "%s\n", to_nvmet_ns(item)->device_path);
263 }
264 
265 static ssize_t nvmet_ns_device_path_store(struct config_item *item,
266 		const char *page, size_t count)
267 {
268 	struct nvmet_ns *ns = to_nvmet_ns(item);
269 	struct nvmet_subsys *subsys = ns->subsys;
270 	int ret;
271 
272 	mutex_lock(&subsys->lock);
273 	ret = -EBUSY;
274 	if (nvmet_ns_enabled(ns))
275 		goto out_unlock;
276 
277 	kfree(ns->device_path);
278 
279 	ret = -ENOMEM;
280 	ns->device_path = kstrdup(page, GFP_KERNEL);
281 	if (!ns->device_path)
282 		goto out_unlock;
283 
284 	mutex_unlock(&subsys->lock);
285 	return count;
286 
287 out_unlock:
288 	mutex_unlock(&subsys->lock);
289 	return ret;
290 }
291 
292 CONFIGFS_ATTR(nvmet_ns_, device_path);
293 
294 static ssize_t nvmet_ns_device_nguid_show(struct config_item *item, char *page)
295 {
296 	return sprintf(page, "%pUb\n", &to_nvmet_ns(item)->nguid);
297 }
298 
299 static ssize_t nvmet_ns_device_nguid_store(struct config_item *item,
300 		const char *page, size_t count)
301 {
302 	struct nvmet_ns *ns = to_nvmet_ns(item);
303 	struct nvmet_subsys *subsys = ns->subsys;
304 	u8 nguid[16];
305 	const char *p = page;
306 	int i;
307 	int ret = 0;
308 
309 	mutex_lock(&subsys->lock);
310 	if (nvmet_ns_enabled(ns)) {
311 		ret = -EBUSY;
312 		goto out_unlock;
313 	}
314 
315 	for (i = 0; i < 16; i++) {
316 		if (p + 2 > page + count) {
317 			ret = -EINVAL;
318 			goto out_unlock;
319 		}
320 		if (!isxdigit(p[0]) || !isxdigit(p[1])) {
321 			ret = -EINVAL;
322 			goto out_unlock;
323 		}
324 
325 		nguid[i] = (hex_to_bin(p[0]) << 4) | hex_to_bin(p[1]);
326 		p += 2;
327 
328 		if (*p == '-' || *p == ':')
329 			p++;
330 	}
331 
332 	memcpy(&ns->nguid, nguid, sizeof(nguid));
333 out_unlock:
334 	mutex_unlock(&subsys->lock);
335 	return ret ? ret : count;
336 }
337 
338 CONFIGFS_ATTR(nvmet_ns_, device_nguid);
339 
340 static ssize_t nvmet_ns_enable_show(struct config_item *item, char *page)
341 {
342 	return sprintf(page, "%d\n", nvmet_ns_enabled(to_nvmet_ns(item)));
343 }
344 
345 static ssize_t nvmet_ns_enable_store(struct config_item *item,
346 		const char *page, size_t count)
347 {
348 	struct nvmet_ns *ns = to_nvmet_ns(item);
349 	bool enable;
350 	int ret = 0;
351 
352 	if (strtobool(page, &enable))
353 		return -EINVAL;
354 
355 	if (enable)
356 		ret = nvmet_ns_enable(ns);
357 	else
358 		nvmet_ns_disable(ns);
359 
360 	return ret ? ret : count;
361 }
362 
363 CONFIGFS_ATTR(nvmet_ns_, enable);
364 
365 static struct configfs_attribute *nvmet_ns_attrs[] = {
366 	&nvmet_ns_attr_device_path,
367 	&nvmet_ns_attr_device_nguid,
368 	&nvmet_ns_attr_enable,
369 	NULL,
370 };
371 
372 static void nvmet_ns_release(struct config_item *item)
373 {
374 	struct nvmet_ns *ns = to_nvmet_ns(item);
375 
376 	nvmet_ns_free(ns);
377 }
378 
379 static struct configfs_item_operations nvmet_ns_item_ops = {
380 	.release		= nvmet_ns_release,
381 };
382 
383 static struct config_item_type nvmet_ns_type = {
384 	.ct_item_ops		= &nvmet_ns_item_ops,
385 	.ct_attrs		= nvmet_ns_attrs,
386 	.ct_owner		= THIS_MODULE,
387 };
388 
389 static struct config_group *nvmet_ns_make(struct config_group *group,
390 		const char *name)
391 {
392 	struct nvmet_subsys *subsys = namespaces_to_subsys(&group->cg_item);
393 	struct nvmet_ns *ns;
394 	int ret;
395 	u32 nsid;
396 
397 	ret = kstrtou32(name, 0, &nsid);
398 	if (ret)
399 		goto out;
400 
401 	ret = -EINVAL;
402 	if (nsid == 0 || nsid == 0xffffffff)
403 		goto out;
404 
405 	ret = -ENOMEM;
406 	ns = nvmet_ns_alloc(subsys, nsid);
407 	if (!ns)
408 		goto out;
409 	config_group_init_type_name(&ns->group, name, &nvmet_ns_type);
410 
411 	pr_info("adding nsid %d to subsystem %s\n", nsid, subsys->subsysnqn);
412 
413 	return &ns->group;
414 out:
415 	return ERR_PTR(ret);
416 }
417 
418 static struct configfs_group_operations nvmet_namespaces_group_ops = {
419 	.make_group		= nvmet_ns_make,
420 };
421 
422 static struct config_item_type nvmet_namespaces_type = {
423 	.ct_group_ops		= &nvmet_namespaces_group_ops,
424 	.ct_owner		= THIS_MODULE,
425 };
426 
427 static int nvmet_port_subsys_allow_link(struct config_item *parent,
428 		struct config_item *target)
429 {
430 	struct nvmet_port *port = to_nvmet_port(parent->ci_parent);
431 	struct nvmet_subsys *subsys;
432 	struct nvmet_subsys_link *link, *p;
433 	int ret;
434 
435 	if (target->ci_type != &nvmet_subsys_type) {
436 		pr_err("can only link subsystems into the subsystems dir.!\n");
437 		return -EINVAL;
438 	}
439 	subsys = to_subsys(target);
440 	link = kmalloc(sizeof(*link), GFP_KERNEL);
441 	if (!link)
442 		return -ENOMEM;
443 	link->subsys = subsys;
444 
445 	down_write(&nvmet_config_sem);
446 	ret = -EEXIST;
447 	list_for_each_entry(p, &port->subsystems, entry) {
448 		if (p->subsys == subsys)
449 			goto out_free_link;
450 	}
451 
452 	if (list_empty(&port->subsystems)) {
453 		ret = nvmet_enable_port(port);
454 		if (ret)
455 			goto out_free_link;
456 	}
457 
458 	list_add_tail(&link->entry, &port->subsystems);
459 	nvmet_genctr++;
460 	up_write(&nvmet_config_sem);
461 	return 0;
462 
463 out_free_link:
464 	up_write(&nvmet_config_sem);
465 	kfree(link);
466 	return ret;
467 }
468 
469 static int nvmet_port_subsys_drop_link(struct config_item *parent,
470 		struct config_item *target)
471 {
472 	struct nvmet_port *port = to_nvmet_port(parent->ci_parent);
473 	struct nvmet_subsys *subsys = to_subsys(target);
474 	struct nvmet_subsys_link *p;
475 
476 	down_write(&nvmet_config_sem);
477 	list_for_each_entry(p, &port->subsystems, entry) {
478 		if (p->subsys == subsys)
479 			goto found;
480 	}
481 	up_write(&nvmet_config_sem);
482 	return -EINVAL;
483 
484 found:
485 	list_del(&p->entry);
486 	nvmet_genctr++;
487 	if (list_empty(&port->subsystems))
488 		nvmet_disable_port(port);
489 	up_write(&nvmet_config_sem);
490 	kfree(p);
491 	return 0;
492 }
493 
494 static struct configfs_item_operations nvmet_port_subsys_item_ops = {
495 	.allow_link		= nvmet_port_subsys_allow_link,
496 	.drop_link		= nvmet_port_subsys_drop_link,
497 };
498 
499 static struct config_item_type nvmet_port_subsys_type = {
500 	.ct_item_ops		= &nvmet_port_subsys_item_ops,
501 	.ct_owner		= THIS_MODULE,
502 };
503 
504 static int nvmet_allowed_hosts_allow_link(struct config_item *parent,
505 		struct config_item *target)
506 {
507 	struct nvmet_subsys *subsys = to_subsys(parent->ci_parent);
508 	struct nvmet_host *host;
509 	struct nvmet_host_link *link, *p;
510 	int ret;
511 
512 	if (target->ci_type != &nvmet_host_type) {
513 		pr_err("can only link hosts into the allowed_hosts directory!\n");
514 		return -EINVAL;
515 	}
516 
517 	host = to_host(target);
518 	link = kmalloc(sizeof(*link), GFP_KERNEL);
519 	if (!link)
520 		return -ENOMEM;
521 	link->host = host;
522 
523 	down_write(&nvmet_config_sem);
524 	ret = -EINVAL;
525 	if (subsys->allow_any_host) {
526 		pr_err("can't add hosts when allow_any_host is set!\n");
527 		goto out_free_link;
528 	}
529 
530 	ret = -EEXIST;
531 	list_for_each_entry(p, &subsys->hosts, entry) {
532 		if (!strcmp(nvmet_host_name(p->host), nvmet_host_name(host)))
533 			goto out_free_link;
534 	}
535 	list_add_tail(&link->entry, &subsys->hosts);
536 	nvmet_genctr++;
537 	up_write(&nvmet_config_sem);
538 	return 0;
539 out_free_link:
540 	up_write(&nvmet_config_sem);
541 	kfree(link);
542 	return ret;
543 }
544 
545 static int nvmet_allowed_hosts_drop_link(struct config_item *parent,
546 		struct config_item *target)
547 {
548 	struct nvmet_subsys *subsys = to_subsys(parent->ci_parent);
549 	struct nvmet_host *host = to_host(target);
550 	struct nvmet_host_link *p;
551 
552 	down_write(&nvmet_config_sem);
553 	list_for_each_entry(p, &subsys->hosts, entry) {
554 		if (!strcmp(nvmet_host_name(p->host), nvmet_host_name(host)))
555 			goto found;
556 	}
557 	up_write(&nvmet_config_sem);
558 	return -EINVAL;
559 
560 found:
561 	list_del(&p->entry);
562 	nvmet_genctr++;
563 	up_write(&nvmet_config_sem);
564 	kfree(p);
565 	return 0;
566 }
567 
568 static struct configfs_item_operations nvmet_allowed_hosts_item_ops = {
569 	.allow_link		= nvmet_allowed_hosts_allow_link,
570 	.drop_link		= nvmet_allowed_hosts_drop_link,
571 };
572 
573 static struct config_item_type nvmet_allowed_hosts_type = {
574 	.ct_item_ops		= &nvmet_allowed_hosts_item_ops,
575 	.ct_owner		= THIS_MODULE,
576 };
577 
578 static ssize_t nvmet_subsys_attr_allow_any_host_show(struct config_item *item,
579 		char *page)
580 {
581 	return snprintf(page, PAGE_SIZE, "%d\n",
582 		to_subsys(item)->allow_any_host);
583 }
584 
585 static ssize_t nvmet_subsys_attr_allow_any_host_store(struct config_item *item,
586 		const char *page, size_t count)
587 {
588 	struct nvmet_subsys *subsys = to_subsys(item);
589 	bool allow_any_host;
590 	int ret = 0;
591 
592 	if (strtobool(page, &allow_any_host))
593 		return -EINVAL;
594 
595 	down_write(&nvmet_config_sem);
596 	if (allow_any_host && !list_empty(&subsys->hosts)) {
597 		pr_err("Can't set allow_any_host when explicit hosts are set!\n");
598 		ret = -EINVAL;
599 		goto out_unlock;
600 	}
601 
602 	subsys->allow_any_host = allow_any_host;
603 out_unlock:
604 	up_write(&nvmet_config_sem);
605 	return ret ? ret : count;
606 }
607 
608 CONFIGFS_ATTR(nvmet_subsys_, attr_allow_any_host);
609 
610 static struct configfs_attribute *nvmet_subsys_attrs[] = {
611 	&nvmet_subsys_attr_attr_allow_any_host,
612 	NULL,
613 };
614 
615 /*
616  * Subsystem structures & folder operation functions below
617  */
618 static void nvmet_subsys_release(struct config_item *item)
619 {
620 	struct nvmet_subsys *subsys = to_subsys(item);
621 
622 	nvmet_subsys_put(subsys);
623 }
624 
625 static struct configfs_item_operations nvmet_subsys_item_ops = {
626 	.release		= nvmet_subsys_release,
627 };
628 
629 static struct config_item_type nvmet_subsys_type = {
630 	.ct_item_ops		= &nvmet_subsys_item_ops,
631 	.ct_attrs		= nvmet_subsys_attrs,
632 	.ct_owner		= THIS_MODULE,
633 };
634 
635 static struct config_group *nvmet_subsys_make(struct config_group *group,
636 		const char *name)
637 {
638 	struct nvmet_subsys *subsys;
639 
640 	if (sysfs_streq(name, NVME_DISC_SUBSYS_NAME)) {
641 		pr_err("can't create discovery subsystem through configfs\n");
642 		return ERR_PTR(-EINVAL);
643 	}
644 
645 	subsys = nvmet_subsys_alloc(name, NVME_NQN_NVME);
646 	if (!subsys)
647 		return ERR_PTR(-ENOMEM);
648 
649 	config_group_init_type_name(&subsys->group, name, &nvmet_subsys_type);
650 
651 	config_group_init_type_name(&subsys->namespaces_group,
652 			"namespaces", &nvmet_namespaces_type);
653 	configfs_add_default_group(&subsys->namespaces_group, &subsys->group);
654 
655 	config_group_init_type_name(&subsys->allowed_hosts_group,
656 			"allowed_hosts", &nvmet_allowed_hosts_type);
657 	configfs_add_default_group(&subsys->allowed_hosts_group,
658 			&subsys->group);
659 
660 	return &subsys->group;
661 }
662 
663 static struct configfs_group_operations nvmet_subsystems_group_ops = {
664 	.make_group		= nvmet_subsys_make,
665 };
666 
667 static struct config_item_type nvmet_subsystems_type = {
668 	.ct_group_ops		= &nvmet_subsystems_group_ops,
669 	.ct_owner		= THIS_MODULE,
670 };
671 
672 static ssize_t nvmet_referral_enable_show(struct config_item *item,
673 		char *page)
674 {
675 	return snprintf(page, PAGE_SIZE, "%d\n", to_nvmet_port(item)->enabled);
676 }
677 
678 static ssize_t nvmet_referral_enable_store(struct config_item *item,
679 		const char *page, size_t count)
680 {
681 	struct nvmet_port *parent = to_nvmet_port(item->ci_parent->ci_parent);
682 	struct nvmet_port *port = to_nvmet_port(item);
683 	bool enable;
684 
685 	if (strtobool(page, &enable))
686 		goto inval;
687 
688 	if (enable)
689 		nvmet_referral_enable(parent, port);
690 	else
691 		nvmet_referral_disable(port);
692 
693 	return count;
694 inval:
695 	pr_err("Invalid value '%s' for enable\n", page);
696 	return -EINVAL;
697 }
698 
699 CONFIGFS_ATTR(nvmet_referral_, enable);
700 
701 /*
702  * Discovery Service subsystem definitions
703  */
704 static struct configfs_attribute *nvmet_referral_attrs[] = {
705 	&nvmet_attr_addr_adrfam,
706 	&nvmet_attr_addr_portid,
707 	&nvmet_attr_addr_treq,
708 	&nvmet_attr_addr_traddr,
709 	&nvmet_attr_addr_trsvcid,
710 	&nvmet_attr_addr_trtype,
711 	&nvmet_referral_attr_enable,
712 	NULL,
713 };
714 
715 static void nvmet_referral_release(struct config_item *item)
716 {
717 	struct nvmet_port *port = to_nvmet_port(item);
718 
719 	nvmet_referral_disable(port);
720 	kfree(port);
721 }
722 
723 static struct configfs_item_operations nvmet_referral_item_ops = {
724 	.release	= nvmet_referral_release,
725 };
726 
727 static struct config_item_type nvmet_referral_type = {
728 	.ct_owner	= THIS_MODULE,
729 	.ct_attrs	= nvmet_referral_attrs,
730 	.ct_item_ops	= &nvmet_referral_item_ops,
731 };
732 
733 static struct config_group *nvmet_referral_make(
734 		struct config_group *group, const char *name)
735 {
736 	struct nvmet_port *port;
737 
738 	port = kzalloc(sizeof(*port), GFP_KERNEL);
739 	if (!port)
740 		return ERR_PTR(-ENOMEM);
741 
742 	INIT_LIST_HEAD(&port->entry);
743 	config_group_init_type_name(&port->group, name, &nvmet_referral_type);
744 
745 	return &port->group;
746 }
747 
748 static struct configfs_group_operations nvmet_referral_group_ops = {
749 	.make_group		= nvmet_referral_make,
750 };
751 
752 static struct config_item_type nvmet_referrals_type = {
753 	.ct_owner	= THIS_MODULE,
754 	.ct_group_ops	= &nvmet_referral_group_ops,
755 };
756 
757 /*
758  * Ports definitions.
759  */
760 static void nvmet_port_release(struct config_item *item)
761 {
762 	struct nvmet_port *port = to_nvmet_port(item);
763 
764 	kfree(port);
765 }
766 
767 static struct configfs_attribute *nvmet_port_attrs[] = {
768 	&nvmet_attr_addr_adrfam,
769 	&nvmet_attr_addr_treq,
770 	&nvmet_attr_addr_traddr,
771 	&nvmet_attr_addr_trsvcid,
772 	&nvmet_attr_addr_trtype,
773 	NULL,
774 };
775 
776 static struct configfs_item_operations nvmet_port_item_ops = {
777 	.release		= nvmet_port_release,
778 };
779 
780 static struct config_item_type nvmet_port_type = {
781 	.ct_attrs		= nvmet_port_attrs,
782 	.ct_item_ops		= &nvmet_port_item_ops,
783 	.ct_owner		= THIS_MODULE,
784 };
785 
786 static struct config_group *nvmet_ports_make(struct config_group *group,
787 		const char *name)
788 {
789 	struct nvmet_port *port;
790 	u16 portid;
791 
792 	if (kstrtou16(name, 0, &portid))
793 		return ERR_PTR(-EINVAL);
794 
795 	port = kzalloc(sizeof(*port), GFP_KERNEL);
796 	if (!port)
797 		return ERR_PTR(-ENOMEM);
798 
799 	INIT_LIST_HEAD(&port->entry);
800 	INIT_LIST_HEAD(&port->subsystems);
801 	INIT_LIST_HEAD(&port->referrals);
802 
803 	port->disc_addr.portid = cpu_to_le16(portid);
804 	config_group_init_type_name(&port->group, name, &nvmet_port_type);
805 
806 	config_group_init_type_name(&port->subsys_group,
807 			"subsystems", &nvmet_port_subsys_type);
808 	configfs_add_default_group(&port->subsys_group, &port->group);
809 
810 	config_group_init_type_name(&port->referrals_group,
811 			"referrals", &nvmet_referrals_type);
812 	configfs_add_default_group(&port->referrals_group, &port->group);
813 
814 	return &port->group;
815 }
816 
817 static struct configfs_group_operations nvmet_ports_group_ops = {
818 	.make_group		= nvmet_ports_make,
819 };
820 
821 static struct config_item_type nvmet_ports_type = {
822 	.ct_group_ops		= &nvmet_ports_group_ops,
823 	.ct_owner		= THIS_MODULE,
824 };
825 
826 static struct config_group nvmet_subsystems_group;
827 static struct config_group nvmet_ports_group;
828 
829 static void nvmet_host_release(struct config_item *item)
830 {
831 	struct nvmet_host *host = to_host(item);
832 
833 	kfree(host);
834 }
835 
836 static struct configfs_item_operations nvmet_host_item_ops = {
837 	.release		= nvmet_host_release,
838 };
839 
840 static struct config_item_type nvmet_host_type = {
841 	.ct_item_ops		= &nvmet_host_item_ops,
842 	.ct_owner		= THIS_MODULE,
843 };
844 
845 static struct config_group *nvmet_hosts_make_group(struct config_group *group,
846 		const char *name)
847 {
848 	struct nvmet_host *host;
849 
850 	host = kzalloc(sizeof(*host), GFP_KERNEL);
851 	if (!host)
852 		return ERR_PTR(-ENOMEM);
853 
854 	config_group_init_type_name(&host->group, name, &nvmet_host_type);
855 
856 	return &host->group;
857 }
858 
859 static struct configfs_group_operations nvmet_hosts_group_ops = {
860 	.make_group		= nvmet_hosts_make_group,
861 };
862 
863 static struct config_item_type nvmet_hosts_type = {
864 	.ct_group_ops		= &nvmet_hosts_group_ops,
865 	.ct_owner		= THIS_MODULE,
866 };
867 
868 static struct config_group nvmet_hosts_group;
869 
870 static struct config_item_type nvmet_root_type = {
871 	.ct_owner		= THIS_MODULE,
872 };
873 
874 static struct configfs_subsystem nvmet_configfs_subsystem = {
875 	.su_group = {
876 		.cg_item = {
877 			.ci_namebuf	= "nvmet",
878 			.ci_type	= &nvmet_root_type,
879 		},
880 	},
881 };
882 
883 int __init nvmet_init_configfs(void)
884 {
885 	int ret;
886 
887 	config_group_init(&nvmet_configfs_subsystem.su_group);
888 	mutex_init(&nvmet_configfs_subsystem.su_mutex);
889 
890 	config_group_init_type_name(&nvmet_subsystems_group,
891 			"subsystems", &nvmet_subsystems_type);
892 	configfs_add_default_group(&nvmet_subsystems_group,
893 			&nvmet_configfs_subsystem.su_group);
894 
895 	config_group_init_type_name(&nvmet_ports_group,
896 			"ports", &nvmet_ports_type);
897 	configfs_add_default_group(&nvmet_ports_group,
898 			&nvmet_configfs_subsystem.su_group);
899 
900 	config_group_init_type_name(&nvmet_hosts_group,
901 			"hosts", &nvmet_hosts_type);
902 	configfs_add_default_group(&nvmet_hosts_group,
903 			&nvmet_configfs_subsystem.su_group);
904 
905 	ret = configfs_register_subsystem(&nvmet_configfs_subsystem);
906 	if (ret) {
907 		pr_err("configfs_register_subsystem: %d\n", ret);
908 		return ret;
909 	}
910 
911 	return 0;
912 }
913 
914 void __exit nvmet_exit_configfs(void)
915 {
916 	configfs_unregister_subsystem(&nvmet_configfs_subsystem);
917 }
918