Hey Dave,

In the qla4xxx branch of the iscsi git tree I added code so that 
iscsiadm can control sessions that are accessed through qla4xxx.

The patches are here:
http://git.kernel.org/?p=linux/kernel/git/mnc/linux-2.6-iscsi.git;a=commit;h=f95246f8e84a12267e3c9e811a94004f598ef285
http://git.kernel.org/?p=linux/kernel/git/mnc/linux-2.6-iscsi.git;a=commit;h=ea4d8306487fca1b601a2ef69a85951b19843382
http://git.kernel.org/?p=linux/kernel/git/mnc/linux-2.6-iscsi.git;a=commit;h=4320dc0e234368620b40c155d571e8c46b814216
http://git.kernel.org/?p=linux/kernel/git/mnc/linux-2.6-iscsi.git;a=commit;h=76ed2193986e9910fd695c881ae1cb08e35feb1c

I was not sure what I was doing exactly :) since I was going by the 
qlogic.com driver ioctl code, so if you could take a look at
http://git.kernel.org/?p=linux/kernel/git/mnc/linux-2.6-iscsi.git;a=commit;h=ea4d8306487fca1b601a2ef69a85951b19843382
and check if I am interacting with the hardware correctly it would be 
nice.  Specifically I am worried about qla4xxx_session_logout_ddb and 
qla4xxx_session_login_ddb.

If you want to run this then you also need the userspace patch that is 
attached. It should apply to the open-iscsi git head.

To start remove the persistent targets in your FLASH since we will use 
the iscsd db instead (note that for boot and root you can have targets 
in flash and the drivers/firmware auto login will work but you just 
cannot use iscsiadm to login/logout).

To run login/logout then just build the code, modprobe qla4xxx and start 
iscsid. Then you need to do discovery

./iscsiadm -m iface -P 3

will display the different ifaces like this:

Iface: iface0
        Iface Name: iface0
        Iface Transport: qla4xxx
        Iface Initiatorname: unknown
        Iface IPaddress: unknown
        Iface HWaddress: 00:c0:dd:08:63:e8
        Iface Netdev: unknown
        Host Number: 20 State: running
Iface: iface1
        Iface Name: iface1
        Iface Transport: qla4xxx
        Iface Initiatorname: unknown
        Iface IPaddress: unknown
        Iface HWaddress: 00:c0:dd:08:63:ea
        Iface Netdev: unknown
        Host Number: 21 State: running

For this I am going to use the one with mac 00:c0:dd:08:63:e8 (iface0)


./iscsiadm -m discovery -t st -p max -I iface0 -P 1
     Target: iqn.2001-04.com.max.1
         Portal: 20.15.0.4:3260,1
            Iface Name: iface0
     Target: iqn.2001-04.com.max.2
         Portal: 20.15.0.4:3260,1
            Iface Name: iface0
     Target: iqn.2001-04.com.max.3
         Portal: 20.15.0.4:3260,1
            Iface Name: iface0


Then I will log in:

./iscsiadm -m node -T iqn.2001-04.com.max.3 -l

(you can also pass in the portal if you have multiple portals on a 
target and only want to log into one).

You should then see a error or a login ok message.

You can then do

./iscsiadm -m session -P 3

to see some values (I also added code to be able to set the segment 
limtis and max r2ts (does qla4xxx firmware support more than 1 btw.

And then to logout do

./iscsiadm -m node T iqn.2001-04.com.max.3 -u


and you should get a error or a ok message.

Note that you cannot control sessions that are the persistent in the 
firmware/flash. So if you have targets in FLASH then the iscsiadm logout 
and login commands are not supported. qla4xxx will still log into them 
and find disks so that boot and / work, but you cannot login/logout with 
iscsiadm (you actually can if you have targets setup in FLASH, then load 
the module, then start iscsid, but that is by accident).


Some questions on qlogic hardware:

- How do you set CHAP settings for each target?

- How do you set Data/Header digests settings?

- Currently for iscsiadm -m disocvery .... you need a seperate NIC. It 
does not go through the card. Is there a way to ask the card to do 
sendtargets and then just have it tell us what targets were found (I do 
not want the card to login).

Can I just send a discovery session login pdu and sendtargets command in 
a passthrough interface, and then get back raw pdus?

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to open-iscsi@googlegroups.com
To unsubscribe from this group, send email to 
open-iscsi+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/open-iscsi
-~----------~----~----~----~------~----~------~--~---

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[] = {

Reply via email to