From 0c3ef3ed5f2e0b7010827bd274551e3278e0c8fb Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 11 Feb 2011 10:18:31 +0100 Subject: [PATCH 3/6] iscsid: sync uIP and iscsid on startup iscsid and brcm_iscsi_uio need to synchronize at startup so that iscsid can use the correct network settings. References: bnc#608442 Signed-off-by: Benjamin Li Signed-off-by: Hannes Reinecke --- usr/initiator.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++- usr/initiator.h | 1 + usr/uip_mgmt_ipc.h | 8 ++- usr/util.c | 22 ++++++++-- 4 files changed, 126 insertions(+), 11 deletions(-) diff --git a/usr/initiator.c b/usr/initiator.c index 4a4e4ba..9f9f970 100644 --- a/usr/initiator.c +++ b/usr/initiator.c @@ -1076,6 +1076,20 @@ static void iscsi_login_timedout(void *data) } } +static void iscsi_uio_poll_login_timedout(void *data) +{ + struct queue_task *qtask = data; + struct iscsi_conn *conn = qtask->conn; + + log_debug(3, "timeout waiting for UIO ...\n"); + /* + * Flush polls and other events + */ + iscsi_flush_context_pool(conn->session); + + session_conn_shutdown(conn, qtask, MGMT_IPC_ERR_TRANS_TIMEOUT); +} + static void iscsi_login_redirect(iscsi_conn_t *conn) { iscsi_session_t *session = conn->session; @@ -2025,6 +2039,50 @@ cleanup: session_conn_shutdown(conn, qtask, err); } +static void session_conn_uio_poll(void *data) +{ + struct iscsi_conn_context *conn_context = data; + iscsi_conn_t *conn = conn_context->conn; + struct iscsi_session *session = conn->session; + queue_task_t *qtask = conn_context->data; + int rc; + + log_debug(4, "retrying uio poll"); + rc = __set_net_config(session->t, session, &conn->session->nrec.iface); + if (rc != 0) { + if (rc == -EAGAIN) { + conn_context->data = qtask; + iscsi_sched_conn_context(conn_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, MGMT_IPC_ERR_INTERNAL); + iscsi_conn_context_put(conn_context); + return; + } + } + + 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 = 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); + } +} + + void iscsi_sched_conn_context(struct iscsi_conn_context *conn_context, struct iscsi_conn *conn, unsigned long tmo, int event) @@ -2061,6 +2119,11 @@ void iscsi_sched_conn_context(struct iscsi_conn_context *conn_context, conn_context); actor_schedule(&conn_context->actor); break; + case EV_UIO_POLL: + actor_new(&conn_context->actor, session_conn_uio_poll, + conn_context); + actor_schedule(&conn_context->actor); + break; case EV_CONN_LOGOUT_TIMER: actor_timer(&conn_context->actor, tmo * 1000, iscsi_logout_timedout, conn_context); @@ -2175,6 +2238,7 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask) iscsi_session_t *session; iscsi_conn_t *conn; struct iscsi_transport *t; + int rc; if (session_is_running(rec)) { log_error("session [%s,%s,%d] already running.", rec->name, @@ -2251,9 +2315,45 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask) conn = &session->conn[0]; qtask->conn = conn; - if (iface_set_param(t, &rec->iface, session)) { - __session_destroy(session); - return MGMT_IPC_ERR_LOGIN_FAILURE; + rc = iface_set_param(t, &rec->iface, session); + if (t->template->set_net_config) { + /* Ensure that the net config setting was taken */ + if ( rc == -EAGAIN ) { + struct iscsi_conn_context *conn_context; + + 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; + conn->state = STATE_XPT_WAIT; + + iscsi_sched_conn_context(conn_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); + + qtask->rsp.command = MGMT_IPC_SESSION_LOGIN; + qtask->rsp.err = MGMT_IPC_OK; + + return MGMT_IPC_OK; + } else if (rc) { + __session_destroy(session); + return MGMT_IPC_ERR_LOGIN_FAILURE; + } + } else { + if (rc) { + __session_destroy(session); + return MGMT_IPC_ERR_LOGIN_FAILURE; + } } conn->state = STATE_XPT_WAIT; diff --git a/usr/initiator.h b/usr/initiator.h index a6ebd24..4052d4e 100644 --- a/usr/initiator.h +++ b/usr/initiator.h @@ -90,6 +90,7 @@ typedef enum iscsi_event_e { EV_CONN_ERROR, EV_CONN_LOGOUT_TIMER, EV_CONN_STOP, + EV_UIO_POLL, } iscsi_event_e; struct queue_task; diff --git a/usr/uip_mgmt_ipc.h b/usr/uip_mgmt_ipc.h index dd49c0b..63dfc4d 100644 --- a/usr/uip_mgmt_ipc.h +++ b/usr/uip_mgmt_ipc.h @@ -52,9 +52,11 @@ typedef struct iscsid_uip_broadcast { typedef enum iscsid_uip_mgmt_ipc_err { ISCSID_UIP_MGMT_IPC_OK = 0, - ISCISD_UIP_MGMT_IPC_ERR = 1, - ISCISD_UIP_MGMT_IPC_ERR_NOT_FOUND = 2, - ISCISD_UIP_MGMT_IPC_ERR_NOMEM = 3, + ISCISD_UIP_MGMT_IPC_ERR = 1, + ISCISD_UIP_MGMT_IPC_ERR_NOT_FOUND = 2, + ISCISD_UIP_MGMT_IPC_ERR_NOMEM = 3, + ISCISD_UIP_MGMT_IPC_DEVICE_UP = 4, + ISCISD_UIP_MGMT_IPC_DEVICE_INITIALIZING = 5, } iscsid_uip_mgmt_ipc_err_e; /* IPC Response */ diff --git a/usr/util.c b/usr/util.c index 390c895..f22f52d 100644 --- a/usr/util.c +++ b/usr/util.c @@ -398,6 +398,8 @@ int uip_broadcast(void *buf, size_t buf_len) return err; } + log_debug(3, "connected to uIP daemon"); + /* Send the data to uIP */ if ((err = write(fd, buf, buf_len)) != buf_len) { log_error("got write error (%d/%d), daemon died?", @@ -406,6 +408,8 @@ int uip_broadcast(void *buf, size_t buf_len) return -EIO; } + log_debug(3, "send iface config to uIP daemon"); + /* Set the socket to a non-blocking read, this way if there are * problems waiting for uIP, iscsid can bailout early */ flags = fcntl(fd, F_GETFL, 0); @@ -424,8 +428,10 @@ int uip_broadcast(void *buf, size_t buf_len) /* Wait for the response */ err = read(fd, &rsp, sizeof(rsp)); if (err == sizeof(rsp)) { - log_debug(3, "Broadcasted to uIP with length: %ld\n", - buf_len); + log_debug(3, "Broadcasted to uIP with length: %ld " + "cmd: 0x%x rsp: 0x%x\n", buf_len, + rsp.command, rsp.err); + err = 0; break; } else if((err == -1) && (errno == EAGAIN)) { usleep(250000); @@ -437,12 +443,18 @@ int uip_broadcast(void *buf, size_t buf_len) } } - if(count == MAX_UIP_BROADCAST_READ_TRIES) - log_error("Could not broadcast to uIP"); + if (count == MAX_UIP_BROADCAST_READ_TRIES) { + log_error("Could not broadcast to uIP after %d tries", + count); + err = -EAGAIN; + } else if (rsp.err != ISCISD_UIP_MGMT_IPC_DEVICE_UP) { + log_debug(3, "Device is not ready\n"); + err = -EAGAIN; + } close(fd); - return 0; + return err; } void idbm_node_setup_defaults(node_rec_t *rec) -- 1.7.3.4