[PATCH, RFC] Move command allocation from target drivers into target core

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Nic,

In every LIO target driver there is similar code for allocating and
freeing commands. Had you already considered to move that code from
the target drivers into the target core, e.g. with a patch like the
one below? So far this patch has been tested with the iSCSI protocol
only. The ib_srpt driver has been left out because the patches for
making that driver use percpu_ida_alloc/free are not yet upstream.

Thanks,

Bart.

Subject: [PATCH] target: Introduce target_alloc_cmd() and target_free_cmd()

Introduce target_alloc_cmd() and target_free_cmd(). Remove
se_cmd.map_tag. Instead of passing GFP_ATOMIC as the second argument
to percpu_ida_alloc(), pass TASK_RUNNING.
---
 drivers/scsi/qla2xxx/qla_target.c        | 20 +++++---------------
 drivers/target/iscsi/iscsi_target_util.c | 14 ++++----------
 drivers/target/sbp/sbp_target.c          | 10 +++-------
 drivers/target/target_core_transport.c   | 25 +++++++++++++++++++++++++
 drivers/target/tcm_fc/tfc_cmd.c          | 12 ++++--------
 drivers/usb/gadget/function/f_tcm.c      |  9 +++------
 drivers/vhost/scsi.c                     |  9 +++------
 drivers/xen/xen-scsiback.c               | 12 ++++++------
 include/target/target_core_base.h        |  4 ++--
 include/target/target_core_fabric.h      |  2 ++
 10 files changed, 57 insertions(+), 60 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index ca39deb..c8fb44a 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -3334,7 +3334,7 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd)
 		return;
 	}
 	cmd->jiffies_at_free = get_jiffies_64();
-	percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
+	target_free_cmd(sess->se_sess, cmd);
 }
 EXPORT_SYMBOL(qlt_free_cmd);
 
@@ -3840,7 +3840,7 @@ out_term:
 	qlt_send_term_exchange(vha, NULL, &cmd->atio, 1, 0);
 
 	qlt_decr_num_pend_cmds(vha);
-	percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
+	target_free_cmd(sess->se_sess, cmd);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 	spin_lock_irqsave(&ha->tgt.sess_lock, flags);
@@ -3867,13 +3867,10 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
 {
 	struct se_session *se_sess = sess->se_sess;
 	struct qla_tgt_cmd *cmd;
-	int tag;
 
-	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
-	if (tag < 0)
+	cmd = target_alloc_cmd(se_sess, TASK_RUNNING);
+	if (!cmd)
 		return NULL;
-
-	cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag];
 	memset(cmd, 0, sizeof(struct qla_tgt_cmd));
 
 	memcpy(&cmd->atio, atio, sizeof(*atio));
@@ -3881,7 +3878,6 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
 	cmd->tgt = vha->vha_tgt.qla_tgt;
 	qlt_incr_num_pend_cmds(vha);
 	cmd->vha = vha;
-	cmd->se_cmd.map_tag = tag;
 	cmd->sess = sess;
 	cmd->loop_id = sess->loop_id;
 	cmd->conf_compl_supported = sess->conf_compl_supported;
@@ -5220,7 +5216,6 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
 	struct qla_tgt_sess *sess;
 	struct se_session *se_sess;
 	struct qla_tgt_cmd *cmd;
