diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2008-05-19 21:20:44 -0500 |
---|---|---|
committer | Mike Christie <michaelc@cs.wisc.edu> | 2008-05-19 21:20:44 -0500 |
commit | 74489b2eb9f3c5d96c64f859de965cff10bb457f (patch) | |
tree | b1adea6e5d1ae796fd79992a9e13faa46a02ea5d | |
parent | dc75ff01ee126dbde42d4f2fe975c17e25719cf9 (diff) | |
download | open-iscsi-74489b2eb9f3c5d96c64f859de965cff10bb457f.tar.gz |
pass ep to session creation
bnx2i allocates a host per session and iser accesses the
device so we need to pass them a the leading connection
so they can find the hardware that is it bound to.
This also has us call ep_disconnect before calling the stop
conn callout, so these driver do not have to worry about
stopping the receiving path.
-rw-r--r-- | etc/iface.example | 2 | ||||
-rw-r--r-- | include/iscsi_if.h | 7 | ||||
-rw-r--r-- | usr/initiator.c | 58 | ||||
-rw-r--r-- | usr/iscsi_ipc.h | 4 | ||||
-rw-r--r-- | usr/iscsi_sysfs.c | 40 | ||||
-rw-r--r-- | usr/netlink.c | 27 | ||||
-rw-r--r-- | usr/transport.c | 10 |
7 files changed, 116 insertions, 32 deletions
diff --git a/etc/iface.example b/etc/iface.example index 7684aea..7fb7951 100644 --- a/etc/iface.example +++ b/etc/iface.example @@ -19,7 +19,7 @@ # - tcp (Software iSCSI over TCP/IP) # - iser (Software iSCSI over infinniband # - qla4xxx (Qlogic QLA4XXX HBAs) -# +# - bnx2i (Broadcom bnx iSCSI HBAs); # #OPTIONAL: iface.initiatorname # To use a initiator name other than the one set in diff --git a/include/iscsi_if.h b/include/iscsi_if.h index 6548560..e71b88a 100644 --- a/include/iscsi_if.h +++ b/include/iscsi_if.h @@ -50,6 +50,7 @@ enum iscsi_uevent_e { ISCSI_UEVENT_TGT_DSCVR = UEVENT_BASE + 15, ISCSI_UEVENT_SET_HOST_PARAM = UEVENT_BASE + 16, ISCSI_UEVENT_UNBIND_SESSION = UEVENT_BASE + 17, + ISCSI_UEVENT_CREATE_BOUND_SESSION = UEVENT_BASE + 18, /* up events */ ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, @@ -78,6 +79,12 @@ struct iscsi_uevent { uint16_t cmds_max; uint16_t queue_depth; } c_session; + struct msg_create_bound_session { + uint64_t ep_handle; + uint32_t initial_cmdsn; + uint16_t cmds_max; + uint16_t queue_depth; + } c_bound_session; struct msg_destroy_session { uint32_t sid; } d_session; diff --git a/usr/initiator.c b/usr/initiator.c index 96f4693..9c3eb49 100644 --- a/usr/initiator.c +++ b/usr/initiator.c @@ -419,7 +419,14 @@ __session_conn_create(iscsi_session_t *session, int cid) conn->state = STATE_FREE; conn->session = session; + /* + * 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 + * the old connection. Right now we leak a connection. + * We can also probably merge these two fields. + */ conn->socket_fd = -1; + conn->transport_ep_handle = -1; /* connection's timeouts */ conn->id = cid; conn->logout_timeout = conn_rec->timeo.logout_timeout; @@ -602,11 +609,15 @@ session_conn_shutdown(iscsi_conn_t *conn, queue_task_t *qtask, { iscsi_session_t *session = conn->session; + log_debug(2, "disconnect conn"); + /* this will check for a valid interconnect connection */ + conn->session->t->template->ep_disconnect(conn); + if (session->id == -1) - goto disconnect_conn; + goto cleanup; if (!sysfs_session_has_leadconn(session->id)) - goto disconnect_conn; + goto cleanup; if (conn->state == STATE_IN_LOGIN || conn->state == STATE_IN_LOGOUT || @@ -627,11 +638,7 @@ session_conn_shutdown(iscsi_conn_t *conn, queue_task_t *qtask, return MGMT_IPC_ERR_INTERNAL; } -disconnect_conn: - log_debug(2, "disconnect conn"); - /* this will check for a valid interconnect connection */ - conn->session->t->template->ep_disconnect(conn); - +cleanup: if (session->id != -1) { log_debug(2, "kdestroy session %u", session->id); if (ipc->destroy_session(session->t->handle, session->id)) { @@ -686,8 +693,8 @@ static int iscsi_conn_connect(struct iscsi_conn *conn, queue_task_t *qtask) conn->host, sizeof(conn->host), serv, sizeof(serv), NI_NUMERICHOST|NI_NUMERICSERV); - log_error("cannot make a connection to %s:%s (%d)", - conn->host, serv, errno); + log_error("cannot make a connection to %s:%s (%d,%d)", + conn->host, serv, rc, errno); iscsi_conn_context_put(conn_context); return ENOTCONN; } @@ -717,6 +724,7 @@ __session_conn_reopen(iscsi_conn_t *conn, queue_task_t *qtask, int do_stop, conn_delete_timers(conn); conn->state = STATE_XPT_WAIT; + conn->session->t->template->ep_disconnect(conn); if (do_stop) { /* state: STATE_CLEANUP_WAIT */ if (ipc->stop_conn(session->t->handle, session->id, @@ -729,7 +737,6 @@ __session_conn_reopen(iscsi_conn_t *conn, queue_task_t *qtask, int do_stop, log_debug(3, "connection %d:%d is stopped for recovery", session->id, conn->id); } - conn->session->t->template->ep_disconnect(conn); if (!redirected) { delay = session->def_time2wait; @@ -1677,6 +1684,26 @@ static void session_conn_recv_pdu(void *data) } } +static int session_ipc_create(struct iscsi_session *session) +{ + struct iscsi_conn *conn = &session->conn[0]; + int err = 0, kern_ep = 1; + uint32_t host_no = -1; + + if (session->t->template->ep_connect == iscsi_io_tcp_connect) + kern_ep = 0; + + err = ipc->create_session(session->t->handle, + kern_ep ? conn->transport_ep_handle : 0, + session->nrec.session.initial_cmdsn, + session->nrec.session.cmds_max, + session->nrec.session.queue_depth, + &session->id, &host_no); + if (!err) + session->hostno = host_no; + return err; +} + static void session_conn_poll(void *data) { struct iscsi_conn_context *conn_context = data; @@ -1712,18 +1739,13 @@ static void session_conn_poll(void *data) /* do not allocate new connection in case of reopen */ if (session->id == -1) { - if (conn->id == 0 && - ipc->create_session(session->t->handle, - session->nrec.session.initial_cmdsn, - session->nrec.session.cmds_max, - session->nrec.session.queue_depth, - &session->id, &session->hostno)) { + if (conn->id == 0 && session_ipc_create(session)) { log_error("can't create session (%d)", errno); err = MGMT_IPC_ERR_INTERNAL; goto cleanup; } - log_debug(3, "created new iSCSI session %d", - session->id); + log_debug(3, "created new iSCSI session sid %d host " + "no %u", session->id, session->hostno); if (ipc->create_conn(session->t->handle, session->id, conn->id, &conn->id)) { diff --git a/usr/iscsi_ipc.h b/usr/iscsi_ipc.h index 76c485f..74ef948 100644 --- a/usr/iscsi_ipc.h +++ b/usr/iscsi_ipc.h @@ -55,10 +55,10 @@ struct iscsi_ipc { int (*sendtargets) (uint64_t transport_handle, uint32_t host_no, struct sockaddr *addr); - int (*create_session) (uint64_t transport_handle, + int (*create_session) (uint64_t transport_handle, uint64_t ep_handle, uint32_t initial_cmdsn, uint16_t cmds_max, uint16_t qdepth, uint32_t *out_sid, - uint32_t *out_hostno); + uint32_t *hostno); int (*destroy_session) (uint64_t transport_handle, uint32_t sid); diff --git a/usr/iscsi_sysfs.c b/usr/iscsi_sysfs.c index aef766b..00514d3 100644 --- a/usr/iscsi_sysfs.c +++ b/usr/iscsi_sysfs.c @@ -303,6 +303,43 @@ free_buf: return host_no; } +/* TODO: merge and make macro */ +static int __get_host_no_from_netdev(void *data, struct host_info *info) +{ + struct host_info *ret_info = data; + + if (!strcmp(ret_info->iface.netdev, info->iface.netdev)) { + ret_info->host_no = info->host_no; + return 1; + } + return 0; +} + +static uint32_t get_host_no_from_netdev(char *netdev, int *rc) +{ + uint32_t host_no = -1; + struct host_info *info; + int nr_found, local_rc; + + *rc = 0; + + info = calloc(1, sizeof(*info)); + if (!info) { + *rc = ENOMEM; + return -1; + } + strcpy(info->iface.netdev, netdev); + + local_rc = sysfs_for_each_host(info, &nr_found, + __get_host_no_from_netdev); + if (local_rc == 1) + host_no = info->host_no; + else + *rc = ENODEV; + free(info); + return host_no; +} + static int __get_host_no_from_hwaddress(void *data, struct host_info *info) { struct host_info *ret_info = data; @@ -387,6 +424,9 @@ uint32_t get_host_no_from_iface(struct iface_rec *iface, int *rc) else if (strlen(iface->ipaddress) && strcasecmp(iface->ipaddress, DEFAULT_IPADDRESS)) host_no = get_host_no_from_ipaddress(iface->ipaddress, &tmp_rc); + else if(strlen(iface->netdev) && + strcasecmp(iface->netdev, DEFAULT_NETDEV)) + host_no = get_host_no_from_netdev(iface->netdev, &tmp_rc); else tmp_rc = EINVAL; diff --git a/usr/netlink.c b/usr/netlink.c index c9598a5..50f3e61 100644 --- a/usr/netlink.c +++ b/usr/netlink.c @@ -340,9 +340,9 @@ ksendtargets(uint64_t transport_handle, uint32_t host_no, struct sockaddr *addr) } static int -kcreate_session(uint64_t transport_handle, uint32_t initial_cmdsn, - uint16_t cmds_max, uint16_t qdepth, - uint32_t *out_sid, uint32_t *out_hostno) +kcreate_session(uint64_t transport_handle, uint64_t ep_handle, + uint32_t initial_cmdsn, uint16_t cmds_max, uint16_t qdepth, + uint32_t *out_sid, uint32_t *hostno) { int rc; struct iscsi_uevent ev; @@ -351,17 +351,26 @@ kcreate_session(uint64_t transport_handle, uint32_t initial_cmdsn, memset(&ev, 0, sizeof(struct iscsi_uevent)); - ev.type = ISCSI_UEVENT_CREATE_SESSION; - ev.transport_handle = transport_handle; - ev.u.c_session.initial_cmdsn = initial_cmdsn; - ev.u.c_session.cmds_max = cmds_max; - ev.u.c_session.queue_depth = qdepth; + if (ep_handle == 0) { + ev.type = ISCSI_UEVENT_CREATE_SESSION; + ev.transport_handle = transport_handle; + ev.u.c_session.initial_cmdsn = initial_cmdsn; + ev.u.c_session.cmds_max = cmds_max; + ev.u.c_session.queue_depth = qdepth; + } else { + ev.type = ISCSI_UEVENT_CREATE_BOUND_SESSION; + ev.transport_handle = transport_handle; + ev.u.c_bound_session.initial_cmdsn = initial_cmdsn; + ev.u.c_bound_session.cmds_max = cmds_max; + ev.u.c_bound_session.queue_depth = qdepth; + ev.u.c_bound_session.ep_handle = ep_handle; + } if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) { return rc; } - *out_hostno = ev.r.c_session_ret.host_no; + *hostno = ev.r.c_session_ret.host_no; *out_sid = ev.r.c_session_ret.sid; return 0; diff --git a/usr/transport.c b/usr/transport.c index 8fcc8c7..c2edbcc 100644 --- a/usr/transport.c +++ b/usr/transport.c @@ -28,7 +28,6 @@ struct iscsi_transport_template iscsi_tcp = { .name = "tcp", - .rdma = 0, .ep_connect = iscsi_io_tcp_connect, .ep_poll = iscsi_io_tcp_poll, .ep_disconnect = iscsi_io_tcp_disconnect, @@ -42,14 +41,21 @@ struct iscsi_transport_template iscsi_iser = { .ep_disconnect = ktransport_ep_disconnect, }; +struct iscsi_transport_template bnx2i = { + .name = "bnx2i", + .ep_connect = ktransport_ep_connect, + .ep_poll = ktransport_ep_poll, + .ep_disconnect = ktransport_ep_disconnect, +}; + struct iscsi_transport_template qla4xxx = { .name = "qla4xxx", - .rdma = 0, }; static struct iscsi_transport_template *iscsi_transport_templates[] = { &iscsi_tcp, &iscsi_iser, + &bnx2i, &qla4xxx, NULL }; |