Commit b689bf62 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Changpeng Liu
Browse files

lib/iscsi: Move spdk_iscsi_read_pdu() down in the file



The subsequent patches will merge spdk_iscsi_read_pdu(),
spdk_iscsi_execute(), and iscsi_conn_handle_incoming_pdus() into
a single function by introducing state machine.

Current ordering will create unnecessary function declaration.
Hence move spdk_iscsi_read_pdu() down to the next to
spdk_iscsi_execute() to avoid it.

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


Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent f6193dd9
Loading
Loading
Loading
Loading
+178 −178
Original line number Diff line number Diff line
@@ -460,184 +460,6 @@ iscsi_conn_read_data_segment(struct spdk_iscsi_conn *conn,
	}
}

int
spdk_iscsi_read_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu **_pdu)
{
	struct spdk_iscsi_pdu *pdu;
	struct spdk_mempool *pool;
	uint32_t crc32c;
	int ahs_len;
	int data_len;
	int rc;

	if (conn->pdu_in_progress == NULL) {
		conn->pdu_in_progress = spdk_get_pdu();
		if (conn->pdu_in_progress == NULL) {
			return SPDK_ISCSI_CONNECTION_FATAL;
		}
	}

	pdu = conn->pdu_in_progress;

	if (pdu->bhs_valid_bytes < ISCSI_BHS_LEN) {
		rc = spdk_iscsi_conn_read_data(conn,
					       ISCSI_BHS_LEN - pdu->bhs_valid_bytes,
					       (uint8_t *)&pdu->bhs + pdu->bhs_valid_bytes);
		if (rc < 0) {
			goto error;
		}
		pdu->bhs_valid_bytes += rc;
		if (pdu->bhs_valid_bytes < ISCSI_BHS_LEN) {
			return 0;
		}
	}

	data_len = ISCSI_ALIGN(DGET24(pdu->bhs.data_segment_len));

	/* AHS */
	ahs_len = pdu->bhs.total_ahs_len * 4;
	assert(ahs_len <= ISCSI_AHS_LEN);
	if (pdu->ahs_valid_bytes < ahs_len) {
		rc = spdk_iscsi_conn_read_data(conn,
					       ahs_len - pdu->ahs_valid_bytes,
					       pdu->ahs + pdu->ahs_valid_bytes);
		if (rc < 0) {
			goto error;
		}

		pdu->ahs_valid_bytes += rc;
		if (pdu->ahs_valid_bytes < ahs_len) {
			return 0;
		}
	}

	/* Header Digest */
	if (conn->header_digest &&
	    pdu->hdigest_valid_bytes < ISCSI_DIGEST_LEN) {
		rc = spdk_iscsi_conn_read_data(conn,
					       ISCSI_DIGEST_LEN - pdu->hdigest_valid_bytes,
					       pdu->header_digest + pdu->hdigest_valid_bytes);
		if (rc < 0) {
			goto error;
		}

		pdu->hdigest_valid_bytes += rc;
		if (pdu->hdigest_valid_bytes < ISCSI_DIGEST_LEN) {
			return 0;
		}
	}

	/* copy the actual data into local buffer */
	if (pdu->data_valid_bytes < data_len) {
		if (pdu->data_buf == NULL) {
			if (data_len <= spdk_get_max_immediate_data_size()) {
				pool = g_spdk_iscsi.pdu_immediate_data_pool;
				pdu->data_buf_len = SPDK_BDEV_BUF_SIZE_WITH_MD(spdk_get_max_immediate_data_size());
			} else if (data_len <= SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH) {
				pool = g_spdk_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);
				rc = SPDK_ISCSI_CONNECTION_FATAL;
				goto error;
			}
			pdu->mobj = spdk_mempool_get(pool);
			if (pdu->mobj == NULL) {
				return 0;
			}
			pdu->data_buf = pdu->mobj->buf;

			if (spdk_unlikely(spdk_iscsi_get_dif_ctx(conn, pdu, &pdu->dif_ctx))) {
				pdu->dif_insert_or_strip = true;
			}
		}

		rc = iscsi_conn_read_data_segment(conn, pdu, data_len);
		if (rc < 0) {
			goto error;
		}

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

	/* copy out the data digest */
	if (conn->data_digest && data_len != 0 &&
	    pdu->ddigest_valid_bytes < ISCSI_DIGEST_LEN) {
		rc = spdk_iscsi_conn_read_data(conn,
					       ISCSI_DIGEST_LEN - pdu->ddigest_valid_bytes,
					       pdu->data_digest + pdu->ddigest_valid_bytes);
		if (rc < 0) {
			goto error;
		}

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

	/* All data for this PDU has now been read from the socket. */
	conn->pdu_in_progress = NULL;

	spdk_trace_record(TRACE_ISCSI_READ_PDU, conn->id, pdu->data_valid_bytes,
			  (uintptr_t)pdu, pdu->bhs.opcode);

	/* Data Segment */
	if (data_len != 0) {
		if (!iscsi_check_data_segment_length(conn, pdu, data_len)) {
			rc = iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR);
			/*
			 * If spdk_iscsi_reject() was not able to reject the PDU,
			 * treat it as a fatal connection error.  Otherwise,
			 * return SUCCESS here so that the caller will continue
			 * to attempt to read PDUs.
			 */
			if (rc == 0) {
				spdk_put_pdu(pdu);
				return 0;
			} else {
				goto error;
			}
		}

		pdu->data = pdu->data_buf;
		pdu->data_from_mempool = true;
		pdu->data_segment_len = data_len;
	}

	/* check digest */
	if (conn->header_digest) {
		crc32c = spdk_iscsi_pdu_calc_header_digest(pdu);
		rc = MATCH_DIGEST_WORD(pdu->header_digest, crc32c);
		if (rc == 0) {
			SPDK_ERRLOG("header digest error (%s)\n", conn->initiator_name);
			rc = SPDK_ISCSI_CONNECTION_FATAL;
			goto error;
		}
	}
	if (conn->data_digest && data_len != 0) {
		crc32c = spdk_iscsi_pdu_calc_data_digest(pdu);
		rc = MATCH_DIGEST_WORD(pdu->data_digest, crc32c);
		if (rc == 0) {
			rc = SPDK_ISCSI_CONNECTION_FATAL;
			SPDK_ERRLOG("data digest error (%s)\n", conn->initiator_name);
			goto error;
		}
	}

	*_pdu = pdu;
	return 1;

error:
	spdk_put_pdu(pdu);
	conn->pdu_in_progress = NULL;
	return rc;
}

