@@ -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)
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(-)