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