@@ -1704,7 +1704,6 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
cls_session = starget_to_session(scsi_target(sc->device));
session = cls_session->dd_data;
- spin_lock_bh(&session->frwd_lock);
reason = iscsi_session_chkready(cls_session);
if (reason) {
@@ -1761,7 +1760,9 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
goto fault;
}
+ spin_lock_bh(&session->frwd_lock);
if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
+ spin_unlock_bh(&session->frwd_lock);
reason = FAILURE_SESSION_IN_RECOVERY;
sc->result = DID_REQUEUE << 16;
goto fault;
@@ -1769,6 +1770,7 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
task = iscsi_alloc_task(conn, sc);
if (!task) {
+ spin_unlock_bh(&session->frwd_lock);
reason = FAILURE_OOM;
goto reject;
}
@@ -1803,21 +1805,23 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
return 0;
prepd_reject:
+ spin_unlock_bh(&session->frwd_lock);
+
spin_lock_bh(&session->back_lock);
iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
spin_unlock_bh(&session->back_lock);
reject:
- spin_unlock_bh(&session->frwd_lock);
ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
sc->cmnd[0], reason);
return SCSI_MLQUEUE_TARGET_BUSY;
prepd_fault:
+ spin_unlock_bh(&session->frwd_lock);
+
spin_lock_bh(&session->back_lock);
iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
spin_unlock_bh(&session->back_lock);
fault:
- spin_unlock_bh(&session->frwd_lock);
ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
sc->cmnd[0], reason);
scsi_set_resid(sc, scsi_bufflen(sc));
@@ -326,8 +326,9 @@ struct iscsi_session {
* can enclose the mutual exclusion zone protected by the backward lock
* but not vice versa.
*/
- spinlock_t frwd_lock; /* protects session state, *
- * cmdsn and session *
+ spinlock_t frwd_lock; /* protects session state *
+ * in the eh paths, cmdsn *
+ * suspend bit and session *
* resources: *
* - cmdpool kfifo_out , *
* - mgmtpool, queues */
This drops the frwd lock for the session state checks in queuecommand. Like with the transport class case, we only need it as a hint since when the session is cleaned up we will block the session which flushes the queues, and then we clean up all running IO. So the locking just prevents cleaning up extra cmds. It is still needed: 1. when accessing suspend_tx in queuecomand because drivers that implement ep_disconnect will set that bit from disconnect (called before stop) and expect that no new commands will be queued to it. Note that the comment for this was wrong and that is fixed in this patch. 2. the list addition for the drivers that use the iscsi xmit wq. Signed-off-by: Mike Christie <michael.christie@oracle.com> --- drivers/scsi/libiscsi.c | 10 +++++++--- include/scsi/libiscsi.h | 5 +++-- 2 files changed, 10 insertions(+), 5 deletions(-)