diff options
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/target_core_xcopy.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c index 0f1319336f3e..d4fe7cb2bd00 100644 --- a/drivers/target/target_core_xcopy.c +++ b/drivers/target/target_core_xcopy.c @@ -674,12 +674,16 @@ static void target_xcopy_do_work(struct work_struct *work) unsigned int max_sectors; int rc = 0; unsigned short nolb, max_nolb, copied_nolb = 0; + sense_reason_t sense_rc; - if (target_parse_xcopy_cmd(xop) != TCM_NO_SENSE) + sense_rc = target_parse_xcopy_cmd(xop); + if (sense_rc != TCM_NO_SENSE) goto err_free; - if (WARN_ON_ONCE(!xop->src_dev) || WARN_ON_ONCE(!xop->dst_dev)) + if (WARN_ON_ONCE(!xop->src_dev) || WARN_ON_ONCE(!xop->dst_dev)) { + sense_rc = TCM_INVALID_PARAMETER_LIST; goto err_free; + } src_dev = xop->src_dev; dst_dev = xop->dst_dev; @@ -762,20 +766,20 @@ static void target_xcopy_do_work(struct work_struct *work) return; out: + /* + * The XCOPY command was aborted after some data was transferred. + * Terminate command with CHECK CONDITION status, with the sense key + * set to COPY ABORTED. + */ + sense_rc = TCM_COPY_TARGET_DEVICE_NOT_REACHABLE; xcopy_pt_undepend_remotedev(xop); target_free_sgl(xop->xop_data_sg, xop->xop_data_nents); err_free: kfree(xop); - /* - * Don't override an error scsi status if it has already been set - */ - if (ec_cmd->scsi_status == SAM_STAT_GOOD) { - pr_warn_ratelimited("target_xcopy_do_work: rc: %d, Setting X-COPY" - " CHECK_CONDITION -> sending response\n", rc); - ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION; - } - target_complete_cmd(ec_cmd, ec_cmd->scsi_status); + pr_warn_ratelimited("target_xcopy_do_work: rc: %d, sense: %u, XCOPY operation failed\n", + rc, sense_rc); + target_complete_cmd_with_sense(ec_cmd, SAM_STAT_CHECK_CONDITION, sense_rc); } /* |