2 * Configfs interface for the NVMe target.
3 * Copyright (c) 2015-2016 HGST, a Western Digital Company.
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.
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
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>
23 static struct config_item_type nvmet_host_type;
24 static struct config_item_type nvmet_subsys_type;
27 * nvmet_port Generic ConfigFS definitions.
28 * Used in any place in the ConfigFS tree that refers to an address.
30 static ssize_t nvmet_addr_adrfam_show(struct config_item *item,
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");
41 return sprintf(page, "\n");
45 static ssize_t nvmet_addr_adrfam_store(struct config_item *item,
46 const char *page, size_t count)
48 struct nvmet_port *port = to_nvmet_port(item);
51 pr_err("Cannot modify address while enabled\n");
52 pr_err("Disable the address before modifying\n");
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;
63 pr_err("Invalid value '%s' for adrfam\n", page);
70 CONFIGFS_ATTR(nvmet_, addr_adrfam);
72 static ssize_t nvmet_addr_portid_show(struct config_item *item,
75 struct nvmet_port *port = to_nvmet_port(item);
77 return snprintf(page, PAGE_SIZE, "%d\n",
78 le16_to_cpu(port->disc_addr.portid));
81 static ssize_t nvmet_addr_portid_store(struct config_item *item,
82 const char *page, size_t count)
84 struct nvmet_port *port = to_nvmet_port(item);
87 if (kstrtou16(page, 0, &portid)) {
88 pr_err("Invalid value '%s' for portid\n", page);
93 pr_err("Cannot modify address while enabled\n");
94 pr_err("Disable the address before modifying\n");
97 port->disc_addr.portid = cpu_to_le16(portid);
101 CONFIGFS_ATTR(nvmet_, addr_portid);
103 static ssize_t nvmet_addr_traddr_show(struct config_item *item,
106 struct nvmet_port *port = to_nvmet_port(item);
108 return snprintf(page, PAGE_SIZE, "%s\n",
109 port->disc_addr.traddr);
112 static ssize_t nvmet_addr_traddr_store(struct config_item *item,
113 const char *page, size_t count)
115 struct nvmet_port *port = to_nvmet_port(item);
117 if (count > NVMF_TRADDR_SIZE) {
118 pr_err("Invalid value '%s' for traddr\n", page);
123 pr_err("Cannot modify address while enabled\n");
124 pr_err("Disable the address before modifying\n");
127 return snprintf(port->disc_addr.traddr,
128 sizeof(port->disc_addr.traddr), "%s", page);
131 CONFIGFS_ATTR(nvmet_, addr_traddr);
133 static ssize_t nvmet_addr_treq_show(struct config_item *item,
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");
144 return sprintf(page, "\n");
148 static ssize_t nvmet_addr_treq_store(struct config_item *item,
149 const char *page, size_t count)
151 struct nvmet_port *port = to_nvmet_port(item);
154 pr_err("Cannot modify address while enabled\n");
155 pr_err("Disable the address before modifying\n");
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;
166 pr_err("Invalid value '%s' for treq\n", page);
173 CONFIGFS_ATTR(nvmet_, addr_treq);
175 static ssize_t nvmet_addr_trsvcid_show(struct config_item *item,
178 struct nvmet_port *port = to_nvmet_port(item);
180 return snprintf(page, PAGE_SIZE, "%s\n",
181 port->disc_addr.trsvcid);
184 static ssize_t nvmet_addr_trsvcid_store(struct config_item *item,
185 const char *page, size_t count)
187 struct nvmet_port *port = to_nvmet_port(item);
189 if (count > NVMF_TRSVCID_SIZE) {
190 pr_err("Invalid value '%s' for trsvcid\n", page);
194 pr_err("Cannot modify address while enabled\n");
195 pr_err("Disable the address before modifying\n");
198 return snprintf(port->disc_addr.trsvcid,
199 sizeof(port->disc_addr.trsvcid), "%s", page);
202 CONFIGFS_ATTR(nvmet_, addr_trsvcid);
204 static ssize_t nvmet_addr_trtype_show(struct config_item *item,
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");
213 return sprintf(page, "\n");
217 static void nvmet_port_init_tsas_rdma(struct nvmet_port *port)
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;
226 static void nvmet_port_init_tsas_loop(struct nvmet_port *port)
228 port->disc_addr.trtype = NVMF_TRTYPE_LOOP;
229 memset(&port->disc_addr.tsas, 0, NVMF_TSAS_SIZE);
232 static ssize_t nvmet_addr_trtype_store(struct config_item *item,
233 const char *page, size_t count)
235 struct nvmet_port *port = to_nvmet_port(item);
238 pr_err("Cannot modify address while enabled\n");
239 pr_err("Disable the address before modifying\n");
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);
248 pr_err("Invalid value '%s' for trtype\n", page);
255 CONFIGFS_ATTR(nvmet_, addr_trtype);
258 * Namespace structures & file operation functions below
260 static ssize_t nvmet_ns_device_path_show(struct config_item *item, char *page)
262 return sprintf(page, "%s\n", to_nvmet_ns(item)->device_path);
265 static ssize_t nvmet_ns_device_path_store(struct config_item *item,
266 const char *page, size_t count)
268 struct nvmet_ns *ns = to_nvmet_ns(item);
269 struct nvmet_subsys *subsys = ns->subsys;
272 mutex_lock(&subsys->lock);
277 kfree(ns->device_path);
280 ns->device_path = kstrdup(page, GFP_KERNEL);
281 if (!ns->device_path)
284 mutex_unlock(&subsys->lock);
288 mutex_unlock(&subsys->lock);
292 CONFIGFS_ATTR(nvmet_ns_, device_path);
294 static ssize_t nvmet_ns_device_nguid_show(struct config_item *item, char *page)
296 return sprintf(page, "%pUb\n", &to_nvmet_ns(item)->nguid);
299 static ssize_t nvmet_ns_device_nguid_store(struct config_item *item,
300 const char *page, size_t count)
302 struct nvmet_ns *ns = to_nvmet_ns(item);
303 struct nvmet_subsys *subsys = ns->subsys;
305 const char *p = page;
309 mutex_lock(&subsys->lock);
315 for (i = 0; i < 16; i++) {
316 if (p + 2 > page + count) {
320 if (!isxdigit(p[0]) || !isxdigit(p[1])) {
325 nguid[i] = (hex_to_bin(p[0]) << 4) | hex_to_bin(p[1]);
328 if (*p == '-' || *p == ':')
332 memcpy(&ns->nguid, nguid, sizeof(nguid));
334 mutex_unlock(&subsys->lock);
335 return ret ? ret : count;
338 CONFIGFS_ATTR(nvmet_ns_, device_nguid);
340 static ssize_t nvmet_ns_enable_show(struct config_item *item, char *page)
342 return sprintf(page, "%d\n", to_nvmet_ns(item)->enabled);
345 static ssize_t nvmet_ns_enable_store(struct config_item *item,
346 const char *page, size_t count)
348 struct nvmet_ns *ns = to_nvmet_ns(item);
352 if (strtobool(page, &enable))
356 ret = nvmet_ns_enable(ns);
358 nvmet_ns_disable(ns);
360 return ret ? ret : count;
363 CONFIGFS_ATTR(nvmet_ns_, enable);
365 static struct configfs_attribute *nvmet_ns_attrs[] = {
366 &nvmet_ns_attr_device_path,
367 &nvmet_ns_attr_device_nguid,
368 &nvmet_ns_attr_enable,
372 static void nvmet_ns_release(struct config_item *item)
374 struct nvmet_ns *ns = to_nvmet_ns(item);
379 static struct configfs_item_operations nvmet_ns_item_ops = {
380 .release = nvmet_ns_release,
383 static struct config_item_type nvmet_ns_type = {
384 .ct_item_ops = &nvmet_ns_item_ops,
385 .ct_attrs = nvmet_ns_attrs,
386 .ct_owner = THIS_MODULE,
389 static struct config_group *nvmet_ns_make(struct config_group *group,
392 struct nvmet_subsys *subsys = namespaces_to_subsys(&group->cg_item);
397 ret = kstrtou32(name, 0, &nsid);
402 if (nsid == 0 || nsid == 0xffffffff)
406 ns = nvmet_ns_alloc(subsys, nsid);
409 config_group_init_type_name(&ns->group, name, &nvmet_ns_type);
411 pr_info("adding nsid %d to subsystem %s\n", nsid, subsys->subsysnqn);
418 static struct configfs_group_operations nvmet_namespaces_group_ops = {
419 .make_group = nvmet_ns_make,
422 static struct config_item_type nvmet_namespaces_type = {
423 .ct_group_ops = &nvmet_namespaces_group_ops,
424 .ct_owner = THIS_MODULE,
427 static int nvmet_port_subsys_allow_link(struct config_item *parent,
428 struct config_item *target)
430 struct nvmet_port *port = to_nvmet_port(parent->ci_parent);
431 struct nvmet_subsys *subsys;
432 struct nvmet_subsys_link *link, *p;
435 if (target->ci_type != &nvmet_subsys_type) {
436 pr_err("can only link subsystems into the subsystems dir.!\n");
439 subsys = to_subsys(target);
440 link = kmalloc(sizeof(*link), GFP_KERNEL);
443 link->subsys = subsys;
445 down_write(&nvmet_config_sem);
447 list_for_each_entry(p, &port->subsystems, entry) {
448 if (p->subsys == subsys)
452 if (list_empty(&port->subsystems)) {
453 ret = nvmet_enable_port(port);
458 list_add_tail(&link->entry, &port->subsystems);
460 up_write(&nvmet_config_sem);
464 up_write(&nvmet_config_sem);
469 static int nvmet_port_subsys_drop_link(struct config_item *parent,
470 struct config_item *target)
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;
476 down_write(&nvmet_config_sem);
477 list_for_each_entry(p, &port->subsystems, entry) {
478 if (p->subsys == subsys)
481 up_write(&nvmet_config_sem);
487 if (list_empty(&port->subsystems))
488 nvmet_disable_port(port);
489 up_write(&nvmet_config_sem);
494 static struct configfs_item_operations nvmet_port_subsys_item_ops = {
495 .allow_link = nvmet_port_subsys_allow_link,
496 .drop_link = nvmet_port_subsys_drop_link,
499 static struct config_item_type nvmet_port_subsys_type = {
500 .ct_item_ops = &nvmet_port_subsys_item_ops,
501 .ct_owner = THIS_MODULE,
504 static int nvmet_allowed_hosts_allow_link(struct config_item *parent,
505 struct config_item *target)
507 struct nvmet_subsys *subsys = to_subsys(parent->ci_parent);
508 struct nvmet_host *host;
509 struct nvmet_host_link *link, *p;
512 if (target->ci_type != &nvmet_host_type) {
513 pr_err("can only link hosts into the allowed_hosts directory!\n");
517 host = to_host(target);
518 link = kmalloc(sizeof(*link), GFP_KERNEL);
523 down_write(&nvmet_config_sem);
525 if (subsys->allow_any_host) {
526 pr_err("can't add hosts when allow_any_host is set!\n");
531 list_for_each_entry(p, &subsys->hosts, entry) {
532 if (!strcmp(nvmet_host_name(p->host), nvmet_host_name(host)))
535 list_add_tail(&link->entry, &subsys->hosts);
537 up_write(&nvmet_config_sem);
540 up_write(&nvmet_config_sem);
545 static int nvmet_allowed_hosts_drop_link(struct config_item *parent,
546 struct config_item *target)
548 struct nvmet_subsys *subsys = to_subsys(parent->ci_parent);
549 struct nvmet_host *host = to_host(target);
550 struct nvmet_host_link *p;
552 down_write(&nvmet_config_sem);
553 list_for_each_entry(p, &subsys->hosts, entry) {
554 if (!strcmp(nvmet_host_name(p->host), nvmet_host_name(host)))
557 up_write(&nvmet_config_sem);
563 up_write(&nvmet_config_sem);
568 static struct configfs_item_operations nvmet_allowed_hosts_item_ops = {
569 .allow_link = nvmet_allowed_hosts_allow_link,
570 .drop_link = nvmet_allowed_hosts_drop_link,
573 static struct config_item_type nvmet_allowed_hosts_type = {
574 .ct_item_ops = &nvmet_allowed_hosts_item_ops,
575 .ct_owner = THIS_MODULE,
578 static ssize_t nvmet_subsys_attr_allow_any_host_show(struct config_item *item,
581 return snprintf(page, PAGE_SIZE, "%d\n",
582 to_subsys(item)->allow_any_host);
585 static ssize_t nvmet_subsys_attr_allow_any_host_store(struct config_item *item,
586 const char *page, size_t count)
588 struct nvmet_subsys *subsys = to_subsys(item);
592 if (strtobool(page, &allow_any_host))
595 down_write(&nvmet_config_sem);
596 if (allow_any_host && !list_empty(&subsys->hosts)) {
597 pr_err("Can't set allow_any_host when explicit hosts are set!\n");
602 subsys->allow_any_host = allow_any_host;
604 up_write(&nvmet_config_sem);
605 return ret ? ret : count;
608 CONFIGFS_ATTR(nvmet_subsys_, attr_allow_any_host);
610 static struct configfs_attribute *nvmet_subsys_attrs[] = {
611 &nvmet_subsys_attr_attr_allow_any_host,
616 * Subsystem structures & folder operation functions below
618 static void nvmet_subsys_release(struct config_item *item)
620 struct nvmet_subsys *subsys = to_subsys(item);
622 nvmet_subsys_put(subsys);
625 static struct configfs_item_operations nvmet_subsys_item_ops = {
626 .release = nvmet_subsys_release,
629 static struct config_item_type nvmet_subsys_type = {
630 .ct_item_ops = &nvmet_subsys_item_ops,
631 .ct_attrs = nvmet_subsys_attrs,
632 .ct_owner = THIS_MODULE,
635 static struct config_group *nvmet_subsys_make(struct config_group *group,
638 struct nvmet_subsys *subsys;
640 if (sysfs_streq(name, NVME_DISC_SUBSYS_NAME)) {
641 pr_err("can't create discovery subsystem through configfs\n");
642 return ERR_PTR(-EINVAL);
645 subsys = nvmet_subsys_alloc(name, NVME_NQN_NVME);
647 return ERR_PTR(-ENOMEM);
649 config_group_init_type_name(&subsys->group, name, &nvmet_subsys_type);
651 config_group_init_type_name(&subsys->namespaces_group,
652 "namespaces", &nvmet_namespaces_type);
653 configfs_add_default_group(&subsys->namespaces_group, &subsys->group);
655 config_group_init_type_name(&subsys->allowed_hosts_group,
656 "allowed_hosts", &nvmet_allowed_hosts_type);
657 configfs_add_default_group(&subsys->allowed_hosts_group,
660 return &subsys->group;
663 static struct configfs_group_operations nvmet_subsystems_group_ops = {
664 .make_group = nvmet_subsys_make,
667 static struct config_item_type nvmet_subsystems_type = {
668 .ct_group_ops = &nvmet_subsystems_group_ops,
669 .ct_owner = THIS_MODULE,
672 static ssize_t nvmet_referral_enable_show(struct config_item *item,
675 return snprintf(page, PAGE_SIZE, "%d\n", to_nvmet_port(item)->enabled);
678 static ssize_t nvmet_referral_enable_store(struct config_item *item,
679 const char *page, size_t count)
681 struct nvmet_port *parent = to_nvmet_port(item->ci_parent->ci_parent);
682 struct nvmet_port *port = to_nvmet_port(item);
685 if (strtobool(page, &enable))
689 nvmet_referral_enable(parent, port);
691 nvmet_referral_disable(port);
695 pr_err("Invalid value '%s' for enable\n", page);
699 CONFIGFS_ATTR(nvmet_referral_, enable);
702 * Discovery Service subsystem definitions
704 static struct configfs_attribute *nvmet_referral_attrs[] = {
705 &nvmet_attr_addr_adrfam,
706 &nvmet_attr_addr_portid,
707 &nvmet_attr_addr_treq,
708 &nvmet_attr_addr_traddr,
709 &nvmet_attr_addr_trsvcid,
710 &nvmet_attr_addr_trtype,
711 &nvmet_referral_attr_enable,
715 static void nvmet_referral_release(struct config_item *item)
717 struct nvmet_port *port = to_nvmet_port(item);
719 nvmet_referral_disable(port);
723 static struct configfs_item_operations nvmet_referral_item_ops = {
724 .release = nvmet_referral_release,
727 static struct config_item_type nvmet_referral_type = {
728 .ct_owner = THIS_MODULE,
729 .ct_attrs = nvmet_referral_attrs,
730 .ct_item_ops = &nvmet_referral_item_ops,
733 static struct config_group *nvmet_referral_make(
734 struct config_group *group, const char *name)
736 struct nvmet_port *port;
738 port = kzalloc(sizeof(*port), GFP_KERNEL);
740 return ERR_PTR(-ENOMEM);
742 INIT_LIST_HEAD(&port->entry);
743 config_group_init_type_name(&port->group, name, &nvmet_referral_type);
748 static struct configfs_group_operations nvmet_referral_group_ops = {
749 .make_group = nvmet_referral_make,
752 static struct config_item_type nvmet_referrals_type = {
753 .ct_owner = THIS_MODULE,
754 .ct_group_ops = &nvmet_referral_group_ops,
760 static void nvmet_port_release(struct config_item *item)
762 struct nvmet_port *port = to_nvmet_port(item);
767 static struct configfs_attribute *nvmet_port_attrs[] = {
768 &nvmet_attr_addr_adrfam,
769 &nvmet_attr_addr_treq,
770 &nvmet_attr_addr_traddr,
771 &nvmet_attr_addr_trsvcid,
772 &nvmet_attr_addr_trtype,
776 static struct configfs_item_operations nvmet_port_item_ops = {
777 .release = nvmet_port_release,
780 static struct config_item_type nvmet_port_type = {
781 .ct_attrs = nvmet_port_attrs,
782 .ct_item_ops = &nvmet_port_item_ops,
783 .ct_owner = THIS_MODULE,
786 static struct config_group *nvmet_ports_make(struct config_group *group,
789 struct nvmet_port *port;
792 if (kstrtou16(name, 0, &portid))
793 return ERR_PTR(-EINVAL);
795 port = kzalloc(sizeof(*port), GFP_KERNEL);
797 return ERR_PTR(-ENOMEM);
799 INIT_LIST_HEAD(&port->entry);
800 INIT_LIST_HEAD(&port->subsystems);
801 INIT_LIST_HEAD(&port->referrals);
803 port->disc_addr.portid = cpu_to_le16(portid);
804 config_group_init_type_name(&port->group, name, &nvmet_port_type);
806 config_group_init_type_name(&port->subsys_group,
807 "subsystems", &nvmet_port_subsys_type);
808 configfs_add_default_group(&port->subsys_group, &port->group);
810 config_group_init_type_name(&port->referrals_group,
811 "referrals", &nvmet_referrals_type);
812 configfs_add_default_group(&port->referrals_group, &port->group);
817 static struct configfs_group_operations nvmet_ports_group_ops = {
818 .make_group = nvmet_ports_make,
821 static struct config_item_type nvmet_ports_type = {
822 .ct_group_ops = &nvmet_ports_group_ops,
823 .ct_owner = THIS_MODULE,
826 static struct config_group nvmet_subsystems_group;
827 static struct config_group nvmet_ports_group;
829 static void nvmet_host_release(struct config_item *item)
831 struct nvmet_host *host = to_host(item);
836 static struct configfs_item_operations nvmet_host_item_ops = {
837 .release = nvmet_host_release,
840 static struct config_item_type nvmet_host_type = {
841 .ct_item_ops = &nvmet_host_item_ops,
842 .ct_owner = THIS_MODULE,
845 static struct config_group *nvmet_hosts_make_group(struct config_group *group,
848 struct nvmet_host *host;
850 host = kzalloc(sizeof(*host), GFP_KERNEL);
852 return ERR_PTR(-ENOMEM);
854 config_group_init_type_name(&host->group, name, &nvmet_host_type);
859 static struct configfs_group_operations nvmet_hosts_group_ops = {
860 .make_group = nvmet_hosts_make_group,
863 static struct config_item_type nvmet_hosts_type = {
864 .ct_group_ops = &nvmet_hosts_group_ops,
865 .ct_owner = THIS_MODULE,
868 static struct config_group nvmet_hosts_group;
870 static struct config_item_type nvmet_root_type = {
871 .ct_owner = THIS_MODULE,
874 static struct configfs_subsystem nvmet_configfs_subsystem = {
877 .ci_namebuf = "nvmet",
878 .ci_type = &nvmet_root_type,
883 int __init nvmet_init_configfs(void)
887 config_group_init(&nvmet_configfs_subsystem.su_group);
888 mutex_init(&nvmet_configfs_subsystem.su_mutex);
890 config_group_init_type_name(&nvmet_subsystems_group,
891 "subsystems", &nvmet_subsystems_type);
892 configfs_add_default_group(&nvmet_subsystems_group,
893 &nvmet_configfs_subsystem.su_group);
895 config_group_init_type_name(&nvmet_ports_group,
896 "ports", &nvmet_ports_type);
897 configfs_add_default_group(&nvmet_ports_group,
898 &nvmet_configfs_subsystem.su_group);
900 config_group_init_type_name(&nvmet_hosts_group,
901 "hosts", &nvmet_hosts_type);
902 configfs_add_default_group(&nvmet_hosts_group,
903 &nvmet_configfs_subsystem.su_group);
905 ret = configfs_register_subsystem(&nvmet_configfs_subsystem);
907 pr_err("configfs_register_subsystem: %d\n", ret);
914 void __exit nvmet_exit_configfs(void)
916 configfs_unregister_subsystem(&nvmet_configfs_subsystem);