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

Commit c6668726 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI target updates from Nicholas Bellinger:
 "Lots of activity in target land the last months.

  The highlights include:

   - Convert fabric drivers tree-wide to target_register_template() (hch
     + bart)

   - iser-target hardening fixes + v1.0 improvements (sagi)

   - Convert iscsi_thread_set usage to kthread.h + kill
     iscsi_target_tq.c (sagi + nab)

   - Add support for T10-PI WRITE_STRIP + READ_INSERT operation (mkp +
     sagi + nab)

   - DIF fixes for CONFIG_DEBUG_SG=y + UNMAP file emulation (akinobu +
     sagi + mkp)

   - Extended TCMU ABI v2 for future BIDI + DIF support (andy + ilias)

   - Fix COMPARE_AND_WRITE handling for NO_ALLLOC drivers (hch + nab)

  Thanks to everyone who contributed this round with new features,
  bug-reports, fixes, cleanups and improvements.

  Looking forward, it's currently shaping up to be a busy v4.2 as well"

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (69 commits)
  target: Put TCMU under a new config option
  target: Version 2 of TCMU ABI
  target: fix tcm_mod_builder.py
  target/file: Fix UNMAP with DIF protection support
  target/file: Fix SG table for prot_buf initialization
  target/file: Fix BUG() when CONFIG_DEBUG_SG=y and DIF protection enabled
  target: Make core_tmr_abort_task() skip TMFs
  target/sbc: Update sbc_dif_generate pr_debug output
  target/sbc: Make internal DIF emulation honor ->prot_checks
  target/sbc: Return INVALID_CDB_FIELD if DIF + sess_prot_type disabled
  target: Ensure sess_prot_type is saved across session restart
  target/rd: Don't pass incomplete scatterlist entries to sbc_dif_verify_*
  target: Remove the unused flag SCF_ACK_KREF
  target: Fix two sparse warnings
  target: Fix COMPARE_AND_WRITE with SG_TO_MEM_NOALLOC handling
  target: simplify the target template registration API
  target: simplify target_xcopy_init_pt_lun
  target: remove the unused SCF_CMD_XCOPY_PASSTHROUGH flag
  target/rd: reduce code duplication in rd_execute_rw()
  tcm_loop: fixup tpgt string to integer conversion
  ...
parents 06b45f2a 68d4cef3
Loading
Loading
Loading
Loading
+12 −67
Original line number Original line Diff line number Diff line
@@ -237,8 +237,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
	buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
	buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
	buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"
	buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"


	buf += "/* Local pointer to allocated TCM configfs fabric module */\n"
	buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops;\n\n"
	buf += "struct target_fabric_configfs *" + fabric_mod_name + "_fabric_configfs;\n\n"


	buf += "static struct se_node_acl *" + fabric_mod_name + "_make_nodeacl(\n"
	buf += "static struct se_node_acl *" + fabric_mod_name + "_make_nodeacl(\n"
	buf += "	struct se_portal_group *se_tpg,\n"
	buf += "	struct se_portal_group *se_tpg,\n"
@@ -309,8 +308,8 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
	buf += "	}\n"
	buf += "	}\n"
	buf += "	tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n"
	buf += "	tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n"
	buf += "	tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n"
	buf += "	tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n"
	buf += "	ret = core_tpg_register(&" + fabric_mod_name + "_fabric_configfs->tf_ops, wwn,\n"
	buf += "	ret = core_tpg_register(&" + fabric_mod_name + "_ops, wwn,\n"
	buf += "				&tpg->se_tpg, (void *)tpg,\n"
	buf += "				&tpg->se_tpg, tpg,\n"
	buf += "				TRANSPORT_TPG_TYPE_NORMAL);\n"
	buf += "				TRANSPORT_TPG_TYPE_NORMAL);\n"
	buf += "	if (ret < 0) {\n"
	buf += "	if (ret < 0) {\n"
	buf += "		kfree(tpg);\n"
	buf += "		kfree(tpg);\n"
