diff options
Diffstat (limited to 'drivers/target/target_core_xcopy.c')
| -rw-r--r-- | drivers/target/target_core_xcopy.c | 53 | 
1 files changed, 37 insertions, 16 deletions
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c index 3da4fd10b9f8..474cd44fac14 100644 --- a/drivers/target/target_core_xcopy.c +++ b/drivers/target/target_core_xcopy.c @@ -82,6 +82,9 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op  	mutex_lock(&g_device_mutex);  	list_for_each_entry(se_dev, &g_device_list, g_dev_node) { +		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]); @@ -357,6 +360,7 @@ struct xcopy_pt_cmd {  	struct se_cmd se_cmd;  	struct xcopy_op *xcopy_op;  	struct completion xpt_passthrough_sem; +	unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER];  };  static struct se_port xcopy_pt_port; @@ -675,7 +679,8 @@ static int target_xcopy_issue_pt_cmd(struct xcopy_pt_cmd *xpt_cmd)  	pr_debug("target_xcopy_issue_pt_cmd(): SCSI status: 0x%02x\n",  			se_cmd->scsi_status); -	return 0; + +	return (se_cmd->scsi_status) ? -EINVAL : 0;  }  static int target_xcopy_read_source( @@ -708,7 +713,7 @@ static int target_xcopy_read_source(  		(unsigned long long)src_lba, src_sectors, length);  	transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, NULL, length, -				DMA_FROM_DEVICE, 0, NULL); +			      DMA_FROM_DEVICE, 0, &xpt_cmd->sense_buffer[0]);  	xop->src_pt_cmd = xpt_cmd;  	rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0], @@ -768,7 +773,7 @@ static int target_xcopy_write_destination(  		(unsigned long long)dst_lba, dst_sectors, length);  	transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, NULL, length, -				DMA_TO_DEVICE, 0, NULL); +			      DMA_TO_DEVICE, 0, &xpt_cmd->sense_buffer[0]);  	xop->dst_pt_cmd = xpt_cmd;  	rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, dst_dev, &cdb[0], @@ -884,30 +889,42 @@ out:  sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)  { +	struct se_device *dev = se_cmd->se_dev;  	struct xcopy_op *xop = NULL;  	unsigned char *p = NULL, *seg_desc;  	unsigned int list_id, list_id_usage, sdll, inline_dl, sa; +	sense_reason_t ret = TCM_INVALID_PARAMETER_LIST;  	int rc;  	unsigned short tdll; +	if (!dev->dev_attrib.emulate_3pc) { +		pr_err("EXTENDED_COPY operation explicitly disabled\n"); +		return TCM_UNSUPPORTED_SCSI_OPCODE; +	} +  	sa = se_cmd->t_task_cdb[1] & 0x1f;  	if (sa != 0x00) {  		pr_err("EXTENDED_COPY(LID4) not supported\n");  		return TCM_UNSUPPORTED_SCSI_OPCODE;  	} +	xop = kzalloc(sizeof(struct xcopy_op), GFP_KERNEL); +	if (!xop) { +		pr_err("Unable to allocate xcopy_op\n"); +		return TCM_OUT_OF_RESOURCES; +	} +	xop->xop_se_cmd = se_cmd; +  	p = transport_kmap_data_sg(se_cmd);  	if (!p) {  		pr_err("transport_kmap_data_sg() failed in target_do_xcopy\n"); +		kfree(xop);  		return TCM_OUT_OF_RESOURCES;  	}  	list_id = p[0]; -	if (list_id != 0x00) { -		pr_err("XCOPY with non zero list_id: 0x%02x\n", list_id); -		goto out; -	} -	list_id_usage = (p[1] & 0x18); +	list_id_usage = (p[1] & 0x18) >> 3; +  	/*  	 * Determine TARGET DESCRIPTOR LIST LENGTH + SEGMENT DESCRIPTOR LIST LENGTH  	 */ @@ -920,13 +937,6 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)  		goto out;  	} -	xop = kzalloc(sizeof(struct xcopy_op), GFP_KERNEL); -	if (!xop) { -		pr_err("Unable to allocate xcopy_op\n"); -		goto out; -	} -	xop->xop_se_cmd = se_cmd; -  	pr_debug("Processing XCOPY with list_id: 0x%02x list_id_usage: 0x%02x"  		" tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,  		tdll, sdll, inline_dl); @@ -935,6 +945,17 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)  	if (rc <= 0)  		goto out; +	if (xop->src_dev->dev_attrib.block_size != +	    xop->dst_dev->dev_attrib.block_size) { +		pr_err("XCOPY: Non matching src_dev block_size: %u + dst_dev" +		       " block_size: %u currently unsupported\n", +			xop->src_dev->dev_attrib.block_size, +			xop->dst_dev->dev_attrib.block_size); +		xcopy_pt_undepend_remotedev(xop); +		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; +		goto out; +	} +  	pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc,  				rc * XCOPY_TARGET_DESC_LEN);  	seg_desc = &p[16]; @@ -957,7 +978,7 @@ out:  	if (p)  		transport_kunmap_data_sg(se_cmd);  	kfree(xop); -	return TCM_INVALID_CDB_FIELD; +	return ret;  }  static sense_reason_t target_rcr_operating_parameters(struct se_cmd *se_cmd)  | 
