[Stgt-devel] [PATCH 04/18] iser bidi alloc read buf

Pete Wyckoff pw
Tue Sep 4 22:08:18 CEST 2007


Allocate the read buffer for bidirectional commands in the transport to
pass down to devices.  A device can fill and return this buffer in
task->uaddr, and thus choose to do the read or write processing in any
order.  Unfortunately, this allocation can not be combined with the task
and task->data allocation as the bidi read size is not known until after
AHS processing.

Necessary for iscsi RDMA transport to be able to provide its own buffers
for the read phase too.

Signed-off-by: Pete Wyckoff <pw at osc.edu>
---
 usr/iscsi/iscsid.c |   27 +++++++++++++++++++--------
 usr/tgtd.h         |    2 ++
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/usr/iscsi/iscsid.c b/usr/iscsi/iscsid.c
index 41d5cad..4b4e35f 100644
--- a/usr/iscsi/iscsid.c
+++ b/usr/iscsi/iscsid.c
@@ -992,6 +992,8 @@ void iscsi_free_task(struct iscsi_task *task)
 {
 	struct iscsi_connection *conn = task->conn;
 
+	if (task->addr && task->addr != (unsigned long) task->data)
+		free((void *) (unsigned long) task->addr);
 	free(task);
 	/* from alloc */
 	conn_put(conn);
@@ -1007,10 +1009,6 @@ static void iscsi_free_cmd_task(struct iscsi_task *task)
 	target_cmd_done(&task->scmd);
 
 	list_del(&task->c_hlist);
-	if (task->data) {
-		if ((unsigned long) task->data != task->addr)
-			free((void *) (unsigned long) task->addr);
-	}
 	iscsi_free_task(task);
 }
 
@@ -1073,7 +1071,6 @@ static int iscsi_target_cmd_queue(struct iscsi_task *task)
 	struct scsi_cmd *scmd = &task->scmd;
 	struct iscsi_connection *conn = task->conn;
 	struct iscsi_cmd *req = (struct iscsi_cmd *) &task->req;
-	unsigned long uaddr = (unsigned long) task->data;
 	uint32_t data_len;
 	uint8_t *ahs;
 	int ahslen;
@@ -1116,18 +1113,32 @@ static int iscsi_target_cmd_queue(struct iscsi_task *task)
 
 	/* figure out incoming (write) and outgoing (read) sizes */
 	data_len = 0;
+	scmd->bidi_uaddr = 0;
+	scmd->bidi_len = 0;
+	task->read_len = 0;
 	task->write_len = 0;
+
 	if (task->dir == WRITE || task->dir == BIDIRECTIONAL) {
 		task->write_len = ntohl(req->data_length);
 		data_len = task->write_len;
 	}
-	task->read_len = 0;
 	if (task->dir == BIDIRECTIONAL && ahslen >= 8) {
 		struct iscsi_rlength_ahdr *ahs_bidi = (void *) ahs;
 		if (ahs_bidi->ahstype == ISCSI_AHSTYPE_RLENGTH) {
 			task->read_len = ntohl(ahs_bidi->read_length);
 			dprintf("bidi read len %u\n", task->read_len);
 		}
+		if (task->read_len) {
+			uint32_t len;
+			void *buf;
+
+			len = roundup(task->read_len, 4);
+			buf = malloc(len);
+			if (!buf)
+				return -ENOMEM;
+			scmd->bidi_uaddr = (unsigned long) buf;
+			scmd->bidi_len = task->read_len;
+		}
 	}
 	if (task->dir == READ) {
 		task->read_len = ntohl(req->data_length);
@@ -1136,10 +1147,10 @@ static int iscsi_target_cmd_queue(struct iscsi_task *task)
 
 	memcpy(scmd->lun, task->req.lun, sizeof(scmd->lun));
 	scmd->rw = req->flags & ISCSI_FLAG_CMD_WRITE;
-	scmd->len = ntohl(req->data_length);
+	scmd->len = data_len;
 	scmd->attribute = cmd_attr(task);
 	scmd->tag = req->itt;
-	scmd->uaddr = uaddr;
+	scmd->uaddr = (unsigned long) task->data;
 
 	return target_cmd_queue(conn->session->target->tid, scmd);
 }
diff --git a/usr/tgtd.h b/usr/tgtd.h
index a260588..c92b663 100644
--- a/usr/tgtd.h
+++ b/usr/tgtd.h
@@ -129,6 +129,8 @@ struct scsi_cmd {
 
 	uint64_t uaddr;
 	uint32_t len;
+	uint64_t bidi_uaddr;  /* for read part when bidi */
+	uint32_t bidi_len;
 	int mmapped;
 	struct scsi_lu *dev;
 	unsigned long state;
-- 
1.5.2.5




More information about the stgt mailing list