diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2011-01-29 22:50:43 -0600 |
---|---|---|
committer | Mike Christie <michaelc@cs.wisc.edu> | 2011-01-31 21:52:18 -0600 |
commit | 9dca10af955255f9806942cb3370d4a86660a655 (patch) | |
tree | 5fb8e7f4ada8989fec2c815de7044ea2b75a281a /usr/initiator.c | |
parent | 44cc856b2115e6cd1221fe061b08b23d3cf188c8 (diff) | |
download | open-iscsi-9dca10af955255f9806942cb3370d4a86660a655.tar.gz |
Use pass through interface for sendtargets (take4) Currenly offload cards like bnx2i, be2iscsi, cxgb3i must use a normal eth for discovery. This patch allows us to do discovery using the iscsi class passthrough interface.
Note1 that the dirver must set the CAP_TEXT_NEGO setting, which
might requires scsi-misc.
Limitations of patch:
- MaxRecvDataSegmentLength is limited to 8K for discovery sessions
when offload is used.
V3:
- bug fixes from Eddie Wai to call start conn after we have logged in.
Fixed set param not setting all settings.
Misc cleanups.
V4:
- fix iscsistart segfault due to missing initialization.
Diffstat (limited to 'usr/initiator.c')
-rw-r--r-- | usr/initiator.c | 759 |
1 files changed, 118 insertions, 641 deletions
diff --git a/usr/initiator.c b/usr/initiator.c index 70c873b..81e407f 100644 --- a/usr/initiator.c +++ b/usr/initiator.c @@ -53,31 +53,17 @@ #define PROC_DIR "/proc" 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); -/* - * calculate parameter's padding - */ -static unsigned int -__padding(unsigned int param) -{ - int pad; - - pad = param & 3; - if (pad) { - pad = 4 - pad; - log_debug(1, "parameter's value %d padded to %d bytes\n", - param, param + pad); - } - return param + pad; -} - -static int iscsi_conn_context_alloc(iscsi_conn_t *conn) +static int iscsi_ev_context_alloc(iscsi_conn_t *conn) { int i; for (i = 0; i < CONTEXT_POOL_MAX; i++) { conn->context_pool[i] = calloc(1, - sizeof(struct iscsi_conn_context) + + sizeof(struct iscsi_ev_context) + ipc->ctldev_bufmax); if (!conn->context_pool[i]) { int j; @@ -91,7 +77,7 @@ static int iscsi_conn_context_alloc(iscsi_conn_t *conn) return 0; } -static void iscsi_conn_context_free(iscsi_conn_t *conn) +static void iscsi_ev_context_free(iscsi_conn_t *conn) { int i; @@ -107,10 +93,10 @@ static void iscsi_conn_context_free(iscsi_conn_t *conn) } } -struct iscsi_conn_context *iscsi_conn_context_get(iscsi_conn_t *conn, - int ev_size) +static struct iscsi_ev_context * +iscsi_ev_context_get(iscsi_conn_t *conn, int ev_size) { - struct iscsi_conn_context *conn_context; + struct iscsi_ev_context *ev_context; int i; if (ev_size > ipc->ctldev_bufmax) @@ -121,26 +107,26 @@ struct iscsi_conn_context *iscsi_conn_context_get(iscsi_conn_t *conn, continue; if (!conn->context_pool[i]->allocated) { - conn_context = conn->context_pool[i]; + ev_context = conn->context_pool[i]; - memset(&conn_context->actor, 0, + memset(&ev_context->actor, 0, sizeof(struct actor)); - conn_context->allocated = 1; + ev_context->allocated = 1; /* some callers abuse this pointer */ - conn_context->data = (void *)conn_context + - sizeof(struct iscsi_conn_context); - log_debug(7, "get conn context %p", - &conn_context->actor); - return conn_context; + ev_context->data = (void *)ev_context + + sizeof(struct iscsi_ev_context); + log_debug(7, "get ev context %p", + &ev_context->actor); + return ev_context; } } return NULL; } -void iscsi_conn_context_put(struct iscsi_conn_context *conn_context) +static void iscsi_ev_context_put(struct iscsi_ev_context *ev_context) { - log_debug(7, "put conn context %p", &conn_context->actor); - conn_context->allocated = 0; + log_debug(7, "put ev context %p", &ev_context->actor); + ev_context->allocated = 0; } static void session_online_devs(int host_no, int sid) @@ -250,183 +236,6 @@ __check_iscsi_status_class(iscsi_session_t *session, int cid, return CONN_LOGIN_FAILED; } -static void -__setup_authentication(iscsi_session_t *session, - struct iscsi_auth_config *auth_cfg) -{ - /* if we have any incoming credentials, we insist on authenticating - * the target or not logging in at all - */ - if (auth_cfg->username_in[0] - || auth_cfg->password_in_length) { - /* sanity check the config */ - if (auth_cfg->password_length == 0) { - log_debug(1, - "node record has incoming " - "authentication credentials but has no outgoing " - "credentials configured, exiting"); - return; - } - session->bidirectional_auth = 1; - } else { - /* no or 1-way authentication */ - session->bidirectional_auth = 0; - } - - /* copy in whatever credentials we have */ - strlcpy(session->username, auth_cfg->username, - sizeof (session->username)); - session->username[sizeof (session->username) - 1] = '\0'; - if ((session->password_length = auth_cfg->password_length)) - memcpy(session->password, auth_cfg->password, - session->password_length); - - strlcpy(session->username_in, auth_cfg->username_in, - sizeof (session->username_in)); - session->username_in[sizeof (session->username_in) - 1] = '\0'; - if ((session->password_in_length = - auth_cfg->password_in_length)) - memcpy(session->password_in, auth_cfg->password_in, - session->password_in_length); - - if (session->password_length || session->password_in_length) { - /* setup the auth buffers */ - session->auth_buffers[0].address = &session->auth_client_block; - session->auth_buffers[0].length = - sizeof (session->auth_client_block); - session->auth_buffers[1].address = - &session->auth_recv_string_block; - session->auth_buffers[1].length = - sizeof (session->auth_recv_string_block); - - session->auth_buffers[2].address = - &session->auth_send_string_block; - session->auth_buffers[2].length = - sizeof (session->auth_send_string_block); - - session->auth_buffers[3].address = - &session->auth_recv_binary_block; - session->auth_buffers[3].length = - sizeof (session->auth_recv_binary_block); - - session->auth_buffers[4].address = - &session->auth_send_binary_block; - session->auth_buffers[4].length = - sizeof (session->auth_send_binary_block); - - session->num_auth_buffers = 5; - log_debug(6, "authentication setup complete..."); - } else { - session->num_auth_buffers = 0; - log_debug(6, "no authentication configured..."); - } -} - -static int -setup_portal(iscsi_conn_t *conn, conn_rec_t *conn_rec) -{ - char port[NI_MAXSERV]; - - sprintf(port, "%d", conn_rec->port); - if (resolve_address(conn_rec->address, port, &conn->saddr)) { - log_error("cannot resolve host name %s", - conn_rec->address); - return EINVAL; - } - conn->failback_saddr = conn->saddr; - - getnameinfo((struct sockaddr *)&conn->saddr, sizeof(conn->saddr), - conn->host, sizeof(conn->host), NULL, 0, NI_NUMERICHOST); - log_debug(4, "resolved %s to %s", conn_rec->address, conn->host); - return 0; -} - -static void -iscsi_copy_operational_params(iscsi_conn_t *conn) -{ - iscsi_session_t *session = conn->session; - conn_rec_t *conn_rec = &session->nrec.conn[conn->id]; - node_rec_t *rec = &session->nrec; - - conn->hdrdgst_en = conn_rec->iscsi.HeaderDigest; - conn->datadgst_en = conn_rec->iscsi.DataDigest; - - conn->max_recv_dlength = - __padding(conn_rec->iscsi.MaxRecvDataSegmentLength); - if (conn->max_recv_dlength < ISCSI_MIN_MAX_RECV_SEG_LEN || - conn->max_recv_dlength > ISCSI_MAX_MAX_RECV_SEG_LEN) { - log_error("Invalid iscsi.MaxRecvDataSegmentLength. Must be " - "within %u and %u. Setting to %u\n", - ISCSI_MIN_MAX_RECV_SEG_LEN, - ISCSI_MAX_MAX_RECV_SEG_LEN, - DEF_INI_MAX_RECV_SEG_LEN); - conn_rec->iscsi.MaxRecvDataSegmentLength = - DEF_INI_MAX_RECV_SEG_LEN; - conn->max_recv_dlength = DEF_INI_MAX_RECV_SEG_LEN; - } - - /* zero indicates to use the target's value */ - conn->max_xmit_dlength = - __padding(conn_rec->iscsi.MaxXmitDataSegmentLength); - if (conn->max_xmit_dlength == 0) - conn->max_xmit_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN; - if (conn->max_xmit_dlength < ISCSI_MIN_MAX_RECV_SEG_LEN || - conn->max_xmit_dlength > ISCSI_MAX_MAX_RECV_SEG_LEN) { - log_error("Invalid iscsi.MaxXmitDataSegmentLength. Must be " - "within %u and %u. Setting to %u\n", - ISCSI_MIN_MAX_RECV_SEG_LEN, - ISCSI_MAX_MAX_RECV_SEG_LEN, - DEF_INI_MAX_RECV_SEG_LEN); - conn_rec->iscsi.MaxXmitDataSegmentLength = - DEF_INI_MAX_RECV_SEG_LEN; - conn->max_xmit_dlength = DEF_INI_MAX_RECV_SEG_LEN; - } - - /* session's operational parameters */ - session->initial_r2t_en = rec->session.iscsi.InitialR2T; - session->imm_data_en = rec->session.iscsi.ImmediateData; - session->first_burst = __padding(rec->session.iscsi.FirstBurstLength); - /* - * some targets like netapp fail the login if sent bad first_burst - * and max_burst lens, even when immediate data=no and - * initial r2t = Yes, so we always check the user values. - */ - if (session->first_burst < ISCSI_MIN_FIRST_BURST_LEN || - session->first_burst > ISCSI_MAX_FIRST_BURST_LEN) { - log_error("Invalid iscsi.FirstBurstLength of %u. Must be " - "within %u and %u. Setting to %u\n", - session->first_burst, - ISCSI_MIN_FIRST_BURST_LEN, - ISCSI_MAX_FIRST_BURST_LEN, - DEF_INI_FIRST_BURST_LEN); - rec->session.iscsi.FirstBurstLength = DEF_INI_FIRST_BURST_LEN; - session->first_burst = DEF_INI_FIRST_BURST_LEN; - } - - session->max_burst = __padding(rec->session.iscsi.MaxBurstLength); - if (session->max_burst < ISCSI_MIN_MAX_BURST_LEN || - session->max_burst > ISCSI_MAX_MAX_BURST_LEN) { - log_error("Invalid iscsi.MaxBurstLength of %u. Must be " - "within %u and %u. Setting to %u\n", - session->max_burst, ISCSI_MIN_MAX_BURST_LEN, - ISCSI_MAX_MAX_BURST_LEN, DEF_INI_MAX_BURST_LEN); - rec->session.iscsi.MaxBurstLength = DEF_INI_MAX_BURST_LEN; - session->max_burst = DEF_INI_MAX_BURST_LEN; - } - - if (session->first_burst > session->max_burst) { - log_error("Invalid iscsi.FirstBurstLength of %u. Must be " - "less than iscsi.MaxBurstLength. Setting to %u\n", - session->first_burst, session->max_burst); - rec->session.iscsi.FirstBurstLength = session->max_burst; - session->first_burst = session->max_burst; - } - - session->def_time2wait = rec->session.iscsi.DefaultTime2Wait; - session->def_time2retain = rec->session.iscsi.DefaultTime2Retain; - session->erl = rec->session.iscsi.ERL; -} - static int __session_conn_create(iscsi_session_t *session, int cid) { @@ -434,7 +243,7 @@ __session_conn_create(iscsi_session_t *session, int cid) conn_rec_t *conn_rec = &session->nrec.conn[cid]; int err; - if (iscsi_conn_context_alloc(conn)) { + if (iscsi_ev_context_alloc(conn)) { log_error("cannot allocate context_pool for conn cid %d", cid); return ENOMEM; } @@ -486,14 +295,15 @@ __session_conn_create(iscsi_session_t *session, int cid) conn->noop_out_interval = DEF_NOOP_OUT_INTERVAL; } - iscsi_copy_operational_params(conn); + iscsi_copy_operational_params(conn, &session->nrec.session.iscsi, + &conn_rec->iscsi); /* TCP options */ conn->tcp_window_size = conn_rec->tcp.window_size; /* FIXME: type_of_service */ /* resolve the string address to an IP address */ - err = setup_portal(conn, conn_rec); + err = iscsi_setup_portal(conn, conn_rec->address, conn_rec->port); if (err) return err; return 0; @@ -506,7 +316,7 @@ session_release(iscsi_session_t *session) if (session->target_alias) free(session->target_alias); - iscsi_conn_context_free(&session->conn[0]); + iscsi_ev_context_free(&session->conn[0]); free(session); } @@ -524,11 +334,10 @@ __session_create(node_rec_t *rec, struct iscsi_transport *t) log_debug(2, "Allocted session %p", session); INIT_LIST_HEAD(&session->list); - /* opened at daemon load time (iscsid.c) */ - session->ctrl_fd = control_fd; session->t = t; session->reopen_qtask.mgmt_ipc_fd = -1; session->id = -1; + session->use_ipc = 1; /* save node record. we might need it for redirection */ memcpy(&session->nrec, rec, sizeof(node_rec_t)); @@ -570,7 +379,7 @@ __session_create(node_rec_t *rec, struct iscsi_transport *t) session->isid[5] = 0; /* setup authentication variables for the session*/ - __setup_authentication(session, &rec->session.auth); + iscsi_setup_authentication(session, &rec->session.auth); session->param_mask = ~0ULL; if (!(t->caps & CAP_MULTI_R2T)) @@ -601,18 +410,18 @@ __session_create(node_rec_t *rec, struct iscsi_transport *t) static void iscsi_flush_context_pool(struct iscsi_session *session) { - struct iscsi_conn_context *conn_context; + struct iscsi_ev_context *ev_context; struct iscsi_conn *conn = &session->conn[0]; int i; for (i = 0; i < CONTEXT_POOL_MAX; i++) { - conn_context = conn->context_pool[i]; - if (!conn_context) + ev_context = conn->context_pool[i]; + if (!ev_context) continue; - if (conn_context->allocated) { + if (ev_context->allocated) { actor_delete(&(conn->context_pool[i]->actor)); - iscsi_conn_context_put(conn_context); + iscsi_ev_context_put(ev_context); } } } @@ -709,17 +518,17 @@ queue_delayed_reopen(queue_task_t *qtask, int delay) static int iscsi_conn_connect(struct iscsi_conn *conn, queue_task_t *qtask) { - struct iscsi_conn_context *conn_context; + struct iscsi_ev_context *ev_context; int rc; - conn_context = iscsi_conn_context_get(conn, 0); - if (!conn_context) { + 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; } - conn_context->data = qtask; + ev_context->data = qtask; rc = conn->session->t->template->ep_connect(conn, 1); if (rc < 0 && errno != EINPROGRESS) { @@ -732,11 +541,11 @@ static int iscsi_conn_connect(struct iscsi_conn *conn, queue_task_t *qtask) log_error("cannot make a connection to %s:%s (%d,%d)", conn->host, serv, rc, errno); - iscsi_conn_context_put(conn_context); + iscsi_ev_context_put(ev_context); return ENOTCONN; } - iscsi_sched_conn_context(conn_context, conn, 0, EV_CONN_POLL); + 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, @@ -1020,15 +829,15 @@ __conn_error_handle(iscsi_session_t *session, iscsi_conn_t *conn) static void session_conn_error(void *data) { - struct iscsi_conn_context *conn_context = data; - enum iscsi_err error = *(enum iscsi_err *)conn_context->data; - iscsi_conn_t *conn = conn_context->conn; + struct iscsi_ev_context *ev_context = data; + enum iscsi_err error = *(enum iscsi_err *)ev_context->data; + iscsi_conn_t *conn = ev_context->conn; iscsi_session_t *session = conn->session; log_warning("Kernel reported iSCSI connection %d:%d error (%d) " "state (%d)", session->id, conn->id, error, conn->state); - iscsi_conn_context_put(conn_context); + iscsi_ev_context_put(ev_context); switch (error) { case ISCSI_ERR_INVALID_HOST: @@ -1136,17 +945,6 @@ static void conn_send_nop_out(void *data) &conn->nop_out_timer, conn->noop_out_timeout); } -static void -print_param_value(enum iscsi_param param, void *value, int type) -{ - log_debug(3, "set operational parameter %d to:", param); - - if (type == ISCSI_STRING) - log_debug(3, "%s", value ? (char *)value : "NULL"); - else - log_debug(3, "%u", *(uint32_t *)value); -} - void free_initiator(void) { struct iscsi_transport *t; @@ -1188,292 +986,23 @@ static void session_scan_host(struct iscsi_session *session, int hostno, mgmt_ipc_write_rsp(qtask, MGMT_IPC_ERR_INTERNAL); } -static int __iscsi_host_set_param(struct iscsi_transport *t, - int host_no, int param, char *value, - int type) -{ - int rc; - - rc = ipc->set_host_param(t->handle, host_no, param, value, type); - /* 2.6.20 and below returns EINVAL */ - if (rc && rc != -ENOSYS && rc != -EINVAL) { - log_error("can't set operational parameter %d for " - "host %d, retcode %d (%d)", param, host_no, - rc, errno); - return rc; - } - return 0; -} - -mgmt_ipc_err_e iscsi_host_set_param(int host_no, int param, char *value) -{ - struct iscsi_transport *t; - - t = iscsi_sysfs_get_transport_by_hba(host_no); - if (!t) - return MGMT_IPC_ERR_TRANS_FAILURE; - if (__iscsi_host_set_param(t, host_no, param, value, ISCSI_STRING)) - return MGMT_IPC_ERR; - return MGMT_IPC_OK; -} - -#define MAX_SESSION_PARAMS 32 -#define MAX_HOST_PARAMS 3 - static void setup_full_feature_phase(iscsi_conn_t *conn) { iscsi_session_t *session = conn->session; iscsi_login_context_t *c = &conn->login_context; - int i, rc; - uint32_t one = 1, zero = 0; - struct hostparam { - int param; - int type; - void *value; - int set; - } hosttbl[MAX_HOST_PARAMS] = { - { - .param = ISCSI_HOST_PARAM_NETDEV_NAME, - .value = session->nrec.iface.netdev, - .type = ISCSI_STRING, - .set = 1, - }, { - .param = ISCSI_HOST_PARAM_HWADDRESS, - .value = session->nrec.iface.hwaddress, - .type = ISCSI_STRING, - .set = 1, - }, { - .param = ISCSI_HOST_PARAM_INITIATOR_NAME, - .value = session->initiator_name, - .type = ISCSI_STRING, - .set = 0, - }, - }; - struct connparam { - int param; - int type; - void *value; - int conn_only; - } conntbl[MAX_SESSION_PARAMS] = { - { - .param = ISCSI_PARAM_MAX_RECV_DLENGTH, - .value = &conn->max_recv_dlength, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_MAX_XMIT_DLENGTH, - .value = &conn->max_xmit_dlength, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_HDRDGST_EN, - .value = &conn->hdrdgst_en, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_DATADGST_EN, - .value = &conn->datadgst_en, - .type = ISCSI_INT, - .conn_only = 1, - }, { - .param = ISCSI_PARAM_INITIAL_R2T_EN, - .value = &session->initial_r2t_en, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_MAX_R2T, - .value = &one, /* FIXME: session->max_r2t */ - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_IMM_DATA_EN, - .value = &session->imm_data_en, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_FIRST_BURST, - .value = &session->first_burst, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_MAX_BURST, - .value = &session->max_burst, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_PDU_INORDER_EN, - .value = &session->pdu_inorder_en, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param =ISCSI_PARAM_DATASEQ_INORDER_EN, - .value = &session->dataseq_inorder_en, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_ERL, - .value = &zero, /* FIXME: session->erl */ - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_IFMARKER_EN, - .value = &zero,/* FIXME: session->ifmarker_en */ - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_OFMARKER_EN, - .value = &zero,/* FIXME: session->ofmarker_en */ - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_EXP_STATSN, - .value = &conn->exp_statsn, - .type = ISCSI_INT, - .conn_only = 1, - }, { - .param = ISCSI_PARAM_TARGET_NAME, - .conn_only = 0, - .type = ISCSI_STRING, - .value = session->target_name, - }, { - .param = ISCSI_PARAM_TPGT, - .value = &session->portal_group_tag, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_PERSISTENT_ADDRESS, - .value = session->nrec.conn[conn->id].address, - .type = ISCSI_STRING, - .conn_only = 1, - }, { - .param = ISCSI_PARAM_PERSISTENT_PORT, - .value = &session->nrec.conn[conn->id].port, - .type = ISCSI_INT, - .conn_only = 1, - }, { - .param = ISCSI_PARAM_SESS_RECOVERY_TMO, - .value = &session->replacement_timeout, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_USERNAME, - .value = session->username, - .type = ISCSI_STRING, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_USERNAME_IN, - .value = session->username_in, - .type = ISCSI_STRING, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_PASSWORD, - .value = session->password, - .type = ISCSI_STRING, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_PASSWORD_IN, - .value = session->password_in, - .type = ISCSI_STRING, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_FAST_ABORT, - .value = &session->fast_abort, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_ABORT_TMO, - .value = &session->abort_timeout, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_LU_RESET_TMO, - .value = &session->lu_reset_timeout, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_TGT_RESET_TMO, - .value = &session->tgt_reset_timeout, - .type = ISCSI_INT, - .conn_only = 0, - }, { - .param = ISCSI_PARAM_PING_TMO, - .value = &conn->noop_out_timeout, - .type = ISCSI_INT, - .conn_only = 1, - }, { - .param = ISCSI_PARAM_RECV_TMO, - .value = &conn->noop_out_interval, - .type = ISCSI_INT, - .conn_only = 1, - }, { - .param = ISCSI_PARAM_IFACE_NAME, - .value = session->nrec.iface.name, - .type = ISCSI_STRING, - }, { - .param = ISCSI_PARAM_INITIATOR_NAME, - .value = session->initiator_name, - .type = ISCSI_STRING, - }, - }; + int rc; actor_delete(&conn->login_timer); - /* Entered full-feature phase! */ - for (i = 0; i < MAX_SESSION_PARAMS; i++) { - if (conn->id != 0 && !conntbl[i].conn_only) - continue; - - if (!(session->param_mask & (1ULL << conntbl[i].param))) - continue; - - rc = ipc->set_param(session->t->handle, session->id, - conn->id, conntbl[i].param, conntbl[i].value, - conntbl[i].type); - if (rc && rc != -ENOSYS) { - log_error("can't set operational parameter %d for " - "connection %d:%d, retcode %d (%d)", - conntbl[i].param, session->id, conn->id, - rc, errno); - - iscsi_login_eh(conn, c->qtask, - MGMT_IPC_ERR_LOGIN_FAILURE); - return; - } - if (rc == -ENOSYS) { - switch (conntbl[i].param) { - case ISCSI_PARAM_PING_TMO: - /* - * older kernels may not support nops - * in kernel - */ - conn->userspace_nop = 1; - break; - case ISCSI_PARAM_INITIATOR_NAME: - /* use host level one instead */ - hosttbl[ISCSI_HOST_PARAM_INITIATOR_NAME].set = 1; - break; - } - } - - print_param_value(conntbl[i].param, conntbl[i].value, - conntbl[i].type); + if (iscsi_session_set_params(conn)) { + iscsi_login_eh(conn, c->qtask, MGMT_IPC_ERR_LOGIN_FAILURE); + return; } - for (i = 0; i < MAX_HOST_PARAMS; i++) { - if (!hosttbl[i].set) - continue; - - if (__iscsi_host_set_param(session->t, session->hostno, - hosttbl[i].param, hosttbl[i].value, - hosttbl[i].type)) { - iscsi_login_eh(conn, c->qtask, - MGMT_IPC_ERR_LOGIN_FAILURE); - return; - } - - print_param_value(hosttbl[i].param, hosttbl[i].value, - hosttbl[i].type); + if (iscsi_host_set_params(session)) { + iscsi_login_eh(conn, c->qtask, MGMT_IPC_ERR_LOGIN_FAILURE); + return; } if (ipc->start_conn(session->t->handle, session->id, conn->id, @@ -1527,10 +1056,10 @@ setup_full_feature_phase(iscsi_conn_t *conn) static void iscsi_logout_timedout(void *data) { - struct iscsi_conn_context *conn_context = data; - struct iscsi_conn *conn = conn_context->conn; + struct iscsi_ev_context *ev_context = data; + struct iscsi_conn *conn = ev_context->conn; - iscsi_conn_context_put(conn_context); + iscsi_ev_context_put(ev_context); /* * assume we were in STATE_IN_LOGOUT or there * was some nasty error @@ -1542,7 +1071,7 @@ static void iscsi_logout_timedout(void *data) static int iscsi_send_logout(iscsi_conn_t *conn) { struct iscsi_logout hdr; - struct iscsi_conn_context *conn_context; + struct iscsi_ev_context *ev_context; if (conn->state != STATE_LOGGED_IN) return EINVAL; @@ -1558,12 +1087,12 @@ static int iscsi_send_logout(iscsi_conn_t *conn) return EIO; conn->state = STATE_IN_LOGOUT; - conn_context = iscsi_conn_context_get(conn, 0); - if (!conn_context) + ev_context = iscsi_ev_context_get(conn, 0); + if (!ev_context) /* unbounded logout */ log_warning("Could not allocate conn context for logout."); else { - iscsi_sched_conn_context(conn_context, conn, + iscsi_sched_ev_context(ev_context, conn, conn->logout_timeout, EV_CONN_LOGOUT_TIMER); log_debug(3, "logout timeout timer %u\n", @@ -1575,11 +1104,11 @@ static int iscsi_send_logout(iscsi_conn_t *conn) static void iscsi_stop(void *data) { - struct iscsi_conn_context *conn_context = data; - struct iscsi_conn *conn = conn_context->conn; + struct iscsi_ev_context *ev_context = data; + struct iscsi_conn *conn = ev_context->conn; int rc = 0; - iscsi_conn_context_put(conn_context); + iscsi_ev_context_put(ev_context); if (!iscsi_send_logout(conn)) return; @@ -1741,11 +1270,11 @@ failed: static void session_conn_recv_pdu(void *data) { - struct iscsi_conn_context *conn_context = data; - iscsi_conn_t *conn = conn_context->conn; + struct iscsi_ev_context *ev_context = data; + iscsi_conn_t *conn = ev_context->conn; struct iscsi_hdr hdr; - conn->recv_context = conn_context; + conn->recv_context = ev_context; switch (conn->state) { case STATE_IN_LOGIN: @@ -1755,11 +1284,10 @@ static void session_conn_recv_pdu(void *data) case STATE_IN_LOGOUT: case STATE_LOGOUT_REQUESTED: /* read incoming PDU */ - if (!iscsi_io_recv_pdu(conn, &hdr, ISCSI_DIGEST_NONE, - conn->data, ISCSI_DEF_MAX_RECV_SEG_LEN, - ISCSI_DIGEST_NONE, 0)) { + if (iscsi_io_recv_pdu(conn, &hdr, ISCSI_DIGEST_NONE, + conn->data, ISCSI_DEF_MAX_RECV_SEG_LEN, + ISCSI_DIGEST_NONE, 0) < 0) return; - } switch (hdr.opcode & ISCSI_OPCODE_MASK) { case ISCSI_OP_NOOP_IN: @@ -1777,17 +1305,17 @@ static void session_conn_recv_pdu(void *data) } break; case STATE_XPT_WAIT: - iscsi_conn_context_put(conn_context); + iscsi_ev_context_put(ev_context); log_debug(1, "ignoring incoming PDU in XPT_WAIT. " "let connection re-establish or fail"); break; case STATE_CLEANUP_WAIT: - iscsi_conn_context_put(conn_context); + iscsi_ev_context_put(ev_context); log_debug(1, "ignoring incoming PDU in XPT_WAIT. " "let connection cleanup"); break; default: - iscsi_conn_context_put(conn_context); + iscsi_ev_context_put(ev_context); log_error("Invalid state. Dropping PDU.\n"); } } @@ -1910,15 +1438,15 @@ retry_create: static void session_conn_poll(void *data) { - struct iscsi_conn_context *conn_context = data; - iscsi_conn_t *conn = conn_context->conn; + struct iscsi_ev_context *ev_context = data; + iscsi_conn_t *conn = ev_context->conn; struct iscsi_session *session = conn->session; mgmt_ipc_err_e err = MGMT_IPC_OK; - queue_task_t *qtask = conn_context->data; + queue_task_t *qtask = ev_context->data; iscsi_login_context_t *c = &conn->login_context; int rc; - iscsi_conn_context_put(conn_context); + iscsi_ev_context_put(ev_context); if (conn->state != STATE_XPT_WAIT) return; @@ -1927,16 +1455,16 @@ static void session_conn_poll(void *data) if (rc == 0) { log_debug(4, "poll not connected %d", rc); /* timedout: Poll again. */ - conn_context = iscsi_conn_context_get(conn, 0); - if (!conn_context) { + ev_context = iscsi_ev_context_get(conn, 0); + if (!ev_context) { /* while polling the recv pool should be full */ log_error("BUG: session_conn_poll could not get conn " "context."); iscsi_login_eh(conn, qtask, MGMT_IPC_ERR_INTERNAL); return; } - conn_context->data = qtask; - iscsi_sched_conn_context(conn_context, conn, 0, EV_CONN_POLL); + ev_context->data = qtask; + iscsi_sched_ev_context(ev_context, conn, 0, EV_CONN_POLL); } else if (rc > 0) { /* connected! */ memset(c, 0, sizeof(iscsi_login_context_t)); @@ -1961,10 +1489,9 @@ static void session_conn_poll(void *data) "%d:%d", session->id, conn->id); } - iscsi_copy_operational_params(conn); - - if (session->t->template->create_conn) - session->t->template->create_conn(conn); + iscsi_copy_operational_params(conn, + &session->nrec.session.iscsi, + &session->nrec.conn[conn->id].iscsi); /* * TODO: use the iface number or some other value * so this will be persistent @@ -2011,70 +1538,55 @@ cleanup: session_conn_shutdown(conn, qtask, err); } -void iscsi_sched_conn_context(struct iscsi_conn_context *conn_context, - struct iscsi_conn *conn, unsigned long tmo, - int event) +static int iscsi_sched_ev_context(struct iscsi_ev_context *ev_context, + struct iscsi_conn *conn, unsigned long tmo, + int event) { enum iscsi_err error; log_debug(7, "sched conn context %p event %d, tmo %lu", - &conn_context->actor, event, tmo); + &ev_context->actor, event, tmo); - conn_context->conn = conn; + ev_context->conn = conn; switch (event) { case EV_CONN_RECV_PDU: - actor_new(&conn_context->actor, session_conn_recv_pdu, - conn_context); - actor_schedule(&conn_context->actor); + actor_new(&ev_context->actor, session_conn_recv_pdu, + ev_context); + actor_schedule(&ev_context->actor); break; case EV_CONN_ERROR: - error = *(enum iscsi_err *)conn_context->data; + error = *(enum iscsi_err *)ev_context->data; - actor_new(&conn_context->actor, session_conn_error, - conn_context); + actor_new(&ev_context->actor, session_conn_error, + ev_context); /* * We handle invalid host, by killing the session. * It must go at the head of the queue, so we do not * initiate error handling or logout or some other op. */ if (error == ISCSI_ERR_INVALID_HOST) - actor_schedule_head(&conn_context->actor); + actor_schedule_head(&ev_context->actor); else - actor_schedule(&conn_context->actor); + actor_schedule(&ev_context->actor); break; case EV_CONN_POLL: - actor_new(&conn_context->actor, session_conn_poll, - conn_context); - actor_schedule(&conn_context->actor); + actor_new(&ev_context->actor, session_conn_poll, + ev_context); + actor_schedule(&ev_context->actor); break; case EV_CONN_LOGOUT_TIMER: - actor_timer(&conn_context->actor, tmo * 1000, - iscsi_logout_timedout, conn_context); + actor_timer(&ev_context->actor, tmo * 1000, + iscsi_logout_timedout, ev_context); break; case EV_CONN_STOP: - actor_new(&conn_context->actor, iscsi_stop, - conn_context); - actor_schedule(&conn_context->actor); + actor_new(&ev_context->actor, iscsi_stop, + ev_context); + actor_schedule(&ev_context->actor); break; default: log_error("Invalid event type %d.", event); - return; - } -} - -iscsi_session_t* -session_find_by_sid(int sid) -{ - struct iscsi_transport *t; - iscsi_session_t *session; - - list_for_each_entry(t, &transports, list) { - list_for_each_entry(session, &t->sessions, list) { - if (session->id == sid) - return session; - } } - return NULL; + return 0; } static iscsi_session_t* session_find_by_rec(node_rec_t *rec) @@ -2111,50 +1623,6 @@ static int session_is_running(node_rec_t *rec) return 0; } -static int iface_set_param(struct iscsi_transport *t, struct iface_rec *iface, - struct iscsi_session *session) -{ - int rc = 0; - - log_debug(3, "setting iface %s, dev %s, set ip %s, hw %s, " - "transport %s.\n", - iface->name, iface->netdev, iface->ipaddress, - iface->hwaddress, iface->transport_name); - - if (!t->template->set_host_ip) - return 0; - - /* if we need to set the ip addr then set all the iface net settings */ - 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; - } - - rc = __iscsi_host_set_param(t, session->hostno, - ISCSI_HOST_PARAM_IPADDRESS, - iface->ipaddress, ISCSI_STRING); - if (rc) - return rc; - - if (iface_is_bound_by_netdev(iface)) { - rc = __iscsi_host_set_param(t, session->hostno, - ISCSI_HOST_PARAM_NETDEV_NAME, - iface->netdev, ISCSI_STRING); - if (rc) - return rc; - } - - if (iface_is_bound_by_hwaddr(iface)) { - rc = __iscsi_host_set_param(t, session->hostno, - ISCSI_HOST_PARAM_HWADDRESS, - iface->hwaddress, ISCSI_STRING); - if (rc) - return rc; - } - return 0; -} - int session_login_task(node_rec_t *rec, queue_task_t *qtask) { @@ -2168,8 +1636,6 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask) t = iscsi_sysfs_get_transport_by_name(rec->iface.transport_name); if (!t) return MGMT_IPC_ERR_TRANS_NOT_FOUND; - if (set_transport_template(t)) - return MGMT_IPC_ERR_TRANS_NOT_FOUND; if ((!(t->caps & CAP_RECOVERY_L0) && rec->session.iscsi.ERL != 0) || @@ -2234,7 +1700,7 @@ 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)) { + if (iscsi_host_set_net_params(&rec->iface, session)) { __session_destroy(session); return MGMT_IPC_ERR_LOGIN_FAILURE; } @@ -2279,8 +1745,6 @@ iscsi_sync_session(node_rec_t *rec, queue_task_t *qtask, uint32_t sid) t = iscsi_sysfs_get_transport_by_name(rec->iface.transport_name); if (!t) return MGMT_IPC_ERR_TRANS_NOT_FOUND; - if (set_transport_template(t)) - return MGMT_IPC_ERR_TRANS_NOT_FOUND; session = __session_create(rec, t); if (!session) @@ -2392,7 +1856,7 @@ iscsi_host_send_targets(queue_task_t *qtask, int host_no, int do_login, struct iscsi_transport *t; t = iscsi_sysfs_get_transport_by_hba(host_no); - if (!t || set_transport_template(t)) { + if (!t) { log_error("Invalid host no %d for sendtargets\n", host_no); return MGMT_IPC_ERR_TRANS_FAILURE; } @@ -2412,7 +1876,7 @@ iscsi_host_send_targets(queue_task_t *qtask, int host_no, int do_login, * the card will have sessions preset in the FLASH and will log into them * automaotically then send us notification that a session is setup. */ -void iscsi_async_session_creation(uint32_t host_no, uint32_t sid) +static void iscsi_async_session_creation(uint32_t host_no, uint32_t sid) { struct iscsi_transport *transport; @@ -2428,7 +1892,20 @@ void iscsi_async_session_creation(uint32_t host_no, uint32_t sid) session_scan_host(NULL, host_no, NULL); } -void iscsi_async_session_destruction(uint32_t host_no, uint32_t sid) +static void iscsi_async_session_destruction(uint32_t host_no, uint32_t sid) { log_debug(3, "session destroyed sid %u host no %d", sid, host_no); } + +static struct iscsi_ipc_ev_clbk ipc_clbk = { + .create_session = iscsi_async_session_creation, + .destroy_session = iscsi_async_session_destruction, + .get_ev_context = iscsi_ev_context_get, + .put_ev_context = iscsi_ev_context_put, + .sched_ev_context = iscsi_sched_ev_context, +}; + +void iscsi_initiator_init(void) +{ + ipc_register_ev_callback(&ipc_clbk); +} |