linux/drivers/nvme/target/configfs.c
<<
>>
Prefs
   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
  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        case NVMF_ADDR_FAMILY_FC:
  41                return sprintf(page, "fc\n");
  42        default:
  43                return sprintf(page, "\n");
  44        }
  45}
  46
  47static 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
  74CONFIGFS_ATTR(nvmet_, addr_adrfam);
  75
  76static 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
  85static 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
 105CONFIGFS_ATTR(nvmet_, addr_portid);
 106
 107static 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
 116static 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
 135CONFIGFS_ATTR(nvmet_, addr_traddr);
 136
 137static 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
 152static 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
 177CONFIGFS_ATTR(nvmet_, addr_treq);
 178
 179static 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
 188static 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
 206CONFIGFS_ATTR(nvmet_, addr_trsvcid);
 207
 208static 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
 223static 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
 232static 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
 238static 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
 244static 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
 269CONFIGFS_ATTR(nvmet_, addr_trtype);
 270
 271/*
 272 * Namespace structures & file operation functions below
 273 */
 274static 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
 279static 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
 301out_unlock:
 302        mutex_unlock(&subsys->lock);
 303        return ret;
 304}
 305
 306CONFIGFS_ATTR(nvmet_ns_, device_path);
 307
 308static 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
 313static 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
 331out_unlock:
 332        mutex_unlock(&subsys->lock);
 333        return ret ? ret : count;
 334}
 335
 336static 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
 341CONFIGFS_ATTR(nvmet_ns_, device_uuid);
 342
 343static 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));
 377out_unlock:
 378        mutex_unlock(&subsys->lock);
 379        return ret ? ret : count;
 380}
 381
 382CONFIGFS_ATTR(nvmet_ns_, device_nguid);
 383
 384static 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
 389static 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
 407CONFIGFS_ATTR(nvmet_ns_, enable);
 408
 409static 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
 417static 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
 424static struct configfs_item_operations nvmet_ns_item_ops = {
 425        .release                = nvmet_ns_release,
 426};
 427
 428static 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
 434static 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 == NVME_NSID_ALL)
 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;
 459out:
 460        return ERR_PTR(ret);
 461}
 462
 463static struct configfs_group_operations nvmet_namespaces_group_ops = {
 464        .make_group             = nvmet_ns_make,
 465};
 466
 467static struct config_item_type nvmet_namespaces_type = {
 468        .ct_group_ops           = &nvmet_namespaces_group_ops,
 469        .ct_owner               = THIS_MODULE,
 470};
 471
 472static 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
 508out_free_link:
 509        up_write(&nvmet_config_sem);
 510        kfree(link);
 511        return ret;
 512}
 513
 514static 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
 529found:
 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
 538static 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
 543static struct config_item_type nvmet_port_subsys_type = {
 544        .ct_item_ops            = &nvmet_port_subsys_item_ops,
 545        .ct_owner               = THIS_MODULE,
 546};
 547
 548static 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;
 583out_free_link:
 584        up_write(&nvmet_config_sem);
 585        kfree(link);
 586        return ret;
 587}
 588
 589static 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
 604found:
 605        list_del(&p->entry);
 606        nvmet_genctr++;
 607        up_write(&nvmet_config_sem);
 608        kfree(p);
 609}
 610
 611static 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
 616static struct config_item_type nvmet_allowed_hosts_type = {
 617        .ct_item_ops            = &nvmet_allowed_hosts_item_ops,
 618        .ct_owner               = THIS_MODULE,
 619};
 620
 621static 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
 628static 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;
 646out_unlock:
 647        up_write(&nvmet_config_sem);
 648        return ret ? ret : count;
 649}
 650
 651CONFIGFS_ATTR(nvmet_subsys_, attr_allow_any_host);
 652
 653static 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
 669static 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}
 687CONFIGFS_ATTR(nvmet_subsys_, attr_version);
 688
 689static 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
 697static 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}
 708CONFIGFS_ATTR(nvmet_subsys_, attr_serial);
 709
 710static 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 */
 720static 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
 728static struct configfs_item_operations nvmet_subsys_item_ops = {
 729        .release                = nvmet_subsys_release,
 730};
 731
 732static 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
 738static 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
 766static struct configfs_group_operations nvmet_subsystems_group_ops = {
 767        .make_group             = nvmet_subsys_make,
 768};
 769
 770static struct config_item_type nvmet_subsystems_type = {
 771        .ct_group_ops           = &nvmet_subsystems_group_ops,
 772        .ct_owner               = THIS_MODULE,
 773};
 774
 775static 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
 781static 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;
 797inval:
 798        pr_err("Invalid value '%s' for enable\n", page);
 799        return -EINVAL;
 800}
 801
 802CONFIGFS_ATTR(nvmet_referral_, enable);
 803
 804/*
 805 * Discovery Service subsystem definitions
 806 */
 807static 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
 818static 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
 826static struct configfs_item_operations nvmet_referral_item_ops = {
 827        .release        = nvmet_referral_release,
 828};
 829
 830static 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
 836static 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
 851static struct configfs_group_operations nvmet_referral_group_ops = {
 852        .make_group             = nvmet_referral_make,
 853};
 854
 855static 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 */
 863static void nvmet_port_release(struct config_item *item)
 864{
 865        struct nvmet_port *port = to_nvmet_port(item);
 866
 867        kfree(port);
 868}
 869
 870static 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
 879static struct configfs_item_operations nvmet_port_item_ops = {
 880        .release                = nvmet_port_release,
 881};
 882
 883static 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
 889static 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
 920static struct configfs_group_operations nvmet_ports_group_ops = {
 921        .make_group             = nvmet_ports_make,
 922};
 923
 924static struct config_item_type nvmet_ports_type = {
 925        .ct_group_ops           = &nvmet_ports_group_ops,
 926        .ct_owner               = THIS_MODULE,
 927};
 928
 929static struct config_group nvmet_subsystems_group;
 930static struct config_group nvmet_ports_group;
 931
 932static void nvmet_host_release(struct config_item *item)
 933{
 934        struct nvmet_host *host = to_host(item);
 935
 936        kfree(host);
 937}
 938
 939static struct configfs_item_operations nvmet_host_item_ops = {
 940        .release                = nvmet_host_release,
 941};
 942
 943static struct config_item_type nvmet_host_type = {
 944        .ct_item_ops            = &nvmet_host_item_ops,
 945        .ct_owner               = THIS_MODULE,
 946};
 947
 948static 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
 962static struct configfs_group_operations nvmet_hosts_group_ops = {
 963        .make_group             = nvmet_hosts_make_group,
 964};
 965
 966static struct config_item_type nvmet_hosts_type = {
 967        .ct_group_ops           = &nvmet_hosts_group_ops,
 968        .ct_owner               = THIS_MODULE,
 969};
 970
 971static struct config_group nvmet_hosts_group;
 972
 973static struct config_item_type nvmet_root_type = {
 974        .ct_owner               = THIS_MODULE,
 975};
 976
 977static 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
 986int __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
1017void __exit nvmet_exit_configfs(void)
1018{
1019        configfs_unregister_subsystem(&nvmet_configfs_subsystem);
1020}
1021