blob: a780e2dbc940d4fc58639fe869a02375ffe4d186 [file] [log] [blame]
Christoph Hellwiga07b4972016-06-21 18:04:20 +02001/*
2 * Configfs interface for the NVMe target.
3 * Copyright (c) 2015-2016 HGST, a Western Digital Company.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 */
14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/slab.h>
18#include <linux/stat.h>
19#include <linux/ctype.h>
20
21#include "nvmet.h"
22
23static struct config_item_type nvmet_host_type;
24static struct config_item_type nvmet_subsys_type;
25
26/*
27 * nvmet_port Generic ConfigFS definitions.
28 * Used in any place in the ConfigFS tree that refers to an address.
29 */
30static ssize_t nvmet_addr_adrfam_show(struct config_item *item,
31 char *page)
32{
33 switch (to_nvmet_port(item)->disc_addr.adrfam) {
34 case NVMF_ADDR_FAMILY_IP4:
35 return sprintf(page, "ipv4\n");
36 case NVMF_ADDR_FAMILY_IP6:
37 return sprintf(page, "ipv6\n");
38 case NVMF_ADDR_FAMILY_IB:
39 return sprintf(page, "ib\n");
40 default:
41 return sprintf(page, "\n");
42 }
43}
44
45static 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
70CONFIGFS_ATTR(nvmet_, addr_adrfam);
71
72static 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
81static 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
101CONFIGFS_ATTR(nvmet_, addr_portid);
102
103static 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
112static 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
131CONFIGFS_ATTR(nvmet_, addr_traddr);
132
133static 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
148static 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
173CONFIGFS_ATTR(nvmet_, addr_treq);
174
175static 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
184static 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
202CONFIGFS_ATTR(nvmet_, addr_trsvcid);
203
204static 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
217static 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
226static 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
232static 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
255CONFIGFS_ATTR(nvmet_, addr_trtype);
256
257/*
258 * Namespace structures & file operation functions below
259 */
260static 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
265static ssize_t nvmet_ns_device_path_store(struct config_item *item,
266 const char *page, size_t count)
267{
268 struct nvmet_ns *ns = to_nvmet_ns(item);
269 struct nvmet_subsys *subsys = ns->subsys;
270 int ret;
271
272 mutex_lock(&subsys->lock);
273 ret = -EBUSY;
274 if (nvmet_ns_enabled(ns))
275 goto out_unlock;
276
277 kfree(ns->device_path);
278
279 ret = -ENOMEM;
280 ns->device_path = kstrdup(page, GFP_KERNEL);
281 if (!ns->device_path)
282 goto out_unlock;
283
284 mutex_unlock(&subsys->lock);
285 return count;
286
287out_unlock:
288 mutex_unlock(&subsys->lock);
289 return ret;
290}
291
292CONFIGFS_ATTR(nvmet_ns_, device_path);
293
294static 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
299static ssize_t nvmet_ns_device_nguid_store(struct config_item *item,
300 const char *page, size_t count)
301{
302 struct nvmet_ns *ns = to_nvmet_ns(item);
303 struct nvmet_subsys *subsys = ns->subsys;
304 u8 nguid[16];
305 const char *p = page;
306 int i;
307 int ret = 0;
308
309 mutex_lock(&subsys->lock);
310 if (nvmet_ns_enabled(ns)) {
311 ret = -EBUSY;
312 goto out_unlock;
313 }
314
315 for (i = 0; i < 16; i++) {
316 if (p + 2 > page + count) {
317 ret = -EINVAL;
318 goto out_unlock;
319 }
320 if (!isxdigit(p[0]) || !isxdigit(p[1])) {
321 ret = -EINVAL;
322 goto out_unlock;
323 }
324
325 nguid[i] = (hex_to_bin(p[0]) << 4) | hex_to_bin(p[1]);
326 p += 2;
327
328 if (*p == '-' || *p == ':')
329 p++;
330 }
331
332 memcpy(&ns->nguid, nguid, sizeof(nguid));
333out_unlock:
334 mutex_unlock(&subsys->lock);
335 return ret ? ret : count;
336}
337
338CONFIGFS_ATTR(nvmet_ns_, device_nguid);
339
340static ssize_t nvmet_ns_enable_show(struct config_item *item, char *page)
341{
342 return sprintf(page, "%d\n", nvmet_ns_enabled(to_nvmet_ns(item)));
343}
344
345static 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
363CONFIGFS_ATTR(nvmet_ns_, enable);
364
365static 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
372static 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
379static struct configfs_item_operations nvmet_ns_item_ops = {
380 .release = nvmet_ns_release,
381};
382
383static 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
389static 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;
414out:
415 return ERR_PTR(ret);
416}
417
418static struct configfs_group_operations nvmet_namespaces_group_ops = {
419 .make_group = nvmet_ns_make,
420};
421
422static struct config_item_type nvmet_namespaces_type = {
423 .ct_group_ops = &nvmet_namespaces_group_ops,
424 .ct_owner = THIS_MODULE,
425};
426
427static 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
463out_free_link:
464 up_write(&nvmet_config_sem);
465 kfree(link);
466 return ret;
467}
468
Andrzej Pietrasiewicze16769d2016-11-28 13:22:42 +0100469static void nvmet_port_subsys_drop_link(struct config_item *parent,
Christoph Hellwiga07b4972016-06-21 18:04:20 +0200470 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);
Andrzej Pietrasiewicze16769d2016-11-28 13:22:42 +0100482 return;
Christoph Hellwiga07b4972016-06-21 18:04:20 +0200483
484found:
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);
Christoph Hellwiga07b4972016-06-21 18:04:20 +0200491}
492
493static struct configfs_item_operations nvmet_port_subsys_item_ops = {
494 .allow_link = nvmet_port_subsys_allow_link,
495 .drop_link = nvmet_port_subsys_drop_link,
496};
497
498static struct config_item_type nvmet_port_subsys_type = {
499 .ct_item_ops = &nvmet_port_subsys_item_ops,
500 .ct_owner = THIS_MODULE,
501};
502
503static int nvmet_allowed_hosts_allow_link(struct config_item *parent,
504 struct config_item *target)
505{
506 struct nvmet_subsys *subsys = to_subsys(parent->ci_parent);
507 struct nvmet_host *host;
508 struct nvmet_host_link *link, *p;
509 int ret;
510
511 if (target->ci_type != &nvmet_host_type) {
512 pr_err("can only link hosts into the allowed_hosts directory!\n");
513 return -EINVAL;
514 }
515
516 host = to_host(target);
517 link = kmalloc(sizeof(*link), GFP_KERNEL);
518 if (!link)
519 return -ENOMEM;
520 link->host = host;
521
522 down_write(&nvmet_config_sem);
523 ret = -EINVAL;
524 if (subsys->allow_any_host) {
525 pr_err("can't add hosts when allow_any_host is set!\n");
526 goto out_free_link;
527 }
528
529 ret = -EEXIST;
530 list_for_each_entry(p, &subsys->hosts, entry) {
531 if (!strcmp(nvmet_host_name(p->host), nvmet_host_name(host)))
532 goto out_free_link;
533 }
534 list_add_tail(&link->entry, &subsys->hosts);
535 nvmet_genctr++;
536 up_write(&nvmet_config_sem);
537 return 0;
538out_free_link:
539 up_write(&nvmet_config_sem);
540 kfree(link);
541 return ret;
542}
543
Andrzej Pietrasiewicze16769d2016-11-28 13:22:42 +0100544static void nvmet_allowed_hosts_drop_link(struct config_item *parent,
Christoph Hellwiga07b4972016-06-21 18:04:20 +0200545 struct config_item *target)
546{
547 struct nvmet_subsys *subsys = to_subsys(parent->ci_parent);
548 struct nvmet_host *host = to_host(target);
549 struct nvmet_host_link *p;
550
551 down_write(&nvmet_config_sem);
552 list_for_each_entry(p, &subsys->hosts, entry) {
553 if (!strcmp(nvmet_host_name(p->host), nvmet_host_name(host)))
554 goto found;
555 }
556 up_write(&nvmet_config_sem);
Andrzej Pietrasiewicze16769d2016-11-28 13:22:42 +0100557 return;
Christoph Hellwiga07b4972016-06-21 18:04:20 +0200558
559found:
560 list_del(&p->entry);
561 nvmet_genctr++;
562 up_write(&nvmet_config_sem);
563 kfree(p);
Christoph Hellwiga07b4972016-06-21 18:04:20 +0200564}
565
566static struct configfs_item_operations nvmet_allowed_hosts_item_ops = {
567 .allow_link = nvmet_allowed_hosts_allow_link,
568 .drop_link = nvmet_allowed_hosts_drop_link,
569};
570
571static struct config_item_type nvmet_allowed_hosts_type = {
572 .ct_item_ops = &nvmet_allowed_hosts_item_ops,
573 .ct_owner = THIS_MODULE,
574};
575
576static ssize_t nvmet_subsys_attr_allow_any_host_show(struct config_item *item,
577 char *page)
578{
579 return snprintf(page, PAGE_SIZE, "%d\n",
580 to_subsys(item)->allow_any_host);
581}
582
583static ssize_t nvmet_subsys_attr_allow_any_host_store(struct config_item *item,
584 const char *page, size_t count)
585{
586 struct nvmet_subsys *subsys = to_subsys(item);
587 bool allow_any_host;
588 int ret = 0;
589
590 if (strtobool(page, &allow_any_host))
591 return -EINVAL;
592
593 down_write(&nvmet_config_sem);
594 if (allow_any_host && !list_empty(&subsys->hosts)) {
595 pr_err("Can't set allow_any_host when explicit hosts are set!\n");
596 ret = -EINVAL;
597 goto out_unlock;
598 }
599
600 subsys->allow_any_host = allow_any_host;
601out_unlock:
602 up_write(&nvmet_config_sem);
603 return ret ? ret : count;
604}
605
606CONFIGFS_ATTR(nvmet_subsys_, attr_allow_any_host);
607
608static struct configfs_attribute *nvmet_subsys_attrs[] = {
609 &nvmet_subsys_attr_attr_allow_any_host,
610 NULL,
611};
612
613/*
614 * Subsystem structures & folder operation functions below
615 */
616static void nvmet_subsys_release(struct config_item *item)
617{
618 struct nvmet_subsys *subsys = to_subsys(item);
619
620 nvmet_subsys_put(subsys);
621}
622
623static struct configfs_item_operations nvmet_subsys_item_ops = {
624 .release = nvmet_subsys_release,
625};
626
627static struct config_item_type nvmet_subsys_type = {
628 .ct_item_ops = &nvmet_subsys_item_ops,
629 .ct_attrs = nvmet_subsys_attrs,
630 .ct_owner = THIS_MODULE,
631};
632
633static struct config_group *nvmet_subsys_make(struct config_group *group,
634 const char *name)
635{
636 struct nvmet_subsys *subsys;
637
638 if (sysfs_streq(name, NVME_DISC_SUBSYS_NAME)) {
639 pr_err("can't create discovery subsystem through configfs\n");
640 return ERR_PTR(-EINVAL);
641 }
642
643 subsys = nvmet_subsys_alloc(name, NVME_NQN_NVME);
644 if (!subsys)
645 return ERR_PTR(-ENOMEM);
646
647 config_group_init_type_name(&subsys->group, name, &nvmet_subsys_type);
648
649 config_group_init_type_name(&subsys->namespaces_group,
650 "namespaces", &nvmet_namespaces_type);
651 configfs_add_default_group(&subsys->namespaces_group, &subsys->group);
652
653 config_group_init_type_name(&subsys->allowed_hosts_group,
654 "allowed_hosts", &nvmet_allowed_hosts_type);
655 configfs_add_default_group(&subsys->allowed_hosts_group,
656 &subsys->group);
657
658 return &subsys->group;
659}
660
661static struct configfs_group_operations nvmet_subsystems_group_ops = {
662 .make_group = nvmet_subsys_make,
663};
664
665static struct config_item_type nvmet_subsystems_type = {
666 .ct_group_ops = &nvmet_subsystems_group_ops,
667 .ct_owner = THIS_MODULE,
668};
669
670static ssize_t nvmet_referral_enable_show(struct config_item *item,
671 char *page)
672{
673 return snprintf(page, PAGE_SIZE, "%d\n", to_nvmet_port(item)->enabled);
674}
675
676static ssize_t nvmet_referral_enable_store(struct config_item *item,
677 const char *page, size_t count)
678{
679 struct nvmet_port *parent = to_nvmet_port(item->ci_parent->ci_parent);
680 struct nvmet_port *port = to_nvmet_port(item);
681 bool enable;
682
683 if (strtobool(page, &enable))
684 goto inval;
685
686 if (enable)
687 nvmet_referral_enable(parent, port);
688 else
689 nvmet_referral_disable(port);
690
691 return count;
692inval:
693 pr_err("Invalid value '%s' for enable\n", page);
694 return -EINVAL;
695}
696
697CONFIGFS_ATTR(nvmet_referral_, enable);
698
699/*
700 * Discovery Service subsystem definitions
701 */
702static struct configfs_attribute *nvmet_referral_attrs[] = {
703 &nvmet_attr_addr_adrfam,
704 &nvmet_attr_addr_portid,
705 &nvmet_attr_addr_treq,
706 &nvmet_attr_addr_traddr,
707 &nvmet_attr_addr_trsvcid,
708 &nvmet_attr_addr_trtype,
709 &nvmet_referral_attr_enable,
710 NULL,
711};
712
713static void nvmet_referral_release(struct config_item *item)
714{
715 struct nvmet_port *port = to_nvmet_port(item);
716
717 nvmet_referral_disable(port);
718 kfree(port);
719}
720
721static struct configfs_item_operations nvmet_referral_item_ops = {
722 .release = nvmet_referral_release,
723};
724
725static struct config_item_type nvmet_referral_type = {
726 .ct_owner = THIS_MODULE,
727 .ct_attrs = nvmet_referral_attrs,
728 .ct_item_ops = &nvmet_referral_item_ops,
729};
730
731static struct config_group *nvmet_referral_make(
732 struct config_group *group, const char *name)
733{
734 struct nvmet_port *port;
735
736 port = kzalloc(sizeof(*port), GFP_KERNEL);
737 if (!port)
Dan Carpenterf98d9ca2016-07-07 11:15:26 +0300738 return ERR_PTR(-ENOMEM);
Christoph Hellwiga07b4972016-06-21 18:04:20 +0200739
740 INIT_LIST_HEAD(&port->entry);
741 config_group_init_type_name(&port->group, name, &nvmet_referral_type);
742
743 return &port->group;
744}
745
746static struct configfs_group_operations nvmet_referral_group_ops = {
747 .make_group = nvmet_referral_make,
748};
749
750static struct config_item_type nvmet_referrals_type = {
751 .ct_owner = THIS_MODULE,
752 .ct_group_ops = &nvmet_referral_group_ops,
753};
754
755/*
756 * Ports definitions.
757 */
758static void nvmet_port_release(struct config_item *item)
759{
760 struct nvmet_port *port = to_nvmet_port(item);
761
762 kfree(port);
763}
764
765static struct configfs_attribute *nvmet_port_attrs[] = {
766 &nvmet_attr_addr_adrfam,
767 &nvmet_attr_addr_treq,
768 &nvmet_attr_addr_traddr,
769 &nvmet_attr_addr_trsvcid,
770 &nvmet_attr_addr_trtype,
771 NULL,
772};
773
774static struct configfs_item_operations nvmet_port_item_ops = {
775 .release = nvmet_port_release,
776};
777
778static struct config_item_type nvmet_port_type = {
779 .ct_attrs = nvmet_port_attrs,
780 .ct_item_ops = &nvmet_port_item_ops,
781 .ct_owner = THIS_MODULE,
782};
783
784static struct config_group *nvmet_ports_make(struct config_group *group,
785 const char *name)
786{
787 struct nvmet_port *port;
788 u16 portid;
789
790 if (kstrtou16(name, 0, &portid))
791 return ERR_PTR(-EINVAL);
792
793 port = kzalloc(sizeof(*port), GFP_KERNEL);
794 if (!port)
Dan Carpenterf98d9ca2016-07-07 11:15:26 +0300795 return ERR_PTR(-ENOMEM);
Christoph Hellwiga07b4972016-06-21 18:04:20 +0200796
797 INIT_LIST_HEAD(&port->entry);
798 INIT_LIST_HEAD(&port->subsystems);
799 INIT_LIST_HEAD(&port->referrals);
800
801 port->disc_addr.portid = cpu_to_le16(portid);
802 config_group_init_type_name(&port->group, name, &nvmet_port_type);
803
804 config_group_init_type_name(&port->subsys_group,
805 "subsystems", &nvmet_port_subsys_type);
806 configfs_add_default_group(&port->subsys_group, &port->group);
807
808 config_group_init_type_name(&port->referrals_group,
809 "referrals", &nvmet_referrals_type);
810 configfs_add_default_group(&port->referrals_group, &port->group);
811
812 return &port->group;
813}
814
815static struct configfs_group_operations nvmet_ports_group_ops = {
816 .make_group = nvmet_ports_make,
817};
818
819static struct config_item_type nvmet_ports_type = {
820 .ct_group_ops = &nvmet_ports_group_ops,
821 .ct_owner = THIS_MODULE,
822};
823
824static struct config_group nvmet_subsystems_group;
825static struct config_group nvmet_ports_group;
826
827static void nvmet_host_release(struct config_item *item)
828{
829 struct nvmet_host *host = to_host(item);
830
831 kfree(host);
832}
833
834static struct configfs_item_operations nvmet_host_item_ops = {
835 .release = nvmet_host_release,
836};
837
838static struct config_item_type nvmet_host_type = {
839 .ct_item_ops = &nvmet_host_item_ops,
840 .ct_owner = THIS_MODULE,
841};
842
843static struct config_group *nvmet_hosts_make_group(struct config_group *group,
844 const char *name)
845{
846 struct nvmet_host *host;
847
848 host = kzalloc(sizeof(*host), GFP_KERNEL);
849 if (!host)
850 return ERR_PTR(-ENOMEM);
851
852 config_group_init_type_name(&host->group, name, &nvmet_host_type);
853
854 return &host->group;
855}
856
857static struct configfs_group_operations nvmet_hosts_group_ops = {
858 .make_group = nvmet_hosts_make_group,
859};
860
861static struct config_item_type nvmet_hosts_type = {
862 .ct_group_ops = &nvmet_hosts_group_ops,
863 .ct_owner = THIS_MODULE,
864};
865
866static struct config_group nvmet_hosts_group;
867
868static struct config_item_type nvmet_root_type = {
869 .ct_owner = THIS_MODULE,
870};
871
872static struct configfs_subsystem nvmet_configfs_subsystem = {
873 .su_group = {
874 .cg_item = {
875 .ci_namebuf = "nvmet",
876 .ci_type = &nvmet_root_type,
877 },
878 },
879};
880
881int __init nvmet_init_configfs(void)
882{
883 int ret;
884
885 config_group_init(&nvmet_configfs_subsystem.su_group);
886 mutex_init(&nvmet_configfs_subsystem.su_mutex);
887
888 config_group_init_type_name(&nvmet_subsystems_group,
889 "subsystems", &nvmet_subsystems_type);
890 configfs_add_default_group(&nvmet_subsystems_group,
891 &nvmet_configfs_subsystem.su_group);
892
893 config_group_init_type_name(&nvmet_ports_group,
894 "ports", &nvmet_ports_type);
895 configfs_add_default_group(&nvmet_ports_group,
896 &nvmet_configfs_subsystem.su_group);
897
898 config_group_init_type_name(&nvmet_hosts_group,
899 "hosts", &nvmet_hosts_type);
900 configfs_add_default_group(&nvmet_hosts_group,
901 &nvmet_configfs_subsystem.su_group);
902
903 ret = configfs_register_subsystem(&nvmet_configfs_subsystem);
904 if (ret) {
905 pr_err("configfs_register_subsystem: %d\n", ret);
906 return ret;
907 }
908
909 return 0;
910}
911
912void __exit nvmet_exit_configfs(void)
913{
914 configfs_unregister_subsystem(&nvmet_configfs_subsystem);
915}