summaryrefslogtreecommitdiff
path: root/usr/initiator.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2007-08-27 19:41:23 -0500
committerMike Christie <michaelc@cs.wisc.edu>2007-08-27 19:41:23 -0500
commit8ec5a9b9e5be619b7d93bf0ebc5fd9f15476c900 (patch)
tree3a31666c4f9c266d9c979ca5e56295275d35315e /usr/initiator.c
parentf084aefd18f5f4b14d62daaa191dda2374677813 (diff)
downloadopen-iscsi-8ec5a9b9e5be619b7d93bf0ebc5fd9f15476c900.tar.gz
mv initial_login_retry_max to initiator.c
we put initial_login_retry_max in iscsiadm as a temp hack. This moves it to is perm home ini initiator.c.
Diffstat (limited to 'usr/initiator.c')
-rw-r--r--usr/initiator.c295
1 files changed, 151 insertions, 144 deletions
diff --git a/usr/initiator.c b/usr/initiator.c
index 02e5459..8ef825b 100644
--- a/usr/initiator.c
+++ b/usr/initiator.c
@@ -492,6 +492,7 @@ __session_create(node_rec_t *rec, struct iscsi_transport *t)
session->ctrl_fd = control_fd;
session->t = t;
session->reopen_qtask.mgmt_ipc_fd = -1;
+ session->id = -1;
/* save node record. we might need it for redirection */
memcpy(&session->nrec, rec, sizeof(node_rec_t));
@@ -651,14 +652,49 @@ queue_delayed_reopen(queue_task_t *qtask, int delay)
iscsi_login_timedout, qtask);
}
+static int iscsi_conn_connect(struct iscsi_conn *conn, queue_task_t *qtask)
+{
+ struct iscsi_conn_context *conn_context;
+ int rc;
+
+ conn_context = iscsi_conn_context_get(conn, 0);
+ if (!conn_context) {
+ /* while reopening the recv pool should be full */
+ log_error("BUG: __session_conn_reopen could not get conn "
+ "context for recv.");
+ return ENOMEM;
+ }
+ conn_context->data = qtask;
+
+ rc = conn->session->t->template->ep_connect(conn, 1);
+ if (rc < 0 && errno != EINPROGRESS) {
+ char serv[NI_MAXSERV];
+
+ getnameinfo((struct sockaddr *) &conn->saddr,
+ sizeof(conn->saddr),
+ conn->host, sizeof(conn->host), serv, sizeof(serv),
+ NI_NUMERICHOST|NI_NUMERICSERV);
+
+ log_error("cannot make a connection to %s:%s (%d)",
+ conn->host, serv, errno);
+ iscsi_conn_context_put(conn_context);
+ return ENOTCONN;
+ }
+
+ iscsi_sched_conn_context(conn_context, conn, 0, EV_CONN_POLL);
+ log_debug(3, "Setting login timer %p timeout %d", &conn->login_timer,
+ conn->login_timeout);
+ actor_timer(&conn->login_timer, conn->login_timeout * 1000,
+ iscsi_login_timedout, qtask);
+ return 0;
+}
+
static void
__session_conn_reopen(iscsi_conn_t *conn, queue_task_t *qtask, int do_stop,
int redirected)
{
iscsi_session_t *session = conn->session;
- struct iscsi_conn_context *conn_context;
uint32_t delay;
- int rc;
log_debug(1, "re-opening session %d (reopen_cnt %d)", session->id,
session->reopen_cnt);
@@ -691,38 +727,14 @@ __session_conn_reopen(iscsi_conn_t *conn, queue_task_t *qtask, int do_stop,
goto queue_reopen;
}
- conn_context = iscsi_conn_context_get(conn, 0);
- if (!conn_context) {
- /* while reopening the recv pool should be full */
- log_error("BUG: __session_conn_reopen could not get conn "
- "context for recv.");
- delay = ISCSI_INTERNAL_ERR_REOPEN_DELAY;
- goto queue_reopen;
- }
- conn_context->data = qtask;
-
- rc = conn->session->t->template->ep_connect(conn, 1);
- if (rc < 0 && errno != EINPROGRESS) {
- char serv[NI_MAXSERV];
-
- getnameinfo((struct sockaddr *) &conn->saddr,
- sizeof(conn->saddr),
- conn->host, sizeof(conn->host), serv, sizeof(serv),
- NI_NUMERICHOST|NI_NUMERICSERV);
+ if (!redirected)
+ session->reopen_cnt++;
- log_error("cannot make a connection to %s:%s (%d)",
- conn->host, serv, errno);
+ if (iscsi_conn_connect(conn, qtask)) {
delay = ISCSI_CONN_ERR_REOPEN_DELAY;
- iscsi_conn_context_put(conn_context);
goto queue_reopen;
}
-
- iscsi_sched_conn_context(conn_context, conn, 0, EV_CONN_POLL);
- log_debug(3, "Setting login timer %p timeout %d", &conn->login_timer,
- conn->login_timeout);
- actor_timer(&conn->login_timer, conn->login_timeout * 1000,
- iscsi_login_timedout, qtask);
- return;
+ return;
queue_reopen:
log_debug(4, "Waiting %u seconds before trying to reconnect.\n", delay);
@@ -732,9 +744,6 @@ queue_reopen:
static void
session_conn_reopen(iscsi_conn_t *conn, queue_task_t *qtask, int do_stop)
{
- iscsi_session_t *session = conn->session;
-
- session->reopen_cnt++;
/*
* If we were temporarily redirected, we need to fall back to
* the original address to see where the target will send us
@@ -746,6 +755,111 @@ session_conn_reopen(iscsi_conn_t *conn, queue_task_t *qtask, int do_stop)
__session_conn_reopen(conn, qtask, do_stop, 0);
}
+static void iscsi_login_eh(struct iscsi_conn *conn, struct queue_task *qtask,
+ mgmt_ipc_err_e err)
+{
+ struct iscsi_session *session = conn->session;
+ int initial_login_retry_max;
+
+ initial_login_retry_max = session->nrec.session.initial_login_retry_max;
+ log_debug(3, "iscsi_login_eh");
+ /*
+ * Flush polls and other events
+ */
+ iscsi_flush_context_pool(conn->session);
+
+ switch (conn->state) {
+ case STATE_XPT_WAIT:
+ switch (session->r_stage) {
+ case R_STAGE_NO_CHANGE:
+ session->t->template->ep_disconnect(conn);
+ log_debug(6, "login failed STATE_XPT_WAIT/"
+ "R_STAGE_NO_CHANGE (%d/%d)",
+ session->reopen_cnt,
+ initial_login_retry_max);
+ /* timeout during initial connect.
+ * clean connection. write ipc rsp or retry */
+ if (initial_login_retry_max < session->reopen_cnt + 1)
+ session_conn_cleanup(qtask, err);
+ else {
+ session->reopen_cnt++;
+ if (iscsi_conn_connect(conn, qtask))
+ queue_delayed_reopen(qtask,
+ ISCSI_CONN_ERR_REOPEN_DELAY);
+ }
+ break;
+ case R_STAGE_SESSION_REDIRECT:
+ log_debug(6, "login failed STATE_XPT_WAIT/"
+ "R_STAGE_SESSION_REDIRECT (%d/%d)",
+ session->reopen_cnt,
+ initial_login_retry_max);
+ /* timeout during initial redirect connect
+ * clean connection. write ipc rsp or retry */
+ if (initial_login_retry_max < session->reopen_cnt + 1)
+ __session_conn_shutdown(conn, qtask, err);
+ else
+ session_conn_reopen(conn, qtask, 0);
+ break;
+ case R_STAGE_SESSION_REOPEN:
+ log_debug(6, "login failed STATE_XPT_WAIT/"
+ "R_STAGE_SESSION_REOPEN %d",
+ session->reopen_cnt);
+ /* timeout during reopen connect. try again */
+ session_conn_reopen(conn, qtask, 0);
+ break;
+ case R_STAGE_SESSION_CLEANUP:
+ __session_conn_shutdown(conn, qtask, err);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ case STATE_IN_LOGIN:
+ switch (session->r_stage) {
+ case R_STAGE_NO_CHANGE:
+ case R_STAGE_SESSION_REDIRECT:
+ log_debug(6, "login failed STATE_IN_LOGIN/"
+ "R_STAGE_NO_CHANGE %d",
+ session->reopen_cnt);
+ /*
+ * send pdu timeout during initial connect or
+ * initial redirected connect. Clean connection
+ * and write rsp or retry.
+ */
+ if (initial_login_retry_max < session->reopen_cnt + 1)
+ session_conn_shutdown(conn, qtask, err);
+ else
+ session_conn_reopen(conn, qtask,
+ STOP_CONN_RECOVER);
+ break;
+ case R_STAGE_SESSION_REOPEN:
+ log_debug(6, "login failed STATE_IN_LOGIN/"
+ "R_STAGE_SESSION_REOPEN %d",
+ session->reopen_cnt);
+ /*
+ * If we get a retryable error during the initial
+ * login then we will hit this path and
+ * initial_login_retry_max is ignored.
+ */
+ session_conn_reopen(conn, qtask, STOP_CONN_RECOVER);
+ break;
+ case R_STAGE_SESSION_CLEANUP:
+ session_conn_shutdown(conn, qtask,
+ MGMT_IPC_ERR_PDU_TIMEOUT);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ default:
+ log_error("Ignoring login error %d in conn state %d.\n",
+ err, conn->state);
+ break;
+ }
+}
+
static void
__conn_error_handle(iscsi_session_t *session, iscsi_conn_t *conn)
{
@@ -794,11 +908,9 @@ __conn_error_handle(iscsi_session_t *session, iscsi_conn_t *conn)
qtask = session->sync_qtask;
else
qtask = &session->reopen_qtask;
-
- session_conn_reopen(conn, qtask, STOP_CONN_RECOVER);
+ iscsi_login_eh(conn, qtask, STOP_CONN_RECOVER);
return;
}
-
log_debug(1, "ignoring conn error in login. "
"let it timeout");
return;
@@ -836,79 +948,6 @@ static void session_conn_error(void *data)
__conn_error_handle(session, conn);
}
-static void iscsi_login_eh(struct iscsi_conn *conn, struct queue_task *qtask,
- mgmt_ipc_err_e err)
-{
- struct iscsi_session *session = conn->session;
-
- log_debug(3, "iscsi_login_eh");
- /*
- * Flush polls and other events
- */
- iscsi_flush_context_pool(conn->session);
-
- switch (conn->state) {
- case STATE_XPT_WAIT:
- switch (session->r_stage) {
- case R_STAGE_NO_CHANGE:
- session->t->template->ep_disconnect(conn);
- log_debug(6, "conn_timer popped at XPT_WAIT: login");
- /* timeout during initial connect.
- * clean connection. write ipc rsp */
- session_conn_cleanup(qtask, err);
- break;
- case R_STAGE_SESSION_REDIRECT:
- log_debug(6, "conn_timer popped at XPT_WAIT: "
- "login redirect");
- /* timeout during initial redirect connect
- * clean connection. write ipc rsp */
- __session_conn_shutdown(conn, qtask, err);
- break;
- case R_STAGE_SESSION_REOPEN:
- log_debug(6, "conn_timer popped at XPT_WAIT: reopen");
- /* timeout during reopen connect. try again */
- session_conn_reopen(conn, qtask, 0);
- break;
- case R_STAGE_SESSION_CLEANUP:
- __session_conn_shutdown(conn, qtask, err);
- break;
- default:
- break;
- }
-
- break;
- case STATE_IN_LOGIN:
- switch (session->r_stage) {
- case R_STAGE_NO_CHANGE:
- case R_STAGE_SESSION_REDIRECT:
- log_debug(6, "conn_timer popped at IN_LOGIN: cleanup");
- /*
- * send pdu timeout during initial connect or
- * initial redirected connect. Clean connection
- * and write rsp.
- */
- session_conn_shutdown(conn, qtask, err);
- break;
- case R_STAGE_SESSION_REOPEN:
- log_debug(6, "conn_timer popped at IN_LOGIN: reopen");
- session_conn_reopen(conn, qtask, STOP_CONN_RECOVER);
- break;
- case R_STAGE_SESSION_CLEANUP:
- session_conn_shutdown(conn, qtask,
- MGMT_IPC_ERR_PDU_TIMEOUT);
- break;
- default:
- break;
- }
-
- break;
- default:
- log_error("Ignoring login error %d in conn state %d.\n",
- err, conn->state);
- break;
- }
-}
-
static void iscsi_login_timedout(void *data)
{
struct queue_task *qtask = data;
@@ -1387,9 +1426,6 @@ setup_full_feature_phase(iscsi_conn_t *conn)
retry:
session->r_stage = R_STAGE_SESSION_REOPEN;
- session_conn_reopen(conn, c->qtask, STOP_CONN_RECOVER);
- return;
-
failed:
iscsi_login_eh(conn, c->qtask, MGMT_IPC_ERR_LOGIN_FAILURE);
return;
@@ -1665,7 +1701,7 @@ static void session_conn_poll(void *data)
memset(c, 0, sizeof(iscsi_login_context_t));
/* do not allocate new connection in case of reopen */
- if (session->r_stage == R_STAGE_NO_CHANGE) {
+ if (session->id == -1) {
if (conn->id == 0 &&
ipc->create_session(session->t->handle,
session->nrec.session.initial_cmdsn,
@@ -1834,11 +1870,9 @@ int session_is_running(node_rec_t *rec)
int
session_login_task(node_rec_t *rec, queue_task_t *qtask)
{
- int rc;
iscsi_session_t *session;
iscsi_conn_t *conn;
struct iscsi_transport *t;
- struct iscsi_conn_context *conn_context;
t = get_transport_by_name(rec->iface.transport_name);
if (!t)
@@ -1905,41 +1939,14 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask)
conn = &session->conn[0];
qtask->conn = conn;
- conn_context = iscsi_conn_context_get(conn, 0);
- if (!conn_context) {
- /* while logging the recv pool should be full */
- log_error("BUG: session_login_task could not get conn "
- "context for poll.");
- __session_destroy(session);
- return MGMT_IPC_ERR_INTERNAL;
- }
- conn_context->data = qtask;
-
- rc = session->t->template->ep_connect(conn, 1);
- if (rc < 0 && errno != EINPROGRESS) {
- char serv[NI_MAXSERV];
-
- getnameinfo((struct sockaddr *) &conn->saddr,
- sizeof(conn->saddr),
- conn->host, sizeof(conn->host), serv, sizeof(serv),
- NI_NUMERICHOST|NI_NUMERICSERV);
-
- log_error("cannot make a connection to %s:%s (%d)",
- conn->host, serv, errno);
+ conn->state = STATE_XPT_WAIT;
+ if (iscsi_conn_connect(conn, qtask)) {
__session_destroy(session);
return MGMT_IPC_ERR_TRANS_FAILURE;
}
- conn->state = STATE_XPT_WAIT;
-
- iscsi_sched_conn_context(conn_context, conn, 0, EV_CONN_POLL);
- log_debug(3, "Setting login timer %p timeout %d", &conn->login_timer,
- conn->login_timeout);
- actor_timer(&conn->login_timer, conn->login_timeout * 1000,
- iscsi_login_timedout, qtask);
qtask->rsp.command = MGMT_IPC_SESSION_LOGIN;
qtask->rsp.err = MGMT_IPC_OK;
-
return MGMT_IPC_OK;
}