-	int tag;
 
 	if (unlikely(tgt->tgt_stop)) {
 		ql_dbg(ql_dbg_io, vha, 0x300a,
@@ -5250,12 +5245,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
 		return;
 
 	se_sess = sess->se_sess;
-
-	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
-	if (tag < 0)
-		return;
-
-	cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag];
+	cmd = target_alloc_cmd(se_sess, TASK_RUNNING);
 	if (!cmd) {
 		ql_dbg(ql_dbg_io, vha, 0x3009,
 			"qla_target(%d): %s: Allocation of cmd failed\n",
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 428b0d9..88494d8 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -154,17 +154,12 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, int state)
 {
 	struct iscsi_cmd *cmd;
 	struct se_session *se_sess = conn->sess->se_sess;
-	int size, tag;
 
-	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, state);
-	if (tag < 0)
+	cmd = target_alloc_cmd(se_sess, state);
+	if (!cmd)
 		return NULL;
+	memset(cmd, 0, se_sess->tag_size);
 
-	size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size;
-	cmd = (struct iscsi_cmd *)(se_sess->sess_cmd_map + (tag * size));
-	memset(cmd, 0, size);
-
-	cmd->se_cmd.map_tag = tag;
 	cmd->conn = conn;
 	INIT_LIST_HEAD(&cmd->i_conn_node);
 	INIT_LIST_HEAD(&cmd->datain_list);
@@ -687,7 +682,6 @@ void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
 void iscsit_release_cmd(struct iscsi_cmd *cmd)
 {
 	struct iscsi_session *sess;
-	struct se_cmd *se_cmd = &cmd->se_cmd;
 
 	if (cmd->conn)
 		sess = cmd->conn->sess;
@@ -703,7 +697,7 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd)
 	kfree(cmd->iov_data);
 	kfree(cmd->text_in_ptr);
 
-	percpu_ida_free(&sess->se_sess->sess_tag_pool, se_cmd->map_tag);
+	target_free_cmd(sess->se_sess, cmd);
 }
 EXPORT_SYMBOL(iscsit_release_cmd);
 
diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index 58bb6ed..90eb2f3 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -926,15 +926,11 @@ static struct sbp_target_request *sbp_mgt_get_req(struct sbp_session *sess,
 {
 	struct se_session *se_sess = sess->se_sess;
 	struct sbp_target_request *req;
-	int tag;
 
-	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC);
-	if (tag < 0)
+	req = target_alloc_cmd(se_sess, TASK_RUNNING);
+	if (!req)
 		return ERR_PTR(-ENOMEM);
-
-	req = &((struct sbp_target_request *)se_sess->sess_cmd_map)[tag];
 	memset(req, 0, sizeof(*req));
-	req->se_cmd.map_tag = tag;
 	req->se_cmd.tag = next_orb;
 
 	return req;
@@ -1460,7 +1456,7 @@ static void sbp_free_request(struct sbp_target_request *req)
 	kfree(req->pg_tbl);
 	kfree(req->cmd_buf);
 
-	percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
+	target_free_cmd(se_sess, req);
 }
 
 static void sbp_mgt_agent_process(struct work_struct *work)
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 6c089af..5f92922 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -269,6 +269,9 @@ int transport_alloc_session_tags(struct se_session *se_sess,
 		return -ENOMEM;
 	}
 
+	se_sess->tag_num = tag_num;
+	se_sess->tag_size = tag_size;
+	
 	return 0;
 }
 EXPORT_SYMBOL(transport_alloc_session_tags);
@@ -568,6 +571,28 @@ void transport_deregister_session(struct se_session *se_sess)
 }
 EXPORT_SYMBOL(transport_deregister_session);
 
+void *target_alloc_cmd(struct se_session *sess, int state)
+{
+	int tag = percpu_ida_alloc(&sess->sess_tag_pool, state);
+
+	WARN_ON_ONCE(sess->tag_size == 0);
+	return tag >= 0 ? sess->sess_cmd_map + tag * sess->tag_size : NULL;
+}
+EXPORT_SYMBOL(target_alloc_cmd);
+
+void target_free_cmd(struct se_session *sess, void *ioctx)
+{
+	int tag;
+
+	WARN_ON_ONCE(ioctx < sess->sess_cmd_map ||
+		     ioctx >= sess->sess_cmd_map +
+		     sess->tag_num * sess->tag_size);
+	tag = (ioctx - sess->sess_cmd_map) / sess->tag_size;
+	WARN_ON_ONCE(ioctx != sess->sess_cmd_map + tag * sess->tag_size);
+	percpu_ida_free(&sess->sess_tag_pool, tag);
+}
+EXPORT_SYMBOL(target_free_cmd);
+
 static void target_remove_from_state_list(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index 216e18c..2fd5dbf 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -94,7 +94,7 @@ static void ft_free_cmd(struct ft_cmd *cmd)
 	if (fr_seq(fp))
 		lport->tt.seq_release(fr_seq(fp));
 	fc_frame_free(fp);
-	percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
+	target_free_cmd(sess->se_sess, cmd);
 	ft_sess_put(sess);	/* undo get from lookup at recv */
 }
 
