configfs.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929
  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. #include "nvmet.h"
  21. static struct config_item_type nvmet_host_type;
  22. static struct config_item_type nvmet_subsys_type;
  23. /*
  24. * nvmet_port Generic ConfigFS definitions.
  25. * Used in any place in the ConfigFS tree that refers to an address.
  26. */
  27. static ssize_t nvmet_addr_adrfam_show(struct config_item *item,
  28. char *page)
  29. {
  30. switch (to_nvmet_port(item)->disc_addr.adrfam) {
  31. case NVMF_ADDR_FAMILY_IP4:
  32. return sprintf(page, "ipv4\n");
  33. case NVMF_ADDR_FAMILY_IP6:
  34. return sprintf(page, "ipv6\n");
  35. case NVMF_ADDR_FAMILY_IB:
  36. return sprintf(page, "ib\n");
  37. case NVMF_ADDR_FAMILY_FC:
  38. return sprintf(page, "fc\n");
  39. default:
  40. return sprintf(page, "\n");
  41. }
  42. }
  43. static ssize_t nvmet_addr_adrfam_store(struct config_item *item,
  44. const char *page, size_t count)
  45. {
  46. struct nvmet_port *port = to_nvmet_port(item);
  47. if (port->enabled) {
  48. pr_err("Cannot modify address while enabled\n");
  49. pr_err("Disable the address before modifying\n");
  50. return -EACCES;
  51. }
  52. if (sysfs_streq(page, "ipv4")) {
  53. port->disc_addr.adrfam = NVMF_ADDR_FAMILY_IP4;
  54. } else if (sysfs_streq(page, "ipv6")) {
  55. port->disc_addr.adrfam = NVMF_ADDR_FAMILY_IP6;
  56. } else if (sysfs_streq(page, "ib")) {
  57. port->disc_addr.adrfam = NVMF_ADDR_FAMILY_IB;
  58. } else if (sysfs_streq(page, "fc")) {
  59. port->disc_addr.adrfam = NVMF_ADDR_FAMILY_FC;
  60. } else {
  61. pr_err("Invalid value '%s' for adrfam\n", page);
  62. return -EINVAL;
  63. }
  64. return count;
  65. }
  66. CONFIGFS_ATTR(nvmet_, addr_adrfam);
  67. static ssize_t nvmet_addr_portid_show(struct config_item *item,
  68. char *page)
  69. {
  70. struct nvmet_port *port = to_nvmet_port(item);
  71. return snprintf(page, PAGE_SIZE, "%d\n",
  72. le16_to_cpu(port->disc_addr.portid));
  73. }
  74. static ssize_t nvmet_addr_portid_store(struct config_item *item,
  75. const char *page, size_t count)
  76. {
  77. struct nvmet_port *port = to_nvmet_port(item);
  78. u16 portid = 0;
  79. if (kstrtou16(page, 0, &portid)) {
  80. pr_err("Invalid value '%s' for portid\n", page);
  81. return -EINVAL;
  82. }
  83. if (port->enabled) {
  84. pr_err("Cannot modify address while enabled\n");
  85. pr_err("Disable the address before modifying\n");
  86. return -EACCES;
  87. }
  88. port->disc_addr.portid = cpu_to_le16(portid);
  89. return count;
  90. }
  91. CONFIGFS_ATTR(nvmet_, addr_portid);
  92. static ssize_t nvmet_addr_traddr_show(struct config_item *item,
  93. char *page)
  94. {
  95. struct nvmet_port *port = to_nvmet_port(item);
  96. return snprintf(page, PAGE_SIZE, "%s\n",
  97. port->disc_addr.traddr);
  98. }
  99. static ssize_t nvmet_addr_traddr_store(struct config_item *item,
  100. const char *page, size_t count)
  101. {
  102. struct nvmet_port *port = to_nvmet_port(item);
  103. if (count > NVMF_TRADDR_SIZE) {
  104. pr_err("Invalid value '%s' for traddr\n", page);
  105. return -EINVAL;
  106. }
  107. if (port->enabled) {
  108. pr_err("Cannot modify address while enabled\n");
  109. pr_err("Disable the address before modifying\n");
  110. return -EACCES;
  111. }
  112. return snprintf(port->disc_addr.traddr,
  113. sizeof(port->disc_addr.traddr), "%s", page);
  114. }
  115. CONFIGFS_ATTR(nvmet_, addr_traddr);
  116. static ssize_t nvmet_addr_treq_show(struct config_item *item,
  117. char *page)
  118. {
  119. switch (to_nvmet_port(item)->disc_addr.treq) {
  120. case NVMF_TREQ_NOT_SPECIFIED:
  121. return sprintf(page, "not specified\n");
  122. case NVMF_TREQ_REQUIRED:
  123. return sprintf(page, "required\n");
  124. case NVMF_TREQ_NOT_REQUIRED:
  125. return sprintf(page, "not required\n");
  126. default:
  127. return sprintf(page, "\n");
  128. }
  129. }
  130. static ssize_t nvmet_addr_treq_store(struct config_item *item,
  131. const char *page, size_t count)
  132. {
  133. struct nvmet_port *port = to_nvmet_port(item);
  134. if (port->enabled) {
  135. pr_err("Cannot modify address while enabled\n");
  136. pr_err("Disable the address before modifying\n");
  137. return -EACCES;
  138. }
  139. if (sysfs_streq(page, "not specified")) {
  140. port->disc_addr.treq = NVMF_TREQ_NOT_SPECIFIED;
  141. } else if (sysfs_streq(page, "required")) {
  142. port->disc_addr.treq = NVMF_TREQ_REQUIRED;
  143. } else if (sysfs_streq(page, "not required")) {
  144. port->disc_addr.treq = NVMF_TREQ_NOT_REQUIRED;
  145. } else {
  146. pr_err("Invalid value '%s' for treq\n", page);
  147. return -EINVAL;
  148. }
  149. return count;
  150. }
  151. CONFIGFS_ATTR(nvmet_, addr_treq);
  152. static ssize_t nvmet_addr_trsvcid_show(struct config_item *item,
  153. char *page)
  154. {
  155. struct nvmet_port *port = to_nvmet_port(item);
  156. return snprintf(page, PAGE_SIZE, "%s\n",
  157. port->disc_addr.trsvcid);
  158. }
  159. static ssize_t nvmet_addr_trsvcid_store(struct config_item *item,
  160. const char *page, size_t count)
  161. {
  162. struct nvmet_port *port = to_nvmet_port(item);
  163. if (count > NVMF_TRSVCID_SIZE) {
  164. pr_err("Invalid value '%s' for trsvcid\n", page);
  165. return -EINVAL;
  166. }
  167. if (port->enabled) {
  168. pr_err("Cannot modify address while enabled\n");
  169. pr_err("Disable the address before modifying\n");
  170. return -EACCES;
  171. }
  172. return snprintf(port->disc_addr.trsvcid,
  173. sizeof(port->disc_addr.trsvcid), "%s", page);
  174. }
  175. CONFIGFS_ATTR(nvmet_, addr_trsvcid);
  176. static ssize_t nvmet_addr_trtype_show(struct config_item *item,
  177. char *page)
  178. {
  179. switch (to_nvmet_port(item)->disc_addr.trtype) {
  180. case NVMF_TRTYPE_RDMA:
  181. return sprintf(page, "rdma\n");
  182. case NVMF_TRTYPE_LOOP:
  183. return sprintf(page, "loop\n");
  184. case NVMF_TRTYPE_FC:
  185. return sprintf(page, "fc\n");
  186. default:
  187. return sprintf(page, "\n");
  188. }
  189. }
  190. static void nvmet_port_init_tsas_rdma(struct nvmet_port *port)
  191. {
  192. port->disc_addr.trtype = NVMF_TRTYPE_RDMA;
  193. memset(&port->disc_addr.tsas.rdma, 0, NVMF_TSAS_SIZE);
  194. port->disc_addr.tsas.rdma.qptype = NVMF_RDMA_QPTYPE_CONNECTED;
  195. port->disc_addr.tsas.rdma.prtype = NVMF_RDMA_PRTYPE_NOT_SPECIFIED;
  196. port->disc_addr.tsas.rdma.cms = NVMF_RDMA_CMS_RDMA_CM;
  197. }
  198. static void nvmet_port_init_tsas_loop(struct nvmet_port *port)
  199. {
  200. port->disc_addr.trtype = NVMF_TRTYPE_LOOP;
  201. memset(&port->disc_addr.tsas, 0, NVMF_TSAS_SIZE);
  202. }
  203. static void nvmet_port_init_tsas_fc(struct nvmet_port *port)
  204. {
  205. port->disc_addr.trtype = NVMF_TRTYPE_FC;
  206. memset(&port->disc_addr.tsas, 0, NVMF_TSAS_SIZE);
  207. }
  208. static ssize_t nvmet_addr_trtype_store(struct config_item *item,
  209. const char *page, size_t count)
  210. {
  211. struct nvmet_port *port = to_nvmet_port(item);
  212. if (port->enabled) {
  213. pr_err("Cannot modify address while enabled\n");
  214. pr_err("Disable the address before modifying\n");
  215. return -EACCES;
  216. }
  217. if (sysfs_streq(page, "rdma")) {
  218. nvmet_port_init_tsas_rdma(port);
  219. } else if (sysfs_streq(page, "loop")) {
  220. nvmet_port_init_tsas_loop(port);
  221. } else if (sysfs_streq(page, "fc")) {
  222. nvmet_port_init_tsas_fc(port);
  223. } else {
  224. pr_err("Invalid value '%s' for trtype\n", page);
  225. return -EINVAL;
  226. }
  227. return count;
  228. }
  229. CONFIGFS_ATTR(nvmet_, addr_trtype);
  230. /*
  231. * Namespace structures & file operation functions below
  232. */
  233. static ssize_t nvmet_ns_device_path_show(struct config_item *item, char *page)
  234. {
  235. return sprintf(page, "%s\n", to_nvmet_ns(item)->device_path);
  236. }
  237. static ssize_t nvmet_ns_device_path_store(struct config_item *item,
  238. const char *page, size_t count)
  239. {
  240. struct nvmet_ns *ns = to_nvmet_ns(item);
  241. struct nvmet_subsys *subsys = ns->subsys;
  242. int ret;
  243. mutex_lock(&subsys->lock);
  244. ret = -EBUSY;
  245. if (ns->enabled)
  246. goto out_unlock;
  247. kfree(ns->device_path);
  248. ret = -ENOMEM;
  249. ns->device_path = kstrdup(page, GFP_KERNEL);
  250. if (!ns->device_path)
  251. goto out_unlock;
  252. mutex_unlock(&subsys->lock);
  253. return count;
  254. out_unlock:
  255. mutex_unlock(&subsys->lock);
  256. return ret;
  257. }
  258. CONFIGFS_ATTR(nvmet_ns_, device_path);
  259. static ssize_t nvmet_ns_device_nguid_show(struct config_item *item, char *page)
  260. {
  261. return sprintf(page, "%pUb\n", &to_nvmet_ns(item)->nguid);
  262. }
  263. static ssize_t nvmet_ns_device_nguid_store(struct config_item *item,
  264. const char *page, size_t count)
  265. {
  266. struct nvmet_ns *ns = to_nvmet_ns(item);
  267. struct nvmet_subsys *subsys = ns->subsys;
  268. u8 nguid[16];
  269. const char *p = page;
  270. int i;
  271. int ret = 0;
  272. mutex_lock(&subsys->lock);
  273. if (ns->enabled) {
  274. ret = -EBUSY;
  275. goto out_unlock;
  276. }
  277. for (i = 0; i < 16; i++) {
  278. if (p + 2 > page + count) {
  279. ret = -EINVAL;
  280. goto out_unlock;
  281. }
  282. if (!isxdigit(p[0]) || !isxdigit(p[1])) {
  283. ret = -EINVAL;
  284. goto out_unlock;
  285. }
  286. nguid[i] = (hex_to_bin(p[0]) << 4) | hex_to_bin(p[1]);
  287. p += 2;
  288. if (*p == '-' || *p == ':')
  289. p++;
  290. }
  291. memcpy(&ns->nguid, nguid, sizeof(nguid));
  292. out_unlock:
  293. mutex_unlock(&subsys->lock);
  294. return ret ? ret : count;
  295. }
  296. CONFIGFS_ATTR(nvmet_ns_, device_nguid);
  297. static ssize_t nvmet_ns_enable_show(struct config_item *item, char *page)
  298. {
  299. return sprintf(page, "%d\n", to_nvmet_ns(item)->enabled);
  300. }
  301. static ssize_t nvmet_ns_enable_store(struct config_item *item,
  302. const char *page, size_t count)
  303. {
  304. struct nvmet_ns *ns = to_nvmet_ns(item);
  305. bool enable;
  306. int ret = 0;
  307. if (strtobool(page, &enable))
  308. return -EINVAL;
  309. if (enable)
  310. ret = nvmet_ns_enable(ns);
  311. else
  312. nvmet_ns_disable(ns);
  313. return ret ? ret : count;
  314. }
  315. CONFIGFS_ATTR(nvmet_ns_, enable);
  316. static struct configfs_attribute *nvmet_ns_attrs[] = {
  317. &nvmet_ns_attr_device_path,
  318. &nvmet_ns_attr_device_nguid,
  319. &nvmet_ns_attr_enable,
  320. NULL,
  321. };
  322. static void nvmet_ns_release(struct config_item *item)
  323. {
  324. struct nvmet_ns *ns = to_nvmet_ns(item);
  325. nvmet_ns_free(ns);
  326. }
  327. static struct configfs_item_operations nvmet_ns_item_ops = {
  328. .release = nvmet_ns_release,
  329. };
  330. static struct config_item_type nvmet_ns_type = {
  331. .ct_item_ops = &nvmet_ns_item_ops,
  332. .ct_attrs = nvmet_ns_attrs,
  333. .ct_owner = THIS_MODULE,
  334. };
  335. static struct config_group *nvmet_ns_make(struct config_group *group,
  336. const char *name)
  337. {
  338. struct nvmet_subsys *subsys = namespaces_to_subsys(&group->cg_item);
  339. struct nvmet_ns *ns;
  340. int ret;
  341. u32 nsid;
  342. ret = kstrtou32(name, 0, &nsid);
  343. if (ret)
  344. goto out;
  345. ret = -EINVAL;
  346. if (nsid == 0 || nsid == 0xffffffff)
  347. goto out;
  348. ret = -ENOMEM;
  349. ns = nvmet_ns_alloc(subsys, nsid);
  350. if (!ns)
  351. goto out;
  352. config_group_init_type_name(&ns->group, name, &nvmet_ns_type);
  353. pr_info("adding nsid %d to subsystem %s\n", nsid, subsys->subsysnqn);
  354. return &ns->group;
  355. out:
  356. return ERR_PTR(ret);
  357. }
  358. static struct configfs_group_operations nvmet_namespaces_group_ops = {
  359. .make_group = nvmet_ns_make,
  360. };
  361. static struct config_item_type nvmet_namespaces_type = {
  362. .ct_group_ops = &nvmet_namespaces_group_ops,
  363. .ct_owner = THIS_MODULE,
  364. };
  365. static int nvmet_port_subsys_allow_link(struct config_item *parent,
  366. struct config_item *target)
  367. {
  368. struct nvmet_port *port = to_nvmet_port(parent->ci_parent);
  369. struct nvmet_subsys *subsys;
  370. struct nvmet_subsys_link *link, *p;
  371. int ret;
  372. if (target->ci_type != &nvmet_subsys_type) {
  373. pr_err("can only link subsystems into the subsystems dir.!\n");
  374. return -EINVAL;
  375. }
  376. subsys = to_subsys(target);
  377. link = kmalloc(sizeof(*link), GFP_KERNEL);
  378. if (!link)
  379. return -ENOMEM;
  380. link->subsys = subsys;
  381. down_write(&nvmet_config_sem);
  382. ret = -EEXIST;
  383. list_for_each_entry(p, &port->subsystems, entry) {
  384. if (p->subsys == subsys)
  385. goto out_free_link;
  386. }
  387. if (list_empty(&port->subsystems)) {
  388. ret = nvmet_enable_port(port);
  389. if (ret)
  390. goto out_free_link;
  391. }
  392. list_add_tail(&link->entry, &port->subsystems);
  393. nvmet_genctr++;
  394. up_write(&nvmet_config_sem);
  395. return 0;
  396. out_free_link:
  397. up_write(&nvmet_config_sem);
  398. kfree(link);
  399. return ret;
  400. }
  401. static void nvmet_port_subsys_drop_link(struct config_item *parent,
  402. struct config_item *target)
  403. {
  404. struct nvmet_port *port = to_nvmet_port(parent->ci_parent);
  405. struct nvmet_subsys *subsys = to_subsys(target);
  406. struct nvmet_subsys_link *p;
  407. down_write(&nvmet_config_sem);
  408. list_for_each_entry(p, &port->subsystems, entry) {
  409. if (p->subsys == subsys)
  410. goto found;
  411. }
  412. up_write(&nvmet_config_sem);
  413. return;
  414. found:
  415. list_del(&p->entry);
  416. nvmet_genctr++;
  417. if (list_empty(&port->subsystems))
  418. nvmet_disable_port(port);
  419. up_write(&nvmet_config_sem);
  420. kfree(p);
  421. }
  422. static struct configfs_item_operations nvmet_port_subsys_item_ops = {
  423. .allow_link = nvmet_port_subsys_allow_link,
  424. .drop_link = nvmet_port_subsys_drop_link,
  425. };
  426. static struct config_item_type nvmet_port_subsys_type = {
  427. .ct_item_ops = &nvmet_port_subsys_item_ops,
  428. .ct_owner = THIS_MODULE,
  429. };
  430. static int nvmet_allowed_hosts_allow_link(struct config_item *parent,
  431. struct config_item *target)
  432. {
  433. struct nvmet_subsys *subsys = to_subsys(parent->ci_parent);
  434. struct nvmet_host *host;
  435. struct nvmet_host_link *link, *p;
  436. int ret;
  437. if (target->ci_type != &nvmet_host_type) {
  438. pr_err("can only link hosts into the allowed_hosts directory!\n");
  439. return -EINVAL;
  440. }
  441. host = to_host(target);
  442. link = kmalloc(sizeof(*link), GFP_KERNEL);
  443. if (!link)
  444. return -ENOMEM;
  445. link->host = host;
  446. down_write(&nvmet_config_sem);
  447. ret = -EINVAL;
  448. if (subsys->allow_any_host) {
  449. pr_err("can't add hosts when allow_any_host is set!\n");
  450. goto out_free_link;
  451. }
  452. ret = -EEXIST;
  453. list_for_each_entry(p, &subsys->hosts, entry) {
  454. if (!strcmp(nvmet_host_name(p->host), nvmet_host_name(host)))
  455. goto out_free_link;
  456. }
  457. list_add_tail(&link->entry, &subsys->hosts);
  458. nvmet_genctr++;
  459. up_write(&nvmet_config_sem);
  460. return 0;
  461. out_free_link:
  462. up_write(&nvmet_config_sem);
  463. kfree(link);
  464. return ret;
  465. }
  466. static void nvmet_allowed_hosts_drop_link(struct config_item *parent,
  467. struct config_item *target)
  468. {
  469. struct nvmet_subsys *subsys = to_subsys(parent->ci_parent);
  470. struct nvmet_host *host = to_host(target);
  471. struct nvmet_host_link *p;
  472. down_write(&nvmet_config_sem);
  473. list_for_each_entry(p, &subsys->hosts, entry) {
  474. if (!strcmp(nvmet_host_name(p->host), nvmet_host_name(host)))
  475. goto found;
  476. }
  477. up_write(&nvmet_config_sem);
  478. return;
  479. found:
  480. list_del(&p->entry);
  481. nvmet_genctr++;
  482. up_write(&nvmet_config_sem);
  483. kfree(p);
  484. }
  485. static struct configfs_item_operations nvmet_allowed_hosts_item_ops = {
  486. .allow_link = nvmet_allowed_hosts_allow_link,
  487. .drop_link = nvmet_allowed_hosts_drop_link,
  488. };
  489. static struct config_item_type nvmet_allowed_hosts_type = {
  490. .ct_item_ops = &nvmet_allowed_hosts_item_ops,
  491. .ct_owner = THIS_MODULE,
  492. };
  493. static ssize_t nvmet_subsys_attr_allow_any_host_show(struct config_item *item,
  494. char *page)
  495. {
  496. return snprintf(page, PAGE_SIZE, "%d\n",
  497. to_subsys(item)->allow_any_host);
  498. }
  499. static ssize_t nvmet_subsys_attr_allow_any_host_store(struct config_item *item,
  500. const char *page, size_t count)
  501. {
  502. struct nvmet_subsys *subsys = to_subsys(item);
  503. bool allow_any_host;
  504. int ret = 0;
  505. if (strtobool(page, &allow_any_host))
  506. return -EINVAL;
  507. down_write(&nvmet_config_sem);
  508. if (allow_any_host && !list_empty(&subsys->hosts)) {
  509. pr_err("Can't set allow_any_host when explicit hosts are set!\n");
  510. ret = -EINVAL;
  511. goto out_unlock;
  512. }
  513. subsys->allow_any_host = allow_any_host;
  514. out_unlock:
  515. up_write(&nvmet_config_sem);
  516. return ret ? ret : count;
  517. }
  518. CONFIGFS_ATTR(nvmet_subsys_, attr_allow_any_host);
  519. static struct configfs_attribute *nvmet_subsys_attrs[] = {
  520. &nvmet_subsys_attr_attr_allow_any_host,
  521. NULL,
  522. };
  523. /*
  524. * Subsystem structures & folder operation functions below
  525. */
  526. static void nvmet_subsys_release(struct config_item *item)
  527. {
  528. struct nvmet_subsys *subsys = to_subsys(item);
  529. nvmet_subsys_put(subsys);
  530. }
  531. static struct configfs_item_operations nvmet_subsys_item_ops = {
  532. .release = nvmet_subsys_release,
  533. };
  534. static struct config_item_type nvmet_subsys_type = {
  535. .ct_item_ops = &nvmet_subsys_item_ops,
  536. .ct_attrs = nvmet_subsys_attrs,
  537. .ct_owner = THIS_MODULE,
  538. };
  539. static struct config_group *nvmet_subsys_make(struct config_group *group,
  540. const char *name)
  541. {
  542. struct nvmet_subsys *subsys;
  543. if (sysfs_streq(name, NVME_DISC_SUBSYS_NAME)) {
  544. pr_err("can't create discovery subsystem through configfs\n");
  545. return ERR_PTR(-EINVAL);
  546. }
  547. subsys = nvmet_subsys_alloc(name, NVME_NQN_NVME);
  548. if (!subsys)
  549. return ERR_PTR(-ENOMEM);
  550. config_group_init_type_name(&subsys->group, name, &nvmet_subsys_type);
  551. config_group_init_type_name(&subsys->namespaces_group,
  552. "namespaces", &nvmet_namespaces_type);
  553. configfs_add_default_group(&subsys->namespaces_group, &subsys->group);
  554. config_group_init_type_name(&subsys->allowed_hosts_group,
  555. "allowed_hosts", &nvmet_allowed_hosts_type);
  556. configfs_add_default_group(&subsys->allowed_hosts_group,
  557. &subsys->group);
  558. return &subsys->group;
  559. }
  560. static struct configfs_group_operations nvmet_subsystems_group_ops = {
  561. .make_group = nvmet_subsys_make,
  562. };
  563. static struct config_item_type nvmet_subsystems_type = {
  564. .ct_group_ops = &nvmet_subsystems_group_ops,
  565. .ct_owner = THIS_MODULE,
  566. };
  567. static ssize_t nvmet_referral_enable_show(struct config_item *item,
  568. char *page)
  569. {
  570. return snprintf(page, PAGE_SIZE, "%d\n", to_nvmet_port(item)->enabled);
  571. }
  572. static ssize_t nvmet_referral_enable_store(struct config_item *item,
  573. const char *page, size_t count)
  574. {
  575. struct nvmet_port *parent = to_nvmet_port(item->ci_parent->ci_parent);
  576. struct nvmet_port *port = to_nvmet_port(item);
  577. bool enable;
  578. if (strtobool(page, &enable))
  579. goto inval;
  580. if (enable)
  581. nvmet_referral_enable(parent, port);
  582. else
  583. nvmet_referral_disable(port);
  584. return count;
  585. inval:
  586. pr_err("Invalid value '%s' for enable\n", page);
  587. return -EINVAL;
  588. }
  589. CONFIGFS_ATTR(nvmet_referral_, enable);
  590. /*
  591. * Discovery Service subsystem definitions
  592. */
  593. static struct configfs_attribute *nvmet_referral_attrs[] = {
  594. &nvmet_attr_addr_adrfam,
  595. &nvmet_attr_addr_portid,
  596. &nvmet_attr_addr_treq,
  597. &nvmet_attr_addr_traddr,
  598. &nvmet_attr_addr_trsvcid,
  599. &nvmet_attr_addr_trtype,
  600. &nvmet_referral_attr_enable,
  601. NULL,
  602. };
  603. static void nvmet_referral_release(struct config_item *item)
  604. {
  605. struct nvmet_port *port = to_nvmet_port(item);
  606. nvmet_referral_disable(port);
  607. kfree(port);
  608. }
  609. static struct configfs_item_operations nvmet_referral_item_ops = {
  610. .release = nvmet_referral_release,
  611. };
  612. static struct config_item_type nvmet_referral_type = {
  613. .ct_owner = THIS_MODULE,
  614. .ct_attrs = nvmet_referral_attrs,
  615. .ct_item_ops = &nvmet_referral_item_ops,
  616. };
  617. static struct config_group *nvmet_referral_make(
  618. struct config_group *group, const char *name)
  619. {
  620. struct nvmet_port *port;
  621. port = kzalloc(sizeof(*port), GFP_KERNEL);
  622. if (!port)
  623. return ERR_PTR(-ENOMEM);
  624. INIT_LIST_HEAD(&port->entry);
  625. config_group_init_type_name(&port->group, name, &nvmet_referral_type);
  626. return &port->group;
  627. }
  628. static struct configfs_group_operations nvmet_referral_group_ops = {
  629. .make_group = nvmet_referral_make,
  630. };
  631. static struct config_item_type nvmet_referrals_type = {
  632. .ct_owner = THIS_MODULE,
  633. .ct_group_ops = &nvmet_referral_group_ops,
  634. };
  635. /*
  636. * Ports definitions.
  637. */
  638. static void nvmet_port_release(struct config_item *item)
  639. {
  640. struct nvmet_port *port = to_nvmet_port(item);
  641. kfree(port);
  642. }
  643. static struct configfs_attribute *nvmet_port_attrs[] = {
  644. &nvmet_attr_addr_adrfam,
  645. &nvmet_attr_addr_treq,
  646. &nvmet_attr_addr_traddr,
  647. &nvmet_attr_addr_trsvcid,
  648. &nvmet_attr_addr_trtype,
  649. NULL,
  650. };
  651. static struct configfs_item_operations nvmet_port_item_ops = {
  652. .release = nvmet_port_release,
  653. };
  654. static struct config_item_type nvmet_port_type = {
  655. .ct_attrs = nvmet_port_attrs,
  656. .ct_item_ops = &nvmet_port_item_ops,
  657. .ct_owner = THIS_MODULE,
  658. };
  659. static struct config_group *nvmet_ports_make(struct config_group *group,
  660. const char *name)
  661. {
  662. struct nvmet_port *port;
  663. u16 portid;
  664. if (kstrtou16(name, 0, &portid))
  665. return ERR_PTR(-EINVAL);
  666. port = kzalloc(sizeof(*port), GFP_KERNEL);
  667. if (!port)
  668. return ERR_PTR(-ENOMEM);
  669. INIT_LIST_HEAD(&port->entry);
  670. INIT_LIST_HEAD(&port->subsystems);
  671. INIT_LIST_HEAD(&port->referrals);
  672. port->disc_addr.portid = cpu_to_le16(portid);
  673. config_group_init_type_name(&port->group, name, &nvmet_port_type);
  674. config_group_init_type_name(&port->subsys_group,
  675. "subsystems", &nvmet_port_subsys_type);
  676. configfs_add_default_group(&port->subsys_group, &port->group);
  677. config_group_init_type_name(&port->referrals_group,
  678. "referrals", &nvmet_referrals_type);
  679. configfs_add_default_group(&port->referrals_group, &port->group);
  680. return &port->group;
  681. }
  682. static struct configfs_group_operations nvmet_ports_group_ops = {
  683. .make_group = nvmet_ports_make,
  684. };
  685. static struct config_item_type nvmet_ports_type = {
  686. .ct_group_ops = &nvmet_ports_group_ops,
  687. .ct_owner = THIS_MODULE,
  688. };
  689. static struct config_group nvmet_subsystems_group;
  690. static struct config_group nvmet_ports_group;
  691. static void nvmet_host_release(struct config_item *item)
  692. {
  693. struct nvmet_host *host = to_host(item);
  694. kfree(host);
  695. }
  696. static struct configfs_item_operations nvmet_host_item_ops = {
  697. .release = nvmet_host_release,
  698. };
  699. static struct config_item_type nvmet_host_type = {
  700. .ct_item_ops = &nvmet_host_item_ops,
  701. .ct_owner = THIS_MODULE,
  702. };
  703. static struct config_group *nvmet_hosts_make_group(struct config_group *group,
  704. const char *name)
  705. {
  706. struct nvmet_host *host;
  707. host = kzalloc(sizeof(*host), GFP_KERNEL);
  708. if (!host)
  709. return ERR_PTR(-ENOMEM);
  710. config_group_init_type_name(&host->group, name, &nvmet_host_type);
  711. return &host->group;
  712. }
  713. static struct configfs_group_operations nvmet_hosts_group_ops = {
  714. .make_group = nvmet_hosts_make_group,
  715. };
  716. static struct config_item_type nvmet_hosts_type = {
  717. .ct_group_ops = &nvmet_hosts_group_ops,
  718. .ct_owner = THIS_MODULE,
  719. };
  720. static struct config_group nvmet_hosts_group;
  721. static struct config_item_type nvmet_root_type = {
  722. .ct_owner = THIS_MODULE,
  723. };
  724. static struct configfs_subsystem nvmet_configfs_subsystem = {
  725. .su_group = {
  726. .cg_item = {
  727. .ci_namebuf = "nvmet",
  728. .ci_type = &nvmet_root_type,
  729. },
  730. },
  731. };
  732. int __init nvmet_init_configfs(void)
  733. {
  734. int ret;
  735. config_group_init(&nvmet_configfs_subsystem.su_group);
  736. mutex_init(&nvmet_configfs_subsystem.su_mutex);
  737. config_group_init_type_name(&nvmet_subsystems_group,
  738. "subsystems", &nvmet_subsystems_type);
  739. configfs_add_default_group(&nvmet_subsystems_group,
  740. &nvmet_configfs_subsystem.su_group);
  741. config_group_init_type_name(&nvmet_ports_group,
  742. "ports", &nvmet_ports_type);
  743. configfs_add_default_group(&nvmet_ports_group,
  744. &nvmet_configfs_subsystem.su_group);
  745. config_group_init_type_name(&nvmet_hosts_group,
  746. "hosts", &nvmet_hosts_type);
  747. configfs_add_default_group(&nvmet_hosts_group,
  748. &nvmet_configfs_subsystem.su_group);
  749. ret = configfs_register_subsystem(&nvmet_configfs_subsystem);
  750. if (ret) {
  751. pr_err("configfs_register_subsystem: %d\n", ret);
  752. return ret;
  753. }
  754. return 0;
  755. }
  756. void __exit nvmet_exit_configfs(void)
  757. {
  758. configfs_unregister_subsystem(&nvmet_configfs_subsystem);
  759. }