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