target: Make EXTENDED_COPY 0xe4 failure return COPY TARGET DEVICE NOT REACHABLE
[cascardo/linux.git] / drivers / target / target_core_xcopy.c
index 75cd854..f2a1443 100644 (file)
@@ -104,7 +104,7 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op
        }
        mutex_unlock(&g_device_mutex);
 
-       pr_err("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
+       pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
        return -EINVAL;
 }
 
@@ -185,7 +185,7 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
 
 static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
                                struct xcopy_op *xop, unsigned char *p,
-                               unsigned short tdll)
+                               unsigned short tdll, sense_reason_t *sense_ret)
 {
        struct se_device *local_dev = se_cmd->se_dev;
        unsigned char *desc = p;
@@ -193,6 +193,8 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
        unsigned short start = 0;
        bool src = true;
 
+       *sense_ret = TCM_INVALID_PARAMETER_LIST;
+
        if (offset != 0) {
                pr_err("XCOPY target descriptor list length is not"
                        " multiple of %d\n", XCOPY_TARGET_DESC_LEN);
@@ -243,9 +245,16 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
                rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true);
        else
                rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false);
-
-       if (rc < 0)
+       /*
+        * If a matching IEEE NAA 0x83 descriptor for the requested device
+        * is not located on this node, return COPY_ABORTED with ASQ/ASQC
+        * 0x0d/0x02 - COPY_TARGET_DEVICE_NOT_REACHABLE to request the
+        * initiator to fall back to normal copy method.
+        */
+       if (rc < 0) {
+               *sense_ret = TCM_COPY_TARGET_DEVICE_NOT_REACHABLE;
                goto out;
+       }
 
        pr_debug("XCOPY TGT desc: Source dev: %p NAA IEEE WWN: 0x%16phN\n",
                 xop->src_dev, &xop->src_tid_wwn[0]);
@@ -816,7 +825,8 @@ out:
        xcopy_pt_undepend_remotedev(xop);
        kfree(xop);
 
-       pr_warn("target_xcopy_do_work: Setting X-COPY CHECK_CONDITION -> sending response\n");
+       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, SAM_STAT_CHECK_CONDITION);
 }
@@ -875,7 +885,7 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
                " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
                tdll, sdll, inline_dl);
 
-       rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll);
+       rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret);
        if (rc <= 0)
                goto out;