Author: trasz
Date: Wed Apr 16 17:39:10 2014
New Revision: 264544
URL: http://svnweb.freebsd.org/changeset/base/264544

Log:
  Add kern.iscsi.fail_on_disconnection; this is required for gmultipath
  to work.
  
  Sponsored by: The FreeBSD Foundation

Modified:
  head/sys/dev/iscsi/iscsi.c

Modified: head/sys/dev/iscsi/iscsi.c
==============================================================================
--- head/sys/dev/iscsi/iscsi.c  Wed Apr 16 17:12:59 2014        (r264543)
+++ head/sys/dev/iscsi/iscsi.c  Wed Apr 16 17:39:10 2014        (r264544)
@@ -97,6 +97,10 @@ static int maxtags = 255;
 TUNABLE_INT("kern.iscsi.maxtags", &maxtags);
 SYSCTL_INT(_kern_iscsi, OID_AUTO, maxtags, CTLFLAG_RWTUN, &maxtags,
     0, "Max number of IO requests queued");
+static int fail_on_disconnection = 0;
+TUNABLE_INT("kern.iscsi.fail_on_disconnection", &fail_on_disconnection);
+SYSCTL_INT(_kern_iscsi, OID_AUTO, fail_on_disconnection, CTLFLAG_RWTUN,
+    &fail_on_disconnection, 0, "Destroy CAM SIM on connection failure");
 
 static MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI initiator");
 static uma_zone_t iscsi_outstanding_zone;
@@ -301,22 +305,11 @@ iscsi_session_terminate_tasks(struct isc
 }
 
 static void
