diff mbox

[RFC,12/13] target: merge cmd completion functions

Message ID 1496263970-7632-13-git-send-email-mchristi@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Mike Christie May 31, 2017, 8:52 p.m. UTC
This patch merges the cmd completion functions so there is a common
code path.

Signed-off-by: Mike Christie <mchristi@redhat.com>
---
 drivers/target/target_core_transport.c | 156 +++++++++++----------------------
 1 file changed, 49 insertions(+), 107 deletions(-)
diff mbox

Patch

diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 6aee378..faad7b4 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -68,7 +68,7 @@ 
 static void transport_handle_queue_full(struct se_cmd *cmd,
 		struct se_device *dev, int err, bool write_pending);
 static int transport_put_cmd(struct se_cmd *cmd);
-static void target_complete_ok_work(struct work_struct *work);
+static void target_complete_cmd_work(struct work_struct *work);
 
 int init_se_kmem_caches(void)
 {
@@ -670,14 +670,6 @@  void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
 		transport_put_cmd(cmd);
 }
 
-static void target_complete_failure_work(struct work_struct *work)
-{
-	struct se_cmd *cmd = container_of(work, struct se_cmd, work);
-
-	transport_generic_request_failure(cmd,
-			TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE);
-}
-
 /*
  * Used when asking transport to copy Sense Data from the underlying
  * Linux/SCSI struct scsi_cmnd
@@ -721,24 +713,10 @@  void transport_copy_sense_to_cmd(struct se_cmd *cmd, unsigned char *sense)
 
 void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
 {
-	int success;
 	unsigned long flags;
-
 	cmd->scsi_status = scsi_status;
 
 	spin_lock_irqsave(&cmd->t_state_lock, flags);
-	switch (cmd->scsi_status) {
-	case SAM_STAT_CHECK_CONDITION:
-		if (cmd->se_cmd_flags & SCF_TASK_SENSE)
-			success = 1;
-		else
-			success = 0;
-		break;
-	default:
-		success = 1;
-		break;
-	}
-
 	/*
 	 * Check for case where an explicit ABORT_TASK has been received
 	 * and transport_wait_for_tasks() will be waiting for completion..
@@ -748,12 +726,9 @@  void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
 		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		complete_all(&cmd->t_transport_stop_comp);
 		return;
-	} else if (!success) {
-		INIT_WORK(&cmd->work, target_complete_failure_work);
-	} else {
-		INIT_WORK(&cmd->work, target_complete_ok_work);
 	}
 
+	INIT_WORK(&cmd->work, target_complete_cmd_work);
 	cmd->t_state = TRANSPORT_COMPLETE;
 	cmd->transport_state |= (CMD_T_COMPLETE | CMD_T_ACTIVE);
 	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
@@ -1678,19 +1653,8 @@  int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
 void transport_generic_request_failure(struct se_cmd *cmd,
 		sense_reason_t sense_reason)
 {
-	int ret = 0, post_ret = 0;
-
-	/*
-	 * For SAM Task Attribute emulation for failed struct se_cmd
-	 */
-	transport_complete_task_attr(cmd);
-	/*
-	 * Handle special case for COMPARE_AND_WRITE failure, where the
-	 * callback is expected to drop the per device ->caw_sem.
-	 */
-	if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
-	     cmd->transport_complete_callback)
-		cmd->transport_complete_callback(cmd, false, &post_ret);
+	u8 scsi_status = SAM_STAT_CHECK_CONDITION;
+	unsigned long flags;
 
 	if (transport_check_aborted_status(cmd, 1))
 		return;
