[RHEL7,COMMIT] ms/target: Make EXTENDED_COPY 0xe4 failure return COPY TARGET DEVICE NOT REACHABLE

Submitted by Konstantin Khorenko on April 2, 2018, 2:28 p.m.

Details

Message ID 201804021428.w32ESLtc023875@finist_ce7.work
State New
Series "target: backport bug fixes from the upstream kernel"
Headers show

Commit Message

Konstantin Khorenko April 2, 2018, 2:28 p.m.
The commit is pushed to "branch-rh7-3.10.0-693.21.1.vz7.46.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.21.1.vz7.46.2
------>
commit e88c04a22ad5034135f77ae0a8fffba0d6eb2fb0
Author: Nicholas Bellinger <nab@linux-iscsi.org>
Date:   Mon Apr 2 17:28:21 2018 +0300

    ms/target: Make EXTENDED_COPY 0xe4 failure return COPY TARGET DEVICE NOT REACHABLE
    
    ML: 449a137846c84829a328757cd21fd9ca65c08519
    
    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>
    Signed-off-by: Andrei Vagin <avagin@openvz.org>
---
 drivers/target/target_core_transport.c |  7 +++++++
 drivers/target/target_core_xcopy.c     | 22 ++++++++++++++++------
 include/target/target_core_base.h      |  1 +
 3 files changed, 24 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 2a01d8e88fbb..5bc36e428cf1 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1656,6 +1656,7 @@  void transport_generic_request_failure(struct se_cmd *cmd,
 	case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED:
 	case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
 	case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
+	case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE:
 		break;
 	case TCM_OUT_OF_RESOURCES:
 		sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -2773,6 +2774,12 @@  static const struct sense_info sense_info_table[] = {
 		.ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */
 		.add_sector_info = true,
 	},
+	[TCM_COPY_TARGET_DEVICE_NOT_REACHABLE] = {
+		.key = COPY_ABORTED,
+		.asc = 0x0d,
+		.ascq = 0x02, /* COPY TARGET DEVICE NOT REACHABLE */
+
+	},
 	[TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = {
 		/*
 		 * 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 a7c89740feb0..5cfb3829c2d6 100644
--- a/drivers/target/target_core_xcopy.c
+++ b/drivers/target/target_core_xcopy.c
@@ -116,7 +116,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;
 }
 
@@ -197,7 +197,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;
@@ -205,6 +205,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);
@@ -255,9 +257,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]);
@@ -861,7 +870,8 @@  static void target_xcopy_do_work(struct work_struct *work)
 	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);
 }
@@ -920,7 +930,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;
 
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 288935002951..55c66cdbb414 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -214,6 +214,7 @@  enum tcm_sense_reason_table {
 	TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED	= R(0x15),
 	TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED	= R(0x16),
 	TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED	= R(0x17),
+	TCM_COPY_TARGET_DEVICE_NOT_REACHABLE	= R(0x18),
 #undef R
 };