Skip site navigation (1)Skip section navigation (2)
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>