ut/iscsi: Add test cases for the function iscsi_pdu_payload_read()
Test sharing data buffer among multiple Data-OUT PDUs. Allocate real data buffers and the iscsi_conn_read_data() stub writes data patterns into them. The data pattern is to write offset per 4 bytes. This requires read length to 4 bytes multiples but the requirement will be acceptable. Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Change-Id: I87c673c3bb0ada2afebb9332af9525cd9d7388f2 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6568 Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Mellanox Build Bot
This commit is contained in:
parent
ce43ae2123
commit
4af8b24ace
@ -27,6 +27,7 @@ TAILQ_HEAD(, spdk_iscsi_pdu) g_write_pdu_list = TAILQ_HEAD_INITIALIZER(g_write_p
|
||||
|
||||
static bool g_task_pool_is_empty = false;
|
||||
static bool g_pdu_pool_is_empty = false;
|
||||
static uint32_t g_conn_read_len;
|
||||
|
||||
struct spdk_iscsi_task *
|
||||
iscsi_task_get(struct spdk_iscsi_conn *conn,
|
||||
@ -182,11 +183,35 @@ iscsi_task_cpl(struct spdk_scsi_task *scsi_task)
|
||||
|
||||
DEFINE_STUB_V(iscsi_task_mgmt_cpl, (struct spdk_scsi_task *scsi_task));
|
||||
|
||||
DEFINE_STUB(iscsi_conn_read_data, int,
|
||||
(struct spdk_iscsi_conn *conn, int bytes, void *buf), 0);
|
||||
int
|
||||
iscsi_conn_read_data(struct spdk_iscsi_conn *conn, int bytes, void *buf)
|
||||
{
|
||||
uint32_t *data = buf;
|
||||
int i;
|
||||
|
||||
DEFINE_STUB(iscsi_conn_readv_data, int,
|
||||
(struct spdk_iscsi_conn *conn, struct iovec *iov, int iovcnt), 0);
|
||||
/* Limit the length to 4 bytes multiples. */
|
||||
SPDK_CU_ASSERT_FATAL((bytes % 4) == 0);
|
||||
|
||||
for (i = 0; i < bytes; i += 4) {
|
||||
data[i / 4] = g_conn_read_len + i;
|
||||
}
|
||||
|
||||
g_conn_read_len += bytes;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int
|
||||
iscsi_conn_readv_data(struct spdk_iscsi_conn *conn, struct iovec *iov, int iovcnt)
|
||||
{
|
||||
int i, len = 0;
|
||||
|
||||
for (i = 0; i < iovcnt; i++) {
|
||||
len += iov[i].iov_len;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void
|
||||
iscsi_conn_write_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu,
|
||||
|
@ -2021,6 +2021,109 @@ empty_text_with_cbit_test(void)
|
||||
iscsi_put_pdu(req_pdu);
|
||||
}
|
||||
|
||||
static void
|
||||
check_pdu_payload_read(struct spdk_iscsi_pdu *pdu, struct spdk_mobj *mobj,
|
||||
int rc, int index, uint32_t read_offset)
|
||||
{
|
||||
uint64_t buf_offset;
|
||||
uint32_t *data;
|
||||
uint32_t i;
|
||||
|
||||
data = (uint32_t *)pdu->data;
|
||||
buf_offset = (uint64_t)pdu->data - (uint64_t)mobj->buf;
|
||||
|
||||
CU_ASSERT(pdu->mobj[index] == mobj);
|
||||
CU_ASSERT(pdu->data_from_mempool == true);
|
||||
CU_ASSERT(buf_offset == 0 || pdu->data_offset == 0);
|
||||
CU_ASSERT(mobj->data_len + pdu->data_offset == buf_offset + pdu->data_valid_bytes);
|
||||
CU_ASSERT(rc > 0 || pdu->data_valid_bytes == pdu->data_segment_len);
|
||||
|
||||
for (i = 0; i < pdu->data_valid_bytes - pdu->data_offset; i += 4) {
|
||||
CU_ASSERT(data[i / 4] == (uint32_t)(read_offset + i));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pdu_payload_read_test(void)
|
||||
{
|
||||
struct spdk_iscsi_conn conn = {};
|
||||
struct spdk_iscsi_pdu pdu = {};
|
||||
struct spdk_mobj mobj1 = {}, mobj2 = {};
|
||||
int rc;
|
||||
|
||||
g_iscsi.FirstBurstLength = SPDK_ISCSI_FIRST_BURST_LENGTH;
|
||||
|
||||
mobj1.buf = calloc(1, SPDK_BDEV_BUF_SIZE_WITH_MD(SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH));
|
||||
SPDK_CU_ASSERT_FATAL(mobj1.buf != NULL);
|
||||
|
||||
mobj2.buf = calloc(1, SPDK_BDEV_BUF_SIZE_WITH_MD(SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH));
|
||||
SPDK_CU_ASSERT_FATAL(mobj2.buf != NULL);
|
||||
|
||||
MOCK_SET(spdk_mempool_get, &mobj1);
|
||||
|
||||
/* The following tests assume that a iscsi_conn_read_data() call could read
|
||||
* the required length of the data and all read lengths are 4 bytes multiples.
|
||||
* The latter is to verify data is copied to the correct offset by using data patterns.
|
||||
*/
|
||||
|
||||
/* Case 1: data segment size is equal with max immediate data size. */
|
||||
pdu.data_segment_len = iscsi_get_max_immediate_data_size();
|
||||
pdu.data_buf_len = pdu.data_segment_len;
|
||||
g_conn_read_len = 0;
|
||||
|
||||
rc = iscsi_pdu_payload_read(&conn, &pdu);
|
||||
check_pdu_payload_read(&pdu, &mobj1, rc, 0, 0);
|
||||
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
mobj1.data_len = 0;
|
||||
|
||||
/* Case 2: data segment size is equal with SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH. */
|
||||
pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||
pdu.data_buf_len = pdu.data_segment_len;
|
||||
g_conn_read_len = 0;
|
||||
|
||||
rc = iscsi_pdu_payload_read(&conn, &pdu);
|
||||
check_pdu_payload_read(&pdu, &mobj1, rc, 0, 0);
|
||||
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
mobj1.data_len = 0;
|
||||
|
||||
/* Case 3: data segment size is larger than SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH.
|
||||
* This should result in error.
|
||||
*/
|
||||
pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH + 1;
|
||||
pdu.data_buf_len = pdu.data_segment_len;
|
||||
g_conn_read_len = 0;
|
||||
|
||||
rc = iscsi_pdu_payload_read(&conn, &pdu);
|
||||
CU_ASSERT(rc < 0);
|
||||
|
||||
/* Case 4: read starts from the middle of the 1st data buffer, the 1st data buffer
|
||||
* ran out, allocate the 2nd data buffer, and read the remaining data to the 2nd
|
||||
* data buffer.
|
||||
*/
|
||||
mobj1.data_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2;
|
||||
pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||
pdu.data_buf_len = SPDK_BDEV_BUF_SIZE_WITH_MD(SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
|
||||
pdu.mobj[0] = &mobj1;
|
||||
pdu.data = (void *)((uint64_t)mobj1.buf + SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2);
|
||||
pdu.data_from_mempool = true;
|
||||
g_conn_read_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2;
|
||||
|
||||
rc = iscsi_pdu_payload_read(&conn, &pdu);
|
||||
check_pdu_payload_read(&pdu, &mobj1, rc, 0, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2);
|
||||
|
||||
MOCK_SET(spdk_mempool_get, &mobj2);
|
||||
|
||||
rc = iscsi_pdu_payload_read(&conn, &pdu);
|
||||
check_pdu_payload_read(&pdu, &mobj2, rc, 1, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
|
||||
|
||||
MOCK_CLEAR(spdk_mempool_get);
|
||||
|
||||
free(mobj1.buf);
|
||||
free(mobj2.buf);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -2053,6 +2156,7 @@ main(int argc, char **argv)
|
||||
CU_ADD_TEST(suite, pdu_hdr_op_nopout_test);
|
||||
CU_ADD_TEST(suite, pdu_hdr_op_data_test);
|
||||
CU_ADD_TEST(suite, empty_text_with_cbit_test);
|
||||
CU_ADD_TEST(suite, pdu_payload_read_test);
|
||||
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
CU_basic_run_tests();
|
||||
|
Loading…
x
Reference in New Issue
Block a user