Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9c1cd1b6 authored by Andy Grover's avatar Andy Grover Committed by Nicholas Bellinger
Browse files

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: default avatarAndy Grover <agrover@redhat.com>
Reviewed-by: default avatarIlias Tsitsimpis <iliastsi@arrikto.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent cf87edc6
Loading
Loading
Loading
Loading
+1 −20
Original line number Diff line number Diff line
@@ -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
------------

+74 −50
Original line number Diff line number Diff line
@@ -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;
		}
@@ -1016,12 +1036,9 @@ static sector_t tcmu_get_blocks(struct se_device *dev)
}

static sense_reason_t
tcmu_execute_rw(struct se_cmd *se_cmd, struct scatterlist *sgl, u32 sgl_nents,
		enum dma_data_direction data_direction)
tcmu_pass_op(struct se_cmd *se_cmd)
{
	int ret;

	ret = tcmu_queue_cmd(se_cmd);
	int ret = tcmu_queue_cmd(se_cmd);

	if (ret != 0)
		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -1030,62 +1047,69 @@ tcmu_execute_rw(struct se_cmd *se_cmd, struct scatterlist *sgl, u32 sgl_nents,
}

static sense_reason_t
tcmu_pass_op(struct se_cmd *se_cmd)
tcmu_parse_cdb(struct se_cmd *cmd)
{
	int ret = tcmu_queue_cmd(se_cmd);
	unsigned char *cdb = cmd->t_task_cdb;

	if (ret != 0)
		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
	else
	/*
	 * 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;
	}

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,
};
	/* 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;
		}
	}

static sense_reason_t
tcmu_parse_cdb(struct se_cmd *cmd)
{
	return sbc_parse_cdb(cmd, &tcmu_sbc_ops);
	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,