aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/target/target_core_xcopy.c79
1 files changed, 48 insertions, 31 deletions
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c
index 41a2a8ad1046..2595c1eb9e91 100644
--- a/drivers/target/target_core_xcopy.c
+++ b/drivers/target/target_core_xcopy.c
@@ -98,7 +98,7 @@ static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn,
98} 98}
99 99
100static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop, 100static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop,
101 unsigned char *p, bool src) 101 unsigned char *p, unsigned short cscd_index)
102{ 102{
103 unsigned char *desc = p; 103 unsigned char *desc = p;
104 unsigned short ript; 104 unsigned short ript;
@@ -143,7 +143,13 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
143 return -EINVAL; 143 return -EINVAL;
144 } 144 }
145 145
146 if (src) { 146 if (cscd_index != xop->stdi && cscd_index != xop->dtdi) {
147 pr_debug("XCOPY 0xe4: ignoring CSCD entry %d - neither src nor "
148 "dest\n", cscd_index);
149 return 0;
150 }
151
152 if (cscd_index == xop->stdi) {
147 memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN); 153 memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
148 /* 154 /*
149 * Determine if the source designator matches the local device 155 * Determine if the source designator matches the local device
@@ -155,10 +161,15 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
155 pr_debug("XCOPY 0xe4: Set xop->src_dev %p from source" 161 pr_debug("XCOPY 0xe4: Set xop->src_dev %p from source"
156 " received xop\n", xop->src_dev); 162 " received xop\n", xop->src_dev);
157 } 163 }
158 } else { 164 }
165
166 if (cscd_index == xop->dtdi) {
159 memcpy(&xop->dst_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN); 167 memcpy(&xop->dst_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
160 /* 168 /*
161 * Determine if the destination designator matches the local device 169 * Determine if the destination designator matches the local
170 * device. If @cscd_index corresponds to both source (stdi) and
171 * destination (dtdi), or dtdi comes after stdi, then
172 * XCOL_DEST_RECV_OP wins.
162 */ 173 */
163 if (!memcmp(&xop->local_dev_wwn[0], &xop->dst_tid_wwn[0], 174 if (!memcmp(&xop->local_dev_wwn[0], &xop->dst_tid_wwn[0],
164 XCOPY_NAA_IEEE_REGEX_LEN)) { 175 XCOPY_NAA_IEEE_REGEX_LEN)) {
@@ -178,9 +189,9 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
178{ 189{
179 struct se_device *local_dev = se_cmd->se_dev; 190 struct se_device *local_dev = se_cmd->se_dev;
180 unsigned char *desc = p; 191 unsigned char *desc = p;
181 int offset = tdll % XCOPY_TARGET_DESC_LEN, rc, ret = 0; 192 int offset = tdll % XCOPY_TARGET_DESC_LEN, rc;
193 unsigned short cscd_index = 0;
182 unsigned short start = 0; 194 unsigned short start = 0;
183 bool src = true;
184 195
185 *sense_ret = TCM_INVALID_PARAMETER_LIST; 196 *sense_ret = TCM_INVALID_PARAMETER_LIST;
186 197
@@ -206,25 +217,19 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
206 217
207 while (start < tdll) { 218 while (start < tdll) {
208 /* 219 /*
209 * Check target descriptor identification with 0xE4 type with 220 * Check target descriptor identification with 0xE4 type, and
210 * use VPD 0x83 WWPN matching .. 221 * compare the current index with the CSCD descriptor IDs in
222 * the segment descriptor. Use VPD 0x83 WWPN matching ..
211 */ 223 */
212 switch (desc[0]) { 224 switch (desc[0]) {
213 case 0xe4: 225 case 0xe4:
214 rc = target_xcopy_parse_tiddesc_e4(se_cmd, xop, 226 rc = target_xcopy_parse_tiddesc_e4(se_cmd, xop,
215 &desc[0], src); 227 &desc[0], cscd_index);
216 if (rc != 0) 228 if (rc != 0)
217 goto out; 229 goto out;
218 /*
219 * Assume target descriptors are in source -> destination order..
220 */
221 if (src)
222 src = false;
223 else
224 src = true;
225 start += XCOPY_TARGET_DESC_LEN; 230 start += XCOPY_TARGET_DESC_LEN;
226 desc += XCOPY_TARGET_DESC_LEN; 231 desc += XCOPY_TARGET_DESC_LEN;
227 ret++; 232 cscd_index++;
228 break; 233 break;
229 default: 234 default:
230 pr_err("XCOPY unsupported descriptor type code:" 235 pr_err("XCOPY unsupported descriptor type code:"
@@ -234,12 +239,21 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
234 } 239 }
235 } 240 }
236 241
237 if (xop->op_origin == XCOL_SOURCE_RECV_OP) 242 switch (xop->op_origin) {
243 case XCOL_SOURCE_RECV_OP:
238 rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn, 244 rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn,
239 &xop->dst_dev); 245 &xop->dst_dev);
240 else 246 break;
247 case XCOL_DEST_RECV_OP:
241 rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn, 248 rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn,
242 &xop->src_dev); 249 &xop->src_dev);
250 break;
251 default:
252 pr_err("XCOPY CSCD descriptor IDs not found in CSCD list - "
253 "stdi: %hu dtdi: %hu\n", xop->stdi, xop->dtdi);
254 rc = -EINVAL;
255 break;
256 }
243 /* 257 /*
244 * If a matching IEEE NAA 0x83 descriptor for the requested device 258 * If a matching IEEE NAA 0x83 descriptor for the requested device
245 * is not located on this node, return COPY_ABORTED with ASQ/ASQC 259 * is not located on this node, return COPY_ABORTED with ASQ/ASQC
@@ -256,7 +270,7 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
256 pr_debug("XCOPY TGT desc: Dest dev: %p NAA IEEE WWN: 0x%16phN\n", 270 pr_debug("XCOPY TGT desc: Dest dev: %p NAA IEEE WWN: 0x%16phN\n",
257 xop->dst_dev, &xop->dst_tid_wwn[0]); 271 xop->dst_dev, &xop->dst_tid_wwn[0]);
258 272
259 return ret; 273 return cscd_index;
260 274
261out: 275out:
262 return -EINVAL; 276 return -EINVAL;
@@ -913,6 +927,20 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
913 " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage, 927 " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
914 tdll, sdll, inline_dl); 928 tdll, sdll, inline_dl);
915 929
930 /*
931 * skip over the target descriptors until segment descriptors
932 * have been passed - CSCD ids are needed to determine src and dest.
933 */
934 seg_desc = &p[16] + tdll;
935
936 rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc,
937 sdll, &ret);
938 if (rc <= 0)
939 goto out;
940
941 pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc,
942 rc * XCOPY_SEGMENT_DESC_LEN);
943
916 rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret); 944 rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret);
917 if (rc <= 0) 945 if (rc <= 0)
918 goto out; 946 goto out;
@@ -930,19 +958,8 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
930 958
931 pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc, 959 pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc,
932 rc * XCOPY_TARGET_DESC_LEN); 960 rc * XCOPY_TARGET_DESC_LEN);
933 seg_desc = &p[16];
934 seg_desc += (rc * XCOPY_TARGET_DESC_LEN);
935
936 rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc,
937 sdll, &ret);
938 if (rc <= 0) {
939 xcopy_pt_undepend_remotedev(xop);
940 goto out;
941 }
942 transport_kunmap_data_sg(se_cmd); 961 transport_kunmap_data_sg(se_cmd);
943 962
944 pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc,
945 rc * XCOPY_SEGMENT_DESC_LEN);
946 INIT_WORK(&xop->xop_work, target_xcopy_do_work); 963 INIT_WORK(&xop->xop_work, target_xcopy_do_work);
947 queue_work(xcopy_wq, &xop->xop_work); 964 queue_work(xcopy_wq, &xop->xop_work);
948 return TCM_NO_SENSE; 965 return TCM_NO_SENSE;