changeset 13273:44d974917227

416 iscsit responses truncated to 1 PDU Reviewed by: eric.schrock@delphix.com Reviewed by: garrett@nexenta.com Approved by: garrett@nexenta.com
author Alexander Stetsenko <ams@nexenta.com>
date Fri, 21 Jan 2011 22:57:03 +0300
parents f7d89c5253a8
children 4d93421497f8
files usr/src/uts/common/io/comstar/port/iscsit/iscsit_text.c
diffstat 1 files changed, 51 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/comstar/port/iscsit/iscsit_text.c	Fri Jan 21 13:13:50 2011 +0100
+++ b/usr/src/uts/common/io/comstar/port/iscsit/iscsit_text.c	Fri Jan 21 22:57:03 2011 +0300
@@ -21,6 +21,9 @@
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
+/*
+ * Copyright 2011, Nexenta Systems, Inc. All rights reserved.
+ */
 
 #include <sys/cpuvar.h>
 #include <sys/types.h>
@@ -356,7 +359,7 @@
  * To test with smaller PDUs in order to force multi-PDU responses,
  * set this value such that: 0 < test_max_len < 8192
  */
-uint32_t iscsit_text_max_len = 0;
+uint32_t iscsit_text_max_len = ISCSI_DEFAULT_MAX_RECV_SEG_LEN;
 #endif
 
 /*
@@ -369,55 +372,58 @@
 	iscsi_text_rsp_hdr_t *th_resp;
 	idm_pdu_t	*resp;
 	uint32_t	len, remainder, max_len;
-	char 		*base;
-	int		final;
+	char		*base;
+	boolean_t	final;
 
 	max_len = ISCSI_DEFAULT_MAX_RECV_SEG_LEN;
 #ifdef DEBUG
-	if (iscsit_text_max_len > 0 && iscsit_text_max_len < 8192)
+	if (iscsit_text_max_len > 0 && iscsit_text_max_len < max_len)
 		max_len = iscsit_text_max_len;
 #endif
-	remainder = ict->ict_text_rsp_valid_len - ict->ict_text_rsp_off;
-	if (remainder <= max_len) {
-		len = remainder;
-		final = 1;
-	} else {
-		len = max_len;
-		final = 0;
-	}
-	/*
-	 * Allocate a PDU and copy in text response buffer
-	 */
-	resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), len);
-	idm_pdu_init(resp, ict->ict_ic, ict, iscsit_text_resp_complete_cb);
-	/* Advance the StatSN for each Text Response sent */
-	resp->isp_flags |= IDM_PDU_SET_STATSN | IDM_PDU_ADVANCE_STATSN;
-	base = ict->ict_text_rsp_buf + ict->ict_text_rsp_off;
-	bcopy(base, resp->isp_data, len);
-	/*
-	 * Fill in the response header
-	 */
-	th_resp = (iscsi_text_rsp_hdr_t *)resp->isp_hdr;
-	bzero(th_resp, sizeof (*th_resp));
-	th_resp->opcode = ISCSI_OP_TEXT_RSP;
-	th_resp->itt = th_req->itt;
-	hton24(th_resp->dlength, len);
-	if (final) {
-		th_resp->flags = ISCSI_FLAG_FINAL;
-		th_resp->ttt = ISCSI_RSVD_TASK_TAG;
-		kmem_free(ict->ict_text_rsp_buf, ict->ict_text_rsp_len);
-		ict->ict_text_rsp_buf = NULL;
-		ict->ict_text_rsp_len = 0;
-		ict->ict_text_rsp_valid_len = 0;
-		ict->ict_text_rsp_off = 0;
-	} else {
-		th_resp->flags = ISCSI_FLAG_TEXT_CONTINUE;
-		th_resp->ttt = ict->ict_text_rsp_ttt;
-		ict->ict_text_rsp_off += len;
-	}
-	/* Send the response on its way */
-	iscsit_conn_hold(ict);
-	iscsit_pdu_tx(resp);
+	do {
+		remainder = ict->ict_text_rsp_valid_len - ict->ict_text_rsp_off;
+		if (remainder <= max_len) {
+			len = remainder;
+			final = B_TRUE;
+		} else {
+			len = max_len;
+			final = B_FALSE;
+		}
+		/*
+		 * Allocate a PDU and copy in text response buffer
+		 */
+		resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), len);
+		idm_pdu_init(resp, ict->ict_ic, ict,
+		    iscsit_text_resp_complete_cb);
+		/* Advance the StatSN for each Text Response sent */
+		resp->isp_flags |= IDM_PDU_SET_STATSN | IDM_PDU_ADVANCE_STATSN;
+		base = ict->ict_text_rsp_buf + ict->ict_text_rsp_off;
+		bcopy(base, resp->isp_data, len);
+		/*
+		 * Fill in the response header
+		 */
+		th_resp = (iscsi_text_rsp_hdr_t *)resp->isp_hdr;
+		bzero(th_resp, sizeof (*th_resp));
+		th_resp->opcode = ISCSI_OP_TEXT_RSP;
+		th_resp->itt = th_req->itt;
+		hton24(th_resp->dlength, len);
+		if (final) {
+			th_resp->flags = ISCSI_FLAG_FINAL;
+			th_resp->ttt = ISCSI_RSVD_TASK_TAG;
+			kmem_free(ict->ict_text_rsp_buf, ict->ict_text_rsp_len);
+			ict->ict_text_rsp_buf = NULL;
+			ict->ict_text_rsp_len = 0;
+			ict->ict_text_rsp_valid_len = 0;
+			ict->ict_text_rsp_off = 0;
+		} else {
+			th_resp->flags = ISCSI_FLAG_TEXT_CONTINUE;
+			th_resp->ttt = ict->ict_text_rsp_ttt;
+			ict->ict_text_rsp_off += len;
+		}
+		/* Send the response on its way */
+		iscsit_conn_hold(ict);
+		iscsit_pdu_tx(resp);
+	} while (!final);
 	/* Free the request pdu */
 	idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
 }