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

Pete Wyckoff pw
Tue Oct 16 17:19:03 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 69832b2..5d90b06 100644
--- a/usr/iscsi/iscsid.c
+++ b/usr/iscsi/iscsid.c
@@ -988,6 +988,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);
@@ -1003,10 +1005,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);
 }
 
@@ -1069,7 +1067,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;
@@ -1112,18 +1109,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);
@@ -1132,10 +1143,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 1f8e33b..1f5b41f 100644
--- a/usr/tgtd.h
+++ b/usr/tgtd.h
@@ -143,6 +143,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.3.4




More information about the stgt mailing list