Commit abb6823d authored by Ziye Yang's avatar Ziye Yang Committed by Jim Harris
Browse files

iscsi: Add the support for long text response.



This patch adds the support for long text response.

Change-Id: I8ef146069c9b8d86eb6df4c9e60cc6a3b2ff1ad7
Signed-off-by: default avatarZiye Yang <ziye.yang@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4993


Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 0e47be4b
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -158,6 +158,12 @@ struct spdk_iscsi_conn {
	struct spdk_iscsi_tgt_node	*target;
	struct spdk_scsi_dev		*dev;

	/* To handle the case that SendTargets response is split into
	 * multiple PDUs due to very small MaxRecvDataSegmentLength.
	 */
	uint32_t			send_tgt_completed_size;
	struct iscsi_param		*params_text;

	/* for fast access */
	int header_digest;
	int data_digest;
+15 −1
Original line number Diff line number Diff line
@@ -2360,6 +2360,11 @@ iscsi_pdu_payload_op_text(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *p
		return -1;
	}

	if (pdu->data_segment_len == 0 && params == NULL) {
		params = conn->params_text;
		conn->params_text = NULL;
	}

	data = calloc(1, alloc_len);
	if (!data) {
		SPDK_ERRLOG("calloc() failed for data segment\n");
@@ -2406,6 +2411,11 @@ iscsi_pdu_payload_op_text(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *p
							   data_len);
			}
		}

		if (conn->send_tgt_completed_size != 0) {
			F_bit = 0;
			C_bit = 1;
		}
	} else {
		if (iscsi_param_eq_val(conn->sess->params, "SessionType", "Discovery")) {
			iscsi_param_free(params);
@@ -2414,7 +2424,11 @@ iscsi_pdu_payload_op_text(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *p
		}
	}

	if (spdk_likely(conn->send_tgt_completed_size == 0)) {
		iscsi_param_free(params);
	} else {
		conn->params_text = params;
	}
	SPDK_LOGDUMP(iscsi, "Negotiated Params", data, data_len);

	/* response PDU */
+78 −16
Original line number Diff line number Diff line
@@ -49,6 +49,11 @@
#define MAX_TMPBUF 4096
#define MAX_MASKBUF 128


#define MAX_TMP_NAME_BUF (11 /* TargetName= */ + MAX_TARGET_NAME + 1 /* null */)
#define MAX_TMP_ADDR_BUF (14 /* TargetAddress= */ + MAX_PORTAL_ADDR + 1 /* : */ + \
			  MAX_PORTAL_PORT + 1 /* , */ + 10 /* max length of int in Decimal */ + 1 /* null */)