@@ -370,7 +369,10 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
	buf += "	NULL,\n"
	buf += "	NULL,\n"
	buf += "};\n\n"
	buf += "};\n\n"


	buf += "static struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
	buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
	buf += "	.module				= THIS_MODULE,\n"
	buf += "	.name				= " + fabric_mod_name + ",\n"
	buf += "	.get_fabric_proto_ident		= " + fabric_mod_name + "_get_fabric_proto_ident,\n"
	buf += "	.get_fabric_name		= " + fabric_mod_name + "_get_fabric_name,\n"
	buf += "	.get_fabric_name		= " + fabric_mod_name + "_get_fabric_name,\n"
	buf += "	.get_fabric_proto_ident		= " + fabric_mod_name + "_get_fabric_proto_ident,\n"
	buf += "	.get_fabric_proto_ident		= " + fabric_mod_name + "_get_fabric_proto_ident,\n"
	buf += "	.tpg_get_wwn			= " + fabric_mod_name + "_get_fabric_wwn,\n"
	buf += "	.tpg_get_wwn			= " + fabric_mod_name + "_get_fabric_wwn,\n"
@@ -413,75 +415,18 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
	buf += "	.fabric_drop_np			= NULL,\n"
	buf += "	.fabric_drop_np			= NULL,\n"
	buf += "	.fabric_make_nodeacl		= " + fabric_mod_name + "_make_nodeacl,\n"
	buf += "	.fabric_make_nodeacl		= " + fabric_mod_name + "_make_nodeacl,\n"
	buf += "	.fabric_drop_nodeacl		= " + fabric_mod_name + "_drop_nodeacl,\n"
	buf += "	.fabric_drop_nodeacl		= " + fabric_mod_name + "_drop_nodeacl,\n"
	buf += "};\n\n"
	buf += "\n"

	buf += "	.tfc_wwn_attrs			= " + fabric_mod_name + "_wwn_attrs;\n"
	buf += "static int " + fabric_mod_name + "_register_configfs(void)\n"
	buf += "{\n"
	buf += "	struct target_fabric_configfs *fabric;\n"
	buf += "	int ret;\n\n"
	buf += "	printk(KERN_INFO \"" + fabric_mod_name.upper() + " fabric module %s on %s/%s\"\n"
	buf += "		\" on \"UTS_RELEASE\"\\n\"," + fabric_mod_name.upper() + "_VERSION, utsname()->sysname,\n"
	buf += "		utsname()->machine);\n"
	buf += "	/*\n"
	buf += "	 * Register the top level struct config_item_type with TCM core\n"
	buf += "	 */\n"
	buf += "	fabric = target_fabric_configfs_init(THIS_MODULE, \"" + fabric_mod_name + "\");\n"
	buf += "	if (IS_ERR(fabric)) {\n"
	buf += "		printk(KERN_ERR \"target_fabric_configfs_init() failed\\n\");\n"
	buf += "		return PTR_ERR(fabric);\n"
	buf += "	}\n"
	buf += "	/*\n"
	buf += "	 * Setup fabric->tf_ops from our local " + fabric_mod_name + "_ops\n"
	buf += "	 */\n"
	buf += "	fabric->tf_ops = " + fabric_mod_name + "_ops;\n"
	buf += "	/*\n"
	buf += "	 * Setup default attribute lists for various fabric->tf_cit_tmpl\n"
	buf += "	 */\n"
	buf += "	fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = " + fabric_mod_name + "_wwn_attrs;\n"
	buf += "	fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = NULL;\n"
	buf += "	fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;\n"
	buf += "	fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;\n"
	buf += "	fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;\n"
	buf += "	fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;\n"
	buf += "	fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;\n"
	buf += "	fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;\n"
	buf += "	fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;\n"
	buf += "	/*\n"
	buf += "	 * Register the fabric for use within TCM\n"
	buf += "	 */\n"
	buf += "	ret = target_fabric_configfs_register(fabric);\n"
	buf += "	if (ret < 0) {\n"
	buf += "		printk(KERN_ERR \"target_fabric_configfs_register() failed\"\n"
	buf += "				\" for " + fabric_mod_name.upper() + "\\n\");\n"
	buf += "		return ret;\n"
	buf += "	}\n"
	buf += "	/*\n"
	buf += "	 * Setup our local pointer to *fabric\n"
	buf += "	 */\n"
	buf += "	" + fabric_mod_name + "_fabric_configfs = fabric;\n"
	buf += "	printk(KERN_INFO \"" +  fabric_mod_name.upper() + "[0] - Set fabric -> " + fabric_mod_name + "_fabric_configfs\\n\");\n"
	buf += "	return 0;\n"
	buf += "};\n\n"
	buf += "static void __exit " + fabric_mod_name + "_deregister_configfs(void)\n"
	buf += "{\n"
	buf += "	if (!" + fabric_mod_name + "_fabric_configfs)\n"
	buf += "		return;\n\n"
	buf += "	target_fabric_configfs_deregister(" + fabric_mod_name + "_fabric_configfs);\n"
	buf += "	" + fabric_mod_name + "_fabric_configfs = NULL;\n"
	buf += "	printk(KERN_INFO \"" +  fabric_mod_name.upper() + "[0] - Cleared " + fabric_mod_name + "_fabric_configfs\\n\");\n"
	buf += "};\n\n"
	buf += "};\n\n"


	buf += "static int __init " + fabric_mod_name + "_init(void)\n"
	buf += "static int __init " + fabric_mod_name + "_init(void)\n"
	buf += "{\n"
	buf += "{\n"
	buf += "	int ret;\n\n"
	buf += "	return target_register_template(" + fabric_mod_name + "_ops);\n"
	buf += "	ret = " + fabric_mod_name + "_register_configfs();\n"
	buf += "	if (ret < 0)\n"
	buf += "		return ret;\n\n"
	buf += "	return 0;\n"
	buf += "};\n\n"
	buf += "};\n\n"

	buf += "static void __exit " + fabric_mod_name + "_exit(void)\n"
	buf += "static void __exit " + fabric_mod_name + "_exit(void)\n"
	buf += "{\n"
	buf += "{\n"
	buf += "	" + fabric_mod_name + "_deregister_configfs();\n"
	buf += "	target_unregister_template(" + fabric_mod_name + "_ops);\n"
	buf += "};\n\n"
	buf += "};\n\n"


	buf += "MODULE_DESCRIPTION(\"" + fabric_mod_name.upper() + " series fabric driver\");\n"
	buf += "MODULE_DESCRIPTION(\"" + fabric_mod_name.upper() + " series fabric driver\");\n"
