On 03/09/2015 08:54 PM, Lee Duncan wrote: > Hi Mike: > > I am *finally* getting to this bug, previously buried under a mountain of > more pressing matters. > >> On Jan 12, 2015, at 12:50 PM, Mike Christie <micha...@cs.wisc.edu> wrote: >> >> Thanks. I merged and pushed these patches. >> >> When you get some time, reply to that mail I sent offlist about how long >> it is taking for the set host net params to succeed, so I can fix my >> login/init patch as needed. > > I have looked at this problem again, and I will reply in a new email > tomorrow. Fair warning. :)
:) Hey, Attached is the patch that was modifying iscsid's code path which from what I understand handled the same problem you were handling in the iscsiadm's discovery code path. The patch is removing the iscsiuio specific calls in iscsid and using the generic initial login/connect retry code. It is currently retrying for up to login_timeout seconds instead of the hard coded 5 seconds. -- 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.
>From 05abcf6947f32186e540a102b20cd7d768a29d08 Mon Sep 17 00:00:00 2001 From: Mike Christie <micha...@cs.wisc.edu> Date: Thu, 5 Feb 2015 02:11:16 -0600 Subject: [PATCH 1/1] iscsid: make sure actor is delated before rescheduling iscsi_conn_connect() be called from a login_timer that is not deleted. This causes it to be scheduled multiple times. This patch adds a new function actor_timer_mod to handle both deletion and rescheduling. This patch also then removed the uio poll code which was using the login_timer to schedule itself. This uio retry, is now just done in the generic initial login retry. --- usr/actor.c | 8 ++++ usr/actor.h | 3 +- usr/initiator.c | 122 +++++-------------------------------------------- usr/initiator.h | 1 - usr/initiator_common.c | 8 ++-- 5 files changed, 26 insertions(+), 116 deletions(-) diff --git a/usr/actor.c b/usr/actor.c index 37b5024..21cd819 100644 --- a/usr/actor.c +++ b/usr/actor.c @@ -182,6 +182,14 @@ actor_timer(actor_t *thread, uint32_t timeout_secs, void (*callback)(void *), actor_schedule_private(thread, timeout_secs, 0); } +void +actor_timer_mod(actor_t *thread, uint32_t new_timeout_secs, void *data) +{ + actor_delete(thread); + thread->data = data; + actor_schedule_private(thread, new_timeout_secs, 0); +} + /* * Execute all items that have expired. * diff --git a/usr/actor.h b/usr/actor.h index 7283dce..f572f2e 100644 --- a/usr/actor.h +++ b/usr/actor.h @@ -43,7 +43,8 @@ extern void actor_schedule_head(actor_t *thread); extern void actor_schedule(actor_t *thread); extern void actor_timer(actor_t *thread, uint32_t delay_secs, void (*callback)(void *), void *data); -extern int actor_timer_mod(actor_t *thread, uint32_t new_delay_secs, void *data); +extern void actor_timer_mod(actor_t *thread, uint32_t new_delay_secs, + void *data); extern void actor_poll(void); #endif /* ACTOR_H */ diff --git a/usr/initiator.c b/usr/initiator.c index 1aadc9b..f70db4d 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_init(&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 @@ -528,9 +529,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, - iscsi_login_timedout, qtask); + actor_timer_mod(&conn->login_timer, delay, qtask); } static int iscsi_conn_connect(struct iscsi_conn *conn, queue_task_t *qtask) @@ -565,53 +564,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, - iscsi_login_timedout, qtask); + actor_timer_mod(&conn->login_timer, conn->login_timeout, 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, - 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) @@ -1740,53 +1696,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) @@ -1825,12 +1734,7 @@ static int iscsi_sched_ev_context(struct iscsi_ev_context *ev_context, break; case EV_CONN_POLL: actor_init(&ev_context->actor, session_conn_poll, - ev_context); - actor_schedule(&ev_context->actor); - break; - case EV_UIO_POLL: - actor_init(&ev_context->actor, session_conn_uio_poll, - ev_context); + ev_context); actor_schedule(&ev_context->actor); break; case EV_CONN_LOGOUT_TIMER: @@ -1970,14 +1874,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; @@ -2024,17 +1926,17 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask) static void session_login_task_retry(void *data) { struct login_task_retry_info *info = data; + struct node_rec *rec = info->rec; int rc; - rc = __session_login_task(info->rec, info->qtask); + rc = __session_login_task(rec, info->qtask); if (rc == ISCSI_ERR_HOST_NOT_FOUND) { - if (info->retry_count == 5) { + if (info->retry_count == rec->conn[0].timeo.login_timeout) { /* give up */ goto write_rsp; } - rc = queue_session_login_task_retry(info, info->rec, - info->qtask); + rc = queue_session_login_task_retry(info, rec, info->qtask); if (rc) goto write_rsp; /* we are going to internally retry */ 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 eb03b23..98ca636 100644 --- a/usr/initiator_common.c +++ b/usr/initiator_common.c @@ -249,7 +249,7 @@ int iscsi_setup_portal(struct iscsi_conn *conn, char *address, int port) return 0; } -int host_set_param(struct iscsi_transport *t, +static int host_set_param(struct iscsi_transport *t, uint32_t host_no, int param, char *value, int type) { @@ -261,7 +261,7 @@ int host_set_param(struct iscsi_transport *t, log_error("can't set operational parameter %d for " "host %d, retcode %d (%d)", param, host_no, rc, errno); - return rc; + return ISCSI_ERR_INVAL; } return 0; } @@ -677,13 +677,13 @@ int iscsi_host_set_net_params(struct iface_rec *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; } else if (t->template->set_host_ip == SET_HOST_IP_OPT) { log_info("Optional iface.ipaddress for iface %s " "not set.\n", iface->name); return 0; } else { - return EINVAL; + return ISCSI_ERR_INVAL; } } -- 1.8.3.1