iscsi: Unify build and fast-forward iovecs to flush PDUs
Building iovecs had been done in spdk_iscsi_build_iovs() and fast-forwarding iovecs for the partially written first PDU had been done in-line separately. This patch unifies these two operations into spdk_iscsi_build_iovs(). Fast-forwarding iovecs is necessary only for the first PDU, but the operation is applied to all PDUs after this patch. Extra overhead will be negligible because usually at most two iovecs are consumed, one is for the base header segment and another is for the data segment. Change-Id: I8feafac6d280439eb7cf73136107adbac820ae09 Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/446174 Reviewed-by: Ziye Yang <ziye.yang@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
42596fb6b1
commit
879386d759
@ -1166,7 +1166,11 @@ spdk_iscsi_conn_flush_pdus_internal(struct spdk_iscsi_conn *conn)
|
||||
|
||||
/*
|
||||
* Build up a list of iovecs for the first few PDUs in the
|
||||
* connection's write_pdu_list.
|
||||
* connection's write_pdu_list. For the first PDU, check if it was
|
||||
* partially written out the last time this function was called, and
|
||||
* if so adjust the iovec array accordingly. This check is done in
|
||||
* spdk_iscsi_build_iovs() and so applied to remaining PDUs too.
|
||||
* But extra overhead is negligible.
|
||||
*/
|
||||
while (pdu != NULL && ((num_iovs - iovcnt) >= 5)) {
|
||||
pdu_length = spdk_iscsi_get_pdu_length(pdu,
|
||||
@ -1177,24 +1181,8 @@ spdk_iscsi_conn_flush_pdus_internal(struct spdk_iscsi_conn *conn)
|
||||
pdu = TAILQ_NEXT(pdu, tailq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the first PDU was partially written out the last time
|
||||
* this function was called, and if so adjust the iovec array
|
||||
* accordingly.
|
||||
*/
|
||||
writev_offset = TAILQ_FIRST(&conn->write_pdu_list)->writev_offset;
|
||||
total_length -= writev_offset;
|
||||
while (writev_offset > 0) {
|
||||
if (writev_offset >= iov->iov_len) {
|
||||
writev_offset -= iov->iov_len;
|
||||
iov++;
|
||||
iovcnt--;
|
||||
} else {
|
||||
iov->iov_len -= writev_offset;
|
||||
iov->iov_base = (char *)iov->iov_base + writev_offset;
|
||||
writev_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
spdk_trace_record(TRACE_ISCSI_FLUSH_WRITEBUF_START, conn->id, total_length, 0, iovcnt);
|
||||
|
||||
|
@ -569,11 +569,13 @@ spdk_iscsi_build_iovs(struct spdk_iscsi_conn *conn, struct iovec *iovs,
|
||||
{
|
||||
int iovcnt = 0;
|
||||
int enable_digest;
|
||||
int total_ahs_len;
|
||||
int data_len;
|
||||
uint32_t total_ahs_len;
|
||||
uint32_t data_len;
|
||||
uint32_t iov_offset;
|
||||
|
||||
total_ahs_len = pdu->bhs.total_ahs_len;
|
||||
data_len = DGET24(pdu->bhs.data_segment_len);
|
||||
data_len = ISCSI_ALIGN(data_len);
|
||||
|
||||
enable_digest = 1;
|
||||
if (pdu->bhs.opcode == ISCSI_OP_LOGIN_RSP) {
|
||||
@ -581,38 +583,61 @@ spdk_iscsi_build_iovs(struct spdk_iscsi_conn *conn, struct iovec *iovs,
|
||||
enable_digest = 0;
|
||||
}
|
||||
|
||||
/* BHS */
|
||||
iovs[iovcnt].iov_base = &pdu->bhs;
|
||||
iovs[iovcnt].iov_len = ISCSI_BHS_LEN;
|
||||
iovcnt++;
|
||||
iov_offset = pdu->writev_offset;
|
||||
|
||||
/* BHS */
|
||||
if (iov_offset >= ISCSI_BHS_LEN) {
|
||||
iov_offset -= ISCSI_BHS_LEN;
|
||||
} else {
|
||||
iovs[iovcnt].iov_base = (uint8_t *)&pdu->bhs + iov_offset;
|
||||
iovs[iovcnt].iov_len = ISCSI_BHS_LEN - iov_offset;
|
||||
iov_offset = 0;
|
||||
iovcnt++;
|
||||
}
|
||||
/* AHS */
|
||||
if (total_ahs_len > 0) {
|
||||
iovs[iovcnt].iov_base = pdu->ahs;
|
||||
iovs[iovcnt].iov_len = 4 * total_ahs_len;
|
||||
if (iov_offset >= 4 * total_ahs_len) {
|
||||
iov_offset -= 4 * total_ahs_len;
|
||||
} else {
|
||||
iovs[iovcnt].iov_base = pdu->ahs + iov_offset;
|
||||
iovs[iovcnt].iov_len = 4 * total_ahs_len - iov_offset;
|
||||
iov_offset = 0;
|
||||
iovcnt++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Header Digest */
|
||||
if (enable_digest && conn->header_digest) {
|
||||
iovs[iovcnt].iov_base = pdu->header_digest;
|
||||
iovs[iovcnt].iov_len = ISCSI_DIGEST_LEN;
|
||||
if (iov_offset >= ISCSI_DIGEST_LEN) {
|
||||
iov_offset -= ISCSI_DIGEST_LEN;
|
||||
} else {
|
||||
iovs[iovcnt].iov_base = pdu->header_digest + iov_offset;
|
||||
iovs[iovcnt].iov_len = ISCSI_DIGEST_LEN - iov_offset;
|
||||
iov_offset = 0;
|
||||
iovcnt++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Data Segment */
|
||||
if (data_len > 0) {
|
||||
iovs[iovcnt].iov_base = pdu->data;
|
||||
iovs[iovcnt].iov_len = ISCSI_ALIGN(data_len);
|
||||
if (iov_offset >= data_len) {
|
||||
iov_offset -= data_len;
|
||||
} else {
|
||||
iovs[iovcnt].iov_base = pdu->data + iov_offset;
|
||||
iovs[iovcnt].iov_len = data_len - iov_offset;
|
||||
iov_offset = 0;
|
||||
iovcnt++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Data Digest */
|
||||
if (enable_digest && conn->data_digest && data_len != 0) {
|
||||
iovs[iovcnt].iov_base = pdu->data_digest;
|
||||
iovs[iovcnt].iov_len = ISCSI_DIGEST_LEN;
|
||||
if (iov_offset < ISCSI_DIGEST_LEN) {
|
||||
iovs[iovcnt].iov_base = pdu->data_digest + iov_offset;
|
||||
iovs[iovcnt].iov_len = ISCSI_DIGEST_LEN - iov_offset;
|
||||
iovcnt++;
|
||||
}
|
||||
}
|
||||
|
||||
return iovcnt;
|
||||
}
|
||||
|
@ -1202,6 +1202,97 @@ abort_queued_datain_tasks_test(void)
|
||||
spdk_put_pdu(pdu1);
|
||||
}
|
||||
|
||||
static void
|
||||
build_iovs_test(void)
|
||||
{
|
||||
struct spdk_iscsi_conn conn = {};
|
||||
struct spdk_iscsi_pdu pdu = {};
|
||||
struct iovec iovs[5] = {};
|
||||
uint8_t *data;
|
||||
int rc;
|
||||
|
||||
conn.header_digest = true;
|
||||
conn.data_digest = true;
|
||||
|
||||
DSET24(&pdu.bhs.data_segment_len, 512);
|
||||
data = calloc(1, 512);
|
||||
SPDK_CU_ASSERT_FATAL(data != NULL);
|
||||
pdu.data = data;
|
||||
|
||||
pdu.bhs.total_ahs_len = 0;
|
||||
pdu.bhs.opcode = ISCSI_OP_SCSI;
|
||||
|
||||
pdu.writev_offset = 0;
|
||||
rc = spdk_iscsi_build_iovs(&conn, iovs, &pdu);
|
||||
CU_ASSERT(rc == 4);
|
||||
CU_ASSERT(iovs[0].iov_base == (void *)&pdu.bhs);
|
||||
CU_ASSERT(iovs[0].iov_len == ISCSI_BHS_LEN);
|
||||
CU_ASSERT(iovs[1].iov_base == (void *)pdu.header_digest);
|
||||
CU_ASSERT(iovs[1].iov_len == ISCSI_DIGEST_LEN);
|
||||
CU_ASSERT(iovs[2].iov_base == (void *)pdu.data);
|
||||
CU_ASSERT(iovs[2].iov_len == 512);
|
||||
CU_ASSERT(iovs[3].iov_base == (void *)pdu.data_digest);
|
||||
CU_ASSERT(iovs[3].iov_len == ISCSI_DIGEST_LEN);
|
||||
|
||||
pdu.writev_offset = ISCSI_BHS_LEN / 2;
|
||||
rc = spdk_iscsi_build_iovs(&conn, iovs, &pdu);
|
||||
CU_ASSERT(rc == 4);
|
||||
CU_ASSERT(iovs[0].iov_base == (void *)((uint8_t *)&pdu.bhs + ISCSI_BHS_LEN / 2));
|
||||
CU_ASSERT(iovs[0].iov_len == ISCSI_BHS_LEN / 2);
|
||||
CU_ASSERT(iovs[1].iov_base == (void *)pdu.header_digest);
|
||||
CU_ASSERT(iovs[1].iov_len == ISCSI_DIGEST_LEN);
|
||||
CU_ASSERT(iovs[2].iov_base == (void *)pdu.data);
|
||||
CU_ASSERT(iovs[2].iov_len == 512);
|
||||
CU_ASSERT(iovs[3].iov_base == (void *)pdu.data_digest);
|
||||
CU_ASSERT(iovs[3].iov_len == ISCSI_DIGEST_LEN);
|
||||
|
||||
pdu.writev_offset = ISCSI_BHS_LEN;
|
||||
rc = spdk_iscsi_build_iovs(&conn, iovs, &pdu);
|
||||
CU_ASSERT(rc == 3);
|
||||
CU_ASSERT(iovs[0].iov_base == (void *)pdu.header_digest);
|
||||
CU_ASSERT(iovs[0].iov_len == ISCSI_DIGEST_LEN);
|
||||
CU_ASSERT(iovs[1].iov_base == (void *)pdu.data);
|
||||
CU_ASSERT(iovs[1].iov_len == 512);
|
||||
CU_ASSERT(iovs[2].iov_base == (void *)pdu.data_digest);
|
||||
CU_ASSERT(iovs[2].iov_len == ISCSI_DIGEST_LEN);
|
||||
|
||||
pdu.writev_offset = ISCSI_BHS_LEN + ISCSI_DIGEST_LEN / 2;
|
||||
rc = spdk_iscsi_build_iovs(&conn, iovs, &pdu);
|
||||
CU_ASSERT(rc == 3);
|
||||
CU_ASSERT(iovs[0].iov_base == (void *)((uint8_t *)pdu.header_digest + ISCSI_DIGEST_LEN / 2));
|
||||
CU_ASSERT(iovs[0].iov_len == ISCSI_DIGEST_LEN / 2);
|
||||
CU_ASSERT(iovs[1].iov_base == (void *)pdu.data);
|
||||
CU_ASSERT(iovs[1].iov_len == 512);
|
||||
CU_ASSERT(iovs[2].iov_base == (void *)pdu.data_digest);
|
||||
CU_ASSERT(iovs[2].iov_len == ISCSI_DIGEST_LEN);
|
||||
|
||||
pdu.writev_offset = ISCSI_BHS_LEN + ISCSI_DIGEST_LEN;
|
||||
rc = spdk_iscsi_build_iovs(&conn, iovs, &pdu);
|
||||
CU_ASSERT(rc == 2);
|
||||
CU_ASSERT(iovs[0].iov_base == (void *)pdu.data);
|
||||
CU_ASSERT(iovs[0].iov_len == 512);
|
||||
CU_ASSERT(iovs[1].iov_base == (void *)pdu.data_digest);
|
||||
CU_ASSERT(iovs[1].iov_len == ISCSI_DIGEST_LEN);
|
||||
|
||||
pdu.writev_offset = ISCSI_BHS_LEN + ISCSI_DIGEST_LEN + 512;
|
||||
rc = spdk_iscsi_build_iovs(&conn, iovs, &pdu);
|
||||
CU_ASSERT(rc == 1);
|
||||
CU_ASSERT(iovs[0].iov_base == (void *)pdu.data_digest);
|
||||
CU_ASSERT(iovs[0].iov_len == ISCSI_DIGEST_LEN);
|
||||
|
||||
pdu.writev_offset = ISCSI_BHS_LEN + ISCSI_DIGEST_LEN + 512 + ISCSI_DIGEST_LEN / 2;
|
||||
rc = spdk_iscsi_build_iovs(&conn, iovs, &pdu);
|
||||
CU_ASSERT(rc == 1);
|
||||
CU_ASSERT(iovs[0].iov_base == (void *)((uint8_t *)pdu.data_digest + ISCSI_DIGEST_LEN / 2));
|
||||
CU_ASSERT(iovs[0].iov_len == ISCSI_DIGEST_LEN / 2);
|
||||
|
||||
pdu.writev_offset = ISCSI_BHS_LEN + ISCSI_DIGEST_LEN + 512 + ISCSI_DIGEST_LEN;
|
||||
rc = spdk_iscsi_build_iovs(&conn, iovs, &pdu);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -1238,6 +1329,7 @@ main(int argc, char **argv)
|
||||
abort_queued_datain_task_test) == NULL
|
||||
|| CU_add_test(suite, "abort_queued_datain_tasks_test",
|
||||
abort_queued_datain_tasks_test) == NULL
|
||||
|| CU_add_test(suite, "build_iovs_test", build_iovs_test) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
|
Loading…
Reference in New Issue
Block a user