aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2016-10-08 20:26:44 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2016-10-20 00:22:32 -0400
commit449a137846c84829a328757cd21fd9ca65c08519 (patch)
tree630c757a9341dc6cd1e5e731987d127e3ada0a38
parent527268df31e57cf2b6d417198717c6d6afdb1e3e (diff)
target: Make EXTENDED_COPY 0xe4 failure return COPY TARGET DEVICE NOT REACHABLE
This patch addresses a bug where EXTENDED_COPY across multiple LUNs results in a CHECK_CONDITION when the source + destination are not located on the same physical node. ESX Host environments expect sense COPY_ABORTED w/ COPY TARGET DEVICE NOT REACHABLE to be returned when this occurs, in order to signal fallback to local copy method. As described in section 6.3.3 of spc4r22: "If it is not possible to complete processing of a segment because the copy manager is unable to establish communications with a copy target device, because the copy target device does not respond to INQUIRY, or because the data returned in response to INQUIRY indicates an unsupported logical unit, then the EXTENDED COPY command shall be terminated with CHECK CONDITION status, with the sense key set to COPY ABORTED, and the additional sense code set to COPY TARGET DEVICE NOT REACHABLE." Tested on v4.1.y with ESX v5.5u2+ with BlockCopy across multiple nodes. Reported-by: Nixon Vincent <nixon.vincent@calsoftinc.com> Tested-by: Nixon Vincent <nixon.vincent@calsoftinc.com> Cc: Nixon Vincent <nixon.vincent@calsoftinc.com> Tested-by: Dinesh Israni <ddi@datera.io> Signed-off-by: Dinesh Israni <ddi@datera.io> Cc: Dinesh Israni <ddi@datera.io> Cc: stable@vger.kernel.org # 3.14+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/target_core_transport.c7
-rw-r--r--drivers/target/target_core_xcopy.c22
-rw-r--r--include/target/target_core_base.h1
3 files changed, 24 insertions, 6 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 00ec46413146..000bc6d077ea 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1706,6 +1706,7 @@ void transport_generic_request_failure(struct se_cmd *cmd,
1706 case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED: 1706 case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED:
1707 case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED: 1707 case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
1708 case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED: 1708 case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
1709 case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE:
1709 break; 1710 break;
1710 case TCM_OUT_OF_RESOURCES: 1711 case TCM_OUT_OF_RESOURCES:
1711 sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 1712 sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -2873,6 +2874,12 @@ static const struct sense_info sense_info_table[] = {
2873 .ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */ 2874 .ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */
2874 .add_sector_info = true, 2875 .add_sector_info = true,
2875 }, 2876 },
2877 [TCM_COPY_TARGET_DEVICE_NOT_REACHABLE] = {
2878 .key = COPY_ABORTED,
2879 .asc = 0x0d,
2880 .ascq = 0x02, /* COPY TARGET DEVICE NOT REACHABLE */
2881
2882 },
2876 [TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = { 2883 [TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = {
2877 /* 2884 /*
2878 * Returning ILLEGAL REQUEST would cause immediate IO errors on 2885 * Returning ILLEGAL REQUEST would cause immediate IO errors on
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c
index 75cd85426ae3..f2a1443ecb33 100644
--- a/drivers/target/target_core_xcopy.c
+++ b/drivers/target/target_core_xcopy.c
@@ -104,7 +104,7 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op
104 } 104 }
105 mutex_unlock(&g_device_mutex); 105 mutex_unlock(&g_device_mutex);
106 106
107 pr_err("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n"); 107 pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
108 return -EINVAL; 108 return -EINVAL;
109} 109}
110 110
@@ -185,7 +185,7 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
185 185
186static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, 186static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
187 struct xcopy_op *xop, unsigned char *p, 187 struct xcopy_op *xop, unsigned char *p,
188 unsigned short tdll) 188 unsigned short tdll, sense_reason_t *sense_ret)
189{ 189{
190 struct se_device *local_dev = se_cmd->se_dev; 190 struct se_device *local_dev = se_cmd->se_dev;
191 unsigned char *desc = p; 191 unsigned char *desc = p;
@@ -193,6 +193,8 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
193 unsigned short start = 0; 193 unsigned short start = 0;
194 bool src = true; 194 bool src = true;
195 195
196 *sense_ret = TCM_INVALID_PARAMETER_LIST;
197
196 if (offset != 0) { 198 if (offset != 0) {
197 pr_err("XCOPY target descriptor list length is not" 199 pr_err("XCOPY target descriptor list length is not"
198 " multiple of %d\n", XCOPY_TARGET_DESC_LEN); 200 " multiple of %d\n", XCOPY_TARGET_DESC_LEN);
@@ -243,9 +245,16 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
243 rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true); 245 rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true);
244 else 246 else
245 rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false); 247 rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false);
246 248 /*
247 if (rc < 0) 249 * If a matching IEEE NAA 0x83 descriptor for the requested device
250 * is not located on this node, return COPY_ABORTED with ASQ/ASQC
251 * 0x0d/0x02 - COPY_TARGET_DEVICE_NOT_REACHABLE to request the
252 * initiator to fall back to normal copy method.
253 */
254 if (rc < 0) {
255 *sense_ret = TCM_COPY_TARGET_DEVICE_NOT_REACHABLE;
248 goto out; 256 goto out;
257 }
249 258
250 pr_debug("XCOPY TGT desc: Source dev: %p NAA IEEE WWN: 0x%16phN\n", 259 pr_debug("XCOPY TGT desc: Source dev: %p NAA IEEE WWN: 0x%16phN\n",
251 xop->src_dev, &xop->src_tid_wwn[0]); 260 xop->src_dev, &xop->src_tid_wwn[0]);
@@ -816,7 +825,8 @@ out:
816 xcopy_pt_undepend_remotedev(xop); 825 xcopy_pt_undepend_remotedev(xop);
817 kfree(xop); 826 kfree(xop);
818 827
819 pr_warn("target_xcopy_do_work: Setting X-COPY CHECK_CONDITION -> sending response\n"); 828 pr_warn_ratelimited("target_xcopy_do_work: rc: %d, Setting X-COPY CHECK_CONDITION"
829 " -> sending response\n", rc);
820 ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION; 830 ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
821 target_complete_cmd(ec_cmd, SAM_STAT_CHECK_CONDITION); 831 target_complete_cmd(ec_cmd, SAM_STAT_CHECK_CONDITION);
822} 832}
@@ -875,7 +885,7 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
875 " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage, 885 " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
876 tdll, sdll, inline_dl); 886 tdll, sdll, inline_dl);
877 887
878 rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll); 888 rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret);
879 if (rc <= 0) 889 if (rc <= 0)
880 goto out; 890 goto out;
881 891
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index fb8e3b6febdf..c2119008990a 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -177,6 +177,7 @@ enum tcm_sense_reason_table {
177 TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED = R(0x15), 177 TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED = R(0x15),
178 TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16), 178 TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16),
179 TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17), 179 TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17),
180 TCM_COPY_TARGET_DEVICE_NOT_REACHABLE = R(0x18),
180#undef R 181#undef R
181}; 182};
182 183