blob: 0939a5492c1644a2aa2b95ab09ff041923681227 [file] [log] [blame]
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001/*******************************************************************************
2* Filename: target_core_fabric_configfs.c
3 *
4 * This file contains generic fabric module configfs infrastructure for
5 * TCM v4.x code
6 *
Nicholas Bellinger4c762512013-09-05 15:29:12 -07007 * (c) Copyright 2010-2013 Datera, Inc.
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08008 *
Nicholas Bellingerfd9a11d2012-11-09 14:51:48 -08009 * Nicholas A. Bellinger <nab@linux-iscsi.org>
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -080010*
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 ****************************************************************************/
21
22#include <linux/module.h>
23#include <linux/moduleparam.h>
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -080024#include <linux/utsname.h>
25#include <linux/init.h>
26#include <linux/fs.h>
27#include <linux/namei.h>
28#include <linux/slab.h>
29#include <linux/types.h>
30#include <linux/delay.h>
31#include <linux/unistd.h>
32#include <linux/string.h>
33#include <linux/syscalls.h>
34#include <linux/configfs.h>
35
36#include <target/target_core_base.h>
Christoph Hellwigc4795fb2011-11-16 09:46:48 -050037#include <target/target_core_fabric.h>
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -080038#include <target/target_core_fabric_configfs.h>
39#include <target/target_core_configfs.h>
40#include <target/configfs_macros.h>
41
Christoph Hellwige26d99a2011-11-14 12:30:30 -050042#include "target_core_internal.h"
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -080043#include "target_core_alua.h"
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -080044#include "target_core_pr.h"
45
46#define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \
47static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
48{ \
Christoph Hellwig968ebe72015-05-03 08:50:55 +020049 struct config_item_type *cit = &tf->tf_##_name##_cit; \
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -080050 \
51 cit->ct_item_ops = _item_ops; \
52 cit->ct_group_ops = _group_ops; \
53 cit->ct_attrs = _attrs; \
Christoph Hellwig0dc2e8d2015-05-03 08:50:54 +020054 cit->ct_owner = tf->tf_ops->module; \
Andy Grover6708bb22011-06-08 10:36:43 -070055 pr_debug("Setup generic %s\n", __stringify(_name)); \
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -080056}
57
Christoph Hellwig9ac89282015-04-08 20:01:35 +020058#define TF_CIT_SETUP_DRV(_name, _item_ops, _group_ops) \
59static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
60{ \
Christoph Hellwig968ebe72015-05-03 08:50:55 +020061 struct config_item_type *cit = &tf->tf_##_name##_cit; \
Christoph Hellwigef0caf82015-05-03 08:50:53 +020062 struct configfs_attribute **attrs = tf->tf_ops->tfc_##_name##_attrs; \
Christoph Hellwig9ac89282015-04-08 20:01:35 +020063 \
64 cit->ct_item_ops = _item_ops; \
65 cit->ct_group_ops = _group_ops; \
66 cit->ct_attrs = attrs; \
Christoph Hellwig0dc2e8d2015-05-03 08:50:54 +020067 cit->ct_owner = tf->tf_ops->module; \
Christoph Hellwig9ac89282015-04-08 20:01:35 +020068 pr_debug("Setup generic %s\n", __stringify(_name)); \
69}
70
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -080071/* Start of tfc_tpg_mappedlun_cit */
72
73static int target_fabric_mappedlun_link(
74 struct config_item *lun_acl_ci,
75 struct config_item *lun_ci)
76{
77 struct se_dev_entry *deve;
78 struct se_lun *lun = container_of(to_config_group(lun_ci),
79 struct se_lun, lun_group);
80 struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci),
81 struct se_lun_acl, se_lun_group);
82 struct se_portal_group *se_tpg;
83 struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s;
84 int ret = 0, lun_access;
Nicholas Bellinger0ff87542012-12-04 23:43:57 -080085
86 if (lun->lun_link_magic != SE_LUN_LINK_MAGIC) {
87 pr_err("Bad lun->lun_link_magic, not a valid lun_ci pointer:"
88 " %p to struct lun: %p\n", lun_ci, lun);
89 return -EFAULT;
90 }
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -080091 /*
92 * Ensure that the source port exists
93 */
Andy Grover6708bb22011-06-08 10:36:43 -070094 if (!lun->lun_sep || !lun->lun_sep->sep_tpg) {
95 pr_err("Source se_lun->lun_sep or lun->lun_sep->sep"
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -080096 "_tpg does not exist\n");
97 return -EINVAL;
98 }
99 se_tpg = lun->lun_sep->sep_tpg;
100
101 nacl_ci = &lun_acl_ci->ci_parent->ci_group->cg_item;
102 tpg_ci = &nacl_ci->ci_group->cg_item;
103 wwn_ci = &tpg_ci->ci_group->cg_item;
104 tpg_ci_s = &lun_ci->ci_parent->ci_group->cg_item;
105 wwn_ci_s = &tpg_ci_s->ci_group->cg_item;
106 /*
107 * Make sure the SymLink is going to the same $FABRIC/$WWN/tpgt_$TPGT
108 */
109 if (strcmp(config_item_name(wwn_ci), config_item_name(wwn_ci_s))) {
Andy Grover6708bb22011-06-08 10:36:43 -0700110 pr_err("Illegal Initiator ACL SymLink outside of %s\n",
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800111 config_item_name(wwn_ci));
112 return -EINVAL;
113 }
114 if (strcmp(config_item_name(tpg_ci), config_item_name(tpg_ci_s))) {
Andy Grover6708bb22011-06-08 10:36:43 -0700115 pr_err("Illegal Initiator ACL Symlink outside of %s"
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800116 " TPGT: %s\n", config_item_name(wwn_ci),
117 config_item_name(tpg_ci));
118 return -EINVAL;
119 }
120 /*
121 * If this struct se_node_acl was dynamically generated with
122 * tpg_1/attrib/generate_node_acls=1, use the existing deve->lun_flags,
123 * which be will write protected (READ-ONLY) when
124 * tpg_1/attrib/demo_mode_write_protect=1
125 */
Nicholas Bellinger29a05de2015-03-22 20:42:19 -0700126 rcu_read_lock();
127 deve = target_nacl_find_deve(lacl->se_lun_nacl, lacl->mapped_lun);
128 if (deve)
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800129 lun_access = deve->lun_flags;
130 else
131 lun_access =
Andy Grovere3d6f902011-07-19 08:55:10 +0000132 (se_tpg->se_tpg_tfo->tpg_check_prod_mode_write_protect(
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800133 se_tpg)) ? TRANSPORT_LUNFLAGS_READ_ONLY :
134 TRANSPORT_LUNFLAGS_READ_WRITE;
Nicholas Bellinger29a05de2015-03-22 20:42:19 -0700135 rcu_read_unlock();
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800136 /*
137 * Determine the actual mapped LUN value user wants..
138 *
139 * This value is what the SCSI Initiator actually sees the
140 * iscsi/$IQN/$TPGT/lun/lun_* as on their SCSI Initiator Ports.
141 */
142 ret = core_dev_add_initiator_node_lun_acl(se_tpg, lacl,
143 lun->unpacked_lun, lun_access);
144
145 return (ret < 0) ? -EINVAL : 0;
146}
147
148static int target_fabric_mappedlun_unlink(
149 struct config_item *lun_acl_ci,
150 struct config_item *lun_ci)
151{
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800152 struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci),
153 struct se_lun_acl, se_lun_group);
Nicholas Bellinger29a05de2015-03-22 20:42:19 -0700154 struct se_lun *lun = container_of(to_config_group(lun_ci),
155 struct se_lun, lun_group);
156 struct se_portal_group *se_tpg = lun->lun_sep->sep_tpg;
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800157
Nicholas Bellinger29a05de2015-03-22 20:42:19 -0700158 return core_dev_del_initiator_node_lun_acl(se_tpg, lun, lacl);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800159}
160
161CONFIGFS_EATTR_STRUCT(target_fabric_mappedlun, se_lun_acl);
162#define TCM_MAPPEDLUN_ATTR(_name, _mode) \
163static struct target_fabric_mappedlun_attribute target_fabric_mappedlun_##_name = \
164 __CONFIGFS_EATTR(_name, _mode, \
165 target_fabric_mappedlun_show_##_name, \
166 target_fabric_mappedlun_store_##_name);
167
168static ssize_t target_fabric_mappedlun_show_write_protect(
169 struct se_lun_acl *lacl,
170 char *page)
171{
172 struct se_node_acl *se_nacl = lacl->se_lun_nacl;
173 struct se_dev_entry *deve;
Nicholas Bellinger29a05de2015-03-22 20:42:19 -0700174 ssize_t len = 0;
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800175
Nicholas Bellinger29a05de2015-03-22 20:42:19 -0700176 rcu_read_lock();
177 deve = target_nacl_find_deve(se_nacl, lacl->mapped_lun);
178 if (deve) {
179 len = sprintf(page, "%d\n",
180 (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) ? 1 : 0);
181 }
182 rcu_read_unlock();
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800183
184 return len;
185}
186
187static ssize_t target_fabric_mappedlun_store_write_protect(
188 struct se_lun_acl *lacl,
189 const char *page,
190 size_t count)
191{
192 struct se_node_acl *se_nacl = lacl->se_lun_nacl;
193 struct se_portal_group *se_tpg = se_nacl->se_tpg;
194 unsigned long op;
Jingoo Han57103d72013-07-19 16:22:19 +0900195 int ret;
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800196
Jingoo Han57103d72013-07-19 16:22:19 +0900197 ret = kstrtoul(page, 0, &op);
198 if (ret)
199 return ret;
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800200
201 if ((op != 1) && (op != 0))
202 return -EINVAL;
203
204 core_update_device_list_access(lacl->mapped_lun, (op) ?
205 TRANSPORT_LUNFLAGS_READ_ONLY :
206 TRANSPORT_LUNFLAGS_READ_WRITE,
207 lacl->se_lun_nacl);
208
Andy Grover6708bb22011-06-08 10:36:43 -0700209 pr_debug("%s_ConfigFS: Changed Initiator ACL: %s"
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800210 " Mapped LUN: %u Write Protect bit to %s\n",
Andy Grovere3d6f902011-07-19 08:55:10 +0000211 se_tpg->se_tpg_tfo->get_fabric_name(),
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800212 lacl->initiatorname, lacl->mapped_lun, (op) ? "ON" : "OFF");
213
214 return count;
215
216}
217
218TCM_MAPPEDLUN_ATTR(write_protect, S_IRUGO | S_IWUSR);
219
220CONFIGFS_EATTR_OPS(target_fabric_mappedlun, se_lun_acl, se_lun_group);
221
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -0800222static void target_fabric_mappedlun_release(struct config_item *item)
223{
224 struct se_lun_acl *lacl = container_of(to_config_group(item),
225 struct se_lun_acl, se_lun_group);
226 struct se_portal_group *se_tpg = lacl->se_lun_nacl->se_tpg;
227
228 core_dev_free_initiator_node_lun_acl(se_tpg, lacl);
229}
230
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800231static struct configfs_attribute *target_fabric_mappedlun_attrs[] = {
232 &target_fabric_mappedlun_write_protect.attr,
233 NULL,
234};
235
236static struct configfs_item_operations target_fabric_mappedlun_item_ops = {
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -0800237 .release = target_fabric_mappedlun_release,
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800238 .show_attribute = target_fabric_mappedlun_attr_show,
239 .store_attribute = target_fabric_mappedlun_attr_store,
240 .allow_link = target_fabric_mappedlun_link,
241 .drop_link = target_fabric_mappedlun_unlink,
242};
243
244TF_CIT_SETUP(tpg_mappedlun, &target_fabric_mappedlun_item_ops, NULL,
245 target_fabric_mappedlun_attrs);
246
247/* End of tfc_tpg_mappedlun_cit */
248
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700249/* Start of tfc_tpg_mappedlun_port_cit */
250
251static struct config_group *target_core_mappedlun_stat_mkdir(
252 struct config_group *group,
253 const char *name)
254{
255 return ERR_PTR(-ENOSYS);
256}
257
258static void target_core_mappedlun_stat_rmdir(
259 struct config_group *group,
260 struct config_item *item)
261{
262 return;
263}
264
265static struct configfs_group_operations target_fabric_mappedlun_stat_group_ops = {
266 .make_group = target_core_mappedlun_stat_mkdir,
267 .drop_item = target_core_mappedlun_stat_rmdir,
268};
269
270TF_CIT_SETUP(tpg_mappedlun_stat, NULL, &target_fabric_mappedlun_stat_group_ops,
271 NULL);
272
273/* End of tfc_tpg_mappedlun_port_cit */
274
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800275/* Start of tfc_tpg_nacl_attrib_cit */
276
277CONFIGFS_EATTR_OPS(target_fabric_nacl_attrib, se_node_acl, acl_attrib_group);
278
279static struct configfs_item_operations target_fabric_nacl_attrib_item_ops = {
280 .show_attribute = target_fabric_nacl_attrib_attr_show,
281 .store_attribute = target_fabric_nacl_attrib_attr_store,
282};
283
Christoph Hellwig9ac89282015-04-08 20:01:35 +0200284TF_CIT_SETUP_DRV(tpg_nacl_attrib, &target_fabric_nacl_attrib_item_ops, NULL);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800285
286/* End of tfc_tpg_nacl_attrib_cit */
287
288/* Start of tfc_tpg_nacl_auth_cit */
289
290CONFIGFS_EATTR_OPS(target_fabric_nacl_auth, se_node_acl, acl_auth_group);
291
292static struct configfs_item_operations target_fabric_nacl_auth_item_ops = {
293 .show_attribute = target_fabric_nacl_auth_attr_show,
294 .store_attribute = target_fabric_nacl_auth_attr_store,
295};
296
Christoph Hellwig9ac89282015-04-08 20:01:35 +0200297TF_CIT_SETUP_DRV(tpg_nacl_auth, &target_fabric_nacl_auth_item_ops, NULL);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800298
299/* End of tfc_tpg_nacl_auth_cit */
300
301/* Start of tfc_tpg_nacl_param_cit */
302
303CONFIGFS_EATTR_OPS(target_fabric_nacl_param, se_node_acl, acl_param_group);
304
305static struct configfs_item_operations target_fabric_nacl_param_item_ops = {
306 .show_attribute = target_fabric_nacl_param_attr_show,
307 .store_attribute = target_fabric_nacl_param_attr_store,
308};
309
Christoph Hellwig9ac89282015-04-08 20:01:35 +0200310TF_CIT_SETUP_DRV(tpg_nacl_param, &target_fabric_nacl_param_item_ops, NULL);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800311
312/* End of tfc_tpg_nacl_param_cit */
313
314/* Start of tfc_tpg_nacl_base_cit */
315
316CONFIGFS_EATTR_OPS(target_fabric_nacl_base, se_node_acl, acl_group);
317
318static struct config_group *target_fabric_make_mappedlun(
319 struct config_group *group,
320 const char *name)
321{
322 struct se_node_acl *se_nacl = container_of(group,
323 struct se_node_acl, acl_group);
324 struct se_portal_group *se_tpg = se_nacl->se_tpg;
325 struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
Joern Engelda0abae2014-09-02 17:49:57 -0400326 struct se_lun_acl *lacl = NULL;
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800327 struct config_item *acl_ci;
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700328 struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL;
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800329 char *buf;
330 unsigned long mapped_lun;
331 int ret = 0;
332
333 acl_ci = &group->cg_item;
Andy Grover6708bb22011-06-08 10:36:43 -0700334 if (!acl_ci) {
335 pr_err("Unable to locatel acl_ci\n");
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800336 return NULL;
337 }
338
339 buf = kzalloc(strlen(name) + 1, GFP_KERNEL);
Andy Grover6708bb22011-06-08 10:36:43 -0700340 if (!buf) {
341 pr_err("Unable to allocate memory for name buf\n");
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800342 return ERR_PTR(-ENOMEM);
343 }
344 snprintf(buf, strlen(name) + 1, "%s", name);
345 /*
346 * Make sure user is creating iscsi/$IQN/$TPGT/acls/$INITIATOR/lun_$ID.
347 */
348 if (strstr(buf, "lun_") != buf) {
Andy Grover6708bb22011-06-08 10:36:43 -0700349 pr_err("Unable to locate \"lun_\" from buf: %s"
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800350 " name: %s\n", buf, name);
351 ret = -EINVAL;
352 goto out;
353 }
354 /*
355 * Determine the Mapped LUN value. This is what the SCSI Initiator
356 * Port will actually see.
357 */
Jingoo Han57103d72013-07-19 16:22:19 +0900358 ret = kstrtoul(buf + 4, 0, &mapped_lun);
359 if (ret)
360 goto out;
361 if (mapped_lun > UINT_MAX) {
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800362 ret = -EINVAL;
363 goto out;
364 }
Nicholas Bellingerfbbf8552013-02-18 18:31:37 -0800365 if (mapped_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) {
366 pr_err("Mapped LUN: %lu exceeds TRANSPORT_MAX_LUNS_PER_TPG"
367 "-1: %u for Target Portal Group: %u\n", mapped_lun,
368 TRANSPORT_MAX_LUNS_PER_TPG-1,
369 se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg));
370 ret = -EINVAL;
371 goto out;
372 }
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800373
Nicholas Bellingerfcf29482013-02-18 18:00:33 -0800374 lacl = core_dev_init_initiator_node_lun_acl(se_tpg, se_nacl,
375 mapped_lun, &ret);
Andy Grover6708bb22011-06-08 10:36:43 -0700376 if (!lacl) {
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700377 ret = -EINVAL;
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800378 goto out;
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700379 }
380
381 lacl_cg = &lacl->se_lun_group;
Sebastian Andrzej Siewior13f6a912012-11-27 18:54:21 +0100382 lacl_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700383 GFP_KERNEL);
384 if (!lacl_cg->default_groups) {
Andy Grover6708bb22011-06-08 10:36:43 -0700385 pr_err("Unable to allocate lacl_cg->default_groups\n");
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700386 ret = -ENOMEM;
387 goto out;
388 }
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800389
390 config_group_init_type_name(&lacl->se_lun_group, name,
Christoph Hellwig968ebe72015-05-03 08:50:55 +0200391 &tf->tf_tpg_mappedlun_cit);
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700392 config_group_init_type_name(&lacl->ml_stat_grps.stat_group,
Christoph Hellwig968ebe72015-05-03 08:50:55 +0200393 "statistics", &tf->tf_tpg_mappedlun_stat_cit);
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700394 lacl_cg->default_groups[0] = &lacl->ml_stat_grps.stat_group;
395 lacl_cg->default_groups[1] = NULL;
396
Andy Grovere3d6f902011-07-19 08:55:10 +0000397 ml_stat_grp = &lacl->ml_stat_grps.stat_group;
Sebastian Andrzej Siewior13f6a912012-11-27 18:54:21 +0100398 ml_stat_grp->default_groups = kmalloc(sizeof(struct config_group *) * 3,
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700399 GFP_KERNEL);
400 if (!ml_stat_grp->default_groups) {
Andy Grover6708bb22011-06-08 10:36:43 -0700401 pr_err("Unable to allocate ml_stat_grp->default_groups\n");
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700402 ret = -ENOMEM;
403 goto out;
404 }
405 target_stat_setup_mappedlun_default_groups(lacl);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800406
407 kfree(buf);
408 return &lacl->se_lun_group;
409out:
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700410 if (lacl_cg)
411 kfree(lacl_cg->default_groups);
Joern Engelda0abae2014-09-02 17:49:57 -0400412 kfree(lacl);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800413 kfree(buf);
414 return ERR_PTR(ret);
415}
416
417static void target_fabric_drop_mappedlun(
418 struct config_group *group,
419 struct config_item *item)
420{
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700421 struct se_lun_acl *lacl = container_of(to_config_group(item),
422 struct se_lun_acl, se_lun_group);
423 struct config_item *df_item;
424 struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL;
425 int i;
426
Andy Grovere3d6f902011-07-19 08:55:10 +0000427 ml_stat_grp = &lacl->ml_stat_grps.stat_group;
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700428 for (i = 0; ml_stat_grp->default_groups[i]; i++) {
429 df_item = &ml_stat_grp->default_groups[i]->cg_item;
430 ml_stat_grp->default_groups[i] = NULL;
431 config_item_put(df_item);
432 }
433 kfree(ml_stat_grp->default_groups);
434
435 lacl_cg = &lacl->se_lun_group;
436 for (i = 0; lacl_cg->default_groups[i]; i++) {
437 df_item = &lacl_cg->default_groups[i]->cg_item;
438 lacl_cg->default_groups[i] = NULL;
439 config_item_put(df_item);
440 }
441 kfree(lacl_cg->default_groups);
442
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800443 config_item_put(item);
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -0800444}
445
446static void target_fabric_nacl_base_release(struct config_item *item)
447{
448 struct se_node_acl *se_nacl = container_of(to_config_group(item),
449 struct se_node_acl, acl_group);
Christoph Hellwigc7d6a802015-04-13 19:51:14 +0200450 struct target_fabric_configfs *tf = se_nacl->se_tpg->se_tpg_wwn->wwn_tf;
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -0800451
Christoph Hellwigef0caf82015-05-03 08:50:53 +0200452 if (tf->tf_ops->fabric_cleanup_nodeacl)
453 tf->tf_ops->fabric_cleanup_nodeacl(se_nacl);
Christoph Hellwigc7d6a802015-04-13 19:51:14 +0200454 core_tpg_del_initiator_node_acl(se_nacl);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800455}
456
457static struct configfs_item_operations target_fabric_nacl_base_item_ops = {
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -0800458 .release = target_fabric_nacl_base_release,
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800459 .show_attribute = target_fabric_nacl_base_attr_show,
460 .store_attribute = target_fabric_nacl_base_attr_store,
461};
462
463static struct configfs_group_operations target_fabric_nacl_base_group_ops = {
464 .make_group = target_fabric_make_mappedlun,
465 .drop_item = target_fabric_drop_mappedlun,
466};
467
Christoph Hellwig9ac89282015-04-08 20:01:35 +0200468TF_CIT_SETUP_DRV(tpg_nacl_base, &target_fabric_nacl_base_item_ops,
469 &target_fabric_nacl_base_group_ops);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800470
471/* End of tfc_tpg_nacl_base_cit */
472
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700473/* Start of tfc_node_fabric_stats_cit */
474/*
475 * This is used as a placeholder for struct se_node_acl->acl_fabric_stat_group
476 * to allow fabrics access to ->acl_fabric_stat_group->default_groups[]
477 */
478TF_CIT_SETUP(tpg_nacl_stat, NULL, NULL, NULL);
479
480/* End of tfc_wwn_fabric_stats_cit */
481
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800482/* Start of tfc_tpg_nacl_cit */
483
484static struct config_group *target_fabric_make_nodeacl(
485 struct config_group *group,
486 const char *name)
487{
488 struct se_portal_group *se_tpg = container_of(group,
489 struct se_portal_group, tpg_acl_group);
490 struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
491 struct se_node_acl *se_nacl;
492 struct config_group *nacl_cg;
493
Christoph Hellwigc7d6a802015-04-13 19:51:14 +0200494 se_nacl = core_tpg_add_initiator_node_acl(se_tpg, name);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800495 if (IS_ERR(se_nacl))
Thomas Meyere1750ba2011-08-01 23:58:18 +0200496 return ERR_CAST(se_nacl);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800497
Christoph Hellwigef0caf82015-05-03 08:50:53 +0200498 if (tf->tf_ops->fabric_init_nodeacl) {
499 int ret = tf->tf_ops->fabric_init_nodeacl(se_nacl, name);
Christoph Hellwigc7d6a802015-04-13 19:51:14 +0200500 if (ret) {
501 core_tpg_del_initiator_node_acl(se_nacl);
502 return ERR_PTR(ret);
503 }
504 }
505
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800506 nacl_cg = &se_nacl->acl_group;
507 nacl_cg->default_groups = se_nacl->acl_default_groups;
508 nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group;
509 nacl_cg->default_groups[1] = &se_nacl->acl_auth_group;
510 nacl_cg->default_groups[2] = &se_nacl->acl_param_group;
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700511 nacl_cg->default_groups[3] = &se_nacl->acl_fabric_stat_group;
512 nacl_cg->default_groups[4] = NULL;
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800513
514 config_group_init_type_name(&se_nacl->acl_group, name,
Christoph Hellwig968ebe72015-05-03 08:50:55 +0200515 &tf->tf_tpg_nacl_base_cit);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800516 config_group_init_type_name(&se_nacl->acl_attrib_group, "attrib",
Christoph Hellwig968ebe72015-05-03 08:50:55 +0200517 &tf->tf_tpg_nacl_attrib_cit);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800518 config_group_init_type_name(&se_nacl->acl_auth_group, "auth",
Christoph Hellwig968ebe72015-05-03 08:50:55 +0200519 &tf->tf_tpg_nacl_auth_cit);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800520 config_group_init_type_name(&se_nacl->acl_param_group, "param",
Christoph Hellwig968ebe72015-05-03 08:50:55 +0200521 &tf->tf_tpg_nacl_param_cit);
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700522 config_group_init_type_name(&se_nacl->acl_fabric_stat_group,
Christoph Hellwig968ebe72015-05-03 08:50:55 +0200523 "fabric_statistics", &tf->tf_tpg_nacl_stat_cit);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800524
525 return &se_nacl->acl_group;
526}
527
528static void target_fabric_drop_nodeacl(
529 struct config_group *group,
530 struct config_item *item)
531{
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800532 struct se_node_acl *se_nacl = container_of(to_config_group(item),
533 struct se_node_acl, acl_group);
534 struct config_item *df_item;
535 struct config_group *nacl_cg;
536 int i;
537
538 nacl_cg = &se_nacl->acl_group;
539 for (i = 0; nacl_cg->default_groups[i]; i++) {
540 df_item = &nacl_cg->default_groups[i]->cg_item;
541 nacl_cg->default_groups[i] = NULL;
542 config_item_put(df_item);
543 }
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -0800544 /*
545 * struct se_node_acl free is done in target_fabric_nacl_base_release()
546 */
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800547 config_item_put(item);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800548}
549
550static struct configfs_group_operations target_fabric_nacl_group_ops = {
551 .make_group = target_fabric_make_nodeacl,
552 .drop_item = target_fabric_drop_nodeacl,
553};
554
555TF_CIT_SETUP(tpg_nacl, NULL, &target_fabric_nacl_group_ops, NULL);
556
557/* End of tfc_tpg_nacl_cit */
558
559/* Start of tfc_tpg_np_base_cit */
560
561CONFIGFS_EATTR_OPS(target_fabric_np_base, se_tpg_np, tpg_np_group);
562
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -0800563static void target_fabric_np_base_release(struct config_item *item)
564{
565 struct se_tpg_np *se_tpg_np = container_of(to_config_group(item),
566 struct se_tpg_np, tpg_np_group);
567 struct se_portal_group *se_tpg = se_tpg_np->tpg_np_parent;
568 struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
569
Christoph Hellwigef0caf82015-05-03 08:50:53 +0200570 tf->tf_ops->fabric_drop_np(se_tpg_np);
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -0800571}
572
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800573static struct configfs_item_operations target_fabric_np_base_item_ops = {
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -0800574 .release = target_fabric_np_base_release,
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800575 .show_attribute = target_fabric_np_base_attr_show,
576 .store_attribute = target_fabric_np_base_attr_store,
577};
578
Christoph Hellwig9ac89282015-04-08 20:01:35 +0200579TF_CIT_SETUP_DRV(tpg_np_base, &target_fabric_np_base_item_ops, NULL);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800580
581/* End of tfc_tpg_np_base_cit */
582
583/* Start of tfc_tpg_np_cit */
584
585static struct config_group *target_fabric_make_np(
586 struct config_group *group,
587 const char *name)
588{
589 struct se_portal_group *se_tpg = container_of(group,
590 struct se_portal_group, tpg_np_group);
591 struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
592 struct se_tpg_np *se_tpg_np;
593
Christoph Hellwigef0caf82015-05-03 08:50:53 +0200594 if (!tf->tf_ops->fabric_make_np) {
Andy Grover6708bb22011-06-08 10:36:43 -0700595 pr_err("tf->tf_ops.fabric_make_np is NULL\n");
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800596 return ERR_PTR(-ENOSYS);
597 }
598
Christoph Hellwigef0caf82015-05-03 08:50:53 +0200599 se_tpg_np = tf->tf_ops->fabric_make_np(se_tpg, group, name);
Andy Grover6708bb22011-06-08 10:36:43 -0700600 if (!se_tpg_np || IS_ERR(se_tpg_np))
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800601 return ERR_PTR(-EINVAL);
602
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -0800603 se_tpg_np->tpg_np_parent = se_tpg;
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800604 config_group_init_type_name(&se_tpg_np->tpg_np_group, name,
Christoph Hellwig968ebe72015-05-03 08:50:55 +0200605 &tf->tf_tpg_np_base_cit);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800606
607 return &se_tpg_np->tpg_np_group;
608}
609
610static void target_fabric_drop_np(
611 struct config_group *group,
612 struct config_item *item)
613{
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -0800614 /*
615 * struct se_tpg_np is released via target_fabric_np_base_release()
616 */
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800617 config_item_put(item);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800618}
619
620static struct configfs_group_operations target_fabric_np_group_ops = {
621 .make_group = &target_fabric_make_np,
622 .drop_item = &target_fabric_drop_np,
623};
624
625TF_CIT_SETUP(tpg_np, NULL, &target_fabric_np_group_ops, NULL);
626
627/* End of tfc_tpg_np_cit */
628
629/* Start of tfc_tpg_port_cit */
630
631CONFIGFS_EATTR_STRUCT(target_fabric_port, se_lun);
632#define TCM_PORT_ATTR(_name, _mode) \
633static struct target_fabric_port_attribute target_fabric_port_##_name = \
634 __CONFIGFS_EATTR(_name, _mode, \
635 target_fabric_port_show_attr_##_name, \
636 target_fabric_port_store_attr_##_name);
637
638#define TCM_PORT_ATTOR_RO(_name) \
639 __CONFIGFS_EATTR_RO(_name, \
640 target_fabric_port_show_attr_##_name);
641
642/*
643 * alua_tg_pt_gp
644 */
645static ssize_t target_fabric_port_show_attr_alua_tg_pt_gp(
646 struct se_lun *lun,
647 char *page)
648{
Andy Grover6708bb22011-06-08 10:36:43 -0700649 if (!lun || !lun->lun_sep)
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800650 return -ENODEV;
651
652 return core_alua_show_tg_pt_gp_info(lun->lun_sep, page);
653}
654
655static ssize_t target_fabric_port_store_attr_alua_tg_pt_gp(
656 struct se_lun *lun,
657 const char *page,
658 size_t count)
659{
Andy Grover6708bb22011-06-08 10:36:43 -0700660 if (!lun || !lun->lun_sep)
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800661 return -ENODEV;
662
663 return core_alua_store_tg_pt_gp_info(lun->lun_sep, page, count);
664}
665
666TCM_PORT_ATTR(alua_tg_pt_gp, S_IRUGO | S_IWUSR);
667
668/*
669 * alua_tg_pt_offline
670 */
671static ssize_t target_fabric_port_show_attr_alua_tg_pt_offline(
672 struct se_lun *lun,
673 char *page)
674{
Andy Grover6708bb22011-06-08 10:36:43 -0700675 if (!lun || !lun->lun_sep)
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800676 return -ENODEV;
677
678 return core_alua_show_offline_bit(lun, page);
679}
680
681static ssize_t target_fabric_port_store_attr_alua_tg_pt_offline(
682 struct se_lun *lun,
683 const char *page,
684 size_t count)
685{
Andy Grover6708bb22011-06-08 10:36:43 -0700686 if (!lun || !lun->lun_sep)
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800687 return -ENODEV;
688
689 return core_alua_store_offline_bit(lun, page, count);
690}
691
692TCM_PORT_ATTR(alua_tg_pt_offline, S_IRUGO | S_IWUSR);
693
694/*
695 * alua_tg_pt_status
696 */
697static ssize_t target_fabric_port_show_attr_alua_tg_pt_status(
698 struct se_lun *lun,
699 char *page)
700{
Andy Grover6708bb22011-06-08 10:36:43 -0700701 if (!lun || !lun->lun_sep)
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800702 return -ENODEV;
703
704 return core_alua_show_secondary_status(lun, page);
705}
706
707static ssize_t target_fabric_port_store_attr_alua_tg_pt_status(
708 struct se_lun *lun,
709 const char *page,
710 size_t count)
711{
Andy Grover6708bb22011-06-08 10:36:43 -0700712 if (!lun || !lun->lun_sep)
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800713 return -ENODEV;
714
715 return core_alua_store_secondary_status(lun, page, count);
716}
717
718TCM_PORT_ATTR(alua_tg_pt_status, S_IRUGO | S_IWUSR);
719
720/*
721 * alua_tg_pt_write_md
722 */
723static ssize_t target_fabric_port_show_attr_alua_tg_pt_write_md(
724 struct se_lun *lun,
725 char *page)
726{
Andy Grover6708bb22011-06-08 10:36:43 -0700727 if (!lun || !lun->lun_sep)
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800728 return -ENODEV;
729
730 return core_alua_show_secondary_write_metadata(lun, page);
731}
732
733static ssize_t target_fabric_port_store_attr_alua_tg_pt_write_md(
734 struct se_lun *lun,
735 const char *page,
736 size_t count)
737{
Andy Grover6708bb22011-06-08 10:36:43 -0700738 if (!lun || !lun->lun_sep)
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800739 return -ENODEV;
740
741 return core_alua_store_secondary_write_metadata(lun, page, count);
742}
743
744TCM_PORT_ATTR(alua_tg_pt_write_md, S_IRUGO | S_IWUSR);
745
746
747static struct configfs_attribute *target_fabric_port_attrs[] = {
748 &target_fabric_port_alua_tg_pt_gp.attr,
749 &target_fabric_port_alua_tg_pt_offline.attr,
750 &target_fabric_port_alua_tg_pt_status.attr,
751 &target_fabric_port_alua_tg_pt_write_md.attr,
752 NULL,
753};
754
755CONFIGFS_EATTR_OPS(target_fabric_port, se_lun, lun_group);
756
757static int target_fabric_port_link(
758 struct config_item *lun_ci,
759 struct config_item *se_dev_ci)
760{
761 struct config_item *tpg_ci;
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800762 struct se_lun *lun = container_of(to_config_group(lun_ci),
763 struct se_lun, lun_group);
764 struct se_lun *lun_p;
765 struct se_portal_group *se_tpg;
Christoph Hellwig0fd97cc2012-10-08 00:03:19 -0400766 struct se_device *dev =
767 container_of(to_config_group(se_dev_ci), struct se_device, dev_group);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800768 struct target_fabric_configfs *tf;
769 int ret;
770
Nicholas Bellinger0ff87542012-12-04 23:43:57 -0800771 if (dev->dev_link_magic != SE_DEV_LINK_MAGIC) {
772 pr_err("Bad dev->dev_link_magic, not a valid se_dev_ci pointer:"
773 " %p to struct se_device: %p\n", se_dev_ci, dev);
774 return -EFAULT;
775 }
776
Nicholas Bellingerfaa06ab2013-01-31 14:56:12 -0800777 if (!(dev->dev_flags & DF_CONFIGURED)) {
778 pr_err("se_device not configured yet, cannot port link\n");
779 return -ENODEV;
780 }
781
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800782 tpg_ci = &lun_ci->ci_parent->ci_group->cg_item;
783 se_tpg = container_of(to_config_group(tpg_ci),
784 struct se_portal_group, tpg_group);
785 tf = se_tpg->se_tpg_wwn->wwn_tf;
786
787 if (lun->lun_se_dev != NULL) {
Andy Grover6708bb22011-06-08 10:36:43 -0700788 pr_err("Port Symlink already exists\n");
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800789 return -EEXIST;
790 }
791
Andy Grover2dca6732012-07-12 17:34:55 -0700792 lun_p = core_dev_add_lun(se_tpg, dev, lun->unpacked_lun);
Sebastian Andrzej Siewior8d9efe52012-01-11 21:43:38 +0100793 if (IS_ERR(lun_p)) {
Andy Grover6708bb22011-06-08 10:36:43 -0700794 pr_err("core_dev_add_lun() failed\n");
Sebastian Andrzej Siewior8d9efe52012-01-11 21:43:38 +0100795 ret = PTR_ERR(lun_p);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800796 goto out;
797 }
798
Christoph Hellwigef0caf82015-05-03 08:50:53 +0200799 if (tf->tf_ops->fabric_post_link) {
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800800 /*
801 * Call the optional fabric_post_link() to allow a
802 * fabric module to setup any additional state once
803 * core_dev_add_lun() has been called..
804 */
Christoph Hellwigef0caf82015-05-03 08:50:53 +0200805 tf->tf_ops->fabric_post_link(se_tpg, lun);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800806 }
807
808 return 0;
809out:
810 return ret;
811}
812
813static int target_fabric_port_unlink(
814 struct config_item *lun_ci,
815 struct config_item *se_dev_ci)
816{
817 struct se_lun *lun = container_of(to_config_group(lun_ci),
818 struct se_lun, lun_group);
819 struct se_portal_group *se_tpg = lun->lun_sep->sep_tpg;
820 struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
821
Christoph Hellwigef0caf82015-05-03 08:50:53 +0200822 if (tf->tf_ops->fabric_pre_unlink) {
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800823 /*
824 * Call the optional fabric_pre_unlink() to allow a
825 * fabric module to release any additional stat before
826 * core_dev_del_lun() is called.
827 */
Christoph Hellwigef0caf82015-05-03 08:50:53 +0200828 tf->tf_ops->fabric_pre_unlink(se_tpg, lun);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800829 }
830
Andy Grovercd9d7cb2014-06-30 16:39:44 -0700831 core_dev_del_lun(se_tpg, lun);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800832 return 0;
833}
834
835static struct configfs_item_operations target_fabric_port_item_ops = {
836 .show_attribute = target_fabric_port_attr_show,
837 .store_attribute = target_fabric_port_attr_store,
838 .allow_link = target_fabric_port_link,
839 .drop_link = target_fabric_port_unlink,
840};
841
842TF_CIT_SETUP(tpg_port, &target_fabric_port_item_ops, NULL, target_fabric_port_attrs);
843
844/* End of tfc_tpg_port_cit */
845
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700846/* Start of tfc_tpg_port_stat_cit */
847
848static struct config_group *target_core_port_stat_mkdir(
849 struct config_group *group,
850 const char *name)
851{
852 return ERR_PTR(-ENOSYS);
853}
854
855static void target_core_port_stat_rmdir(
856 struct config_group *group,
857 struct config_item *item)
858{
859 return;
860}
861
862static struct configfs_group_operations target_fabric_port_stat_group_ops = {
863 .make_group = target_core_port_stat_mkdir,
864 .drop_item = target_core_port_stat_rmdir,
865};
866
867TF_CIT_SETUP(tpg_port_stat, NULL, &target_fabric_port_stat_group_ops, NULL);
868
869/* End of tfc_tpg_port_stat_cit */
870
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800871/* Start of tfc_tpg_lun_cit */
872
873static struct config_group *target_fabric_make_lun(
874 struct config_group *group,
875 const char *name)
876{
877 struct se_lun *lun;
878 struct se_portal_group *se_tpg = container_of(group,
879 struct se_portal_group, tpg_lun_group);
880 struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700881 struct config_group *lun_cg = NULL, *port_stat_grp = NULL;
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800882 unsigned long unpacked_lun;
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700883 int errno;
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800884
885 if (strstr(name, "lun_") != name) {
Andy Grover6708bb22011-06-08 10:36:43 -0700886 pr_err("Unable to locate \'_\" in"
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800887 " \"lun_$LUN_NUMBER\"\n");
888 return ERR_PTR(-EINVAL);
889 }
Jingoo Han57103d72013-07-19 16:22:19 +0900890 errno = kstrtoul(name + 4, 0, &unpacked_lun);
891 if (errno)
892 return ERR_PTR(errno);
893 if (unpacked_lun > UINT_MAX)
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800894 return ERR_PTR(-EINVAL);
895
896 lun = core_get_lun_from_tpg(se_tpg, unpacked_lun);
Andy Grover6708bb22011-06-08 10:36:43 -0700897 if (!lun)
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800898 return ERR_PTR(-EINVAL);
899
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700900 lun_cg = &lun->lun_group;
Sebastian Andrzej Siewior13f6a912012-11-27 18:54:21 +0100901 lun_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700902 GFP_KERNEL);
903 if (!lun_cg->default_groups) {
Andy Grover6708bb22011-06-08 10:36:43 -0700904 pr_err("Unable to allocate lun_cg->default_groups\n");
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700905 return ERR_PTR(-ENOMEM);
906 }
907
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800908 config_group_init_type_name(&lun->lun_group, name,
Christoph Hellwig968ebe72015-05-03 08:50:55 +0200909 &tf->tf_tpg_port_cit);
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700910 config_group_init_type_name(&lun->port_stat_grps.stat_group,
Christoph Hellwig968ebe72015-05-03 08:50:55 +0200911 "statistics", &tf->tf_tpg_port_stat_cit);
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700912 lun_cg->default_groups[0] = &lun->port_stat_grps.stat_group;
913 lun_cg->default_groups[1] = NULL;
914
Andy Grovere3d6f902011-07-19 08:55:10 +0000915 port_stat_grp = &lun->port_stat_grps.stat_group;
Andy Groverab6dae82013-12-09 14:27:36 -0800916 port_stat_grp->default_groups = kzalloc(sizeof(struct config_group *) * 4,
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700917 GFP_KERNEL);
918 if (!port_stat_grp->default_groups) {
Andy Grover6708bb22011-06-08 10:36:43 -0700919 pr_err("Unable to allocate port_stat_grp->default_groups\n");
Joern Engel1481473b2014-09-17 15:11:28 -0700920 kfree(lun_cg->default_groups);
921 return ERR_PTR(-ENOMEM);
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700922 }
923 target_stat_setup_port_default_groups(lun);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800924
925 return &lun->lun_group;
926}
927
928static void target_fabric_drop_lun(
929 struct config_group *group,
930 struct config_item *item)
931{
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700932 struct se_lun *lun = container_of(to_config_group(item),
933 struct se_lun, lun_group);
934 struct config_item *df_item;
935 struct config_group *lun_cg, *port_stat_grp;
936 int i;
937
Andy Grovere3d6f902011-07-19 08:55:10 +0000938 port_stat_grp = &lun->port_stat_grps.stat_group;
Nicholas Bellinger12d2338422011-03-14 04:06:11 -0700939 for (i = 0; port_stat_grp->default_groups[i]; i++) {
940 df_item = &port_stat_grp->default_groups[i]->cg_item;
941 port_stat_grp->default_groups[i] = NULL;
942 config_item_put(df_item);
943 }
944 kfree(port_stat_grp->default_groups);
945
946 lun_cg = &lun->lun_group;
947 for (i = 0; lun_cg->default_groups[i]; i++) {
948 df_item = &lun_cg->default_groups[i]->cg_item;
949 lun_cg->default_groups[i] = NULL;
950 config_item_put(df_item);
951 }
952 kfree(lun_cg->default_groups);
953
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800954 config_item_put(item);
955}
956
957static struct configfs_group_operations target_fabric_lun_group_ops = {
958 .make_group = &target_fabric_make_lun,
959 .drop_item = &target_fabric_drop_lun,
960};
961
962TF_CIT_SETUP(tpg_lun, NULL, &target_fabric_lun_group_ops, NULL);
963
964/* End of tfc_tpg_lun_cit */
965
966/* Start of tfc_tpg_attrib_cit */
967
968CONFIGFS_EATTR_OPS(target_fabric_tpg_attrib, se_portal_group, tpg_attrib_group);
969
970static struct configfs_item_operations target_fabric_tpg_attrib_item_ops = {
971 .show_attribute = target_fabric_tpg_attrib_attr_show,
972 .store_attribute = target_fabric_tpg_attrib_attr_store,
973};
974
Christoph Hellwig9ac89282015-04-08 20:01:35 +0200975TF_CIT_SETUP_DRV(tpg_attrib, &target_fabric_tpg_attrib_item_ops, NULL);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800976
977/* End of tfc_tpg_attrib_cit */
978
Nicholas Bellingere4b512e2013-06-19 18:37:00 -0700979/* Start of tfc_tpg_auth_cit */
980
981CONFIGFS_EATTR_OPS(target_fabric_tpg_auth, se_portal_group, tpg_auth_group);
982
983static struct configfs_item_operations target_fabric_tpg_auth_item_ops = {
984 .show_attribute = target_fabric_tpg_auth_attr_show,
985 .store_attribute = target_fabric_tpg_auth_attr_store,
986};
987
Christoph Hellwig9ac89282015-04-08 20:01:35 +0200988TF_CIT_SETUP_DRV(tpg_auth, &target_fabric_tpg_auth_item_ops, NULL);
Nicholas Bellingere4b512e2013-06-19 18:37:00 -0700989
990/* End of tfc_tpg_attrib_cit */
991
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -0800992/* Start of tfc_tpg_param_cit */
993
994CONFIGFS_EATTR_OPS(target_fabric_tpg_param, se_portal_group, tpg_param_group);
995
996static struct configfs_item_operations target_fabric_tpg_param_item_ops = {
997 .show_attribute = target_fabric_tpg_param_attr_show,
998 .store_attribute = target_fabric_tpg_param_attr_store,
999};
1000
Christoph Hellwig9ac89282015-04-08 20:01:35 +02001001TF_CIT_SETUP_DRV(tpg_param, &target_fabric_tpg_param_item_ops, NULL);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001002
1003/* End of tfc_tpg_param_cit */
1004
1005/* Start of tfc_tpg_base_cit */
1006/*
1007 * For use with TF_TPG_ATTR() and TF_TPG_ATTR_RO()
1008 */
1009CONFIGFS_EATTR_OPS(target_fabric_tpg, se_portal_group, tpg_group);
1010
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -08001011static void target_fabric_tpg_release(struct config_item *item)
1012{
1013 struct se_portal_group *se_tpg = container_of(to_config_group(item),
1014 struct se_portal_group, tpg_group);
1015 struct se_wwn *wwn = se_tpg->se_tpg_wwn;
1016 struct target_fabric_configfs *tf = wwn->wwn_tf;
1017
Christoph Hellwigef0caf82015-05-03 08:50:53 +02001018 tf->tf_ops->fabric_drop_tpg(se_tpg);
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -08001019}
1020
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001021static struct configfs_item_operations target_fabric_tpg_base_item_ops = {
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -08001022 .release = target_fabric_tpg_release,
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001023 .show_attribute = target_fabric_tpg_attr_show,
1024 .store_attribute = target_fabric_tpg_attr_store,
1025};
1026
Christoph Hellwig9ac89282015-04-08 20:01:35 +02001027TF_CIT_SETUP_DRV(tpg_base, &target_fabric_tpg_base_item_ops, NULL);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001028
1029/* End of tfc_tpg_base_cit */
1030
1031/* Start of tfc_tpg_cit */
1032
1033static struct config_group *target_fabric_make_tpg(
1034 struct config_group *group,
1035 const char *name)
1036{
1037 struct se_wwn *wwn = container_of(group, struct se_wwn, wwn_group);
1038 struct target_fabric_configfs *tf = wwn->wwn_tf;
1039 struct se_portal_group *se_tpg;
1040
Christoph Hellwigef0caf82015-05-03 08:50:53 +02001041 if (!tf->tf_ops->fabric_make_tpg) {
1042 pr_err("tf->tf_ops->fabric_make_tpg is NULL\n");
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001043 return ERR_PTR(-ENOSYS);
1044 }
1045
Christoph Hellwigef0caf82015-05-03 08:50:53 +02001046 se_tpg = tf->tf_ops->fabric_make_tpg(wwn, group, name);
Andy Grover6708bb22011-06-08 10:36:43 -07001047 if (!se_tpg || IS_ERR(se_tpg))
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001048 return ERR_PTR(-EINVAL);
1049 /*
1050 * Setup default groups from pre-allocated se_tpg->tpg_default_groups
1051 */
1052 se_tpg->tpg_group.default_groups = se_tpg->tpg_default_groups;
1053 se_tpg->tpg_group.default_groups[0] = &se_tpg->tpg_lun_group;
1054 se_tpg->tpg_group.default_groups[1] = &se_tpg->tpg_np_group;
1055 se_tpg->tpg_group.default_groups[2] = &se_tpg->tpg_acl_group;
1056 se_tpg->tpg_group.default_groups[3] = &se_tpg->tpg_attrib_group;
Nicholas Bellingere4b512e2013-06-19 18:37:00 -07001057 se_tpg->tpg_group.default_groups[4] = &se_tpg->tpg_auth_group;
1058 se_tpg->tpg_group.default_groups[5] = &se_tpg->tpg_param_group;
1059 se_tpg->tpg_group.default_groups[6] = NULL;
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001060
1061 config_group_init_type_name(&se_tpg->tpg_group, name,
Christoph Hellwig968ebe72015-05-03 08:50:55 +02001062 &tf->tf_tpg_base_cit);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001063 config_group_init_type_name(&se_tpg->tpg_lun_group, "lun",
Christoph Hellwig968ebe72015-05-03 08:50:55 +02001064 &tf->tf_tpg_lun_cit);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001065 config_group_init_type_name(&se_tpg->tpg_np_group, "np",
Christoph Hellwig968ebe72015-05-03 08:50:55 +02001066 &tf->tf_tpg_np_cit);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001067 config_group_init_type_name(&se_tpg->tpg_acl_group, "acls",
Christoph Hellwig968ebe72015-05-03 08:50:55 +02001068 &tf->tf_tpg_nacl_cit);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001069 config_group_init_type_name(&se_tpg->tpg_attrib_group, "attrib",
Christoph Hellwig968ebe72015-05-03 08:50:55 +02001070 &tf->tf_tpg_attrib_cit);
Nicholas Bellingere4b512e2013-06-19 18:37:00 -07001071 config_group_init_type_name(&se_tpg->tpg_auth_group, "auth",
Christoph Hellwig968ebe72015-05-03 08:50:55 +02001072 &tf->tf_tpg_auth_cit);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001073 config_group_init_type_name(&se_tpg->tpg_param_group, "param",
Christoph Hellwig968ebe72015-05-03 08:50:55 +02001074 &tf->tf_tpg_param_cit);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001075
1076 return &se_tpg->tpg_group;
1077}
1078
1079static void target_fabric_drop_tpg(
1080 struct config_group *group,
1081 struct config_item *item)
1082{
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001083 struct se_portal_group *se_tpg = container_of(to_config_group(item),
1084 struct se_portal_group, tpg_group);
1085 struct config_group *tpg_cg = &se_tpg->tpg_group;
1086 struct config_item *df_item;
1087 int i;
1088 /*
1089 * Release default groups, but do not release tpg_cg->default_groups
1090 * memory as it is statically allocated at se_tpg->tpg_default_groups.
1091 */
1092 for (i = 0; tpg_cg->default_groups[i]; i++) {
1093 df_item = &tpg_cg->default_groups[i]->cg_item;
1094 tpg_cg->default_groups[i] = NULL;
1095 config_item_put(df_item);
1096 }
1097
1098 config_item_put(item);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001099}
1100
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -08001101static void target_fabric_release_wwn(struct config_item *item)
1102{
1103 struct se_wwn *wwn = container_of(to_config_group(item),
1104 struct se_wwn, wwn_group);
1105 struct target_fabric_configfs *tf = wwn->wwn_tf;
1106
Christoph Hellwigef0caf82015-05-03 08:50:53 +02001107 tf->tf_ops->fabric_drop_wwn(wwn);
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -08001108}
1109
1110static struct configfs_item_operations target_fabric_tpg_item_ops = {
1111 .release = target_fabric_release_wwn,
1112};
1113
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001114static struct configfs_group_operations target_fabric_tpg_group_ops = {
1115 .make_group = target_fabric_make_tpg,
1116 .drop_item = target_fabric_drop_tpg,
1117};
1118
Nicholas Bellinger1f6fe7c2011-02-09 15:34:54 -08001119TF_CIT_SETUP(tpg, &target_fabric_tpg_item_ops, &target_fabric_tpg_group_ops,
1120 NULL);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001121
1122/* End of tfc_tpg_cit */
1123
Nicholas Bellinger12d2338422011-03-14 04:06:11 -07001124/* Start of tfc_wwn_fabric_stats_cit */
1125/*
1126 * This is used as a placeholder for struct se_wwn->fabric_stat_group
1127 * to allow fabrics access to ->fabric_stat_group->default_groups[]
1128 */
1129TF_CIT_SETUP(wwn_fabric_stats, NULL, NULL, NULL);
1130
1131/* End of tfc_wwn_fabric_stats_cit */
1132
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001133/* Start of tfc_wwn_cit */
1134
1135static struct config_group *target_fabric_make_wwn(
1136 struct config_group *group,
1137 const char *name)
1138{
1139 struct target_fabric_configfs *tf = container_of(group,
1140 struct target_fabric_configfs, tf_group);
1141 struct se_wwn *wwn;
1142
Christoph Hellwigef0caf82015-05-03 08:50:53 +02001143 if (!tf->tf_ops->fabric_make_wwn) {
Andy Grover6708bb22011-06-08 10:36:43 -07001144 pr_err("tf->tf_ops.fabric_make_wwn is NULL\n");
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001145 return ERR_PTR(-ENOSYS);
1146 }
1147
Christoph Hellwigef0caf82015-05-03 08:50:53 +02001148 wwn = tf->tf_ops->fabric_make_wwn(tf, group, name);
Andy Grover6708bb22011-06-08 10:36:43 -07001149 if (!wwn || IS_ERR(wwn))
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001150 return ERR_PTR(-EINVAL);
1151
1152 wwn->wwn_tf = tf;
Nicholas Bellinger12d2338422011-03-14 04:06:11 -07001153 /*
1154 * Setup default groups from pre-allocated wwn->wwn_default_groups
1155 */
1156 wwn->wwn_group.default_groups = wwn->wwn_default_groups;
1157 wwn->wwn_group.default_groups[0] = &wwn->fabric_stat_group;
1158 wwn->wwn_group.default_groups[1] = NULL;
1159
Christoph Hellwig968ebe72015-05-03 08:50:55 +02001160 config_group_init_type_name(&wwn->wwn_group, name, &tf->tf_tpg_cit);
Nicholas Bellinger12d2338422011-03-14 04:06:11 -07001161 config_group_init_type_name(&wwn->fabric_stat_group, "fabric_statistics",
Christoph Hellwig968ebe72015-05-03 08:50:55 +02001162 &tf->tf_wwn_fabric_stats_cit);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001163
1164 return &wwn->wwn_group;
1165}
1166
1167static void target_fabric_drop_wwn(
1168 struct config_group *group,
1169 struct config_item *item)
1170{
Nicholas Bellinger12d2338422011-03-14 04:06:11 -07001171 struct se_wwn *wwn = container_of(to_config_group(item),
1172 struct se_wwn, wwn_group);
1173 struct config_item *df_item;
1174 struct config_group *cg = &wwn->wwn_group;
1175 int i;
1176
1177 for (i = 0; cg->default_groups[i]; i++) {
1178 df_item = &cg->default_groups[i]->cg_item;
1179 cg->default_groups[i] = NULL;
1180 config_item_put(df_item);
1181 }
1182
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001183 config_item_put(item);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001184}
1185
1186static struct configfs_group_operations target_fabric_wwn_group_ops = {
1187 .make_group = target_fabric_make_wwn,
1188 .drop_item = target_fabric_drop_wwn,
1189};
1190/*
1191 * For use with TF_WWN_ATTR() and TF_WWN_ATTR_RO()
1192 */
1193CONFIGFS_EATTR_OPS(target_fabric_wwn, target_fabric_configfs, tf_group);
1194
1195static struct configfs_item_operations target_fabric_wwn_item_ops = {
1196 .show_attribute = target_fabric_wwn_attr_show,
1197 .store_attribute = target_fabric_wwn_attr_store,
1198};
1199
Christoph Hellwig9ac89282015-04-08 20:01:35 +02001200TF_CIT_SETUP_DRV(wwn, &target_fabric_wwn_item_ops, &target_fabric_wwn_group_ops);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001201
1202/* End of tfc_wwn_cit */
1203
1204/* Start of tfc_discovery_cit */
1205
1206CONFIGFS_EATTR_OPS(target_fabric_discovery, target_fabric_configfs,
1207 tf_disc_group);
1208
1209static struct configfs_item_operations target_fabric_discovery_item_ops = {
1210 .show_attribute = target_fabric_discovery_attr_show,
1211 .store_attribute = target_fabric_discovery_attr_store,
1212};
1213
Christoph Hellwig9ac89282015-04-08 20:01:35 +02001214TF_CIT_SETUP_DRV(discovery, &target_fabric_discovery_item_ops, NULL);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001215
1216/* End of tfc_discovery_cit */
1217
1218int target_fabric_setup_cits(struct target_fabric_configfs *tf)
1219{
1220 target_fabric_setup_discovery_cit(tf);
1221 target_fabric_setup_wwn_cit(tf);
Nicholas Bellinger12d2338422011-03-14 04:06:11 -07001222 target_fabric_setup_wwn_fabric_stats_cit(tf);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001223 target_fabric_setup_tpg_cit(tf);
1224 target_fabric_setup_tpg_base_cit(tf);
1225 target_fabric_setup_tpg_port_cit(tf);
Nicholas Bellinger12d2338422011-03-14 04:06:11 -07001226 target_fabric_setup_tpg_port_stat_cit(tf);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001227 target_fabric_setup_tpg_lun_cit(tf);
1228 target_fabric_setup_tpg_np_cit(tf);
1229 target_fabric_setup_tpg_np_base_cit(tf);
1230 target_fabric_setup_tpg_attrib_cit(tf);
Nicholas Bellingere4b512e2013-06-19 18:37:00 -07001231 target_fabric_setup_tpg_auth_cit(tf);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001232 target_fabric_setup_tpg_param_cit(tf);
1233 target_fabric_setup_tpg_nacl_cit(tf);
1234 target_fabric_setup_tpg_nacl_base_cit(tf);
1235 target_fabric_setup_tpg_nacl_attrib_cit(tf);
1236 target_fabric_setup_tpg_nacl_auth_cit(tf);
1237 target_fabric_setup_tpg_nacl_param_cit(tf);
Nicholas Bellinger12d2338422011-03-14 04:06:11 -07001238 target_fabric_setup_tpg_nacl_stat_cit(tf);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001239 target_fabric_setup_tpg_mappedlun_cit(tf);
Nicholas Bellinger12d2338422011-03-14 04:06:11 -07001240 target_fabric_setup_tpg_mappedlun_stat_cit(tf);
Nicholas Bellingerc66ac9d2010-12-17 11:11:26 -08001241
1242 return 0;
1243}