Hey Roi, Vikas and Eddie, The attached patch fixes the issue Roi reported where the login_timer was not deleted and so we end up with a infinite loop. Roi, could you test your failure case?
Vikas and Eddie, I ccd you guys because it modifies the bnx2i iscsiuio code. There was a issue where iscsiuio was not ready (or the host was not yet ready) and so iscsid would poll iscsiuio for a second or two and it would use the login_timer as a watchdog. A couple weeks ago we hit a issue with be2iscsi where the host was not ready to go so iscsid got code to poll the iscsi/scsi_host. So this patch removes the iscsiuio login_timer use and then also has it use this new common setup polling. I have tested software iscsi. -- You received this message because you are subscribed to the Google Groups "open-iscsi" group. To unsubscribe from this group and stop receiving emails from it, send an email to open-iscsi+unsubscr...@googlegroups.com. To post to this group, send email to open-iscsi@googlegroups.com. Visit this group at http://groups.google.com/group/open-iscsi. For more options, visit https://groups.google.com/d/optout.
diff --git a/usr/actor.c b/usr/actor.c index b8f8e61..381328c 100644 --- a/usr/actor.c +++ b/usr/actor.c @@ -187,16 +187,12 @@ actor_timer(actor_t *thread, uint32_t timeout, void (*callback)(void *), actor_schedule_private(thread, timeout, 0); } -int +void actor_timer_mod(actor_t *thread, uint32_t timeout, void *data) { - if (thread->state == ACTOR_WAITING) { - list_del_init(&thread->list); - thread->data = data; - actor_schedule_private(thread, timeout, 0); - return 1; - } - return 0; + actor_delete(thread); + thread->data = data; + actor_schedule_private(thread, timeout, 0); } void diff --git a/usr/actor.h b/usr/actor.h index 704224d..ad49b49 100644 --- a/usr/actor.h +++ b/usr/actor.h @@ -48,7 +48,7 @@ extern void actor_schedule_head(actor_t *thread); extern void actor_schedule(actor_t *thread); extern void actor_timer(actor_t *thread, uint32_t timeout, void (*callback)(void *), void *data); -extern int actor_timer_mod(actor_t *thread, uint32_t new_timeout, void *data); +extern void actor_timer_mod(actor_t *thread, uint32_t new_timeout, void *data); extern void actor_poll(void); extern void actor_init(void); diff --git a/usr/initiator.c b/usr/initiator.c index b4b8957..4a94254 100644 --- a/usr/initiator.c +++ b/usr/initiator.c @@ -262,6 +262,7 @@ __session_conn_create(iscsi_session_t *session, int cid) conn->state = ISCSI_CONN_STATE_FREE; conn->session = session; + actor_new(&conn->login_timer, iscsi_login_timedout, NULL); /* * TODO: we must export the socket_fd/transport_eph from sysfs * so if iscsid is resyncing up we can pick that up and cleanup up @@ -526,9 +527,7 @@ queue_delayed_reopen(queue_task_t *qtask, int delay) * iscsi_login_eh can handle the login resched as * if it were login time out */ - actor_delete(&conn->login_timer); - actor_timer(&conn->login_timer, delay * 1000, - iscsi_login_timedout, qtask); + actor_timer_mod(&conn->login_timer, delay * 1000, qtask); } static int iscsi_conn_connect(struct iscsi_conn *conn, queue_task_t *qtask) @@ -563,53 +562,10 @@ static int iscsi_conn_connect(struct iscsi_conn *conn, queue_task_t *qtask) iscsi_sched_ev_context(ev_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); + actor_timer_mod(&conn->login_timer, conn->login_timeout * 1000, qtask); return 0; } -static void iscsi_uio_poll_login_timedout(void *data) -{ - struct queue_task *qtask = data; - struct iscsi_conn *conn = qtask->conn; - iscsi_session_t *session = conn->session; - - log_debug(3, "timeout waiting for UIO ...\n"); - mgmt_ipc_write_rsp(qtask, ISCSI_ERR_TRANS_TIMEOUT); - conn_delete_timers(conn); - __session_destroy(session); -} - -static int iscsi_sched_uio_poll(queue_task_t *qtask) -{ - struct iscsi_conn *conn = qtask->conn; - struct iscsi_session *session = conn->session; - struct iscsi_transport *t = session->t; - struct iscsi_ev_context *ev_context; - - if (!t->template->set_net_config) - return 0; - - ev_context = iscsi_ev_context_get(conn, 0); - if (!ev_context) { - /* while reopening the recv pool should be full */ - log_error("BUG: __session_conn_reopen could " - "not get conn context for recv."); - return -ENOMEM; - } - - ev_context->data = qtask; - conn->state = ISCSI_CONN_STATE_XPT_WAIT; - - iscsi_sched_ev_context(ev_context, conn, 0, EV_UIO_POLL); - - log_debug(3, "Setting login UIO poll timer %p timeout %d", - &conn->login_timer, conn->login_timeout); - actor_timer(&conn->login_timer, conn->login_timeout * 1000, - iscsi_uio_poll_login_timedout, qtask); - return -EAGAIN; -} - static void __session_conn_reopen(iscsi_conn_t *conn, queue_task_t *qtask, int do_stop, int redirected) @@ -1738,53 +1694,6 @@ failed_login: } -static void session_conn_uio_poll(void *data) -{ - struct iscsi_ev_context *ev_context = data; - iscsi_conn_t *conn = ev_context->conn; - struct iscsi_session *session = conn->session; - queue_task_t *qtask = ev_context->data; - int rc; - - log_debug(4, "retrying uio poll"); - rc = iscsi_set_net_config(session->t, session, - &conn->session->nrec.iface); - if (rc != 0) { - if (rc == ISCSI_ERR_AGAIN) { - ev_context->data = qtask; - iscsi_sched_ev_context(ev_context, conn, 2, - EV_UIO_POLL); - return; - } else { - log_error("session_conn_uio_poll() " - "connection failure [0x%x]", rc); - actor_delete(&conn->login_timer); - iscsi_login_eh(conn, qtask, ISCSI_ERR_INTERNAL); - iscsi_ev_context_put(ev_context); - return; - } - } - - iscsi_ev_context_put(ev_context); - actor_delete(&conn->login_timer); - log_debug(4, "UIO ready trying connect"); - - /* uIP is ready try to connect */ - if (gettimeofday(&conn->initial_connect_time, NULL)) - log_error("Could not get initial connect time. If " - "login errors iscsid may give up the initial " - "login early. You should manually login."); - - conn->state = ISCSI_CONN_STATE_XPT_WAIT; - if (iscsi_conn_connect(conn, qtask)) { - int delay = ISCSI_CONN_ERR_REOPEN_DELAY; - - log_debug(4, "Waiting %u seconds before trying to reconnect.\n", - delay); - queue_delayed_reopen(qtask, delay); - } -} - static int iscsi_sched_ev_context(struct iscsi_ev_context *ev_context, struct iscsi_conn *conn, unsigned long tmo, int event) @@ -1826,11 +1735,6 @@ static int iscsi_sched_ev_context(struct iscsi_ev_context *ev_context, ev_context); actor_schedule(&ev_context->actor); break; - case EV_UIO_POLL: - actor_new(&ev_context->actor, session_conn_uio_poll, - ev_context); - actor_schedule(&ev_context->actor); - break; case EV_CONN_LOGOUT_TIMER: actor_timer(&ev_context->actor, tmo * 1000, iscsi_logout_timedout, ev_context); @@ -1968,14 +1872,12 @@ static int __session_login_task(node_rec_t *rec, queue_task_t *qtask) rc = iscsi_host_set_net_params(&rec->iface, session); if (rc == ISCSI_ERR_AGAIN) { - iscsi_sched_uio_poll(qtask); /* - * Cannot block iscsid, so caller is going to internally - * retry the operation. + * host/iscsiuio not ready. Cannot block iscsid, so caller is + * going to internally retry the operation. */ - qtask->rsp.command = MGMT_IPC_SESSION_LOGIN; - qtask->rsp.err = ISCSI_SUCCESS; - return ISCSI_SUCCESS; + __session_destroy(session); + return ISCSI_ERR_HOST_NOT_FOUND; } else if (rc) { __session_destroy(session); return ISCSI_ERR_LOGIN; diff --git a/usr/initiator.h b/usr/initiator.h index c34625b..c11d77f 100644 --- a/usr/initiator.h +++ b/usr/initiator.h @@ -83,7 +83,6 @@ typedef enum iscsi_event_e { EV_CONN_LOGOUT_TIMER, EV_CONN_STOP, EV_CONN_LOGIN, - EV_UIO_POLL, } iscsi_event_e; struct queue_task; diff --git a/usr/initiator_common.c b/usr/initiator_common.c index 50f8d41..4a1647e 100644 --- a/usr/initiator_common.c +++ b/usr/initiator_common.c @@ -687,7 +687,7 @@ int iscsi_host_set_net_params(struct iface_rec *iface, if (!iface_is_bound_by_ipaddr(iface)) { log_warning("Please set the iface.ipaddress for iface %s, " "then retry the login command.\n", iface->name); - return EINVAL; + return ISCSI_ERR_INVAL; } /* these type of drivers need the netdev upd */