+28 −15
Original line number Original line Diff line number Diff line
@@ -138,27 +138,40 @@ signals the kernel via a 4-byte write(). When cmd_head equals
cmd_tail, the ring is empty -- no commands are currently waiting to be
cmd_tail, the ring is empty -- no commands are currently waiting to be
processed by userspace.
processed by userspace.


TCMU commands start with a common header containing "len_op", a 32-bit
TCMU commands are 8-byte aligned. They start with a common header
value that stores the length, as well as the opcode in the lowest
containing "len_op", a 32-bit value that stores the length, as well as
unused bits. Currently only two opcodes are defined, TCMU_OP_PAD and
the opcode in the lowest unused bits. It also contains cmd_id and
TCMU_OP_CMD. When userspace encounters a command with PAD opcode, it
flags fields for setting by the kernel (kflags) and userspace
should skip ahead by the bytes in "length". (The kernel inserts PAD
(uflags).
entries to ensure each CMD entry fits contigously into the circular

buffer.)
Currently only two opcodes are defined, TCMU_OP_CMD and TCMU_OP_PAD.


When userspace handles a CMD, it finds the SCSI CDB (Command Data
When the opcode is CMD, the entry in the command ring is a struct
Block) via tcmu_cmd_entry.req.cdb_off. This is an offset from the
tcmu_cmd_entry. Userspace finds the SCSI CDB (Command Data Block) via
start of the overall shared memory region, not the entry. The data
tcmu_cmd_entry.req.cdb_off. This is an offset from the start of the
in/out buffers are accessible via tht req.iov[] array. Note that
overall shared memory region, not the entry. The data in/out buffers
each iov.iov_base is also an offset from the start of the region.
are accessible via tht req.iov[] array. iov_cnt contains the number of

entries in iov[] needed to describe either the Data-In or Data-Out
TCMU currently does not support BIDI operations.
buffers. For bidirectional commands, iov_cnt specifies how many iovec
entries cover the Data-Out area, and iov_bidi_count specifies how many
iovec entries immediately after that in iov[] cover the Data-In
area. Just like other fields, iov.iov_base is an offset from the start
of the region.


When completing a command, userspace sets rsp.scsi_status, and
When completing a command, userspace sets rsp.scsi_status, and
rsp.sense_buffer if necessary. Userspace then increments
rsp.sense_buffer if necessary. Userspace then increments
mailbox.cmd_tail by entry.hdr.length (mod cmdr_size) and signals the
mailbox.cmd_tail by entry.hdr.length (mod cmdr_size) and signals the
kernel via the UIO method, a 4-byte write to the file descriptor.
kernel via the UIO method, a 4-byte write to the file descriptor.


When the opcode is PAD, userspace only updates cmd_tail as above --
it's a no-op. (The kernel inserts PAD entries to ensure each CMD entry
is contiguous within the command ring.)

