1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /******************************************************************************* |
3 | * This file contains the configfs implementation for iSCSI Target mode |
4 | * from the LIO-Target Project. |
5 | * |
6 | * (c) Copyright 2007-2013 Datera, Inc. |
7 | * |
8 | * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> |
9 | * |
10 | ****************************************************************************/ |
11 | |
12 | #include <linux/configfs.h> |
13 | #include <linux/ctype.h> |
14 | #include <linux/export.h> |
15 | #include <linux/inet.h> |
16 | #include <linux/module.h> |
17 | #include <net/ipv6.h> |
18 | #include <target/target_core_base.h> |
19 | #include <target/target_core_fabric.h> |
20 | #include <target/iscsi/iscsi_transport.h> |
21 | #include <target/iscsi/iscsi_target_core.h> |
22 | #include "iscsi_target_parameters.h" |
23 | #include "iscsi_target_device.h" |
24 | #include "iscsi_target_erl0.h" |
25 | #include "iscsi_target_nodeattrib.h" |
26 | #include "iscsi_target_tpg.h" |
27 | #include "iscsi_target_util.h" |
28 | #include "iscsi_target.h" |
29 | #include <target/iscsi/iscsi_target_stat.h> |
30 | |
31 | |
32 | /* Start items for lio_target_portal_cit */ |
33 | |
34 | static inline struct iscsi_tpg_np *to_iscsi_tpg_np(struct config_item *item) |
35 | { |
36 | return container_of(to_tpg_np(item), struct iscsi_tpg_np, se_tpg_np); |
37 | } |
38 | |
39 | static ssize_t lio_target_np_driver_show(struct config_item *item, char *page, |
40 | enum iscsit_transport_type type) |
41 | { |
42 | struct iscsi_tpg_np *tpg_np = to_iscsi_tpg_np(item); |
43 | struct iscsi_tpg_np *tpg_np_new; |
44 | ssize_t rb; |
45 | |
46 | tpg_np_new = iscsit_tpg_locate_child_np(tpg_np, type); |
47 | if (tpg_np_new) |
48 | rb = sysfs_emit(buf: page, fmt: "1\n" ); |
49 | else |
50 | rb = sysfs_emit(buf: page, fmt: "0\n" ); |
51 | |
52 | return rb; |
53 | } |
54 | |
55 | static ssize_t lio_target_np_driver_store(struct config_item *item, |
56 | const char *page, size_t count, enum iscsit_transport_type type, |
57 | const char *mod_name) |
58 | { |
59 | struct iscsi_tpg_np *tpg_np = to_iscsi_tpg_np(item); |
60 | struct iscsi_np *np; |
61 | struct iscsi_portal_group *tpg; |
62 | struct iscsi_tpg_np *tpg_np_new = NULL; |
63 | u32 op; |
64 | int rc; |
65 | |
66 | rc = kstrtou32(s: page, base: 0, res: &op); |
67 | if (rc) |
68 | return rc; |
69 | if ((op != 1) && (op != 0)) { |
70 | pr_err("Illegal value for tpg_enable: %u\n" , op); |
71 | return -EINVAL; |
72 | } |
73 | np = tpg_np->tpg_np; |
74 | if (!np) { |
75 | pr_err("Unable to locate struct iscsi_np from" |
76 | " struct iscsi_tpg_np\n" ); |
77 | return -EINVAL; |
78 | } |
79 | |
80 | tpg = tpg_np->tpg; |
81 | if (iscsit_get_tpg(tpg) < 0) |
82 | return -EINVAL; |
83 | |
84 | if (op) { |
85 | if (strlen(mod_name)) { |
86 | rc = request_module(mod_name); |
87 | if (rc != 0) { |
88 | pr_warn("Unable to request_module for %s\n" , |
89 | mod_name); |
90 | rc = 0; |
91 | } |
92 | } |
93 | |
94 | tpg_np_new = iscsit_tpg_add_network_portal(tpg, |
95 | &np->np_sockaddr, tpg_np, type); |
96 | if (IS_ERR(ptr: tpg_np_new)) { |
97 | rc = PTR_ERR(ptr: tpg_np_new); |
98 | goto out; |
99 | } |
100 | } else { |
101 | tpg_np_new = iscsit_tpg_locate_child_np(tpg_np, type); |
102 | if (tpg_np_new) { |
103 | rc = iscsit_tpg_del_network_portal(tpg, tpg_np_new); |
104 | if (rc < 0) |
105 | goto out; |
106 | } |
107 | } |
108 | |
109 | iscsit_put_tpg(tpg); |
110 | return count; |
111 | out: |
112 | iscsit_put_tpg(tpg); |
113 | return rc; |
114 | } |
115 | |
116 | static ssize_t lio_target_np_iser_show(struct config_item *item, char *page) |
117 | { |
118 | return lio_target_np_driver_show(item, page, type: ISCSI_INFINIBAND); |
119 | } |
120 | |
121 | static ssize_t lio_target_np_iser_store(struct config_item *item, |
122 | const char *page, size_t count) |
123 | { |
124 | return lio_target_np_driver_store(item, page, count, |
125 | type: ISCSI_INFINIBAND, mod_name: "ib_isert" ); |
126 | } |
127 | CONFIGFS_ATTR(lio_target_np_, iser); |
128 | |
129 | static ssize_t lio_target_np_cxgbit_show(struct config_item *item, char *page) |
130 | { |
131 | return lio_target_np_driver_show(item, page, type: ISCSI_CXGBIT); |
132 | } |
133 | |
134 | static ssize_t lio_target_np_cxgbit_store(struct config_item *item, |
135 | const char *page, size_t count) |
136 | { |
137 | return lio_target_np_driver_store(item, page, count, |
138 | type: ISCSI_CXGBIT, mod_name: "cxgbit" ); |
139 | } |
140 | CONFIGFS_ATTR(lio_target_np_, cxgbit); |
141 | |
142 | static struct configfs_attribute *lio_target_portal_attrs[] = { |
143 | &lio_target_np_attr_iser, |
144 | &lio_target_np_attr_cxgbit, |
145 | NULL, |
146 | }; |
147 | |
148 | /* Stop items for lio_target_portal_cit */ |
149 | |
150 | /* Start items for lio_target_np_cit */ |
151 | |
152 | #define MAX_PORTAL_LEN 256 |
153 | |
154 | static struct se_tpg_np *lio_target_call_addnptotpg( |
155 | struct se_portal_group *se_tpg, |
156 | struct config_group *group, |
157 | const char *name) |
158 | { |
159 | struct iscsi_portal_group *tpg; |
160 | struct iscsi_tpg_np *tpg_np; |
161 | char *str, *str2, *ip_str, *port_str; |
162 | struct sockaddr_storage sockaddr = { }; |
163 | int ret; |
164 | char buf[MAX_PORTAL_LEN + 1] = { }; |
165 | |
166 | if (strlen(name) > MAX_PORTAL_LEN) { |
167 | pr_err("strlen(name): %d exceeds MAX_PORTAL_LEN: %d\n" , |
168 | (int)strlen(name), MAX_PORTAL_LEN); |
169 | return ERR_PTR(error: -EOVERFLOW); |
170 | } |
171 | snprintf(buf, MAX_PORTAL_LEN + 1, fmt: "%s" , name); |
172 | |
173 | str = strstr(buf, "[" ); |
174 | if (str) { |
175 | str2 = strstr(str, "]" ); |
176 | if (!str2) { |
177 | pr_err("Unable to locate trailing \"]\"" |
178 | " in IPv6 iSCSI network portal address\n" ); |
179 | return ERR_PTR(error: -EINVAL); |
180 | } |
181 | |
182 | ip_str = str + 1; /* Skip over leading "[" */ |
183 | *str2 = '\0'; /* Terminate the unbracketed IPv6 address */ |
184 | str2++; /* Skip over the \0 */ |
185 | |
186 | port_str = strstr(str2, ":" ); |
187 | if (!port_str) { |
188 | pr_err("Unable to locate \":port\"" |
189 | " in IPv6 iSCSI network portal address\n" ); |
190 | return ERR_PTR(error: -EINVAL); |
191 | } |
192 | *port_str = '\0'; /* Terminate string for IP */ |
193 | port_str++; /* Skip over ":" */ |
194 | } else { |
195 | ip_str = &buf[0]; |
196 | port_str = strstr(ip_str, ":" ); |
197 | if (!port_str) { |
198 | pr_err("Unable to locate \":port\"" |
199 | " in IPv4 iSCSI network portal address\n" ); |
200 | return ERR_PTR(error: -EINVAL); |
201 | } |
202 | *port_str = '\0'; /* Terminate string for IP */ |
203 | port_str++; /* Skip over ":" */ |
204 | } |
205 | |
206 | ret = inet_pton_with_scope(net: &init_net, AF_UNSPEC, src: ip_str, |
207 | port: port_str, addr: &sockaddr); |
208 | if (ret) { |
209 | pr_err("malformed ip/port passed: %s\n" , name); |
210 | return ERR_PTR(error: ret); |
211 | } |
212 | |
213 | tpg = to_iscsi_tpg(se_tpg); |
214 | ret = iscsit_get_tpg(tpg); |
215 | if (ret < 0) |
216 | return ERR_PTR(error: -EINVAL); |
217 | |
218 | pr_debug("LIO_Target_ConfigFS: REGISTER -> %s TPGT: %hu" |
219 | " PORTAL: %s\n" , |
220 | config_item_name(&se_tpg->se_tpg_wwn->wwn_group.cg_item), |
221 | tpg->tpgt, name); |
222 | /* |
223 | * Assume ISCSI_TCP by default. Other network portals for other |
224 | * iSCSI fabrics: |
225 | * |
226 | * Traditional iSCSI over SCTP (initial support) |
227 | * iSER/TCP (TODO, hardware available) |
228 | * iSER/SCTP (TODO, software emulation with osc-iwarp) |
229 | * iSER/IB (TODO, hardware available) |
230 | * |
231 | * can be enabled with attributes under |
232 | * sys/kernel/config/iscsi/$IQN/$TPG/np/$IP:$PORT/ |
233 | * |
234 | */ |
235 | tpg_np = iscsit_tpg_add_network_portal(tpg, &sockaddr, NULL, |
236 | ISCSI_TCP); |
237 | if (IS_ERR(ptr: tpg_np)) { |
238 | iscsit_put_tpg(tpg); |
239 | return ERR_CAST(ptr: tpg_np); |
240 | } |
241 | pr_debug("LIO_Target_ConfigFS: addnptotpg done!\n" ); |
242 | |
243 | iscsit_put_tpg(tpg); |
244 | return &tpg_np->se_tpg_np; |
245 | } |
246 | |
247 | static void lio_target_call_delnpfromtpg( |
248 | struct se_tpg_np *se_tpg_np) |
249 | { |
250 | struct iscsi_portal_group *tpg; |
251 | struct iscsi_tpg_np *tpg_np; |
252 | struct se_portal_group *se_tpg; |
253 | int ret; |
254 | |
255 | tpg_np = container_of(se_tpg_np, struct iscsi_tpg_np, se_tpg_np); |
256 | tpg = tpg_np->tpg; |
257 | ret = iscsit_get_tpg(tpg); |
258 | if (ret < 0) |
259 | return; |
260 | |
261 | se_tpg = &tpg->tpg_se_tpg; |
262 | pr_debug("LIO_Target_ConfigFS: DEREGISTER -> %s TPGT: %hu" |
263 | " PORTAL: %pISpc\n" , config_item_name(&se_tpg->se_tpg_wwn->wwn_group.cg_item), |
264 | tpg->tpgt, &tpg_np->tpg_np->np_sockaddr); |
265 | |
266 | ret = iscsit_tpg_del_network_portal(tpg, tpg_np); |
267 | if (ret < 0) |
268 | goto out; |
269 | |
270 | pr_debug("LIO_Target_ConfigFS: delnpfromtpg done!\n" ); |
271 | out: |
272 | iscsit_put_tpg(tpg); |
273 | } |
274 | |
275 | /* End items for lio_target_np_cit */ |
276 | |
277 | /* Start items for lio_target_nacl_attrib_cit */ |
278 | |
279 | #define ISCSI_NACL_ATTR(name) \ |
280 | static ssize_t iscsi_nacl_attrib_##name##_show(struct config_item *item,\ |
281 | char *page) \ |
282 | { \ |
283 | struct se_node_acl *se_nacl = attrib_to_nacl(item); \ |
284 | struct iscsi_node_acl *nacl = to_iscsi_nacl(se_nacl); \ |
285 | return sysfs_emit(page, "%u\n", nacl->node_attrib.name); \ |
286 | } \ |
287 | \ |
288 | static ssize_t iscsi_nacl_attrib_##name##_store(struct config_item *item,\ |
289 | const char *page, size_t count) \ |
290 | { \ |
291 | struct se_node_acl *se_nacl = attrib_to_nacl(item); \ |
292 | struct iscsi_node_acl *nacl = to_iscsi_nacl(se_nacl); \ |
293 | u32 val; \ |
294 | int ret; \ |
295 | \ |
296 | ret = kstrtou32(page, 0, &val); \ |
297 | if (ret) \ |
298 | return ret; \ |
299 | ret = iscsit_na_##name(nacl, val); \ |
300 | if (ret < 0) \ |
301 | return ret; \ |
302 | \ |
303 | return count; \ |
304 | } \ |
305 | \ |
306 | CONFIGFS_ATTR(iscsi_nacl_attrib_, name) |
307 | |
308 | ISCSI_NACL_ATTR(dataout_timeout); |
309 | ISCSI_NACL_ATTR(dataout_timeout_retries); |
310 | ISCSI_NACL_ATTR(default_erl); |
311 | ISCSI_NACL_ATTR(nopin_timeout); |
312 | ISCSI_NACL_ATTR(nopin_response_timeout); |
313 | ISCSI_NACL_ATTR(random_datain_pdu_offsets); |
314 | ISCSI_NACL_ATTR(random_datain_seq_offsets); |
315 | ISCSI_NACL_ATTR(random_r2t_offsets); |
316 | |
317 | static ssize_t iscsi_nacl_attrib_authentication_show(struct config_item *item, |
318 | char *page) |
319 | { |
320 | struct se_node_acl *se_nacl = attrib_to_nacl(item); |
321 | struct iscsi_node_acl *nacl = to_iscsi_nacl(se_nacl); |
322 | |
323 | return sysfs_emit(buf: page, fmt: "%d\n" , nacl->node_attrib.authentication); |
324 | } |
325 | |
326 | static ssize_t iscsi_nacl_attrib_authentication_store(struct config_item *item, |
327 | const char *page, size_t count) |
328 | { |
329 | struct se_node_acl *se_nacl = attrib_to_nacl(item); |
330 | struct iscsi_node_acl *nacl = to_iscsi_nacl(se_nacl); |
331 | s32 val; |
332 | int ret; |
333 | |
334 | ret = kstrtos32(s: page, base: 0, res: &val); |
335 | if (ret) |
336 | return ret; |
337 | if (val != 0 && val != 1 && val != NA_AUTHENTICATION_INHERITED) |
338 | return -EINVAL; |
339 | |
340 | nacl->node_attrib.authentication = val; |
341 | |
342 | return count; |
343 | } |
344 | |
345 | CONFIGFS_ATTR(iscsi_nacl_attrib_, authentication); |
346 | |
347 | static struct configfs_attribute *lio_target_nacl_attrib_attrs[] = { |
348 | &iscsi_nacl_attrib_attr_dataout_timeout, |
349 | &iscsi_nacl_attrib_attr_dataout_timeout_retries, |
350 | &iscsi_nacl_attrib_attr_default_erl, |
351 | &iscsi_nacl_attrib_attr_nopin_timeout, |
352 | &iscsi_nacl_attrib_attr_nopin_response_timeout, |
353 | &iscsi_nacl_attrib_attr_random_datain_pdu_offsets, |
354 | &iscsi_nacl_attrib_attr_random_datain_seq_offsets, |
355 | &iscsi_nacl_attrib_attr_random_r2t_offsets, |
356 | &iscsi_nacl_attrib_attr_authentication, |
357 | NULL, |
358 | }; |
359 | |
360 | /* End items for lio_target_nacl_attrib_cit */ |
361 | |
362 | /* Start items for lio_target_nacl_auth_cit */ |
363 | |
364 | #define __DEF_NACL_AUTH_STR(prefix, name, flags) \ |
365 | static ssize_t __iscsi_##prefix##_##name##_show( \ |
366 | struct iscsi_node_acl *nacl, \ |
367 | char *page) \ |
368 | { \ |
369 | struct iscsi_node_auth *auth = &nacl->node_auth; \ |
370 | \ |
371 | if (!capable(CAP_SYS_ADMIN)) \ |
372 | return -EPERM; \ |
373 | return snprintf(page, PAGE_SIZE, "%s\n", auth->name); \ |
374 | } \ |
375 | \ |
376 | static ssize_t __iscsi_##prefix##_##name##_store( \ |
377 | struct iscsi_node_acl *nacl, \ |
378 | const char *page, \ |
379 | size_t count) \ |
380 | { \ |
381 | struct iscsi_node_auth *auth = &nacl->node_auth; \ |
382 | \ |
383 | if (!capable(CAP_SYS_ADMIN)) \ |
384 | return -EPERM; \ |
385 | if (count >= sizeof(auth->name)) \ |
386 | return -EINVAL; \ |
387 | snprintf(auth->name, sizeof(auth->name), "%s", page); \ |
388 | if (!strncmp("NULL", auth->name, 4)) \ |
389 | auth->naf_flags &= ~flags; \ |
390 | else \ |
391 | auth->naf_flags |= flags; \ |
392 | \ |
393 | if ((auth->naf_flags & NAF_USERID_IN_SET) && \ |
394 | (auth->naf_flags & NAF_PASSWORD_IN_SET)) \ |
395 | auth->authenticate_target = 1; \ |
396 | else \ |
397 | auth->authenticate_target = 0; \ |
398 | \ |
399 | return count; \ |
400 | } |
401 | |
402 | #define DEF_NACL_AUTH_STR(name, flags) \ |
403 | __DEF_NACL_AUTH_STR(nacl_auth, name, flags) \ |
404 | static ssize_t iscsi_nacl_auth_##name##_show(struct config_item *item, \ |
405 | char *page) \ |
406 | { \ |
407 | struct se_node_acl *nacl = auth_to_nacl(item); \ |
408 | return __iscsi_nacl_auth_##name##_show(to_iscsi_nacl(nacl), page); \ |
409 | } \ |
410 | static ssize_t iscsi_nacl_auth_##name##_store(struct config_item *item, \ |
411 | const char *page, size_t count) \ |
412 | { \ |
413 | struct se_node_acl *nacl = auth_to_nacl(item); \ |
414 | return __iscsi_nacl_auth_##name##_store(to_iscsi_nacl(nacl), \ |
415 | page, count); \ |
416 | } \ |
417 | \ |
418 | CONFIGFS_ATTR(iscsi_nacl_auth_, name) |
419 | |
420 | /* |
421 | * One-way authentication userid |
422 | */ |
423 | DEF_NACL_AUTH_STR(userid, NAF_USERID_SET); |
424 | DEF_NACL_AUTH_STR(password, NAF_PASSWORD_SET); |
425 | DEF_NACL_AUTH_STR(userid_mutual, NAF_USERID_IN_SET); |
426 | DEF_NACL_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET); |
427 | |
428 | #define __DEF_NACL_AUTH_INT(prefix, name) \ |
429 | static ssize_t __iscsi_##prefix##_##name##_show( \ |
430 | struct iscsi_node_acl *nacl, \ |
431 | char *page) \ |
432 | { \ |
433 | struct iscsi_node_auth *auth = &nacl->node_auth; \ |
434 | \ |
435 | if (!capable(CAP_SYS_ADMIN)) \ |
436 | return -EPERM; \ |
437 | \ |
438 | return snprintf(page, PAGE_SIZE, "%d\n", auth->name); \ |
439 | } |
440 | |
441 | #define DEF_NACL_AUTH_INT(name) \ |
442 | __DEF_NACL_AUTH_INT(nacl_auth, name) \ |
443 | static ssize_t iscsi_nacl_auth_##name##_show(struct config_item *item, \ |
444 | char *page) \ |
445 | { \ |
446 | struct se_node_acl *nacl = auth_to_nacl(item); \ |
447 | return __iscsi_nacl_auth_##name##_show(to_iscsi_nacl(nacl), page); \ |
448 | } \ |
449 | \ |
450 | CONFIGFS_ATTR_RO(iscsi_nacl_auth_, name) |
451 | |
452 | DEF_NACL_AUTH_INT(authenticate_target); |
453 | |
454 | static struct configfs_attribute *lio_target_nacl_auth_attrs[] = { |
455 | &iscsi_nacl_auth_attr_userid, |
456 | &iscsi_nacl_auth_attr_password, |
457 | &iscsi_nacl_auth_attr_authenticate_target, |
458 | &iscsi_nacl_auth_attr_userid_mutual, |
459 | &iscsi_nacl_auth_attr_password_mutual, |
460 | NULL, |
461 | }; |
462 | |
463 | /* End items for lio_target_nacl_auth_cit */ |
464 | |
465 | /* Start items for lio_target_nacl_param_cit */ |
466 | |
467 | #define ISCSI_NACL_PARAM(name) \ |
468 | static ssize_t iscsi_nacl_param_##name##_show(struct config_item *item, \ |
469 | char *page) \ |
470 | { \ |
471 | struct se_node_acl *se_nacl = param_to_nacl(item); \ |
472 | struct iscsit_session *sess; \ |
473 | struct se_session *se_sess; \ |
474 | ssize_t rb; \ |
475 | \ |
476 | spin_lock_bh(&se_nacl->nacl_sess_lock); \ |
477 | se_sess = se_nacl->nacl_sess; \ |
478 | if (!se_sess) { \ |
479 | rb = snprintf(page, PAGE_SIZE, \ |
480 | "No Active iSCSI Session\n"); \ |
481 | } else { \ |
482 | sess = se_sess->fabric_sess_ptr; \ |
483 | rb = snprintf(page, PAGE_SIZE, "%u\n", \ |
484 | (u32)sess->sess_ops->name); \ |
485 | } \ |
486 | spin_unlock_bh(&se_nacl->nacl_sess_lock); \ |
487 | \ |
488 | return rb; \ |
489 | } \ |
490 | \ |
491 | CONFIGFS_ATTR_RO(iscsi_nacl_param_, name) |
492 | |
493 | ISCSI_NACL_PARAM(MaxConnections); |
494 | ISCSI_NACL_PARAM(InitialR2T); |
495 | ISCSI_NACL_PARAM(ImmediateData); |
496 | ISCSI_NACL_PARAM(MaxBurstLength); |
497 | ISCSI_NACL_PARAM(FirstBurstLength); |
498 | ISCSI_NACL_PARAM(DefaultTime2Wait); |
499 | ISCSI_NACL_PARAM(DefaultTime2Retain); |
500 | ISCSI_NACL_PARAM(MaxOutstandingR2T); |
501 | ISCSI_NACL_PARAM(DataPDUInOrder); |
502 | ISCSI_NACL_PARAM(DataSequenceInOrder); |
503 | ISCSI_NACL_PARAM(ErrorRecoveryLevel); |
504 | |
505 | static struct configfs_attribute *lio_target_nacl_param_attrs[] = { |
506 | &iscsi_nacl_param_attr_MaxConnections, |
507 | &iscsi_nacl_param_attr_InitialR2T, |
508 | &iscsi_nacl_param_attr_ImmediateData, |
509 | &iscsi_nacl_param_attr_MaxBurstLength, |
510 | &iscsi_nacl_param_attr_FirstBurstLength, |
511 | &iscsi_nacl_param_attr_DefaultTime2Wait, |
512 | &iscsi_nacl_param_attr_DefaultTime2Retain, |
513 | &iscsi_nacl_param_attr_MaxOutstandingR2T, |
514 | &iscsi_nacl_param_attr_DataPDUInOrder, |
515 | &iscsi_nacl_param_attr_DataSequenceInOrder, |
516 | &iscsi_nacl_param_attr_ErrorRecoveryLevel, |
517 | NULL, |
518 | }; |
519 | |
520 | /* End items for lio_target_nacl_param_cit */ |
521 | |
522 | /* Start items for lio_target_acl_cit */ |
523 | |
524 | static ssize_t lio_target_nacl_info_show(struct config_item *item, char *page) |
525 | { |
526 | struct se_node_acl *se_nacl = acl_to_nacl(item); |
527 | struct iscsit_session *sess; |
528 | struct iscsit_conn *conn; |
529 | struct se_session *se_sess; |
530 | ssize_t rb = 0; |
531 | u32 max_cmd_sn; |
532 | |
533 | spin_lock_bh(lock: &se_nacl->nacl_sess_lock); |
534 | se_sess = se_nacl->nacl_sess; |
535 | if (!se_sess) { |
536 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "No active iSCSI Session for Initiator" |
537 | " Endpoint: %s\n" , se_nacl->initiatorname); |
538 | } else { |
539 | sess = se_sess->fabric_sess_ptr; |
540 | |
541 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "InitiatorName: %s\n" , |
542 | sess->sess_ops->InitiatorName); |
543 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "InitiatorAlias: %s\n" , |
544 | sess->sess_ops->InitiatorAlias); |
545 | |
546 | rb += sysfs_emit_at(buf: page, at: rb, |
547 | fmt: "LIO Session ID: %u ISID: 0x%6ph TSIH: %hu " , |
548 | sess->sid, sess->isid, sess->tsih); |
549 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "SessionType: %s\n" , |
550 | (sess->sess_ops->SessionType) ? |
551 | "Discovery" : "Normal" ); |
552 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "Session State: " ); |
553 | switch (sess->session_state) { |
554 | case TARG_SESS_STATE_FREE: |
555 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "TARG_SESS_FREE\n" ); |
556 | break; |
557 | case TARG_SESS_STATE_ACTIVE: |
558 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "TARG_SESS_STATE_ACTIVE\n" ); |
559 | break; |
560 | case TARG_SESS_STATE_LOGGED_IN: |
561 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "TARG_SESS_STATE_LOGGED_IN\n" ); |
562 | break; |
563 | case TARG_SESS_STATE_FAILED: |
564 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "TARG_SESS_STATE_FAILED\n" ); |
565 | break; |
566 | case TARG_SESS_STATE_IN_CONTINUE: |
567 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "TARG_SESS_STATE_IN_CONTINUE\n" ); |
568 | break; |
569 | default: |
570 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "ERROR: Unknown Session" |
571 | " State!\n" ); |
572 | break; |
573 | } |
574 | |
575 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "---------------------[iSCSI Session" |
576 | " Values]-----------------------\n" ); |
577 | rb += sysfs_emit_at(buf: page, at: rb, fmt: " CmdSN/WR : CmdSN/WC : ExpCmdSN" |
578 | " : MaxCmdSN : ITT : TTT\n" ); |
579 | max_cmd_sn = (u32) atomic_read(v: &sess->max_cmd_sn); |
580 | rb += sysfs_emit_at(buf: page, at: rb, fmt: " 0x%08x 0x%08x 0x%08x 0x%08x" |
581 | " 0x%08x 0x%08x\n" , |
582 | sess->cmdsn_window, |
583 | (max_cmd_sn - sess->exp_cmd_sn) + 1, |
584 | sess->exp_cmd_sn, max_cmd_sn, |
585 | sess->init_task_tag, sess->targ_xfer_tag); |
586 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "----------------------[iSCSI" |
587 | " Connections]-------------------------\n" ); |
588 | |
589 | spin_lock(lock: &sess->conn_lock); |
590 | list_for_each_entry(conn, &sess->sess_conn_list, conn_list) { |
591 | rb += sysfs_emit_at(buf: page, at: rb, fmt: "CID: %hu Connection" |
592 | " State: " , conn->cid); |
593 | switch (conn->conn_state) { |
594 | case TARG_CONN_STATE_FREE: |
595 | rb += sysfs_emit_at(buf: page, at: rb, |
596 | fmt: "TARG_CONN_STATE_FREE\n" ); |
597 | break; |
598 | case TARG_CONN_STATE_XPT_UP: |
599 | rb += sysfs_emit_at(buf: page, at: rb, |
600 | fmt: "TARG_CONN_STATE_XPT_UP\n" ); |
601 | break; |
602 | case TARG_CONN_STATE_IN_LOGIN: |
603 | rb += sysfs_emit_at(buf: page, at: rb, |
604 | fmt: "TARG_CONN_STATE_IN_LOGIN\n" ); |
605 | break; |
606 | case TARG_CONN_STATE_LOGGED_IN: |
607 | rb += sysfs_emit_at(buf: page, at: rb, |
608 | fmt: "TARG_CONN_STATE_LOGGED_IN\n" ); |
609 | break; |
610 | case TARG_CONN_STATE_IN_LOGOUT: |
611 | rb += sysfs_emit_at(buf: page, at: rb, |
612 | fmt: "TARG_CONN_STATE_IN_LOGOUT\n" ); |
613 | break; |
614 | case TARG_CONN_STATE_LOGOUT_REQUESTED: |
615 | rb += sysfs_emit_at(buf: page, at: rb, |
616 | fmt: "TARG_CONN_STATE_LOGOUT_REQUESTED\n" ); |
617 | break; |
618 | case TARG_CONN_STATE_CLEANUP_WAIT: |
619 | rb += sysfs_emit_at(buf: page, at: rb, |
620 | fmt: "TARG_CONN_STATE_CLEANUP_WAIT\n" ); |
621 | break; |
622 | default: |
623 | rb += sysfs_emit_at(buf: page, at: rb, |
624 | fmt: "ERROR: Unknown Connection State!\n" ); |
625 | break; |
626 | } |
627 | |
628 | rb += sysfs_emit_at(buf: page, at: rb, fmt: " Address %pISc %s" , &conn->login_sockaddr, |
629 | (conn->network_transport == ISCSI_TCP) ? |
630 | "TCP" : "SCTP" ); |
631 | rb += sysfs_emit_at(buf: page, at: rb, fmt: " StatSN: 0x%08x\n" , |
632 | conn->stat_sn); |
633 | } |
634 | spin_unlock(lock: &sess->conn_lock); |
635 | } |
636 | spin_unlock_bh(lock: &se_nacl->nacl_sess_lock); |
637 | |
638 | return rb; |
639 | } |
640 | |
641 | static ssize_t lio_target_nacl_cmdsn_depth_show(struct config_item *item, |
642 | char *page) |
643 | { |
644 | return sysfs_emit(buf: page, fmt: "%u\n" , acl_to_nacl(item)->queue_depth); |
645 | } |
646 | |
647 | static ssize_t lio_target_nacl_cmdsn_depth_store(struct config_item *item, |
648 | const char *page, size_t count) |
649 | { |
650 | struct se_node_acl *se_nacl = acl_to_nacl(item); |
651 | struct se_portal_group *se_tpg = se_nacl->se_tpg; |
652 | struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); |
653 | struct config_item *acl_ci, *tpg_ci, *wwn_ci; |
654 | u32 cmdsn_depth = 0; |
655 | int ret; |
656 | |
657 | ret = kstrtou32(s: page, base: 0, res: &cmdsn_depth); |
658 | if (ret) |
659 | return ret; |
660 | if (cmdsn_depth > TA_DEFAULT_CMDSN_DEPTH_MAX) { |
661 | pr_err("Passed cmdsn_depth: %u exceeds" |
662 | " TA_DEFAULT_CMDSN_DEPTH_MAX: %u\n" , cmdsn_depth, |
663 | TA_DEFAULT_CMDSN_DEPTH_MAX); |
664 | return -EINVAL; |
665 | } |
666 | acl_ci = &se_nacl->acl_group.cg_item; |
667 | if (!acl_ci) { |
668 | pr_err("Unable to locatel acl_ci\n" ); |
669 | return -EINVAL; |
670 | } |
671 | tpg_ci = &acl_ci->ci_parent->ci_group->cg_item; |
672 | if (!tpg_ci) { |
673 | pr_err("Unable to locate tpg_ci\n" ); |
674 | return -EINVAL; |
675 | } |
676 | wwn_ci = &tpg_ci->ci_group->cg_item; |
677 | if (!wwn_ci) { |
678 | pr_err("Unable to locate config_item wwn_ci\n" ); |
679 | return -EINVAL; |
680 | } |
681 | |
682 | if (iscsit_get_tpg(tpg) < 0) |
683 | return -EINVAL; |
684 | |
685 | ret = core_tpg_set_initiator_node_queue_depth(se_nacl, cmdsn_depth); |
686 | |
687 | pr_debug("LIO_Target_ConfigFS: %s/%s Set CmdSN Window: %u for" |
688 | "InitiatorName: %s\n" , config_item_name(wwn_ci), |
689 | config_item_name(tpg_ci), cmdsn_depth, |
690 | config_item_name(acl_ci)); |
691 | |
692 | iscsit_put_tpg(tpg); |
693 | return (!ret) ? count : (ssize_t)ret; |
694 | } |
695 | |
696 | static ssize_t lio_target_nacl_tag_show(struct config_item *item, char *page) |
697 | { |
698 | return snprintf(buf: page, PAGE_SIZE, fmt: "%s" , acl_to_nacl(item)->acl_tag); |
699 | } |
700 | |
701 | static ssize_t lio_target_nacl_tag_store(struct config_item *item, |
702 | const char *page, size_t count) |
703 | { |
704 | struct se_node_acl *se_nacl = acl_to_nacl(item); |
705 | int ret; |
706 | |
707 | ret = core_tpg_set_initiator_node_tag(se_nacl->se_tpg, se_nacl, page); |
708 | |
709 | if (ret < 0) |
710 | return ret; |
711 | return count; |
712 | } |
713 | |
714 | CONFIGFS_ATTR_RO(lio_target_nacl_, info); |
715 | CONFIGFS_ATTR(lio_target_nacl_, cmdsn_depth); |
716 | CONFIGFS_ATTR(lio_target_nacl_, tag); |
717 | |
718 | static struct configfs_attribute *lio_target_initiator_attrs[] = { |
719 | &lio_target_nacl_attr_info, |
720 | &lio_target_nacl_attr_cmdsn_depth, |
721 | &lio_target_nacl_attr_tag, |
722 | NULL, |
723 | }; |
724 | |
725 | static int lio_target_init_nodeacl(struct se_node_acl *se_nacl, |
726 | const char *name) |
727 | { |
728 | struct iscsi_node_acl *acl = to_iscsi_nacl(se_nacl); |
729 | |
730 | config_group_init_type_name(group: &acl->node_stat_grps.iscsi_sess_stats_group, |
731 | name: "iscsi_sess_stats" , type: &iscsi_stat_sess_cit); |
732 | configfs_add_default_group(new_group: &acl->node_stat_grps.iscsi_sess_stats_group, |
733 | group: &se_nacl->acl_fabric_stat_group); |
734 | return 0; |
735 | } |
736 | |
737 | /* End items for lio_target_acl_cit */ |
738 | |
739 | /* Start items for lio_target_tpg_attrib_cit */ |
740 | |
741 | #define DEF_TPG_ATTRIB(name) \ |
742 | \ |
743 | static ssize_t iscsi_tpg_attrib_##name##_show(struct config_item *item, \ |
744 | char *page) \ |
745 | { \ |
746 | struct se_portal_group *se_tpg = attrib_to_tpg(item); \ |
747 | struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ |
748 | ssize_t rb; \ |
749 | \ |
750 | if (iscsit_get_tpg(tpg) < 0) \ |
751 | return -EINVAL; \ |
752 | \ |
753 | rb = sysfs_emit(page, "%u\n", tpg->tpg_attrib.name); \ |
754 | iscsit_put_tpg(tpg); \ |
755 | return rb; \ |
756 | } \ |
757 | \ |
758 | static ssize_t iscsi_tpg_attrib_##name##_store(struct config_item *item,\ |
759 | const char *page, size_t count) \ |
760 | { \ |
761 | struct se_portal_group *se_tpg = attrib_to_tpg(item); \ |
762 | struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ |
763 | u32 val; \ |
764 | int ret; \ |
765 | \ |
766 | if (iscsit_get_tpg(tpg) < 0) \ |
767 | return -EINVAL; \ |
768 | \ |
769 | ret = kstrtou32(page, 0, &val); \ |
770 | if (ret) \ |
771 | goto out; \ |
772 | ret = iscsit_ta_##name(tpg, val); \ |
773 | if (ret < 0) \ |
774 | goto out; \ |
775 | \ |
776 | iscsit_put_tpg(tpg); \ |
777 | return count; \ |
778 | out: \ |
779 | iscsit_put_tpg(tpg); \ |
780 | return ret; \ |
781 | } \ |
782 | CONFIGFS_ATTR(iscsi_tpg_attrib_, name) |
783 | |
784 | DEF_TPG_ATTRIB(authentication); |
785 | DEF_TPG_ATTRIB(login_timeout); |
786 | DEF_TPG_ATTRIB(generate_node_acls); |
787 | DEF_TPG_ATTRIB(default_cmdsn_depth); |
788 | DEF_TPG_ATTRIB(cache_dynamic_acls); |
789 | DEF_TPG_ATTRIB(demo_mode_write_protect); |
790 | DEF_TPG_ATTRIB(prod_mode_write_protect); |
791 | DEF_TPG_ATTRIB(demo_mode_discovery); |
792 | DEF_TPG_ATTRIB(default_erl); |
793 | DEF_TPG_ATTRIB(t10_pi); |
794 | DEF_TPG_ATTRIB(fabric_prot_type); |
795 | DEF_TPG_ATTRIB(tpg_enabled_sendtargets); |
796 | DEF_TPG_ATTRIB(login_keys_workaround); |
797 | |
798 | static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = { |
799 | &iscsi_tpg_attrib_attr_authentication, |
800 | &iscsi_tpg_attrib_attr_login_timeout, |
801 | &iscsi_tpg_attrib_attr_generate_node_acls, |
802 | &iscsi_tpg_attrib_attr_default_cmdsn_depth, |
803 | &iscsi_tpg_attrib_attr_cache_dynamic_acls, |
804 | &iscsi_tpg_attrib_attr_demo_mode_write_protect, |
805 | &iscsi_tpg_attrib_attr_prod_mode_write_protect, |
806 | &iscsi_tpg_attrib_attr_demo_mode_discovery, |
807 | &iscsi_tpg_attrib_attr_default_erl, |
808 | &iscsi_tpg_attrib_attr_t10_pi, |
809 | &iscsi_tpg_attrib_attr_fabric_prot_type, |
810 | &iscsi_tpg_attrib_attr_tpg_enabled_sendtargets, |
811 | &iscsi_tpg_attrib_attr_login_keys_workaround, |
812 | NULL, |
813 | }; |
814 | |
815 | /* End items for lio_target_tpg_attrib_cit */ |
816 | |
817 | /* Start items for lio_target_tpg_auth_cit */ |
818 | |
819 | #define __DEF_TPG_AUTH_STR(prefix, name, flags) \ |
820 | static ssize_t __iscsi_##prefix##_##name##_show(struct se_portal_group *se_tpg, \ |
821 | char *page) \ |
822 | { \ |
823 | struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ |
824 | struct iscsi_node_auth *auth = &tpg->tpg_demo_auth; \ |
825 | \ |
826 | if (!capable(CAP_SYS_ADMIN)) \ |
827 | return -EPERM; \ |
828 | \ |
829 | return snprintf(page, PAGE_SIZE, "%s\n", auth->name); \ |
830 | } \ |
831 | \ |
832 | static ssize_t __iscsi_##prefix##_##name##_store(struct se_portal_group *se_tpg,\ |
833 | const char *page, size_t count) \ |
834 | { \ |
835 | struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ |
836 | struct iscsi_node_auth *auth = &tpg->tpg_demo_auth; \ |
837 | \ |
838 | if (!capable(CAP_SYS_ADMIN)) \ |
839 | return -EPERM; \ |
840 | \ |
841 | snprintf(auth->name, sizeof(auth->name), "%s", page); \ |
842 | if (!(strncmp("NULL", auth->name, 4))) \ |
843 | auth->naf_flags &= ~flags; \ |
844 | else \ |
845 | auth->naf_flags |= flags; \ |
846 | \ |
847 | if ((auth->naf_flags & NAF_USERID_IN_SET) && \ |
848 | (auth->naf_flags & NAF_PASSWORD_IN_SET)) \ |
849 | auth->authenticate_target = 1; \ |
850 | else \ |
851 | auth->authenticate_target = 0; \ |
852 | \ |
853 | return count; \ |
854 | } |
855 | |
856 | #define DEF_TPG_AUTH_STR(name, flags) \ |
857 | __DEF_TPG_AUTH_STR(tpg_auth, name, flags) \ |
858 | static ssize_t iscsi_tpg_auth_##name##_show(struct config_item *item, \ |
859 | char *page) \ |
860 | { \ |
861 | return __iscsi_tpg_auth_##name##_show(auth_to_tpg(item), page); \ |
862 | } \ |
863 | \ |
864 | static ssize_t iscsi_tpg_auth_##name##_store(struct config_item *item, \ |
865 | const char *page, size_t count) \ |
866 | { \ |
867 | return __iscsi_tpg_auth_##name##_store(auth_to_tpg(item), page, count); \ |
868 | } \ |
869 | \ |
870 | CONFIGFS_ATTR(iscsi_tpg_auth_, name); |
871 | |
872 | |
873 | DEF_TPG_AUTH_STR(userid, NAF_USERID_SET); |
874 | DEF_TPG_AUTH_STR(password, NAF_PASSWORD_SET); |
875 | DEF_TPG_AUTH_STR(userid_mutual, NAF_USERID_IN_SET); |
876 | DEF_TPG_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET); |
877 | |
878 | #define __DEF_TPG_AUTH_INT(prefix, name) \ |
879 | static ssize_t __iscsi_##prefix##_##name##_show(struct se_portal_group *se_tpg, \ |
880 | char *page) \ |
881 | { \ |
882 | struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ |
883 | struct iscsi_node_auth *auth = &tpg->tpg_demo_auth; \ |
884 | \ |
885 | if (!capable(CAP_SYS_ADMIN)) \ |
886 | return -EPERM; \ |
887 | \ |
888 | return snprintf(page, PAGE_SIZE, "%d\n", auth->name); \ |
889 | } |
890 | |
891 | #define DEF_TPG_AUTH_INT(name) \ |
892 | __DEF_TPG_AUTH_INT(tpg_auth, name) \ |
893 | static ssize_t iscsi_tpg_auth_##name##_show(struct config_item *item, \ |
894 | char *page) \ |
895 | { \ |
896 | return __iscsi_tpg_auth_##name##_show(auth_to_tpg(item), page); \ |
897 | } \ |
898 | CONFIGFS_ATTR_RO(iscsi_tpg_auth_, name); |
899 | |
900 | DEF_TPG_AUTH_INT(authenticate_target); |
901 | |
902 | static struct configfs_attribute *lio_target_tpg_auth_attrs[] = { |
903 | &iscsi_tpg_auth_attr_userid, |
904 | &iscsi_tpg_auth_attr_password, |
905 | &iscsi_tpg_auth_attr_authenticate_target, |
906 | &iscsi_tpg_auth_attr_userid_mutual, |
907 | &iscsi_tpg_auth_attr_password_mutual, |
908 | NULL, |
909 | }; |
910 | |
911 | /* End items for lio_target_tpg_auth_cit */ |
912 | |
913 | /* Start items for lio_target_tpg_param_cit */ |
914 | |
915 | #define DEF_TPG_PARAM(name) \ |
916 | static ssize_t iscsi_tpg_param_##name##_show(struct config_item *item, \ |
917 | char *page) \ |
918 | { \ |
919 | struct se_portal_group *se_tpg = param_to_tpg(item); \ |
920 | struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ |
921 | struct iscsi_param *param; \ |
922 | ssize_t rb; \ |
923 | \ |
924 | if (iscsit_get_tpg(tpg) < 0) \ |
925 | return -EINVAL; \ |
926 | \ |
927 | param = iscsi_find_param_from_key(__stringify(name), \ |
928 | tpg->param_list); \ |
929 | if (!param) { \ |
930 | iscsit_put_tpg(tpg); \ |
931 | return -EINVAL; \ |
932 | } \ |
933 | rb = snprintf(page, PAGE_SIZE, "%s\n", param->value); \ |
934 | \ |
935 | iscsit_put_tpg(tpg); \ |
936 | return rb; \ |
937 | } \ |
938 | static ssize_t iscsi_tpg_param_##name##_store(struct config_item *item, \ |
939 | const char *page, size_t count) \ |
940 | { \ |
941 | struct se_portal_group *se_tpg = param_to_tpg(item); \ |
942 | struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); \ |
943 | char *buf; \ |
944 | int ret, len; \ |
945 | \ |
946 | buf = kzalloc(PAGE_SIZE, GFP_KERNEL); \ |
947 | if (!buf) \ |
948 | return -ENOMEM; \ |
949 | len = snprintf(buf, PAGE_SIZE, "%s=%s", __stringify(name), page); \ |
950 | if (isspace(buf[len-1])) \ |
951 | buf[len-1] = '\0'; /* Kill newline */ \ |
952 | \ |
953 | if (iscsit_get_tpg(tpg) < 0) { \ |
954 | kfree(buf); \ |
955 | return -EINVAL; \ |
956 | } \ |
957 | \ |
958 | ret = iscsi_change_param_value(buf, tpg->param_list, 1); \ |
959 | if (ret < 0) \ |
960 | goto out; \ |
961 | \ |
962 | kfree(buf); \ |
963 | iscsit_put_tpg(tpg); \ |
964 | return count; \ |
965 | out: \ |
966 | kfree(buf); \ |
967 | iscsit_put_tpg(tpg); \ |
968 | return -EINVAL; \ |
969 | } \ |
970 | CONFIGFS_ATTR(iscsi_tpg_param_, name) |
971 | |
972 | DEF_TPG_PARAM(AuthMethod); |
973 | DEF_TPG_PARAM(HeaderDigest); |
974 | DEF_TPG_PARAM(DataDigest); |
975 | DEF_TPG_PARAM(MaxConnections); |
976 | DEF_TPG_PARAM(TargetAlias); |
977 | DEF_TPG_PARAM(InitialR2T); |
978 | DEF_TPG_PARAM(ImmediateData); |
979 | DEF_TPG_PARAM(MaxRecvDataSegmentLength); |
980 | DEF_TPG_PARAM(MaxXmitDataSegmentLength); |
981 | DEF_TPG_PARAM(MaxBurstLength); |
982 | DEF_TPG_PARAM(FirstBurstLength); |
983 | DEF_TPG_PARAM(DefaultTime2Wait); |
984 | DEF_TPG_PARAM(DefaultTime2Retain); |
985 | DEF_TPG_PARAM(MaxOutstandingR2T); |
986 | DEF_TPG_PARAM(DataPDUInOrder); |
987 | DEF_TPG_PARAM(DataSequenceInOrder); |
988 | DEF_TPG_PARAM(ErrorRecoveryLevel); |
989 | DEF_TPG_PARAM(IFMarker); |
990 | DEF_TPG_PARAM(OFMarker); |
991 | DEF_TPG_PARAM(IFMarkInt); |
992 | DEF_TPG_PARAM(OFMarkInt); |
993 | |
994 | static struct configfs_attribute *lio_target_tpg_param_attrs[] = { |
995 | &iscsi_tpg_param_attr_AuthMethod, |
996 | &iscsi_tpg_param_attr_HeaderDigest, |
997 | &iscsi_tpg_param_attr_DataDigest, |
998 | &iscsi_tpg_param_attr_MaxConnections, |
999 | &iscsi_tpg_param_attr_TargetAlias, |
1000 | &iscsi_tpg_param_attr_InitialR2T, |
1001 | &iscsi_tpg_param_attr_ImmediateData, |
1002 | &iscsi_tpg_param_attr_MaxRecvDataSegmentLength, |
1003 | &iscsi_tpg_param_attr_MaxXmitDataSegmentLength, |
1004 | &iscsi_tpg_param_attr_MaxBurstLength, |
1005 | &iscsi_tpg_param_attr_FirstBurstLength, |
1006 | &iscsi_tpg_param_attr_DefaultTime2Wait, |
1007 | &iscsi_tpg_param_attr_DefaultTime2Retain, |
1008 | &iscsi_tpg_param_attr_MaxOutstandingR2T, |
1009 | &iscsi_tpg_param_attr_DataPDUInOrder, |
1010 | &iscsi_tpg_param_attr_DataSequenceInOrder, |
1011 | &iscsi_tpg_param_attr_ErrorRecoveryLevel, |
1012 | &iscsi_tpg_param_attr_IFMarker, |
1013 | &iscsi_tpg_param_attr_OFMarker, |
1014 | &iscsi_tpg_param_attr_IFMarkInt, |
1015 | &iscsi_tpg_param_attr_OFMarkInt, |
1016 | NULL, |
1017 | }; |
1018 | |
1019 | /* End items for lio_target_tpg_param_cit */ |
1020 | |
1021 | /* Start items for lio_target_tpg_cit */ |
1022 | |
1023 | static ssize_t lio_target_tpg_dynamic_sessions_show(struct config_item *item, |
1024 | char *page) |
1025 | { |
1026 | return target_show_dynamic_sessions(to_tpg(item), page); |
1027 | } |
1028 | |
1029 | CONFIGFS_ATTR_RO(lio_target_tpg_, dynamic_sessions); |
1030 | |
1031 | static struct configfs_attribute *lio_target_tpg_attrs[] = { |
1032 | &lio_target_tpg_attr_dynamic_sessions, |
1033 | NULL, |
1034 | }; |
1035 | |
1036 | /* End items for lio_target_tpg_cit */ |
1037 | |
1038 | /* Start items for lio_target_tiqn_cit */ |
1039 | |
1040 | static struct se_portal_group *lio_target_tiqn_addtpg(struct se_wwn *wwn, |
1041 | const char *name) |
1042 | { |
1043 | struct iscsi_portal_group *tpg; |
1044 | struct iscsi_tiqn *tiqn; |
1045 | char *tpgt_str; |
1046 | int ret; |
1047 | u16 tpgt; |
1048 | |
1049 | tiqn = container_of(wwn, struct iscsi_tiqn, tiqn_wwn); |
1050 | /* |
1051 | * Only tpgt_# directory groups can be created below |
1052 | * target/iscsi/iqn.superturodiskarry/ |
1053 | */ |
1054 | tpgt_str = strstr(name, "tpgt_" ); |
1055 | if (!tpgt_str) { |
1056 | pr_err("Unable to locate \"tpgt_#\" directory" |
1057 | " group\n" ); |
1058 | return NULL; |
1059 | } |
1060 | tpgt_str += 5; /* Skip ahead of "tpgt_" */ |
1061 | ret = kstrtou16(s: tpgt_str, base: 0, res: &tpgt); |
1062 | if (ret) |
1063 | return NULL; |
1064 | |
1065 | tpg = iscsit_alloc_portal_group(tiqn, tpgt); |
1066 | if (!tpg) |
1067 | return NULL; |
1068 | |
1069 | ret = core_tpg_register(wwn, &tpg->tpg_se_tpg, SCSI_PROTOCOL_ISCSI); |
1070 | if (ret < 0) |
1071 | goto free_out; |
1072 | |
1073 | ret = iscsit_tpg_add_portal_group(tiqn, tpg); |
1074 | if (ret != 0) |
1075 | goto out; |
1076 | |
1077 | pr_debug("LIO_Target_ConfigFS: REGISTER -> %s\n" , tiqn->tiqn); |
1078 | pr_debug("LIO_Target_ConfigFS: REGISTER -> Allocated TPG: %s\n" , |
1079 | name); |
1080 | return &tpg->tpg_se_tpg; |
1081 | out: |
1082 | core_tpg_deregister(&tpg->tpg_se_tpg); |
1083 | free_out: |
1084 | kfree(objp: tpg); |
1085 | return NULL; |
1086 | } |
1087 | |
1088 | static int lio_target_tiqn_enabletpg(struct se_portal_group *se_tpg, |
1089 | bool enable) |
1090 | { |
1091 | struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); |
1092 | int ret; |
1093 | |
1094 | ret = iscsit_get_tpg(tpg); |
1095 | if (ret < 0) |
1096 | return -EINVAL; |
1097 | |
1098 | if (enable) { |
1099 | ret = iscsit_tpg_enable_portal_group(tpg); |
1100 | if (ret < 0) |
1101 | goto out; |
1102 | } else { |
1103 | /* |
1104 | * iscsit_tpg_disable_portal_group() assumes force=1 |
1105 | */ |
1106 | ret = iscsit_tpg_disable_portal_group(tpg, 1); |
1107 | if (ret < 0) |
1108 | goto out; |
1109 | } |
1110 | |
1111 | iscsit_put_tpg(tpg); |
1112 | return 0; |
1113 | out: |
1114 | iscsit_put_tpg(tpg); |
1115 | return -EINVAL; |
1116 | } |
1117 | |
1118 | static void lio_target_tiqn_deltpg(struct se_portal_group *se_tpg) |
1119 | { |
1120 | struct iscsi_portal_group *tpg; |
1121 | struct iscsi_tiqn *tiqn; |
1122 | |
1123 | tpg = to_iscsi_tpg(se_tpg); |
1124 | tiqn = tpg->tpg_tiqn; |
1125 | /* |
1126 | * iscsit_tpg_del_portal_group() assumes force=1 |
1127 | */ |
1128 | pr_debug("LIO_Target_ConfigFS: DEREGISTER -> Releasing TPG\n" ); |
1129 | iscsit_tpg_del_portal_group(tiqn, tpg, 1); |
1130 | } |
1131 | |
1132 | /* End items for lio_target_tiqn_cit */ |
1133 | |
1134 | /* Start LIO-Target TIQN struct contig_item lio_target_cit */ |
1135 | |
1136 | static ssize_t lio_target_wwn_lio_version_show(struct config_item *item, |
1137 | char *page) |
1138 | { |
1139 | return sysfs_emit(buf: page, fmt: "Datera Inc. iSCSI Target %s\n" , ISCSIT_VERSION); |
1140 | } |
1141 | |
1142 | CONFIGFS_ATTR_RO(lio_target_wwn_, lio_version); |
1143 | |
1144 | static ssize_t lio_target_wwn_cpus_allowed_list_show( |
1145 | struct config_item *item, char *page) |
1146 | { |
1147 | return sysfs_emit(buf: page, fmt: "%*pbl\n" , |
1148 | cpumask_pr_args(iscsit_global->allowed_cpumask)); |
1149 | } |
1150 | |
1151 | static ssize_t lio_target_wwn_cpus_allowed_list_store( |
1152 | struct config_item *item, const char *page, size_t count) |
1153 | { |
1154 | int ret = -ENOMEM; |
1155 | char *orig; |
1156 | cpumask_var_t new_allowed_cpumask; |
1157 | |
1158 | if (!zalloc_cpumask_var(mask: &new_allowed_cpumask, GFP_KERNEL)) |
1159 | goto out; |
1160 | |
1161 | orig = kstrdup(s: page, GFP_KERNEL); |
1162 | if (!orig) |
1163 | goto out_free_cpumask; |
1164 | |
1165 | ret = cpulist_parse(buf: orig, dstp: new_allowed_cpumask); |
1166 | if (!ret) |
1167 | cpumask_copy(dstp: iscsit_global->allowed_cpumask, |
1168 | srcp: new_allowed_cpumask); |
1169 | |
1170 | kfree(objp: orig); |
1171 | out_free_cpumask: |
1172 | free_cpumask_var(mask: new_allowed_cpumask); |
1173 | out: |
1174 | return ret ? ret : count; |
1175 | } |
1176 | |
1177 | CONFIGFS_ATTR(lio_target_wwn_, cpus_allowed_list); |
1178 | |
1179 | static struct configfs_attribute *lio_target_wwn_attrs[] = { |
1180 | &lio_target_wwn_attr_lio_version, |
1181 | &lio_target_wwn_attr_cpus_allowed_list, |
1182 | NULL, |
1183 | }; |
1184 | |
1185 | static struct se_wwn *lio_target_call_coreaddtiqn( |
1186 | struct target_fabric_configfs *tf, |
1187 | struct config_group *group, |
1188 | const char *name) |
1189 | { |
1190 | struct iscsi_tiqn *tiqn; |
1191 | |
1192 | tiqn = iscsit_add_tiqn((unsigned char *)name); |
1193 | if (IS_ERR(ptr: tiqn)) |
1194 | return ERR_CAST(ptr: tiqn); |
1195 | |
1196 | pr_debug("LIO_Target_ConfigFS: REGISTER -> %s\n" , tiqn->tiqn); |
1197 | pr_debug("LIO_Target_ConfigFS: REGISTER -> Allocated Node:" |
1198 | " %s\n" , name); |
1199 | return &tiqn->tiqn_wwn; |
1200 | } |
1201 | |
1202 | static void lio_target_add_wwn_groups(struct se_wwn *wwn) |
1203 | { |
1204 | struct iscsi_tiqn *tiqn = container_of(wwn, struct iscsi_tiqn, tiqn_wwn); |
1205 | |
1206 | config_group_init_type_name(group: &tiqn->tiqn_stat_grps.iscsi_instance_group, |
1207 | name: "iscsi_instance" , type: &iscsi_stat_instance_cit); |
1208 | configfs_add_default_group(new_group: &tiqn->tiqn_stat_grps.iscsi_instance_group, |
1209 | group: &tiqn->tiqn_wwn.fabric_stat_group); |
1210 | |
1211 | config_group_init_type_name(group: &tiqn->tiqn_stat_grps.iscsi_sess_err_group, |
1212 | name: "iscsi_sess_err" , type: &iscsi_stat_sess_err_cit); |
1213 | configfs_add_default_group(new_group: &tiqn->tiqn_stat_grps.iscsi_sess_err_group, |
1214 | group: &tiqn->tiqn_wwn.fabric_stat_group); |
1215 | |
1216 | config_group_init_type_name(group: &tiqn->tiqn_stat_grps.iscsi_tgt_attr_group, |
1217 | name: "iscsi_tgt_attr" , type: &iscsi_stat_tgt_attr_cit); |
1218 | configfs_add_default_group(new_group: &tiqn->tiqn_stat_grps.iscsi_tgt_attr_group, |
1219 | group: &tiqn->tiqn_wwn.fabric_stat_group); |
1220 | |
1221 | config_group_init_type_name(group: &tiqn->tiqn_stat_grps.iscsi_login_stats_group, |
1222 | name: "iscsi_login_stats" , type: &iscsi_stat_login_cit); |
1223 | configfs_add_default_group(new_group: &tiqn->tiqn_stat_grps.iscsi_login_stats_group, |
1224 | group: &tiqn->tiqn_wwn.fabric_stat_group); |
1225 | |
1226 | config_group_init_type_name(group: &tiqn->tiqn_stat_grps.iscsi_logout_stats_group, |
1227 | name: "iscsi_logout_stats" , type: &iscsi_stat_logout_cit); |
1228 | configfs_add_default_group(new_group: &tiqn->tiqn_stat_grps.iscsi_logout_stats_group, |
1229 | group: &tiqn->tiqn_wwn.fabric_stat_group); |
1230 | } |
1231 | |
1232 | static void lio_target_call_coredeltiqn( |
1233 | struct se_wwn *wwn) |
1234 | { |
1235 | struct iscsi_tiqn *tiqn = container_of(wwn, struct iscsi_tiqn, tiqn_wwn); |
1236 | |
1237 | pr_debug("LIO_Target_ConfigFS: DEREGISTER -> %s\n" , |
1238 | tiqn->tiqn); |
1239 | iscsit_del_tiqn(tiqn); |
1240 | } |
1241 | |
1242 | /* End LIO-Target TIQN struct contig_lio_target_cit */ |
1243 | |
1244 | /* Start lio_target_discovery_auth_cit */ |
1245 | |
1246 | #define DEF_DISC_AUTH_STR(name, flags) \ |
1247 | __DEF_NACL_AUTH_STR(disc, name, flags) \ |
1248 | static ssize_t iscsi_disc_##name##_show(struct config_item *item, char *page) \ |
1249 | { \ |
1250 | return __iscsi_disc_##name##_show(&iscsit_global->discovery_acl,\ |
1251 | page); \ |
1252 | } \ |
1253 | static ssize_t iscsi_disc_##name##_store(struct config_item *item, \ |
1254 | const char *page, size_t count) \ |
1255 | { \ |
1256 | return __iscsi_disc_##name##_store(&iscsit_global->discovery_acl, \ |
1257 | page, count); \ |
1258 | \ |
1259 | } \ |
1260 | CONFIGFS_ATTR(iscsi_disc_, name) |
1261 | |
1262 | DEF_DISC_AUTH_STR(userid, NAF_USERID_SET); |
1263 | DEF_DISC_AUTH_STR(password, NAF_PASSWORD_SET); |
1264 | DEF_DISC_AUTH_STR(userid_mutual, NAF_USERID_IN_SET); |
1265 | DEF_DISC_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET); |
1266 | |
1267 | #define DEF_DISC_AUTH_INT(name) \ |
1268 | __DEF_NACL_AUTH_INT(disc, name) \ |
1269 | static ssize_t iscsi_disc_##name##_show(struct config_item *item, char *page) \ |
1270 | { \ |
1271 | return __iscsi_disc_##name##_show(&iscsit_global->discovery_acl, \ |
1272 | page); \ |
1273 | } \ |
1274 | CONFIGFS_ATTR_RO(iscsi_disc_, name) |
1275 | |
1276 | DEF_DISC_AUTH_INT(authenticate_target); |
1277 | |
1278 | |
1279 | static ssize_t iscsi_disc_enforce_discovery_auth_show(struct config_item *item, |
1280 | char *page) |
1281 | { |
1282 | struct iscsi_node_auth *discovery_auth = &iscsit_global->discovery_acl.node_auth; |
1283 | |
1284 | return sysfs_emit(buf: page, fmt: "%d\n" , discovery_auth->enforce_discovery_auth); |
1285 | } |
1286 | |
1287 | static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item, |
1288 | const char *page, size_t count) |
1289 | { |
1290 | struct iscsi_param *param; |
1291 | struct iscsi_portal_group *discovery_tpg = iscsit_global->discovery_tpg; |
1292 | u32 op; |
1293 | int err; |
1294 | |
1295 | err = kstrtou32(s: page, base: 0, res: &op); |
1296 | if (err) |
1297 | return -EINVAL; |
1298 | if ((op != 1) && (op != 0)) { |
1299 | pr_err("Illegal value for enforce_discovery_auth:" |
1300 | " %u\n" , op); |
1301 | return -EINVAL; |
1302 | } |
1303 | |
1304 | if (!discovery_tpg) { |
1305 | pr_err("iscsit_global->discovery_tpg is NULL\n" ); |
1306 | return -EINVAL; |
1307 | } |
1308 | |
1309 | param = iscsi_find_param_from_key(AUTHMETHOD, |
1310 | discovery_tpg->param_list); |
1311 | if (!param) |
1312 | return -EINVAL; |
1313 | |
1314 | if (op) { |
1315 | /* |
1316 | * Reset the AuthMethod key to CHAP. |
1317 | */ |
1318 | if (iscsi_update_param_value(param, CHAP) < 0) |
1319 | return -EINVAL; |
1320 | |
1321 | discovery_tpg->tpg_attrib.authentication = 1; |
1322 | iscsit_global->discovery_acl.node_auth.enforce_discovery_auth = 1; |
1323 | pr_debug("LIO-CORE[0] Successfully enabled" |
1324 | " authentication enforcement for iSCSI" |
1325 | " Discovery TPG\n" ); |
1326 | } else { |
1327 | /* |
1328 | * Reset the AuthMethod key to CHAP,None |
1329 | */ |
1330 | if (iscsi_update_param_value(param, "CHAP,None" ) < 0) |
1331 | return -EINVAL; |
1332 | |
1333 | discovery_tpg->tpg_attrib.authentication = 0; |
1334 | iscsit_global->discovery_acl.node_auth.enforce_discovery_auth = 0; |
1335 | pr_debug("LIO-CORE[0] Successfully disabled" |
1336 | " authentication enforcement for iSCSI" |
1337 | " Discovery TPG\n" ); |
1338 | } |
1339 | |
1340 | return count; |
1341 | } |
1342 | |
1343 | CONFIGFS_ATTR(iscsi_disc_, enforce_discovery_auth); |
1344 | |
1345 | static struct configfs_attribute *lio_target_discovery_auth_attrs[] = { |
1346 | &iscsi_disc_attr_userid, |
1347 | &iscsi_disc_attr_password, |
1348 | &iscsi_disc_attr_authenticate_target, |
1349 | &iscsi_disc_attr_userid_mutual, |
1350 | &iscsi_disc_attr_password_mutual, |
1351 | &iscsi_disc_attr_enforce_discovery_auth, |
1352 | NULL, |
1353 | }; |
1354 | |
1355 | /* End lio_target_discovery_auth_cit */ |
1356 | |
1357 | /* Start functions for target_core_fabric_ops */ |
1358 | |
1359 | static int iscsi_get_cmd_state(struct se_cmd *se_cmd) |
1360 | { |
1361 | struct iscsit_cmd *cmd = container_of(se_cmd, struct iscsit_cmd, se_cmd); |
1362 | |
1363 | return cmd->i_state; |
1364 | } |
1365 | |
1366 | static u32 lio_sess_get_index(struct se_session *se_sess) |
1367 | { |
1368 | struct iscsit_session *sess = se_sess->fabric_sess_ptr; |
1369 | |
1370 | return sess->session_index; |
1371 | } |
1372 | |
1373 | static u32 lio_sess_get_initiator_sid( |
1374 | struct se_session *se_sess, |
1375 | unsigned char *buf, |
1376 | u32 size) |
1377 | { |
1378 | struct iscsit_session *sess = se_sess->fabric_sess_ptr; |
1379 | /* |
1380 | * iSCSI Initiator Session Identifier from RFC-3720. |
1381 | */ |
1382 | return snprintf(buf, size, fmt: "%6phN" , sess->isid); |
1383 | } |
1384 | |
1385 | static int lio_queue_data_in(struct se_cmd *se_cmd) |
1386 | { |
1387 | struct iscsit_cmd *cmd = container_of(se_cmd, struct iscsit_cmd, se_cmd); |
1388 | struct iscsit_conn *conn = cmd->conn; |
1389 | |
1390 | cmd->i_state = ISTATE_SEND_DATAIN; |
1391 | return conn->conn_transport->iscsit_queue_data_in(conn, cmd); |
1392 | } |
1393 | |
1394 | static int lio_write_pending(struct se_cmd *se_cmd) |
1395 | { |
1396 | struct iscsit_cmd *cmd = container_of(se_cmd, struct iscsit_cmd, se_cmd); |
1397 | struct iscsit_conn *conn = cmd->conn; |
1398 | |
1399 | if (!cmd->immediate_data && !cmd->unsolicited_data) |
1400 | return conn->conn_transport->iscsit_get_dataout(conn, cmd, false); |
1401 | |
1402 | return 0; |
1403 | } |
1404 | |
1405 | static int lio_queue_status(struct se_cmd *se_cmd) |
1406 | { |
1407 | struct iscsit_cmd *cmd = container_of(se_cmd, struct iscsit_cmd, se_cmd); |
1408 | struct iscsit_conn *conn = cmd->conn; |
1409 | |
1410 | cmd->i_state = ISTATE_SEND_STATUS; |
1411 | |
1412 | if (cmd->se_cmd.scsi_status || cmd->sense_reason) { |
1413 | return iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); |
1414 | } |
1415 | return conn->conn_transport->iscsit_queue_status(conn, cmd); |
1416 | } |
1417 | |
1418 | static void lio_queue_tm_rsp(struct se_cmd *se_cmd) |
1419 | { |
1420 | struct iscsit_cmd *cmd = container_of(se_cmd, struct iscsit_cmd, se_cmd); |
1421 | |
1422 | cmd->i_state = ISTATE_SEND_TASKMGTRSP; |
1423 | iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); |
1424 | } |
1425 | |
1426 | static void lio_aborted_task(struct se_cmd *se_cmd) |
1427 | { |
1428 | struct iscsit_cmd *cmd = container_of(se_cmd, struct iscsit_cmd, se_cmd); |
1429 | |
1430 | cmd->conn->conn_transport->iscsit_aborted_task(cmd->conn, cmd); |
1431 | } |
1432 | |
1433 | static char *lio_tpg_get_endpoint_wwn(struct se_portal_group *se_tpg) |
1434 | { |
1435 | return to_iscsi_tpg(se_tpg)->tpg_tiqn->tiqn; |
1436 | } |
1437 | |
1438 | static u16 lio_tpg_get_tag(struct se_portal_group *se_tpg) |
1439 | { |
1440 | return to_iscsi_tpg(se_tpg)->tpgt; |
1441 | } |
1442 | |
1443 | static u32 lio_tpg_get_default_depth(struct se_portal_group *se_tpg) |
1444 | { |
1445 | return to_iscsi_tpg(se_tpg)->tpg_attrib.default_cmdsn_depth; |
1446 | } |
1447 | |
1448 | static int lio_tpg_check_demo_mode(struct se_portal_group *se_tpg) |
1449 | { |
1450 | return to_iscsi_tpg(se_tpg)->tpg_attrib.generate_node_acls; |
1451 | } |
1452 | |
1453 | static int lio_tpg_check_demo_mode_cache(struct se_portal_group *se_tpg) |
1454 | { |
1455 | return to_iscsi_tpg(se_tpg)->tpg_attrib.cache_dynamic_acls; |
1456 | } |
1457 | |
1458 | static int lio_tpg_check_demo_mode_write_protect( |
1459 | struct se_portal_group *se_tpg) |
1460 | { |
1461 | return to_iscsi_tpg(se_tpg)->tpg_attrib.demo_mode_write_protect; |
1462 | } |
1463 | |
1464 | static int lio_tpg_check_prod_mode_write_protect( |
1465 | struct se_portal_group *se_tpg) |
1466 | { |
1467 | return to_iscsi_tpg(se_tpg)->tpg_attrib.prod_mode_write_protect; |
1468 | } |
1469 | |
1470 | static int lio_tpg_check_prot_fabric_only( |
1471 | struct se_portal_group *se_tpg) |
1472 | { |
1473 | /* |
1474 | * Only report fabric_prot_type if t10_pi has also been enabled |
1475 | * for incoming ib_isert sessions. |
1476 | */ |
1477 | if (!to_iscsi_tpg(se_tpg)->tpg_attrib.t10_pi) |
1478 | return 0; |
1479 | return to_iscsi_tpg(se_tpg)->tpg_attrib.fabric_prot_type; |
1480 | } |
1481 | |
1482 | /* |
1483 | * This function calls iscsit_inc_session_usage_count() on the |
1484 | * struct iscsit_session in question. |
1485 | */ |
1486 | static void lio_tpg_close_session(struct se_session *se_sess) |
1487 | { |
1488 | struct iscsit_session *sess = se_sess->fabric_sess_ptr; |
1489 | struct se_portal_group *se_tpg = &sess->tpg->tpg_se_tpg; |
1490 | |
1491 | spin_lock_bh(lock: &se_tpg->session_lock); |
1492 | spin_lock(lock: &sess->conn_lock); |
1493 | if (atomic_read(v: &sess->session_fall_back_to_erl0) || |
1494 | atomic_read(v: &sess->session_logout) || |
1495 | atomic_read(v: &sess->session_close) || |
1496 | (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) { |
1497 | spin_unlock(lock: &sess->conn_lock); |
1498 | spin_unlock_bh(lock: &se_tpg->session_lock); |
1499 | return; |
1500 | } |
1501 | iscsit_inc_session_usage_count(sess); |
1502 | atomic_set(v: &sess->session_reinstatement, i: 1); |
1503 | atomic_set(v: &sess->session_fall_back_to_erl0, i: 1); |
1504 | atomic_set(v: &sess->session_close, i: 1); |
1505 | spin_unlock(lock: &sess->conn_lock); |
1506 | |
1507 | iscsit_stop_time2retain_timer(sess); |
1508 | spin_unlock_bh(lock: &se_tpg->session_lock); |
1509 | |
1510 | iscsit_stop_session(sess, 1, 1); |
1511 | iscsit_dec_session_usage_count(sess); |
1512 | } |
1513 | |
1514 | static u32 lio_tpg_get_inst_index(struct se_portal_group *se_tpg) |
1515 | { |
1516 | return to_iscsi_tpg(se_tpg)->tpg_tiqn->tiqn_index; |
1517 | } |
1518 | |
1519 | static void lio_set_default_node_attributes(struct se_node_acl *se_acl) |
1520 | { |
1521 | struct iscsi_node_acl *acl = to_iscsi_nacl(se_nacl: se_acl); |
1522 | struct se_portal_group *se_tpg = se_acl->se_tpg; |
1523 | struct iscsi_portal_group *tpg = to_iscsi_tpg(se_tpg); |
1524 | |
1525 | acl->node_attrib.nacl = acl; |
1526 | iscsit_set_default_node_attribues(acl, tpg); |
1527 | } |
1528 | |
1529 | static int lio_check_stop_free(struct se_cmd *se_cmd) |
1530 | { |
1531 | return target_put_sess_cmd(se_cmd); |
1532 | } |
1533 | |
1534 | static void lio_release_cmd(struct se_cmd *se_cmd) |
1535 | { |
1536 | struct iscsit_cmd *cmd = container_of(se_cmd, struct iscsit_cmd, se_cmd); |
1537 | |
1538 | pr_debug("Entering lio_release_cmd for se_cmd: %p\n" , se_cmd); |
1539 | iscsit_release_cmd(cmd); |
1540 | } |
1541 | |
1542 | const struct target_core_fabric_ops iscsi_ops = { |
1543 | .module = THIS_MODULE, |
1544 | .fabric_alias = "iscsi" , |
1545 | .fabric_name = "iSCSI" , |
1546 | .node_acl_size = sizeof(struct iscsi_node_acl), |
1547 | .tpg_get_wwn = lio_tpg_get_endpoint_wwn, |
1548 | .tpg_get_tag = lio_tpg_get_tag, |
1549 | .tpg_get_default_depth = lio_tpg_get_default_depth, |
1550 | .tpg_check_demo_mode = lio_tpg_check_demo_mode, |
1551 | .tpg_check_demo_mode_cache = lio_tpg_check_demo_mode_cache, |
1552 | .tpg_check_demo_mode_write_protect = |
1553 | lio_tpg_check_demo_mode_write_protect, |
1554 | .tpg_check_prod_mode_write_protect = |
1555 | lio_tpg_check_prod_mode_write_protect, |
1556 | .tpg_check_prot_fabric_only = &lio_tpg_check_prot_fabric_only, |
1557 | .tpg_get_inst_index = lio_tpg_get_inst_index, |
1558 | .check_stop_free = lio_check_stop_free, |
1559 | .release_cmd = lio_release_cmd, |
1560 | .close_session = lio_tpg_close_session, |
1561 | .sess_get_index = lio_sess_get_index, |
1562 | .sess_get_initiator_sid = lio_sess_get_initiator_sid, |
1563 | .write_pending = lio_write_pending, |
1564 | .set_default_node_attributes = lio_set_default_node_attributes, |
1565 | .get_cmd_state = iscsi_get_cmd_state, |
1566 | .queue_data_in = lio_queue_data_in, |
1567 | .queue_status = lio_queue_status, |
1568 | .queue_tm_rsp = lio_queue_tm_rsp, |
1569 | .aborted_task = lio_aborted_task, |
1570 | .fabric_make_wwn = lio_target_call_coreaddtiqn, |
1571 | .fabric_drop_wwn = lio_target_call_coredeltiqn, |
1572 | .add_wwn_groups = lio_target_add_wwn_groups, |
1573 | .fabric_make_tpg = lio_target_tiqn_addtpg, |
1574 | .fabric_enable_tpg = lio_target_tiqn_enabletpg, |
1575 | .fabric_drop_tpg = lio_target_tiqn_deltpg, |
1576 | .fabric_make_np = lio_target_call_addnptotpg, |
1577 | .fabric_drop_np = lio_target_call_delnpfromtpg, |
1578 | .fabric_init_nodeacl = lio_target_init_nodeacl, |
1579 | |
1580 | .tfc_discovery_attrs = lio_target_discovery_auth_attrs, |
1581 | .tfc_wwn_attrs = lio_target_wwn_attrs, |
1582 | .tfc_tpg_base_attrs = lio_target_tpg_attrs, |
1583 | .tfc_tpg_attrib_attrs = lio_target_tpg_attrib_attrs, |
1584 | .tfc_tpg_auth_attrs = lio_target_tpg_auth_attrs, |
1585 | .tfc_tpg_param_attrs = lio_target_tpg_param_attrs, |
1586 | .tfc_tpg_np_base_attrs = lio_target_portal_attrs, |
1587 | .tfc_tpg_nacl_base_attrs = lio_target_initiator_attrs, |
1588 | .tfc_tpg_nacl_attrib_attrs = lio_target_nacl_attrib_attrs, |
1589 | .tfc_tpg_nacl_auth_attrs = lio_target_nacl_auth_attrs, |
1590 | .tfc_tpg_nacl_param_attrs = lio_target_nacl_param_attrs, |
1591 | |
1592 | .write_pending_must_be_called = 1, |
1593 | |
1594 | .default_submit_type = TARGET_DIRECT_SUBMIT, |
1595 | .direct_submit_supp = 1, |
1596 | }; |
1597 | |