target/user: Only support full command pass-through
After much discussion, give up on only passing a subset of SCSI commands to userspace and pass them all. Based on what pscsi is doing, make sure to set SCF_SCSI_DATA_CDB for I/O ops, and define attributes identical to pscsi. Make hw_block_size configurable via dev param. Remove mention of command filtering from tcmu-design.txt. Signed-off-by: Andy Grover <agrover@redhat.com> Reviewed-by: Ilias Tsitsimpis <iliastsi@arrikto.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
		
							parent
							
								
									cf87edc602
								
							
						
					
					
						commit
						9c1cd1b68c
					
				| @ -15,8 +15,7 @@ Contents: | ||||
|   a) Discovering and configuring TCMU uio devices | ||||
|   b) Waiting for events on the device(s) | ||||
|   c) Managing the command ring | ||||
| 3) Command filtering | ||||
| 4) A final note | ||||
| 3) A final note | ||||
| 
 | ||||
| 
 | ||||
| TCM Userspace Design | ||||
| @ -364,24 +363,6 @@ int handle_device_events(int fd, void *map) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Command filtering | ||||
| ----------------- | ||||
| 
 | ||||
| Initial TCMU support is for a filtered commandset.  Only IO-related | ||||
| commands are presented to userspace, and the rest are handled by LIO's | ||||
| in-kernel command emulation. The commands presented are all versions | ||||
| of: | ||||
| 
 | ||||
| READ | ||||
| WRITE | ||||
| WRITE_VERIFY | ||||
| XDWRITEREAD | ||||
| WRITE_SAME | ||||
| COMPARE_AND_WRITE | ||||
| SYNCHRONIZE_CACHE | ||||
| UNMAP | ||||
| 
 | ||||
| 
 | ||||
| A final note | ||||
| ------------ | ||||
| 
 | ||||
|  | ||||
| @ -938,12 +938,13 @@ static void tcmu_free_device(struct se_device *dev) | ||||
| } | ||||
| 
 | ||||
| enum { | ||||
| 	Opt_dev_config, Opt_dev_size, Opt_err, | ||||
| 	Opt_dev_config, Opt_dev_size, Opt_hw_block_size, Opt_err, | ||||
| }; | ||||
| 
 | ||||
| static match_table_t tokens = { | ||||
| 	{Opt_dev_config, "dev_config=%s"}, | ||||
| 	{Opt_dev_size, "dev_size=%u"}, | ||||
| 	{Opt_hw_block_size, "hw_block_size=%u"}, | ||||
| 	{Opt_err, NULL} | ||||
| }; | ||||
| 
 | ||||
| @ -954,6 +955,7 @@ static ssize_t tcmu_set_configfs_dev_params(struct se_device *dev, | ||||
| 	char *orig, *ptr, *opts, *arg_p; | ||||
| 	substring_t args[MAX_OPT_ARGS]; | ||||
| 	int ret = 0, token; | ||||
| 	unsigned long tmp_ul; | ||||
| 
 | ||||
| 	opts = kstrdup(page, GFP_KERNEL); | ||||
| 	if (!opts) | ||||
| @ -986,6 +988,24 @@ static ssize_t tcmu_set_configfs_dev_params(struct se_device *dev, | ||||
| 			if (ret < 0) | ||||
| 				pr_err("kstrtoul() failed for dev_size=\n"); | ||||
| 			break; | ||||
| 		case Opt_hw_block_size: | ||||
| 			arg_p = match_strdup(&args[0]); | ||||
| 			if (!arg_p) { | ||||
| 				ret = -ENOMEM; | ||||
| 				break; | ||||
| 			} | ||||
| 			ret = kstrtoul(arg_p, 0, &tmp_ul); | ||||
| 			kfree(arg_p); | ||||
| 			if (ret < 0) { | ||||
| 				pr_err("kstrtoul() failed for hw_block_size=\n"); | ||||
| 				break; | ||||
| 			} | ||||
| 			if (!tmp_ul) { | ||||
| 				pr_err("hw_block_size must be nonzero\n"); | ||||
| 				break; | ||||
| 			} | ||||
| 			dev->dev_attrib.hw_block_size = tmp_ul; | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| @ -1015,20 +1035,6 @@ static sector_t tcmu_get_blocks(struct se_device *dev) | ||||
| 		       dev->dev_attrib.block_size); | ||||
| } | ||||
| 
 | ||||
