From c0e509e7535372cd5d655bc5a20d3d2bae45df84 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 7 May 2014 14:38:13 -0500 Subject: [PATCH] iscsid: retry login for ISCSI_ERR_HOST_NOT_FOUND If a driver is being loaded then the scsi_host might not yet be added. This has iscsid retry login if the host is not yet in sysfs. --- usr/initiator.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 100 insertions(+), 11 deletions(-) diff --git a/usr/initiator.c b/usr/initiator.c index 05a5b19..b4b8957 100644 --- a/usr/initiator.c +++ b/usr/initiator.c @@ -55,10 +55,19 @@ #define PROC_DIR "/proc" +struct login_task_retry_info { + actor_t retry_actor; + queue_task_t *qtask; + node_rec_t *rec; + int retry_count; +}; + static void iscsi_login_timedout(void *data); static int iscsi_sched_ev_context(struct iscsi_ev_context *ev_context, struct iscsi_conn *conn, unsigned long tmo, int event); +static int queue_session_login_task_retry(struct login_task_retry_info *info, + node_rec_t *rec, queue_task_t *qtask); static int iscsi_ev_context_alloc(iscsi_conn_t *conn) { @@ -324,14 +333,17 @@ session_release(iscsi_session_t *session) } static iscsi_session_t* -__session_create(node_rec_t *rec, struct iscsi_transport *t) +__session_create(node_rec_t *rec, struct iscsi_transport *t, int *rc) { iscsi_session_t *session; - int hostno, rc = 0; + int hostno; + + *rc = 0; session = calloc(1, sizeof (*session)); if (session == NULL) { log_debug(1, "can not allocate memory for session"); + *rc = ISCSI_ERR_NOMEM; return NULL; } log_debug(2, "Allocted session %p", session); @@ -356,8 +368,8 @@ __session_create(node_rec_t *rec, struct iscsi_transport *t) session->initiator_name = dconfig->initiator_name; else { log_error("No initiator name set. Cannot create session."); - free(session); - return NULL; + *rc = ISCSI_ERR_INVAL; + goto free_session; } if (strlen(session->nrec.iface.alias)) @@ -386,8 +398,8 @@ __session_create(node_rec_t *rec, struct iscsi_transport *t) iscsi_session_init_params(session); - hostno = iscsi_sysfs_get_host_no_from_hwinfo(&rec->iface, &rc); - if (!rc) { + hostno = iscsi_sysfs_get_host_no_from_hwinfo(&rec->iface, rc); + if (!*rc) { /* * if the netdev or mac was set, then we are going to want * to want to bind the all the conns/eps to a specific host @@ -395,10 +407,18 @@ __session_create(node_rec_t *rec, struct iscsi_transport *t) */ session->conn[0].bind_ep = 1; session->hostno = hostno; + } else if (*rc == ISCSI_ERR_HOST_NOT_FOUND) { + goto free_session; + } else { + *rc = 0; } list_add_tail(&session->list, &t->sessions); return session; + +free_session: + free(session); + return NULL; } static void iscsi_flush_context_pool(struct iscsi_session *session) @@ -1862,8 +1882,7 @@ static int session_is_running(node_rec_t *rec) return 0; } -int -session_login_task(node_rec_t *rec, queue_task_t *qtask) +static int __session_login_task(node_rec_t *rec, queue_task_t *qtask) { iscsi_session_t *session; iscsi_conn_t *conn; @@ -1930,8 +1949,10 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask) rec->conn[0].iscsi.OFMarker = 0; } - session = __session_create(rec, t); - if (!session) + session = __session_create(rec, t, &rc); + if (rc == ISCSI_ERR_HOST_NOT_FOUND) + return rc; + else if (!session) return ISCSI_ERR_LOGIN; /* FIXME: login all connections! marked as "automatic" */ @@ -1979,6 +2000,74 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask) return ISCSI_SUCCESS; } +int +session_login_task(node_rec_t *rec, queue_task_t *qtask) +{ + int rc; + + rc = __session_login_task(rec, qtask); + if (rc == ISCSI_ERR_HOST_NOT_FOUND) { + rc = queue_session_login_task_retry(NULL, rec, qtask); + if (rc) + return rc; + /* + * we are going to internally retry. Will return final rc + * when completed + */ + return ISCSI_SUCCESS; + } + return rc; +} + +static void session_login_task_retry(void *data) +{ + struct login_task_retry_info *info = data; + int rc; + + rc = __session_login_task(info->rec, info->qtask); + if (rc == ISCSI_ERR_HOST_NOT_FOUND) { + if (info->retry_count == 5) { + /* give up */ + goto write_rsp; + } + + rc = queue_session_login_task_retry(info, info->rec, + info->qtask); + if (rc) + goto write_rsp; + /* we are going to internally retry */ + return; + } else if (rc) { + /* hard error - no retry */ + goto write_rsp; + } else + /* successfully started login operation */ + goto free; +write_rsp: + mgmt_ipc_write_rsp(info->qtask, rc); +free: + free(info); +} + +static int queue_session_login_task_retry(struct login_task_retry_info *info, + node_rec_t *rec, queue_task_t *qtask) +{ + if (!info) { + info = malloc(sizeof(*info)); + if (!info) + return ISCSI_ERR_NOMEM; + memset(info, 0, sizeof(*info)); + info->qtask = qtask; + info->rec = rec; + } + + info->retry_count++; + log_debug(4, "queue session setup attempt in %d secs, retries %d\n", + 3, info->retry_count); + actor_timer(&info->retry_actor, 3000, session_login_task_retry, info); + return 0; +} + static int sync_conn(iscsi_session_t *session, uint32_t cid) { @@ -2006,7 +2095,7 @@ iscsi_sync_session(node_rec_t *rec, queue_task_t *qtask, uint32_t sid) if (!t) return ISCSI_ERR_TRANS_NOT_FOUND; - session = __session_create(rec, t); + session = __session_create(rec, t, &err); if (!session) return ISCSI_ERR_LOGIN; -- 1.9.3