[Stgt-devel] [PATCH] save stag & va for a scsi command on the task object

Erez Zilber erezz
Thu Aug 16 16:44:33 CEST 2007


When a command PDU is received, the iSER header contains the read/write
va & stag. This data was saved on the conn_info object. If another command PDU
was received before this data was used, its va & stag were written over the
data for the previous command. This fix saves the va & stag on the task object.

Signed-off-by: Erez Zilber <erezz at voltaire.com>
---
 usr/iscsi/iscsi_rdma.c |   47 +++++++++++++++++++++++++++++++++++++++++++----
 usr/iscsi/iscsi_tcp.c  |    6 ++++++
 usr/iscsi/iscsid.c     |   10 +++++++++-
 usr/iscsi/iscsid.h     |    3 +++
 usr/iscsi/transport.h  |    2 ++
 5 files changed, 63 insertions(+), 5 deletions(-)

diff --git a/usr/iscsi/iscsi_rdma.c b/usr/iscsi/iscsi_rdma.c
index cc3d836..0e4a080 100644
--- a/usr/iscsi/iscsi_rdma.c
+++ b/usr/iscsi/iscsi_rdma.c
@@ -119,6 +119,12 @@ struct rdmalist {
 	struct iscsi_task	*task;
 };
 
+struct iser_task {
+	/* read and write from the initiator's point of view */
+	uint32_t rem_read_stag, rem_write_stag;
+	uint64_t rem_read_va, rem_write_va;
+};
+
 /*
  * One of these for each iscsi_connection, adds more fields needed for iser.
  */
@@ -1230,6 +1236,7 @@ static int iser_rdma_write(int ind, struct iscsi_pdu *rsp,
 	struct conn_info *ci = &cl.conn[ind];
 	struct iscsi_data_rsp *datain = (struct iscsi_data_rsp *) &rsp->bhs;
 	int last_rdma = (task->offset == task->len);
+	struct iser_task *itask = (struct iser_task *)task->trans_data;
 
 	iser_out(4, "in %s size %d, %p", __func__, rsp->datasize, rsp);
 
@@ -1249,10 +1256,13 @@ static int iser_rdma_write(int ind, struct iscsi_pdu *rsp,
 	dprintf("offset %d len %d last %d\n", task->offset, task->len,
 		last_rdma);
 
+	iser_out(4, "%s() posting RDMA write req: "
+		 "rem_read_stag %x rem_read_va %lx", __func__,
+		 itask->rem_read_stag, itask->rem_read_va);
 	ret = iser_post_rdma_wr(ci, rdmal, rsp->datasize, IBV_WR_RDMA_WRITE,
 				last_rdma ? IBV_SEND_SIGNALED : 0,
-				ci->rem_read_va + offset, ci->rem_read_stag,
-				task);
+				itask->rem_read_va + offset,
+				itask->rem_read_stag, task);
 
 	if (ret < 0) {
 		eprintf("iser_post_rdma_wr failed\n");
@@ -1279,6 +1289,7 @@ static int iser_rdma_read(int ind, struct iscsi_pdu *rsp)
 	struct conn_info *ci = &cl.conn[ind];
 	struct iscsi_connection *conn = ci->iscsi_conn;
 	struct iscsi_task *task = conn->tx_task;
+	struct iser_task *itask = (struct iser_task *)task->trans_data;
 	struct iscsi_r2t_rsp *r2t = (struct iscsi_r2t_rsp *) &rsp->bhs;
 	uint8_t *buf;
 	uint32_t len;
@@ -1295,9 +1306,13 @@ static int iser_rdma_read(int ind, struct iscsi_pdu *rsp)
 		return -1;
 	}
 
+	iser_out(4, "%s() posting RDMA read req: "
+		 "rem_read_stag %x rem_read_va %lx", __func__,
+		 itask->rem_write_stag, itask->rem_write_va);
+
 	ret = iser_post_rdma_wr(ci, rdma, len, IBV_WR_RDMA_READ,
-				IBV_SEND_SIGNALED, ci->rem_write_va,
-				ci->rem_write_stag, task);
+				IBV_SEND_SIGNALED, itask->rem_write_va,
+				itask->rem_write_stag, task);
 	if (ret < 0) {
 		iser_out(4, "iser_post_rdma_wr failed");
 		return ret;
@@ -1447,10 +1462,34 @@ static void iser_event_modify(int ep, int events)
 	}
 }
 
