Commit fbbf8555a986ed31e54f006b6cc637ea4ff1425b
1 parent
fcf29481fb
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
target: Add missing mapped_lun bounds checking during make_mappedlun setup
This patch adds missing bounds checking for the configfs provided mapped_lun value during target_fabric_make_mappedlun() setup ahead of se_lun_acl initialization. This addresses a potential OOPs when using a mapped_lun value that exceeds the hardcoded TRANSPORT_MAX_LUNS_PER_TPG-1 value within se_node_acl->device_list[]. Reported-by: Jan Engelhardt <jengelh@inai.de> Cc: Jan Engelhardt <jengelh@inai.de> Cc: <stable@vger.kernel.org> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Showing 1 changed file with 8 additions and 0 deletions Inline Diff
drivers/target/target_core_fabric_configfs.c
1 | /******************************************************************************* | 1 | /******************************************************************************* |
2 | * Filename: target_core_fabric_configfs.c | 2 | * Filename: target_core_fabric_configfs.c |
3 | * | 3 | * |
4 | * This file contains generic fabric module configfs infrastructure for | 4 | * This file contains generic fabric module configfs infrastructure for |
5 | * TCM v4.x code | 5 | * TCM v4.x code |
6 | * | 6 | * |
7 | * (c) Copyright 2010-2012 RisingTide Systems LLC. | 7 | * (c) Copyright 2010-2012 RisingTide Systems LLC. |
8 | * | 8 | * |
9 | * Nicholas A. Bellinger <nab@linux-iscsi.org> | 9 | * Nicholas A. Bellinger <nab@linux-iscsi.org> |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 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 | 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 | 13 | * the Free Software Foundation; either version 2 of the License, or |
14 | * (at your option) any later version. | 14 | * (at your option) any later version. |
15 | * | 15 | * |
16 | * This program is distributed in the hope that it will be useful, | 16 | * This program is distributed in the hope that it will be useful, |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | * GNU General Public License for more details. | 19 | * GNU General Public License for more details. |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/moduleparam.h> | 23 | #include <linux/moduleparam.h> |
24 | #include <linux/utsname.h> | 24 | #include <linux/utsname.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
27 | #include <linux/namei.h> | 27 | #include <linux/namei.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | #include <linux/unistd.h> | 31 | #include <linux/unistd.h> |
32 | #include <linux/string.h> | 32 | #include <linux/string.h> |
33 | #include <linux/syscalls.h> | 33 | #include <linux/syscalls.h> |
34 | #include <linux/configfs.h> | 34 | #include <linux/configfs.h> |
35 | 35 | ||
36 | #include <target/target_core_base.h> | 36 | #include <target/target_core_base.h> |
37 | #include <target/target_core_fabric.h> | 37 | #include <target/target_core_fabric.h> |
38 | #include <target/target_core_fabric_configfs.h> | 38 | #include <target/target_core_fabric_configfs.h> |
39 | #include <target/target_core_configfs.h> | 39 | #include <target/target_core_configfs.h> |
40 | #include <target/configfs_macros.h> | 40 | #include <target/configfs_macros.h> |
41 | 41 | ||
42 | #include "target_core_internal.h" | 42 | #include "target_core_internal.h" |
43 | #include "target_core_alua.h" | 43 | #include "target_core_alua.h" |
44 | #include "target_core_pr.h" | 44 | #include "target_core_pr.h" |
45 | 45 | ||
46 | #define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \ | 46 | #define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \ |
47 | static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \ | 47 | static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \ |
48 | { \ | 48 | { \ |
49 | struct target_fabric_configfs_template *tfc = &tf->tf_cit_tmpl; \ | 49 | struct target_fabric_configfs_template *tfc = &tf->tf_cit_tmpl; \ |
50 | struct config_item_type *cit = &tfc->tfc_##_name##_cit; \ | 50 | struct config_item_type *cit = &tfc->tfc_##_name##_cit; \ |
51 | \ | 51 | \ |
52 | cit->ct_item_ops = _item_ops; \ | 52 | cit->ct_item_ops = _item_ops; \ |
53 | cit->ct_group_ops = _group_ops; \ | 53 | cit->ct_group_ops = _group_ops; \ |
54 | cit->ct_attrs = _attrs; \ | 54 | cit->ct_attrs = _attrs; \ |
55 | cit->ct_owner = tf->tf_module; \ | 55 | cit->ct_owner = tf->tf_module; \ |
56 | pr_debug("Setup generic %s\n", __stringify(_name)); \ | 56 | pr_debug("Setup generic %s\n", __stringify(_name)); \ |
57 | } | 57 | } |
58 | 58 | ||
59 | /* Start of tfc_tpg_mappedlun_cit */ | 59 | /* Start of tfc_tpg_mappedlun_cit */ |
60 | 60 | ||
61 | static int target_fabric_mappedlun_link( | 61 | static int target_fabric_mappedlun_link( |
62 | struct config_item *lun_acl_ci, | 62 | struct config_item *lun_acl_ci, |
63 | struct config_item *lun_ci) | 63 | struct config_item *lun_ci) |
64 | { | 64 | { |
65 | struct se_dev_entry *deve; | 65 | struct se_dev_entry *deve; |
66 | struct se_lun *lun = container_of(to_config_group(lun_ci), | 66 | struct se_lun *lun = container_of(to_config_group(lun_ci), |
67 | struct se_lun, lun_group); | 67 | struct se_lun, lun_group); |
68 | struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci), | 68 | struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci), |
69 | struct se_lun_acl, se_lun_group); | 69 | struct se_lun_acl, se_lun_group); |
70 | struct se_portal_group *se_tpg; | 70 | struct se_portal_group *se_tpg; |
71 | struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s; | 71 | struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s; |
72 | int ret = 0, lun_access; | 72 | int ret = 0, lun_access; |
73 | 73 | ||
74 | if (lun->lun_link_magic != SE_LUN_LINK_MAGIC) { | 74 | if (lun->lun_link_magic != SE_LUN_LINK_MAGIC) { |
75 | pr_err("Bad lun->lun_link_magic, not a valid lun_ci pointer:" | 75 | pr_err("Bad lun->lun_link_magic, not a valid lun_ci pointer:" |
76 | " %p to struct lun: %p\n", lun_ci, lun); | 76 | " %p to struct lun: %p\n", lun_ci, lun); |
77 | return -EFAULT; | 77 | return -EFAULT; |
78 | } | 78 | } |
79 | /* | 79 | /* |
80 | * Ensure that the source port exists | 80 | * Ensure that the source port exists |
81 | */ | 81 | */ |
82 | if (!lun->lun_sep || !lun->lun_sep->sep_tpg) { | 82 | if (!lun->lun_sep || !lun->lun_sep->sep_tpg) { |
83 | pr_err("Source se_lun->lun_sep or lun->lun_sep->sep" | 83 | pr_err("Source se_lun->lun_sep or lun->lun_sep->sep" |
84 | "_tpg does not exist\n"); | 84 | "_tpg does not exist\n"); |
85 | return -EINVAL; | 85 | return -EINVAL; |
86 | } | 86 | } |
87 | se_tpg = lun->lun_sep->sep_tpg; | 87 | se_tpg = lun->lun_sep->sep_tpg; |
88 | 88 | ||
89 | nacl_ci = &lun_acl_ci->ci_parent->ci_group->cg_item; | 89 | nacl_ci = &lun_acl_ci->ci_parent->ci_group->cg_item; |
90 | tpg_ci = &nacl_ci->ci_group->cg_item; | 90 | tpg_ci = &nacl_ci->ci_group->cg_item; |
91 | wwn_ci = &tpg_ci->ci_group->cg_item; | 91 | wwn_ci = &tpg_ci->ci_group->cg_item; |
92 | tpg_ci_s = &lun_ci->ci_parent->ci_group->cg_item; | 92 | tpg_ci_s = &lun_ci->ci_parent->ci_group->cg_item; |
93 | wwn_ci_s = &tpg_ci_s->ci_group->cg_item; | 93 | wwn_ci_s = &tpg_ci_s->ci_group->cg_item; |
94 | /* | 94 | /* |
95 | * Make sure the SymLink is going to the same $FABRIC/$WWN/tpgt_$TPGT | 95 | * Make sure the SymLink is going to the same $FABRIC/$WWN/tpgt_$TPGT |
96 | */ | 96 | */ |
97 | if (strcmp(config_item_name(wwn_ci), config_item_name(wwn_ci_s))) { | 97 | if (strcmp(config_item_name(wwn_ci), config_item_name(wwn_ci_s))) { |
98 | pr_err("Illegal Initiator ACL SymLink outside of %s\n", | 98 | pr_err("Illegal Initiator ACL SymLink outside of %s\n", |
99 | config_item_name(wwn_ci)); | 99 | config_item_name(wwn_ci)); |
100 | return -EINVAL; | 100 | return -EINVAL; |
101 | } | 101 | } |
102 | if (strcmp(config_item_name(tpg_ci), config_item_name(tpg_ci_s))) { | 102 | if (strcmp(config_item_name(tpg_ci), config_item_name(tpg_ci_s))) { |
103 | pr_err("Illegal Initiator ACL Symlink outside of %s" | 103 | pr_err("Illegal Initiator ACL Symlink outside of %s" |
104 | " TPGT: %s\n", config_item_name(wwn_ci), | 104 | " TPGT: %s\n", config_item_name(wwn_ci), |
105 | config_item_name(tpg_ci)); | 105 | config_item_name(tpg_ci)); |
106 | return -EINVAL; | 106 | return -EINVAL; |
107 | } | 107 | } |
108 | /* | 108 | /* |
109 | * If this struct se_node_acl was dynamically generated with | 109 | * If this struct se_node_acl was dynamically generated with |
110 | * tpg_1/attrib/generate_node_acls=1, use the existing deve->lun_flags, | 110 | * tpg_1/attrib/generate_node_acls=1, use the existing deve->lun_flags, |
111 | * which be will write protected (READ-ONLY) when | 111 | * which be will write protected (READ-ONLY) when |
112 | * tpg_1/attrib/demo_mode_write_protect=1 | 112 | * tpg_1/attrib/demo_mode_write_protect=1 |
113 | */ | 113 | */ |
114 | spin_lock_irq(&lacl->se_lun_nacl->device_list_lock); | 114 | spin_lock_irq(&lacl->se_lun_nacl->device_list_lock); |
115 | deve = lacl->se_lun_nacl->device_list[lacl->mapped_lun]; | 115 | deve = lacl->se_lun_nacl->device_list[lacl->mapped_lun]; |
116 | if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) | 116 | if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) |
117 | lun_access = deve->lun_flags; | 117 | lun_access = deve->lun_flags; |
118 | else | 118 | else |
119 | lun_access = | 119 | lun_access = |
120 | (se_tpg->se_tpg_tfo->tpg_check_prod_mode_write_protect( | 120 | (se_tpg->se_tpg_tfo->tpg_check_prod_mode_write_protect( |
121 | se_tpg)) ? TRANSPORT_LUNFLAGS_READ_ONLY : | 121 | se_tpg)) ? TRANSPORT_LUNFLAGS_READ_ONLY : |
122 | TRANSPORT_LUNFLAGS_READ_WRITE; | 122 | TRANSPORT_LUNFLAGS_READ_WRITE; |
123 | spin_unlock_irq(&lacl->se_lun_nacl->device_list_lock); | 123 | spin_unlock_irq(&lacl->se_lun_nacl->device_list_lock); |
124 | /* | 124 | /* |
125 | * Determine the actual mapped LUN value user wants.. | 125 | * Determine the actual mapped LUN value user wants.. |
126 | * | 126 | * |
127 | * This value is what the SCSI Initiator actually sees the | 127 | * This value is what the SCSI Initiator actually sees the |
128 | * iscsi/$IQN/$TPGT/lun/lun_* as on their SCSI Initiator Ports. | 128 | * iscsi/$IQN/$TPGT/lun/lun_* as on their SCSI Initiator Ports. |
129 | */ | 129 | */ |
130 | ret = core_dev_add_initiator_node_lun_acl(se_tpg, lacl, | 130 | ret = core_dev_add_initiator_node_lun_acl(se_tpg, lacl, |
131 | lun->unpacked_lun, lun_access); | 131 | lun->unpacked_lun, lun_access); |
132 | 132 | ||
133 | return (ret < 0) ? -EINVAL : 0; | 133 | return (ret < 0) ? -EINVAL : 0; |
134 | } | 134 | } |
135 | 135 | ||
136 | static int target_fabric_mappedlun_unlink( | 136 | static int target_fabric_mappedlun_unlink( |
137 | struct config_item *lun_acl_ci, | 137 | struct config_item *lun_acl_ci, |
138 | struct config_item *lun_ci) | 138 | struct config_item *lun_ci) |
139 | { | 139 | { |
140 | struct se_lun *lun; | 140 | struct se_lun *lun; |
141 | struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci), | 141 | struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci), |
142 | struct se_lun_acl, se_lun_group); | 142 | struct se_lun_acl, se_lun_group); |
143 | struct se_node_acl *nacl = lacl->se_lun_nacl; | 143 | struct se_node_acl *nacl = lacl->se_lun_nacl; |
144 | struct se_dev_entry *deve = nacl->device_list[lacl->mapped_lun]; | 144 | struct se_dev_entry *deve = nacl->device_list[lacl->mapped_lun]; |
145 | struct se_portal_group *se_tpg; | 145 | struct se_portal_group *se_tpg; |
146 | /* | 146 | /* |
147 | * Determine if the underlying MappedLUN has already been released.. | 147 | * Determine if the underlying MappedLUN has already been released.. |
148 | */ | 148 | */ |
149 | if (!deve->se_lun) | 149 | if (!deve->se_lun) |
150 | return 0; | 150 | return 0; |
151 | 151 | ||
152 | lun = container_of(to_config_group(lun_ci), struct se_lun, lun_group); | 152 | lun = container_of(to_config_group(lun_ci), struct se_lun, lun_group); |
153 | se_tpg = lun->lun_sep->sep_tpg; | 153 | se_tpg = lun->lun_sep->sep_tpg; |
154 | 154 | ||
155 | core_dev_del_initiator_node_lun_acl(se_tpg, lun, lacl); | 155 | core_dev_del_initiator_node_lun_acl(se_tpg, lun, lacl); |
156 | return 0; | 156 | return 0; |
157 | } | 157 | } |
158 | 158 | ||
159 | CONFIGFS_EATTR_STRUCT(target_fabric_mappedlun, se_lun_acl); | 159 | CONFIGFS_EATTR_STRUCT(target_fabric_mappedlun, se_lun_acl); |
160 | #define TCM_MAPPEDLUN_ATTR(_name, _mode) \ | 160 | #define TCM_MAPPEDLUN_ATTR(_name, _mode) \ |
161 | static struct target_fabric_mappedlun_attribute target_fabric_mappedlun_##_name = \ | 161 | static struct target_fabric_mappedlun_attribute target_fabric_mappedlun_##_name = \ |
162 | __CONFIGFS_EATTR(_name, _mode, \ | 162 | __CONFIGFS_EATTR(_name, _mode, \ |
163 | target_fabric_mappedlun_show_##_name, \ | 163 | target_fabric_mappedlun_show_##_name, \ |
164 | target_fabric_mappedlun_store_##_name); | 164 | target_fabric_mappedlun_store_##_name); |
165 | 165 | ||
166 | static ssize_t target_fabric_mappedlun_show_write_protect( | 166 | static ssize_t target_fabric_mappedlun_show_write_protect( |
167 | struct se_lun_acl *lacl, | 167 | struct se_lun_acl *lacl, |
168 | char *page) | 168 | char *page) |
169 | { | 169 | { |
170 | struct se_node_acl *se_nacl = lacl->se_lun_nacl; | 170 | struct se_node_acl *se_nacl = lacl->se_lun_nacl; |
171 | struct se_dev_entry *deve; | 171 | struct se_dev_entry *deve; |
172 | ssize_t len; | 172 | ssize_t len; |
173 | 173 | ||
174 | spin_lock_irq(&se_nacl->device_list_lock); | 174 | spin_lock_irq(&se_nacl->device_list_lock); |
175 | deve = se_nacl->device_list[lacl->mapped_lun]; | 175 | deve = se_nacl->device_list[lacl->mapped_lun]; |
176 | len = sprintf(page, "%d\n", | 176 | len = sprintf(page, "%d\n", |
177 | (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) ? | 177 | (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) ? |
178 | 1 : 0); | 178 | 1 : 0); |
179 | spin_unlock_irq(&se_nacl->device_list_lock); | 179 | spin_unlock_irq(&se_nacl->device_list_lock); |
180 | 180 | ||
181 | return len; | 181 | return len; |
182 | } | 182 | } |
183 | 183 | ||
184 | static ssize_t target_fabric_mappedlun_store_write_protect( | 184 | static ssize_t target_fabric_mappedlun_store_write_protect( |
185 | struct se_lun_acl *lacl, | 185 | struct se_lun_acl *lacl, |
186 | const char *page, | 186 | const char *page, |
187 | size_t count) | 187 | size_t count) |
188 | { | 188 | { |
189 | struct se_node_acl *se_nacl = lacl->se_lun_nacl; | 189 | struct se_node_acl *se_nacl = lacl->se_lun_nacl; |
190 | struct se_portal_group *se_tpg = se_nacl->se_tpg; | 190 | struct se_portal_group *se_tpg = se_nacl->se_tpg; |
191 | unsigned long op; | 191 | unsigned long op; |
192 | 192 | ||
193 | if (strict_strtoul(page, 0, &op)) | 193 | if (strict_strtoul(page, 0, &op)) |
194 | return -EINVAL; | 194 | return -EINVAL; |
195 | 195 | ||
196 | if ((op != 1) && (op != 0)) | 196 | if ((op != 1) && (op != 0)) |
197 | return -EINVAL; | 197 | return -EINVAL; |
198 | 198 | ||
199 | core_update_device_list_access(lacl->mapped_lun, (op) ? | 199 | core_update_device_list_access(lacl->mapped_lun, (op) ? |
200 | TRANSPORT_LUNFLAGS_READ_ONLY : | 200 | TRANSPORT_LUNFLAGS_READ_ONLY : |
201 | TRANSPORT_LUNFLAGS_READ_WRITE, | 201 | TRANSPORT_LUNFLAGS_READ_WRITE, |
202 | lacl->se_lun_nacl); | 202 | lacl->se_lun_nacl); |
203 | 203 | ||
204 | pr_debug("%s_ConfigFS: Changed Initiator ACL: %s" | 204 | pr_debug("%s_ConfigFS: Changed Initiator ACL: %s" |
205 | " Mapped LUN: %u Write Protect bit to %s\n", | 205 | " Mapped LUN: %u Write Protect bit to %s\n", |
206 | se_tpg->se_tpg_tfo->get_fabric_name(), | 206 | se_tpg->se_tpg_tfo->get_fabric_name(), |
207 | lacl->initiatorname, lacl->mapped_lun, (op) ? "ON" : "OFF"); | 207 | lacl->initiatorname, lacl->mapped_lun, (op) ? "ON" : "OFF"); |
208 | 208 | ||
209 | return count; | 209 | return count; |
210 | 210 | ||
211 | } | 211 | } |
212 | 212 | ||
213 | TCM_MAPPEDLUN_ATTR(write_protect, S_IRUGO | S_IWUSR); | 213 | TCM_MAPPEDLUN_ATTR(write_protect, S_IRUGO | S_IWUSR); |
214 | 214 | ||
215 | CONFIGFS_EATTR_OPS(target_fabric_mappedlun, se_lun_acl, se_lun_group); | 215 | CONFIGFS_EATTR_OPS(target_fabric_mappedlun, se_lun_acl, se_lun_group); |
216 | 216 | ||
217 | static void target_fabric_mappedlun_release(struct config_item *item) | 217 | static void target_fabric_mappedlun_release(struct config_item *item) |
218 | { | 218 | { |
219 | struct se_lun_acl *lacl = container_of(to_config_group(item), | 219 | struct se_lun_acl *lacl = container_of(to_config_group(item), |
220 | struct se_lun_acl, se_lun_group); | 220 | struct se_lun_acl, se_lun_group); |
221 | struct se_portal_group *se_tpg = lacl->se_lun_nacl->se_tpg; | 221 | struct se_portal_group *se_tpg = lacl->se_lun_nacl->se_tpg; |
222 | 222 | ||
223 | core_dev_free_initiator_node_lun_acl(se_tpg, lacl); | 223 | core_dev_free_initiator_node_lun_acl(se_tpg, lacl); |
224 | } | 224 | } |
225 | 225 | ||
226 | static struct configfs_attribute *target_fabric_mappedlun_attrs[] = { | 226 | static struct configfs_attribute *target_fabric_mappedlun_attrs[] = { |
227 | &target_fabric_mappedlun_write_protect.attr, | 227 | &target_fabric_mappedlun_write_protect.attr, |
228 | NULL, | 228 | NULL, |
229 | }; | 229 | }; |
230 | 230 | ||
231 | static struct configfs_item_operations target_fabric_mappedlun_item_ops = { | 231 | static struct configfs_item_operations target_fabric_mappedlun_item_ops = { |
232 | .release = target_fabric_mappedlun_release, | 232 | .release = target_fabric_mappedlun_release, |
233 | .show_attribute = target_fabric_mappedlun_attr_show, | 233 | .show_attribute = target_fabric_mappedlun_attr_show, |
234 | .store_attribute = target_fabric_mappedlun_attr_store, | 234 | .store_attribute = target_fabric_mappedlun_attr_store, |
235 | .allow_link = target_fabric_mappedlun_link, | 235 | .allow_link = target_fabric_mappedlun_link, |
236 | .drop_link = target_fabric_mappedlun_unlink, | 236 | .drop_link = target_fabric_mappedlun_unlink, |
237 | }; | 237 | }; |
238 | 238 | ||
239 | TF_CIT_SETUP(tpg_mappedlun, &target_fabric_mappedlun_item_ops, NULL, | 239 | TF_CIT_SETUP(tpg_mappedlun, &target_fabric_mappedlun_item_ops, NULL, |
240 | target_fabric_mappedlun_attrs); | 240 | target_fabric_mappedlun_attrs); |
241 | 241 | ||
242 | /* End of tfc_tpg_mappedlun_cit */ | 242 | /* End of tfc_tpg_mappedlun_cit */ |
243 | 243 | ||
244 | /* Start of tfc_tpg_mappedlun_port_cit */ | 244 | /* Start of tfc_tpg_mappedlun_port_cit */ |
245 | 245 | ||
246 | static struct config_group *target_core_mappedlun_stat_mkdir( | 246 | static struct config_group *target_core_mappedlun_stat_mkdir( |
247 | struct config_group *group, | 247 | struct config_group *group, |
248 | const char *name) | 248 | const char *name) |
249 | { | 249 | { |
250 | return ERR_PTR(-ENOSYS); | 250 | return ERR_PTR(-ENOSYS); |
251 | } | 251 | } |
252 | 252 | ||
253 | static void target_core_mappedlun_stat_rmdir( | 253 | static void target_core_mappedlun_stat_rmdir( |
254 | struct config_group *group, | 254 | struct config_group *group, |
255 | struct config_item *item) | 255 | struct config_item *item) |
256 | { | 256 | { |
257 | return; | 257 | return; |
258 | } | 258 | } |
259 | 259 | ||
260 | static struct configfs_group_operations target_fabric_mappedlun_stat_group_ops = { | 260 | static struct configfs_group_operations target_fabric_mappedlun_stat_group_ops = { |
261 | .make_group = target_core_mappedlun_stat_mkdir, | 261 | .make_group = target_core_mappedlun_stat_mkdir, |
262 | .drop_item = target_core_mappedlun_stat_rmdir, | 262 | .drop_item = target_core_mappedlun_stat_rmdir, |
263 | }; | 263 | }; |
264 | 264 | ||
265 | TF_CIT_SETUP(tpg_mappedlun_stat, NULL, &target_fabric_mappedlun_stat_group_ops, | 265 | TF_CIT_SETUP(tpg_mappedlun_stat, NULL, &target_fabric_mappedlun_stat_group_ops, |
266 | NULL); | 266 | NULL); |
267 | 267 | ||
268 | /* End of tfc_tpg_mappedlun_port_cit */ | 268 | /* End of tfc_tpg_mappedlun_port_cit */ |
269 | 269 | ||
270 | /* Start of tfc_tpg_nacl_attrib_cit */ | 270 | /* Start of tfc_tpg_nacl_attrib_cit */ |
271 | 271 | ||
272 | CONFIGFS_EATTR_OPS(target_fabric_nacl_attrib, se_node_acl, acl_attrib_group); | 272 | CONFIGFS_EATTR_OPS(target_fabric_nacl_attrib, se_node_acl, acl_attrib_group); |
273 | 273 | ||
274 | static struct configfs_item_operations target_fabric_nacl_attrib_item_ops = { | 274 | static struct configfs_item_operations target_fabric_nacl_attrib_item_ops = { |
275 | .show_attribute = target_fabric_nacl_attrib_attr_show, | 275 | .show_attribute = target_fabric_nacl_attrib_attr_show, |
276 | .store_attribute = target_fabric_nacl_attrib_attr_store, | 276 | .store_attribute = target_fabric_nacl_attrib_attr_store, |
277 | }; | 277 | }; |
278 | 278 | ||
279 | TF_CIT_SETUP(tpg_nacl_attrib, &target_fabric_nacl_attrib_item_ops, NULL, NULL); | 279 | TF_CIT_SETUP(tpg_nacl_attrib, &target_fabric_nacl_attrib_item_ops, NULL, NULL); |
280 | 280 | ||
281 | /* End of tfc_tpg_nacl_attrib_cit */ | 281 | /* End of tfc_tpg_nacl_attrib_cit */ |
282 | 282 | ||
283 | /* Start of tfc_tpg_nacl_auth_cit */ | 283 | /* Start of tfc_tpg_nacl_auth_cit */ |
284 | 284 | ||
285 | CONFIGFS_EATTR_OPS(target_fabric_nacl_auth, se_node_acl, acl_auth_group); | 285 | CONFIGFS_EATTR_OPS(target_fabric_nacl_auth, se_node_acl, acl_auth_group); |
286 | 286 | ||
287 | static struct configfs_item_operations target_fabric_nacl_auth_item_ops = { | 287 | static struct configfs_item_operations target_fabric_nacl_auth_item_ops = { |
288 | .show_attribute = target_fabric_nacl_auth_attr_show, | 288 | .show_attribute = target_fabric_nacl_auth_attr_show, |
289 | .store_attribute = target_fabric_nacl_auth_attr_store, | 289 | .store_attribute = target_fabric_nacl_auth_attr_store, |
290 | }; | 290 | }; |
291 | 291 | ||
292 | TF_CIT_SETUP(tpg_nacl_auth, &target_fabric_nacl_auth_item_ops, NULL, NULL); | 292 | TF_CIT_SETUP(tpg_nacl_auth, &target_fabric_nacl_auth_item_ops, NULL, NULL); |
293 | 293 | ||
294 | /* End of tfc_tpg_nacl_auth_cit */ | 294 | /* End of tfc_tpg_nacl_auth_cit */ |
295 | 295 | ||
296 | /* Start of tfc_tpg_nacl_param_cit */ | 296 | /* Start of tfc_tpg_nacl_param_cit */ |
297 | 297 | ||
298 | CONFIGFS_EATTR_OPS(target_fabric_nacl_param, se_node_acl, acl_param_group); | 298 | CONFIGFS_EATTR_OPS(target_fabric_nacl_param, se_node_acl, acl_param_group); |
299 | 299 | ||
300 | static struct configfs_item_operations target_fabric_nacl_param_item_ops = { | 300 | static struct configfs_item_operations target_fabric_nacl_param_item_ops = { |
301 | .show_attribute = target_fabric_nacl_param_attr_show, | 301 | .show_attribute = target_fabric_nacl_param_attr_show, |
302 | .store_attribute = target_fabric_nacl_param_attr_store, | 302 | .store_attribute = target_fabric_nacl_param_attr_store, |
303 | }; | 303 | }; |
304 | 304 | ||
305 | TF_CIT_SETUP(tpg_nacl_param, &target_fabric_nacl_param_item_ops, NULL, NULL); | 305 | TF_CIT_SETUP(tpg_nacl_param, &target_fabric_nacl_param_item_ops, NULL, NULL); |
306 | 306 | ||
307 | /* End of tfc_tpg_nacl_param_cit */ | 307 | /* End of tfc_tpg_nacl_param_cit */ |
308 | 308 | ||
309 | /* Start of tfc_tpg_nacl_base_cit */ | 309 | /* Start of tfc_tpg_nacl_base_cit */ |
310 | 310 | ||
311 | CONFIGFS_EATTR_OPS(target_fabric_nacl_base, se_node_acl, acl_group); | 311 | CONFIGFS_EATTR_OPS(target_fabric_nacl_base, se_node_acl, acl_group); |
312 | 312 | ||
313 | static struct config_group *target_fabric_make_mappedlun( | 313 | static struct config_group *target_fabric_make_mappedlun( |
314 | struct config_group *group, | 314 | struct config_group *group, |
315 | const char *name) | 315 | const char *name) |
316 | { | 316 | { |
317 | struct se_node_acl *se_nacl = container_of(group, | 317 | struct se_node_acl *se_nacl = container_of(group, |
318 | struct se_node_acl, acl_group); | 318 | struct se_node_acl, acl_group); |
319 | struct se_portal_group *se_tpg = se_nacl->se_tpg; | 319 | struct se_portal_group *se_tpg = se_nacl->se_tpg; |
320 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; | 320 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; |
321 | struct se_lun_acl *lacl; | 321 | struct se_lun_acl *lacl; |
322 | struct config_item *acl_ci; | 322 | struct config_item *acl_ci; |
323 | struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL; | 323 | struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL; |
324 | char *buf; | 324 | char *buf; |
325 | unsigned long mapped_lun; | 325 | unsigned long mapped_lun; |
326 | int ret = 0; | 326 | int ret = 0; |
327 | 327 | ||
328 | acl_ci = &group->cg_item; | 328 | acl_ci = &group->cg_item; |
329 | if (!acl_ci) { | 329 | if (!acl_ci) { |
330 | pr_err("Unable to locatel acl_ci\n"); | 330 | pr_err("Unable to locatel acl_ci\n"); |
331 | return NULL; | 331 | return NULL; |
332 | } | 332 | } |
333 | 333 | ||
334 | buf = kzalloc(strlen(name) + 1, GFP_KERNEL); | 334 | buf = kzalloc(strlen(name) + 1, GFP_KERNEL); |
335 | if (!buf) { | 335 | if (!buf) { |
336 | pr_err("Unable to allocate memory for name buf\n"); | 336 | pr_err("Unable to allocate memory for name buf\n"); |
337 | return ERR_PTR(-ENOMEM); | 337 | return ERR_PTR(-ENOMEM); |
338 | } | 338 | } |
339 | snprintf(buf, strlen(name) + 1, "%s", name); | 339 | snprintf(buf, strlen(name) + 1, "%s", name); |
340 | /* | 340 | /* |
341 | * Make sure user is creating iscsi/$IQN/$TPGT/acls/$INITIATOR/lun_$ID. | 341 | * Make sure user is creating iscsi/$IQN/$TPGT/acls/$INITIATOR/lun_$ID. |
342 | */ | 342 | */ |
343 | if (strstr(buf, "lun_") != buf) { | 343 | if (strstr(buf, "lun_") != buf) { |
344 | pr_err("Unable to locate \"lun_\" from buf: %s" | 344 | pr_err("Unable to locate \"lun_\" from buf: %s" |
345 | " name: %s\n", buf, name); | 345 | " name: %s\n", buf, name); |
346 | ret = -EINVAL; | 346 | ret = -EINVAL; |
347 | goto out; | 347 | goto out; |
348 | } | 348 | } |
349 | /* | 349 | /* |
350 | * Determine the Mapped LUN value. This is what the SCSI Initiator | 350 | * Determine the Mapped LUN value. This is what the SCSI Initiator |
351 | * Port will actually see. | 351 | * Port will actually see. |
352 | */ | 352 | */ |
353 | if (strict_strtoul(buf + 4, 0, &mapped_lun) || mapped_lun > UINT_MAX) { | 353 | if (strict_strtoul(buf + 4, 0, &mapped_lun) || mapped_lun > UINT_MAX) { |
354 | ret = -EINVAL; | 354 | ret = -EINVAL; |
355 | goto out; | 355 | goto out; |
356 | } | 356 | } |
357 | if (mapped_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) { | ||
358 | pr_err("Mapped LUN: %lu exceeds TRANSPORT_MAX_LUNS_PER_TPG" | ||
359 | "-1: %u for Target Portal Group: %u\n", mapped_lun, | ||
360 | TRANSPORT_MAX_LUNS_PER_TPG-1, | ||
361 | se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg)); | ||
362 | ret = -EINVAL; | ||
363 | goto out; | ||
364 | } | ||
357 | 365 | ||
358 | lacl = core_dev_init_initiator_node_lun_acl(se_tpg, se_nacl, | 366 | lacl = core_dev_init_initiator_node_lun_acl(se_tpg, se_nacl, |
359 | mapped_lun, &ret); | 367 | mapped_lun, &ret); |
360 | if (!lacl) { | 368 | if (!lacl) { |
361 | ret = -EINVAL; | 369 | ret = -EINVAL; |
362 | goto out; | 370 | goto out; |
363 | } | 371 | } |
364 | 372 | ||
365 | lacl_cg = &lacl->se_lun_group; | 373 | lacl_cg = &lacl->se_lun_group; |
366 | lacl_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, | 374 | lacl_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, |
367 | GFP_KERNEL); | 375 | GFP_KERNEL); |
368 | if (!lacl_cg->default_groups) { | 376 | if (!lacl_cg->default_groups) { |
369 | pr_err("Unable to allocate lacl_cg->default_groups\n"); | 377 | pr_err("Unable to allocate lacl_cg->default_groups\n"); |
370 | ret = -ENOMEM; | 378 | ret = -ENOMEM; |
371 | goto out; | 379 | goto out; |
372 | } | 380 | } |
373 | 381 | ||
374 | config_group_init_type_name(&lacl->se_lun_group, name, | 382 | config_group_init_type_name(&lacl->se_lun_group, name, |
375 | &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_cit); | 383 | &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_cit); |
376 | config_group_init_type_name(&lacl->ml_stat_grps.stat_group, | 384 | config_group_init_type_name(&lacl->ml_stat_grps.stat_group, |
377 | "statistics", &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_stat_cit); | 385 | "statistics", &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_stat_cit); |
378 | lacl_cg->default_groups[0] = &lacl->ml_stat_grps.stat_group; | 386 | lacl_cg->default_groups[0] = &lacl->ml_stat_grps.stat_group; |
379 | lacl_cg->default_groups[1] = NULL; | 387 | lacl_cg->default_groups[1] = NULL; |
380 | 388 | ||
381 | ml_stat_grp = &lacl->ml_stat_grps.stat_group; | 389 | ml_stat_grp = &lacl->ml_stat_grps.stat_group; |
382 | ml_stat_grp->default_groups = kmalloc(sizeof(struct config_group *) * 3, | 390 | ml_stat_grp->default_groups = kmalloc(sizeof(struct config_group *) * 3, |
383 | GFP_KERNEL); | 391 | GFP_KERNEL); |
384 | if (!ml_stat_grp->default_groups) { | 392 | if (!ml_stat_grp->default_groups) { |
385 | pr_err("Unable to allocate ml_stat_grp->default_groups\n"); | 393 | pr_err("Unable to allocate ml_stat_grp->default_groups\n"); |
386 | ret = -ENOMEM; | 394 | ret = -ENOMEM; |
387 | goto out; | 395 | goto out; |
388 | } | 396 | } |
389 | target_stat_setup_mappedlun_default_groups(lacl); | 397 | target_stat_setup_mappedlun_default_groups(lacl); |
390 | 398 | ||
391 | kfree(buf); | 399 | kfree(buf); |
392 | return &lacl->se_lun_group; | 400 | return &lacl->se_lun_group; |
393 | out: | 401 | out: |
394 | if (lacl_cg) | 402 | if (lacl_cg) |
395 | kfree(lacl_cg->default_groups); | 403 | kfree(lacl_cg->default_groups); |
396 | kfree(buf); | 404 | kfree(buf); |
397 | return ERR_PTR(ret); | 405 | return ERR_PTR(ret); |
398 | } | 406 | } |
399 | 407 | ||
400 | static void target_fabric_drop_mappedlun( | 408 | static void target_fabric_drop_mappedlun( |
401 | struct config_group *group, | 409 | struct config_group *group, |
402 | struct config_item *item) | 410 | struct config_item *item) |
403 | { | 411 | { |
404 | struct se_lun_acl *lacl = container_of(to_config_group(item), | 412 | struct se_lun_acl *lacl = container_of(to_config_group(item), |
405 | struct se_lun_acl, se_lun_group); | 413 | struct se_lun_acl, se_lun_group); |
406 | struct config_item *df_item; | 414 | struct config_item *df_item; |
407 | struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL; | 415 | struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL; |
408 | int i; | 416 | int i; |
409 | 417 | ||
410 | ml_stat_grp = &lacl->ml_stat_grps.stat_group; | 418 | ml_stat_grp = &lacl->ml_stat_grps.stat_group; |
411 | for (i = 0; ml_stat_grp->default_groups[i]; i++) { | 419 | for (i = 0; ml_stat_grp->default_groups[i]; i++) { |
412 | df_item = &ml_stat_grp->default_groups[i]->cg_item; | 420 | df_item = &ml_stat_grp->default_groups[i]->cg_item; |
413 | ml_stat_grp->default_groups[i] = NULL; | 421 | ml_stat_grp->default_groups[i] = NULL; |
414 | config_item_put(df_item); | 422 | config_item_put(df_item); |
415 | } | 423 | } |
416 | kfree(ml_stat_grp->default_groups); | 424 | kfree(ml_stat_grp->default_groups); |
417 | 425 | ||
418 | lacl_cg = &lacl->se_lun_group; | 426 | lacl_cg = &lacl->se_lun_group; |
419 | for (i = 0; lacl_cg->default_groups[i]; i++) { | 427 | for (i = 0; lacl_cg->default_groups[i]; i++) { |
420 | df_item = &lacl_cg->default_groups[i]->cg_item; | 428 | df_item = &lacl_cg->default_groups[i]->cg_item; |
421 | lacl_cg->default_groups[i] = NULL; | 429 | lacl_cg->default_groups[i] = NULL; |
422 | config_item_put(df_item); | 430 | config_item_put(df_item); |
423 | } | 431 | } |
424 | kfree(lacl_cg->default_groups); | 432 | kfree(lacl_cg->default_groups); |
425 | 433 | ||
426 | config_item_put(item); | 434 | config_item_put(item); |
427 | } | 435 | } |
428 | 436 | ||
429 | static void target_fabric_nacl_base_release(struct config_item *item) | 437 | static void target_fabric_nacl_base_release(struct config_item *item) |
430 | { | 438 | { |
431 | struct se_node_acl *se_nacl = container_of(to_config_group(item), | 439 | struct se_node_acl *se_nacl = container_of(to_config_group(item), |
432 | struct se_node_acl, acl_group); | 440 | struct se_node_acl, acl_group); |
433 | struct se_portal_group *se_tpg = se_nacl->se_tpg; | 441 | struct se_portal_group *se_tpg = se_nacl->se_tpg; |
434 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; | 442 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; |
435 | 443 | ||
436 | tf->tf_ops.fabric_drop_nodeacl(se_nacl); | 444 | tf->tf_ops.fabric_drop_nodeacl(se_nacl); |
437 | } | 445 | } |
438 | 446 | ||
439 | static struct configfs_item_operations target_fabric_nacl_base_item_ops = { | 447 | static struct configfs_item_operations target_fabric_nacl_base_item_ops = { |
440 | .release = target_fabric_nacl_base_release, | 448 | .release = target_fabric_nacl_base_release, |
441 | .show_attribute = target_fabric_nacl_base_attr_show, | 449 | .show_attribute = target_fabric_nacl_base_attr_show, |
442 | .store_attribute = target_fabric_nacl_base_attr_store, | 450 | .store_attribute = target_fabric_nacl_base_attr_store, |
443 | }; | 451 | }; |
444 | 452 | ||
445 | static struct configfs_group_operations target_fabric_nacl_base_group_ops = { | 453 | static struct configfs_group_operations target_fabric_nacl_base_group_ops = { |
446 | .make_group = target_fabric_make_mappedlun, | 454 | .make_group = target_fabric_make_mappedlun, |
447 | .drop_item = target_fabric_drop_mappedlun, | 455 | .drop_item = target_fabric_drop_mappedlun, |
448 | }; | 456 | }; |
449 | 457 | ||
450 | TF_CIT_SETUP(tpg_nacl_base, &target_fabric_nacl_base_item_ops, | 458 | TF_CIT_SETUP(tpg_nacl_base, &target_fabric_nacl_base_item_ops, |
451 | &target_fabric_nacl_base_group_ops, NULL); | 459 | &target_fabric_nacl_base_group_ops, NULL); |
452 | 460 | ||
453 | /* End of tfc_tpg_nacl_base_cit */ | 461 | /* End of tfc_tpg_nacl_base_cit */ |
454 | 462 | ||
455 | /* Start of tfc_node_fabric_stats_cit */ | 463 | /* Start of tfc_node_fabric_stats_cit */ |
456 | /* | 464 | /* |
457 | * This is used as a placeholder for struct se_node_acl->acl_fabric_stat_group | 465 | * This is used as a placeholder for struct se_node_acl->acl_fabric_stat_group |
458 | * to allow fabrics access to ->acl_fabric_stat_group->default_groups[] | 466 | * to allow fabrics access to ->acl_fabric_stat_group->default_groups[] |
459 | */ | 467 | */ |
460 | TF_CIT_SETUP(tpg_nacl_stat, NULL, NULL, NULL); | 468 | TF_CIT_SETUP(tpg_nacl_stat, NULL, NULL, NULL); |
461 | 469 | ||
462 | /* End of tfc_wwn_fabric_stats_cit */ | 470 | /* End of tfc_wwn_fabric_stats_cit */ |
463 | 471 | ||
464 | /* Start of tfc_tpg_nacl_cit */ | 472 | /* Start of tfc_tpg_nacl_cit */ |
465 | 473 | ||
466 | static struct config_group *target_fabric_make_nodeacl( | 474 | static struct config_group *target_fabric_make_nodeacl( |
467 | struct config_group *group, | 475 | struct config_group *group, |
468 | const char *name) | 476 | const char *name) |
469 | { | 477 | { |
470 | struct se_portal_group *se_tpg = container_of(group, | 478 | struct se_portal_group *se_tpg = container_of(group, |
471 | struct se_portal_group, tpg_acl_group); | 479 | struct se_portal_group, tpg_acl_group); |
472 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; | 480 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; |
473 | struct se_node_acl *se_nacl; | 481 | struct se_node_acl *se_nacl; |
474 | struct config_group *nacl_cg; | 482 | struct config_group *nacl_cg; |
475 | 483 | ||
476 | if (!tf->tf_ops.fabric_make_nodeacl) { | 484 | if (!tf->tf_ops.fabric_make_nodeacl) { |
477 | pr_err("tf->tf_ops.fabric_make_nodeacl is NULL\n"); | 485 | pr_err("tf->tf_ops.fabric_make_nodeacl is NULL\n"); |
478 | return ERR_PTR(-ENOSYS); | 486 | return ERR_PTR(-ENOSYS); |
479 | } | 487 | } |
480 | 488 | ||
481 | se_nacl = tf->tf_ops.fabric_make_nodeacl(se_tpg, group, name); | 489 | se_nacl = tf->tf_ops.fabric_make_nodeacl(se_tpg, group, name); |
482 | if (IS_ERR(se_nacl)) | 490 | if (IS_ERR(se_nacl)) |
483 | return ERR_CAST(se_nacl); | 491 | return ERR_CAST(se_nacl); |
484 | 492 | ||
485 | nacl_cg = &se_nacl->acl_group; | 493 | nacl_cg = &se_nacl->acl_group; |
486 | nacl_cg->default_groups = se_nacl->acl_default_groups; | 494 | nacl_cg->default_groups = se_nacl->acl_default_groups; |
487 | nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group; | 495 | nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group; |
488 | nacl_cg->default_groups[1] = &se_nacl->acl_auth_group; | 496 | nacl_cg->default_groups[1] = &se_nacl->acl_auth_group; |
489 | nacl_cg->default_groups[2] = &se_nacl->acl_param_group; | 497 | nacl_cg->default_groups[2] = &se_nacl->acl_param_group; |
490 | nacl_cg->default_groups[3] = &se_nacl->acl_fabric_stat_group; | 498 | nacl_cg->default_groups[3] = &se_nacl->acl_fabric_stat_group; |
491 | nacl_cg->default_groups[4] = NULL; | 499 | nacl_cg->default_groups[4] = NULL; |
492 | 500 | ||
493 | config_group_init_type_name(&se_nacl->acl_group, name, | 501 | config_group_init_type_name(&se_nacl->acl_group, name, |
494 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_base_cit); | 502 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_base_cit); |
495 | config_group_init_type_name(&se_nacl->acl_attrib_group, "attrib", | 503 | config_group_init_type_name(&se_nacl->acl_attrib_group, "attrib", |
496 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_attrib_cit); | 504 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_attrib_cit); |
497 | config_group_init_type_name(&se_nacl->acl_auth_group, "auth", | 505 | config_group_init_type_name(&se_nacl->acl_auth_group, "auth", |
498 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_auth_cit); | 506 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_auth_cit); |
499 | config_group_init_type_name(&se_nacl->acl_param_group, "param", | 507 | config_group_init_type_name(&se_nacl->acl_param_group, "param", |
500 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_param_cit); | 508 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_param_cit); |
501 | config_group_init_type_name(&se_nacl->acl_fabric_stat_group, | 509 | config_group_init_type_name(&se_nacl->acl_fabric_stat_group, |
502 | "fabric_statistics", | 510 | "fabric_statistics", |
503 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_stat_cit); | 511 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_stat_cit); |
504 | 512 | ||
505 | return &se_nacl->acl_group; | 513 | return &se_nacl->acl_group; |
506 | } | 514 | } |
507 | 515 | ||
508 | static void target_fabric_drop_nodeacl( | 516 | static void target_fabric_drop_nodeacl( |
509 | struct config_group *group, | 517 | struct config_group *group, |
510 | struct config_item *item) | 518 | struct config_item *item) |
511 | { | 519 | { |
512 | struct se_node_acl *se_nacl = container_of(to_config_group(item), | 520 | struct se_node_acl *se_nacl = container_of(to_config_group(item), |
513 | struct se_node_acl, acl_group); | 521 | struct se_node_acl, acl_group); |
514 | struct config_item *df_item; | 522 | struct config_item *df_item; |
515 | struct config_group *nacl_cg; | 523 | struct config_group *nacl_cg; |
516 | int i; | 524 | int i; |
517 | 525 | ||
518 | nacl_cg = &se_nacl->acl_group; | 526 | nacl_cg = &se_nacl->acl_group; |
519 | for (i = 0; nacl_cg->default_groups[i]; i++) { | 527 | for (i = 0; nacl_cg->default_groups[i]; i++) { |
520 | df_item = &nacl_cg->default_groups[i]->cg_item; | 528 | df_item = &nacl_cg->default_groups[i]->cg_item; |
521 | nacl_cg->default_groups[i] = NULL; | 529 | nacl_cg->default_groups[i] = NULL; |
522 | config_item_put(df_item); | 530 | config_item_put(df_item); |
523 | } | 531 | } |
524 | /* | 532 | /* |
525 | * struct se_node_acl free is done in target_fabric_nacl_base_release() | 533 | * struct se_node_acl free is done in target_fabric_nacl_base_release() |
526 | */ | 534 | */ |
527 | config_item_put(item); | 535 | config_item_put(item); |
528 | } | 536 | } |
529 | 537 | ||
530 | static struct configfs_group_operations target_fabric_nacl_group_ops = { | 538 | static struct configfs_group_operations target_fabric_nacl_group_ops = { |
531 | .make_group = target_fabric_make_nodeacl, | 539 | .make_group = target_fabric_make_nodeacl, |
532 | .drop_item = target_fabric_drop_nodeacl, | 540 | .drop_item = target_fabric_drop_nodeacl, |
533 | }; | 541 | }; |
534 | 542 | ||
535 | TF_CIT_SETUP(tpg_nacl, NULL, &target_fabric_nacl_group_ops, NULL); | 543 | TF_CIT_SETUP(tpg_nacl, NULL, &target_fabric_nacl_group_ops, NULL); |
536 | 544 | ||
537 | /* End of tfc_tpg_nacl_cit */ | 545 | /* End of tfc_tpg_nacl_cit */ |
538 | 546 | ||
539 | /* Start of tfc_tpg_np_base_cit */ | 547 | /* Start of tfc_tpg_np_base_cit */ |
540 | 548 | ||
541 | CONFIGFS_EATTR_OPS(target_fabric_np_base, se_tpg_np, tpg_np_group); | 549 | CONFIGFS_EATTR_OPS(target_fabric_np_base, se_tpg_np, tpg_np_group); |
542 | 550 | ||
543 | static void target_fabric_np_base_release(struct config_item *item) | 551 | static void target_fabric_np_base_release(struct config_item *item) |
544 | { | 552 | { |
545 | struct se_tpg_np *se_tpg_np = container_of(to_config_group(item), | 553 | struct se_tpg_np *se_tpg_np = container_of(to_config_group(item), |
546 | struct se_tpg_np, tpg_np_group); | 554 | struct se_tpg_np, tpg_np_group); |
547 | struct se_portal_group *se_tpg = se_tpg_np->tpg_np_parent; | 555 | struct se_portal_group *se_tpg = se_tpg_np->tpg_np_parent; |
548 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; | 556 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; |
549 | 557 | ||
550 | tf->tf_ops.fabric_drop_np(se_tpg_np); | 558 | tf->tf_ops.fabric_drop_np(se_tpg_np); |
551 | } | 559 | } |
552 | 560 | ||
553 | static struct configfs_item_operations target_fabric_np_base_item_ops = { | 561 | static struct configfs_item_operations target_fabric_np_base_item_ops = { |
554 | .release = target_fabric_np_base_release, | 562 | .release = target_fabric_np_base_release, |
555 | .show_attribute = target_fabric_np_base_attr_show, | 563 | .show_attribute = target_fabric_np_base_attr_show, |
556 | .store_attribute = target_fabric_np_base_attr_store, | 564 | .store_attribute = target_fabric_np_base_attr_store, |
557 | }; | 565 | }; |
558 | 566 | ||
559 | TF_CIT_SETUP(tpg_np_base, &target_fabric_np_base_item_ops, NULL, NULL); | 567 | TF_CIT_SETUP(tpg_np_base, &target_fabric_np_base_item_ops, NULL, NULL); |
560 | 568 | ||
561 | /* End of tfc_tpg_np_base_cit */ | 569 | /* End of tfc_tpg_np_base_cit */ |
562 | 570 | ||
563 | /* Start of tfc_tpg_np_cit */ | 571 | /* Start of tfc_tpg_np_cit */ |
564 | 572 | ||
565 | static struct config_group *target_fabric_make_np( | 573 | static struct config_group *target_fabric_make_np( |
566 | struct config_group *group, | 574 | struct config_group *group, |
567 | const char *name) | 575 | const char *name) |
568 | { | 576 | { |
569 | struct se_portal_group *se_tpg = container_of(group, | 577 | struct se_portal_group *se_tpg = container_of(group, |
570 | struct se_portal_group, tpg_np_group); | 578 | struct se_portal_group, tpg_np_group); |
571 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; | 579 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; |
572 | struct se_tpg_np *se_tpg_np; | 580 | struct se_tpg_np *se_tpg_np; |
573 | 581 | ||
574 | if (!tf->tf_ops.fabric_make_np) { | 582 | if (!tf->tf_ops.fabric_make_np) { |
575 | pr_err("tf->tf_ops.fabric_make_np is NULL\n"); | 583 | pr_err("tf->tf_ops.fabric_make_np is NULL\n"); |
576 | return ERR_PTR(-ENOSYS); | 584 | return ERR_PTR(-ENOSYS); |
577 | } | 585 | } |
578 | 586 | ||
579 | se_tpg_np = tf->tf_ops.fabric_make_np(se_tpg, group, name); | 587 | se_tpg_np = tf->tf_ops.fabric_make_np(se_tpg, group, name); |
580 | if (!se_tpg_np || IS_ERR(se_tpg_np)) | 588 | if (!se_tpg_np || IS_ERR(se_tpg_np)) |
581 | return ERR_PTR(-EINVAL); | 589 | return ERR_PTR(-EINVAL); |
582 | 590 | ||
583 | se_tpg_np->tpg_np_parent = se_tpg; | 591 | se_tpg_np->tpg_np_parent = se_tpg; |
584 | config_group_init_type_name(&se_tpg_np->tpg_np_group, name, | 592 | config_group_init_type_name(&se_tpg_np->tpg_np_group, name, |
585 | &TF_CIT_TMPL(tf)->tfc_tpg_np_base_cit); | 593 | &TF_CIT_TMPL(tf)->tfc_tpg_np_base_cit); |
586 | 594 | ||
587 | return &se_tpg_np->tpg_np_group; | 595 | return &se_tpg_np->tpg_np_group; |
588 | } | 596 | } |
589 | 597 | ||
590 | static void target_fabric_drop_np( | 598 | static void target_fabric_drop_np( |
591 | struct config_group *group, | 599 | struct config_group *group, |
592 | struct config_item *item) | 600 | struct config_item *item) |
593 | { | 601 | { |
594 | /* | 602 | /* |
595 | * struct se_tpg_np is released via target_fabric_np_base_release() | 603 | * struct se_tpg_np is released via target_fabric_np_base_release() |
596 | */ | 604 | */ |
597 | config_item_put(item); | 605 | config_item_put(item); |
598 | } | 606 | } |
599 | 607 | ||
600 | static struct configfs_group_operations target_fabric_np_group_ops = { | 608 | static struct configfs_group_operations target_fabric_np_group_ops = { |
601 | .make_group = &target_fabric_make_np, | 609 | .make_group = &target_fabric_make_np, |
602 | .drop_item = &target_fabric_drop_np, | 610 | .drop_item = &target_fabric_drop_np, |
603 | }; | 611 | }; |
604 | 612 | ||
605 | TF_CIT_SETUP(tpg_np, NULL, &target_fabric_np_group_ops, NULL); | 613 | TF_CIT_SETUP(tpg_np, NULL, &target_fabric_np_group_ops, NULL); |
606 | 614 | ||
607 | /* End of tfc_tpg_np_cit */ | 615 | /* End of tfc_tpg_np_cit */ |
608 | 616 | ||
609 | /* Start of tfc_tpg_port_cit */ | 617 | /* Start of tfc_tpg_port_cit */ |
610 | 618 | ||
611 | CONFIGFS_EATTR_STRUCT(target_fabric_port, se_lun); | 619 | CONFIGFS_EATTR_STRUCT(target_fabric_port, se_lun); |
612 | #define TCM_PORT_ATTR(_name, _mode) \ | 620 | #define TCM_PORT_ATTR(_name, _mode) \ |
613 | static struct target_fabric_port_attribute target_fabric_port_##_name = \ | 621 | static struct target_fabric_port_attribute target_fabric_port_##_name = \ |
614 | __CONFIGFS_EATTR(_name, _mode, \ | 622 | __CONFIGFS_EATTR(_name, _mode, \ |
615 | target_fabric_port_show_attr_##_name, \ | 623 | target_fabric_port_show_attr_##_name, \ |
616 | target_fabric_port_store_attr_##_name); | 624 | target_fabric_port_store_attr_##_name); |
617 | 625 | ||
618 | #define TCM_PORT_ATTOR_RO(_name) \ | 626 | #define TCM_PORT_ATTOR_RO(_name) \ |
619 | __CONFIGFS_EATTR_RO(_name, \ | 627 | __CONFIGFS_EATTR_RO(_name, \ |
620 | target_fabric_port_show_attr_##_name); | 628 | target_fabric_port_show_attr_##_name); |
621 | 629 | ||
622 | /* | 630 | /* |
623 | * alua_tg_pt_gp | 631 | * alua_tg_pt_gp |
624 | */ | 632 | */ |
625 | static ssize_t target_fabric_port_show_attr_alua_tg_pt_gp( | 633 | static ssize_t target_fabric_port_show_attr_alua_tg_pt_gp( |
626 | struct se_lun *lun, | 634 | struct se_lun *lun, |
627 | char *page) | 635 | char *page) |
628 | { | 636 | { |
629 | if (!lun || !lun->lun_sep) | 637 | if (!lun || !lun->lun_sep) |
630 | return -ENODEV; | 638 | return -ENODEV; |
631 | 639 | ||
632 | return core_alua_show_tg_pt_gp_info(lun->lun_sep, page); | 640 | return core_alua_show_tg_pt_gp_info(lun->lun_sep, page); |
633 | } | 641 | } |
634 | 642 | ||
635 | static ssize_t target_fabric_port_store_attr_alua_tg_pt_gp( | 643 | static ssize_t target_fabric_port_store_attr_alua_tg_pt_gp( |
636 | struct se_lun *lun, | 644 | struct se_lun *lun, |
637 | const char *page, | 645 | const char *page, |
638 | size_t count) | 646 | size_t count) |
639 | { | 647 | { |
640 | if (!lun || !lun->lun_sep) | 648 | if (!lun || !lun->lun_sep) |
641 | return -ENODEV; | 649 | return -ENODEV; |
642 | 650 | ||
643 | return core_alua_store_tg_pt_gp_info(lun->lun_sep, page, count); | 651 | return core_alua_store_tg_pt_gp_info(lun->lun_sep, page, count); |
644 | } | 652 | } |
645 | 653 | ||
646 | TCM_PORT_ATTR(alua_tg_pt_gp, S_IRUGO | S_IWUSR); | 654 | TCM_PORT_ATTR(alua_tg_pt_gp, S_IRUGO | S_IWUSR); |
647 | 655 | ||
648 | /* | 656 | /* |
649 | * alua_tg_pt_offline | 657 | * alua_tg_pt_offline |
650 | */ | 658 | */ |
651 | static ssize_t target_fabric_port_show_attr_alua_tg_pt_offline( | 659 | static ssize_t target_fabric_port_show_attr_alua_tg_pt_offline( |
652 | struct se_lun *lun, | 660 | struct se_lun *lun, |
653 | char *page) | 661 | char *page) |
654 | { | 662 | { |
655 | if (!lun || !lun->lun_sep) | 663 | if (!lun || !lun->lun_sep) |
656 | return -ENODEV; | 664 | return -ENODEV; |
657 | 665 | ||
658 | return core_alua_show_offline_bit(lun, page); | 666 | return core_alua_show_offline_bit(lun, page); |
659 | } | 667 | } |
660 | 668 | ||
661 | static ssize_t target_fabric_port_store_attr_alua_tg_pt_offline( | 669 | static ssize_t target_fabric_port_store_attr_alua_tg_pt_offline( |
662 | struct se_lun *lun, | 670 | struct se_lun *lun, |
663 | const char *page, | 671 | const char *page, |
664 | size_t count) | 672 | size_t count) |
665 | { | 673 | { |
666 | if (!lun || !lun->lun_sep) | 674 | if (!lun || !lun->lun_sep) |
667 | return -ENODEV; | 675 | return -ENODEV; |
668 | 676 | ||
669 | return core_alua_store_offline_bit(lun, page, count); | 677 | return core_alua_store_offline_bit(lun, page, count); |
670 | } | 678 | } |
671 | 679 | ||
672 | TCM_PORT_ATTR(alua_tg_pt_offline, S_IRUGO | S_IWUSR); | 680 | TCM_PORT_ATTR(alua_tg_pt_offline, S_IRUGO | S_IWUSR); |
673 | 681 | ||
674 | /* | 682 | /* |
675 | * alua_tg_pt_status | 683 | * alua_tg_pt_status |
676 | */ | 684 | */ |
677 | static ssize_t target_fabric_port_show_attr_alua_tg_pt_status( | 685 | static ssize_t target_fabric_port_show_attr_alua_tg_pt_status( |
678 | struct se_lun *lun, | 686 | struct se_lun *lun, |
679 | char *page) | 687 | char *page) |
680 | { | 688 | { |
681 | if (!lun || !lun->lun_sep) | 689 | if (!lun || !lun->lun_sep) |
682 | return -ENODEV; | 690 | return -ENODEV; |
683 | 691 | ||
684 | return core_alua_show_secondary_status(lun, page); | 692 | return core_alua_show_secondary_status(lun, page); |
685 | } | 693 | } |
686 | 694 | ||
687 | static ssize_t target_fabric_port_store_attr_alua_tg_pt_status( | 695 | static ssize_t target_fabric_port_store_attr_alua_tg_pt_status( |
688 | struct se_lun *lun, | 696 | struct se_lun *lun, |
689 | const char *page, | 697 | const char *page, |
690 | size_t count) | 698 | size_t count) |
691 | { | 699 | { |
692 | if (!lun || !lun->lun_sep) | 700 | if (!lun || !lun->lun_sep) |
693 | return -ENODEV; | 701 | return -ENODEV; |
694 | 702 | ||
695 | return core_alua_store_secondary_status(lun, page, count); | 703 | return core_alua_store_secondary_status(lun, page, count); |
696 | } | 704 | } |
697 | 705 | ||
698 | TCM_PORT_ATTR(alua_tg_pt_status, S_IRUGO | S_IWUSR); | 706 | TCM_PORT_ATTR(alua_tg_pt_status, S_IRUGO | S_IWUSR); |
699 | 707 | ||
700 | /* | 708 | /* |
701 | * alua_tg_pt_write_md | 709 | * alua_tg_pt_write_md |
702 | */ | 710 | */ |
703 | static ssize_t target_fabric_port_show_attr_alua_tg_pt_write_md( | 711 | static ssize_t target_fabric_port_show_attr_alua_tg_pt_write_md( |
704 | struct se_lun *lun, | 712 | struct se_lun *lun, |
705 | char *page) | 713 | char *page) |
706 | { | 714 | { |
707 | if (!lun || !lun->lun_sep) | 715 | if (!lun || !lun->lun_sep) |
708 | return -ENODEV; | 716 | return -ENODEV; |
709 | 717 | ||
710 | return core_alua_show_secondary_write_metadata(lun, page); | 718 | return core_alua_show_secondary_write_metadata(lun, page); |
711 | } | 719 | } |
712 | 720 | ||
713 | static ssize_t target_fabric_port_store_attr_alua_tg_pt_write_md( | 721 | static ssize_t target_fabric_port_store_attr_alua_tg_pt_write_md( |
714 | struct se_lun *lun, | 722 | struct se_lun *lun, |
715 | const char *page, | 723 | const char *page, |
716 | size_t count) | 724 | size_t count) |
717 | { | 725 | { |
718 | if (!lun || !lun->lun_sep) | 726 | if (!lun || !lun->lun_sep) |
719 | return -ENODEV; | 727 | return -ENODEV; |
720 | 728 | ||
721 | return core_alua_store_secondary_write_metadata(lun, page, count); | 729 | return core_alua_store_secondary_write_metadata(lun, page, count); |
722 | } | 730 | } |
723 | 731 | ||
724 | TCM_PORT_ATTR(alua_tg_pt_write_md, S_IRUGO | S_IWUSR); | 732 | TCM_PORT_ATTR(alua_tg_pt_write_md, S_IRUGO | S_IWUSR); |
725 | 733 | ||
726 | 734 | ||
727 | static struct configfs_attribute *target_fabric_port_attrs[] = { | 735 | static struct configfs_attribute *target_fabric_port_attrs[] = { |
728 | &target_fabric_port_alua_tg_pt_gp.attr, | 736 | &target_fabric_port_alua_tg_pt_gp.attr, |
729 | &target_fabric_port_alua_tg_pt_offline.attr, | 737 | &target_fabric_port_alua_tg_pt_offline.attr, |
730 | &target_fabric_port_alua_tg_pt_status.attr, | 738 | &target_fabric_port_alua_tg_pt_status.attr, |
731 | &target_fabric_port_alua_tg_pt_write_md.attr, | 739 | &target_fabric_port_alua_tg_pt_write_md.attr, |
732 | NULL, | 740 | NULL, |
733 | }; | 741 | }; |
734 | 742 | ||
735 | CONFIGFS_EATTR_OPS(target_fabric_port, se_lun, lun_group); | 743 | CONFIGFS_EATTR_OPS(target_fabric_port, se_lun, lun_group); |
736 | 744 | ||
737 | static int target_fabric_port_link( | 745 | static int target_fabric_port_link( |
738 | struct config_item *lun_ci, | 746 | struct config_item *lun_ci, |
739 | struct config_item *se_dev_ci) | 747 | struct config_item *se_dev_ci) |
740 | { | 748 | { |
741 | struct config_item *tpg_ci; | 749 | struct config_item *tpg_ci; |
742 | struct se_lun *lun = container_of(to_config_group(lun_ci), | 750 | struct se_lun *lun = container_of(to_config_group(lun_ci), |
743 | struct se_lun, lun_group); | 751 | struct se_lun, lun_group); |
744 | struct se_lun *lun_p; | 752 | struct se_lun *lun_p; |
745 | struct se_portal_group *se_tpg; | 753 | struct se_portal_group *se_tpg; |
746 | struct se_device *dev = | 754 | struct se_device *dev = |
747 | container_of(to_config_group(se_dev_ci), struct se_device, dev_group); | 755 | container_of(to_config_group(se_dev_ci), struct se_device, dev_group); |
748 | struct target_fabric_configfs *tf; | 756 | struct target_fabric_configfs *tf; |
749 | int ret; | 757 | int ret; |
750 | 758 | ||
751 | if (dev->dev_link_magic != SE_DEV_LINK_MAGIC) { | 759 | if (dev->dev_link_magic != SE_DEV_LINK_MAGIC) { |
752 | pr_err("Bad dev->dev_link_magic, not a valid se_dev_ci pointer:" | 760 | pr_err("Bad dev->dev_link_magic, not a valid se_dev_ci pointer:" |
753 | " %p to struct se_device: %p\n", se_dev_ci, dev); | 761 | " %p to struct se_device: %p\n", se_dev_ci, dev); |
754 | return -EFAULT; | 762 | return -EFAULT; |
755 | } | 763 | } |
756 | 764 | ||
757 | if (!(dev->dev_flags & DF_CONFIGURED)) { | 765 | if (!(dev->dev_flags & DF_CONFIGURED)) { |
758 | pr_err("se_device not configured yet, cannot port link\n"); | 766 | pr_err("se_device not configured yet, cannot port link\n"); |
759 | return -ENODEV; | 767 | return -ENODEV; |
760 | } | 768 | } |
761 | 769 | ||
762 | tpg_ci = &lun_ci->ci_parent->ci_group->cg_item; | 770 | tpg_ci = &lun_ci->ci_parent->ci_group->cg_item; |
763 | se_tpg = container_of(to_config_group(tpg_ci), | 771 | se_tpg = container_of(to_config_group(tpg_ci), |
764 | struct se_portal_group, tpg_group); | 772 | struct se_portal_group, tpg_group); |
765 | tf = se_tpg->se_tpg_wwn->wwn_tf; | 773 | tf = se_tpg->se_tpg_wwn->wwn_tf; |
766 | 774 | ||
767 | if (lun->lun_se_dev != NULL) { | 775 | if (lun->lun_se_dev != NULL) { |
768 | pr_err("Port Symlink already exists\n"); | 776 | pr_err("Port Symlink already exists\n"); |
769 | return -EEXIST; | 777 | return -EEXIST; |
770 | } | 778 | } |
771 | 779 | ||
772 | lun_p = core_dev_add_lun(se_tpg, dev, lun->unpacked_lun); | 780 | lun_p = core_dev_add_lun(se_tpg, dev, lun->unpacked_lun); |
773 | if (IS_ERR(lun_p)) { | 781 | if (IS_ERR(lun_p)) { |
774 | pr_err("core_dev_add_lun() failed\n"); | 782 | pr_err("core_dev_add_lun() failed\n"); |
775 | ret = PTR_ERR(lun_p); | 783 | ret = PTR_ERR(lun_p); |
776 | goto out; | 784 | goto out; |
777 | } | 785 | } |
778 | 786 | ||
779 | if (tf->tf_ops.fabric_post_link) { | 787 | if (tf->tf_ops.fabric_post_link) { |
780 | /* | 788 | /* |
781 | * Call the optional fabric_post_link() to allow a | 789 | * Call the optional fabric_post_link() to allow a |
782 | * fabric module to setup any additional state once | 790 | * fabric module to setup any additional state once |
783 | * core_dev_add_lun() has been called.. | 791 | * core_dev_add_lun() has been called.. |
784 | */ | 792 | */ |
785 | tf->tf_ops.fabric_post_link(se_tpg, lun); | 793 | tf->tf_ops.fabric_post_link(se_tpg, lun); |
786 | } | 794 | } |
787 | 795 | ||
788 | return 0; | 796 | return 0; |
789 | out: | 797 | out: |
790 | return ret; | 798 | return ret; |
791 | } | 799 | } |
792 | 800 | ||
793 | static int target_fabric_port_unlink( | 801 | static int target_fabric_port_unlink( |
794 | struct config_item *lun_ci, | 802 | struct config_item *lun_ci, |
795 | struct config_item *se_dev_ci) | 803 | struct config_item *se_dev_ci) |
796 | { | 804 | { |
797 | struct se_lun *lun = container_of(to_config_group(lun_ci), | 805 | struct se_lun *lun = container_of(to_config_group(lun_ci), |
798 | struct se_lun, lun_group); | 806 | struct se_lun, lun_group); |
799 | struct se_portal_group *se_tpg = lun->lun_sep->sep_tpg; | 807 | struct se_portal_group *se_tpg = lun->lun_sep->sep_tpg; |
800 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; | 808 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; |
801 | 809 | ||
802 | if (tf->tf_ops.fabric_pre_unlink) { | 810 | if (tf->tf_ops.fabric_pre_unlink) { |
803 | /* | 811 | /* |
804 | * Call the optional fabric_pre_unlink() to allow a | 812 | * Call the optional fabric_pre_unlink() to allow a |
805 | * fabric module to release any additional stat before | 813 | * fabric module to release any additional stat before |
806 | * core_dev_del_lun() is called. | 814 | * core_dev_del_lun() is called. |
807 | */ | 815 | */ |
808 | tf->tf_ops.fabric_pre_unlink(se_tpg, lun); | 816 | tf->tf_ops.fabric_pre_unlink(se_tpg, lun); |
809 | } | 817 | } |
810 | 818 | ||
811 | core_dev_del_lun(se_tpg, lun->unpacked_lun); | 819 | core_dev_del_lun(se_tpg, lun->unpacked_lun); |
812 | return 0; | 820 | return 0; |
813 | } | 821 | } |
814 | 822 | ||
815 | static struct configfs_item_operations target_fabric_port_item_ops = { | 823 | static struct configfs_item_operations target_fabric_port_item_ops = { |
816 | .show_attribute = target_fabric_port_attr_show, | 824 | .show_attribute = target_fabric_port_attr_show, |
817 | .store_attribute = target_fabric_port_attr_store, | 825 | .store_attribute = target_fabric_port_attr_store, |
818 | .allow_link = target_fabric_port_link, | 826 | .allow_link = target_fabric_port_link, |
819 | .drop_link = target_fabric_port_unlink, | 827 | .drop_link = target_fabric_port_unlink, |
820 | }; | 828 | }; |
821 | 829 | ||
822 | TF_CIT_SETUP(tpg_port, &target_fabric_port_item_ops, NULL, target_fabric_port_attrs); | 830 | TF_CIT_SETUP(tpg_port, &target_fabric_port_item_ops, NULL, target_fabric_port_attrs); |
823 | 831 | ||
824 | /* End of tfc_tpg_port_cit */ | 832 | /* End of tfc_tpg_port_cit */ |
825 | 833 | ||
826 | /* Start of tfc_tpg_port_stat_cit */ | 834 | /* Start of tfc_tpg_port_stat_cit */ |
827 | 835 | ||
828 | static struct config_group *target_core_port_stat_mkdir( | 836 | static struct config_group *target_core_port_stat_mkdir( |
829 | struct config_group *group, | 837 | struct config_group *group, |
830 | const char *name) | 838 | const char *name) |
831 | { | 839 | { |
832 | return ERR_PTR(-ENOSYS); | 840 | return ERR_PTR(-ENOSYS); |
833 | } | 841 | } |
834 | 842 | ||
835 | static void target_core_port_stat_rmdir( | 843 | static void target_core_port_stat_rmdir( |
836 | struct config_group *group, | 844 | struct config_group *group, |
837 | struct config_item *item) | 845 | struct config_item *item) |
838 | { | 846 | { |
839 | return; | 847 | return; |
840 | } | 848 | } |
841 | 849 | ||
842 | static struct configfs_group_operations target_fabric_port_stat_group_ops = { | 850 | static struct configfs_group_operations target_fabric_port_stat_group_ops = { |
843 | .make_group = target_core_port_stat_mkdir, | 851 | .make_group = target_core_port_stat_mkdir, |
844 | .drop_item = target_core_port_stat_rmdir, | 852 | .drop_item = target_core_port_stat_rmdir, |
845 | }; | 853 | }; |
846 | 854 | ||
847 | TF_CIT_SETUP(tpg_port_stat, NULL, &target_fabric_port_stat_group_ops, NULL); | 855 | TF_CIT_SETUP(tpg_port_stat, NULL, &target_fabric_port_stat_group_ops, NULL); |
848 | 856 | ||
849 | /* End of tfc_tpg_port_stat_cit */ | 857 | /* End of tfc_tpg_port_stat_cit */ |
850 | 858 | ||
851 | /* Start of tfc_tpg_lun_cit */ | 859 | /* Start of tfc_tpg_lun_cit */ |
852 | 860 | ||
853 | static struct config_group *target_fabric_make_lun( | 861 | static struct config_group *target_fabric_make_lun( |
854 | struct config_group *group, | 862 | struct config_group *group, |
855 | const char *name) | 863 | const char *name) |
856 | { | 864 | { |
857 | struct se_lun *lun; | 865 | struct se_lun *lun; |
858 | struct se_portal_group *se_tpg = container_of(group, | 866 | struct se_portal_group *se_tpg = container_of(group, |
859 | struct se_portal_group, tpg_lun_group); | 867 | struct se_portal_group, tpg_lun_group); |
860 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; | 868 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; |
861 | struct config_group *lun_cg = NULL, *port_stat_grp = NULL; | 869 | struct config_group *lun_cg = NULL, *port_stat_grp = NULL; |
862 | unsigned long unpacked_lun; | 870 | unsigned long unpacked_lun; |
863 | int errno; | 871 | int errno; |
864 | 872 | ||
865 | if (strstr(name, "lun_") != name) { | 873 | if (strstr(name, "lun_") != name) { |
866 | pr_err("Unable to locate \'_\" in" | 874 | pr_err("Unable to locate \'_\" in" |
867 | " \"lun_$LUN_NUMBER\"\n"); | 875 | " \"lun_$LUN_NUMBER\"\n"); |
868 | return ERR_PTR(-EINVAL); | 876 | return ERR_PTR(-EINVAL); |
869 | } | 877 | } |
870 | if (strict_strtoul(name + 4, 0, &unpacked_lun) || unpacked_lun > UINT_MAX) | 878 | if (strict_strtoul(name + 4, 0, &unpacked_lun) || unpacked_lun > UINT_MAX) |
871 | return ERR_PTR(-EINVAL); | 879 | return ERR_PTR(-EINVAL); |
872 | 880 | ||
873 | lun = core_get_lun_from_tpg(se_tpg, unpacked_lun); | 881 | lun = core_get_lun_from_tpg(se_tpg, unpacked_lun); |
874 | if (!lun) | 882 | if (!lun) |
875 | return ERR_PTR(-EINVAL); | 883 | return ERR_PTR(-EINVAL); |
876 | 884 | ||
877 | lun_cg = &lun->lun_group; | 885 | lun_cg = &lun->lun_group; |
878 | lun_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, | 886 | lun_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, |
879 | GFP_KERNEL); | 887 | GFP_KERNEL); |
880 | if (!lun_cg->default_groups) { | 888 | if (!lun_cg->default_groups) { |
881 | pr_err("Unable to allocate lun_cg->default_groups\n"); | 889 | pr_err("Unable to allocate lun_cg->default_groups\n"); |
882 | return ERR_PTR(-ENOMEM); | 890 | return ERR_PTR(-ENOMEM); |
883 | } | 891 | } |
884 | 892 | ||
885 | config_group_init_type_name(&lun->lun_group, name, | 893 | config_group_init_type_name(&lun->lun_group, name, |
886 | &TF_CIT_TMPL(tf)->tfc_tpg_port_cit); | 894 | &TF_CIT_TMPL(tf)->tfc_tpg_port_cit); |
887 | config_group_init_type_name(&lun->port_stat_grps.stat_group, | 895 | config_group_init_type_name(&lun->port_stat_grps.stat_group, |
888 | "statistics", &TF_CIT_TMPL(tf)->tfc_tpg_port_stat_cit); | 896 | "statistics", &TF_CIT_TMPL(tf)->tfc_tpg_port_stat_cit); |
889 | lun_cg->default_groups[0] = &lun->port_stat_grps.stat_group; | 897 | lun_cg->default_groups[0] = &lun->port_stat_grps.stat_group; |
890 | lun_cg->default_groups[1] = NULL; | 898 | lun_cg->default_groups[1] = NULL; |
891 | 899 | ||
892 | port_stat_grp = &lun->port_stat_grps.stat_group; | 900 | port_stat_grp = &lun->port_stat_grps.stat_group; |
893 | port_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3, | 901 | port_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3, |
894 | GFP_KERNEL); | 902 | GFP_KERNEL); |
895 | if (!port_stat_grp->default_groups) { | 903 | if (!port_stat_grp->default_groups) { |
896 | pr_err("Unable to allocate port_stat_grp->default_groups\n"); | 904 | pr_err("Unable to allocate port_stat_grp->default_groups\n"); |
897 | errno = -ENOMEM; | 905 | errno = -ENOMEM; |
898 | goto out; | 906 | goto out; |
899 | } | 907 | } |
900 | target_stat_setup_port_default_groups(lun); | 908 | target_stat_setup_port_default_groups(lun); |
901 | 909 | ||
902 | return &lun->lun_group; | 910 | return &lun->lun_group; |
903 | out: | 911 | out: |
904 | if (lun_cg) | 912 | if (lun_cg) |
905 | kfree(lun_cg->default_groups); | 913 | kfree(lun_cg->default_groups); |
906 | return ERR_PTR(errno); | 914 | return ERR_PTR(errno); |
907 | } | 915 | } |
908 | 916 | ||
909 | static void target_fabric_drop_lun( | 917 | static void target_fabric_drop_lun( |
910 | struct config_group *group, | 918 | struct config_group *group, |
911 | struct config_item *item) | 919 | struct config_item *item) |
912 | { | 920 | { |
913 | struct se_lun *lun = container_of(to_config_group(item), | 921 | struct se_lun *lun = container_of(to_config_group(item), |
914 | struct se_lun, lun_group); | 922 | struct se_lun, lun_group); |
915 | struct config_item *df_item; | 923 | struct config_item *df_item; |
916 | struct config_group *lun_cg, *port_stat_grp; | 924 | struct config_group *lun_cg, *port_stat_grp; |
917 | int i; | 925 | int i; |
918 | 926 | ||
919 | port_stat_grp = &lun->port_stat_grps.stat_group; | 927 | port_stat_grp = &lun->port_stat_grps.stat_group; |
920 | for (i = 0; port_stat_grp->default_groups[i]; i++) { | 928 | for (i = 0; port_stat_grp->default_groups[i]; i++) { |
921 | df_item = &port_stat_grp->default_groups[i]->cg_item; | 929 | df_item = &port_stat_grp->default_groups[i]->cg_item; |
922 | port_stat_grp->default_groups[i] = NULL; | 930 | port_stat_grp->default_groups[i] = NULL; |
923 | config_item_put(df_item); | 931 | config_item_put(df_item); |
924 | } | 932 | } |
925 | kfree(port_stat_grp->default_groups); | 933 | kfree(port_stat_grp->default_groups); |
926 | 934 | ||
927 | lun_cg = &lun->lun_group; | 935 | lun_cg = &lun->lun_group; |
928 | for (i = 0; lun_cg->default_groups[i]; i++) { | 936 | for (i = 0; lun_cg->default_groups[i]; i++) { |
929 | df_item = &lun_cg->default_groups[i]->cg_item; | 937 | df_item = &lun_cg->default_groups[i]->cg_item; |
930 | lun_cg->default_groups[i] = NULL; | 938 | lun_cg->default_groups[i] = NULL; |
931 | config_item_put(df_item); | 939 | config_item_put(df_item); |
932 | } | 940 | } |
933 | kfree(lun_cg->default_groups); | 941 | kfree(lun_cg->default_groups); |
934 | 942 | ||
935 | config_item_put(item); | 943 | config_item_put(item); |
936 | } | 944 | } |
937 | 945 | ||
938 | static struct configfs_group_operations target_fabric_lun_group_ops = { | 946 | static struct configfs_group_operations target_fabric_lun_group_ops = { |
939 | .make_group = &target_fabric_make_lun, | 947 | .make_group = &target_fabric_make_lun, |
940 | .drop_item = &target_fabric_drop_lun, | 948 | .drop_item = &target_fabric_drop_lun, |
941 | }; | 949 | }; |
942 | 950 | ||
943 | TF_CIT_SETUP(tpg_lun, NULL, &target_fabric_lun_group_ops, NULL); | 951 | TF_CIT_SETUP(tpg_lun, NULL, &target_fabric_lun_group_ops, NULL); |
944 | 952 | ||
945 | /* End of tfc_tpg_lun_cit */ | 953 | /* End of tfc_tpg_lun_cit */ |
946 | 954 | ||
947 | /* Start of tfc_tpg_attrib_cit */ | 955 | /* Start of tfc_tpg_attrib_cit */ |
948 | 956 | ||
949 | CONFIGFS_EATTR_OPS(target_fabric_tpg_attrib, se_portal_group, tpg_attrib_group); | 957 | CONFIGFS_EATTR_OPS(target_fabric_tpg_attrib, se_portal_group, tpg_attrib_group); |
950 | 958 | ||
951 | static struct configfs_item_operations target_fabric_tpg_attrib_item_ops = { | 959 | static struct configfs_item_operations target_fabric_tpg_attrib_item_ops = { |
952 | .show_attribute = target_fabric_tpg_attrib_attr_show, | 960 | .show_attribute = target_fabric_tpg_attrib_attr_show, |
953 | .store_attribute = target_fabric_tpg_attrib_attr_store, | 961 | .store_attribute = target_fabric_tpg_attrib_attr_store, |
954 | }; | 962 | }; |
955 | 963 | ||
956 | TF_CIT_SETUP(tpg_attrib, &target_fabric_tpg_attrib_item_ops, NULL, NULL); | 964 | TF_CIT_SETUP(tpg_attrib, &target_fabric_tpg_attrib_item_ops, NULL, NULL); |
957 | 965 | ||
958 | /* End of tfc_tpg_attrib_cit */ | 966 | /* End of tfc_tpg_attrib_cit */ |
959 | 967 | ||
960 | /* Start of tfc_tpg_param_cit */ | 968 | /* Start of tfc_tpg_param_cit */ |
961 | 969 | ||
962 | CONFIGFS_EATTR_OPS(target_fabric_tpg_param, se_portal_group, tpg_param_group); | 970 | CONFIGFS_EATTR_OPS(target_fabric_tpg_param, se_portal_group, tpg_param_group); |
963 | 971 | ||
964 | static struct configfs_item_operations target_fabric_tpg_param_item_ops = { | 972 | static struct configfs_item_operations target_fabric_tpg_param_item_ops = { |
965 | .show_attribute = target_fabric_tpg_param_attr_show, | 973 | .show_attribute = target_fabric_tpg_param_attr_show, |
966 | .store_attribute = target_fabric_tpg_param_attr_store, | 974 | .store_attribute = target_fabric_tpg_param_attr_store, |
967 | }; | 975 | }; |
968 | 976 | ||
969 | TF_CIT_SETUP(tpg_param, &target_fabric_tpg_param_item_ops, NULL, NULL); | 977 | TF_CIT_SETUP(tpg_param, &target_fabric_tpg_param_item_ops, NULL, NULL); |
970 | 978 | ||
971 | /* End of tfc_tpg_param_cit */ | 979 | /* End of tfc_tpg_param_cit */ |
972 | 980 | ||
973 | /* Start of tfc_tpg_base_cit */ | 981 | /* Start of tfc_tpg_base_cit */ |
974 | /* | 982 | /* |
975 | * For use with TF_TPG_ATTR() and TF_TPG_ATTR_RO() | 983 | * For use with TF_TPG_ATTR() and TF_TPG_ATTR_RO() |
976 | */ | 984 | */ |
977 | CONFIGFS_EATTR_OPS(target_fabric_tpg, se_portal_group, tpg_group); | 985 | CONFIGFS_EATTR_OPS(target_fabric_tpg, se_portal_group, tpg_group); |
978 | 986 | ||
979 | static void target_fabric_tpg_release(struct config_item *item) | 987 | static void target_fabric_tpg_release(struct config_item *item) |
980 | { | 988 | { |
981 | struct se_portal_group *se_tpg = container_of(to_config_group(item), | 989 | struct se_portal_group *se_tpg = container_of(to_config_group(item), |
982 | struct se_portal_group, tpg_group); | 990 | struct se_portal_group, tpg_group); |
983 | struct se_wwn *wwn = se_tpg->se_tpg_wwn; | 991 | struct se_wwn *wwn = se_tpg->se_tpg_wwn; |
984 | struct target_fabric_configfs *tf = wwn->wwn_tf; | 992 | struct target_fabric_configfs *tf = wwn->wwn_tf; |
985 | 993 | ||
986 | tf->tf_ops.fabric_drop_tpg(se_tpg); | 994 | tf->tf_ops.fabric_drop_tpg(se_tpg); |
987 | } | 995 | } |
988 | 996 | ||
989 | static struct configfs_item_operations target_fabric_tpg_base_item_ops = { | 997 | static struct configfs_item_operations target_fabric_tpg_base_item_ops = { |
990 | .release = target_fabric_tpg_release, | 998 | .release = target_fabric_tpg_release, |
991 | .show_attribute = target_fabric_tpg_attr_show, | 999 | .show_attribute = target_fabric_tpg_attr_show, |
992 | .store_attribute = target_fabric_tpg_attr_store, | 1000 | .store_attribute = target_fabric_tpg_attr_store, |
993 | }; | 1001 | }; |
994 | 1002 | ||
995 | TF_CIT_SETUP(tpg_base, &target_fabric_tpg_base_item_ops, NULL, NULL); | 1003 | TF_CIT_SETUP(tpg_base, &target_fabric_tpg_base_item_ops, NULL, NULL); |
996 | 1004 | ||
997 | /* End of tfc_tpg_base_cit */ | 1005 | /* End of tfc_tpg_base_cit */ |
998 | 1006 | ||
999 | /* Start of tfc_tpg_cit */ | 1007 | /* Start of tfc_tpg_cit */ |
1000 | 1008 | ||
1001 | static struct config_group *target_fabric_make_tpg( | 1009 | static struct config_group *target_fabric_make_tpg( |
1002 | struct config_group *group, | 1010 | struct config_group *group, |
1003 | const char *name) | 1011 | const char *name) |
1004 | { | 1012 | { |
1005 | struct se_wwn *wwn = container_of(group, struct se_wwn, wwn_group); | 1013 | struct se_wwn *wwn = container_of(group, struct se_wwn, wwn_group); |
1006 | struct target_fabric_configfs *tf = wwn->wwn_tf; | 1014 | struct target_fabric_configfs *tf = wwn->wwn_tf; |
1007 | struct se_portal_group *se_tpg; | 1015 | struct se_portal_group *se_tpg; |
1008 | 1016 | ||
1009 | if (!tf->tf_ops.fabric_make_tpg) { | 1017 | if (!tf->tf_ops.fabric_make_tpg) { |
1010 | pr_err("tf->tf_ops.fabric_make_tpg is NULL\n"); | 1018 | pr_err("tf->tf_ops.fabric_make_tpg is NULL\n"); |
1011 | return ERR_PTR(-ENOSYS); | 1019 | return ERR_PTR(-ENOSYS); |
1012 | } | 1020 | } |
1013 | 1021 | ||
1014 | se_tpg = tf->tf_ops.fabric_make_tpg(wwn, group, name); | 1022 | se_tpg = tf->tf_ops.fabric_make_tpg(wwn, group, name); |
1015 | if (!se_tpg || IS_ERR(se_tpg)) | 1023 | if (!se_tpg || IS_ERR(se_tpg)) |
1016 | return ERR_PTR(-EINVAL); | 1024 | return ERR_PTR(-EINVAL); |
1017 | /* | 1025 | /* |
1018 | * Setup default groups from pre-allocated se_tpg->tpg_default_groups | 1026 | * Setup default groups from pre-allocated se_tpg->tpg_default_groups |
1019 | */ | 1027 | */ |
1020 | se_tpg->tpg_group.default_groups = se_tpg->tpg_default_groups; | 1028 | se_tpg->tpg_group.default_groups = se_tpg->tpg_default_groups; |
1021 | se_tpg->tpg_group.default_groups[0] = &se_tpg->tpg_lun_group; | 1029 | se_tpg->tpg_group.default_groups[0] = &se_tpg->tpg_lun_group; |
1022 | se_tpg->tpg_group.default_groups[1] = &se_tpg->tpg_np_group; | 1030 | se_tpg->tpg_group.default_groups[1] = &se_tpg->tpg_np_group; |
1023 | se_tpg->tpg_group.default_groups[2] = &se_tpg->tpg_acl_group; | 1031 | se_tpg->tpg_group.default_groups[2] = &se_tpg->tpg_acl_group; |
1024 | se_tpg->tpg_group.default_groups[3] = &se_tpg->tpg_attrib_group; | 1032 | se_tpg->tpg_group.default_groups[3] = &se_tpg->tpg_attrib_group; |
1025 | se_tpg->tpg_group.default_groups[4] = &se_tpg->tpg_param_group; | 1033 | se_tpg->tpg_group.default_groups[4] = &se_tpg->tpg_param_group; |
1026 | se_tpg->tpg_group.default_groups[5] = NULL; | 1034 | se_tpg->tpg_group.default_groups[5] = NULL; |
1027 | 1035 | ||
1028 | config_group_init_type_name(&se_tpg->tpg_group, name, | 1036 | config_group_init_type_name(&se_tpg->tpg_group, name, |
1029 | &TF_CIT_TMPL(tf)->tfc_tpg_base_cit); | 1037 | &TF_CIT_TMPL(tf)->tfc_tpg_base_cit); |
1030 | config_group_init_type_name(&se_tpg->tpg_lun_group, "lun", | 1038 | config_group_init_type_name(&se_tpg->tpg_lun_group, "lun", |
1031 | &TF_CIT_TMPL(tf)->tfc_tpg_lun_cit); | 1039 | &TF_CIT_TMPL(tf)->tfc_tpg_lun_cit); |
1032 | config_group_init_type_name(&se_tpg->tpg_np_group, "np", | 1040 | config_group_init_type_name(&se_tpg->tpg_np_group, "np", |
1033 | &TF_CIT_TMPL(tf)->tfc_tpg_np_cit); | 1041 | &TF_CIT_TMPL(tf)->tfc_tpg_np_cit); |
1034 | config_group_init_type_name(&se_tpg->tpg_acl_group, "acls", | 1042 | config_group_init_type_name(&se_tpg->tpg_acl_group, "acls", |
1035 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_cit); | 1043 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_cit); |
1036 | config_group_init_type_name(&se_tpg->tpg_attrib_group, "attrib", | 1044 | config_group_init_type_name(&se_tpg->tpg_attrib_group, "attrib", |
1037 | &TF_CIT_TMPL(tf)->tfc_tpg_attrib_cit); | 1045 | &TF_CIT_TMPL(tf)->tfc_tpg_attrib_cit); |
1038 | config_group_init_type_name(&se_tpg->tpg_param_group, "param", | 1046 | config_group_init_type_name(&se_tpg->tpg_param_group, "param", |
1039 | &TF_CIT_TMPL(tf)->tfc_tpg_param_cit); | 1047 | &TF_CIT_TMPL(tf)->tfc_tpg_param_cit); |
1040 | 1048 | ||
1041 | return &se_tpg->tpg_group; | 1049 | return &se_tpg->tpg_group; |
1042 | } | 1050 | } |
1043 | 1051 | ||
1044 | static void target_fabric_drop_tpg( | 1052 | static void target_fabric_drop_tpg( |
1045 | struct config_group *group, | 1053 | struct config_group *group, |
1046 | struct config_item *item) | 1054 | struct config_item *item) |
1047 | { | 1055 | { |
1048 | struct se_portal_group *se_tpg = container_of(to_config_group(item), | 1056 | struct se_portal_group *se_tpg = container_of(to_config_group(item), |
1049 | struct se_portal_group, tpg_group); | 1057 | struct se_portal_group, tpg_group); |
1050 | struct config_group *tpg_cg = &se_tpg->tpg_group; | 1058 | struct config_group *tpg_cg = &se_tpg->tpg_group; |
1051 | struct config_item *df_item; | 1059 | struct config_item *df_item; |
1052 | int i; | 1060 | int i; |
1053 | /* | 1061 | /* |
1054 | * Release default groups, but do not release tpg_cg->default_groups | 1062 | * Release default groups, but do not release tpg_cg->default_groups |
1055 | * memory as it is statically allocated at se_tpg->tpg_default_groups. | 1063 | * memory as it is statically allocated at se_tpg->tpg_default_groups. |
1056 | */ | 1064 | */ |
1057 | for (i = 0; tpg_cg->default_groups[i]; i++) { | 1065 | for (i = 0; tpg_cg->default_groups[i]; i++) { |
1058 | df_item = &tpg_cg->default_groups[i]->cg_item; | 1066 | df_item = &tpg_cg->default_groups[i]->cg_item; |
1059 | tpg_cg->default_groups[i] = NULL; | 1067 | tpg_cg->default_groups[i] = NULL; |
1060 | config_item_put(df_item); | 1068 | config_item_put(df_item); |
1061 | } | 1069 | } |
1062 | 1070 | ||
1063 | config_item_put(item); | 1071 | config_item_put(item); |
1064 | } | 1072 | } |
1065 | 1073 | ||
1066 | static void target_fabric_release_wwn(struct config_item *item) | 1074 | static void target_fabric_release_wwn(struct config_item *item) |
1067 | { | 1075 | { |
1068 | struct se_wwn *wwn = container_of(to_config_group(item), | 1076 | struct se_wwn *wwn = container_of(to_config_group(item), |
1069 | struct se_wwn, wwn_group); | 1077 | struct se_wwn, wwn_group); |
1070 | struct target_fabric_configfs *tf = wwn->wwn_tf; | 1078 | struct target_fabric_configfs *tf = wwn->wwn_tf; |
1071 | 1079 | ||
1072 | tf->tf_ops.fabric_drop_wwn(wwn); | 1080 | tf->tf_ops.fabric_drop_wwn(wwn); |
1073 | } | 1081 | } |
1074 | 1082 | ||
1075 | static struct configfs_item_operations target_fabric_tpg_item_ops = { | 1083 | static struct configfs_item_operations target_fabric_tpg_item_ops = { |
1076 | .release = target_fabric_release_wwn, | 1084 | .release = target_fabric_release_wwn, |
1077 | }; | 1085 | }; |
1078 | 1086 | ||
1079 | static struct configfs_group_operations target_fabric_tpg_group_ops = { | 1087 | static struct configfs_group_operations target_fabric_tpg_group_ops = { |
1080 | .make_group = target_fabric_make_tpg, | 1088 | .make_group = target_fabric_make_tpg, |
1081 | .drop_item = target_fabric_drop_tpg, | 1089 | .drop_item = target_fabric_drop_tpg, |
1082 | }; | 1090 | }; |
1083 | 1091 | ||
1084 | TF_CIT_SETUP(tpg, &target_fabric_tpg_item_ops, &target_fabric_tpg_group_ops, | 1092 | TF_CIT_SETUP(tpg, &target_fabric_tpg_item_ops, &target_fabric_tpg_group_ops, |
1085 | NULL); | 1093 | NULL); |
1086 | 1094 | ||
1087 | /* End of tfc_tpg_cit */ | 1095 | /* End of tfc_tpg_cit */ |
1088 | 1096 | ||
1089 | /* Start of tfc_wwn_fabric_stats_cit */ | 1097 | /* Start of tfc_wwn_fabric_stats_cit */ |
1090 | /* | 1098 | /* |
1091 | * This is used as a placeholder for struct se_wwn->fabric_stat_group | 1099 | * This is used as a placeholder for struct se_wwn->fabric_stat_group |
1092 | * to allow fabrics access to ->fabric_stat_group->default_groups[] | 1100 | * to allow fabrics access to ->fabric_stat_group->default_groups[] |
1093 | */ | 1101 | */ |
1094 | TF_CIT_SETUP(wwn_fabric_stats, NULL, NULL, NULL); | 1102 | TF_CIT_SETUP(wwn_fabric_stats, NULL, NULL, NULL); |
1095 | 1103 | ||
1096 | /* End of tfc_wwn_fabric_stats_cit */ | 1104 | /* End of tfc_wwn_fabric_stats_cit */ |
1097 | 1105 | ||
1098 | /* Start of tfc_wwn_cit */ | 1106 | /* Start of tfc_wwn_cit */ |
1099 | 1107 | ||
1100 | static struct config_group *target_fabric_make_wwn( | 1108 | static struct config_group *target_fabric_make_wwn( |
1101 | struct config_group *group, | 1109 | struct config_group *group, |
1102 | const char *name) | 1110 | const char *name) |
1103 | { | 1111 | { |
1104 | struct target_fabric_configfs *tf = container_of(group, | 1112 | struct target_fabric_configfs *tf = container_of(group, |
1105 | struct target_fabric_configfs, tf_group); | 1113 | struct target_fabric_configfs, tf_group); |
1106 | struct se_wwn *wwn; | 1114 | struct se_wwn *wwn; |
1107 | 1115 | ||
1108 | if (!tf->tf_ops.fabric_make_wwn) { | 1116 | if (!tf->tf_ops.fabric_make_wwn) { |
1109 | pr_err("tf->tf_ops.fabric_make_wwn is NULL\n"); | 1117 | pr_err("tf->tf_ops.fabric_make_wwn is NULL\n"); |
1110 | return ERR_PTR(-ENOSYS); | 1118 | return ERR_PTR(-ENOSYS); |
1111 | } | 1119 | } |
1112 | 1120 | ||
1113 | wwn = tf->tf_ops.fabric_make_wwn(tf, group, name); | 1121 | wwn = tf->tf_ops.fabric_make_wwn(tf, group, name); |
1114 | if (!wwn || IS_ERR(wwn)) | 1122 | if (!wwn || IS_ERR(wwn)) |
1115 | return ERR_PTR(-EINVAL); | 1123 | return ERR_PTR(-EINVAL); |
1116 | 1124 | ||
1117 | wwn->wwn_tf = tf; | 1125 | wwn->wwn_tf = tf; |
1118 | /* | 1126 | /* |
1119 | * Setup default groups from pre-allocated wwn->wwn_default_groups | 1127 | * Setup default groups from pre-allocated wwn->wwn_default_groups |
1120 | */ | 1128 | */ |
1121 | wwn->wwn_group.default_groups = wwn->wwn_default_groups; | 1129 | wwn->wwn_group.default_groups = wwn->wwn_default_groups; |
1122 | wwn->wwn_group.default_groups[0] = &wwn->fabric_stat_group; | 1130 | wwn->wwn_group.default_groups[0] = &wwn->fabric_stat_group; |
1123 | wwn->wwn_group.default_groups[1] = NULL; | 1131 | wwn->wwn_group.default_groups[1] = NULL; |
1124 | 1132 | ||
1125 | config_group_init_type_name(&wwn->wwn_group, name, | 1133 | config_group_init_type_name(&wwn->wwn_group, name, |
1126 | &TF_CIT_TMPL(tf)->tfc_tpg_cit); | 1134 | &TF_CIT_TMPL(tf)->tfc_tpg_cit); |
1127 | config_group_init_type_name(&wwn->fabric_stat_group, "fabric_statistics", | 1135 | config_group_init_type_name(&wwn->fabric_stat_group, "fabric_statistics", |
1128 | &TF_CIT_TMPL(tf)->tfc_wwn_fabric_stats_cit); | 1136 | &TF_CIT_TMPL(tf)->tfc_wwn_fabric_stats_cit); |
1129 | 1137 | ||
1130 | return &wwn->wwn_group; | 1138 | return &wwn->wwn_group; |
1131 | } | 1139 | } |
1132 | 1140 | ||
1133 | static void target_fabric_drop_wwn( | 1141 | static void target_fabric_drop_wwn( |
1134 | struct config_group *group, | 1142 | struct config_group *group, |
1135 | struct config_item *item) | 1143 | struct config_item *item) |
1136 | { | 1144 | { |
1137 | struct se_wwn *wwn = container_of(to_config_group(item), | 1145 | struct se_wwn *wwn = container_of(to_config_group(item), |
1138 | struct se_wwn, wwn_group); | 1146 | struct se_wwn, wwn_group); |
1139 | struct config_item *df_item; | 1147 | struct config_item *df_item; |
1140 | struct config_group *cg = &wwn->wwn_group; | 1148 | struct config_group *cg = &wwn->wwn_group; |
1141 | int i; | 1149 | int i; |
1142 | 1150 | ||
1143 | for (i = 0; cg->default_groups[i]; i++) { | 1151 | for (i = 0; cg->default_groups[i]; i++) { |
1144 | df_item = &cg->default_groups[i]->cg_item; | 1152 | df_item = &cg->default_groups[i]->cg_item; |
1145 | cg->default_groups[i] = NULL; | 1153 | cg->default_groups[i] = NULL; |
1146 | config_item_put(df_item); | 1154 | config_item_put(df_item); |
1147 | } | 1155 | } |
1148 | 1156 | ||
1149 | config_item_put(item); | 1157 | config_item_put(item); |
1150 | } | 1158 | } |
1151 | 1159 | ||
1152 | static struct configfs_group_operations target_fabric_wwn_group_ops = { | 1160 | static struct configfs_group_operations target_fabric_wwn_group_ops = { |
1153 | .make_group = target_fabric_make_wwn, | 1161 | .make_group = target_fabric_make_wwn, |
1154 | .drop_item = target_fabric_drop_wwn, | 1162 | .drop_item = target_fabric_drop_wwn, |
1155 | }; | 1163 | }; |
1156 | /* | 1164 | /* |
1157 | * For use with TF_WWN_ATTR() and TF_WWN_ATTR_RO() | 1165 | * For use with TF_WWN_ATTR() and TF_WWN_ATTR_RO() |
1158 | */ | 1166 | */ |
1159 | CONFIGFS_EATTR_OPS(target_fabric_wwn, target_fabric_configfs, tf_group); | 1167 | CONFIGFS_EATTR_OPS(target_fabric_wwn, target_fabric_configfs, tf_group); |
1160 | 1168 | ||
1161 | static struct configfs_item_operations target_fabric_wwn_item_ops = { | 1169 | static struct configfs_item_operations target_fabric_wwn_item_ops = { |
1162 | .show_attribute = target_fabric_wwn_attr_show, | 1170 | .show_attribute = target_fabric_wwn_attr_show, |
1163 | .store_attribute = target_fabric_wwn_attr_store, | 1171 | .store_attribute = target_fabric_wwn_attr_store, |
1164 | }; | 1172 | }; |
1165 | 1173 | ||
1166 | TF_CIT_SETUP(wwn, &target_fabric_wwn_item_ops, &target_fabric_wwn_group_ops, NULL); | 1174 | TF_CIT_SETUP(wwn, &target_fabric_wwn_item_ops, &target_fabric_wwn_group_ops, NULL); |
1167 | 1175 | ||
1168 | /* End of tfc_wwn_cit */ | 1176 | /* End of tfc_wwn_cit */ |
1169 | 1177 | ||
1170 | /* Start of tfc_discovery_cit */ | 1178 | /* Start of tfc_discovery_cit */ |
1171 | 1179 | ||
1172 | CONFIGFS_EATTR_OPS(target_fabric_discovery, target_fabric_configfs, | 1180 | CONFIGFS_EATTR_OPS(target_fabric_discovery, target_fabric_configfs, |
1173 | tf_disc_group); | 1181 | tf_disc_group); |
1174 | 1182 | ||
1175 | static struct configfs_item_operations target_fabric_discovery_item_ops = { | 1183 | static struct configfs_item_operations target_fabric_discovery_item_ops = { |
1176 | .show_attribute = target_fabric_discovery_attr_show, | 1184 | .show_attribute = target_fabric_discovery_attr_show, |
1177 | .store_attribute = target_fabric_discovery_attr_store, | 1185 | .store_attribute = target_fabric_discovery_attr_store, |
1178 | }; | 1186 | }; |
1179 | 1187 | ||
1180 | TF_CIT_SETUP(discovery, &target_fabric_discovery_item_ops, NULL, NULL); | 1188 | TF_CIT_SETUP(discovery, &target_fabric_discovery_item_ops, NULL, NULL); |
1181 | 1189 | ||
1182 | /* End of tfc_discovery_cit */ | 1190 | /* End of tfc_discovery_cit */ |
1183 | 1191 | ||
1184 | int target_fabric_setup_cits(struct target_fabric_configfs *tf) | 1192 | int target_fabric_setup_cits(struct target_fabric_configfs *tf) |
1185 | { | 1193 | { |
1186 | target_fabric_setup_discovery_cit(tf); | 1194 | target_fabric_setup_discovery_cit(tf); |
1187 | target_fabric_setup_wwn_cit(tf); | 1195 | target_fabric_setup_wwn_cit(tf); |
1188 | target_fabric_setup_wwn_fabric_stats_cit(tf); | 1196 | target_fabric_setup_wwn_fabric_stats_cit(tf); |
1189 | target_fabric_setup_tpg_cit(tf); | 1197 | target_fabric_setup_tpg_cit(tf); |
1190 | target_fabric_setup_tpg_base_cit(tf); | 1198 | target_fabric_setup_tpg_base_cit(tf); |
1191 | target_fabric_setup_tpg_port_cit(tf); | 1199 | target_fabric_setup_tpg_port_cit(tf); |
1192 | target_fabric_setup_tpg_port_stat_cit(tf); | 1200 | target_fabric_setup_tpg_port_stat_cit(tf); |
1193 | target_fabric_setup_tpg_lun_cit(tf); | 1201 | target_fabric_setup_tpg_lun_cit(tf); |
1194 | target_fabric_setup_tpg_np_cit(tf); | 1202 | target_fabric_setup_tpg_np_cit(tf); |
1195 | target_fabric_setup_tpg_np_base_cit(tf); | 1203 | target_fabric_setup_tpg_np_base_cit(tf); |
1196 | target_fabric_setup_tpg_attrib_cit(tf); | 1204 | target_fabric_setup_tpg_attrib_cit(tf); |
1197 | target_fabric_setup_tpg_param_cit(tf); | 1205 | target_fabric_setup_tpg_param_cit(tf); |
1198 | target_fabric_setup_tpg_nacl_cit(tf); | 1206 | target_fabric_setup_tpg_nacl_cit(tf); |
1199 | target_fabric_setup_tpg_nacl_base_cit(tf); | 1207 | target_fabric_setup_tpg_nacl_base_cit(tf); |
1200 | target_fabric_setup_tpg_nacl_attrib_cit(tf); | 1208 | target_fabric_setup_tpg_nacl_attrib_cit(tf); |
1201 | target_fabric_setup_tpg_nacl_auth_cit(tf); | 1209 | target_fabric_setup_tpg_nacl_auth_cit(tf); |
1202 | target_fabric_setup_tpg_nacl_param_cit(tf); | 1210 | target_fabric_setup_tpg_nacl_param_cit(tf); |
1203 | target_fabric_setup_tpg_nacl_stat_cit(tf); | 1211 | target_fabric_setup_tpg_nacl_stat_cit(tf); |
1204 | target_fabric_setup_tpg_mappedlun_cit(tf); | 1212 | target_fabric_setup_tpg_mappedlun_cit(tf); |
1205 | target_fabric_setup_tpg_mappedlun_stat_cit(tf); | 1213 | target_fabric_setup_tpg_mappedlun_stat_cit(tf); |
1206 | 1214 | ||
1207 | return 0; | 1215 | return 0; |
1208 | } | 1216 | } |
1209 | 1217 |