aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/iscsi/iscsi.c
diff options
context:
space:
mode:
authorEdward Tomasz Napierala <trasz@FreeBSD.org>2020-10-18 16:30:49 +0000
committerEdward Tomasz Napierala <trasz@FreeBSD.org>2020-10-18 16:30:49 +0000
commit186bcdaac7c70e59eb04412ad402a6fb57b97d11 (patch)
tree4e5a5ecbcb8c8b4fcf7c94da20dd6022c2af4596 /sys/dev/iscsi/iscsi.c
parentd22ff249d9733ed0ff628efd797f3ea3ec66c913 (diff)
downloadsrc-186bcdaac7c70e59eb04412ad402a6fb57b97d11.tar.gz
src-186bcdaac7c70e59eb04412ad402a6fb57b97d11.zip
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
Notes
Notes: svn path=/head/; revision=366812
Diffstat (limited to 'sys/dev/iscsi/iscsi.c')
-rw-r--r--sys/dev/iscsi/iscsi.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c
index 9663106cf05e..5fa3bdb9dff4 100644
--- a/sys/dev/iscsi/iscsi.c
+++ b/sys/dev/iscsi/iscsi.c
@@ -367,8 +367,8 @@ iscsi_session_cleanup(struct iscsi_session *is, bool destroy_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_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 {
@@ -2355,6 +2355,17 @@ iscsi_action(struct cam_sim *sim, union ccb *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;
+ }
+
switch (ccb->ccb_h.func_code) {
case XPT_PATH_INQ:
{