@@ -450,20 +450,16 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp)
 	struct ft_cmd *cmd;
 	struct fc_lport *lport = sess->tport->lport;
 	struct se_session *se_sess = sess->se_sess;
-	int tag;
 
-	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
-	if (tag < 0)
+	cmd = target_alloc_cmd(se_sess, TASK_RUNNING);
+	if (!cmd)
 		goto busy;
-
-	cmd = &((struct ft_cmd *)se_sess->sess_cmd_map)[tag];
 	memset(cmd, 0, sizeof(struct ft_cmd));
 
-	cmd->se_cmd.map_tag = tag;
 	cmd->sess = sess;
 	cmd->seq = lport->tt.seq_assign(lport, fp);
 	if (!cmd->seq) {
-		percpu_ida_free(&se_sess->sess_tag_pool, tag);
+		target_free_cmd(se_sess, cmd);
 		goto busy;
 	}
 	cmd->req_frame = fp;		/* hold frame during cmd */
diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c
index 35fe3c8..78cdfd9 100644
--- a/drivers/usb/gadget/function/f_tcm.c
+++ b/drivers/usb/gadget/function/f_tcm.c
@@ -1071,15 +1071,12 @@ static struct usbg_cmd *usbg_get_cmd(struct f_uas *fu,
 {
 	struct se_session *se_sess = tv_nexus->tvn_se_sess;
 	struct usbg_cmd *cmd;
-	int tag;
 
-	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC);
-	if (tag < 0)
+	cmd = target_alloc_cmd(se_sess, TASK_RUNNING);
+	if (!cmd)
 		return ERR_PTR(-ENOMEM);
 
-	cmd = &((struct usbg_cmd *)se_sess->sess_cmd_map)[tag];
 	memset(cmd, 0, sizeof(*cmd));
-	cmd->se_cmd.map_tag = tag;
 	cmd->se_cmd.tag = cmd->tag = scsi_tag;
 	cmd->fu = fu;
 
@@ -1287,7 +1284,7 @@ static void usbg_release_cmd(struct se_cmd *se_cmd)
 	struct se_session *se_sess = se_cmd->se_sess;
 
 	kfree(cmd->data_buf);
-	percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
+	target_free_cmd(se_sess, cmd);
 }
 
 static u32 usbg_sess_get_index(struct se_session *se_sess)
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 9d6320e..6608e3d 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -330,7 +330,7 @@ static void vhost_scsi_release_cmd(struct se_cmd *se_cmd)
 	}
 
 	vhost_scsi_put_inflight(tv_cmd->inflight);
-	percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
+	target_free_cmd(se_sess, tv_cmd);
 }
 
 static u32 vhost_scsi_sess_get_index(struct se_session *se_sess)
@@ -578,7 +578,6 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
 	struct se_session *se_sess;
 	struct scatterlist *sg, *prot_sg;
 	struct page **pages;
-	int tag;
 
 	tv_nexus = tpg->tpg_nexus;
 	if (!tv_nexus) {
@@ -587,13 +586,12 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
 	}
 	se_sess = tv_nexus->tvn_se_sess;
 