+void iscsi_iser_task_init(struct iscsi_task *task)
+{
+	struct conn_info *ci;
+	struct iser_task *itask;
+
+	iser_out(8, "%s() Entry", __func__);
+
+	ci = &cl.conn[task->conn->fd];
+	if (!ci->valid) {
+		eprintf("conn %d not valid\n", task->conn->fd);
+		exit(1);
+	}
+
+	itask = (struct iser_task *)task->trans_data;
+
+	/* copy the remote va & stag that were temporarily saved in conn_info */
+	itask->rem_read_stag = ci->rem_read_stag;
+	itask->rem_read_va = ci->rem_read_va;
+	itask->rem_write_stag = ci->rem_write_stag;
+	itask->rem_write_va = ci->rem_write_va;
+}
+
 struct iscsi_transport iscsi_iser = {
 	.name			= "iser",
 	.rdma			= 1,
+	.trans_data_len		= sizeof(struct iser_task),
 	.ep_init		= iscsi_iser_init,
+	.ep_task_init		= iscsi_iser_task_init,
 	.ep_read		= iscsi_iser_read,
 	.ep_write_begin		= iscsi_iser_write_begin,
 	.ep_write_end		= iscsi_iser_write_end,
diff --git a/usr/iscsi/iscsi_tcp.c b/usr/iscsi/iscsi_tcp.c
index e7f5989..b6e9630 100644
--- a/usr/iscsi/iscsi_tcp.c
+++ b/usr/iscsi/iscsi_tcp.c
@@ -251,10 +251,16 @@ void iscsi_tcp_free(void *buf)
 	free(buf);
 }
 
+void iscsi_tcp_task_init(struct iscsi_task *task)
+{
+}
+
 struct iscsi_transport iscsi_tcp = {
 	.name			= "iscsi",
 	.rdma			= 0,
+	.trans_data_len		= 0,
 	.ep_init		= iscsi_tcp_init,
+	.ep_task_init		= iscsi_tcp_task_init,
 	.ep_read		= iscsi_tcp_read,
 	.ep_write_begin		= iscsi_tcp_write_begin,
 	.ep_write_end		= iscsi_tcp_write_end,
diff --git a/usr/iscsi/iscsid.c b/usr/iscsi/iscsid.c
index a3fa6af..c174b98 100644
--- a/usr/iscsi/iscsid.c
+++ b/usr/iscsi/iscsid.c
@@ -1022,11 +1022,17 @@ iscsi_alloc_task(struct iscsi_connection *conn, int ext_len)
 	struct iscsi_hdr *req = (struct iscsi_hdr *) &conn->req.bhs;
 	struct iscsi_task *task;
 
-	task = conn->tp->ep_malloc(sizeof(*task) + ext_len);
+	task = conn->tp->ep_malloc(sizeof(*task) + conn->tp->trans_data_len +
+				   ext_len);
 	if (!task)
 		return NULL;
 	memset(task, 0, sizeof(*task));
 
+	if (conn->tp->trans_data_len) {
+		task->trans_data = (void *)((unsigned long)&task[1] + ext_len);
+		memset(task->trans_data, 0, conn->tp->trans_data_len);
+	}
+
 	memcpy(&task->req, req, sizeof(*req));
 	task->conn = conn;
 	INIT_LIST_HEAD(&task->c_hlist);
@@ -1470,6 +1476,8 @@ static int iscsi_scsi_cmd_rx_start(struct iscsi_connection *conn)
 	else
 		return -ENOMEM;
 
+	conn->tp->ep_task_init(task);
+
 	task->tag = req->itt;
 
 	if (ahs_len) {
diff --git a/usr/iscsi/iscsid.h b/usr/iscsi/iscsid.h
index 95540f2..ae4490a 100644
--- a/usr/iscsi/iscsid.h
+++ b/usr/iscsi/iscsid.h
@@ -128,6 +128,9 @@ struct iscsi_task {
 	void *ahs;
 	void *data;
 
+	/* Transport specific data */
+	void *trans_data;
+
 	struct scsi_cmd scmd;
 
 	unsigned long extdata[0];
diff --git a/usr/iscsi/transport.h b/usr/iscsi/transport.h
index ebb9a23..54f8cd6 100644
--- a/usr/iscsi/transport.h
+++ b/usr/iscsi/transport.h
@@ -7,8 +7,10 @@ struct iscsi_task;
 struct iscsi_transport {
 	const char *name;
 	int rdma;
+	int trans_data_len;
 
 	int (*ep_init) (void);
+	void (*ep_task_init) (struct iscsi_task *task);
 	size_t (*ep_read) (int ep, void *buf, size_t nbytes);
 	size_t (*ep_write_begin) (int ep, void *buf, size_t nbytes);
 	void (*ep_write_end)(int ep);
-- 
1.5.2





More information about the stgt mailing list