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 |