diff options
author | trasz <trasz@FreeBSD.org> | 2014-05-07 07:48:32 +0000 |
---|---|---|
committer | trasz <trasz@FreeBSD.org> | 2014-05-07 07:48:32 +0000 |
commit | a3b0c7e4a8cfbe4b4a4cf24848a4f5e97b7ac6de (patch) | |
tree | 0b5d5df1c8f2a61fce8f6bea27bf024235030e8f | |
parent | 5498c3860b7acec6eb0771167725b1c60727fccf (diff) | |
download | FreeBSD-src-a3b0c7e4a8cfbe4b4a4cf24848a4f5e97b7ac6de.zip FreeBSD-src-a3b0c7e4a8cfbe4b4a4cf24848a4f5e97b7ac6de.tar.gz |
MFC r264544:
Add kern.iscsi.fail_on_disconnection; this is required for gmultipath
to work.
Sponsored by: The FreeBSD Foundation
-rw-r--r-- | sys/dev/iscsi/iscsi.c | 128 |
1 files changed, 65 insertions, 63 deletions
diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c index 785f657..fc90a93 100644 --- a/sys/dev/iscsi/iscsi.c +++ b/sys/dev/iscsi/iscsi.c @@ -96,6 +96,10 @@ static int maxtags = 255; TUNABLE_INT("kern.iscsi.maxtags", &maxtags); SYSCTL_INT(_kern_iscsi, OID_AUTO, maxtags, CTLFLAG_RWTUN, &maxtags, 255, "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; @@ -300,22 +304,11 @@ iscsi_session_terminate_tasks(struct iscsi_session *is, bool requeue) } 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. @@ -335,12 +328,63 @@ iscsi_maintenance_thread_reconnect(struct iscsi_session *is) 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), @@ -350,9 +394,6 @@ iscsi_maintenance_thread_reconnect(struct iscsi_session *is) * 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; @@ -364,7 +405,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); @@ -385,48 +425,9 @@ iscsi_maintenance_thread_terminate(struct iscsi_session *is) 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")); @@ -2004,7 +2005,8 @@ iscsi_action(struct cam_sim *sim, union ccb *ccb) 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; |