GNU Linux-libre 4.9.309-gnu1
[releases.git] / drivers / nvme / target / configfs.c
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 (ns->enabled)
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 (ns->enabled) {
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", to_nvmet_ns(item)->enabled);
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 }