Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+24 -6
+7
drivers/target/target_core_transport.c
··· 1706 1706 case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED: 1707 1707 case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED: 1708 1708 case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED: 1709 + case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE: 1709 1710 break; 1710 1711 case TCM_OUT_OF_RESOURCES: 1711 1712 sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; ··· 2873 2872 .asc = 0x10, 2874 2873 .ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */ 2875 2874 .add_sector_info = true, 2875 + }, 2876 + [TCM_COPY_TARGET_DEVICE_NOT_REACHABLE] = { 2877 + .key = COPY_ABORTED, 2878 + .asc = 0x0d, 2879 + .ascq = 0x02, /* COPY TARGET DEVICE NOT REACHABLE */ 2880 + 2876 2881 }, 2877 2882 [TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = { 2878 2883 /*
+16 -6
drivers/target/target_core_xcopy.c
··· 104 104 } 105 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 108 return -EINVAL; 109 109 } 110 110 ··· 185 185 186 186 static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, 187 187 struct xcopy_op *xop, unsigned char *p, 188 - unsigned short tdll) 188 + unsigned short tdll, sense_reason_t *sense_ret) 189 189 { 190 190 struct se_device *local_dev = se_cmd->se_dev; 191 191 unsigned char *desc = p; 192 192 int offset = tdll % XCOPY_TARGET_DESC_LEN, rc, ret = 0; 193 193 unsigned short start = 0; 194 194 bool src = true; 195 + 196 + *sense_ret = TCM_INVALID_PARAMETER_LIST; 195 197 196 198 if (offset != 0) { 197 199 pr_err("XCOPY target descriptor list length is not" ··· 245 243 rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true); 246 244 else 247 245 rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false); 248 - 249 - if (rc < 0) 246 + /* 247 + * If a matching IEEE NAA 0x83 descriptor for the requested device 248 + * is not located on this node, return COPY_ABORTED with ASQ/ASQC 249 + * 0x0d/0x02 - COPY_TARGET_DEVICE_NOT_REACHABLE to request the 250 + * initiator to fall back to normal copy method. 251 + */ 252 + if (rc < 0) { 253 + *sense_ret = TCM_COPY_TARGET_DEVICE_NOT_REACHABLE; 250 254 goto out; 255 + } 251 256 252 257 pr_debug("XCOPY TGT desc: Source dev: %p NAA IEEE WWN: 0x%16phN\n", 253 258 xop->src_dev, &xop->src_tid_wwn[0]); ··· 825 816 xcopy_pt_undepend_remotedev(xop); 826 817 kfree(xop); 827 818 828 - pr_warn("target_xcopy_do_work: Setting X-COPY CHECK_CONDITION -> sending response\n"); 819 + pr_warn_ratelimited("target_xcopy_do_work: rc: %d, Setting X-COPY CHECK_CONDITION" 820 + " -> sending response\n", rc); 829 821 ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION; 830 822 target_complete_cmd(ec_cmd, SAM_STAT_CHECK_CONDITION); 831 823 } ··· 885 875 " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage, 886 876 tdll, sdll, inline_dl); 887 877 888 - rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll); 878 + rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret); 889 879 if (rc <= 0) 890 880 goto out; 891 881
+1
include/target/target_core_base.h
··· 177 177 TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED = R(0x15), 178 178 TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16), 179 179 TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17), 180 + TCM_COPY_TARGET_DEVICE_NOT_REACHABLE = R(0x18), 180 181 #undef R 181 182 }; 182 183