struct _iscsi_sgl {
	struct iovec	*iov;
	int		iovcnt;
@@ -4806,6 +4628,184 @@ spdk_iscsi_execute(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
	return 0;
}

int
spdk_iscsi_read_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu **_pdu)
{
	struct spdk_iscsi_pdu *pdu;
	struct spdk_mempool *pool;
	uint32_t crc32c;
	int ahs_len;
	int data_len;
	int rc;

	if (conn->pdu_in_progress == NULL) {
		conn->pdu_in_progress = spdk_get_pdu();
		if (conn->pdu_in_progress == NULL) {
			return SPDK_ISCSI_CONNECTION_FATAL;
		}
	}

	pdu = conn->pdu_in_progress;

	if (pdu->bhs_valid_bytes < ISCSI_BHS_LEN) {
		rc = spdk_iscsi_conn_read_data(conn,
					       ISCSI_BHS_LEN - pdu->bhs_valid_bytes,
					       (uint8_t *)&pdu->bhs + pdu->bhs_valid_bytes);
		if (rc < 0) {
			goto error;
		}
		pdu->bhs_valid_bytes += rc;
		if (pdu->bhs_valid_bytes < ISCSI_BHS_LEN) {
			return 0;
		}
	}

	data_len = ISCSI_ALIGN(DGET24(pdu->bhs.data_segment_len));

	/* AHS */
	ahs_len = pdu->bhs.total_ahs_len * 4;
	assert(ahs_len <= ISCSI_AHS_LEN);
	if (pdu->ahs_valid_bytes < ahs_len) {
		rc = spdk_iscsi_conn_read_data(conn,
					       ahs_len - pdu->ahs_valid_bytes,
					       pdu->ahs + pdu->ahs_valid_bytes);
		if (rc < 0) {
			goto error;
		}

		pdu->ahs_valid_bytes += rc;
		if (pdu->ahs_valid_bytes < ahs_len) {
			return 0;
		}
	}

	/* Header Digest */
	if (conn->header_digest &&
	    pdu->hdigest_valid_bytes < ISCSI_DIGEST_LEN) {
		rc = spdk_iscsi_conn_read_data(conn,
					       ISCSI_DIGEST_LEN - pdu->hdigest_valid_bytes,
					       pdu->header_digest + pdu->hdigest_valid_bytes);
		if (rc < 0) {
			goto error;
		}

		pdu->hdigest_valid_bytes += rc;
		if (pdu->hdigest_valid_bytes < ISCSI_DIGEST_LEN) {
			return 0;
		}
	}

	/* copy the actual data into local buffer */
	if (pdu->data_valid_bytes < data_len) {
		if (pdu->data_buf == NULL) {
			if (data_len <= spdk_get_max_immediate_data_size()) {
				pool = g_spdk_iscsi.pdu_immediate_data_pool;
				pdu->data_buf_len = SPDK_BDEV_BUF_SIZE_WITH_MD(spdk_get_max_immediate_data_size());
			} else if (data_len <= SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH) {
				pool = g_spdk_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);
				rc = SPDK_ISCSI_CONNECTION_FATAL;
				goto error;
			}
			pdu->mobj = spdk_mempool_get(pool);
			if (pdu->mobj == NULL) {
				return 0;
			}
			pdu->data_buf = pdu->mobj->buf;

			if (spdk_unlikely(spdk_iscsi_get_dif_ctx(conn, pdu, &pdu->dif_ctx))) {
				pdu->dif_insert_or_strip = true;
			}
		}

		rc = iscsi_conn_read_data_segment(conn, pdu, data_len);
		if (rc < 0) {
			goto error;
		}

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

	/* copy out the data digest */
	if (conn->data_digest && data_len != 0 &&
	    pdu->ddigest_valid_bytes < ISCSI_DIGEST_LEN) {
		rc = spdk_iscsi_conn_read_data(conn,
					       ISCSI_DIGEST_LEN - pdu->ddigest_valid_bytes,
					       pdu->data_digest + pdu->ddigest_valid_bytes);
		if (rc < 0) {
			goto error;
		}

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

	/* All data for this PDU has now been read from the socket. */
	conn->pdu_in_progress = NULL;

	spdk_trace_record(TRACE_ISCSI_READ_PDU, conn->id, pdu->data_valid_bytes,
			  (uintptr_t)pdu, pdu->bhs.opcode);

	/* Data Segment */
	if (data_len != 0) {
		if (!iscsi_check_data_segment_length(conn, pdu, data_len)) {
			rc = iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR);
			/*
			 * If spdk_iscsi_reject() was not able to reject the PDU,
			 * treat it as a fatal connection error.  Otherwise,
			 * return SUCCESS here so that the caller will continue
			 * to attempt to read PDUs.
			 */
			if (rc == 0) {
				spdk_put_pdu(pdu);
				return 0;
			} else {
				goto error;
			}
		}

		pdu->data = pdu->data_buf;
		pdu->data_from_mempool = true;
		pdu->data_segment_len = data_len;
	}

	/* check digest */
	if (conn->header_digest) {
		crc32c = spdk_iscsi_pdu_calc_header_digest(pdu);
		rc = MATCH_DIGEST_WORD(pdu->header_digest, crc32c);
		if (rc == 0) {
			SPDK_ERRLOG("header digest error (%s)\n", conn->initiator_name);
			rc = SPDK_ISCSI_CONNECTION_FATAL;
			goto error;
		}
	}
	if (conn->data_digest && data_len != 0) {
		crc32c = spdk_iscsi_pdu_calc_data_digest(pdu);
		rc = MATCH_DIGEST_WORD(pdu->data_digest, crc32c);
		if (rc == 0) {
			rc = SPDK_ISCSI_CONNECTION_FATAL;
			SPDK_ERRLOG("data digest error (%s)\n", conn->initiator_name);
			goto error;
		}
	}

	*_pdu = pdu;
	return 1;

error:
	spdk_put_pdu(pdu);
	conn->pdu_in_progress = NULL;
	return rc;
}

bool
spdk_iscsi_get_dif_ctx(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu,
		       struct spdk_dif_ctx *dif_ctx)