diff --git a/include/iscsi_if.h b/include/iscsi_if.h index afa86e8..effd004 100644 --- a/include/iscsi_if.h +++ b/include/iscsi_if.h @@ -335,6 +335,10 @@ enum iscsi_host_param { #define CAP_FW_DB 0x200 #define CAP_SENDTARGETS_OFFLOAD 0x400 #define CAP_DATA_PATH_OFFLOAD 0x800 +#define CAP_DIGEST_OFFLOAD 0x1000 /* offload hdr and data digests */ +#define CAP_PADDING_OFFLOAD 0x2000 /* offload padding insertion, removal, + and verification */ +#define CAP_LOGIN_OFFLOAD 0x4000 /* offload normal session login */ /* * These flags describes reason of stop_conn() call diff --git a/usr/initiator.c b/usr/initiator.c index ada0301..87037a4 100644 --- a/usr/initiator.c +++ b/usr/initiator.c @@ -635,7 +635,7 @@ session_conn_shutdown(iscsi_conn_t *conn, queue_task_t *qtask, log_debug(2, "kdestroy conn"); if (ipc->destroy_conn(session->t->handle, session->id, - conn->id)) { + conn->id)) { log_error("can not safely destroy connection %d", conn->id); return MGMT_IPC_ERR_INTERNAL; } @@ -643,7 +643,14 @@ session_conn_shutdown(iscsi_conn_t *conn, queue_task_t *qtask, cleanup: if (session->id != -1) { log_debug(2, "kdestroy session %u", session->id); - if (ipc->destroy_session(session->t->handle, session->id)) { + session->r_stage = R_STAGE_SESSION_DESTOYED; + err = ipc->destroy_session(session->t->handle, session->id); + /* + * if a lld like ql4xxx initiated session removal then + * this should fail with EINVAL because the kernel's session + * has been removed by the LLD. + */ + if (err && err != -EINVAL) { log_error("can not safely destroy session %d", session->id); return MGMT_IPC_ERR_INTERNAL; @@ -920,6 +927,10 @@ __conn_error_handle(iscsi_session_t *session, iscsi_conn_t *conn) return; } + if (session->t->caps & CAP_LOGIN_OFFLOAD) + /* handled in kernel/firmware */ + return; + switch (conn->state) { case STATE_IN_LOGOUT: /* logout was from eh - fall down to cleanup */ @@ -953,8 +964,8 @@ __conn_error_handle(iscsi_session_t *session, iscsi_conn_t *conn) if (session->r_stage == R_STAGE_SESSION_REOPEN) { queue_task_t *qtask; - if (session->sync_qtask) - qtask = session->sync_qtask; + if (session->notify_qtask) + qtask = session->notify_qtask; else qtask = &session->reopen_qtask; iscsi_login_eh(conn, qtask, MGMT_IPC_ERR_TRANS_FAILURE); @@ -1178,11 +1189,9 @@ mgmt_ipc_err_e iscsi_host_set_param(int host_no, int param, char *value) #define MAX_SESSION_PARAMS 31 #define MAX_HOST_PARAMS 3 -static void -setup_full_feature_phase(iscsi_conn_t *conn) +static int iscsi_set_params(struct iscsi_conn *conn) { - iscsi_session_t *session = conn->session; - iscsi_login_context_t *c = &conn->login_context; + struct iscsi_session *session = conn->session; int i, rc; uint32_t one = 1, zero = 0; struct hostparam { @@ -1370,8 +1379,6 @@ setup_full_feature_phase(iscsi_conn_t *conn) }, }; - 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; @@ -1382,16 +1389,8 @@ setup_full_feature_phase(iscsi_conn_t *conn) 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 && rc != -ENOSYS) + return rc; if (rc == -ENOSYS) { switch (conntbl[i].param) { @@ -1417,17 +1416,33 @@ setup_full_feature_phase(iscsi_conn_t *conn) 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; - } + rc = __iscsi_host_set_param(session->t, session->hostno, + hosttbl[i].param, hosttbl[i].value, + hosttbl[i].type); + if (rc) + return rc; print_param_value(hosttbl[i].param, hosttbl[i].value, hosttbl[i].type); } + return 0; +} + +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 rc; + + rc = iscsi_set_params(conn); + if (rc) { + log_error("can't set operational parameter " + "connection %d:%d, retcode %d", session->id, + conn->id, rc); + iscsi_login_eh(conn, c->qtask, MGMT_IPC_ERR_LOGIN_FAILURE); + return; + } if (ipc->start_conn(session->t->handle, session->id, conn->id, &rc) || rc) { @@ -1450,7 +1465,7 @@ setup_full_feature_phase(iscsi_conn_t *conn) log_warning("connection%d:%d is operational now", session->id, conn->id); } else { - session->sync_qtask = NULL; + session->notify_qtask = NULL; session_online_devs(session->hostno, session->id); mgmt_ipc_write_rsp(c->qtask, MGMT_IPC_OK); @@ -1530,8 +1545,10 @@ static void iscsi_stop(void *data) iscsi_conn_context_put(conn_context); - if (!iscsi_send_logout(conn)) - return; + if (!(conn->session->t->caps & CAP_LOGIN_OFFLOAD)) { + if (!iscsi_send_logout(conn)) + return; + } rc = session_conn_shutdown(conn, conn->logout_qtask, MGMT_IPC_OK); if (rc) @@ -1815,10 +1832,12 @@ static void session_conn_poll(void *data) 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)) { + err = ipc->create_conn(session->t->handle, + session->id, conn->id, + &conn->id); + if (err) { log_error("can't create connection (%d)", - errno); + err); err = MGMT_IPC_ERR_INTERNAL; goto cleanup; } @@ -1873,6 +1892,67 @@ cleanup: session_conn_shutdown(conn, qtask, err); } +/* + * HW drivers like qla4xxx present a interface that hides most of the iscsi + * details. Userspace sends down a discovery event then it gets notified + * if the sessions that were logged in as a result asynchronously, or + * the card will have sessions preset in the FLASH and will log into them + * automatically then send us notification that a session is setup. + */ +static void iscsi_session_created(void *data) +{ + struct iscsi_conn_context *conn_context = data; + struct iscsi_conn *conn = conn_context->conn; + struct iscsi_session *session = conn->session; + queue_task_t *qtask; + + iscsi_conn_context_put(conn_context); + + if (!(session->t->caps & CAP_LOGIN_OFFLOAD)) + return; + + if (conn->state != STATE_IN_LOGIN) + /* just a notification that the session struct was created */ + return; + conn->state = STATE_LOGGED_IN; + /* + * ok we were in_login and now we got the notification that we are + * logged in + */ + log_debug(3, "session created sid %u host no %d", session->id, + session->hostno); + qtask = session->notify_qtask; + session->notify_qtask = NULL; + session_scan_host(session->hostno, qtask); + session_online_devs(session->hostno, session->id); +} + +static void iscsi_session_destroyed(void *data) +{ + struct iscsi_conn_context *conn_context = data; + struct iscsi_conn *conn = conn_context->conn; + struct iscsi_session *session = conn->session; + + iscsi_conn_context_put(conn_context); + + if (session->r_stage == R_STAGE_SESSION_DESTOYED) + /* + * session destruction was initiated by iscsid so we can + * ignore this + */ + return; + + /* + * session destruction was completed by kernel so we must clean + * up iscsid bits. + */ + log_debug(3, "session destroyed sid %u host no %d", session->id, + session->hostno); + + if (session_conn_shutdown(conn, NULL, MGMT_IPC_OK)) + log_error("BUG: Could not shutdown session."); +} + void iscsi_sched_conn_context(struct iscsi_conn_context *conn_context, struct iscsi_conn *conn, unsigned long tmo, int event) @@ -1882,6 +1962,16 @@ void iscsi_sched_conn_context(struct iscsi_conn_context *conn_context, conn_context->conn = conn; switch (event) { + case EV_SESSION_CREATED: + actor_new(&conn_context->actor, iscsi_session_created, + conn_context); + actor_schedule(&conn_context->actor); + break; + case EV_SESSION_DESTROYED: + actor_new(&conn_context->actor, iscsi_session_destroyed, + conn_context); + actor_schedule(&conn_context->actor); + break; case EV_CONN_RECV_PDU: actor_new(&conn_context->actor, session_conn_recv_pdu, conn_context); @@ -2006,12 +2096,104 @@ static int iface_set_param(struct iscsi_transport *t, struct iface_rec *iface, return 0; } -int -session_login_task(node_rec_t *rec, queue_task_t *qtask) +static int iscsi_sw_session_login(struct node_rec *rec, queue_task_t *qtask, + struct iscsi_session *session) +{ + struct iscsi_conn *conn = &session->conn[0]; + + if (iface_set_param(session->t, &rec->iface, session)) + return MGMT_IPC_ERR_LOGIN_FAILURE; + + conn->state = STATE_XPT_WAIT; + if (iscsi_conn_connect(conn, qtask)) + return MGMT_IPC_ERR_TRANS_FAILURE; + + 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."); + + qtask->rsp.command = MGMT_IPC_SESSION_LOGIN; + qtask->rsp.err = MGMT_IPC_OK; + return MGMT_IPC_OK; +} + +static int iscsi_hw_session_login(struct node_rec *rec, queue_task_t *qtask, + struct iscsi_session *session) +{ + struct iscsi_conn *conn = &session->conn[0]; + int err = 0, rc = 0; + uint32_t host_no, host_no_ret; + + host_no = iscsi_sysfs_get_host_no_from_hwinfo(&rec->iface, &err); + if (rc) { + log_error("Could not get host no for iface %s.\n", + rec->iface.name); + return MGMT_IPC_ERR_LOGIN_FAILURE; + } + log_debug(2, "match iface %s to hostno %u\n", rec->iface.name, + host_no); + + conn->state = STATE_XPT_WAIT; + err = ipc->create_session(session->t->handle, host_no, 0, + session->nrec.session.cmds_max, + session->nrec.session.queue_depth, + &session->id, &host_no_ret); + if (err) { + log_error("Could not create hw session (err %d).\n", err); + return MGMT_IPC_ERR_LOGIN_FAILURE; + } + + if (host_no_ret != host_no) + log_error("Host no mismatch got %u. Expected %u.\n", + host_no_ret, host_no); + session->hostno = host_no_ret; + + err = ipc->create_conn(session->t->handle, session->id, conn->id, + &conn->id); + if (err) { + log_error("Can't create connection (%d)", err); + err = MGMT_IPC_ERR_INTERNAL; + goto destroy_kern_session; + } + log_debug(3, "created new iSCSI connection " + "%d:%d", session->id, conn->id); + + iscsi_copy_operational_params(conn); + iscsi_set_params(conn); + + /* + * This only starts the login process. The kernel/firmware + * will notify us when it is complete. + */ + conn->state = STATE_IN_LOGIN; + err = ipc->start_conn(session->t->handle, session->id, conn->id, &rc); + if (err || rc) { + log_error("can't start connection %d:%d retcode %d.", + session->id, conn->id, rc); + goto destroy_kern_conn; + } + + session->notify_qtask = qtask; + qtask->rsp.command = MGMT_IPC_SESSION_LOGIN; + qtask->rsp.err = MGMT_IPC_OK; + return MGMT_IPC_OK; + +destroy_kern_conn: + if (ipc->destroy_conn(session->t->handle, session->id, conn->id)) + log_error("can not safely destroy connection %d", conn->id); +destroy_kern_session: + if (ipc->destroy_session(session->t->handle, session->id)) + log_error("can not safely destroy session %d", + session->id); + return err; +} + +int iscsi_session_login_task(node_rec_t *rec, queue_task_t *qtask) { - iscsi_session_t *session; - iscsi_conn_t *conn; struct iscsi_transport *t; + struct iscsi_session *session; + int err; if (session_is_running(rec)) { log_error("session [%s,%s,%d] already running.", rec->name, @@ -2036,7 +2218,7 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask) } if (!(t->caps & CAP_MULTI_R2T) && - rec->session.iscsi.MaxOutstandingR2T) { + rec->session.iscsi.MaxOutstandingR2T > 1) { log_error("Transport '%s' does not support " "MaxOutstandingR2T %d. Setting " "MaxOutstandingR2T to 1.", t->name, @@ -2078,35 +2260,23 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask) if (!session) return MGMT_IPC_ERR_LOGIN_FAILURE; - /* FIXME: login all connections! marked as "automatic" */ - /* create leading connection */ if (__session_conn_create(session, 0)) { - __session_destroy(session); - return MGMT_IPC_ERR_LOGIN_FAILURE; - } - conn = &session->conn[0]; - qtask->conn = conn; - - if (iface_set_param(t, &rec->iface, session)) { - __session_destroy(session); - return MGMT_IPC_ERR_LOGIN_FAILURE; - } - - conn->state = STATE_XPT_WAIT; - if (iscsi_conn_connect(conn, qtask)) { - __session_destroy(session); - return MGMT_IPC_ERR_TRANS_FAILURE; + err = MGMT_IPC_ERR_LOGIN_FAILURE; + goto destroy_session; } + qtask->conn = &session->conn[0]; - 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."); + if (t->caps & CAP_LOGIN_OFFLOAD) + err = iscsi_hw_session_login(rec, qtask, session); + else + err = iscsi_sw_session_login(rec, qtask, session); + if (err == MGMT_IPC_OK) + return MGMT_IPC_OK; - qtask->rsp.command = MGMT_IPC_SESSION_LOGIN; - qtask->rsp.err = MGMT_IPC_OK; - return MGMT_IPC_OK; +destroy_session: + __session_destroy(session); + return err; } static int @@ -2158,12 +2328,22 @@ iscsi_sync_session(node_rec_t *rec, queue_task_t *qtask, uint32_t sid) err = MGMT_IPC_ERR_INVAL; goto destroy_session; } - - session->sync_qtask = qtask; qtask->rsp.command = MGMT_IPC_SESSION_SYNC; - - session_conn_reopen(&session->conn[0], qtask, STOP_CONN_RECOVER); log_debug(3, "Started sync iSCSI session %d", session->id); + + if (session->t->caps & CAP_LOGIN_OFFLOAD) { + struct iscsi_conn *conn = &session->conn[0]; + /* + * this is broken because it assumes we completed the + * initial setup/login + */ + session->r_stage = R_STAGE_NO_CHANGE; + conn->state = STATE_LOGGED_IN; + session_scan_host(session->hostno, qtask); + } else { + session->notify_qtask = qtask; + session_conn_reopen(&session->conn[0], qtask, STOP_CONN_RECOVER); + } return 0; destroy_session: @@ -2200,7 +2380,7 @@ session_logout_task(int sid, queue_task_t *qtask) * If syncing up or if this is the initial login and mgmt_ipc * has not been notified of that result fail the logout request */ - if (session->sync_qtask || + if (session->notify_qtask || ((conn->state == STATE_XPT_WAIT || conn->state == STATE_IN_LOGIN) && (session->r_stage == R_STAGE_NO_CHANGE || @@ -2213,7 +2393,6 @@ invalid_state: /* FIXME: logout all active connections */ conn = &session->conn[0]; - /* FIXME: implement Logout Request */ if (conn->logout_qtask) goto invalid_state; @@ -2226,9 +2405,14 @@ invalid_state: if (!session_unbind(session)) return MGMT_IPC_OK; - /* unbind is not supported so just do old logout */ - if (!iscsi_send_logout(conn)) - return MGMT_IPC_OK; + /* + * LLDs that offload login also offload logout + */ + if (!(session->t->caps & CAP_LOGIN_OFFLOAD)) { + /* unbind is not supported so just do old logout */ + if (!iscsi_send_logout(conn)) + return MGMT_IPC_OK; + } log_error("Could not send logout pdu. Dropping session\n"); /* fallthrough */ default: @@ -2258,31 +2442,3 @@ iscsi_host_send_targets(queue_task_t *qtask, int host_no, int do_login, return MGMT_IPC_OK; } - -/* - * HW drivers like qla4xxx present a interface that hides most of the iscsi - * details. Userspace sends down a discovery event then it gets notified - * if the sessions that were logged in as a result asynchronously, or - * 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) -{ - struct iscsi_transport *transport; - - transport = iscsi_sysfs_get_transport_by_hba(host_no); - if (!transport) - return; - - if (!(transport->caps & CAP_FW_DB)) - return; - - log_debug(3, "session created sid %u host no %d", sid, host_no); - session_online_devs(host_no, sid); - session_scan_host(host_no, NULL); -} - -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); -} diff --git a/usr/initiator.h b/usr/initiator.h index 682ebfc..b73aa3c 100644 --- a/usr/initiator.h +++ b/usr/initiator.h @@ -58,6 +58,7 @@ typedef enum iscsi_session_r_stage_e { R_STAGE_SESSION_CLEANUP, R_STAGE_SESSION_REOPEN, R_STAGE_SESSION_REDIRECT, + R_STAGE_SESSION_DESTOYED, } iscsi_session_r_stage_e; typedef enum conn_login_status_e { @@ -88,6 +89,8 @@ typedef enum iscsi_event_e { EV_CONN_ERROR, EV_CONN_LOGOUT_TIMER, EV_CONN_STOP, + EV_SESSION_CREATED, + EV_SESSION_DESTROYED, } iscsi_event_e; struct queue_task; @@ -254,8 +257,11 @@ typedef struct iscsi_session { int lu_reset_timeout; int abort_timeout; - /* sync up fields */ - queue_task_t *sync_qtask; + /* + * used for hw and sync up to notify called that the operation + * is complete + */ + queue_task_t *notify_qtask; } iscsi_session_t; /* login.c */ @@ -326,7 +332,7 @@ extern int iscsi_io_recv_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, int timeout); /* initiator.c */ -extern int session_login_task(node_rec_t *rec, queue_task_t *qtask); +extern int iscsi_session_login_task(node_rec_t *rec, queue_task_t *qtask); extern int session_logout_task(int sid, queue_task_t *qtask); extern iscsi_session_t *session_find_by_sid(int sid); extern struct iscsi_conn_context *iscsi_conn_context_get(iscsi_conn_t *conn, @@ -340,8 +346,6 @@ extern mgmt_ipc_err_e iscsi_sync_session(node_rec_t *rec, queue_task_t extern mgmt_ipc_err_e iscsi_host_send_targets(queue_task_t *qtask, int host_no, int do_login, struct sockaddr_storage *ss); extern mgmt_ipc_err_e iscsi_host_set_param(int host_no, int param, char *value); -extern void iscsi_async_session_creation(uint32_t host_no, uint32_t sid); -extern void iscsi_async_session_destruction(uint32_t host_no, uint32_t sid); extern void free_initiator(void); /* isns.c */ diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c index bec9a4d..4ddeaff 100644 --- a/usr/iscsiadm.c +++ b/usr/iscsiadm.c @@ -518,15 +518,6 @@ logout_portal(void *data, struct list_head *list, struct session_info *info) if (!iscsi_match_session(pattern_rec, info)) return -1; - /* we do not support this yet */ - if (t->caps & CAP_FW_DB) { - log_error("Could not logout session [sid: %d, " - "target: %s, portal: %s,%d]", info->sid, - info->targetname, info->persistent_address, - info->port); - log_error("Logout not supported for driver: %s.", t->name); - return -1; - } return __logout_portal(info, list); } @@ -1253,7 +1244,7 @@ do_sendtargets(discovery_rec_t *drec, struct list_head *ifaces, /* try software iscsi */ continue; } - +/* t = iscsi_sysfs_get_transport_by_hba(host_no); if (!t) { log_error("Could not match hostno %d to " @@ -1271,6 +1262,7 @@ do_sendtargets(discovery_rec_t *drec, struct list_head *ifaces, list_del(&iface->list); free(iface); } +*/ } if (list_empty(ifaces)) diff --git a/usr/iscsid.c b/usr/iscsid.c index 63dbf77..6a02d8d 100644 --- a/usr/iscsid.c +++ b/usr/iscsid.c @@ -190,24 +190,6 @@ static int sync_session(void *data, struct session_info *info) if (!t) return 0; - /* - * Just rescan the device in case this is the first startup. - * (TODO: should do this async and check for state). - */ - if (t->caps & CAP_FW_DB) { - uint32_t host_no; - int err; - - host_no = iscsi_sysfs_get_host_no_from_sid(info->sid, &err); - if (err) { - log_error("Could not get host no from sid %u. Can not " - "sync session. Error %d", info->sid, err); - return 0; - } - iscsi_sysfs_scan_host(host_no, 0); - return 0; - } - memset(&rec, 0, sizeof(node_rec_t)); if (idbm_rec_read(&rec, info->targetname, info->tpgt, info->persistent_address, info->persistent_port, diff --git a/usr/mgmt_ipc.c b/usr/mgmt_ipc.c index 7520c80..738ed05 100644 --- a/usr/mgmt_ipc.c +++ b/usr/mgmt_ipc.c @@ -84,7 +84,7 @@ mgmt_ipc_close(int fd) static mgmt_ipc_err_e mgmt_ipc_session_login(queue_task_t *qtask) { - return session_login_task(&qtask->req.u.session.rec, qtask); + return iscsi_session_login_task(&qtask->req.u.session.rec, qtask); } static mgmt_ipc_err_e diff --git a/usr/netlink.c b/usr/netlink.c index 9172259..be979c7 100644 --- a/usr/netlink.c +++ b/usr/netlink.c @@ -284,7 +284,7 @@ __kipc_call(void *iov_base, int iov_len) /* not fatal so let caller handle log */ log_debug(1, "Recieved iferror %d: %s", ev->iferror, - strerror(ev->iferror)); + strerror(-ev->iferror)); else if (ev->iferror < 0) log_error("Received iferror %d: %s", ev->iferror, @@ -895,7 +895,7 @@ static int ctldev_handle(void) char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))]; struct nlmsghdr *nlh; struct iscsi_conn_context *conn_context; - uint32_t sid = 0, cid = 0; + uint32_t sid = 0, cid = 0, host_no = -1; log_debug(7, "in %s", __FUNCTION__); @@ -913,15 +913,13 @@ static int ctldev_handle(void) case ISCSI_KEVENT_CREATE_SESSION: /* old kernels sent ISCSI_UEVENT_CREATE_SESSION on creation */ case ISCSI_UEVENT_CREATE_SESSION: - drop_data(nlh); - iscsi_async_session_creation(ev->r.c_session_ret.host_no, - ev->r.c_session_ret.sid); - return 0; + sid = ev->r.c_session_ret.sid; + host_no = ev->r.c_session_ret.host_no; + break; case ISCSI_KEVENT_DESTROY_SESSION: - drop_data(nlh); - iscsi_async_session_destruction(ev->r.d_session.host_no, - ev->r.d_session.sid); - return 0; + sid = ev->r.d_session.sid; + host_no = ev->r.d_session.host_no; + break; case ISCSI_KEVENT_RECV_PDU: sid = ev->r.recv_req.sid; cid = ev->r.recv_req.cid; @@ -972,6 +970,15 @@ static int ctldev_handle(void) * into ctldev_handle */ switch (ev->type) { + case ISCSI_KEVENT_CREATE_SESSION: + case ISCSI_UEVENT_CREATE_SESSION: + iscsi_sched_conn_context(conn_context, conn, 0, + EV_SESSION_CREATED); + break; + case ISCSI_KEVENT_DESTROY_SESSION: + iscsi_sched_conn_context(conn_context, conn, 0, + EV_SESSION_DESTROYED); + break; case ISCSI_KEVENT_RECV_PDU: iscsi_sched_conn_context(conn_context, conn, 0, EV_CONN_RECV_PDU); diff --git a/usr/transport.c b/usr/transport.c index 07b61db..57fc767 100644 --- a/usr/transport.c +++ b/usr/transport.c @@ -26,6 +26,21 @@ #include "util.h" #include "iscsi_sysfs.h" +static int null_ep_connect(struct iscsi_conn *conn, int non_blocking) +{ + return 0; +} + +static int null_ep_poll(struct iscsi_conn *conn, int timeout_ms) +{ + return 0; +} + +static void null_ep_disconnect(struct iscsi_conn *conn) +{ + return; +} + struct iscsi_transport_template iscsi_tcp = { .name = "tcp", .ep_connect = iscsi_io_tcp_connect, @@ -57,6 +72,9 @@ struct iscsi_transport_template bnx2i = { struct iscsi_transport_template qla4xxx = { .name = "qla4xxx", + .ep_connect = null_ep_connect, + .ep_poll = null_ep_poll, + .ep_disconnect = null_ep_disconnect, }; static struct iscsi_transport_template *iscsi_transport_templates[] = {