[stgt] Strange sendtargets behaviour

FUJITA Tomonori fujita.tomonori at lab.ntt.co.jp
Thu Sep 10 05:49:58 CEST 2009


On Mon, 7 Sep 2009 11:38:49 +0100
Chris Webb <chris at arachsys.com> wrote:

> FUJITA Tomonori <fujita.tomonori at lab.ntt.co.jp> writes:
> 
> > Ok, I hacked up a patch to support multiple PDUs in SendTarget
> > session. Can you try this with the default
> > discovery.sendtargets.iscsi.MaxRecvDataSegmentLength?
> 
> Hi. Many thanks for this. I'll deploy it to a test VM and try it now.

Sorry, I think that there is a bug in the patch (might send corrupted
SendTarget buffer). Let me know this works.


diff --git a/usr/iscsi/conn.c b/usr/iscsi/conn.c
index 61b570e..ba7a58f 100644
--- a/usr/iscsi/conn.c
+++ b/usr/iscsi/conn.c
@@ -54,6 +54,7 @@ int conn_init(struct iscsi_connection *conn)
 		free(conn->req_buffer);
 		return -ENOMEM;
 	}
+	conn->rsp_buffer_size = INCOMING_BUFSIZE;
 
 	conn->refcount = 1;
 	conn->state = STATE_FREE;
diff --git a/usr/iscsi/iscsid.c b/usr/iscsi/iscsid.c
index 79c6e2d..5bde3a5 100644
--- a/usr/iscsi/iscsid.c
+++ b/usr/iscsi/iscsid.c
@@ -161,21 +161,23 @@ void text_key_add(struct iscsi_connection *conn, char *key, char *value)
 	if (conn->state == STATE_FULL)
 		max_len = conn->session_param[ISCSI_PARAM_MAX_XMIT_DLENGTH].val;
 	else
-		max_len = INCOMING_BUFSIZE;
+		max_len = conn->rsp_buffer_size;
 
 	if (!conn->rsp.datasize)
 		conn->rsp.data = conn->rsp_buffer;
 
 	buffer = conn->rsp_buffer;
 
-	if (conn->rsp.datasize + len > max_len)
+	if (conn->rsp.datasize + len > max_len &&
+	    (conn->req.bhs.opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_TEXT)
 		goto drop;
 
-	if (conn->rsp.datasize + len > INCOMING_BUFSIZE) {
-		buffer = realloc(buffer, conn->rsp.datasize + len);
-		if (buffer)
+	if (conn->rsp.datasize + len > conn->rsp_buffer_size) {
+		buffer = realloc(buffer, conn->rsp_buffer_size * 2);
+		if (buffer) {
 			conn->rsp_buffer = buffer;
-		else
+			conn->rsp_buffer_size *= 2;
+		} else
 			goto drop;
 	}
 
@@ -805,26 +807,45 @@ static void cmnd_exec_text(struct iscsi_connection *conn)
 {
 	struct iscsi_text *req = (struct iscsi_text *)&conn->req.bhs;
 	struct iscsi_text_rsp *rsp = (struct iscsi_text_rsp *)&conn->rsp.bhs;
+	int max_len = conn->session_param[ISCSI_PARAM_MAX_XMIT_DLENGTH].val;
 
 	memset(rsp, 0, BHS_SIZE);
 
-	if (be32_to_cpu(req->ttt) != 0xffffffff) {
-		/* reject */;
-	}
 	rsp->opcode = ISCSI_OP_TEXT_RSP;
 	rsp->itt = req->itt;
-	/* rsp->ttt = rsp->ttt; */
-	rsp->ttt = 0xffffffff;
 	conn->exp_cmd_sn = be32_to_cpu(req->cmdsn);
 	if (!(req->opcode & ISCSI_OP_IMMEDIATE))
 		conn->exp_cmd_sn++;
 
-	dprintf("Text request: %d\n", conn->state);
-	text_scan_text(conn);
+	if (be32_to_cpu(req->ttt) == ISCSI_RESERVED_TAG) {
+		conn->text_datasize = 0;
+		conn->text_rsp_buffer = conn->rsp_buffer;
+
+		text_scan_text(conn);
+
+		conn->text_datasize = conn->rsp.datasize;
+
+		if (conn->text_datasize > max_len) {
+			conn->ttt++;
+			if (conn->ttt == ISCSI_RESERVED_TAG)
+				conn->ttt++;
+		} else
+			conn->ttt = ISCSI_RESERVED_TAG;
+	} else if (!conn->text_datasize || conn->ttt != be32_to_cpu(req->ttt)) {
+		/* reject */
+		return;
+	}
 
-	if (req->flags & ISCSI_FLAG_CMD_FINAL)
+	if (conn->text_datasize < max_len)
 		rsp->flags = ISCSI_FLAG_CMD_FINAL;
 
+	conn->rsp.datasize = min(max_len, conn->text_datasize);
+	conn->rsp.data = conn->text_rsp_buffer;
+	conn->text_rsp_buffer += conn->rsp.datasize;
+	conn->text_datasize -= conn->rsp.datasize;
+
+	rsp->ttt = cpu_to_be32(conn->ttt);
+
 	rsp->statsn = cpu_to_be32(conn->stat_sn++);
 	rsp->exp_cmdsn = cpu_to_be32(conn->exp_cmd_sn);
 	rsp->max_cmdsn = cpu_to_be32(conn->max_cmd_sn);
diff --git a/usr/iscsi/iscsid.h b/usr/iscsi/iscsid.h
index b301c78..02caad2 100644
--- a/usr/iscsi/iscsid.h
+++ b/usr/iscsi/iscsid.h
@@ -165,11 +165,16 @@ struct iscsi_connection {
 	void *req_buffer;
 	struct iscsi_pdu rsp;
 	void *rsp_buffer;
+	int rsp_buffer_size;
 	unsigned char *rx_buffer;
 	unsigned char *tx_buffer;
 	int rx_size;
 	int tx_size;
 
+	uint32_t ttt;
+	int text_datasize;
+	void *text_rsp_buffer;
+
 	struct iscsi_task *rx_task;
 	struct iscsi_task *tx_task;
 
--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the stgt mailing list