-iscsi_maintenance_thread_reconnect(struct iscsi_session *is)
+iscsi_session_cleanup(struct iscsi_session *is, bool destroy_sim)
 {
        struct icl_pdu *pdu;
 
-       icl_conn_shutdown(is->is_conn);
-       icl_conn_close(is->is_conn);
-
-       ISCSI_SESSION_LOCK(is);
-
-#ifdef ICL_KERNEL_PROXY
-       if (is->is_login_pdu != NULL) {
-               icl_pdu_free(is->is_login_pdu);
-               is->is_login_pdu = NULL;
-       }
-       cv_signal(&is->is_login_cv);
-#endif
+       ISCSI_SESSION_LOCK_ASSERT(is);
 
        /*
         * Don't queue any new PDUs.
@@ -336,12 +329,63 @@ iscsi_maintenance_thread_reconnect(struc
                icl_pdu_free(pdu);
        }
 
-       /*
-        * Terminate SCSI tasks, asking CAM to requeue them.
-        */
-       //ISCSI_SESSION_DEBUG(is, "terminating tasks");
-       iscsi_session_terminate_tasks(is, true);
+       if (destroy_sim == false) {
+               /*
+                * Terminate SCSI tasks, asking CAM to requeue them.
+                */
+               iscsi_session_terminate_tasks(is, true);
+               return;
+       }
+
+       iscsi_session_terminate_tasks(is, false);
 
+       if (is->is_sim == NULL)
+               return;
+
+       ISCSI_SESSION_DEBUG(is, "deregistering SIM");
+       xpt_async(AC_LOST_DEVICE, is->is_path, NULL);
+
+       if (is->is_simq_frozen) {
+               xpt_release_simq(is->is_sim, 1);
+               is->is_simq_frozen = false;
+       }
+
+       xpt_free_path(is->is_path);
+       is->is_path = NULL;
+       xpt_bus_deregister(cam_sim_path(is->is_sim));
+       cam_sim_free(is->is_sim, TRUE /*free_devq*/);
+       is->is_sim = NULL;
+       is->is_devq = NULL;
+}
+
+static void
+iscsi_maintenance_thread_reconnect(struct iscsi_session *is)
+{
+
+       icl_conn_shutdown(is->is_conn);
+       icl_conn_close(is->is_conn);
+
+       ISCSI_SESSION_LOCK(is);
+
+       is->is_connected = false;
+       is->is_reconnecting = false;
+       is->is_login_phase = false;
+
+#ifdef ICL_KERNEL_PROXY
+       if (is->is_login_pdu != NULL) {
+               icl_pdu_free(is->is_login_pdu);
+               is->is_login_pdu = NULL;
+       }
+       cv_signal(&is->is_login_cv);
+#endif
+ 
+       if (fail_on_disconnection) {
+               ISCSI_SESSION_DEBUG(is, "connection failed, destroying 
devices");
+               iscsi_session_cleanup(is, true);
+       } else {
+               iscsi_session_cleanup(is, false);
+       }
+ 
        KASSERT(TAILQ_EMPTY(&is->is_outstanding),
            ("destroying session with active tasks"));
        KASSERT(STAILQ_EMPTY(&is->is_postponed),
@@ -351,9 +395,6 @@ iscsi_maintenance_thread_reconnect(struc
         * Request immediate reconnection from iscsid(8).
         */
        //ISCSI_SESSION_DEBUG(is, "waking up iscsid(8)");
-       is->is_connected = false;
-       is->is_reconnecting = false;
-       is->is_login_phase = false;
        is->is_waiting_for_iscsid = true;
        strlcpy(is->is_reason, "Waiting for iscsid(8)", sizeof(is->is_reason));
        is->is_timeout = 0;
@@ -365,7 +406,6 @@ static void
 iscsi_maintenance_thread_terminate(struct iscsi_session *is)
 {
        struct iscsi_softc *sc;
-       struct icl_pdu *pdu;
 
        sc = is->is_softc;
        sx_xlock(&sc->sc_lock);
@@ -386,48 +426,9 @@ iscsi_maintenance_thread_terminate(struc
        cv_signal(&is->is_login_cv);
 #endif
 
-       /*
-        * Don't queue any new PDUs.
-        */
        callout_drain(&is->is_callout);
-       if (is->is_sim != NULL && is->is_simq_frozen == false) {
-               ISCSI_SESSION_DEBUG(is, "freezing");
-               xpt_freeze_simq(is->is_sim, 1);
-               is->is_simq_frozen = true;
-       }
 
-       /*
-        * Remove postponed PDUs.
-        */
-       while (!STAILQ_EMPTY(&is->is_postponed)) {
-               pdu = STAILQ_FIRST(&is->is_postponed);
-               STAILQ_REMOVE_HEAD(&is->is_postponed, ip_next);
-               icl_pdu_free(pdu);
-       }
-
-       /*
-        * Forcibly terminate SCSI tasks.
-        */
-       ISCSI_SESSION_DEBUG(is, "terminating tasks");
-       iscsi_session_terminate_tasks(is, false);
-
-       /*
-        * Deregister CAM.
-        */
-       if (is->is_sim != NULL) {
-               ISCSI_SESSION_DEBUG(is, "deregistering SIM");
-               xpt_async(AC_LOST_DEVICE, is->is_path, NULL);
-
-               if (is->is_simq_frozen) {
-                       xpt_release_simq(is->is_sim, 1);
-                       is->is_simq_frozen = false;
-               }
-
-               xpt_free_path(is->is_path);
-               xpt_bus_deregister(cam_sim_path(is->is_sim));
-               cam_sim_free(is->is_sim, TRUE /*free_devq*/);
-               is->is_sim = NULL;
-       }
+       iscsi_session_cleanup(is, true);
 
        KASSERT(TAILQ_EMPTY(&is->is_outstanding),
            ("destroying session with active tasks"));
@@ -1971,7 +1972,8 @@ iscsi_action(struct cam_sim *sim, union 
 
        ISCSI_SESSION_LOCK_ASSERT(is);
 
-       if (is->is_terminating) {
+       if (is->is_terminating ||
+           (is->is_connected == false && fail_on_disconnection)) {
                ccb->ccb_h.status = CAM_DEV_NOT_THERE;
                xpt_done(ccb);
                return;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to