Author: mav
Date: Mon Jul  7 05:48:11 2014
New Revision: 268356
URL: http://svnweb.freebsd.org/changeset/base/268356

Log:
  When new connection comes in, check whether we already have session from
  the same intiator (Name+ISID).  If so -- terminate the old session and let
  the new one take its place, as required by iSCSI RFC.

Modified:
  head/sys/cam/ctl/ctl_frontend_iscsi.c
  head/sys/cam/ctl/ctl_frontend_iscsi.h

Modified: head/sys/cam/ctl/ctl_frontend_iscsi.c
==============================================================================
--- head/sys/cam/ctl/ctl_frontend_iscsi.c       Mon Jul  7 05:31:50 2014        
(r268355)
+++ head/sys/cam/ctl/ctl_frontend_iscsi.c       Mon Jul  7 05:48:11 2014        
(r268356)
@@ -1087,7 +1087,8 @@ cfiscsi_session_terminate_tasks(struct c
                        break;
                CFISCSI_SESSION_WARN(cs, "waiting for CTL to terminate tasks, "
                    "%d remaining", cs->cs_outstanding_ctl_pdus);
-               pause("cfiscsi_terminate", hz / 100);
+               tsleep(__DEVOLATILE(void *, &cs->cs_outstanding_ctl_pdus),
+                   0, "cfiscsi_terminate", hz / 100);
        }
 }
 
@@ -1404,7 +1405,7 @@ static void
 cfiscsi_ioctl_handoff(struct ctl_iscsi *ci)
 {
        struct cfiscsi_softc *softc;
-       struct cfiscsi_session *cs;
+       struct cfiscsi_session *cs, *cs2;
        struct cfiscsi_target *ct;
        struct ctl_iscsi_handoff_params *cihp;
        int error;
@@ -1500,12 +1501,34 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *
            cihp->initiator_isid[2], cihp->initiator_isid[3],
            cihp->initiator_isid[4], cihp->initiator_isid[5]);
 
+       refcount_acquire(&cs->cs_outstanding_ctl_pdus);
+restart:
+       if (!cs->cs_terminating) {
+               mtx_lock(&softc->lock);
+               TAILQ_FOREACH(cs2, &softc->sessions, cs_next) {
+                       if (cs2 != cs && cs2->cs_tasks_aborted == false &&
+                           strcmp(cs->cs_initiator_id, cs2->cs_initiator_id) 
== 0) {
+                               cfiscsi_session_terminate(cs2);
+                               mtx_unlock(&softc->lock);
+                               pause("cfiscsi_reinstate", 1);
+                               goto restart;
+                       }
+               }
+               mtx_unlock(&softc->lock);
+       }
+
+       /*
+        * Register initiator with CTL.
+        */
+       cfiscsi_session_register_initiator(cs);
+
 #ifdef ICL_KERNEL_PROXY
        if (cihp->socket > 0) {
 #endif
                error = icl_conn_handoff(cs->cs_conn, cihp->socket);
                if (error != 0) {
-                       cfiscsi_session_delete(cs);
+                       cfiscsi_session_terminate(cs);
+                       refcount_release(&cs->cs_outstanding_ctl_pdus);
                        ci->status = CTL_ISCSI_ERROR;
                        snprintf(ci->error_str, sizeof(ci->error_str),
                            "%s: icl_conn_handoff failed with error %d",
@@ -1516,11 +1539,6 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *
        }
 #endif
 
-       /*
-        * Register initiator with CTL.
-        */
-       cfiscsi_session_register_initiator(cs);
-
 #ifdef ICL_KERNEL_PROXY
        cs->cs_login_phase = false;
 
@@ -1535,6 +1553,7 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *
        }
 #endif
 
+       refcount_release(&cs->cs_outstanding_ctl_pdus);
        ci->status = CTL_ISCSI_OK;
 }
 
@@ -2833,7 +2852,9 @@ cfiscsi_done(union ctl_io *io)
                 * Implicit task termination has just completed; nothing to do.
                 */
                cs = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
+               cs->cs_tasks_aborted = true;
                refcount_release(&cs->cs_outstanding_ctl_pdus);
+               wakeup(__DEVOLATILE(void *, &cs->cs_outstanding_ctl_pdus));
                ctl_free_io(io);
                return;
        }

Modified: head/sys/cam/ctl/ctl_frontend_iscsi.h
==============================================================================
--- head/sys/cam/ctl/ctl_frontend_iscsi.h       Mon Jul  7 05:31:50 2014        
(r268355)
+++ head/sys/cam/ctl/ctl_frontend_iscsi.h       Mon Jul  7 05:48:11 2014        
(r268356)
@@ -80,6 +80,7 @@ struct cfiscsi_session {
        int                             cs_portal_group_tag;
        struct cv                       cs_maintenance_cv;
        bool                            cs_terminating;
+       bool                            cs_tasks_aborted;
        size_t                          cs_max_data_segment_length;
        size_t                          cs_max_burst_length;
        bool                            cs_immediate_data;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to