svn commit: r366812 - head/sys/dev/iscsi

Edward Tomasz Napierala trasz at FreeBSD.org
Sun Oct 18 16:30:50 UTC 2020


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;
 	}


More information about the svn-src-head mailing list