2 * iSCSI Session Management and Slow-path Control
4 * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman
5 * Copyright (C) 2006 Mike Christie
6 * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
7 * maintained by open-iscsi@googlegroups.com
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * See the file COPYING included with this distribution for more details.
23 #include <sys/types.h>
25 #include <sys/resource.h>
34 #include "initiator.h"
35 #include "transport.h"
39 #include "event_poll.h"
40 #include "iscsi_ipc.h"
43 #include "iscsi_util.h"
45 #include "iscsi_sysfs.h"
46 #include "iscsi_settings.h"
50 #define ISCSI_CONN_ERR_REOPEN_DELAY 3
51 #define ISCSI_INTERNAL_ERR_REOPEN_DELAY 5
53 #define PROC_DIR "/proc"
55 static void iscsi_login_timedout(void *data
);
58 * calculate parameter's padding
61 __padding(unsigned int param
)
68 log_debug(1, "parameter's value %d padded to %d bytes\n",
74 static int iscsi_conn_context_alloc(iscsi_conn_t
*conn
)
78 for (i
= 0; i
< CONTEXT_POOL_MAX
; i
++) {
79 conn
->context_pool
[i
] = calloc(1,
80 sizeof(struct iscsi_conn_context
) +
82 if (!conn
->context_pool
[i
]) {
84 for (j
= 0; j
< i
; j
++)
85 free(conn
->context_pool
[j
]);
88 conn
->context_pool
[i
]->conn
= conn
;
94 static void iscsi_conn_context_free(iscsi_conn_t
*conn
)
98 for (i
= 0; i
< CONTEXT_POOL_MAX
; i
++) {
99 if (!conn
->context_pool
[i
])
102 if (conn
->context_pool
[i
]->allocated
)
103 /* missing flush on shutdown */
104 log_error("BUG: context_pool leak %p",
105 conn
->context_pool
[i
]);
106 free(conn
->context_pool
[i
]);
110 struct iscsi_conn_context
*iscsi_conn_context_get(iscsi_conn_t
*conn
,
113 struct iscsi_conn_context
*conn_context
;
116 if (ev_size
> ipc
->ctldev_bufmax
)
119 for (i
= 0; i
< CONTEXT_POOL_MAX
; i
++) {
120 if (!conn
->context_pool
[i
])
123 if (!conn
->context_pool
[i
]->allocated
) {
124 conn_context
= conn
->context_pool
[i
];
126 memset(&conn_context
->actor
, 0,
127 sizeof(struct actor
));
128 conn_context
->allocated
= 1;
129 /* some callers abuse this pointer */
130 conn_context
->data
= (void *)conn_context
+
131 sizeof(struct iscsi_conn_context
);
132 log_debug(7, "get conn context %p",
133 &conn_context
->actor
);
140 void iscsi_conn_context_put(struct iscsi_conn_context
*conn_context
)
142 log_debug(7, "put conn context %p", &conn_context
->actor
);
143 conn_context
->allocated
= 0;
146 static void session_online_devs(int host_no
, int sid
)
148 iscsi_sysfs_for_each_device(NULL
, host_no
, sid
,
149 iscsi_sysfs_set_device_online
);
152 static conn_login_status_e
153 __login_response_status(iscsi_conn_t
*conn
,
154 enum iscsi_login_status login_status
)
156 switch (login_status
) {
158 /* check the status class and detail */
159 return CONN_LOGIN_SUCCESS
;
161 return CONN_LOGIN_IMM_REDIRECT_RETRY
;
163 case LOGIN_REDIRECTION_FAILED
:
164 return CONN_LOGIN_RETRY
;
166 log_error("Login error (Login status %d) on conn %d", conn
->id
,
171 return CONN_LOGIN_FAILED
;
174 static conn_login_status_e
175 __check_iscsi_status_class(iscsi_session_t
*session
, int cid
,
176 uint8_t status_class
, uint8_t status_detail
)
178 iscsi_conn_t
*conn
= &session
->conn
[cid
];
180 switch (status_class
) {
181 case ISCSI_STATUS_CLS_SUCCESS
:
182 return CONN_LOGIN_SUCCESS
;
183 case ISCSI_STATUS_CLS_REDIRECT
:
184 switch (status_detail
) {
185 case ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP
:
186 return CONN_LOGIN_IMM_RETRY
;
187 case ISCSI_LOGIN_STATUS_TGT_MOVED_PERM
:
189 * for a permanent redirect, we need to update the
192 memset(&conn
->failback_saddr
, 0,
193 sizeof(struct sockaddr_storage
));
194 conn
->failback_saddr
= conn
->saddr
;
195 return CONN_LOGIN_IMM_REDIRECT_RETRY
;
197 log_error("conn %d login rejected: redirection "
198 "type 0x%x not supported",
199 conn
->id
, status_detail
);
200 return CONN_LOGIN_RETRY
;
202 case ISCSI_STATUS_CLS_INITIATOR_ERR
:
203 switch (status_detail
) {
204 case ISCSI_LOGIN_STATUS_AUTH_FAILED
:
205 log_error("session %d login rejected: Initiator "
206 "failed authentication with target",
208 return CONN_LOGIN_FAILED
;
209 case ISCSI_LOGIN_STATUS_TGT_FORBIDDEN
:
210 log_error("conn %d login rejected: initiator "
211 "failed authorization with target", conn
->id
);
212 return CONN_LOGIN_FAILED
;
213 case ISCSI_LOGIN_STATUS_TGT_NOT_FOUND
:
214 log_error("conn %d login rejected: initiator "
215 "error - target not found (%02x/%02x)",
216 conn
->id
, status_class
, status_detail
);
217 return CONN_LOGIN_FAILED
;
218 case ISCSI_LOGIN_STATUS_NO_VERSION
:
220 * FIXME: if we handle multiple protocol versions,
221 * before we log an error, try the other supported
224 log_error("conn %d login rejected: incompatible "
225 "version (%02x/%02x), non-retryable, "
226 "giving up", conn
->id
, status_class
,
228 return CONN_LOGIN_FAILED
;
230 log_error("conn %d login rejected: initiator "
231 "error (%02x/%02x)", conn
->id
, status_class
,
233 return CONN_LOGIN_FAILED
;
235 case ISCSI_STATUS_CLS_TARGET_ERR
:
236 log_error("conn %d login rejected: target error "
237 "(%02x/%02x)\n", conn
->id
, status_class
, status_detail
);
239 * We have no idea what the problem is. But spec says initiator
242 return CONN_LOGIN_RETRY
;
244 log_error("conn %d login response with unknown status "
245 "class 0x%x, detail 0x%x\n", conn
->id
, status_class
,
250 return CONN_LOGIN_FAILED
;
254 __setup_authentication(iscsi_session_t
*session
,
255 struct iscsi_auth_config
*auth_cfg
)
257 /* if we have any incoming credentials, we insist on authenticating
258 * the target or not logging in at all
260 if (auth_cfg
->username_in
[0]
261 || auth_cfg
->password_in_length
) {
262 /* sanity check the config */
263 if (auth_cfg
->password_length
== 0) {
265 "node record has incoming "
266 "authentication credentials but has no outgoing "
267 "credentials configured, exiting");
270 session
->bidirectional_auth
= 1;
272 /* no or 1-way authentication */
273 session
->bidirectional_auth
= 0;
276 /* copy in whatever credentials we have */
277 strlcpy(session
->username
, auth_cfg
->username
,
278 sizeof (session
->username
));
279 session
->username
[sizeof (session
->username
) - 1] = '\0';
280 if ((session
->password_length
= auth_cfg
->password_length
))
281 memcpy(session
->password
, auth_cfg
->password
,
282 session
->password_length
);
284 strlcpy(session
->username_in
, auth_cfg
->username_in
,
285 sizeof (session
->username_in
));
286 session
->username_in
[sizeof (session
->username_in
) - 1] = '\0';
287 if ((session
->password_in_length
=
288 auth_cfg
->password_in_length
))
289 memcpy(session
->password_in
, auth_cfg
->password_in
,
290 session
->password_in_length
);
292 if (session
->password_length
|| session
->password_in_length
) {
293 /* setup the auth buffers */
294 session
->auth_buffers
[0].address
= &session
->auth_client_block
;
295 session
->auth_buffers
[0].length
=
296 sizeof (session
->auth_client_block
);
297 session
->auth_buffers
[1].address
=
298 &session
->auth_recv_string_block
;
299 session
->auth_buffers
[1].length
=
300 sizeof (session
->auth_recv_string_block
);
302 session
->auth_buffers
[2].address
=
303 &session
->auth_send_string_block
;
304 session
->auth_buffers
[2].length
=
305 sizeof (session
->auth_send_string_block
);
307 session
->auth_buffers
[3].address
=
308 &session
->auth_recv_binary_block
;
309 session
->auth_buffers
[3].length
=
310 sizeof (session
->auth_recv_binary_block
);
312 session
->auth_buffers
[4].address
=
313 &session
->auth_send_binary_block
;
314 session
->auth_buffers
[4].length
=
315 sizeof (session
->auth_send_binary_block
);
317 session
->num_auth_buffers
= 5;
318 log_debug(6, "authentication setup complete...");
320 session
->num_auth_buffers
= 0;
321 log_debug(6, "no authentication configured...");
326 setup_portal(iscsi_conn_t
*conn
, conn_rec_t
*conn_rec
)
328 char port
[NI_MAXSERV
];
330 sprintf(port
, "%d", conn_rec
->port
);
331 if (resolve_address(conn_rec
->address
, port
, &conn
->saddr
)) {
332 log_error("cannot resolve host name %s",
336 conn
->failback_saddr
= conn
->saddr
;
338 getnameinfo((struct sockaddr
*)&conn
->saddr
, sizeof(conn
->saddr
),
339 conn
->host
, sizeof(conn
->host
), NULL
, 0, NI_NUMERICHOST
);
340 log_debug(4, "resolved %s to %s", conn_rec
->address
, conn
->host
);
345 iscsi_copy_operational_params(iscsi_conn_t
*conn
)
347 iscsi_session_t
*session
= conn
->session
;
348 conn_rec_t
*conn_rec
= &session
->nrec
.conn
[conn
->id
];
349 node_rec_t
*rec
= &session
->nrec
;
351 conn
->hdrdgst_en
= conn_rec
->iscsi
.HeaderDigest
;
352 conn
->datadgst_en
= conn_rec
->iscsi
.DataDigest
;
354 conn
->max_recv_dlength
=
355 __padding(conn_rec
->iscsi
.MaxRecvDataSegmentLength
);
356 if (conn
->max_recv_dlength
< ISCSI_MIN_MAX_RECV_SEG_LEN
||
357 conn
->max_recv_dlength
> ISCSI_MAX_MAX_RECV_SEG_LEN
) {
358 log_error("Invalid iscsi.MaxRecvDataSegmentLength. Must be "
359 "within %u and %u. Setting to %u\n",
360 ISCSI_MIN_MAX_RECV_SEG_LEN
,
361 ISCSI_MAX_MAX_RECV_SEG_LEN
,
362 DEF_INI_MAX_RECV_SEG_LEN
);
363 conn_rec
->iscsi
.MaxRecvDataSegmentLength
=
364 DEF_INI_MAX_RECV_SEG_LEN
;
365 conn
->max_recv_dlength
= DEF_INI_MAX_RECV_SEG_LEN
;
368 /* zero indicates to use the target's value */
369 conn
->max_xmit_dlength
=
370 __padding(conn_rec
->iscsi
.MaxXmitDataSegmentLength
);
371 if (conn
->max_xmit_dlength
== 0)
372 conn
->max_xmit_dlength
= ISCSI_DEF_MAX_RECV_SEG_LEN
;
373 if (conn
->max_xmit_dlength
< ISCSI_MIN_MAX_RECV_SEG_LEN
||
374 conn
->max_xmit_dlength
> ISCSI_MAX_MAX_RECV_SEG_LEN
) {
375 log_error("Invalid iscsi.MaxXmitDataSegmentLength. Must be "
376 "within %u and %u. Setting to %u\n",
377 ISCSI_MIN_MAX_RECV_SEG_LEN
,
378 ISCSI_MAX_MAX_RECV_SEG_LEN
,
379 DEF_INI_MAX_RECV_SEG_LEN
);
380 conn_rec
->iscsi
.MaxXmitDataSegmentLength
=
381 DEF_INI_MAX_RECV_SEG_LEN
;
382 conn
->max_xmit_dlength
= DEF_INI_MAX_RECV_SEG_LEN
;
385 /* session's operational parameters */
386 session
->initial_r2t_en
= rec
->session
.iscsi
.InitialR2T
;
387 session
->imm_data_en
= rec
->session
.iscsi
.ImmediateData
;
388 session
->first_burst
= __padding(rec
->session
.iscsi
.FirstBurstLength
);
390 * some targets like netapp fail the login if sent bad first_burst
391 * and max_burst lens, even when immediate data=no and
392 * initial r2t = Yes, so we always check the user values.
394 if (session
->first_burst
< ISCSI_MIN_FIRST_BURST_LEN
||
395 session
->first_burst
> ISCSI_MAX_FIRST_BURST_LEN
) {
396 log_error("Invalid iscsi.FirstBurstLength of %u. Must be "
397 "within %u and %u. Setting to %u\n",
398 session
->first_burst
,
399 ISCSI_MIN_FIRST_BURST_LEN
,
400 ISCSI_MAX_FIRST_BURST_LEN
,
401 DEF_INI_FIRST_BURST_LEN
);
402 rec
->session
.iscsi
.FirstBurstLength
= DEF_INI_FIRST_BURST_LEN
;
403 session
->first_burst
= DEF_INI_FIRST_BURST_LEN
;
406 session
->max_burst
= __padding(rec
->session
.iscsi
.MaxBurstLength
);
407 if (session
->max_burst
< ISCSI_MIN_MAX_BURST_LEN
||
408 session
->max_burst
> ISCSI_MAX_MAX_BURST_LEN
) {
409 log_error("Invalid iscsi.MaxBurstLength of %u. Must be "
410 "within %u and %u. Setting to %u\n",
411 session
->max_burst
, ISCSI_MIN_MAX_BURST_LEN
,
412 ISCSI_MAX_MAX_BURST_LEN
, DEF_INI_MAX_BURST_LEN
);
413 rec
->session
.iscsi
.MaxBurstLength
= DEF_INI_MAX_BURST_LEN
;
414 session
->max_burst
= DEF_INI_MAX_BURST_LEN
;
417 if (session
->first_burst
> session
->max_burst
) {
418 log_error("Invalid iscsi.FirstBurstLength of %u. Must be "
419 "less than iscsi.MaxBurstLength. Setting to %u\n",
420 session
->first_burst
, session
->max_burst
);
421 rec
->session
.iscsi
.FirstBurstLength
= session
->max_burst
;
422 session
->first_burst
= session
->max_burst
;
425 session
->def_time2wait
= rec
->session
.iscsi
.DefaultTime2Wait
;
426 session
->def_time2retain
= rec
->session
.iscsi
.DefaultTime2Retain
;
427 session
->erl
= rec
->session
.iscsi
.ERL
;
431 __session_conn_create(iscsi_session_t
*session
, int cid
)
433 iscsi_conn_t
*conn
= &session
->conn
[cid
];
434 conn_rec_t
*conn_rec
= &session
->nrec
.conn
[cid
];
437 if (iscsi_conn_context_alloc(conn
)) {
438 log_error("cannot allocate context_pool for conn cid %d", cid
);
442 conn
->state
= STATE_FREE
;
443 conn
->session
= session
;
445 * TODO: we must export the socket_fd/transport_eph from sysfs
446 * so if iscsid is resyncing up we can pick that up and cleanup up
447 * the old connection. Right now we leak a connection.
448 * We can also probably merge these two fields.
450 conn
->socket_fd
= -1;
451 conn
->transport_ep_handle
= -1;
452 /* connection's timeouts */
454 conn
->logout_timeout
= conn_rec
->timeo
.logout_timeout
;
455 if (!conn
->logout_timeout
) {
456 log_error("Invalid timeo.logout_timeout. Must be greater "
457 "than zero. Using default %d.\n",
459 conn
->logout_timeout
= DEF_LOGOUT_TIMEO
;
462 conn
->login_timeout
= conn_rec
->timeo
.login_timeout
;
463 if (!conn
->login_timeout
) {
464 log_error("Invalid timeo.login_timeout. Must be greater "
465 "than zero. Using default %d.\n",
467 conn
->login_timeout
= DEF_LOGIN_TIMEO
;
470 conn
->auth_timeout
= conn_rec
->timeo
.auth_timeout
;
472 /* noop-out setting */
473 conn
->noop_out_interval
= conn_rec
->timeo
.noop_out_interval
;
474 conn
->noop_out_timeout
= conn_rec
->timeo
.noop_out_timeout
;
475 if (conn
->noop_out_interval
&& !conn
->noop_out_timeout
) {
476 log_error("Invalid timeo.noop_out_timeout. Must be greater "
477 "than zero. Using default %d.\n",
479 conn
->noop_out_timeout
= DEF_NOOP_OUT_TIMEO
;
482 if (conn
->noop_out_timeout
&& !conn
->noop_out_interval
) {
483 log_error("Invalid timeo.noop_out_interval. Must be greater "
484 "than zero. Using default %d.\n",
485 DEF_NOOP_OUT_INTERVAL
);
486 conn
->noop_out_interval
= DEF_NOOP_OUT_INTERVAL
;
489 iscsi_copy_operational_params(conn
);
492 conn
->tcp_window_size
= conn_rec
->tcp
.window_size
;
493 /* FIXME: type_of_service */
495 /* resolve the string address to an IP address */
496 err
= setup_portal(conn
, conn_rec
);
503 session_release(iscsi_session_t
*session
)
505 log_debug(2, "Releasing session %p", session
);
507 if (session
->target_alias
)
508 free(session
->target_alias
);
509 iscsi_conn_context_free(&session
->conn
[0]);
513 static iscsi_session_t
*
514 __session_create(node_rec_t
*rec
, struct iscsi_transport
*t
)
516 iscsi_session_t
*session
;
519 session
= calloc(1, sizeof (*session
));
520 if (session
== NULL
) {
521 log_debug(1, "can not allocate memory for session");
524 log_debug(2, "Allocted session %p", session
);
526 INIT_LIST_HEAD(&session
->list
);
527 /* opened at daemon load time (iscsid.c) */
528 session
->ctrl_fd
= control_fd
;
530 session
->reopen_qtask
.mgmt_ipc_fd
= -1;
533 /* save node record. we might need it for redirection */
534 memcpy(&session
->nrec
, rec
, sizeof(node_rec_t
));
536 session
->portal_group_tag
= rec
->tpgt
;
537 session
->type
= ISCSI_SESSION_TYPE_NORMAL
;
538 session
->r_stage
= R_STAGE_NO_CHANGE
;
539 strlcpy(session
->target_name
, rec
->name
, TARGET_NAME_MAXLEN
);
541 if (strlen(session
->nrec
.iface
.iname
))
542 session
->initiator_name
= session
->nrec
.iface
.iname
;
543 else if (dconfig
->initiator_name
)
544 session
->initiator_name
= dconfig
->initiator_name
;
546 log_error("No initiator name set. Cannot create session.");
551 if (strlen(session
->nrec
.iface
.alias
))
552 session
->initiator_alias
= session
->nrec
.iface
.alias
;
554 session
->initiator_alias
= dconfig
->initiator_alias
;
556 /* session's eh parameters */
557 session
->replacement_timeout
= rec
->session
.timeo
.replacement_timeout
;
558 session
->fast_abort
= rec
->session
.iscsi
.FastAbort
;
559 session
->abort_timeout
= rec
->session
.err_timeo
.abort_timeout
;
560 session
->lu_reset_timeout
= rec
->session
.err_timeo
.lu_reset_timeout
;
561 session
->tgt_reset_timeout
= rec
->session
.err_timeo
.tgt_reset_timeout
;
562 session
->host_reset_timeout
= rec
->session
.err_timeo
.host_reset_timeout
;
564 /* OUI and uniqifying number */
565 session
->isid
[0] = DRIVER_ISID_0
;
566 session
->isid
[1] = DRIVER_ISID_1
;
567 session
->isid
[2] = DRIVER_ISID_2
;
568 session
->isid
[3] = 0;
569 session
->isid
[4] = 0;
570 session
->isid
[5] = 0;
572 /* setup authentication variables for the session*/
573 __setup_authentication(session
, &rec
->session
.auth
);
575 session
->param_mask
= ~0ULL;
576 if (!(t
->caps
& CAP_MULTI_R2T
))
577 session
->param_mask
&= ~ISCSI_MAX_R2T
;
578 if (!(t
->caps
& CAP_HDRDGST
))
579 session
->param_mask
&= ~ISCSI_HDRDGST_EN
;
580 if (!(t
->caps
& CAP_DATADGST
))
581 session
->param_mask
&= ~ISCSI_DATADGST_EN
;
582 if (!(t
->caps
& CAP_MARKERS
)) {
583 session
->param_mask
&= ~ISCSI_IFMARKER_EN
;
584 session
->param_mask
&= ~ISCSI_OFMARKER_EN
;
587 hostno
= iscsi_sysfs_get_host_no_from_hwinfo(&rec
->iface
, &rc
);
590 * if the netdev or mac was set, then we are going to want
591 * to want to bind the all the conns/eps to a specific host
592 * if offload is used.
594 session
->conn
[0].bind_ep
= 1;
595 session
->hostno
= hostno
;
598 list_add_tail(&session
->list
, &t
->sessions
);
602 static void iscsi_flush_context_pool(struct iscsi_session
*session
)
604 struct iscsi_conn_context
*conn_context
;
605 struct iscsi_conn
*conn
= &session
->conn
[0];
608 for (i
= 0; i
< CONTEXT_POOL_MAX
; i
++) {
609 conn_context
= conn
->context_pool
[i
];
613 if (conn_context
->allocated
) {
614 actor_delete(&(conn
->context_pool
[i
]->actor
));
615 iscsi_conn_context_put(conn_context
);
621 __session_destroy(iscsi_session_t
*session
)
623 log_debug(1, "destroying session\n");
624 list_del(&session
->list
);
625 iscsi_flush_context_pool(session
);
626 session_release(session
);
630 conn_delete_timers(iscsi_conn_t
*conn
)
632 actor_delete(&conn
->login_timer
);
633 actor_delete(&conn
->nop_out_timer
);
636 static mgmt_ipc_err_e
637 session_conn_shutdown(iscsi_conn_t
*conn
, queue_task_t
*qtask
,
640 iscsi_session_t
*session
= conn
->session
;
642 log_debug(2, "disconnect conn");
643 /* this will check for a valid interconnect connection */
644 conn
->session
->t
->template->ep_disconnect(conn
);
646 if (session
->id
== -1)
649 if (!iscsi_sysfs_session_has_leadconn(session
->id
))
652 if (conn
->state
== STATE_IN_LOGIN
||
653 conn
->state
== STATE_IN_LOGOUT
||
654 conn
->state
== STATE_LOGGED_IN
) {
655 log_debug(2, "stop conn (conn state %d)", conn
->state
);
656 if (ipc
->stop_conn(session
->t
->handle
, session
->id
,
657 conn
->id
, STOP_CONN_TERM
)) {
658 log_error("can't stop connection %d:%d (%d)",
659 session
->id
, conn
->id
, errno
);
660 return MGMT_IPC_ERR_INTERNAL
;
664 log_debug(2, "kdestroy conn");
665 if (ipc
->destroy_conn(session
->t
->handle
, session
->id
,
667 log_error("can not safely destroy connection %d", conn
->id
);
668 return MGMT_IPC_ERR_INTERNAL
;
672 if (session
->id
!= -1) {
673 log_debug(2, "kdestroy session %u", session
->id
);
674 if (ipc
->destroy_session(session
->t
->handle
, session
->id
)) {
675 log_error("can not safely destroy session %d",
677 return MGMT_IPC_ERR_INTERNAL
;
681 log_warning("Connection%d:%d to [target: %s, portal: %s,%d] "
682 "through [iface: %s] is shutdown.",
683 session
->id
, conn
->id
, session
->nrec
.name
,
684 session
->nrec
.conn
[conn
->id
].address
,
685 session
->nrec
.conn
[conn
->id
].port
,
686 session
->nrec
.iface
.name
);
688 mgmt_ipc_write_rsp(qtask
, err
);
689 conn_delete_timers(conn
);
690 __session_destroy(session
);
695 queue_delayed_reopen(queue_task_t
*qtask
, int delay
)
697 iscsi_conn_t
*conn
= qtask
->conn
;
699 log_debug(4, "Requeue reopen attempt in %d secs\n", delay
);
702 * iscsi_login_eh can handle the login resched as
703 * if it were login time out
705 actor_delete(&conn
->login_timer
);
706 actor_timer(&conn
->login_timer
, delay
* 1000,
707 iscsi_login_timedout
, qtask
);
710 static int iscsi_conn_connect(struct iscsi_conn
*conn
, queue_task_t
*qtask
)
712 struct iscsi_conn_context
*conn_context
;
715 conn_context
= iscsi_conn_context_get(conn
, 0);
717 /* while reopening the recv pool should be full */
718 log_error("BUG: __session_conn_reopen could not get conn "
719 "context for recv.");
722 conn_context
->data
= qtask
;
724 rc
= conn
->session
->t
->template->ep_connect(conn
, 1);
725 if (rc
< 0 && errno
!= EINPROGRESS
) {
726 char serv
[NI_MAXSERV
];
728 getnameinfo((struct sockaddr
*) &conn
->saddr
,
730 conn
->host
, sizeof(conn
->host
), serv
, sizeof(serv
),
731 NI_NUMERICHOST
|NI_NUMERICSERV
);
733 log_error("cannot make a connection to %s:%s (%d,%d)",
734 conn
->host
, serv
, rc
, errno
);
735 iscsi_conn_context_put(conn_context
);
739 iscsi_sched_conn_context(conn_context
, conn
, 0, EV_CONN_POLL
);
740 log_debug(3, "Setting login timer %p timeout %d", &conn
->login_timer
,
741 conn
->login_timeout
);
742 actor_timer(&conn
->login_timer
, conn
->login_timeout
* 1000,
743 iscsi_login_timedout
, qtask
);
748 __session_conn_reopen(iscsi_conn_t
*conn
, queue_task_t
*qtask
, int do_stop
,
751 iscsi_session_t
*session
= conn
->session
;
754 log_debug(1, "re-opening session %d (reopen_cnt %d)", session
->id
,
755 session
->reopen_cnt
);
759 /* flush stale polls or errors queued */
760 iscsi_flush_context_pool(session
);
761 conn_delete_timers(conn
);
762 conn
->state
= STATE_XPT_WAIT
;
764 conn
->session
->t
->template->ep_disconnect(conn
);
766 /* state: STATE_CLEANUP_WAIT */
767 if (ipc
->stop_conn(session
->t
->handle
, session
->id
,
768 conn
->id
, do_stop
)) {
769 log_error("can't stop connection %d:%d (%d)",
770 session
->id
, conn
->id
, errno
);
771 delay
= ISCSI_INTERNAL_ERR_REOPEN_DELAY
;
774 log_debug(3, "connection %d:%d is stopped for recovery",
775 session
->id
, conn
->id
);
779 delay
= session
->def_time2wait
;
780 session
->def_time2wait
= 0;
786 session
->reopen_cnt
++;
788 if (iscsi_conn_connect(conn
, qtask
)) {
789 delay
= ISCSI_CONN_ERR_REOPEN_DELAY
;
795 log_debug(4, "Waiting %u seconds before trying to reconnect.\n", delay
);
796 queue_delayed_reopen(qtask
, delay
);
800 session_conn_reopen(iscsi_conn_t
*conn
, queue_task_t
*qtask
, int do_stop
)
803 * If we were temporarily redirected, we need to fall back to
804 * the original address to see where the target will send us
807 memset(&conn
->saddr
, 0, sizeof(struct sockaddr_storage
));
808 conn
->saddr
= conn
->failback_saddr
;
810 __session_conn_reopen(conn
, qtask
, do_stop
, 0);
813 static int iscsi_retry_initial_login(struct iscsi_conn
*conn
)
815 int initial_login_retry_max
;
816 struct timeval now
, timeout
, fail_time
;
818 initial_login_retry_max
=
819 conn
->session
->nrec
.session
.initial_login_retry_max
;
821 memset(&now
, 0, sizeof(now
));
822 memset(&timeout
, 0, sizeof(timeout
));
823 memset(&fail_time
, 0, sizeof(fail_time
));
825 timeout
.tv_sec
= initial_login_retry_max
* conn
->login_timeout
;
826 if (gettimeofday(&now
, NULL
)) {
827 log_error("Could not get time of day. Dropping down to "
828 "max retry check.\n");
829 return initial_login_retry_max
> conn
->session
->reopen_cnt
;
831 timeradd(&conn
->initial_connect_time
, &timeout
, &fail_time
);
834 * if we have been trying for login_retry_max * login_timeout
835 * then it is time to give up
837 if (timercmp(&now
, &fail_time
, >)) {
838 log_debug(1, "Giving up on initial login attempt after "
840 initial_login_retry_max
* conn
->login_timeout
);
847 static void iscsi_login_eh(struct iscsi_conn
*conn
, struct queue_task
*qtask
,
850 struct iscsi_session
*session
= conn
->session
;
852 log_debug(3, "iscsi_login_eh");
854 * Flush polls and other events
856 iscsi_flush_context_pool(conn
->session
);
858 switch (conn
->state
) {
860 switch (session
->r_stage
) {
861 case R_STAGE_NO_CHANGE
:
862 log_debug(6, "login failed STATE_XPT_WAIT/"
863 "R_STAGE_NO_CHANGE");
864 /* timeout during initial connect.
865 * clean connection. write ipc rsp or retry */
866 if (err
== MGMT_IPC_ERR_FATAL_LOGIN_FAILURE
||
867 !iscsi_retry_initial_login(conn
))
868 session_conn_shutdown(conn
, qtask
, err
);
870 session
->reopen_cnt
++;
871 session
->t
->template->ep_disconnect(conn
);
872 if (iscsi_conn_connect(conn
, qtask
))
873 queue_delayed_reopen(qtask
,
874 ISCSI_CONN_ERR_REOPEN_DELAY
);
877 case R_STAGE_SESSION_REDIRECT
:
878 log_debug(6, "login failed STATE_XPT_WAIT/"
879 "R_STAGE_SESSION_REDIRECT");
880 /* timeout during initial redirect connect
881 * clean connection. write ipc rsp or retry */
882 if (err
== MGMT_IPC_ERR_FATAL_LOGIN_FAILURE
||
883 !iscsi_retry_initial_login(conn
))
884 session_conn_shutdown(conn
, qtask
, err
);
886 session_conn_reopen(conn
, qtask
, 0);
888 case R_STAGE_SESSION_REOPEN
:
889 log_debug(6, "login failed STATE_XPT_WAIT/"
890 "R_STAGE_SESSION_REOPEN %d",
891 session
->reopen_cnt
);
892 /* timeout during reopen connect. try again */
893 session_conn_reopen(conn
, qtask
, 0);
895 case R_STAGE_SESSION_CLEANUP
:
896 session_conn_shutdown(conn
, qtask
, err
);
904 switch (session
->r_stage
) {
905 case R_STAGE_NO_CHANGE
:
906 case R_STAGE_SESSION_REDIRECT
:
907 log_debug(6, "login failed STATE_IN_LOGIN/"
908 "R_STAGE_NO_CHANGE %d",
909 session
->reopen_cnt
);
911 * send pdu timeout during initial connect or
912 * initial redirected connect. Clean connection
913 * and write rsp or retry.
915 if (err
== MGMT_IPC_ERR_FATAL_LOGIN_FAILURE
||
916 !iscsi_retry_initial_login(conn
))
917 session_conn_shutdown(conn
, qtask
, err
);
919 session_conn_reopen(conn
, qtask
,
922 case R_STAGE_SESSION_REOPEN
:
923 log_debug(6, "login failed STATE_IN_LOGIN/"
924 "R_STAGE_SESSION_REOPEN %d",
925 session
->reopen_cnt
);
926 session_conn_reopen(conn
, qtask
, STOP_CONN_RECOVER
);
928 case R_STAGE_SESSION_CLEANUP
:
929 session_conn_shutdown(conn
, qtask
,
930 MGMT_IPC_ERR_PDU_TIMEOUT
);
938 log_error("Ignoring login error %d in conn state %d.\n",
945 __conn_error_handle(iscsi_session_t
*session
, iscsi_conn_t
*conn
)
950 * if we got an error while trying to logout for the user then
951 * just cleanup and return to the user.
953 if (conn
->logout_qtask
) {
954 session_conn_shutdown(conn
, conn
->logout_qtask
, MGMT_IPC_OK
);
958 switch (conn
->state
) {
959 case STATE_IN_LOGOUT
:
960 /* logout was from eh - fall down to cleanup */
961 case STATE_LOGGED_IN
:
962 /* mark failed connection */
963 conn
->state
= STATE_CLEANUP_WAIT
;
965 if (session
->erl
> 0) {
966 /* check if we still have some logged in connections */
967 for (i
=0; i
<ISCSI_CONN_MAX
; i
++) {
968 if (session
->conn
[i
].state
== STATE_LOGGED_IN
) {
972 if (i
!= ISCSI_CONN_MAX
) {
973 /* FIXME: re-assign leading connection
980 /* mark all connections as failed */
981 for (i
=0; i
<ISCSI_CONN_MAX
; i
++) {
982 if (session
->conn
[i
].state
== STATE_LOGGED_IN
)
983 session
->conn
[i
].state
= STATE_CLEANUP_WAIT
;
985 session
->r_stage
= R_STAGE_SESSION_REOPEN
;
988 if (session
->r_stage
== R_STAGE_SESSION_REOPEN
) {
991 if (session
->sync_qtask
)
992 qtask
= session
->sync_qtask
;
994 qtask
= &session
->reopen_qtask
;
995 iscsi_login_eh(conn
, qtask
, MGMT_IPC_ERR_TRANS_FAILURE
);
998 log_debug(1, "ignoring conn error in login. "
1001 case STATE_XPT_WAIT
:
1002 log_debug(1, "ignoring conn error in XPT_WAIT. "
1003 "let connection fail on its own");
1005 case STATE_CLEANUP_WAIT
:
1006 log_debug(1, "ignoring conn error in CLEANUP_WAIT. "
1007 "let connection stop");
1010 log_debug(8, "invalid state %d\n", conn
->state
);
1014 if (session
->r_stage
== R_STAGE_SESSION_REOPEN
) {
1015 session_conn_reopen(conn
, &session
->reopen_qtask
,
1021 static void session_conn_error(void *data
)
1023 struct iscsi_conn_context
*conn_context
= data
;
1024 enum iscsi_err error
= *(enum iscsi_err
*)conn_context
->data
;
1025 iscsi_conn_t
*conn
= conn_context
->conn
;
1026 iscsi_session_t
*session
= conn
->session
;
1028 log_warning("Kernel reported iSCSI connection %d:%d error (%d) "
1029 "state (%d)", session
->id
, conn
->id
, error
,
1031 iscsi_conn_context_put(conn_context
);
1034 case ISCSI_ERR_INVALID_HOST
:
1035 if (session_conn_shutdown(conn
, NULL
, MGMT_IPC_OK
))
1036 log_error("BUG: Could not shutdown session.");
1039 __conn_error_handle(session
, conn
);
1043 static void iscsi_login_timedout(void *data
)
1045 struct queue_task
*qtask
= data
;
1046 struct iscsi_conn
*conn
= qtask
->conn
;
1048 switch (conn
->state
) {
1049 case STATE_XPT_WAIT
:
1050 iscsi_login_eh(conn
, qtask
, MGMT_IPC_ERR_TRANS_TIMEOUT
);
1052 case STATE_IN_LOGIN
:
1053 iscsi_login_eh(conn
, qtask
, MGMT_IPC_ERR_PDU_TIMEOUT
);
1056 iscsi_login_eh(conn
, qtask
, MGMT_IPC_ERR_INTERNAL
);
1061 static void iscsi_login_redirect(iscsi_conn_t
*conn
)
1063 iscsi_session_t
*session
= conn
->session
;
1064 iscsi_login_context_t
*c
= &conn
->login_context
;
1066 log_debug(3, "login redirect ...\n");
1068 if (session
->r_stage
== R_STAGE_NO_CHANGE
)
1069 session
->r_stage
= R_STAGE_SESSION_REDIRECT
;
1071 __session_conn_reopen(conn
, c
->qtask
, STOP_CONN_RECOVER
, 1);
1075 __send_nopin_rsp(iscsi_conn_t
*conn
, struct iscsi_nopin
*rhdr
, char *data
)
1077 struct iscsi_nopout hdr
;
1079 memset(&hdr
, 0, sizeof(struct iscsi_nopout
));
1080 hdr
.opcode
= ISCSI_OP_NOOP_OUT
| ISCSI_OP_IMMEDIATE
;
1081 hdr
.flags
= ISCSI_FLAG_CMD_FINAL
;
1082 hdr
.dlength
[0] = rhdr
->dlength
[0];
1083 hdr
.dlength
[1] = rhdr
->dlength
[1];
1084 hdr
.dlength
[2] = rhdr
->dlength
[2];
1085 memcpy(hdr
.lun
, rhdr
->lun
, 8);
1086 hdr
.ttt
= rhdr
->ttt
;
1087 hdr
.itt
= ISCSI_RESERVED_TAG
;
1089 return iscsi_io_send_pdu(conn
, (struct iscsi_hdr
*)&hdr
,
1090 ISCSI_DIGEST_NONE
, data
, ISCSI_DIGEST_NONE
, 0);
1094 __send_nopout(iscsi_conn_t
*conn
)
1096 struct iscsi_nopout hdr
;
1098 memset(&hdr
, 0, sizeof(struct iscsi_nopout
));
1099 hdr
.opcode
= ISCSI_OP_NOOP_OUT
| ISCSI_OP_IMMEDIATE
;
1100 hdr
.flags
= ISCSI_FLAG_CMD_FINAL
;
1101 hdr
.itt
= 0; /* XXX: let kernel send_pdu set for us*/
1102 hdr
.ttt
= ISCSI_RESERVED_TAG
;
1103 /* we have hdr.lun reserved, and no data */
1104 return iscsi_io_send_pdu(conn
, (struct iscsi_hdr
*)&hdr
,
1105 ISCSI_DIGEST_NONE
, NULL
, ISCSI_DIGEST_NONE
, 0);
1108 static void conn_nop_out_timeout(void *data
)
1110 iscsi_conn_t
*conn
= (iscsi_conn_t
*)data
;
1111 iscsi_session_t
*session
= conn
->session
;
1113 log_warning("Nop-out timedout after %d seconds on connection %d:%d "
1114 "state (%d). Dropping session.", conn
->noop_out_timeout
,
1115 session
->id
, conn
->id
, conn
->state
);
1116 /* XXX: error handle */
1117 __conn_error_handle(session
, conn
);
1120 static void conn_send_nop_out(void *data
)
1122 iscsi_conn_t
*conn
= data
;
1125 * we cannot start new request during logout and the logout timer
1126 * will figure things out.
1128 if (conn
->state
== STATE_IN_LOGOUT
)
1131 __send_nopout(conn
);
1133 actor_timer(&conn
->nop_out_timer
, conn
->noop_out_timeout
*1000,
1134 conn_nop_out_timeout
, conn
);
1135 log_debug(3, "noop out timeout timer %p start, timeout %d\n",
1136 &conn
->nop_out_timer
, conn
->noop_out_timeout
);
1140 print_param_value(enum iscsi_param param
, void *value
, int type
)
1142 log_debug(3, "set operational parameter %d to:", param
);
1144 if (type
== ISCSI_STRING
)
1145 log_debug(3, "%s", value
? (char *)value
: "NULL");
1147 log_debug(3, "%u", *(uint32_t *)value
);
1150 void free_initiator(void)
1152 struct iscsi_transport
*t
;
1153 iscsi_session_t
*session
, *tmp
;
1155 list_for_each_entry(t
, &transports
, list
) {
1156 list_for_each_entry_safe(session
, tmp
, &t
->sessions
, list
) {
1157 list_del(&session
->list
);
1158 iscsi_flush_context_pool(session
);
1159 session_release(session
);
1166 static void session_scan_host(struct iscsi_session
*session
, int hostno
,
1167 queue_task_t
*qtask
)
1171 pid
= iscsi_sysfs_scan_host(hostno
, 1);
1173 mgmt_ipc_write_rsp(qtask
, MGMT_IPC_OK
);
1176 iscsi_sysfs_for_each_device(
1177 &session
->nrec
.session
.queue_depth
,
1178 hostno
, session
->id
,
1179 iscsi_sysfs_set_queue_depth
);
1181 } else if (pid
> 0) {
1184 close(qtask
->mgmt_ipc_fd
);
1188 mgmt_ipc_write_rsp(qtask
, MGMT_IPC_ERR_INTERNAL
);
1191 static int __iscsi_host_set_param(struct iscsi_transport
*t
,
1192 int host_no
, int param
, char *value
,
1197 rc
= ipc
->set_host_param(t
->handle
, host_no
, param
, value
, type
);
1198 /* 2.6.20 and below returns EINVAL */
1199 if (rc
&& rc
!= -ENOSYS
&& rc
!= -EINVAL
) {
1200 log_error("can't set operational parameter %d for "
1201 "host %d, retcode %d (%d)", param
, host_no
,
1208 mgmt_ipc_err_e
iscsi_host_set_param(int host_no
, int param
, char *value
)
1210 struct iscsi_transport
*t
;
1212 t
= iscsi_sysfs_get_transport_by_hba(host_no
);
1214 return MGMT_IPC_ERR_TRANS_FAILURE
;
1215 if (__iscsi_host_set_param(t
, host_no
, param
, value
, ISCSI_STRING
))
1216 return MGMT_IPC_ERR
;
1220 #define MAX_SESSION_PARAMS 32
1221 #define MAX_HOST_PARAMS 3
1224 setup_full_feature_phase(iscsi_conn_t
*conn
)
1226 iscsi_session_t
*session
= conn
->session
;
1227 iscsi_login_context_t
*c
= &conn
->login_context
;
1229 uint32_t one
= 1, zero
= 0;
1235 } hosttbl
[MAX_HOST_PARAMS
] = {
1237 .param
= ISCSI_HOST_PARAM_NETDEV_NAME
,
1238 .value
= session
->nrec
.iface
.netdev
,
1239 .type
= ISCSI_STRING
,
1242 .param
= ISCSI_HOST_PARAM_HWADDRESS
,
1243 .value
= session
->nrec
.iface
.hwaddress
,
1244 .type
= ISCSI_STRING
,
1247 .param
= ISCSI_HOST_PARAM_INITIATOR_NAME
,
1248 .value
= session
->initiator_name
,
1249 .type
= ISCSI_STRING
,
1258 } conntbl
[MAX_SESSION_PARAMS
] = {
1260 .param
= ISCSI_PARAM_MAX_RECV_DLENGTH
,
1261 .value
= &conn
->max_recv_dlength
,
1265 .param
= ISCSI_PARAM_MAX_XMIT_DLENGTH
,
1266 .value
= &conn
->max_xmit_dlength
,
1270 .param
= ISCSI_PARAM_HDRDGST_EN
,
1271 .value
= &conn
->hdrdgst_en
,
1275 .param
= ISCSI_PARAM_DATADGST_EN
,
1276 .value
= &conn
->datadgst_en
,
1280 .param
= ISCSI_PARAM_INITIAL_R2T_EN
,
1281 .value
= &session
->initial_r2t_en
,
1285 .param
= ISCSI_PARAM_MAX_R2T
,
1286 .value
= &one
, /* FIXME: session->max_r2t */
1290 .param
= ISCSI_PARAM_IMM_DATA_EN
,
1291 .value
= &session
->imm_data_en
,
1295 .param
= ISCSI_PARAM_FIRST_BURST
,
1296 .value
= &session
->first_burst
,
1300 .param
= ISCSI_PARAM_MAX_BURST
,
1301 .value
= &session
->max_burst
,
1305 .param
= ISCSI_PARAM_PDU_INORDER_EN
,
1306 .value
= &session
->pdu_inorder_en
,
1310 .param
=ISCSI_PARAM_DATASEQ_INORDER_EN
,
1311 .value
= &session
->dataseq_inorder_en
,
1315 .param
= ISCSI_PARAM_ERL
,
1316 .value
= &zero
, /* FIXME: session->erl */
1320 .param
= ISCSI_PARAM_IFMARKER_EN
,
1321 .value
= &zero
,/* FIXME: session->ifmarker_en */
1325 .param
= ISCSI_PARAM_OFMARKER_EN
,
1326 .value
= &zero
,/* FIXME: session->ofmarker_en */
1330 .param
= ISCSI_PARAM_EXP_STATSN
,
1331 .value
= &conn
->exp_statsn
,
1335 .param
= ISCSI_PARAM_TARGET_NAME
,
1337 .type
= ISCSI_STRING
,
1338 .value
= session
->target_name
,
1340 .param
= ISCSI_PARAM_TPGT
,
1341 .value
= &session
->portal_group_tag
,
1345 .param
= ISCSI_PARAM_PERSISTENT_ADDRESS
,
1346 .value
= session
->nrec
.conn
[conn
->id
].address
,
1347 .type
= ISCSI_STRING
,
1350 .param
= ISCSI_PARAM_PERSISTENT_PORT
,
1351 .value
= &session
->nrec
.conn
[conn
->id
].port
,
1355 .param
= ISCSI_PARAM_SESS_RECOVERY_TMO
,
1356 .value
= &session
->replacement_timeout
,
1360 .param
= ISCSI_PARAM_USERNAME
,
1361 .value
= session
->username
,
1362 .type
= ISCSI_STRING
,
1365 .param
= ISCSI_PARAM_USERNAME_IN
,
1366 .value
= session
->username_in
,
1367 .type
= ISCSI_STRING
,
1370 .param
= ISCSI_PARAM_PASSWORD
,
1371 .value
= session
->password
,
1372 .type
= ISCSI_STRING
,
1375 .param
= ISCSI_PARAM_PASSWORD_IN
,
1376 .value
= session
->password_in
,
1377 .type
= ISCSI_STRING
,
1380 .param
= ISCSI_PARAM_FAST_ABORT
,
1381 .value
= &session
->fast_abort
,
1385 .param
= ISCSI_PARAM_ABORT_TMO
,
1386 .value
= &session
->abort_timeout
,
1390 .param
= ISCSI_PARAM_LU_RESET_TMO
,
1391 .value
= &session
->lu_reset_timeout
,
1395 .param
= ISCSI_PARAM_TGT_RESET_TMO
,
1396 .value
= &session
->tgt_reset_timeout
,
1400 .param
= ISCSI_PARAM_PING_TMO
,
1401 .value
= &conn
->noop_out_timeout
,
1405 .param
= ISCSI_PARAM_RECV_TMO
,
1406 .value
= &conn
->noop_out_interval
,
1410 .param
= ISCSI_PARAM_IFACE_NAME
,
1411 .value
= session
->nrec
.iface
.name
,
1412 .type
= ISCSI_STRING
,
1414 .param
= ISCSI_PARAM_INITIATOR_NAME
,
1415 .value
= session
->initiator_name
,
1416 .type
= ISCSI_STRING
,
1420 actor_delete(&conn
->login_timer
);
1421 /* Entered full-feature phase! */
1422 for (i
= 0; i
< MAX_SESSION_PARAMS
; i
++) {
1423 if (conn
->id
!= 0 && !conntbl
[i
].conn_only
)
1426 if (!(session
->param_mask
& (1ULL << conntbl
[i
].param
)))
1429 rc
= ipc
->set_param(session
->t
->handle
, session
->id
,
1430 conn
->id
, conntbl
[i
].param
, conntbl
[i
].value
,
1432 if (rc
&& rc
!= -ENOSYS
) {
1433 log_error("can't set operational parameter %d for "
1434 "connection %d:%d, retcode %d (%d)",
1435 conntbl
[i
].param
, session
->id
, conn
->id
,
1438 iscsi_login_eh(conn
, c
->qtask
,
1439 MGMT_IPC_ERR_LOGIN_FAILURE
);
1443 if (rc
== -ENOSYS
) {
1444 switch (conntbl
[i
].param
) {
1445 case ISCSI_PARAM_PING_TMO
:
1447 * older kernels may not support nops
1450 conn
->userspace_nop
= 1;
1452 case ISCSI_PARAM_INITIATOR_NAME
:
1453 /* use host level one instead */
1454 hosttbl
[ISCSI_HOST_PARAM_INITIATOR_NAME
].set
= 1;
1459 print_param_value(conntbl
[i
].param
, conntbl
[i
].value
,
1463 for (i
= 0; i
< MAX_HOST_PARAMS
; i
++) {
1464 if (!hosttbl
[i
].set
)
1467 if (__iscsi_host_set_param(session
->t
, session
->hostno
,
1468 hosttbl
[i
].param
, hosttbl
[i
].value
,
1470 iscsi_login_eh(conn
, c
->qtask
,
1471 MGMT_IPC_ERR_LOGIN_FAILURE
);
1475 print_param_value(hosttbl
[i
].param
, hosttbl
[i
].value
,
1479 if (ipc
->start_conn(session
->t
->handle
, session
->id
, conn
->id
,
1481 log_error("can't start connection %d:%d retcode %d (%d)",
1482 session
->id
, conn
->id
, rc
, errno
);
1483 iscsi_login_eh(conn
, c
->qtask
, MGMT_IPC_ERR_INTERNAL
);
1487 conn
->state
= STATE_LOGGED_IN
;
1488 if (session
->r_stage
== R_STAGE_NO_CHANGE
||
1489 session
->r_stage
== R_STAGE_SESSION_REDIRECT
) {
1491 * scan host is one-time deal. We
1492 * don't want to re-scan it on recovery.
1495 session_scan_host(session
, session
->hostno
, c
->qtask
);
1497 log_warning("Connection%d:%d to [target: %s, portal: %s,%d] "
1498 "through [iface: %s] is operational now",
1499 session
->id
, conn
->id
, session
->nrec
.name
,
1500 session
->nrec
.conn
[conn
->id
].address
,
1501 session
->nrec
.conn
[conn
->id
].port
,
1502 session
->nrec
.iface
.name
);
1504 session
->sync_qtask
= NULL
;
1506 session_online_devs(session
->hostno
, session
->id
);
1507 mgmt_ipc_write_rsp(c
->qtask
, MGMT_IPC_OK
);
1508 log_warning("connection%d:%d is operational after recovery "
1509 "(%d attempts)", session
->id
, conn
->id
,
1510 session
->reopen_cnt
);
1514 * reset ERL=0 reopen counter
1516 session
->reopen_cnt
= 0;
1517 session
->r_stage
= R_STAGE_NO_CHANGE
;
1520 if (conn
->userspace_nop
&& conn
->noop_out_interval
) {
1521 actor_timer(&conn
->nop_out_timer
, conn
->noop_out_interval
*1000,
1522 conn_send_nop_out
, conn
);
1523 log_debug(3, "noop out timer %p start\n",
1524 &conn
->nop_out_timer
);
1528 static void iscsi_logout_timedout(void *data
)
1530 struct iscsi_conn_context
*conn_context
= data
;
1531 struct iscsi_conn
*conn
= conn_context
->conn
;
1533 iscsi_conn_context_put(conn_context
);
1535 * assume we were in STATE_IN_LOGOUT or there
1536 * was some nasty error
1538 log_debug(3, "logout timeout, dropping conn...\n");
1539 __conn_error_handle(conn
->session
, conn
);
1542 static int iscsi_send_logout(iscsi_conn_t
*conn
)
1544 struct iscsi_logout hdr
;
1545 struct iscsi_conn_context
*conn_context
;
1547 if (conn
->state
!= STATE_LOGGED_IN
)
1550 memset(&hdr
, 0, sizeof(struct iscsi_logout
));
1551 hdr
.opcode
= ISCSI_OP_LOGOUT
| ISCSI_OP_IMMEDIATE
;
1552 hdr
.flags
= ISCSI_FLAG_CMD_FINAL
|
1553 (ISCSI_LOGOUT_REASON_CLOSE_SESSION
& ISCSI_FLAG_LOGOUT_REASON_MASK
);
1554 /* kernel will set the rest */
1556 if (!iscsi_io_send_pdu(conn
, (struct iscsi_hdr
*)&hdr
,
1557 ISCSI_DIGEST_NONE
, NULL
, ISCSI_DIGEST_NONE
, 0))
1559 conn
->state
= STATE_IN_LOGOUT
;
1561 conn_context
= iscsi_conn_context_get(conn
, 0);
1563 /* unbounded logout */
1564 log_warning("Could not allocate conn context for logout.");
1566 iscsi_sched_conn_context(conn_context
, conn
,
1567 conn
->logout_timeout
,
1568 EV_CONN_LOGOUT_TIMER
);
1569 log_debug(3, "logout timeout timer %u\n",
1570 conn
->logout_timeout
* 1000);
1576 static void iscsi_stop(void *data
)
1578 struct iscsi_conn_context
*conn_context
= data
;
1579 struct iscsi_conn
*conn
= conn_context
->conn
;
1582 iscsi_conn_context_put(conn_context
);
1584 if (!iscsi_send_logout(conn
))
1587 rc
= session_conn_shutdown(conn
, conn
->logout_qtask
, MGMT_IPC_OK
);
1589 log_error("BUG: Could not shutdown session.");
1592 static void iscsi_recv_nop_in(iscsi_conn_t
*conn
, struct iscsi_hdr
*hdr
)
1594 if (!conn
->userspace_nop
) {
1595 log_error("Got nop in, but kernel supports nop handling.");
1599 if (hdr
->ttt
== ISCSI_RESERVED_TAG
) {
1601 actor_delete(&conn
->nop_out_timer
);
1602 /* schedule a new ping */
1603 actor_timer(&conn
->nop_out_timer
, conn
->noop_out_interval
*1000,
1604 conn_send_nop_out
, conn
);
1605 } else /* noop in req */
1606 if (!__send_nopin_rsp(conn
, (struct iscsi_nopin
*)hdr
,
1608 log_error("can not send nopin response");
1612 static void iscsi_recv_logout_rsp(iscsi_conn_t
*conn
, struct iscsi_hdr
*hdr
)
1614 struct iscsi_logout_rsp
*logout_rsp
= (struct iscsi_logout_rsp
*)hdr
;
1616 log_debug(3, "Recv: logout response %d\n", logout_rsp
->response
);
1617 if (logout_rsp
->response
== 2 || logout_rsp
->response
== 3) {
1618 conn
->session
->def_time2wait
= ntohs(logout_rsp
->t2wait
);
1619 log_debug(4, "logout rsp returned time2wait %u",
1620 conn
->session
->def_time2wait
);
1622 /* TODO process the hdr */
1623 __conn_error_handle(conn
->session
, conn
);
1626 static void iscsi_recv_async_msg(iscsi_conn_t
*conn
, struct iscsi_hdr
*hdr
)
1628 iscsi_session_t
*session
= conn
->session
;
1629 struct iscsi_async
*async_hdr
= (struct iscsi_async
*)hdr
;
1630 char *buf
= conn
->data
;
1631 unsigned int senselen
;
1632 struct scsi_sense_hdr sshdr
;
1634 log_debug(3, "Read AEN %d\n", async_hdr
->async_event
);
1636 switch (async_hdr
->async_event
) {
1637 case ISCSI_ASYNC_MSG_SCSI_EVENT
:
1638 senselen
= (buf
[0] << 8) | buf
[1];
1641 if (!scsi_normalize_sense((uint8_t *)buf
, senselen
, &sshdr
)) {
1642 log_error("Could not handle AEN %d. Invalid sense.",
1643 async_hdr
->async_event
);
1647 if (sshdr
.asc
== 0x3f && sshdr
.ascq
== 0x0e)
1648 session_scan_host(session
, session
->hostno
, NULL
);
1650 case ISCSI_ASYNC_MSG_REQUEST_LOGOUT
:
1651 log_warning("Target requests logout within %u seconds for "
1652 "connection\n", ntohs(async_hdr
->param3
));
1653 if (iscsi_send_logout(conn
))
1654 log_error("Could not send logout in response to"
1655 "logout request aen\n");
1657 case ISCSI_ASYNC_MSG_DROPPING_CONNECTION
:
1658 log_warning("Target dropping connection %u, reconnect min %u "
1659 "max %u\n", ntohs(async_hdr
->param1
),
1660 ntohs(async_hdr
->param2
), ntohs(async_hdr
->param3
));
1661 session
->def_time2wait
=
1662 (uint32_t)ntohs(async_hdr
->param2
) & 0x0000FFFFFL
;
1664 case ISCSI_ASYNC_MSG_DROPPING_ALL_CONNECTIONS
:
1665 log_warning("Target dropping all connections, reconnect min %u "
1666 "max %u\n", ntohs(async_hdr
->param2
),
1667 ntohs(async_hdr
->param3
));
1668 session
->def_time2wait
=
1669 (uint32_t)ntohs(async_hdr
->param2
) & 0x0000FFFFFL
;
1671 case ISCSI_ASYNC_MSG_PARAM_NEGOTIATION
:
1672 log_warning("Received async event param negotiation, "
1673 "dropping session\n");
1674 __conn_error_handle(session
, conn
);
1676 case ISCSI_ASYNC_MSG_VENDOR_SPECIFIC
:
1678 log_warning("AEN not supported\n");
1682 static void iscsi_recv_login_rsp(struct iscsi_conn
*conn
)
1684 struct iscsi_session
*session
= conn
->session
;
1685 iscsi_login_context_t
*c
= &conn
->login_context
;
1687 if (iscsi_login_rsp(session
, c
)) {
1688 log_debug(1, "login_rsp ret (%d)", c
->ret
);
1690 switch (__login_response_status(conn
, c
->ret
)) {
1691 case CONN_LOGIN_FAILED
:
1693 case CONN_LOGIN_RETRY
:
1695 case CONN_LOGIN_IMM_REDIRECT_RETRY
:
1696 iscsi_login_redirect(conn
);
1699 ; /* success - fall through */
1702 /* check the login status */
1703 switch (__check_iscsi_status_class(session
, conn
->id
,
1705 c
->status_detail
)) {
1706 case CONN_LOGIN_FAILED
:
1708 case CONN_LOGIN_IMM_REDIRECT_RETRY
:
1709 iscsi_login_redirect(conn
);
1711 case CONN_LOGIN_IMM_RETRY
:
1712 case CONN_LOGIN_RETRY
:
1715 ; /* success - fall through */
1719 if (conn
->current_stage
!= ISCSI_FULL_FEATURE_PHASE
) {
1720 /* more nego. needed! */
1721 conn
->state
= STATE_IN_LOGIN
;
1722 if (iscsi_login_req(session
, c
)) {
1723 iscsi_login_eh(conn
, c
->qtask
,
1724 MGMT_IPC_ERR_LOGIN_FAILURE
);
1728 setup_full_feature_phase(conn
);
1732 /* retry if not initial login or initial login has not timed out */
1733 iscsi_login_eh(conn
, c
->qtask
, MGMT_IPC_ERR_LOGIN_FAILURE
);
1736 /* force failure if initial login */
1737 session
->reopen_cnt
= session
->nrec
.session
.initial_login_retry_max
;
1738 iscsi_login_eh(conn
, c
->qtask
, MGMT_IPC_ERR_FATAL_LOGIN_FAILURE
);
1742 static void session_conn_recv_pdu(void *data
)
1744 struct iscsi_conn_context
*conn_context
= data
;
1745 iscsi_conn_t
*conn
= conn_context
->conn
;
1746 struct iscsi_hdr hdr
;
1748 conn
->recv_context
= conn_context
;
1750 switch (conn
->state
) {
1751 case STATE_IN_LOGIN
:
1752 iscsi_recv_login_rsp(conn
);
1754 case STATE_LOGGED_IN
:
1755 case STATE_IN_LOGOUT
:
1756 case STATE_LOGOUT_REQUESTED
:
1757 /* read incoming PDU */
1758 if (!iscsi_io_recv_pdu(conn
, &hdr
, ISCSI_DIGEST_NONE
,
1759 conn
->data
, ISCSI_DEF_MAX_RECV_SEG_LEN
,
1760 ISCSI_DIGEST_NONE
, 0)) {
1764 switch (hdr
.opcode
& ISCSI_OPCODE_MASK
) {
1765 case ISCSI_OP_NOOP_IN
:
1766 iscsi_recv_nop_in(conn
, &hdr
);
1768 case ISCSI_OP_LOGOUT_RSP
:
1769 iscsi_recv_logout_rsp(conn
, &hdr
);
1771 case ISCSI_OP_ASYNC_EVENT
:
1772 iscsi_recv_async_msg(conn
, &hdr
);
1775 log_error("unsupported opcode 0x%x", hdr
.opcode
);
1779 case STATE_XPT_WAIT
:
1780 iscsi_conn_context_put(conn_context
);
1781 log_debug(1, "ignoring incoming PDU in XPT_WAIT. "
1782 "let connection re-establish or fail");
1784 case STATE_CLEANUP_WAIT
:
1785 iscsi_conn_context_put(conn_context
);
1786 log_debug(1, "ignoring incoming PDU in XPT_WAIT. "
1787 "let connection cleanup");
1790 iscsi_conn_context_put(conn_context
);
1791 log_error("Invalid state. Dropping PDU.\n");
1795 static void session_increase_wq_priority(struct iscsi_session
*session
)
1798 struct dirent
*proc_dent
;
1800 char stat_file
[PATH_SIZE
];
1801 char sbuf
[1024]; /* got this from ps */
1802 int pid
, stat_fd
, num_read
;
1803 char *proc_name
, *proc_name_end
;
1806 /* drivers like bnx2i and qla4xxx do not have a write wq */
1807 if (session
->t
->caps
& CAP_DATA_PATH_OFFLOAD
)
1810 proc_dir
= opendir(PROC_DIR
);
1814 while ((proc_dent
= readdir(proc_dir
))) {
1815 if (!strcmp(proc_dent
->d_name
, ".") ||
1816 !strcmp(proc_dent
->d_name
, ".."))
1818 if (sscanf(proc_dent
->d_name
, "%d", &pid
) != 1)
1821 memset(stat_file
, 0, sizeof(stat_file
));
1822 sprintf(stat_file
, PROC_DIR
"/%d/stat", pid
);
1823 if (stat(stat_file
, &statb
))
1826 if (!S_ISREG( statb
.st_mode
))
1829 stat_fd
= open(stat_file
, O_RDONLY
);
1833 memset(sbuf
, 0, sizeof(sbuf
));
1834 num_read
= read(stat_fd
, sbuf
, sizeof(sbuf
));
1838 if (num_read
== sizeof(sbuf
))
1839 sbuf
[num_read
- 1] = '\0';
1841 sbuf
[num_read
] = '\0';
1844 * Finally match proc name to iscsi thread name.
1845 * In newer kernels the name is iscsi_wq_%HOST_NO.
1846 * In older kernels before 2.6.30, it was scsi_wq_%HOST_NO.
1848 * We only support newer kernels.
1850 proc_name
= strchr(sbuf
, '(') + 1;
1854 proc_name_end
= strchr(proc_name
, ')');
1858 *proc_name_end
= '\0';
1860 if (sscanf(proc_name
, "iscsi_q_%u\n", &host_no
) == 1) {
1861 if (host_no
== session
->hostno
) {
1862 if (!setpriority(PRIO_PROCESS
, pid
,
1863 session
->nrec
.session
.xmit_thread_priority
)) {
1873 log_error("Could not set session%d priority. "
1874 "READ/WRITE throughout and latency could be "
1875 "affected.\n", session
->id
);
1878 static int session_ipc_create(struct iscsi_session
*session
)
1880 struct iscsi_conn
*conn
= &session
->conn
[0];
1881 int err
= 0, pass_ep
= 1;
1882 uint32_t host_no
= -1;
1884 if (session
->t
->template->ep_connect
!= ktransport_ep_connect
)
1887 err
= ipc
->create_session(session
->t
->handle
,
1888 pass_ep
? conn
->transport_ep_handle
: 0,
1889 session
->nrec
.session
.initial_cmdsn
,
1890 session
->nrec
.session
.cmds_max
,
1891 session
->nrec
.session
.queue_depth
,
1892 &session
->id
, &host_no
);
1894 * Older kernels were not passed the sessions's leading conn ep,
1895 * so we will get -EINVAL || -ENOSYS for iser.
1897 * 2.6.22 and earlier would send -EINVAL instead of -ENOSYS.
1899 if (pass_ep
&& (err
== -ENOSYS
|| err
== -EINVAL
)) {
1905 session
->hostno
= host_no
;
1906 session_increase_wq_priority(session
);
1911 static void session_conn_poll(void *data
)
1913 struct iscsi_conn_context
*conn_context
= data
;
1914 iscsi_conn_t
*conn
= conn_context
->conn
;
1915 struct iscsi_session
*session
= conn
->session
;
1916 mgmt_ipc_err_e err
= MGMT_IPC_OK
;
1917 queue_task_t
*qtask
= conn_context
->data
;
1918 iscsi_login_context_t
*c
= &conn
->login_context
;
1921 iscsi_conn_context_put(conn_context
);
1923 if (conn
->state
!= STATE_XPT_WAIT
)
1926 rc
= session
->t
->template->ep_poll(conn
, 1);
1928 log_debug(4, "poll not connected %d", rc
);
1929 /* timedout: Poll again. */
1930 conn_context
= iscsi_conn_context_get(conn
, 0);
1931 if (!conn_context
) {
1932 /* while polling the recv pool should be full */
1933 log_error("BUG: session_conn_poll could not get conn "
1935 iscsi_login_eh(conn
, qtask
, MGMT_IPC_ERR_INTERNAL
);
1938 conn_context
->data
= qtask
;
1939 iscsi_sched_conn_context(conn_context
, conn
, 0, EV_CONN_POLL
);
1940 } else if (rc
> 0) {
1942 memset(c
, 0, sizeof(iscsi_login_context_t
));
1944 /* do not allocate new connection in case of reopen */
1945 if (session
->id
== -1) {
1946 if (conn
->id
== 0 && session_ipc_create(session
)) {
1947 log_error("Can't create session.");
1948 err
= MGMT_IPC_ERR_INTERNAL
;
1951 log_debug(3, "created new iSCSI session sid %d host "
1952 "no %u", session
->id
, session
->hostno
);
1954 if (ipc
->create_conn(session
->t
->handle
,
1955 session
->id
, conn
->id
, &conn
->id
)) {
1956 log_error("Can't create connection.");
1957 err
= MGMT_IPC_ERR_INTERNAL
;
1960 log_debug(3, "created new iSCSI connection "
1961 "%d:%d", session
->id
, conn
->id
);
1964 iscsi_copy_operational_params(conn
);
1966 if (session
->t
->template->create_conn
)
1967 session
->t
->template->create_conn(conn
);
1969 * TODO: use the iface number or some other value
1970 * so this will be persistent
1972 session
->isid
[3] = session
->id
;
1974 if (ipc
->bind_conn(session
->t
->handle
, session
->id
,
1975 conn
->id
, conn
->transport_ep_handle
,
1976 (conn
->id
== 0), &rc
) || rc
) {
1977 log_error("can't bind conn %d:%d to session %d, "
1978 "retcode %d (%d)", session
->id
, conn
->id
,
1979 session
->id
, rc
, errno
);
1980 iscsi_login_eh(conn
, qtask
, MGMT_IPC_ERR_LOGIN_FAILURE
);
1983 log_debug(3, "bound iSCSI connection %d:%d to session %d",
1984 session
->id
, conn
->id
, session
->id
);
1988 c
->buffer
= conn
->data
;
1989 c
->bufsize
= sizeof(conn
->data
);
1991 conn
->exp_statsn
= iscsi_sysfs_get_exp_statsn(session
->id
);
1993 if (iscsi_login_begin(session
, c
)) {
1994 iscsi_login_eh(conn
, qtask
, MGMT_IPC_ERR_LOGIN_FAILURE
);
1998 conn
->state
= STATE_IN_LOGIN
;
1999 if (iscsi_login_req(session
, c
)) {
2000 iscsi_login_eh(conn
, qtask
, MGMT_IPC_ERR_LOGIN_FAILURE
);
2004 log_debug(4, "poll error %d", rc
);
2005 queue_delayed_reopen(qtask
, ISCSI_CONN_ERR_REOPEN_DELAY
);
2011 session_conn_shutdown(conn
, qtask
, err
);
2014 void iscsi_sched_conn_context(struct iscsi_conn_context
*conn_context
,
2015 struct iscsi_conn
*conn
, unsigned long tmo
,
2018 enum iscsi_err error
;
2020 log_debug(7, "sched conn context %p event %d, tmo %lu",
2021 &conn_context
->actor
, event
, tmo
);
2023 conn_context
->conn
= conn
;
2025 case EV_CONN_RECV_PDU
:
2026 actor_new(&conn_context
->actor
, session_conn_recv_pdu
,
2028 actor_schedule(&conn_context
->actor
);
2031 error
= *(enum iscsi_err
*)conn_context
->data
;
2033 actor_new(&conn_context
->actor
, session_conn_error
,
2036 * We handle invalid host, by killing the session.
2037 * It must go at the head of the queue, so we do not
2038 * initiate error handling or logout or some other op.
2040 if (error
== ISCSI_ERR_INVALID_HOST
)
2041 actor_schedule_head(&conn_context
->actor
);
2043 actor_schedule(&conn_context
->actor
);
2046 actor_new(&conn_context
->actor
, session_conn_poll
,
2048 actor_schedule(&conn_context
->actor
);
2050 case EV_CONN_LOGOUT_TIMER
:
2051 actor_timer(&conn_context
->actor
, tmo
* 1000,
2052 iscsi_logout_timedout
, conn_context
);
2055 actor_new(&conn_context
->actor
, iscsi_stop
,
2057 actor_schedule(&conn_context
->actor
);
2060 log_error("Invalid event type %d.", event
);
2066 session_find_by_sid(int sid
)
2068 struct iscsi_transport
*t
;
2069 iscsi_session_t
*session
;
2071 list_for_each_entry(t
, &transports
, list
) {
2072 list_for_each_entry(session
, &t
->sessions
, list
) {
2073 if (session
->id
== sid
)
2080 static iscsi_session_t
* session_find_by_rec(node_rec_t
*rec
)
2082 struct iscsi_transport
*t
;
2083 iscsi_session_t
*session
;
2085 list_for_each_entry(t
, &transports
, list
) {
2086 list_for_each_entry(session
, &t
->sessions
, list
) {
2087 if (__iscsi_match_session(rec
, session
->nrec
.name
,
2088 session
->nrec
.conn
[0].address
,
2089 session
->nrec
.conn
[0].port
,
2090 &session
->nrec
.iface
))
2098 * a session could be running in the kernel but not in iscsid
2099 * due to a resync or becuase some other app started the session
2101 static int session_is_running(node_rec_t
*rec
)
2105 if (session_find_by_rec(rec
))
2108 if (iscsi_sysfs_for_each_session(rec
, &nr_found
, iscsi_match_session
))
2114 static int iface_set_param(struct iscsi_transport
*t
, struct iface_rec
*iface
,
2115 struct iscsi_session
*session
)
2119 log_debug(3, "setting iface %s, dev %s, set ip %s, hw %s, "
2121 iface
->name
, iface
->netdev
, iface
->ipaddress
,
2122 iface
->hwaddress
, iface
->transport_name
);
2124 if (!t
->template->set_host_ip
)
2127 /* if we need to set the ip addr then set all the iface net settings */
2128 if (!iface_is_bound_by_ipaddr(iface
)) {
2129 log_warning("Please set the iface.ipaddress for iface %s, "
2130 "then retry the login command.\n", iface
->name
);
2134 rc
= __iscsi_host_set_param(t
, session
->hostno
,
2135 ISCSI_HOST_PARAM_IPADDRESS
,
2136 iface
->ipaddress
, ISCSI_STRING
);
2140 if (iface_is_bound_by_netdev(iface
)) {
2141 rc
= __iscsi_host_set_param(t
, session
->hostno
,
2142 ISCSI_HOST_PARAM_NETDEV_NAME
,
2143 iface
->netdev
, ISCSI_STRING
);
2148 if (iface_is_bound_by_hwaddr(iface
)) {
2149 rc
= __iscsi_host_set_param(t
, session
->hostno
,
2150 ISCSI_HOST_PARAM_HWADDRESS
,
2151 iface
->hwaddress
, ISCSI_STRING
);
2159 session_login_task(node_rec_t
*rec
, queue_task_t
*qtask
)
2161 iscsi_session_t
*session
;
2163 struct iscsi_transport
*t
;
2165 if (session_is_running(rec
))
2166 return MGMT_IPC_ERR_EXISTS
;
2168 t
= iscsi_sysfs_get_transport_by_name(rec
->iface
.transport_name
);
2170 return MGMT_IPC_ERR_TRANS_NOT_FOUND
;
2171 if (set_transport_template(t
))
2172 return MGMT_IPC_ERR_TRANS_NOT_FOUND
;
2174 if ((!(t
->caps
& CAP_RECOVERY_L0
) &&
2175 rec
->session
.iscsi
.ERL
!= 0) ||
2176 (!(t
->caps
& CAP_RECOVERY_L1
) &&
2177 rec
->session
.iscsi
.ERL
> 1)) {
2178 log_error("Transport '%s' does not support ERL %d."
2179 "Setting ERL to ERL0.\n",
2180 t
->name
, rec
->session
.iscsi
.ERL
);
2181 rec
->session
.iscsi
.ERL
= 0;
2184 if (!(t
->caps
& CAP_MULTI_R2T
) &&
2185 rec
->session
.iscsi
.MaxOutstandingR2T
) {
2186 log_error("Transport '%s' does not support "
2187 "MaxOutstandingR2T %d. Setting "
2188 "MaxOutstandingR2T to 1.", t
->name
,
2189 rec
->session
.iscsi
.MaxOutstandingR2T
);
2190 rec
->session
.iscsi
.MaxOutstandingR2T
= 1;
2193 if (!(t
->caps
& CAP_HDRDGST
) &&
2194 rec
->conn
[0].iscsi
.HeaderDigest
) {
2195 log_error("Transport '%s' does not support "
2196 "HeaderDigest != None. Setting HeaderDigest "
2197 "to None.", t
->name
);
2198 rec
->conn
[0].iscsi
.HeaderDigest
= CONFIG_DIGEST_NEVER
;
2201 if (!(t
->caps
& CAP_DATADGST
) &&
2202 rec
->conn
[0].iscsi
.DataDigest
) {
2203 log_error("Transport '%s' does not support "
2204 "DataDigest != None. Setting DataDigest "
2205 "to None", t
->name
);
2206 rec
->conn
[0].iscsi
.DataDigest
= CONFIG_DIGEST_NEVER
;
2209 if (!(t
->caps
& CAP_MARKERS
) &&
2210 rec
->conn
[0].iscsi
.IFMarker
) {
2211 log_error("Transport '%s' does not support IFMarker. "
2212 "Disabling IFMarkers.\n", t
->name
);
2213 rec
->conn
[0].iscsi
.IFMarker
= 0;
2216 if (!(t
->caps
& CAP_MARKERS
) &&
2217 rec
->conn
[0].iscsi
.OFMarker
) {
2218 log_error("Transport '%s' does not support OFMarker."
2219 "Disabling OFMarkers.\n", t
->name
);
2220 rec
->conn
[0].iscsi
.OFMarker
= 0;
2223 session
= __session_create(rec
, t
);
2225 return MGMT_IPC_ERR_LOGIN_FAILURE
;
2227 /* FIXME: login all connections! marked as "automatic" */
2229 /* create leading connection */
2230 if (__session_conn_create(session
, 0)) {
2231 __session_destroy(session
);
2232 return MGMT_IPC_ERR_LOGIN_FAILURE
;
2234 conn
= &session
->conn
[0];
2237 if (iface_set_param(t
, &rec
->iface
, session
)) {
2238 __session_destroy(session
);
2239 return MGMT_IPC_ERR_LOGIN_FAILURE
;
2242 conn
->state
= STATE_XPT_WAIT
;
2243 if (iscsi_conn_connect(conn
, qtask
)) {
2244 __session_destroy(session
);
2245 return MGMT_IPC_ERR_TRANS_FAILURE
;
2248 if (gettimeofday(&conn
->initial_connect_time
, NULL
))
2249 log_error("Could not get initial connect time. If "
2250 "login errors iscsid may give up the initial "
2251 "login early. You should manually login.");
2253 qtask
->rsp
.command
= MGMT_IPC_SESSION_LOGIN
;
2254 qtask
->rsp
.err
= MGMT_IPC_OK
;
2259 sync_conn(iscsi_session_t
*session
, uint32_t cid
)
2263 if (__session_conn_create(session
, cid
))
2265 conn
= &session
->conn
[cid
];
2267 /* TODO: must export via sysfs so we can pick this up */
2268 conn
->state
= STATE_CLEANUP_WAIT
;
2273 iscsi_sync_session(node_rec_t
*rec
, queue_task_t
*qtask
, uint32_t sid
)
2275 iscsi_session_t
*session
;
2276 struct iscsi_transport
*t
;
2279 t
= iscsi_sysfs_get_transport_by_name(rec
->iface
.transport_name
);
2281 return MGMT_IPC_ERR_TRANS_NOT_FOUND
;
2282 if (set_transport_template(t
))
2283 return MGMT_IPC_ERR_TRANS_NOT_FOUND
;
2285 session
= __session_create(rec
, t
);
2287 return MGMT_IPC_ERR_LOGIN_FAILURE
;
2290 session
->hostno
= iscsi_sysfs_get_host_no_from_sid(sid
, &err
);
2292 log_error("Could not get hostno for session %d\n", sid
);
2293 err
= MGMT_IPC_ERR_NOT_FOUND
;
2294 goto destroy_session
;
2297 session
->r_stage
= R_STAGE_SESSION_REOPEN
;
2299 err
= sync_conn(session
, 0);
2302 err
= MGMT_IPC_ERR_NOMEM
;
2304 err
= MGMT_IPC_ERR_INVAL
;
2305 goto destroy_session
;
2308 session
->sync_qtask
= qtask
;
2309 qtask
->rsp
.command
= MGMT_IPC_SESSION_SYNC
;
2311 session_conn_reopen(&session
->conn
[0], qtask
, STOP_CONN_RECOVER
);
2312 log_debug(3, "Started sync iSCSI session %d", session
->id
);
2316 __session_destroy(session
);
2317 log_error("Could not sync session%d err %d\n", sid
, err
);
2321 static int session_unbind(struct iscsi_session
*session
)
2325 err
= ipc
->unbind_session(session
->t
->handle
, session
->id
);
2327 /* older kernels did not support unbind */
2328 log_debug(2, "Could not unbind session %d.\n", err
);
2333 session_logout_task(int sid
, queue_task_t
*qtask
)
2335 iscsi_session_t
*session
;
2337 mgmt_ipc_err_e rc
= MGMT_IPC_OK
;
2339 session
= session_find_by_sid(sid
);
2341 log_debug(1, "session sid %d not found.\n", sid
);
2342 return MGMT_IPC_ERR_NOT_FOUND
;
2344 conn
= &session
->conn
[0];
2346 * If syncing up or if this is the initial login and mgmt_ipc
2347 * has not been notified of that result fail the logout request
2349 if (session
->sync_qtask
||
2350 ((conn
->state
== STATE_XPT_WAIT
||
2351 conn
->state
== STATE_IN_LOGIN
) &&
2352 (session
->r_stage
== R_STAGE_NO_CHANGE
||
2353 session
->r_stage
== R_STAGE_SESSION_REDIRECT
))) {
2355 log_error("session in invalid state for logout. "
2356 "Try again later\n");
2357 return MGMT_IPC_ERR_INTERNAL
;
2360 /* FIXME: logout all active connections */
2361 conn
= &session
->conn
[0];
2362 /* FIXME: implement Logout Request */
2363 if (conn
->logout_qtask
)
2367 qtask
->rsp
.command
= MGMT_IPC_SESSION_LOGOUT
;
2368 conn
->logout_qtask
= qtask
;
2370 switch (conn
->state
) {
2371 case STATE_LOGGED_IN
:
2372 if (!session_unbind(session
))
2375 /* unbind is not supported so just do old logout */
2376 if (!iscsi_send_logout(conn
))
2378 log_error("Could not send logout pdu. Dropping session\n");
2381 rc
= session_conn_shutdown(conn
, qtask
, MGMT_IPC_OK
);
2389 iscsi_host_send_targets(queue_task_t
*qtask
, int host_no
, int do_login
,
2390 struct sockaddr_storage
*ss
)
2392 struct iscsi_transport
*t
;
2394 t
= iscsi_sysfs_get_transport_by_hba(host_no
);
2395 if (!t
|| set_transport_template(t
)) {
2396 log_error("Invalid host no %d for sendtargets\n", host_no
);
2397 return MGMT_IPC_ERR_TRANS_FAILURE
;
2399 if (!(t
->caps
& CAP_SENDTARGETS_OFFLOAD
))
2400 return MGMT_IPC_ERR_TRANS_CAPS
;
2402 if (ipc
->sendtargets(t
->handle
, host_no
, (struct sockaddr
*)ss
))
2403 return MGMT_IPC_ERR
;
2409 * HW drivers like qla4xxx present a interface that hides most of the iscsi
2410 * details. Userspace sends down a discovery event then it gets notified
2411 * if the sessions that were logged in as a result asynchronously, or
2412 * the card will have sessions preset in the FLASH and will log into them
2413 * automaotically then send us notification that a session is setup.
2415 void iscsi_async_session_creation(uint32_t host_no
, uint32_t sid
)
2417 struct iscsi_transport
*transport
;
2419 transport
= iscsi_sysfs_get_transport_by_hba(host_no
);
2423 if (!(transport
->caps
& CAP_FW_DB
))
2426 log_debug(3, "session created sid %u host no %d", sid
, host_no
);
2427 session_online_devs(host_no
, sid
);
2428 session_scan_host(NULL
, host_no
, NULL
);
2431 void iscsi_async_session_destruction(uint32_t host_no
, uint32_t sid
)
2433 log_debug(3, "session destroyed sid %u host no %d", sid
, host_no
);