Date: Sun, 18 Oct 2020 16:30:50 +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: r366812 - head/sys/dev/iscsi Message-ID: <202010181630.09IGUoOY037023@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: trasz Date: Sun Oct 18 16:30:49 2020 New Revision: 366812 URL: https://svnweb.freebsd.org/changeset/base/366812 Log: If the SIM freezes the queue at exactly the wrong moment, after another thread has started to send in a CCB and already checked the queue wasn't frozen, we would end up with iscsi_action() being called despite the queue is now frozen. Add a check to make sure this doesn't happen . Perhaps this should be fixed at the CAM level instead, but given how the send queue and SIM are governed by two separate mutexes, it is somewhat hard to do. Reviewed by: imp, mav MFC after: 2 weeks Sponsored by: NetApp, Inc. Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D26750 Modified: head/sys/dev/iscsi/iscsi.c Modified: head/sys/dev/iscsi/iscsi.c ============================================================================== --- head/sys/dev/iscsi/iscsi.c Sun Oct 18 16:24:08 2020 (r366811) +++ head/sys/dev/iscsi/iscsi.c Sun Oct 18 16:30:49 2020 (r366812) @@ -367,8 +367,8 @@ iscsi_session_cleanup(struct iscsi_session *is, bool d 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_release_simq(is->is_sim, 1); } xpt_free_path(is->is_path); @@ -1479,8 +1479,8 @@ iscsi_ioctl_daemon_handoff(struct iscsi_softc *sc, KASSERT(is->is_simq_frozen, ("reconnect without frozen simq")); ISCSI_SESSION_LOCK(is); ISCSI_SESSION_DEBUG(is, "releasing"); - xpt_release_simq(is->is_sim, 1); is->is_simq_frozen = false; + xpt_release_simq(is->is_sim, 1); ISCSI_SESSION_UNLOCK(is); } else { @@ -2351,6 +2351,17 @@ iscsi_action(struct cam_sim *sim, union ccb *ccb) if (is->is_terminating || (is->is_connected == false && fail_on_disconnection)) { ccb->ccb_h.status = CAM_DEV_NOT_THERE; + xpt_done(ccb); + return; + } + + /* + * Make sure CAM doesn't sneak in a CCB just after freezing the queue. + */ + if (is->is_simq_frozen == true) { + ccb->ccb_h.status &= ~(CAM_SIM_QUEUED | CAM_STATUS_MASK); + ccb->ccb_h.status |= CAM_REQUEUE_REQ; + /* Don't freeze the devq - the SIM queue is already frozen. */ xpt_done(ccb); return; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202010181630.09IGUoOY037023>