From: Sasha Levin Date: Wed, 13 Jan 2021 16:06:39 +0000 (-0500) Subject: Fixes for 4.4 X-Git-Tag: v4.4.252~39 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2f38e617f5360d8e4797ed91e1693d59e7aef042;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 4.4 Signed-off-by: Sasha Levin --- diff --git a/queue-4.4/scsi-target-fix-xcopy-naa-identifier-lookup.patch b/queue-4.4/scsi-target-fix-xcopy-naa-identifier-lookup.patch new file mode 100644 index 00000000000..606cc5b40ae --- /dev/null +++ b/queue-4.4/scsi-target-fix-xcopy-naa-identifier-lookup.patch @@ -0,0 +1,214 @@ +From cf74a05aa4b07668e9359feaad61fb989cd205ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Nov 2020 02:21:58 +0100 +Subject: scsi: target: Fix XCOPY NAA identifier lookup + +From: David Disseldorp + +[ Upstream commit 2896c93811e39d63a4d9b63ccf12a8fbc226e5e4 ] + +When attempting to match EXTENDED COPY CSCD descriptors with corresponding +se_devices, target_xcopy_locate_se_dev_e4() currently iterates over LIO's +global devices list which includes all configured backstores. + +This change ensures that only initiator-accessible backstores are +considered during CSCD descriptor lookup, according to the session's +se_node_acl LUN list. + +To avoid LUN removal race conditions, device pinning is changed from being +configfs based to instead using the se_node_acl lun_ref. + +Reference: CVE-2020-28374 +Fixes: cbf031f425fd ("target: Add support for EXTENDED_COPY copy offload emulation") +Reviewed-by: Lee Duncan +Signed-off-by: David Disseldorp +Signed-off-by: Mike Christie +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/target/target_core_xcopy.c | 119 +++++++++++++++++------------ + drivers/target/target_core_xcopy.h | 1 + + 2 files changed, 71 insertions(+), 49 deletions(-) + +diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c +index b0e8f432c7205..9587375122295 100644 +--- a/drivers/target/target_core_xcopy.c ++++ b/drivers/target/target_core_xcopy.c +@@ -52,60 +52,83 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf) + return 0; + } + +-struct xcopy_dev_search_info { +- const unsigned char *dev_wwn; +- struct se_device *found_dev; +-}; +- ++/** ++ * target_xcopy_locate_se_dev_e4_iter - compare XCOPY NAA device identifiers ++ * ++ * @se_dev: device being considered for match ++ * @dev_wwn: XCOPY requested NAA dev_wwn ++ * @return: 1 on match, 0 on no-match ++ */ + static int target_xcopy_locate_se_dev_e4_iter(struct se_device *se_dev, +- void *data) ++ const unsigned char *dev_wwn) + { +- struct xcopy_dev_search_info *info = data; + unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN]; + int rc; + +- if (!se_dev->dev_attrib.emulate_3pc) ++ if (!se_dev->dev_attrib.emulate_3pc) { ++ pr_debug("XCOPY: emulate_3pc disabled on se_dev %p\n", se_dev); + return 0; ++ } + + memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN); + target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]); + +- rc = memcmp(&tmp_dev_wwn[0], info->dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN); +- if (rc != 0) +- return 0; +- +- info->found_dev = se_dev; +- pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev); +- +- rc = target_depend_item(&se_dev->dev_group.cg_item); ++ rc = memcmp(&tmp_dev_wwn[0], dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN); + if (rc != 0) { +- pr_err("configfs_depend_item attempt failed: %d for se_dev: %p\n", +- rc, se_dev); +- return rc; ++ pr_debug("XCOPY: skip non-matching: %*ph\n", ++ XCOPY_NAA_IEEE_REGEX_LEN, tmp_dev_wwn); ++ return 0; + } ++ pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev); + +- pr_debug("Called configfs_depend_item for se_dev: %p se_dev->se_dev_group: %p\n", +- se_dev, &se_dev->dev_group); + return 1; + } + +-static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn, +- struct se_device **found_dev) ++static int target_xcopy_locate_se_dev_e4(struct se_session *sess, ++ const unsigned char *dev_wwn, ++ struct se_device **_found_dev, ++ struct percpu_ref **_found_lun_ref) + { +- struct xcopy_dev_search_info info; +- int ret; +- +- memset(&info, 0, sizeof(info)); +- info.dev_wwn = dev_wwn; +- +- ret = target_for_each_device(target_xcopy_locate_se_dev_e4_iter, &info); +- if (ret == 1) { +- *found_dev = info.found_dev; +- return 0; +- } else { +- pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n"); +- return -EINVAL; ++ struct se_dev_entry *deve; ++ struct se_node_acl *nacl; ++ struct se_lun *this_lun = NULL; ++ struct se_device *found_dev = NULL; ++ ++ /* cmd with NULL sess indicates no associated $FABRIC_MOD */ ++ if (!sess) ++ goto err_out; ++ ++ pr_debug("XCOPY 0xe4: searching for: %*ph\n", ++ XCOPY_NAA_IEEE_REGEX_LEN, dev_wwn); ++ ++ nacl = sess->se_node_acl; ++ rcu_read_lock(); ++ hlist_for_each_entry_rcu(deve, &nacl->lun_entry_hlist, link) { ++ struct se_device *this_dev; ++ int rc; ++ ++ this_lun = rcu_dereference(deve->se_lun); ++ this_dev = rcu_dereference_raw(this_lun->lun_se_dev); ++ ++ rc = target_xcopy_locate_se_dev_e4_iter(this_dev, dev_wwn); ++ if (rc) { ++ if (percpu_ref_tryget_live(&this_lun->lun_ref)) ++ found_dev = this_dev; ++ break; ++ } + } ++ rcu_read_unlock(); ++ if (found_dev == NULL) ++ goto err_out; ++ ++ pr_debug("lun_ref held for se_dev: %p se_dev->se_dev_group: %p\n", ++ found_dev, &found_dev->dev_group); ++ *_found_dev = found_dev; ++ *_found_lun_ref = &this_lun->lun_ref; ++ return 0; ++err_out: ++ pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n"); ++ return -EINVAL; + } + + static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop, +@@ -248,12 +271,16 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, + + switch (xop->op_origin) { + case XCOL_SOURCE_RECV_OP: +- rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn, +- &xop->dst_dev); ++ rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess, ++ xop->dst_tid_wwn, ++ &xop->dst_dev, ++ &xop->remote_lun_ref); + break; + case XCOL_DEST_RECV_OP: +- rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn, +- &xop->src_dev); ++ rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess, ++ xop->src_tid_wwn, ++ &xop->src_dev, ++ &xop->remote_lun_ref); + break; + default: + pr_err("XCOPY CSCD descriptor IDs not found in CSCD list - " +@@ -397,18 +424,12 @@ static int xcopy_pt_get_cmd_state(struct se_cmd *se_cmd) + + static void xcopy_pt_undepend_remotedev(struct xcopy_op *xop) + { +- struct se_device *remote_dev; +- + if (xop->op_origin == XCOL_SOURCE_RECV_OP) +- remote_dev = xop->dst_dev; ++ pr_debug("putting dst lun_ref for %p\n", xop->dst_dev); + else +- remote_dev = xop->src_dev; +- +- pr_debug("Calling configfs_undepend_item for" +- " remote_dev: %p remote_dev->dev_group: %p\n", +- remote_dev, &remote_dev->dev_group.cg_item); ++ pr_debug("putting src lun_ref for %p\n", xop->src_dev); + +- target_undepend_item(&remote_dev->dev_group.cg_item); ++ percpu_ref_put(xop->remote_lun_ref); + } + + static void xcopy_pt_release_cmd(struct se_cmd *se_cmd) +diff --git a/drivers/target/target_core_xcopy.h b/drivers/target/target_core_xcopy.h +index 700a981c7b415..7db8d0c9223f8 100644 +--- a/drivers/target/target_core_xcopy.h ++++ b/drivers/target/target_core_xcopy.h +@@ -19,6 +19,7 @@ struct xcopy_op { + struct se_device *dst_dev; + unsigned char dst_tid_wwn[XCOPY_NAA_IEEE_REGEX_LEN]; + unsigned char local_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN]; ++ struct percpu_ref *remote_lun_ref; + + sector_t src_lba; + sector_t dst_lba; +-- +2.27.0 + diff --git a/queue-4.4/series b/queue-4.4/series new file mode 100644 index 00000000000..3390efa2250 --- /dev/null +++ b/queue-4.4/series @@ -0,0 +1,6 @@ +target-add-xcopy-target-segment-desc-sense-codes.patch +target-bounds-check-xcopy-segment-descriptor-list.patch +target-simplify-xcopy-wwn-se_dev-lookup-helper.patch +target-use-xcopy-segment-descriptor-cscd-ids.patch +xcopy-loop-over-devices-using-idr-helper.patch +scsi-target-fix-xcopy-naa-identifier-lookup.patch diff --git a/queue-4.4/target-add-xcopy-target-segment-desc-sense-codes.patch b/queue-4.4/target-add-xcopy-target-segment-desc-sense-codes.patch new file mode 100644 index 00000000000..7cdaf428522 --- /dev/null +++ b/queue-4.4/target-add-xcopy-target-segment-desc-sense-codes.patch @@ -0,0 +1,81 @@ +From a37be306c81143333087d2b0cd7aa7499d3395e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Dec 2016 11:37:53 +0100 +Subject: target: add XCOPY target/segment desc sense codes + +From: David Disseldorp + +[ Upstream commit e864212078ded276bdb272b2e0ee6a979357ca8a ] + +As defined in http://www.t10.org/lists/asc-num.htm. To be used during +validation of XCOPY target and segment descriptor lists. + +Signed-off-by: David Disseldorp +Reviewed-by: Christoph Hellwig +Signed-off-by: Bart Van Assche +Signed-off-by: Sasha Levin +--- + drivers/target/target_core_transport.c | 24 ++++++++++++++++++++++++ + include/target/target_core_base.h | 4 ++++ + 2 files changed, 28 insertions(+) + +diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c +index 7199bac673335..96cf2448a1f4f 100644 +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -1730,6 +1730,10 @@ void transport_generic_request_failure(struct se_cmd *cmd, + case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED: + case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED: + case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE: ++ case TCM_TOO_MANY_TARGET_DESCS: ++ case TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE: ++ case TCM_TOO_MANY_SEGMENT_DESCS: ++ case TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE: + break; + case TCM_OUT_OF_RESOURCES: + sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; +@@ -2864,6 +2868,26 @@ static const struct sense_info sense_info_table[] = { + .key = ILLEGAL_REQUEST, + .asc = 0x26, /* INVALID FIELD IN PARAMETER LIST */ + }, ++ [TCM_TOO_MANY_TARGET_DESCS] = { ++ .key = ILLEGAL_REQUEST, ++ .asc = 0x26, ++ .ascq = 0x06, /* TOO MANY TARGET DESCRIPTORS */ ++ }, ++ [TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE] = { ++ .key = ILLEGAL_REQUEST, ++ .asc = 0x26, ++ .ascq = 0x07, /* UNSUPPORTED TARGET DESCRIPTOR TYPE CODE */ ++ }, ++ [TCM_TOO_MANY_SEGMENT_DESCS] = { ++ .key = ILLEGAL_REQUEST, ++ .asc = 0x26, ++ .ascq = 0x08, /* TOO MANY SEGMENT DESCRIPTORS */ ++ }, ++ [TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE] = { ++ .key = ILLEGAL_REQUEST, ++ .asc = 0x26, ++ .ascq = 0x09, /* UNSUPPORTED SEGMENT DESCRIPTOR TYPE CODE */ ++ }, + [TCM_PARAMETER_LIST_LENGTH_ERROR] = { + .key = ILLEGAL_REQUEST, + .asc = 0x1a, /* PARAMETER LIST LENGTH ERROR */ +diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h +index 0eed9fd79ea55..5aa8e0e62e309 100644 +--- a/include/target/target_core_base.h ++++ b/include/target/target_core_base.h +@@ -181,6 +181,10 @@ enum tcm_sense_reason_table { + 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), ++ TCM_TOO_MANY_TARGET_DESCS = R(0x19), ++ TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE = R(0x1a), ++ TCM_TOO_MANY_SEGMENT_DESCS = R(0x1b), ++ TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE = R(0x1c), + #undef R + }; + +-- +2.27.0 + diff --git a/queue-4.4/target-bounds-check-xcopy-segment-descriptor-list.patch b/queue-4.4/target-bounds-check-xcopy-segment-descriptor-list.patch new file mode 100644 index 00000000000..fa78f594da2 --- /dev/null +++ b/queue-4.4/target-bounds-check-xcopy-segment-descriptor-list.patch @@ -0,0 +1,75 @@ +From 9a2926033a2993f9e64009452b69e39a45e1e73b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Dec 2016 11:37:55 +0100 +Subject: target: bounds check XCOPY segment descriptor list + +From: David Disseldorp + +[ Upstream commit af9f62c1686268c0517b289274d38f3a03bebd2a ] + +Check the length of the XCOPY request segment descriptor list against +the value advertised via the MAXIMUM SEGMENT DESCRIPTOR COUNT field in +the RECEIVE COPY OPERATING PARAMETERS response. + +spc4r37 6.4.3.5 states: + If the number of segment descriptors exceeds the allowed number, the + copy manager shall terminate the command with CHECK CONDITION status, + with the sense key set to ILLEGAL REQUEST, and the additional sense + code set to TOO MANY SEGMENT DESCRIPTORS. + +This functionality is testable using the libiscsi +ExtendedCopy.DescrLimits test. + +Signed-off-by: David Disseldorp +Reviewed-by: Christoph Hellwig +Signed-off-by: Bart Van Assche +Signed-off-by: Sasha Levin +--- + drivers/target/target_core_xcopy.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c +index 6415e9b09a529..cd71957c7075f 100644 +--- a/drivers/target/target_core_xcopy.c ++++ b/drivers/target/target_core_xcopy.c +@@ -305,17 +305,26 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op + + static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd, + struct xcopy_op *xop, unsigned char *p, +- unsigned int sdll) ++ unsigned int sdll, sense_reason_t *sense_ret) + { + unsigned char *desc = p; + unsigned int start = 0; + int offset = sdll % XCOPY_SEGMENT_DESC_LEN, rc, ret = 0; + ++ *sense_ret = TCM_INVALID_PARAMETER_LIST; ++ + if (offset != 0) { + pr_err("XCOPY segment descriptor list length is not" + " multiple of %d\n", XCOPY_SEGMENT_DESC_LEN); + return -EINVAL; + } ++ if (sdll > RCR_OP_MAX_SG_DESC_COUNT * XCOPY_SEGMENT_DESC_LEN) { ++ pr_err("XCOPY supports %u segment descriptor(s), sdll: %u too" ++ " large..\n", RCR_OP_MAX_SG_DESC_COUNT, sdll); ++ /* spc4r37 6.4.3.5 SEGMENT DESCRIPTOR LIST LENGTH field */ ++ *sense_ret = TCM_TOO_MANY_SEGMENT_DESCS; ++ return -EINVAL; ++ } + + while (start < sdll) { + /* +@@ -913,7 +922,8 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd) + seg_desc = &p[16]; + seg_desc += (rc * XCOPY_TARGET_DESC_LEN); + +- rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc, sdll); ++ rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc, ++ sdll, &ret); + if (rc <= 0) { + xcopy_pt_undepend_remotedev(xop); + goto out; +-- +2.27.0 + diff --git a/queue-4.4/target-simplify-xcopy-wwn-se_dev-lookup-helper.patch b/queue-4.4/target-simplify-xcopy-wwn-se_dev-lookup-helper.patch new file mode 100644 index 00000000000..fb79ab89dc1 --- /dev/null +++ b/queue-4.4/target-simplify-xcopy-wwn-se_dev-lookup-helper.patch @@ -0,0 +1,82 @@ +From bfeaf20c7abdda692c64dffc51a642e45d970833 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Jan 2017 18:04:05 +0100 +Subject: target: simplify XCOPY wwn->se_dev lookup helper + +From: David Disseldorp + +[ Upstream commit 94aae4caacda89a1bdb7198b260f4ca3595b7ed7 ] + +target_xcopy_locate_se_dev_e4() is used to locate an se_dev, based on +the WWN provided with the XCOPY request. Remove a couple of unneeded +arguments, and rely on the caller for the src/dst test. + +Signed-off-by: David Disseldorp +Reviewed-by: Christoph Hellwig +Signed-off-by: Bart Van Assche +Signed-off-by: Sasha Levin +--- + drivers/target/target_core_xcopy.c | 28 +++++++++------------------- + 1 file changed, 9 insertions(+), 19 deletions(-) + +diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c +index cd71957c7075f..c7bd27bfe3d8c 100644 +--- a/drivers/target/target_core_xcopy.c ++++ b/drivers/target/target_core_xcopy.c +@@ -52,18 +52,13 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf) + return 0; + } + +-static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op *xop, +- bool src) ++static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn, ++ struct se_device **found_dev) + { + struct se_device *se_dev; +- unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN], *dev_wwn; ++ unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN]; + int rc; + +- if (src) +- dev_wwn = &xop->dst_tid_wwn[0]; +- else +- dev_wwn = &xop->src_tid_wwn[0]; +- + mutex_lock(&g_device_mutex); + list_for_each_entry(se_dev, &g_device_list, g_dev_node) { + +@@ -77,15 +72,8 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op + if (rc != 0) + continue; + +- if (src) { +- xop->dst_dev = se_dev; +- pr_debug("XCOPY 0xe4: Setting xop->dst_dev: %p from located" +- " se_dev\n", xop->dst_dev); +- } else { +- xop->src_dev = se_dev; +- pr_debug("XCOPY 0xe4: Setting xop->src_dev: %p from located" +- " se_dev\n", xop->src_dev); +- } ++ *found_dev = se_dev; ++ pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev); + + rc = target_depend_item(&se_dev->dev_group.cg_item); + if (rc != 0) { +@@ -242,9 +230,11 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, + } + + if (xop->op_origin == XCOL_SOURCE_RECV_OP) +- rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true); ++ rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn, ++ &xop->dst_dev); + else +- rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false); ++ rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn, ++ &xop->src_dev); + /* + * If a matching IEEE NAA 0x83 descriptor for the requested device + * is not located on this node, return COPY_ABORTED with ASQ/ASQC +-- +2.27.0 + diff --git a/queue-4.4/target-use-xcopy-segment-descriptor-cscd-ids.patch b/queue-4.4/target-use-xcopy-segment-descriptor-cscd-ids.patch new file mode 100644 index 00000000000..b04f14b3637 --- /dev/null +++ b/queue-4.4/target-use-xcopy-segment-descriptor-cscd-ids.patch @@ -0,0 +1,221 @@ +From cd20770999142e0650e81a711817eeb9b5aa2521 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Jan 2017 18:04:07 +0100 +Subject: target: use XCOPY segment descriptor CSCD IDs + +From: David Disseldorp + +[ Upstream commit 66640d35c1e4ef3c96ba5edb3c5e2ff8ab812e7a ] + +The XCOPY specification in SPC4r37 states that the XCOPY source and +destination device(s) should be derived from the copy source and copy +destination (CSCD) descriptor IDs in the XCOPY segment descriptor. + +The CSCD IDs are generally (for block -> block copies), indexes into +the corresponding CSCD descriptor list, e.g. +================================= +EXTENDED COPY Header +================================= +CSCD Descriptor List +- entry 0 + + LU ID <--------------<------------------\ +- entry 1 | + + LU ID <______________<_____________ | +================================= | | +Segment Descriptor List | | +- segment 0 | | + + src CSCD ID = 0 --------->---------+----/ + + dest CSCD ID = 1 ___________>______| + + len + + src lba + + dest lba +================================= + +Currently LIO completely ignores the src and dest CSCD IDs in the +Segment Descriptor List, and instead assumes that the first entry in the +CSCD list corresponds to the source, and the second to the destination. + +This commit removes this assumption, by ensuring that the Segment +Descriptor List is parsed prior to processing the CSCD Descriptor List. +CSCD Descriptor List processing is modified to compare the current list +index with the previously obtained src and dest CSCD IDs. + +Additionally, XCOPY requests where the src and dest CSCD IDs refer to +the CSCD Descriptor List entry can now be successfully processed. + +Fixes: cbf031f ("target: Add support for EXTENDED_COPY copy offload") +Link: https://bugzilla.kernel.org/show_bug.cgi?id=191381 +Signed-off-by: David Disseldorp +Reviewed-by: Christoph Hellwig +Signed-off-by: Bart Van Assche +Signed-off-by: Sasha Levin +--- + drivers/target/target_core_xcopy.c | 79 ++++++++++++++++++------------ + 1 file changed, 48 insertions(+), 31 deletions(-) + +diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c +index c7bd27bfe3d8c..32db9180820e7 100644 +--- a/drivers/target/target_core_xcopy.c ++++ b/drivers/target/target_core_xcopy.c +@@ -97,7 +97,7 @@ static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn, + } + + static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop, +- unsigned char *p, bool src) ++ unsigned char *p, unsigned short cscd_index) + { + unsigned char *desc = p; + unsigned short ript; +@@ -142,7 +142,13 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op + return -EINVAL; + } + +- if (src) { ++ if (cscd_index != xop->stdi && cscd_index != xop->dtdi) { ++ pr_debug("XCOPY 0xe4: ignoring CSCD entry %d - neither src nor " ++ "dest\n", cscd_index); ++ return 0; ++ } ++ ++ if (cscd_index == xop->stdi) { + memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN); + /* + * Determine if the source designator matches the local device +@@ -154,10 +160,15 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op + pr_debug("XCOPY 0xe4: Set xop->src_dev %p from source" + " received xop\n", xop->src_dev); + } +- } else { ++ } ++ ++ if (cscd_index == xop->dtdi) { + memcpy(&xop->dst_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN); + /* +- * Determine if the destination designator matches the local device ++ * Determine if the destination designator matches the local ++ * device. If @cscd_index corresponds to both source (stdi) and ++ * destination (dtdi), or dtdi comes after stdi, then ++ * XCOL_DEST_RECV_OP wins. + */ + if (!memcmp(&xop->local_dev_wwn[0], &xop->dst_tid_wwn[0], + XCOPY_NAA_IEEE_REGEX_LEN)) { +@@ -177,9 +188,9 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, + { + struct se_device *local_dev = se_cmd->se_dev; + unsigned char *desc = p; +- int offset = tdll % XCOPY_TARGET_DESC_LEN, rc, ret = 0; ++ int offset = tdll % XCOPY_TARGET_DESC_LEN, rc; ++ unsigned short cscd_index = 0; + unsigned short start = 0; +- bool src = true; + + *sense_ret = TCM_INVALID_PARAMETER_LIST; + +@@ -202,25 +213,19 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, + + while (start < tdll) { + /* +- * Check target descriptor identification with 0xE4 type with +- * use VPD 0x83 WWPN matching .. ++ * Check target descriptor identification with 0xE4 type, and ++ * compare the current index with the CSCD descriptor IDs in ++ * the segment descriptor. Use VPD 0x83 WWPN matching .. + */ + switch (desc[0]) { + case 0xe4: + rc = target_xcopy_parse_tiddesc_e4(se_cmd, xop, +- &desc[0], src); ++ &desc[0], cscd_index); + if (rc != 0) + goto out; +- /* +- * Assume target descriptors are in source -> destination order.. +- */ +- if (src) +- src = false; +- else +- src = true; + start += XCOPY_TARGET_DESC_LEN; + desc += XCOPY_TARGET_DESC_LEN; +- ret++; ++ cscd_index++; + break; + default: + pr_err("XCOPY unsupported descriptor type code:" +@@ -229,12 +234,21 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, + } + } + +- if (xop->op_origin == XCOL_SOURCE_RECV_OP) ++ switch (xop->op_origin) { ++ case XCOL_SOURCE_RECV_OP: + rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn, + &xop->dst_dev); +- else ++ break; ++ case XCOL_DEST_RECV_OP: + rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn, + &xop->src_dev); ++ break; ++ default: ++ pr_err("XCOPY CSCD descriptor IDs not found in CSCD list - " ++ "stdi: %hu dtdi: %hu\n", xop->stdi, xop->dtdi); ++ rc = -EINVAL; ++ break; ++ } + /* + * If a matching IEEE NAA 0x83 descriptor for the requested device + * is not located on this node, return COPY_ABORTED with ASQ/ASQC +@@ -251,7 +265,7 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, + pr_debug("XCOPY TGT desc: Dest dev: %p NAA IEEE WWN: 0x%16phN\n", + xop->dst_dev, &xop->dst_tid_wwn[0]); + +- return ret; ++ return cscd_index; + + out: + return -EINVAL; +@@ -892,6 +906,20 @@ 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); + ++ /* ++ * skip over the target descriptors until segment descriptors ++ * have been passed - CSCD ids are needed to determine src and dest. ++ */ ++ seg_desc = &p[16] + tdll; ++ ++ rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc, ++ sdll, &ret); ++ if (rc <= 0) ++ goto out; ++ ++ pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc, ++ rc * XCOPY_SEGMENT_DESC_LEN); ++ + rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret); + if (rc <= 0) + goto out; +@@ -909,19 +937,8 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd) + + pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc, + rc * XCOPY_TARGET_DESC_LEN); +- seg_desc = &p[16]; +- seg_desc += (rc * XCOPY_TARGET_DESC_LEN); +- +- rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc, +- sdll, &ret); +- if (rc <= 0) { +- xcopy_pt_undepend_remotedev(xop); +- goto out; +- } + transport_kunmap_data_sg(se_cmd); + +- pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc, +- rc * XCOPY_SEGMENT_DESC_LEN); + INIT_WORK(&xop->xop_work, target_xcopy_do_work); + queue_work(xcopy_wq, &xop->xop_work); + return TCM_NO_SENSE; +-- +2.27.0 + diff --git a/queue-4.4/xcopy-loop-over-devices-using-idr-helper.patch b/queue-4.4/xcopy-loop-over-devices-using-idr-helper.patch new file mode 100644 index 00000000000..864a2b9757d --- /dev/null +++ b/queue-4.4/xcopy-loop-over-devices-using-idr-helper.patch @@ -0,0 +1,118 @@ +From ba0c874a592ca30ff73f77f3733a716726ae4cf5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Jun 2017 01:18:17 -0500 +Subject: xcopy: loop over devices using idr helper + +From: Mike Christie + +[ Upstream commit 6906d008b4b06e42cad393ac25bec76fbf31fabd ] + +This converts the xcopy code to use the idr helper. The next patch +will drop the g_device_list and make g_device_mutex local to the +target_core_device.c file. + +Signed-off-by: Mike Christie +Reviewed-by: Bart Van Assche +Signed-off-by: Nicholas Bellinger +Signed-off-by: Sasha Levin +--- + drivers/target/target_core_xcopy.c | 70 +++++++++++++++++------------- + 1 file changed, 41 insertions(+), 29 deletions(-) + +diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c +index 32db9180820e7..b0e8f432c7205 100644 +--- a/drivers/target/target_core_xcopy.c ++++ b/drivers/target/target_core_xcopy.c +@@ -52,48 +52,60 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf) + return 0; + } + +-static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn, +- struct se_device **found_dev) ++struct xcopy_dev_search_info { ++ const unsigned char *dev_wwn; ++ struct se_device *found_dev; ++}; ++ ++static int target_xcopy_locate_se_dev_e4_iter(struct se_device *se_dev, ++ void *data) + { +- struct se_device *se_dev; ++ struct xcopy_dev_search_info *info = data; + unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN]; + int rc; + +- mutex_lock(&g_device_mutex); +- list_for_each_entry(se_dev, &g_device_list, g_dev_node) { ++ if (!se_dev->dev_attrib.emulate_3pc) ++ return 0; + +- if (!se_dev->dev_attrib.emulate_3pc) +- continue; ++ memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN); ++ target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]); + +- memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN); +- target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]); ++ rc = memcmp(&tmp_dev_wwn[0], info->dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN); ++ if (rc != 0) ++ return 0; + +- rc = memcmp(&tmp_dev_wwn[0], dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN); +- if (rc != 0) +- continue; ++ info->found_dev = se_dev; ++ pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev); + +- *found_dev = se_dev; +- pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev); ++ rc = target_depend_item(&se_dev->dev_group.cg_item); ++ if (rc != 0) { ++ pr_err("configfs_depend_item attempt failed: %d for se_dev: %p\n", ++ rc, se_dev); ++ return rc; ++ } + +- rc = target_depend_item(&se_dev->dev_group.cg_item); +- if (rc != 0) { +- pr_err("configfs_depend_item attempt failed:" +- " %d for se_dev: %p\n", rc, se_dev); +- mutex_unlock(&g_device_mutex); +- return rc; +- } ++ pr_debug("Called configfs_depend_item for se_dev: %p se_dev->se_dev_group: %p\n", ++ se_dev, &se_dev->dev_group); ++ return 1; ++} ++ ++static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn, ++ struct se_device **found_dev) ++{ ++ struct xcopy_dev_search_info info; ++ int ret; + +- pr_debug("Called configfs_depend_item for se_dev: %p" +- " se_dev->se_dev_group: %p\n", se_dev, +- &se_dev->dev_group); ++ memset(&info, 0, sizeof(info)); ++ info.dev_wwn = dev_wwn; + +- mutex_unlock(&g_device_mutex); ++ ret = target_for_each_device(target_xcopy_locate_se_dev_e4_iter, &info); ++ if (ret == 1) { ++ *found_dev = info.found_dev; + return 0; ++ } else { ++ pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n"); ++ return -EINVAL; + } +- mutex_unlock(&g_device_mutex); +- +- pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n"); +- return -EINVAL; + } + + static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop, +-- +2.27.0 +