Commit 0b576bb7 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Tomasz Zawadzki
Browse files

lib/iscsi: Factor out reading PDU payload operation from iscsi_read_pdu()



This patch follows the last cleanup.

Factor out reading PDU payload operation from iscsi_read_pdu() into a
helper function iscsi_pdu_payload_read(). This reduces the nesting
level, improves the readability, and make the following patches easier.

Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: Ie5f51eedefe00f3b43a7b45dcf84be79f8df4e27
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6414


Reviewed-by: default avatarZiye Yang <ziye.yang@intel.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>
Community-CI: Mellanox Build Bot
parent 36b9a670
Loading
Loading
Loading
Loading
+87 −70
Original line number Diff line number Diff line
@@ -4555,15 +4555,93 @@ iscsi_pdu_payload_handle(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pd
	return rc;
}

/* Return zero if completed to read payload, positive number if still in progress,
 * or negative number if any error.
 */
static int
iscsi_pdu_payload_read(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
{
	struct spdk_mempool *pool;
	uint32_t data_len;
	uint32_t crc32c;
	int rc;

	data_len = pdu->data_segment_len;

	if (pdu->data_buf == NULL) {
		if (data_len <= iscsi_get_max_immediate_data_size()) {
			pool = g_iscsi.pdu_immediate_data_pool;
			pdu->data_buf_len = SPDK_BDEV_BUF_SIZE_WITH_MD(iscsi_get_max_immediate_data_size());
		} else if (data_len <= SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH) {
			pool = g_iscsi.pdu_data_out_pool;
			pdu->data_buf_len = SPDK_BDEV_BUF_SIZE_WITH_MD(SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
		} else {
			SPDK_ERRLOG("Data(%d) > MaxSegment(%d)\n",
				    data_len, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
			return -1;
		}
		pdu->mobj = spdk_mempool_get(pool);
		if (pdu->mobj == NULL) {
			return 1;
		}
		pdu->data_buf = pdu->mobj->buf;
		pdu->data = pdu->mobj->buf;
		pdu->data_from_mempool = true;
	}

	/* copy the actual data into local buffer */
	if ((pdu->data_valid_bytes < data_len)) {
		rc = iscsi_conn_read_data_segment(conn, pdu, data_len);
		if (rc < 0) {
			return rc;
		}

		pdu->data_valid_bytes += rc;
		if (pdu->data_valid_bytes < data_len) {
			return 1;
		}
	}

	/* copy out the data digest */
	if (conn->data_digest &&
	    pdu->ddigest_valid_bytes < ISCSI_DIGEST_LEN) {
		rc = iscsi_conn_read_data(conn,
					  ISCSI_DIGEST_LEN - pdu->ddigest_valid_bytes,
					  pdu->data_digest + pdu->ddigest_valid_bytes);
		if (rc < 0) {
			return rc;
		}

		pdu->ddigest_valid_bytes += rc;
		if (pdu->ddigest_valid_bytes < ISCSI_DIGEST_LEN) {
			return 1;
		}
	}

	/* All data for this PDU has now been read from the socket. */
	spdk_trace_record(TRACE_ISCSI_READ_PDU, conn->id, pdu->data_valid_bytes,
			  (uintptr_t)pdu, pdu->bhs.opcode);

	/* check data digest */
	if (conn->data_digest) {
		crc32c = iscsi_pdu_calc_data_digest(pdu);
		rc = MATCH_DIGEST_WORD(pdu->data_digest, crc32c);
		if (rc == 0) {
			SPDK_ERRLOG("data digest error (%s)\n", conn->initiator_name);
			return -1;
		}
	}

	return 0;
}

static int
iscsi_read_pdu(struct spdk_iscsi_conn *conn)
{
	enum iscsi_pdu_recv_state prev_state;
	struct spdk_iscsi_pdu *pdu;
	struct spdk_mempool *pool;
	uint32_t crc32c;
	int ahs_len;
	uint32_t data_len;
	int rc;

	do {
@@ -4668,76 +4746,15 @@ iscsi_read_pdu(struct spdk_iscsi_conn *conn)
			conn->pdu_recv_state = ISCSI_PDU_RECV_STATE_AWAIT_PDU_PAYLOAD;
			break;
		case ISCSI_PDU_RECV_STATE_AWAIT_PDU_PAYLOAD:
			data_len = pdu->data_segment_len;
			if (data_len != 0) {
				if (pdu->data_buf == NULL) {
					if (data_len <= iscsi_get_max_immediate_data_size()) {
						pool = g_iscsi.pdu_immediate_data_pool;
						pdu->data_buf_len = SPDK_BDEV_BUF_SIZE_WITH_MD(iscsi_get_max_immediate_data_size());
					} else if (data_len <= SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH) {
						pool = g_iscsi.pdu_data_out_pool;
						pdu->data_buf_len = SPDK_BDEV_BUF_SIZE_WITH_MD(SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
					} else {
						SPDK_ERRLOG("Data(%d) > MaxSegment(%d)\n",
							    data_len, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
						conn->pdu_recv_state = ISCSI_PDU_RECV_STATE_ERROR;
						break;
					}
					pdu->mobj = spdk_mempool_get(pool);
					if (pdu->mobj == NULL) {
						return 0;
					}
					pdu->data_buf = pdu->mobj->buf;
					pdu->data = pdu->mobj->buf;
					pdu->data_from_mempool = true;
				}

				/* copy the actual data into local buffer */
				if ((pdu->data_valid_bytes < data_len)) {
					rc = iscsi_conn_read_data_segment(conn, pdu, data_len);
					if (rc < 0) {
						conn->pdu_recv_state = ISCSI_PDU_RECV_STATE_ERROR;
						break;
					}

					pdu->data_valid_bytes += rc;
					if (pdu->data_valid_bytes < data_len) {
						return 0;
					}
				}

				/* copy out the data digest */
				if (conn->data_digest &&
				    pdu->ddigest_valid_bytes < ISCSI_DIGEST_LEN) {
					rc = iscsi_conn_read_data(conn,
								  ISCSI_DIGEST_LEN - pdu->ddigest_valid_bytes,
								  pdu->data_digest + pdu->ddigest_valid_bytes);
					if (rc < 0) {
						conn->pdu_recv_state = ISCSI_PDU_RECV_STATE_ERROR;
						break;
					}

					pdu->ddigest_valid_bytes += rc;
					if (pdu->ddigest_valid_bytes < ISCSI_DIGEST_LEN) {
			if (pdu->data_segment_len != 0) {
				rc = iscsi_pdu_payload_read(conn, pdu);
				if (rc > 0) {
					return 0;
					}
				}

				/* All data for this PDU has now been read from the socket. */
				spdk_trace_record(TRACE_ISCSI_READ_PDU, conn->id, pdu->data_valid_bytes,
						  (uintptr_t)pdu, pdu->bhs.opcode);

				/* check data digest */
				if (conn->data_digest) {
					crc32c = iscsi_pdu_calc_data_digest(pdu);
					rc = MATCH_DIGEST_WORD(pdu->data_digest, crc32c);
					if (rc == 0) {
						SPDK_ERRLOG("data digest error (%s)\n", conn->initiator_name);
				} else if (rc < 0) {
					conn->pdu_recv_state = ISCSI_PDU_RECV_STATE_ERROR;
					break;
				}
			}
			}

			if (!pdu->is_rejected) {
				rc = iscsi_pdu_payload_handle(conn, pdu);