@@ -1737,7 +1701,7 @@  void transport_generic_request_failure(struct se_cmd *cmd,
 		 *
 		 * Uses linux/include/scsi/scsi.h SAM status codes defs
 		 */
-		cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
+		scsi_status = SAM_STAT_RESERVATION_CONFLICT;
 		/*
 		 * For UA Interlock Code 11b, a RESERVATION CONFLICT will
 		 * establish a UNIT ATTENTION with PREVIOUS RESERVATION
@@ -1751,11 +1715,8 @@  void transport_generic_request_failure(struct se_cmd *cmd,
 					       cmd->orig_fe_lun, 0x2C,
 					ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS);
 		}
-		trace_target_cmd_complete(cmd);
-		ret = cmd->se_tfo->queue_status(cmd);
-		if (ret)
-			goto queue_full;
-		goto check_stop;
+
+		goto queue_completion;
 	default:
 		pr_err("Unknown transport error for CDB 0x%02x: %d\n",
 			cmd->t_task_cdb[0], sense_reason);
@@ -1763,17 +1724,12 @@  void transport_generic_request_failure(struct se_cmd *cmd,
 		break;
 	}
 
-	ret = transport_send_check_condition_and_sense(cmd, sense_reason);
-	if (ret)
-		goto queue_full;
-
-check_stop:
-	transport_lun_remove_cmd(cmd);
-	transport_cmd_check_stop_to_fabric(cmd);
-	return;
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
+	transport_setup_sense(cmd, sense_reason);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-queue_full:
-	transport_handle_queue_full(cmd, cmd->se_dev, ret, false);
+queue_completion:
+	target_complete_cmd(cmd, scsi_status);
 }
 EXPORT_SYMBOL(transport_generic_request_failure);
 
@@ -2119,10 +2075,10 @@  static bool target_read_prot_action(struct se_cmd *cmd)
 	return false;
 }
 
-static void target_complete_ok_work(struct work_struct *work)
+static void target_complete_cmd_work(struct work_struct *work)
 {
 	struct se_cmd *cmd = container_of(work, struct se_cmd, work);
-	int ret;
+	int ret = 0;
 
 	/*
 	 * Check if we need to move delayed/dormant tasks from cmds on the
@@ -2139,20 +2095,6 @@  static void target_complete_ok_work(struct work_struct *work)
 		schedule_work(&cmd->se_dev->qf_work_queue);
 
 	/*
-	 * Check if we need to send a sense buffer from
-	 * the struct se_cmd in question.
-	 */
-	if (cmd->se_cmd_flags & SCF_TASK_SENSE) {
-		WARN_ON(!cmd->scsi_status);
-		ret = transport_send_check_condition_and_sense(cmd, 0);
-		if (ret)
-			goto queue_full;
-
-		transport_lun_remove_cmd(cmd);
-		transport_cmd_check_stop_to_fabric(cmd);
-		return;
-	}
-	/*
 	 * Check for a callback, used by amongst other things
 	 * XDWRITE_READ_10 and COMPARE_AND_WRITE emulation.
 	 */
@@ -2161,22 +2103,33 @@  static void target_complete_ok_work(struct work_struct *work)
 		bool caw = (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE);
 		bool zero_dl = !(cmd->data_length);
 		int post_ret = 0;
+		bool good = !(cmd->scsi_status);
+
+		if (good || caw) {
+			rc = cmd->transport_complete_callback(cmd, good,
+							      &post_ret);
+			if (!rc && !post_ret) {
+				if (caw && zero_dl)
+					goto queue_rsp;
+
+				return;
+			} else if (rc && good) {
+				transport_setup_sense(cmd, rc);
+			}
+		}
+	}
 
-		rc = cmd->transport_complete_callback(cmd, true, &post_ret);
-		if (!rc && !post_ret) {
-			if (caw && zero_dl)
-				goto queue_rsp;
-
-			return;
-		} else if (rc) {
-			ret = transport_send_check_condition_and_sense(cmd, rc);
-			if (ret)
-				goto queue_full;
+	if (transport_check_aborted_status(cmd, 1))
+		return;
 
-			transport_lun_remove_cmd(cmd);
-			transport_cmd_check_stop_to_fabric(cmd);
-			return;
-		}
+	/*
+	 * Check if we need to send a sense buffer from
+	 * the struct se_cmd in question.
+	 */
+	if (cmd->se_cmd_flags & SCF_TASK_SENSE) {
+		WARN_ON(!cmd->scsi_status);
+		ret = transport_send_check_condition_and_sense(cmd, 0);
+		goto done;
 	}
 
 queue_rsp:
@@ -2195,18 +2148,11 @@  static void target_complete_ok_work(struct work_struct *work)
 		if (target_read_prot_action(cmd)) {
 			ret = transport_send_check_condition_and_sense(cmd,
 						cmd->pi_err);
-			if (ret)
-				goto queue_full;
-
-			transport_lun_remove_cmd(cmd);
-			transport_cmd_check_stop_to_fabric(cmd);
-			return;
+			break;
 		}
 
 		trace_target_cmd_complete(cmd);
 		ret = cmd->se_tfo->queue_data_in(cmd);
-		if (ret)
-			goto queue_full;
 		break;
 	case DMA_TO_DEVICE:
 		atomic_long_add(cmd->data_length,
@@ -2218,8 +2164,6 @@  static void target_complete_ok_work(struct work_struct *work)
 			atomic_long_add(cmd->data_length,
 					&cmd->se_lun->lun_stats.tx_data_octets);
 			ret = cmd->se_tfo->queue_data_in(cmd);
-			if (ret)
-				goto queue_full;
 			break;
 		}
 		/* Fall through for DMA_TO_DEVICE */
@@ -2227,22 +2171,20 @@  static void target_complete_ok_work(struct work_struct *work)
 queue_status:
 		trace_target_cmd_complete(cmd);
 		ret = cmd->se_tfo->queue_status(cmd);
-		if (ret)
-			goto queue_full;
 		break;
 	default:
 		break;
 	}
 
-	transport_lun_remove_cmd(cmd);
-	transport_cmd_check_stop_to_fabric(cmd);
-	return;
-
-queue_full:
-	pr_debug("Handling complete_ok QUEUE_FULL: se_cmd: %p,"
-		" data_direction: %d\n", cmd, cmd->data_direction);
-
-	transport_handle_queue_full(cmd, cmd->se_dev, ret, false);
+done:
+	if (ret) {
+		pr_debug("Handling complete_ok QUEUE_FULL: se_cmd: %p,"
+			" data_direction: %d\n", cmd, cmd->data_direction);
+		transport_handle_queue_full(cmd, cmd->se_dev, ret, false);
+	} else {
+		transport_lun_remove_cmd(cmd);
+		transport_cmd_check_stop_to_fabric(cmd);
+	}
 }
 
 void target_free_sgl(struct scatterlist *sgl, int nents)