| static sense_reason_t | ||||
| tcmu_execute_rw(struct se_cmd *se_cmd, struct scatterlist *sgl, u32 sgl_nents, | ||||
| 		enum dma_data_direction data_direction) | ||||
| { | ||||
| 	int ret; | ||||
| 
 | ||||
| 	ret = tcmu_queue_cmd(se_cmd); | ||||
| 
 | ||||
| 	if (ret != 0) | ||||
| 		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||||
| 	else | ||||
| 		return TCM_NO_SENSE; | ||||
| } | ||||
| 
 | ||||
| static sense_reason_t | ||||
| tcmu_pass_op(struct se_cmd *se_cmd) | ||||
| { | ||||
| @ -1040,52 +1046,70 @@ tcmu_pass_op(struct se_cmd *se_cmd) | ||||
| 		return TCM_NO_SENSE; | ||||
| } | ||||
| 
 | ||||
| static struct sbc_ops tcmu_sbc_ops = { | ||||
| 	.execute_rw = tcmu_execute_rw, | ||||
| 	.execute_sync_cache	= tcmu_pass_op, | ||||
| 	.execute_write_same	= tcmu_pass_op, | ||||
| 	.execute_write_same_unmap = tcmu_pass_op, | ||||
| 	.execute_unmap		= tcmu_pass_op, | ||||
| }; | ||||
| 
 | ||||
