summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-05-19 21:20:44 -0500
committerMike Christie <michaelc@cs.wisc.edu>2008-05-19 21:20:44 -0500
commit74489b2eb9f3c5d96c64f859de965cff10bb457f (patch)
treeb1adea6e5d1ae796fd79992a9e13faa46a02ea5d
parentdc75ff01ee126dbde42d4f2fe975c17e25719cf9 (diff)
downloadopen-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.example2
-rw-r--r--include/iscsi_if.h7
-rw-r--r--usr/initiator.c58
-rw-r--r--usr/iscsi_ipc.h4
-rw-r--r--usr/iscsi_sysfs.c40
-rw-r--r--usr/netlink.c27
-rw-r--r--usr/transport.c10
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
};