More opcodes may be added in the future. If userspace encounters an
opcode it does not handle, it must set UNKNOWN_OP bit (bit 0) in
hdr.uflags, update cmd_tail, and proceed with processing additional
commands, if any.

The Data Area:
The Data Area:


This is shared-memory space after the command ring. The organization
This is shared-memory space after the command ring. The organization
+380 −311

File changed.

Preview size limit exceeded, changes collapsed.

+18 −19
Original line number Original line Diff line number Diff line
@@ -31,7 +31,6 @@
#define isert_err(fmt, arg...) \
#define isert_err(fmt, arg...) \
	pr_err(PFX "%s: " fmt, __func__ , ## arg)
	pr_err(PFX "%s: " fmt, __func__ , ## arg)


#define ISERT_RDMA_LISTEN_BACKLOG	10
#define ISCSI_ISER_SG_TABLESIZE		256
#define ISCSI_ISER_SG_TABLESIZE		256
#define ISER_FASTREG_LI_WRID		0xffffffffffffffffULL
#define ISER_FASTREG_LI_WRID		0xffffffffffffffffULL
#define ISER_BEACON_WRID               0xfffffffffffffffeULL
#define ISER_BEACON_WRID               0xfffffffffffffffeULL
@@ -160,27 +159,25 @@ struct isert_conn {
	u64			login_req_dma;
	u64			login_req_dma;
	int			login_req_len;
	int			login_req_len;
	u64			login_rsp_dma;
	u64			login_rsp_dma;
	unsigned int		conn_rx_desc_head;
	unsigned int		rx_desc_head;
	struct iser_rx_desc	*conn_rx_descs;
	struct iser_rx_desc	*rx_descs;
	struct ib_recv_wr	conn_rx_wr[ISERT_MIN_POSTED_RX];
	struct ib_recv_wr	rx_wr[ISERT_MIN_POSTED_RX];
	struct iscsi_conn	*conn;
	struct iscsi_conn	*conn;
	struct list_head	conn_accept_node;
	struct list_head	accept_node;
	struct completion	conn_login_comp;
	struct completion	login_comp;
	struct completion	login_req_comp;
	struct completion	login_req_comp;
	struct iser_tx_desc	conn_login_tx_desc;
	struct iser_tx_desc	login_tx_desc;
	struct rdma_cm_id	*conn_cm_id;
	struct rdma_cm_id	*cm_id;
	struct ib_pd		*conn_pd;
	struct ib_qp		*qp;
	struct ib_mr		*conn_mr;
	struct isert_device	*device;
	struct ib_qp		*conn_qp;
	struct mutex		mutex;
	struct isert_device	*conn_device;
	struct completion	wait;
	struct mutex		conn_mutex;
	struct completion	wait_comp_err;
	struct completion	conn_wait;
	struct kref		kref;
	struct completion	conn_wait_comp_err;
	struct list_head	fr_pool;
	struct kref		conn_kref;
	int			fr_pool_size;
	struct list_head	conn_fr_pool;
	int			conn_fr_pool_size;
	/* lock to protect fastreg pool */
	/* lock to protect fastreg pool */
	spinlock_t		conn_lock;
	spinlock_t		pool_lock;
	struct work_struct	release_work;
	struct work_struct	release_work;
	struct ib_recv_wr       beacon;
	struct ib_recv_wr       beacon;
	bool                    logout_posted;
	bool                    logout_posted;
@@ -211,6 +208,8 @@ struct isert_device {
	bool			pi_capable;
	bool			pi_capable;
	int			refcount;
	int			refcount;
	struct ib_device	*ib_device;
	struct ib_device	*ib_device;
	struct ib_pd		*pd;
	struct ib_mr		*mr;
	struct isert_comp	*comps;
	struct isert_comp	*comps;
	int                     comps_used;
	int                     comps_used;
	struct list_head	dev_node;
	struct list_head	dev_node;
+13 −36
Original line number Original line Diff line number Diff line
@@ -93,7 +93,7 @@ MODULE_PARM_DESC(srpt_service_guid,
		 " instead of using the node_guid of the first HCA.");
		 " instead of using the node_guid of the first HCA.");


static struct ib_client srpt_client;
static struct ib_client srpt_client;
static struct target_fabric_configfs *srpt_target;
static const struct target_core_fabric_ops srpt_template;
static void srpt_release_channel(struct srpt_rdma_ch *ch);
static void srpt_release_channel(struct srpt_rdma_ch *ch);
static int srpt_queue_status(struct se_cmd *cmd);
static int srpt_queue_status(struct se_cmd *cmd);


@@ -3845,7 +3845,7 @@ static struct se_portal_group *srpt_make_tpg(struct se_wwn *wwn,
	int res;
	int res;


	/* Initialize sport->port_wwn and sport->port_tpg_1 */
	/* Initialize sport->port_wwn and sport->port_tpg_1 */
	res = core_tpg_register(&srpt_target->tf_ops, &sport->port_wwn,
	res = core_tpg_register(&srpt_template, &sport->port_wwn,
			&sport->port_tpg_1, sport, TRANSPORT_TPG_TYPE_NORMAL);
			&sport->port_tpg_1, sport, TRANSPORT_TPG_TYPE_NORMAL);
	if (res)
	if (res)
		return ERR_PTR(res);
		return ERR_PTR(res);
@@ -3913,7 +3913,9 @@ static struct configfs_attribute *srpt_wwn_attrs[] = {
	NULL,
	NULL,
};
};


static struct target_core_fabric_ops srpt_template = {
static const struct target_core_fabric_ops srpt_template = {
	.module				= THIS_MODULE,
	.name				= "srpt",
	.get_fabric_name		= srpt_get_fabric_name,
	.get_fabric_name		= srpt_get_fabric_name,
	.get_fabric_proto_ident		= srpt_get_fabric_proto_ident,
	.get_fabric_proto_ident		= srpt_get_fabric_proto_ident,
	.tpg_get_wwn			= srpt_get_fabric_wwn,
	.tpg_get_wwn			= srpt_get_fabric_wwn,
@@ -3958,6 +3960,10 @@ static struct target_core_fabric_ops srpt_template = {
	.fabric_drop_np			= NULL,
	.fabric_drop_np			= NULL,
	.fabric_make_nodeacl		= srpt_make_nodeacl,
	.fabric_make_nodeacl		= srpt_make_nodeacl,
	.fabric_drop_nodeacl		= srpt_drop_nodeacl,
	.fabric_drop_nodeacl		= srpt_drop_nodeacl,

	.tfc_wwn_attrs			= srpt_wwn_attrs,
	.tfc_tpg_base_attrs		= srpt_tpg_attrs,
	.tfc_tpg_attrib_attrs		= srpt_tpg_attrib_attrs,
};
};


/**
/**
@@ -3988,33 +3994,9 @@ static int __init srpt_init_module(void)
		goto out;
		goto out;
	}
	}


	srpt_target = target_fabric_configfs_init(THIS_MODULE, "srpt");
	ret = target_register_template(&srpt_template);
	if (IS_ERR(srpt_target)) {
	if (ret)
		pr_err("couldn't register\n");
		ret = PTR_ERR(srpt_target);
		goto out;
		goto out;
	}

	srpt_target->tf_ops = srpt_template;

	/*
	 * Set up default attribute lists.
	 */
	srpt_target->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = srpt_wwn_attrs;
	srpt_target->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = srpt_tpg_attrs;
	srpt_target->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = srpt_tpg_attrib_attrs;
	srpt_target->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
	srpt_target->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
	srpt_target->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
	srpt_target->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
	srpt_target->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
	srpt_target->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;

	ret = target_fabric_configfs_register(srpt_target);
	if (ret < 0) {
		pr_err("couldn't register\n");
		goto out_free_target;
	}


	ret = ib_register_client(&srpt_client);
	ret = ib_register_client(&srpt_client);
	if (ret) {
	if (ret) {
@@ -4025,11 +4007,7 @@ static int __init srpt_init_module(void)
	return 0;
	return 0;


out_unregister_target:
out_unregister_target:
	target_fabric_configfs_deregister(srpt_target);
	target_unregister_template(&srpt_template);
	srpt_target = NULL;
out_free_target:
	if (srpt_target)
		target_fabric_configfs_free(srpt_target);
out:
out:
	return ret;
	return ret;
}
}
@@ -4037,8 +4015,7 @@ static int __init srpt_init_module(void)
static void __exit srpt_cleanup_module(void)
static void __exit srpt_cleanup_module(void)
{
{
	ib_unregister_client(&srpt_client);
	ib_unregister_client(&srpt_client);
	target_fabric_configfs_deregister(srpt_target);
	target_unregister_template(&srpt_template);
	srpt_target = NULL;
}
}


module_init(srpt_init_module);
module_init(srpt_init_module);
Loading