static bool
iscsi_ipv6_netmask_allow_addr(const char *netmask, const char *addr)
{
@@ -295,16 +300,42 @@ iscsi_tgt_node_allow_iscsi_name(struct spdk_iscsi_tgt_node *target, const char *
	return false;
}

static bool
iscsi_copy_str(char *data, int *total, int alloc_len,
	       int *previous_completed_len, int expected_size, char *src)
{
	int len = 0;

	assert(*previous_completed_len >= 0);

	if (alloc_len - *total < 1) {
		return true;
	}

	if (*previous_completed_len < expected_size) {
		len = spdk_min(alloc_len - *total, expected_size - *previous_completed_len);
		memcpy((char *)data + *total, src + *previous_completed_len, len);
		*total += len;
		*previous_completed_len = 0;
	} else {
		*previous_completed_len -= expected_size;
	}

	return false;
}

static int
iscsi_send_tgt_portals(struct spdk_iscsi_conn *conn,
		       struct spdk_iscsi_tgt_node *target,
		       uint8_t *data, int alloc_len, int total)
		       uint8_t *data, int alloc_len, int total,
		       int *previous_completed_len, bool *no_buf_space)
{
	char buf[MAX_TMPBUF];
	struct spdk_iscsi_portal_grp *pg;
	struct spdk_iscsi_pg_map *pg_map;
	struct spdk_iscsi_portal *p;
	char *host;
	char tmp_buf[MAX_TMP_ADDR_BUF];
	int len;

	TAILQ_FOREACH(pg_map, &target->pg_map_head, tailq) {
@@ -318,13 +349,6 @@ iscsi_send_tgt_portals(struct spdk_iscsi_conn *conn,
		}

		TAILQ_FOREACH(p, &pg->head, per_pg_tailq) {
			if (alloc_len - total < 1) {
				/* TODO: long text responses support */
				SPDK_ERRLOG("SPDK doesn't support long text responses now, "
					    "you can use larger MaxRecvDataSegmentLength"
					    "value in initiator\n");
				return alloc_len;
			}
			host = p->host;
			/* wildcard? */
			if (strcasecmp(host, "[::]") == 0 || strcasecmp(host, "0.0.0.0") == 0) {
@@ -341,9 +365,23 @@ iscsi_send_tgt_portals(struct spdk_iscsi_conn *conn,
			}
			SPDK_DEBUGLOG(iscsi, "TargetAddress=%s:%s,%d\n",
				      host, p->port, pg->tag);
			len = snprintf((char *)data + total, alloc_len - total,
				       "TargetAddress=%s:%s,%d", host, p->port, pg->tag);
			total += len + 1;

			memset(tmp_buf, 0, sizeof(tmp_buf));
			/* Caculate the whole string size */
			len = snprintf(NULL, 0, "TargetAddress=%s:%s,%d", host, p->port, pg->tag);
			assert(len < MAX_TMPBUF);

			/* string contents are not fully copied */
			if (*previous_completed_len < len) {
				/* Copy the string into the temporary buffer */
				snprintf(tmp_buf, len + 1, "TargetAddress=%s:%s,%d", host, p->port, pg->tag);
			}

			*no_buf_space = iscsi_copy_str(data, &total, alloc_len, previous_completed_len,
						       len + 1, tmp_buf);
			if (*no_buf_space) {
				break;
			}
		}
	}

@@ -358,6 +396,9 @@ iscsi_send_tgts(struct spdk_iscsi_conn *conn, const char *iiqn,
	int total;
	int len;
	int rc;
	int previous_completed_size = conn->send_tgt_completed_size;
	bool no_buf_space = false;
	char tmp_buf[MAX_TMP_NAME_BUF];

	if (conn == NULL) {
		return 0;
@@ -384,17 +425,38 @@ iscsi_send_tgts(struct spdk_iscsi_conn *conn, const char *iiqn,
			continue;
		}

		len = snprintf((char *)data + total, alloc_len - total, "TargetName=%s",
			       target->name);
		total += len + 1;
		memset(tmp_buf, 0, sizeof(tmp_buf));
		/* Calculate the whole string size */
		len = snprintf(NULL, 0, "TargetName=%s", target->name);
		assert(len < MAX_TMPBUF);

		total = iscsi_send_tgt_portals(conn, target, data, alloc_len, total);
		if (alloc_len - total < 1) {
		/* String contents are not copyied */
		if (previous_completed_size < len) {
			/* Copy the string into the temporary buffer */
			snprintf(tmp_buf, len + 1, "TargetName=%s", target->name);
		}

		no_buf_space = iscsi_copy_str(data, &total, alloc_len, &previous_completed_size,
					      len + 1, tmp_buf);
		if (no_buf_space) {
			break;
		}

		total = iscsi_send_tgt_portals(conn, target, data, alloc_len, total,
					       &previous_completed_size, &no_buf_space);
		if (no_buf_space) {
			break;
		}
	}
	pthread_mutex_unlock(&g_iscsi.mutex);

	/* Only set it when it is not succesufully completed */
	if (no_buf_space) {
		conn->send_tgt_completed_size += total;
	} else {
		conn->send_tgt_completed_size = 0;
	}

	return total;
}