-	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
-	if (tag < 0) {
+	cmd = target_alloc_cmd(se_sess, TASK_RUNNING);
+	if (!cmd) {
 		pr_err("Unable to obtain tag for vhost_scsi_cmd\n");
 		return ERR_PTR(-ENOMEM);
 	}
 
-	cmd = &((struct vhost_scsi_cmd *)se_sess->sess_cmd_map)[tag];
 	sg = cmd->tvc_sgl;
 	prot_sg = cmd->tvc_prot_sgl;
 	pages = cmd->tvc_upages;
@@ -602,7 +600,6 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
 	cmd->tvc_sgl = sg;
 	cmd->tvc_prot_sgl = prot_sg;
 	cmd->tvc_upages = pages;
-	cmd->tvc_se_cmd.map_tag = tag;
 	cmd->tvc_tag = scsi_tag;
 	cmd->tvc_lun = lun;
 	cmd->tvc_task_attr = task_attr;
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index d6950e0..c73f3af 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -665,17 +665,15 @@ static struct vscsibk_pend *scsiback_get_pend_req(struct vscsiif_back_ring *ring
 	struct scsiback_nexus *nexus = tpg->tpg_nexus;
 	struct se_session *se_sess = nexus->tvn_se_sess;
 	struct vscsibk_pend *req;
-	int tag, i;
+	int i;
 
-	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
-	if (tag < 0) {
+	req = target_alloc_cmd(se_sess, TASK_RUNNING);
+	if (!req) {
 		pr_err("Unable to obtain tag for vscsiif_request\n");
 		return ERR_PTR(-ENOMEM);
 	}
 
-	req = &((struct vscsibk_pend *)se_sess->sess_cmd_map)[tag];
 	memset(req, 0, sizeof(*req));
-	req->se_cmd.map_tag = tag;
 
 	for (i = 0; i < VSCSI_MAX_GRANTS; i++)
 		req->grant_handles[i] = SCSIBACK_INVALID_HANDLE;
@@ -1388,6 +1386,8 @@ static int scsiback_check_stop_free(struct se_cmd *se_cmd)
 
 static void scsiback_release_cmd(struct se_cmd *se_cmd)
 {
+	struct vscsibk_pend *req = container_of(se_cmd,
+				struct vscsibk_pend, se_cmd);
 	struct se_session *se_sess = se_cmd->se_sess;
 	struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
 
@@ -1396,7 +1396,7 @@ static void scsiback_release_cmd(struct se_cmd *se_cmd)
 		kfree(tmr);
 	}
 
-	percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
+	target_free_cmd(se_sess, req);
 }
 
 static u32 scsiback_sess_get_index(struct se_session *se_sess)
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index b316b44..a80fefa 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -448,8 +448,6 @@ struct se_cmd {
 	enum dma_data_direction	data_direction;
 	/* For SAM Task Attribute */
 	int			sam_task_attr;
-	/* Used for se_sess->sess_tag_pool */
-	unsigned int		map_tag;
 	/* Transport protocol dependent state, see transport_state_table */
 	enum transport_state_table t_state;
 	/* See se_cmd_flags_table */
@@ -602,6 +600,8 @@ struct se_session {
 	struct list_head	sess_cmd_list;
 	struct list_head	sess_wait_list;
 	spinlock_t		sess_cmd_lock;
+	unsigned int		tag_num;
+	unsigned int		tag_size;
 	void			*sess_cmd_map;
 	struct percpu_ida	sess_tag_pool;
 };
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index ec79da3..cef83dc 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -125,6 +125,8 @@ void	target_put_nacl(struct se_node_acl *);
 void	transport_deregister_session_configfs(struct se_session *);
 void	transport_deregister_session(struct se_session *);
 
+void *target_alloc_cmd(struct se_session *sess, int state);
+void target_free_cmd(struct se_session *sess, void *ioctx);
 
 void	transport_init_se_cmd(struct se_cmd *,
 		const struct target_core_fabric_ops *,
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux