[PATCH 2/2] tcm_qla2xxx: Fix deadlock for tcm_qla2xxx_release_cmd w/ hardware_lock held

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>

This patch fixes a deadlock in tcm_qla2xxx_release_cmd() with the new shutdown
code where qla_hw_data->hardware_lock may already held during an exception
path for tcm_qla2xxx_handle_cmd() -> transport_lookup_cmd_lun().  This
occurs when the descriptor has to released directly in tcm_qla2xxx_free_cmd()
via transport_generic_free_cmd() -> tcm_qla2xxx_release_cmd() due to a
missing se_device association.

Reported-by: Roland Dreier <roland@xxxxxxxxxxxxxxx>
Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxxxxxxxx>
---
 drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c |   59 ++++++++++++++++-------
 1 files changed, 41 insertions(+), 18 deletions(-)

diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c
index 189eabe..2ba34b4 100644
--- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c
+++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c
@@ -447,6 +447,33 @@ void tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd)
 }
 
 /*
+ * Called with qla_hw_data->hardware_lock held..
+ */
+static int tcm_qla2xxx_release_shutdown_check(
+	struct qla_tgt_cmd *cmd,
+	struct qla_tgt_sess *sess)
+{
+	/*
+	 * During shutdown, qla_tgt_wait_for_cmds() will be waiting on
+	 * this outstanding qla_tgt_cmd descriptor.  For this case,
+	 * perform the completion and return, and qla_tgt_wait_for_cmds()
+	 * will handle the direct call to qla_tgt_free_cmd()
+	 */
+	if (cmd->tgt->tgt_stop || sess->tearing_down) {
+		if (atomic_read(&cmd->cmd_free_comp_set) ||
+		    atomic_read(&cmd->cmd_free)) {
+			pr_warn("Detected shutdown, calling complete("
+				"&cmd->cmd_free_comp): cmd: %p\n", cmd);
+			complete(&cmd->cmd_free_comp);
+			return 1;
+		}
+	}
+	list_del(&cmd->cmd_list);
+
+	return 0;
+}
+
+/*
  * Callback from TCM Core to release underlying fabric descriptor
  */
 void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd)
@@ -455,6 +482,7 @@ void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd)
 	struct qla_tgt_sess *sess;
 	struct qla_hw_data *ha;
 	unsigned long flags;
+	int ret;
 
 	if (se_cmd->se_tmr_req != NULL)
 		return;
@@ -467,6 +495,16 @@ void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd)
 
 	ha = sess->vha->hw;
 	/*
+	 * Check if qla_hw_data->hardware_lock is already held from an
+	 * exception path..  This also skips the possible wait for
+	 * completion on cmd_stop_free_comp below..
+	 */
+	if (!cmd->locked_rsp) {
+		if (!tcm_qla2xxx_release_shutdown_check(cmd, sess))
+			qla_tgt_free_cmd(cmd);	
+		return;
+	}
+	/*
 	 * If the callback to tcm_qla2xxx_check_stop_free() has not finished,
 	 * before the release path is invoked, go ahead and wait on
 	 * cmd_stop_free_comp until tcm_qla2xxx_check_stop_free completes.
@@ -480,26 +518,11 @@ void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd)
 		wait_for_completion(&cmd->cmd_stop_free_comp);
 		spin_lock_irqsave(&ha->hardware_lock, flags);
 	}
-	/*
-	 * During shutdown, qla_tgt_wait_for_cmds() will be waiting on
-	 * this outstanding qla_tgt_cmd descriptor.  For this case,
-	 * perform the completion and return, and qla_tgt_wait_for_cmds()
-	 * will handle the direct call to qla_tgt_free_cmd()
-	 */
-	if (cmd->tgt->tgt_stop || sess->tearing_down) {
-		if (atomic_read(&cmd->cmd_free_comp_set) ||
-		    atomic_read(&cmd->cmd_free)) {
-			pr_warn("Detected shutdown, calling complete("
-				"&cmd->cmd_free_comp): cmd: %p\n", cmd);
-			spin_unlock_irqrestore(&ha->hardware_lock, flags);
-			complete(&cmd->cmd_free_comp);
-			return;
-		}
-	}
-	list_del(&cmd->cmd_list);
+	ret = tcm_qla2xxx_release_shutdown_check(cmd, sess);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-	qla_tgt_free_cmd(cmd);
+	if (!ret)
+		qla_tgt_free_cmd(cmd);
 }
 
 int tcm_qla2xxx_shutdown_session(struct se_session *se_sess)
-- 
1.7.2.5

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux