[Stgt-devel] [PATCH 4/7] iser bidi alloc read buf

Pete Wyckoff pw
Mon Jul 30 21:00:23 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
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 e092462..be0f449 100644
--- a/usr/iscsi/iscsid.c
+++ b/usr/iscsi/iscsid.c
@@ -987,6 +987,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);
@@ -1002,10 +1004,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);
 }
 
@@ -1066,7 +1064,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;
@@ -1109,18 +1106,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);
@@ -1129,10 +1140,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 f2ca458..2e50aac 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.4




More information about the stgt mailing list