Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   1/*******************************************************************************
   2 * Filename: target_core_xcopy.c
   3 *
   4 * This file contains support for SPC-4 Extended-Copy offload with generic
   5 * TCM backends.
   6 *
   7 * Copyright (c) 2011-2013 Datera, Inc. All rights reserved.
   8 *
   9 * Author:
  10 * Nicholas A. Bellinger <nab@daterainc.com>
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License as published by
  14 * the Free Software Foundation; either version 2 of the License, or
  15 * (at your option) any later version.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 *
  22 ******************************************************************************/
  23
  24#include <linux/slab.h>
  25#include <linux/spinlock.h>
  26#include <linux/list.h>
  27#include <linux/configfs.h>
  28#include <linux/ratelimit.h>
  29#include <scsi/scsi_proto.h>
  30#include <asm/unaligned.h>
  31
  32#include <target/target_core_base.h>
  33#include <target/target_core_backend.h>
  34#include <target/target_core_fabric.h>
  35
  36#include "target_core_internal.h"
  37#include "target_core_pr.h"
  38#include "target_core_ua.h"
  39#include "target_core_xcopy.h"
  40
  41static struct workqueue_struct *xcopy_wq = NULL;
  42
  43static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf)
  44{
  45	int off = 0;
  46
  47	buf[off++] = (0x6 << 4);
  48	buf[off++] = 0x01;
  49	buf[off++] = 0x40;
  50	buf[off] = (0x5 << 4);
  51
  52	spc_parse_naa_6h_vendor_specific(dev, &buf[off]);
  53	return 0;
  54}
  55
  56static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn,
  57					struct se_device **found_dev)
  58{
  59	struct se_device *se_dev;
  60	unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
  61	int rc;
  62
  63	mutex_lock(&g_device_mutex);
  64	list_for_each_entry(se_dev, &g_device_list, g_dev_node) {
  65
  66		if (!se_dev->dev_attrib.emulate_3pc)
  67			continue;
  68
  69		memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN);
  70		target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]);
  71
  72		rc = memcmp(&tmp_dev_wwn[0], dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN);
  73		if (rc != 0)
  74			continue;
  75
  76		*found_dev = se_dev;
  77		pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
  78
  79		rc = target_depend_item(&se_dev->dev_group.cg_item);
  80		if (rc != 0) {
  81			pr_err("configfs_depend_item attempt failed:"
  82				" %d for se_dev: %p\n", rc, se_dev);
  83			mutex_unlock(&g_device_mutex);
  84			return rc;
  85		}
  86
  87		pr_debug("Called configfs_depend_item for se_dev: %p"
  88			" se_dev->se_dev_group: %p\n", se_dev,
  89			&se_dev->dev_group);
  90
  91		mutex_unlock(&g_device_mutex);
  92		return 0;
  93	}
  94	mutex_unlock(&g_device_mutex);
  95
  96	pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
  97	return -EINVAL;
  98}
  99
 100static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop,
 101				unsigned char *p, unsigned short cscd_index)
 102{
 103	unsigned char *desc = p;
 104	unsigned short ript;
 105	u8 desig_len;
 106	/*
 107	 * Extract RELATIVE INITIATOR PORT IDENTIFIER
 108	 */
 109	ript = get_unaligned_be16(&desc[2]);
 110	pr_debug("XCOPY 0xe4: RELATIVE INITIATOR PORT IDENTIFIER: %hu\n", ript);
 111	/*
 112	 * Check for supported code set, association, and designator type
 113	 */
 114	if ((desc[4] & 0x0f) != 0x1) {
 115		pr_err("XCOPY 0xe4: code set of non binary type not supported\n");
 116		return -EINVAL;
 117	}
 118	if ((desc[5] & 0x30) != 0x00) {
 119		pr_err("XCOPY 0xe4: association other than LUN not supported\n");
 120		return -EINVAL;
 121	}
 122	if ((desc[5] & 0x0f) != 0x3) {
 123		pr_err("XCOPY 0xe4: designator type unsupported: 0x%02x\n",
 124				(desc[5] & 0x0f));
 125		return -EINVAL;
 126	}
 127	/*
 128	 * Check for matching 16 byte length for NAA IEEE Registered Extended
 129	 * Assigned designator
 130	 */
 131	desig_len = desc[7];
 132	if (desig_len != 16) {
 133		pr_err("XCOPY 0xe4: invalid desig_len: %d\n", (int)desig_len);
 134		return -EINVAL;
 135	}
 136	pr_debug("XCOPY 0xe4: desig_len: %d\n", (int)desig_len);
 137	/*
 138	 * Check for NAA IEEE Registered Extended Assigned header..
 139	 */
 140	if ((desc[8] & 0xf0) != 0x60) {
 141		pr_err("XCOPY 0xe4: Unsupported DESIGNATOR TYPE: 0x%02x\n",
 142					(desc[8] & 0xf0));
 143		return -EINVAL;
 144	}
 145
 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) {
 153		memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
 154		/*
 155		 * Determine if the source designator matches the local device
 156		 */
 157		if (!memcmp(&xop->local_dev_wwn[0], &xop->src_tid_wwn[0],
 158				XCOPY_NAA_IEEE_REGEX_LEN)) {
 159			xop->op_origin = XCOL_SOURCE_RECV_OP;
 160			xop->src_dev = se_cmd->se_dev;
 161			pr_debug("XCOPY 0xe4: Set xop->src_dev %p from source"
 162					" received xop\n", xop->src_dev);
 163		}
 164	}
 165
 166	if (cscd_index == xop->dtdi) {
 167		memcpy(&xop->dst_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
 168		/*
 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.
 173		 */
 174		if (!memcmp(&xop->local_dev_wwn[0], &xop->dst_tid_wwn[0],
 175				XCOPY_NAA_IEEE_REGEX_LEN)) {
 176			xop->op_origin = XCOL_DEST_RECV_OP;
 177			xop->dst_dev = se_cmd->se_dev;
 178			pr_debug("XCOPY 0xe4: Set xop->dst_dev: %p from destination"
 179				" received xop\n", xop->dst_dev);
 180		}
 181	}
 182
 183	return 0;
 184}
 185
 186static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
 187				struct xcopy_op *xop, unsigned char *p,
 188				unsigned short tdll, sense_reason_t *sense_ret)
 189{
 190	struct se_device *local_dev = se_cmd->se_dev;
 191	unsigned char *desc = p;
 192	int offset = tdll % XCOPY_TARGET_DESC_LEN, rc;
 193	unsigned short cscd_index = 0;
 194	unsigned short start = 0;
 195
 196	*sense_ret = TCM_INVALID_PARAMETER_LIST;
 197
 198	if (offset != 0) {
 199		pr_err("XCOPY target descriptor list length is not"
 200			" multiple of %d\n", XCOPY_TARGET_DESC_LEN);
 201		*sense_ret = TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE;
 202		return -EINVAL;
 203	}
 204	if (tdll > RCR_OP_MAX_TARGET_DESC_COUNT * XCOPY_TARGET_DESC_LEN) {
 205		pr_err("XCOPY target descriptor supports a maximum"
 206			" two src/dest descriptors, tdll: %hu too large..\n", tdll);
 207		/* spc4r37 6.4.3.4 CSCD DESCRIPTOR LIST LENGTH field */
 208		*sense_ret = TCM_TOO_MANY_TARGET_DESCS;
 209		return -EINVAL;
 210	}
 211	/*
 212	 * Generate an IEEE Registered Extended designator based upon the
 213	 * se_device the XCOPY was received upon..
 214	 */
 215	memset(&xop->local_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN);
 216	target_xcopy_gen_naa_ieee(local_dev, &xop->local_dev_wwn[0]);
 217
 218	while (start < tdll) {
 219		/*
 220		 * Check target descriptor identification with 0xE4 type, and
 221		 * compare the current index with the CSCD descriptor IDs in
 222		 * the segment descriptor. Use VPD 0x83 WWPN matching ..
 223		 */
 224		switch (desc[0]) {
 225		case 0xe4:
 226			rc = target_xcopy_parse_tiddesc_e4(se_cmd, xop,
 227							&desc[0], cscd_index);
 228			if (rc != 0)
 229				goto out;
 230			start += XCOPY_TARGET_DESC_LEN;
 231			desc += XCOPY_TARGET_DESC_LEN;
 232			cscd_index++;
 233			break;
 234		default:
 235			pr_err("XCOPY unsupported descriptor type code:"
 236					" 0x%02x\n", desc[0]);
 237			*sense_ret = TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE;
 238			goto out;
 239		}
 240	}
 241
 242	switch (xop->op_origin) {
 243	case XCOL_SOURCE_RECV_OP:
 244		rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn,
 245						&xop->dst_dev);
 246		break;
 247	case XCOL_DEST_RECV_OP:
 248		rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn,
 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	}
 257	/*
 258	 * If a matching IEEE NAA 0x83 descriptor for the requested device
 259	 * is not located on this node, return COPY_ABORTED with ASQ/ASQC
 260	 * 0x0d/0x02 - COPY_TARGET_DEVICE_NOT_REACHABLE to request the
 261	 * initiator to fall back to normal copy method.
 262	 */
 263	if (rc < 0) {
 264		*sense_ret = TCM_COPY_TARGET_DEVICE_NOT_REACHABLE;
 265		goto out;
 266	}
 267
 268	pr_debug("XCOPY TGT desc: Source dev: %p NAA IEEE WWN: 0x%16phN\n",
 269		 xop->src_dev, &xop->src_tid_wwn[0]);
 270	pr_debug("XCOPY TGT desc: Dest dev: %p NAA IEEE WWN: 0x%16phN\n",
 271		 xop->dst_dev, &xop->dst_tid_wwn[0]);
 272
 273	return cscd_index;
 274
 275out:
 276	return -EINVAL;
 277}
 278
 279static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op *xop,
 280					unsigned char *p)
 281{
 282	unsigned char *desc = p;
 283	int dc = (desc[1] & 0x02);
 284	unsigned short desc_len;
 285
 286	desc_len = get_unaligned_be16(&desc[2]);
 287	if (desc_len != 0x18) {
 288		pr_err("XCOPY segment desc 0x02: Illegal desc_len:"
 289				" %hu\n", desc_len);
 290		return -EINVAL;
 291	}
 292
 293	xop->stdi = get_unaligned_be16(&desc[4]);
 294	xop->dtdi = get_unaligned_be16(&desc[6]);
 295
 296	if (xop->stdi > XCOPY_CSCD_DESC_ID_LIST_OFF_MAX ||
 297	    xop->dtdi > XCOPY_CSCD_DESC_ID_LIST_OFF_MAX) {
 298		pr_err("XCOPY segment desc 0x02: unsupported CSCD ID > 0x%x; stdi: %hu dtdi: %hu\n",
 299			XCOPY_CSCD_DESC_ID_LIST_OFF_MAX, xop->stdi, xop->dtdi);
 300		return -EINVAL;
 301	}
 302
 303	pr_debug("XCOPY seg desc 0x02: desc_len: %hu stdi: %hu dtdi: %hu, DC: %d\n",
 304		desc_len, xop->stdi, xop->dtdi, dc);
 305
 306	xop->nolb = get_unaligned_be16(&desc[10]);
 307	xop->src_lba = get_unaligned_be64(&desc[12]);
 308	xop->dst_lba = get_unaligned_be64(&desc[20]);
 309	pr_debug("XCOPY seg desc 0x02: nolb: %hu src_lba: %llu dst_lba: %llu\n",
 310		xop->nolb, (unsigned long long)xop->src_lba,
 311		(unsigned long long)xop->dst_lba);
 312
 313	if (dc != 0) {
 314		xop->dbl = (desc[29] & 0xff) << 16;
 315		xop->dbl |= (desc[30] & 0xff) << 8;
 316		xop->dbl |= desc[31] & 0xff;
 317
 318		pr_debug("XCOPY seg desc 0x02: DC=1 w/ dbl: %u\n", xop->dbl);
 319	}
 320	return 0;
 321}
 322
 323static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd,
 324				struct xcopy_op *xop, unsigned char *p,
 325				unsigned int sdll, sense_reason_t *sense_ret)
 326{
 327	unsigned char *desc = p;
 328	unsigned int start = 0;
 329	int offset = sdll % XCOPY_SEGMENT_DESC_LEN, rc, ret = 0;
 330
 331	*sense_ret = TCM_INVALID_PARAMETER_LIST;
 332
 333	if (offset != 0) {
 334		pr_err("XCOPY segment descriptor list length is not"
 335			" multiple of %d\n", XCOPY_SEGMENT_DESC_LEN);
 336		*sense_ret = TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE;
 337		return -EINVAL;
 338	}
 339	if (sdll > RCR_OP_MAX_SG_DESC_COUNT * XCOPY_SEGMENT_DESC_LEN) {
 340		pr_err("XCOPY supports %u segment descriptor(s), sdll: %u too"
 341			" large..\n", RCR_OP_MAX_SG_DESC_COUNT, sdll);
 342		/* spc4r37 6.4.3.5 SEGMENT DESCRIPTOR LIST LENGTH field */
 343		*sense_ret = TCM_TOO_MANY_SEGMENT_DESCS;
 344		return -EINVAL;
 345	}
 346
 347	while (start < sdll) {
 348		/*
 349		 * Check segment descriptor type code for block -> block
 350		 */
 351		switch (desc[0]) {
 352		case 0x02:
 353			rc = target_xcopy_parse_segdesc_02(se_cmd, xop, desc);
 354			if (rc < 0)
 355				goto out;
 356
 357			ret++;
 358			start += XCOPY_SEGMENT_DESC_LEN;
 359			desc += XCOPY_SEGMENT_DESC_LEN;
 360			break;
 361		default:
 362			pr_err("XCOPY unsupported segment descriptor"
 363				"type: 0x%02x\n", desc[0]);
 364			*sense_ret = TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE;
 365			goto out;
 366		}
 367	}
 368
 369	return ret;
 370
 371out:
 372	return -EINVAL;
 373}
 374
 375/*
 376 * Start xcopy_pt ops
 377 */
 378
 379struct xcopy_pt_cmd {
 380	bool remote_port;
 381	struct se_cmd se_cmd;
 382	struct xcopy_op *xcopy_op;
 383	struct completion xpt_passthrough_sem;
 384	unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER];
 385};
 386
 387struct se_portal_group xcopy_pt_tpg;
 388static struct se_session xcopy_pt_sess;
 389static struct se_node_acl xcopy_pt_nacl;
 390
 391static char *xcopy_pt_get_fabric_name(void)
 392{
 393        return "xcopy-pt";
 394}
 395
 396static int xcopy_pt_get_cmd_state(struct se_cmd *se_cmd)
 397{
 398        return 0;
 399}
 400
 401static void xcopy_pt_undepend_remotedev(struct xcopy_op *xop)
 402{
 403	struct se_device *remote_dev;
 404
 405	if (xop->op_origin == XCOL_SOURCE_RECV_OP)
 406		remote_dev = xop->dst_dev;
 407	else
 408		remote_dev = xop->src_dev;
 409
 410	pr_debug("Calling configfs_undepend_item for"
 411		  " remote_dev: %p remote_dev->dev_group: %p\n",
 412		  remote_dev, &remote_dev->dev_group.cg_item);
 413
 414	target_undepend_item(&remote_dev->dev_group.cg_item);
 415}
 416
 417static void xcopy_pt_release_cmd(struct se_cmd *se_cmd)
 418{
 419	struct xcopy_pt_cmd *xpt_cmd = container_of(se_cmd,
 420				struct xcopy_pt_cmd, se_cmd);
 421
 422	kfree(xpt_cmd);
 423}
 424
 425static int xcopy_pt_check_stop_free(struct se_cmd *se_cmd)
 426{
 427	struct xcopy_pt_cmd *xpt_cmd = container_of(se_cmd,
 428				struct xcopy_pt_cmd, se_cmd);
 429
 430	complete(&xpt_cmd->xpt_passthrough_sem);
 431	return 0;
 432}
 433
 434static int xcopy_pt_write_pending(struct se_cmd *se_cmd)
 435{
 436	return 0;
 437}
 438
 439static int xcopy_pt_write_pending_status(struct se_cmd *se_cmd)
 440{
 441	return 0;
 442}
 443
 444static int xcopy_pt_queue_data_in(struct se_cmd *se_cmd)
 445{
 446	return 0;
 447}
 448
 449static int xcopy_pt_queue_status(struct se_cmd *se_cmd)
 450{
 451	return 0;
 452}
 453
 454static const struct target_core_fabric_ops xcopy_pt_tfo = {
 455	.get_fabric_name	= xcopy_pt_get_fabric_name,
 456	.get_cmd_state		= xcopy_pt_get_cmd_state,
 457	.release_cmd		= xcopy_pt_release_cmd,
 458	.check_stop_free	= xcopy_pt_check_stop_free,
 459	.write_pending		= xcopy_pt_write_pending,
 460	.write_pending_status	= xcopy_pt_write_pending_status,
 461	.queue_data_in		= xcopy_pt_queue_data_in,
 462	.queue_status		= xcopy_pt_queue_status,
 463};
 464
 465/*
 466 * End xcopy_pt_ops
 467 */
 468
 469int target_xcopy_setup_pt(void)
 470{
 471	xcopy_wq = alloc_workqueue("xcopy_wq", WQ_MEM_RECLAIM, 0);
 472	if (!xcopy_wq) {
 473		pr_err("Unable to allocate xcopy_wq\n");
 474		return -ENOMEM;
 475	}
 476
 477	memset(&xcopy_pt_tpg, 0, sizeof(struct se_portal_group));
 478	INIT_LIST_HEAD(&xcopy_pt_tpg.se_tpg_node);
 479	INIT_LIST_HEAD(&xcopy_pt_tpg.acl_node_list);
 480	INIT_LIST_HEAD(&xcopy_pt_tpg.tpg_sess_list);
 481
 482	xcopy_pt_tpg.se_tpg_tfo = &xcopy_pt_tfo;
 483
 484	memset(&xcopy_pt_nacl, 0, sizeof(struct se_node_acl));
 485	INIT_LIST_HEAD(&xcopy_pt_nacl.acl_list);
 486	INIT_LIST_HEAD(&xcopy_pt_nacl.acl_sess_list);
 487	memset(&xcopy_pt_sess, 0, sizeof(struct se_session));
 488	INIT_LIST_HEAD(&xcopy_pt_sess.sess_list);
 489	INIT_LIST_HEAD(&xcopy_pt_sess.sess_acl_list);
 490	INIT_LIST_HEAD(&xcopy_pt_sess.sess_cmd_list);
 491	spin_lock_init(&xcopy_pt_sess.sess_cmd_lock);
 492
 493	xcopy_pt_nacl.se_tpg = &xcopy_pt_tpg;
 494	xcopy_pt_nacl.nacl_sess = &xcopy_pt_sess;
 495
 496	xcopy_pt_sess.se_tpg = &xcopy_pt_tpg;
 497	xcopy_pt_sess.se_node_acl = &xcopy_pt_nacl;
 498
 499	return 0;
 500}
 501
 502void target_xcopy_release_pt(void)
 503{
 504	if (xcopy_wq)
 505		destroy_workqueue(xcopy_wq);
 506}
 507
 508static void target_xcopy_setup_pt_port(
 509	struct xcopy_pt_cmd *xpt_cmd,
 510	struct xcopy_op *xop,
 511	bool remote_port)
 512{
 513	struct se_cmd *ec_cmd = xop->xop_se_cmd;
 514	struct se_cmd *pt_cmd = &xpt_cmd->se_cmd;
 515
 516	if (xop->op_origin == XCOL_SOURCE_RECV_OP) {
 517		/*
 518		 * Honor destination port reservations for X-COPY PUSH emulation
 519		 * when CDB is received on local source port, and READs blocks to
 520		 * WRITE on remote destination port.
 521		 */
 522		if (remote_port) {
 523			xpt_cmd->remote_port = remote_port;
 524		} else {
 525			pt_cmd->se_lun = ec_cmd->se_lun;
 526			pt_cmd->se_dev = ec_cmd->se_dev;
 527
 528			pr_debug("Honoring local SRC port from ec_cmd->se_dev:"
 529				" %p\n", pt_cmd->se_dev);
 530			pt_cmd->se_lun = ec_cmd->se_lun;
 531			pr_debug("Honoring local SRC port from ec_cmd->se_lun: %p\n",
 532				pt_cmd->se_lun);
 533		}
 534	} else {
 535		/*
 536		 * Honor source port reservation for X-COPY PULL emulation
 537		 * when CDB is received on local desintation port, and READs
 538		 * blocks from the remote source port to WRITE on local
 539		 * destination port.
 540		 */
 541		if (remote_port) {
 542			xpt_cmd->remote_port = remote_port;
 543		} else {
 544			pt_cmd->se_lun = ec_cmd->se_lun;
 545			pt_cmd->se_dev = ec_cmd->se_dev;
 546
 547			pr_debug("Honoring local DST port from ec_cmd->se_dev:"
 548				" %p\n", pt_cmd->se_dev);
 549			pt_cmd->se_lun = ec_cmd->se_lun;
 550			pr_debug("Honoring local DST port from ec_cmd->se_lun: %p\n",
 551				pt_cmd->se_lun);
 552		}
 553	}
 554}
 555
 556static void target_xcopy_init_pt_lun(struct se_device *se_dev,
 557		struct se_cmd *pt_cmd, bool remote_port)
 558{
 559	/*
 560	 * Don't allocate + init an pt_cmd->se_lun if honoring local port for
 561	 * reservations.  The pt_cmd->se_lun pointer will be setup from within
 562	 * target_xcopy_setup_pt_port()
 563	 */
 564	if (remote_port) {
 565		pr_debug("Setup emulated se_dev: %p from se_dev\n",
 566			pt_cmd->se_dev);
 567		pt_cmd->se_lun = &se_dev->xcopy_lun;
 568		pt_cmd->se_dev = se_dev;
 569	}
 570
 571	pt_cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
 572}
 573
 574static int target_xcopy_setup_pt_cmd(
 575	struct xcopy_pt_cmd *xpt_cmd,
 576	struct xcopy_op *xop,
 577	struct se_device *se_dev,
 578	unsigned char *cdb,
 579	bool remote_port,
 580	bool alloc_mem)
 581{
 582	struct se_cmd *cmd = &xpt_cmd->se_cmd;
 583	sense_reason_t sense_rc;
 584	int ret = 0, rc;
 585	/*
 586	 * Setup LUN+port to honor reservations based upon xop->op_origin for
 587	 * X-COPY PUSH or X-COPY PULL based upon where the CDB was received.
 588	 */
 589	target_xcopy_init_pt_lun(se_dev, cmd, remote_port);
 590
 591	xpt_cmd->xcopy_op = xop;
 592	target_xcopy_setup_pt_port(xpt_cmd, xop, remote_port);
 593
 594	cmd->tag = 0;
 595	sense_rc = target_setup_cmd_from_cdb(cmd, cdb);
 596	if (sense_rc) {
 597		ret = -EINVAL;
 598		goto out;
 599	}
 600
 601	if (alloc_mem) {
 602		rc = target_alloc_sgl(&cmd->t_data_sg, &cmd->t_data_nents,
 603				      cmd->data_length, false, false);
 604		if (rc < 0) {
 605			ret = rc;
 606			goto out;
 607		}
 608		/*
 609		 * Set this bit so that transport_free_pages() allows the
 610		 * caller to release SGLs + physical memory allocated by
 611		 * transport_generic_get_mem()..
 612		 */
 613		cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
 614	} else {
 615		/*
 616		 * Here the previously allocated SGLs for the internal READ
 617		 * are mapped zero-copy to the internal WRITE.
 618		 */
 619		sense_rc = transport_generic_map_mem_to_cmd(cmd,
 620					xop->xop_data_sg, xop->xop_data_nents,
 621					NULL, 0);
 622		if (sense_rc) {
 623			ret = -EINVAL;
 624			goto out;
 625		}
 626
 627		pr_debug("Setup PASSTHROUGH_NOALLOC t_data_sg: %p t_data_nents:"
 628			 " %u\n", cmd->t_data_sg, cmd->t_data_nents);
 629	}
 630
 631	return 0;
 632
 633out:
 634	return ret;
 635}
 636
 637static int target_xcopy_issue_pt_cmd(struct xcopy_pt_cmd *xpt_cmd)
 638{
 639	struct se_cmd *se_cmd = &xpt_cmd->se_cmd;
 640	sense_reason_t sense_rc;
 641
 642	sense_rc = transport_generic_new_cmd(se_cmd);
 643	if (sense_rc)
 644		return -EINVAL;
 645
 646	if (se_cmd->data_direction == DMA_TO_DEVICE)
 647		target_execute_cmd(se_cmd);
 648
 649	wait_for_completion_interruptible(&xpt_cmd->xpt_passthrough_sem);
 650
 651	pr_debug("target_xcopy_issue_pt_cmd(): SCSI status: 0x%02x\n",
 652			se_cmd->scsi_status);
 653
 654	return (se_cmd->scsi_status) ? -EINVAL : 0;
 655}
 656
 657static int target_xcopy_read_source(
 658	struct se_cmd *ec_cmd,
 659	struct xcopy_op *xop,
 660	struct se_device *src_dev,
 661	sector_t src_lba,
 662	u32 src_sectors)
 663{
 664	struct xcopy_pt_cmd *xpt_cmd;
 665	struct se_cmd *se_cmd;
 666	u32 length = (src_sectors * src_dev->dev_attrib.block_size);
 667	int rc;
 668	unsigned char cdb[16];
 669	bool remote_port = (xop->op_origin == XCOL_DEST_RECV_OP);
 670
 671	xpt_cmd = kzalloc(sizeof(struct xcopy_pt_cmd), GFP_KERNEL);
 672	if (!xpt_cmd) {
 673		pr_err("Unable to allocate xcopy_pt_cmd\n");
 674		return -ENOMEM;
 675	}
 676	init_completion(&xpt_cmd->xpt_passthrough_sem);
 677	se_cmd = &xpt_cmd->se_cmd;
 678
 679	memset(&cdb[0], 0, 16);
 680	cdb[0] = READ_16;
 681	put_unaligned_be64(src_lba, &cdb[2]);
 682	put_unaligned_be32(src_sectors, &cdb[10]);
 683	pr_debug("XCOPY: Built READ_16: LBA: %llu Sectors: %u Length: %u\n",
 684		(unsigned long long)src_lba, src_sectors, length);
 685
 686	transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length,
 687			      DMA_FROM_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
 688	xop->src_pt_cmd = xpt_cmd;
 689
 690	rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0],
 691				remote_port, true);
 692	if (rc < 0) {
 693		ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
 694		transport_generic_free_cmd(se_cmd, 0);
 695		return rc;
 696	}
 697
 698	xop->xop_data_sg = se_cmd->t_data_sg;
 699	xop->xop_data_nents = se_cmd->t_data_nents;
 700	pr_debug("XCOPY-READ: Saved xop->xop_data_sg: %p, num: %u for READ"
 701		" memory\n", xop->xop_data_sg, xop->xop_data_nents);
 702
 703	rc = target_xcopy_issue_pt_cmd(xpt_cmd);
 704	if (rc < 0) {
 705		ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
 706		transport_generic_free_cmd(se_cmd, 0);
 707		return rc;
 708	}
 709	/*
 710	 * Clear off the allocated t_data_sg, that has been saved for
 711	 * zero-copy WRITE submission reuse in struct xcopy_op..
 712	 */
 713	se_cmd->t_data_sg = NULL;
 714	se_cmd->t_data_nents = 0;
 715
 716	return 0;
 717}
 718
 719static int target_xcopy_write_destination(
 720	struct se_cmd *ec_cmd,
 721	struct xcopy_op *xop,
 722	struct se_device *dst_dev,
 723	sector_t dst_lba,
 724	u32 dst_sectors)
 725{
 726	struct xcopy_pt_cmd *xpt_cmd;
 727	struct se_cmd *se_cmd;
 728	u32 length = (dst_sectors * dst_dev->dev_attrib.block_size);
 729	int rc;
 730	unsigned char cdb[16];
 731	bool remote_port = (xop->op_origin == XCOL_SOURCE_RECV_OP);
 732
 733	xpt_cmd = kzalloc(sizeof(struct xcopy_pt_cmd), GFP_KERNEL);
 734	if (!xpt_cmd) {
 735		pr_err("Unable to allocate xcopy_pt_cmd\n");
 736		return -ENOMEM;
 737	}
 738	init_completion(&xpt_cmd->xpt_passthrough_sem);
 739	se_cmd = &xpt_cmd->se_cmd;
 740
 741	memset(&cdb[0], 0, 16);
 742	cdb[0] = WRITE_16;
 743	put_unaligned_be64(dst_lba, &cdb[2]);
 744	put_unaligned_be32(dst_sectors, &cdb[10]);
 745	pr_debug("XCOPY: Built WRITE_16: LBA: %llu Sectors: %u Length: %u\n",
 746		(unsigned long long)dst_lba, dst_sectors, length);
 747
 748	transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length,
 749			      DMA_TO_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
 750	xop->dst_pt_cmd = xpt_cmd;
 751
 752	rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, dst_dev, &cdb[0],
 753				remote_port, false);
 754	if (rc < 0) {
 755		struct se_cmd *src_cmd = &xop->src_pt_cmd->se_cmd;
 756		ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
 757		/*
 758		 * If the failure happened before the t_mem_list hand-off in
 759		 * target_xcopy_setup_pt_cmd(), Reset memory + clear flag so that
 760		 * core releases this memory on error during X-COPY WRITE I/O.
 761		 */
 762		src_cmd->se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
 763		src_cmd->t_data_sg = xop->xop_data_sg;
 764		src_cmd->t_data_nents = xop->xop_data_nents;
 765
 766		transport_generic_free_cmd(se_cmd, 0);
 767		return rc;
 768	}
 769
 770	rc = target_xcopy_issue_pt_cmd(xpt_cmd);
 771	if (rc < 0) {
 772		ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
 773		se_cmd->se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
 774		transport_generic_free_cmd(se_cmd, 0);
 775		return rc;
 776	}
 777
 778	return 0;
 779}
 780
 781static void target_xcopy_do_work(struct work_struct *work)
 782{
 783	struct xcopy_op *xop = container_of(work, struct xcopy_op, xop_work);
 784	struct se_device *src_dev = xop->src_dev, *dst_dev = xop->dst_dev;
 785	struct se_cmd *ec_cmd = xop->xop_se_cmd;
 786	sector_t src_lba = xop->src_lba, dst_lba = xop->dst_lba, end_lba;
 787	unsigned int max_sectors;
 788	int rc;
 789	unsigned short nolb = xop->nolb, cur_nolb, max_nolb, copied_nolb = 0;
 790
 791	end_lba = src_lba + nolb;
 792	/*
 793	 * Break up XCOPY I/O into hw_max_sectors sized I/O based on the
 794	 * smallest max_sectors between src_dev + dev_dev, or
 795	 */
 796	max_sectors = min(src_dev->dev_attrib.hw_max_sectors,
 797			  dst_dev->dev_attrib.hw_max_sectors);
 798	max_sectors = min_t(u32, max_sectors, XCOPY_MAX_SECTORS);
 799
 800	max_nolb = min_t(u16, max_sectors, ((u16)(~0U)));
 801
 802	pr_debug("target_xcopy_do_work: nolb: %hu, max_nolb: %hu end_lba: %llu\n",
 803			nolb, max_nolb, (unsigned long long)end_lba);
 804	pr_debug("target_xcopy_do_work: Starting src_lba: %llu, dst_lba: %llu\n",
 805			(unsigned long long)src_lba, (unsigned long long)dst_lba);
 806
 807	while (src_lba < end_lba) {
 808		cur_nolb = min(nolb, max_nolb);
 809
 810		pr_debug("target_xcopy_do_work: Calling read src_dev: %p src_lba: %llu,"
 811			" cur_nolb: %hu\n", src_dev, (unsigned long long)src_lba, cur_nolb);
 812
 813		rc = target_xcopy_read_source(ec_cmd, xop, src_dev, src_lba, cur_nolb);
 814		if (rc < 0)
 815			goto out;
 816
 817		src_lba += cur_nolb;
 818		pr_debug("target_xcopy_do_work: Incremented READ src_lba to %llu\n",
 819				(unsigned long long)src_lba);
 820
 821		pr_debug("target_xcopy_do_work: Calling write dst_dev: %p dst_lba: %llu,"
 822			" cur_nolb: %hu\n", dst_dev, (unsigned long long)dst_lba, cur_nolb);
 823
 824		rc = target_xcopy_write_destination(ec_cmd, xop, dst_dev,
 825						dst_lba, cur_nolb);
 826		if (rc < 0) {
 827			transport_generic_free_cmd(&xop->src_pt_cmd->se_cmd, 0);
 828			goto out;
 829		}
 830
 831		dst_lba += cur_nolb;
 832		pr_debug("target_xcopy_do_work: Incremented WRITE dst_lba to %llu\n",
 833				(unsigned long long)dst_lba);
 834
 835		copied_nolb += cur_nolb;
 836		nolb -= cur_nolb;
 837
 838		transport_generic_free_cmd(&xop->src_pt_cmd->se_cmd, 0);
 839		xop->dst_pt_cmd->se_cmd.se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
 840
 841		transport_generic_free_cmd(&xop->dst_pt_cmd->se_cmd, 0);
 842	}
 843
 844	xcopy_pt_undepend_remotedev(xop);
 845	kfree(xop);
 846
 847	pr_debug("target_xcopy_do_work: Final src_lba: %llu, dst_lba: %llu\n",
 848		(unsigned long long)src_lba, (unsigned long long)dst_lba);
 849	pr_debug("target_xcopy_do_work: Blocks copied: %hu, Bytes Copied: %u\n",
 850		copied_nolb, copied_nolb * dst_dev->dev_attrib.block_size);
 851
 852	pr_debug("target_xcopy_do_work: Setting X-COPY GOOD status -> sending response\n");
 853	target_complete_cmd(ec_cmd, SAM_STAT_GOOD);
 854	return;
 855
 856out:
 857	xcopy_pt_undepend_remotedev(xop);
 858	kfree(xop);
 859	/*
 860	 * Don't override an error scsi status if it has already been set
 861	 */
 862	if (ec_cmd->scsi_status == SAM_STAT_GOOD) {
 863		pr_warn_ratelimited("target_xcopy_do_work: rc: %d, Setting X-COPY"
 864			" CHECK_CONDITION -> sending response\n", rc);
 865		ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
 866	}
 867	target_complete_cmd(ec_cmd, ec_cmd->scsi_status);
 868}
 869
 870sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
 871{
 872	struct se_device *dev = se_cmd->se_dev;
 873	struct xcopy_op *xop = NULL;
 874	unsigned char *p = NULL, *seg_desc;
 875	unsigned int list_id, list_id_usage, sdll, inline_dl, sa;
 876	sense_reason_t ret = TCM_INVALID_PARAMETER_LIST;
 877	int rc;
 878	unsigned short tdll;
 879
 880	if (!dev->dev_attrib.emulate_3pc) {
 881		pr_err("EXTENDED_COPY operation explicitly disabled\n");
 882		return TCM_UNSUPPORTED_SCSI_OPCODE;
 883	}
 884
 885	sa = se_cmd->t_task_cdb[1] & 0x1f;
 886	if (sa != 0x00) {
 887		pr_err("EXTENDED_COPY(LID4) not supported\n");
 888		return TCM_UNSUPPORTED_SCSI_OPCODE;
 889	}
 890
 891	if (se_cmd->data_length == 0) {
 892		target_complete_cmd(se_cmd, SAM_STAT_GOOD);
 893		return TCM_NO_SENSE;
 894	}
 895	if (se_cmd->data_length < XCOPY_HDR_LEN) {
 896		pr_err("XCOPY parameter truncation: length %u < hdr_len %u\n",
 897				se_cmd->data_length, XCOPY_HDR_LEN);
 898		return TCM_PARAMETER_LIST_LENGTH_ERROR;
 899	}
 900
 901	xop = kzalloc(sizeof(struct xcopy_op), GFP_KERNEL);
 902	if (!xop) {
 903		pr_err("Unable to allocate xcopy_op\n");
 904		return TCM_OUT_OF_RESOURCES;
 905	}
 906	xop->xop_se_cmd = se_cmd;
 907
 908	p = transport_kmap_data_sg(se_cmd);
 909	if (!p) {
 910		pr_err("transport_kmap_data_sg() failed in target_do_xcopy\n");
 911		kfree(xop);
 912		return TCM_OUT_OF_RESOURCES;
 913	}
 914
 915	list_id = p[0];
 916	list_id_usage = (p[1] & 0x18) >> 3;
 917
 918	/*
 919	 * Determine TARGET DESCRIPTOR LIST LENGTH + SEGMENT DESCRIPTOR LIST LENGTH
 920	 */
 921	tdll = get_unaligned_be16(&p[2]);
 922	sdll = get_unaligned_be32(&p[8]);
 923	if (tdll + sdll > RCR_OP_MAX_DESC_LIST_LEN) {
 924		pr_err("XCOPY descriptor list length %u exceeds maximum %u\n",
 925		       tdll + sdll, RCR_OP_MAX_DESC_LIST_LEN);
 926		ret = TCM_PARAMETER_LIST_LENGTH_ERROR;
 927		goto out;
 928	}
 929
 930	inline_dl = get_unaligned_be32(&p[12]);
 931	if (inline_dl != 0) {
 932		pr_err("XCOPY with non zero inline data length\n");
 933		goto out;
 934	}
 935
 936	if (se_cmd->data_length < (XCOPY_HDR_LEN + tdll + sdll + inline_dl)) {
 937		pr_err("XCOPY parameter truncation: data length %u too small "
 938			"for tdll: %hu sdll: %u inline_dl: %u\n",
 939			se_cmd->data_length, tdll, sdll, inline_dl);
 940		ret = TCM_PARAMETER_LIST_LENGTH_ERROR;
 941		goto out;
 942	}
 943
 944	pr_debug("Processing XCOPY with list_id: 0x%02x list_id_usage: 0x%02x"
 945		" tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
 946		tdll, sdll, inline_dl);
 947
 948	/*
 949	 * skip over the target descriptors until segment descriptors
 950	 * have been passed - CSCD ids are needed to determine src and dest.
 951	 */
 952	seg_desc = &p[16] + tdll;
 953
 954	rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc,
 955						    sdll, &ret);
 956	if (rc <= 0)
 957		goto out;
 958
 959	pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc,
 960				rc * XCOPY_SEGMENT_DESC_LEN);
 961
 962	rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret);
 963	if (rc <= 0)
 964		goto out;
 965
 966	if (xop->src_dev->dev_attrib.block_size !=
 967	    xop->dst_dev->dev_attrib.block_size) {
 968		pr_err("XCOPY: Non matching src_dev block_size: %u + dst_dev"
 969		       " block_size: %u currently unsupported\n",
 970			xop->src_dev->dev_attrib.block_size,
 971			xop->dst_dev->dev_attrib.block_size);
 972		xcopy_pt_undepend_remotedev(xop);
 973		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 974		goto out;
 975	}
 976
 977	pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc,
 978				rc * XCOPY_TARGET_DESC_LEN);
 979	transport_kunmap_data_sg(se_cmd);
 980
 981	INIT_WORK(&xop->xop_work, target_xcopy_do_work);
 982	queue_work(xcopy_wq, &xop->xop_work);
 983	return TCM_NO_SENSE;
 984
 985out:
 986	if (p)
 987		transport_kunmap_data_sg(se_cmd);
 988	kfree(xop);
 989	return ret;
 990}
 991
 992static sense_reason_t target_rcr_operating_parameters(struct se_cmd *se_cmd)
 993{
 994	unsigned char *p;
 995
 996	p = transport_kmap_data_sg(se_cmd);
 997	if (!p) {
 998		pr_err("transport_kmap_data_sg failed in"
 999		       " target_rcr_operating_parameters\n");
1000		return TCM_OUT_OF_RESOURCES;
1001	}
1002
1003	if (se_cmd->data_length < 54) {
1004		pr_err("Receive Copy Results Op Parameters length"
1005		       " too small: %u\n", se_cmd->data_length);
1006		transport_kunmap_data_sg(se_cmd);
1007		return TCM_INVALID_CDB_FIELD;
1008	}
1009	/*
1010	 * Set SNLID=1 (Supports no List ID)
1011	 */
1012	p[4] = 0x1;
1013	/*
1014	 * MAXIMUM TARGET DESCRIPTOR COUNT
1015	 */
1016	put_unaligned_be16(RCR_OP_MAX_TARGET_DESC_COUNT, &p[8]);
1017	/*
1018	 * MAXIMUM SEGMENT DESCRIPTOR COUNT
1019	 */
1020	put_unaligned_be16(RCR_OP_MAX_SG_DESC_COUNT, &p[10]);
1021	/*
1022	 * MAXIMUM DESCRIPTOR LIST LENGTH
1023	 */
1024	put_unaligned_be32(RCR_OP_MAX_DESC_LIST_LEN, &p[12]);
1025	/*
1026	 * MAXIMUM SEGMENT LENGTH
1027	 */
1028	put_unaligned_be32(RCR_OP_MAX_SEGMENT_LEN, &p[16]);
1029	/*
1030	 * MAXIMUM INLINE DATA LENGTH for SA 0x04 (NOT SUPPORTED)
1031	 */
1032	put_unaligned_be32(0x0, &p[20]);
1033	/*
1034	 * HELD DATA LIMIT
1035	 */
1036	put_unaligned_be32(0x0, &p[24]);
1037	/*
1038	 * MAXIMUM STREAM DEVICE TRANSFER SIZE
1039	 */
1040	put_unaligned_be32(0x0, &p[28]);
1041	/*
1042	 * TOTAL CONCURRENT COPIES
1043	 */
1044	put_unaligned_be16(RCR_OP_TOTAL_CONCURR_COPIES, &p[34]);
1045	/*
1046	 * MAXIMUM CONCURRENT COPIES
1047	 */
1048	p[36] = RCR_OP_MAX_CONCURR_COPIES;
1049	/*
1050	 * DATA SEGMENT GRANULARITY (log 2)
1051	 */
1052	p[37] = RCR_OP_DATA_SEG_GRAN_LOG2;
1053	/*
1054	 * INLINE DATA GRANULARITY log 2)
1055	 */
1056	p[38] = RCR_OP_INLINE_DATA_GRAN_LOG2;
1057	/*
1058	 * HELD DATA GRANULARITY
1059	 */
1060	p[39] = RCR_OP_HELD_DATA_GRAN_LOG2;
1061	/*
1062	 * IMPLEMENTED DESCRIPTOR LIST LENGTH
1063	 */
1064	p[43] = 0x2;
1065	/*
1066	 * List of implemented descriptor type codes (ordered)
1067	 */
1068	p[44] = 0x02; /* Copy Block to Block device */
1069	p[45] = 0xe4; /* Identification descriptor target descriptor */
1070
1071	/*
1072	 * AVAILABLE DATA (n-3)
1073	 */
1074	put_unaligned_be32(42, &p[0]);
1075
1076	transport_kunmap_data_sg(se_cmd);
1077	target_complete_cmd(se_cmd, GOOD);
1078
1079	return TCM_NO_SENSE;
1080}
1081
1082sense_reason_t target_do_receive_copy_results(struct se_cmd *se_cmd)
1083{
1084	unsigned char *cdb = &se_cmd->t_task_cdb[0];
1085	int sa = (cdb[1] & 0x1f), list_id = cdb[2];
1086	sense_reason_t rc = TCM_NO_SENSE;
1087
1088	pr_debug("Entering target_do_receive_copy_results: SA: 0x%02x, List ID:"
1089		" 0x%02x, AL: %u\n", sa, list_id, se_cmd->data_length);
1090
1091	if (list_id != 0) {
1092		pr_err("Receive Copy Results with non zero list identifier"
1093		       " not supported\n");
1094		return TCM_INVALID_CDB_FIELD;
1095	}
1096
1097	switch (sa) {
1098	case RCR_SA_OPERATING_PARAMETERS:
1099		rc = target_rcr_operating_parameters(se_cmd);
1100		break;
1101	case RCR_SA_COPY_STATUS:
1102	case RCR_SA_RECEIVE_DATA:
1103	case RCR_SA_FAILED_SEGMENT_DETAILS:
1104	default:
1105		pr_err("Unsupported SA for receive copy results: 0x%02x\n", sa);
1106		return TCM_INVALID_CDB_FIELD;
1107	}
1108
1109	return rc;
1110}