Date: Wed, 16 Apr 2014 17:39:10 +0000 (UTC) From: Edward Tomasz Napierala <trasz@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r264544 - head/sys/dev/iscsi Message-ID: <201404161739.s3GHdA4x038649@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201404161739.s3GHdA4x038649>