]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/nvme/target/configfs.c
Merge tag 'driver-core-4.13-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git...
[karo-tx-linux.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         case NVMF_ADDR_FAMILY_FC:
41                 return sprintf(page, "fc\n");
42         default:
43                 return sprintf(page, "\n");
44         }
45 }
46
47 static 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;
64         } else if (sysfs_streq(page, "fc")) {
65                 port->disc_addr.adrfam = NVMF_ADDR_FAMILY_FC;
66         } else {
67                 pr_err("Invalid value '%s' for adrfam\n", page);
68                 return -EINVAL;
69         }
70
71         return count;
72 }
73
74 CONFIGFS_ATTR(nvmet_, addr_adrfam);
75
76 static 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
85 static 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
105 CONFIGFS_ATTR(nvmet_, addr_portid);
106
107 static 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
116 static 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
135 CONFIGFS_ATTR(nvmet_, addr_traddr);
136
137 static 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
152 static 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
177 CONFIGFS_ATTR(nvmet_, addr_treq);
178
179 static 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
188 static 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
206 CONFIGFS_ATTR(nvmet_, addr_trsvcid);
207
208 static 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");
216         case NVMF_TRTYPE_FC:
217                 return sprintf(page, "fc\n");
218         default:
219                 return sprintf(page, "\n");
220         }
221 }
222
223 static 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
232 static 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
238 static 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
244 static 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);
259         } else if (sysfs_streq(page, "fc")) {
260                 nvmet_port_init_tsas_fc(port);
261         } else {
262                 pr_err("Invalid value '%s' for trtype\n", page);
263                 return -EINVAL;
264         }
265
266         return count;
267 }
268
269 CONFIGFS_ATTR(nvmet_, addr_trtype);
270
271 /*
272  * Namespace structures & file operation functions below
273  */
274 static 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
279 static 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;
288         if (ns->enabled)
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
301 out_unlock:
302         mutex_unlock(&subsys->lock);
303         return ret;
304 }
305
306 CONFIGFS_ATTR(nvmet_ns_, device_path);
307
308 static ssize_t nvmet_ns_device_uuid_show(struct config_item *item, char *page)
309 {
310         return sprintf(page, "%pUb\n", &to_nvmet_ns(item)->uuid);
311 }
312
313 static ssize_t nvmet_ns_device_uuid_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         int ret = 0;
319
320
321         mutex_lock(&subsys->lock);
322         if (ns->enabled) {
323                 ret = -EBUSY;
324                 goto out_unlock;
325         }
326
327
328         if (uuid_parse(page, &ns->uuid))
329                 ret = -EINVAL;
330
331 out_unlock:
332         mutex_unlock(&subsys->lock);
333         return ret ? ret : count;
334 }
335
336 static ssize_t nvmet_ns_device_nguid_show(struct config_item *item, char *page)
337 {
338         return sprintf(page, "%pUb\n", &to_nvmet_ns(item)->nguid);
339 }
340
341 CONFIGFS_ATTR(nvmet_ns_, device_uuid);
342
343 static ssize_t nvmet_ns_device_nguid_store(struct config_item *item,
344                 const char *page, size_t count)
345 {
346         struct nvmet_ns *ns = to_nvmet_ns(item);
347         struct nvmet_subsys *subsys = ns->subsys;
348         u8 nguid[16];
349         const char *p = page;
350         int i;
351         int ret = 0;
352
353         mutex_lock(&subsys->lock);
354         if (ns->enabled) {
355                 ret = -EBUSY;
356                 goto out_unlock;
357         }
358
359         for (i = 0; i < 16; i++) {
360                 if (p + 2 > page + count) {
361                         ret = -EINVAL;
362                         goto out_unlock;
363                 }
364                 if (!isxdigit(p[0]) || !isxdigit(p[1])) {
365                         ret = -EINVAL;
366                         goto out_unlock;
367                 }
368
369                 nguid[i] = (hex_to_bin(p[0]) << 4) | hex_to_bin(p[1]);
370                 p += 2;
371
372                 if (*p == '-' || *p == ':')
373                         p++;
374         }
375
376         memcpy(&ns->nguid, nguid, sizeof(nguid));
377 out_unlock:
378         mutex_unlock(&subsys->lock);
379         return ret ? ret : count;
380 }
381
382 CONFIGFS_ATTR(nvmet_ns_, device_nguid);
383
384 static ssize_t nvmet_ns_enable_show(struct config_item *item, char *page)
385 {
386         return sprintf(page, "%d\n", to_nvmet_ns(item)->enabled);
387 }
388
389 static ssize_t nvmet_ns_enable_store(struct config_item *item,
390                 const char *page, size_t count)
391 {
392         struct nvmet_ns *ns = to_nvmet_ns(item);
393         bool enable;
394         int ret = 0;
395
396         if (strtobool(page, &enable))
397                 return -EINVAL;
398
399         if (enable)
400                 ret = nvmet_ns_enable(ns);
401         else
402                 nvmet_ns_disable(ns);
403
404         return ret ? ret : count;
405 }
406
407 CONFIGFS_ATTR(nvmet_ns_, enable);
408
409 static struct configfs_attribute *nvmet_ns_attrs[] = {
410         &nvmet_ns_attr_device_path,
411         &nvmet_ns_attr_device_nguid,
412         &nvmet_ns_attr_device_uuid,
413         &nvmet_ns_attr_enable,
414         NULL,
415 };
416
417 static void nvmet_ns_release(struct config_item *item)
418 {
419         struct nvmet_ns *ns = to_nvmet_ns(item);
420
421         nvmet_ns_free(ns);
422 }
423
424 static struct configfs_item_operations nvmet_ns_item_ops = {
425         .release                = nvmet_ns_release,
426 };
427
428 static struct config_item_type nvmet_ns_type = {
429         .ct_item_ops            = &nvmet_ns_item_ops,
430         .ct_attrs               = nvmet_ns_attrs,
431         .ct_owner               = THIS_MODULE,
432 };
433
434 static struct config_group *nvmet_ns_make(struct config_group *group,
435                 const char *name)
436 {
437         struct nvmet_subsys *subsys = namespaces_to_subsys(&group->cg_item);
438         struct nvmet_ns *ns;
439         int ret;
440         u32 nsid;
441
442         ret = kstrtou32(name, 0, &nsid);
443         if (ret)
444                 goto out;
445
446         ret = -EINVAL;
447         if (nsid == 0 || nsid == 0xffffffff)
448                 goto out;
449
450         ret = -ENOMEM;
451         ns = nvmet_ns_alloc(subsys, nsid);
452         if (!ns)
453                 goto out;
454         config_group_init_type_name(&ns->group, name, &nvmet_ns_type);
455
456         pr_info("adding nsid %d to subsystem %s\n", nsid, subsys->subsysnqn);
457
458         return &ns->group;
459 out:
460         return ERR_PTR(ret);
461 }
462
463 static struct configfs_group_operations nvmet_namespaces_group_ops = {
464         .make_group             = nvmet_ns_make,
465 };
466
467 static struct config_item_type nvmet_namespaces_type = {
468         .ct_group_ops           = &nvmet_namespaces_group_ops,
469         .ct_owner               = THIS_MODULE,
470 };
471
472 static int nvmet_port_subsys_allow_link(struct config_item *parent,
473                 struct config_item *target)
474 {
475         struct nvmet_port *port = to_nvmet_port(parent->ci_parent);
476         struct nvmet_subsys *subsys;
477         struct nvmet_subsys_link *link, *p;
478         int ret;
479
480         if (target->ci_type != &nvmet_subsys_type) {
481                 pr_err("can only link subsystems into the subsystems dir.!\n");
482                 return -EINVAL;
483         }
484         subsys = to_subsys(target);
485         link = kmalloc(sizeof(*link), GFP_KERNEL);
486         if (!link)
487                 return -ENOMEM;
488         link->subsys = subsys;
489
490         down_write(&nvmet_config_sem);
491         ret = -EEXIST;
492         list_for_each_entry(p, &port->subsystems, entry) {
493                 if (p->subsys == subsys)
494                         goto out_free_link;
495         }
496
497         if (list_empty(&port->subsystems)) {
498                 ret = nvmet_enable_port(port);
499                 if (ret)
500                         goto out_free_link;
501         }
502
503         list_add_tail(&link->entry, &port->subsystems);
504         nvmet_genctr++;
505         up_write(&nvmet_config_sem);
506         return 0;
507
508 out_free_link:
509         up_write(&nvmet_config_sem);
510         kfree(link);
511         return ret;
512 }
513
514 static void nvmet_port_subsys_drop_link(struct config_item *parent,
515                 struct config_item *target)
516 {
517         struct nvmet_port *port = to_nvmet_port(parent->ci_parent);
518         struct nvmet_subsys *subsys = to_subsys(target);
519         struct nvmet_subsys_link *p;
520
521         down_write(&nvmet_config_sem);
522         list_for_each_entry(p, &port->subsystems, entry) {
523                 if (p->subsys == subsys)
524                         goto found;
525         }
526         up_write(&nvmet_config_sem);
527         return;
528
529 found:
530         list_del(&p->entry);
531         nvmet_genctr++;
532         if (list_empty(&port->subsystems))
533                 nvmet_disable_port(port);
534         up_write(&nvmet_config_sem);
535         kfree(p);
536 }
537
538 static struct configfs_item_operations nvmet_port_subsys_item_ops = {
539         .allow_link             = nvmet_port_subsys_allow_link,
540         .drop_link              = nvmet_port_subsys_drop_link,
541 };
542
543 static struct config_item_type nvmet_port_subsys_type = {
544         .ct_item_ops            = &nvmet_port_subsys_item_ops,
545         .ct_owner               = THIS_MODULE,
546 };
547
548 static int nvmet_allowed_hosts_allow_link(struct config_item *parent,
549                 struct config_item *target)
550 {
551         struct nvmet_subsys *subsys = to_subsys(parent->ci_parent);
552         struct nvmet_host *host;
553         struct nvmet_host_link *link, *p;
554         int ret;
555
556         if (target->ci_type != &nvmet_host_type) {
557                 pr_err("can only link hosts into the allowed_hosts directory!\n");
558                 return -EINVAL;
559         }
560
561         host = to_host(target);
562         link = kmalloc(sizeof(*link), GFP_KERNEL);
563         if (!link)
564                 return -ENOMEM;
565         link->host = host;
566
567         down_write(&nvmet_config_sem);
568         ret = -EINVAL;
569         if (subsys->allow_any_host) {
570                 pr_err("can't add hosts when allow_any_host is set!\n");
571                 goto out_free_link;
572         }
573
574         ret = -EEXIST;
575         list_for_each_entry(p, &subsys->hosts, entry) {
576                 if (!strcmp(nvmet_host_name(p->host), nvmet_host_name(host)))
577                         goto out_free_link;
578         }
579         list_add_tail(&link->entry, &subsys->hosts);
580         nvmet_genctr++;
581         up_write(&nvmet_config_sem);
582         return 0;
583 out_free_link:
584         up_write(&nvmet_config_sem);
585         kfree(link);
586         return ret;
587 }
588
589 static void nvmet_allowed_hosts_drop_link(struct config_item *parent,
590                 struct config_item *target)
591 {
592         struct nvmet_subsys *subsys = to_subsys(parent->ci_parent);
593         struct nvmet_host *host = to_host(target);
594         struct nvmet_host_link *p;
595
596         down_write(&nvmet_config_sem);
597         list_for_each_entry(p, &subsys->hosts, entry) {
598                 if (!strcmp(nvmet_host_name(p->host), nvmet_host_name(host)))
599                         goto found;
600         }
601         up_write(&nvmet_config_sem);
602         return;
603
604 found:
605         list_del(&p->entry);
606         nvmet_genctr++;
607         up_write(&nvmet_config_sem);
608         kfree(p);
609 }
610
611 static struct configfs_item_operations nvmet_allowed_hosts_item_ops = {
612         .allow_link             = nvmet_allowed_hosts_allow_link,
613         .drop_link              = nvmet_allowed_hosts_drop_link,
614 };
615
616 static struct config_item_type nvmet_allowed_hosts_type = {
617         .ct_item_ops            = &nvmet_allowed_hosts_item_ops,
618         .ct_owner               = THIS_MODULE,
619 };
620
621 static ssize_t nvmet_subsys_attr_allow_any_host_show(struct config_item *item,
622                 char *page)
623 {
624         return snprintf(page, PAGE_SIZE, "%d\n",
625                 to_subsys(item)->allow_any_host);
626 }
627
628 static ssize_t nvmet_subsys_attr_allow_any_host_store(struct config_item *item,
629                 const char *page, size_t count)
630 {
631         struct nvmet_subsys *subsys = to_subsys(item);
632         bool allow_any_host;
633         int ret = 0;
634
635         if (strtobool(page, &allow_any_host))
636                 return -EINVAL;
637
638         down_write(&nvmet_config_sem);
639         if (allow_any_host && !list_empty(&subsys->hosts)) {
640                 pr_err("Can't set allow_any_host when explicit hosts are set!\n");
641                 ret = -EINVAL;
642                 goto out_unlock;
643         }
644
645         subsys->allow_any_host = allow_any_host;
646 out_unlock:
647         up_write(&nvmet_config_sem);
648         return ret ? ret : count;
649 }
650
651 CONFIGFS_ATTR(nvmet_subsys_, attr_allow_any_host);
652
653 static ssize_t nvmet_subsys_attr_version_show(struct config_item *item,
654                                               char *page)
655 {
656         struct nvmet_subsys *subsys = to_subsys(item);
657
658         if (NVME_TERTIARY(subsys->ver))
659                 return snprintf(page, PAGE_SIZE, "%d.%d.%d\n",
660                                 (int)NVME_MAJOR(subsys->ver),
661                                 (int)NVME_MINOR(subsys->ver),
662                                 (int)NVME_TERTIARY(subsys->ver));
663         else
664                 return snprintf(page, PAGE_SIZE, "%d.%d\n",
665                                 (int)NVME_MAJOR(subsys->ver),
666                                 (int)NVME_MINOR(subsys->ver));
667 }
668
669 static ssize_t nvmet_subsys_attr_version_store(struct config_item *item,
670                                                const char *page, size_t count)
671 {
672         struct nvmet_subsys *subsys = to_subsys(item);
673         int major, minor, tertiary = 0;
674         int ret;
675
676
677         ret = sscanf(page, "%d.%d.%d\n", &major, &minor, &tertiary);
678         if (ret != 2 && ret != 3)
679                 return -EINVAL;
680
681         down_write(&nvmet_config_sem);
682         subsys->ver = NVME_VS(major, minor, tertiary);
683         up_write(&nvmet_config_sem);
684
685         return count;
686 }
687 CONFIGFS_ATTR(nvmet_subsys_, attr_version);
688
689 static ssize_t nvmet_subsys_attr_serial_show(struct config_item *item,
690                                              char *page)
691 {
692         struct nvmet_subsys *subsys = to_subsys(item);
693
694         return snprintf(page, PAGE_SIZE, "%llx\n", subsys->serial);
695 }
696
697 static ssize_t nvmet_subsys_attr_serial_store(struct config_item *item,
698                                               const char *page, size_t count)
699 {
700         struct nvmet_subsys *subsys = to_subsys(item);
701
702         down_write(&nvmet_config_sem);
703         sscanf(page, "%llx\n", &subsys->serial);
704         up_write(&nvmet_config_sem);
705
706         return count;
707 }
708 CONFIGFS_ATTR(nvmet_subsys_, attr_serial);
709
710 static struct configfs_attribute *nvmet_subsys_attrs[] = {
711         &nvmet_subsys_attr_attr_allow_any_host,
712         &nvmet_subsys_attr_attr_version,
713         &nvmet_subsys_attr_attr_serial,
714         NULL,
715 };
716
717 /*
718  * Subsystem structures & folder operation functions below
719  */
720 static void nvmet_subsys_release(struct config_item *item)
721 {
722         struct nvmet_subsys *subsys = to_subsys(item);
723
724         nvmet_subsys_del_ctrls(subsys);
725         nvmet_subsys_put(subsys);
726 }
727
728 static struct configfs_item_operations nvmet_subsys_item_ops = {
729         .release                = nvmet_subsys_release,
730 };
731
732 static struct config_item_type nvmet_subsys_type = {
733         .ct_item_ops            = &nvmet_subsys_item_ops,
734         .ct_attrs               = nvmet_subsys_attrs,
735         .ct_owner               = THIS_MODULE,
736 };
737
738 static struct config_group *nvmet_subsys_make(struct config_group *group,
739                 const char *name)
740 {
741         struct nvmet_subsys *subsys;
742
743         if (sysfs_streq(name, NVME_DISC_SUBSYS_NAME)) {
744                 pr_err("can't create discovery subsystem through configfs\n");
745                 return ERR_PTR(-EINVAL);
746         }
747
748         subsys = nvmet_subsys_alloc(name, NVME_NQN_NVME);
749         if (!subsys)
750                 return ERR_PTR(-ENOMEM);
751
752         config_group_init_type_name(&subsys->group, name, &nvmet_subsys_type);
753
754         config_group_init_type_name(&subsys->namespaces_group,
755                         "namespaces", &nvmet_namespaces_type);
756         configfs_add_default_group(&subsys->namespaces_group, &subsys->group);
757
758         config_group_init_type_name(&subsys->allowed_hosts_group,
759                         "allowed_hosts", &nvmet_allowed_hosts_type);
760         configfs_add_default_group(&subsys->allowed_hosts_group,
761                         &subsys->group);
762
763         return &subsys->group;
764 }
765
766 static struct configfs_group_operations nvmet_subsystems_group_ops = {
767         .make_group             = nvmet_subsys_make,
768 };
769
770 static struct config_item_type nvmet_subsystems_type = {
771         .ct_group_ops           = &nvmet_subsystems_group_ops,
772         .ct_owner               = THIS_MODULE,
773 };
774
775 static ssize_t nvmet_referral_enable_show(struct config_item *item,
776                 char *page)
777 {
778         return snprintf(page, PAGE_SIZE, "%d\n", to_nvmet_port(item)->enabled);
779 }
780
781 static ssize_t nvmet_referral_enable_store(struct config_item *item,
782                 const char *page, size_t count)
783 {
784         struct nvmet_port *parent = to_nvmet_port(item->ci_parent->ci_parent);
785         struct nvmet_port *port = to_nvmet_port(item);
786         bool enable;
787
788         if (strtobool(page, &enable))
789                 goto inval;
790
791         if (enable)
792                 nvmet_referral_enable(parent, port);
793         else
794                 nvmet_referral_disable(port);
795
796         return count;
797 inval:
798         pr_err("Invalid value '%s' for enable\n", page);
799         return -EINVAL;
800 }
801
802 CONFIGFS_ATTR(nvmet_referral_, enable);
803
804 /*
805  * Discovery Service subsystem definitions
806  */
807 static struct configfs_attribute *nvmet_referral_attrs[] = {
808         &nvmet_attr_addr_adrfam,
809         &nvmet_attr_addr_portid,
810         &nvmet_attr_addr_treq,
811         &nvmet_attr_addr_traddr,
812         &nvmet_attr_addr_trsvcid,
813         &nvmet_attr_addr_trtype,
814         &nvmet_referral_attr_enable,
815         NULL,
816 };
817
818 static void nvmet_referral_release(struct config_item *item)
819 {
820         struct nvmet_port *port = to_nvmet_port(item);
821
822         nvmet_referral_disable(port);
823         kfree(port);
824 }
825
826 static struct configfs_item_operations nvmet_referral_item_ops = {
827         .release        = nvmet_referral_release,
828 };
829
830 static struct config_item_type nvmet_referral_type = {
831         .ct_owner       = THIS_MODULE,
832         .ct_attrs       = nvmet_referral_attrs,
833         .ct_item_ops    = &nvmet_referral_item_ops,
834 };
835
836 static struct config_group *nvmet_referral_make(
837                 struct config_group *group, const char *name)
838 {
839         struct nvmet_port *port;
840
841         port = kzalloc(sizeof(*port), GFP_KERNEL);
842         if (!port)
843                 return ERR_PTR(-ENOMEM);
844
845         INIT_LIST_HEAD(&port->entry);
846         config_group_init_type_name(&port->group, name, &nvmet_referral_type);
847
848         return &port->group;
849 }
850
851 static struct configfs_group_operations nvmet_referral_group_ops = {
852         .make_group             = nvmet_referral_make,
853 };
854
855 static struct config_item_type nvmet_referrals_type = {
856         .ct_owner       = THIS_MODULE,
857         .ct_group_ops   = &nvmet_referral_group_ops,
858 };
859
860 /*
861  * Ports definitions.
862  */
863 static void nvmet_port_release(struct config_item *item)
864 {
865         struct nvmet_port *port = to_nvmet_port(item);
866
867         kfree(port);
868 }
869
870 static struct configfs_attribute *nvmet_port_attrs[] = {
871         &nvmet_attr_addr_adrfam,
872         &nvmet_attr_addr_treq,
873         &nvmet_attr_addr_traddr,
874         &nvmet_attr_addr_trsvcid,
875         &nvmet_attr_addr_trtype,
876         NULL,
877 };
878
879 static struct configfs_item_operations nvmet_port_item_ops = {
880         .release                = nvmet_port_release,
881 };
882
883 static struct config_item_type nvmet_port_type = {
884         .ct_attrs               = nvmet_port_attrs,
885         .ct_item_ops            = &nvmet_port_item_ops,
886         .ct_owner               = THIS_MODULE,
887 };
888
889 static struct config_group *nvmet_ports_make(struct config_group *group,
890                 const char *name)
891 {
892         struct nvmet_port *port;
893         u16 portid;
894
895         if (kstrtou16(name, 0, &portid))
896                 return ERR_PTR(-EINVAL);
897
898         port = kzalloc(sizeof(*port), GFP_KERNEL);
899         if (!port)
900                 return ERR_PTR(-ENOMEM);
901
902         INIT_LIST_HEAD(&port->entry);
903         INIT_LIST_HEAD(&port->subsystems);
904         INIT_LIST_HEAD(&port->referrals);
905
906         port->disc_addr.portid = cpu_to_le16(portid);
907         config_group_init_type_name(&port->group, name, &nvmet_port_type);
908
909         config_group_init_type_name(&port->subsys_group,
910                         "subsystems", &nvmet_port_subsys_type);
911         configfs_add_default_group(&port->subsys_group, &port->group);
912
913         config_group_init_type_name(&port->referrals_group,
914                         "referrals", &nvmet_referrals_type);
915         configfs_add_default_group(&port->referrals_group, &port->group);
916
917         return &port->group;
918 }
919
920 static struct configfs_group_operations nvmet_ports_group_ops = {
921         .make_group             = nvmet_ports_make,
922 };
923
924 static struct config_item_type nvmet_ports_type = {
925         .ct_group_ops           = &nvmet_ports_group_ops,
926         .ct_owner               = THIS_MODULE,
927 };
928
929 static struct config_group nvmet_subsystems_group;
930 static struct config_group nvmet_ports_group;
931
932 static void nvmet_host_release(struct config_item *item)
933 {
934         struct nvmet_host *host = to_host(item);
935
936         kfree(host);
937 }
938
939 static struct configfs_item_operations nvmet_host_item_ops = {
940         .release                = nvmet_host_release,
941 };
942
943 static struct config_item_type nvmet_host_type = {
944         .ct_item_ops            = &nvmet_host_item_ops,
945         .ct_owner               = THIS_MODULE,
946 };
947
948 static struct config_group *nvmet_hosts_make_group(struct config_group *group,
949                 const char *name)
950 {
951         struct nvmet_host *host;
952
953         host = kzalloc(sizeof(*host), GFP_KERNEL);
954         if (!host)
955                 return ERR_PTR(-ENOMEM);
956
957         config_group_init_type_name(&host->group, name, &nvmet_host_type);
958
959         return &host->group;
960 }
961
962 static struct configfs_group_operations nvmet_hosts_group_ops = {
963         .make_group             = nvmet_hosts_make_group,
964 };
965
966 static struct config_item_type nvmet_hosts_type = {
967         .ct_group_ops           = &nvmet_hosts_group_ops,
968         .ct_owner               = THIS_MODULE,
969 };
970
971 static struct config_group nvmet_hosts_group;
972
973 static struct config_item_type nvmet_root_type = {
974         .ct_owner               = THIS_MODULE,
975 };
976
977 static struct configfs_subsystem nvmet_configfs_subsystem = {
978         .su_group = {
979                 .cg_item = {
980                         .ci_namebuf     = "nvmet",
981                         .ci_type        = &nvmet_root_type,
982                 },
983         },
984 };
985
986 int __init nvmet_init_configfs(void)
987 {
988         int ret;
989
990         config_group_init(&nvmet_configfs_subsystem.su_group);
991         mutex_init(&nvmet_configfs_subsystem.su_mutex);
992
993         config_group_init_type_name(&nvmet_subsystems_group,
994                         "subsystems", &nvmet_subsystems_type);
995         configfs_add_default_group(&nvmet_subsystems_group,
996                         &nvmet_configfs_subsystem.su_group);
997
998         config_group_init_type_name(&nvmet_ports_group,
999                         "ports", &nvmet_ports_type);
1000         configfs_add_default_group(&nvmet_ports_group,
1001                         &nvmet_configfs_subsystem.su_group);
1002
1003         config_group_init_type_name(&nvmet_hosts_group,
1004                         "hosts", &nvmet_hosts_type);
1005         configfs_add_default_group(&nvmet_hosts_group,
1006                         &nvmet_configfs_subsystem.su_group);
1007
1008         ret = configfs_register_subsystem(&nvmet_configfs_subsystem);
1009         if (ret) {
1010                 pr_err("configfs_register_subsystem: %d\n", ret);
1011                 return ret;
1012         }
1013
1014         return 0;
1015 }
1016
1017 void __exit nvmet_exit_configfs(void)
1018 {
1019         configfs_unregister_subsystem(&nvmet_configfs_subsystem);
1020 }