| static sense_reason_t | ||||
| tcmu_parse_cdb(struct se_cmd *cmd) | ||||
| { | ||||
| 	return sbc_parse_cdb(cmd, &tcmu_sbc_ops); | ||||
| 	unsigned char *cdb = cmd->t_task_cdb; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * For REPORT LUNS we always need to emulate the response, for everything | ||||
| 	 * else, pass it up. | ||||
| 	 */ | ||||
| 	if (cdb[0] == REPORT_LUNS) { | ||||
| 		cmd->execute_cmd = spc_emulate_report_luns; | ||||
| 		return TCM_NO_SENSE; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Set DATA_CDB flag for ops that should have it */ | ||||
| 	switch (cdb[0]) { | ||||
| 	case READ_6: | ||||
| 	case READ_10: | ||||
| 	case READ_12: | ||||
| 	case READ_16: | ||||
| 	case WRITE_6: | ||||
| 	case WRITE_10: | ||||
| 	case WRITE_12: | ||||
| 	case WRITE_16: | ||||
| 	case WRITE_VERIFY: | ||||
| 	case WRITE_VERIFY_12: | ||||
| 	case 0x8e: /* WRITE_VERIFY_16 */ | ||||
| 	case COMPARE_AND_WRITE: | ||||
| 	case XDWRITEREAD_10: | ||||
| 		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; | ||||
| 		break; | ||||
| 	case VARIABLE_LENGTH_CMD: | ||||
| 		switch (get_unaligned_be16(&cdb[8])) { | ||||
| 		case READ_32: | ||||
| 		case WRITE_32: | ||||
| 		case 0x0c: /* WRITE_VERIFY_32 */ | ||||
| 		case XDWRITEREAD_32: | ||||
| 			cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	cmd->execute_cmd = tcmu_pass_op; | ||||
| 
 | ||||
| 	return TCM_NO_SENSE; | ||||
| } | ||||
| 
 | ||||
| DEF_TB_DEFAULT_ATTRIBS(tcmu); | ||||
| DEF_TB_DEV_ATTRIB_RO(tcmu, hw_pi_prot_type); | ||||
| TB_DEV_ATTR_RO(tcmu, hw_pi_prot_type); | ||||
| 
 | ||||
| DEF_TB_DEV_ATTRIB_RO(tcmu, hw_block_size); | ||||
| TB_DEV_ATTR_RO(tcmu, hw_block_size); | ||||
| 
 | ||||
| DEF_TB_DEV_ATTRIB_RO(tcmu, hw_max_sectors); | ||||
| TB_DEV_ATTR_RO(tcmu, hw_max_sectors); | ||||
| 
 | ||||
| DEF_TB_DEV_ATTRIB_RO(tcmu, hw_queue_depth); | ||||
| TB_DEV_ATTR_RO(tcmu, hw_queue_depth); | ||||
| 
 | ||||
| static struct configfs_attribute *tcmu_backend_dev_attrs[] = { | ||||
| 	&tcmu_dev_attrib_emulate_model_alias.attr, | ||||
| 	&tcmu_dev_attrib_emulate_dpo.attr, | ||||
| 	&tcmu_dev_attrib_emulate_fua_write.attr, | ||||
| 	&tcmu_dev_attrib_emulate_fua_read.attr, | ||||
| 	&tcmu_dev_attrib_emulate_write_cache.attr, | ||||
| 	&tcmu_dev_attrib_emulate_ua_intlck_ctrl.attr, | ||||
| 	&tcmu_dev_attrib_emulate_tas.attr, | ||||
| 	&tcmu_dev_attrib_emulate_tpu.attr, | ||||
| 	&tcmu_dev_attrib_emulate_tpws.attr, | ||||
| 	&tcmu_dev_attrib_emulate_caw.attr, | ||||
| 	&tcmu_dev_attrib_emulate_3pc.attr, | ||||
| 	&tcmu_dev_attrib_pi_prot_type.attr, | ||||
| 	&tcmu_dev_attrib_hw_pi_prot_type.attr, | ||||
| 	&tcmu_dev_attrib_pi_prot_format.attr, | ||||
| 	&tcmu_dev_attrib_enforce_pr_isids.attr, | ||||
| 	&tcmu_dev_attrib_is_nonrot.attr, | ||||
| 	&tcmu_dev_attrib_emulate_rest_reord.attr, | ||||
| 	&tcmu_dev_attrib_force_pr_aptpl.attr, | ||||
| 	&tcmu_dev_attrib_hw_block_size.attr, | ||||
| 	&tcmu_dev_attrib_block_size.attr, | ||||
| 	&tcmu_dev_attrib_hw_max_sectors.attr, | ||||
| 	&tcmu_dev_attrib_optimal_sectors.attr, | ||||
| 	&tcmu_dev_attrib_hw_queue_depth.attr, | ||||
| 	&tcmu_dev_attrib_queue_depth.attr, | ||||
| 	&tcmu_dev_attrib_max_unmap_lba_count.attr, | ||||
| 	&tcmu_dev_attrib_max_unmap_block_desc_count.attr, | ||||
| 	&tcmu_dev_attrib_unmap_granularity.attr, | ||||
| 	&tcmu_dev_attrib_unmap_granularity_alignment.attr, | ||||
| 	&tcmu_dev_attrib_max_write_same_len.attr, | ||||
| 	NULL, | ||||
| }; | ||||
| 
 | ||||
| @ -1094,7 +1118,7 @@ static struct se_subsystem_api tcmu_template = { | ||||
| 	.inquiry_prod		= "USER", | ||||
| 	.inquiry_rev		= TCMU_VERSION, | ||||
| 	.owner			= THIS_MODULE, | ||||
| 	.transport_type		= TRANSPORT_PLUGIN_VHBA_PDEV, | ||||
| 	.transport_type		= TRANSPORT_PLUGIN_PHBA_PDEV, | ||||
| 	.attach_hba		= tcmu_attach_hba, | ||||
| 	.detach_hba		= tcmu_detach_hba, | ||||
| 	.alloc_device		= tcmu_alloc_device, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user