From c3e890e92bf8b04b2e0d50727f227d5d151ea285 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Wed, 10 Jan 2018 11:17:31 +0900 Subject: [PATCH] iscsi/ut: Test for read task splitting Splitting an iSCSI task into primary and sub tasks is complex operation and a degradation was caused for it. Hence adding test codes is required but there is no UT code for it yet. primary->bytes_completed is for read completion from bdev and it is tested by this patch. Additional test codes will follow: - primary->bytes_completed is tested when read tasks do not complete in order. - primary->task.data_transferred is for write completion to initiator through network. - primary->task.data_transferred is tested by another patch because primary->bytes_completed is used in iscsi/conn.c but primary->task.data_transferred is used in iscsi/iscsi.c. Change-Id: I94b47048111a3d3b249b84d5c54941b0a89ccd40 Signed-off-by: Shuhei Matsumoto Reviewed-on: https://review.gerrithub.io/394143 Tested-by: SPDK Automated Test System Reviewed-by: Jim Harris Reviewed-by: Ben Walker --- test/unit/lib/iscsi/Makefile | 2 +- test/unit/lib/iscsi/conn.c/.gitignore | 1 + test/unit/lib/iscsi/conn.c/Makefile | 56 ++++ test/unit/lib/iscsi/conn.c/conn_ut.c | 367 ++++++++++++++++++++++++++ unittest.sh | 1 + 5 files changed, 426 insertions(+), 1 deletion(-) create mode 100644 test/unit/lib/iscsi/conn.c/.gitignore create mode 100644 test/unit/lib/iscsi/conn.c/Makefile create mode 100644 test/unit/lib/iscsi/conn.c/conn_ut.c diff --git a/test/unit/lib/iscsi/Makefile b/test/unit/lib/iscsi/Makefile index 90d500fc69..99fe1ac3f4 100644 --- a/test/unit/lib/iscsi/Makefile +++ b/test/unit/lib/iscsi/Makefile @@ -34,7 +34,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk -DIRS-y = init_grp.c iscsi.c param.c tgt_node.c +DIRS-y = conn.c init_grp.c iscsi.c param.c tgt_node.c .PHONY: all clean $(DIRS-y) diff --git a/test/unit/lib/iscsi/conn.c/.gitignore b/test/unit/lib/iscsi/conn.c/.gitignore new file mode 100644 index 0000000000..3bb0afd8a3 --- /dev/null +++ b/test/unit/lib/iscsi/conn.c/.gitignore @@ -0,0 +1 @@ +conn_ut diff --git a/test/unit/lib/iscsi/conn.c/Makefile b/test/unit/lib/iscsi/conn.c/Makefile new file mode 100644 index 0000000000..12ab576439 --- /dev/null +++ b/test/unit/lib/iscsi/conn.c/Makefile @@ -0,0 +1,56 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) +include $(SPDK_ROOT_DIR)/mk/spdk.common.mk +include $(SPDK_ROOT_DIR)/mk/spdk.app.mk + +SPDK_LIB_LIST = log cunit trace conf util + +CFLAGS += -I$(SPDK_ROOT_DIR)/test +CFLAGS += -I$(SPDK_ROOT_DIR)/lib +LIBS += $(SPDK_LIB_LINKER_ARGS) +LIBS += -lcunit + +APP = conn_ut +C_SRCS = conn_ut.c + +all: $(APP) + +$(APP): $(OBJS) $(SPDK_LIB_FILES) + $(LINK_C) + +clean: + $(CLEAN_C) $(APP) + +include $(SPDK_ROOT_DIR)/mk/spdk.deps.mk diff --git a/test/unit/lib/iscsi/conn.c/conn_ut.c b/test/unit/lib/iscsi/conn.c/conn_ut.c new file mode 100644 index 0000000000..51703460ce --- /dev/null +++ b/test/unit/lib/iscsi/conn.c/conn_ut.c @@ -0,0 +1,367 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "spdk_cunit.h" +#include "CUnit/Basic.h" + +#include "iscsi/conn.c" +#include "net/net_framework_default.c" + +SPDK_LOG_REGISTER_COMPONENT("iscsi", SPDK_LOG_ISCSI) + +#define DMIN32(A,B) ((uint32_t) ((uint32_t)(A) > (uint32_t)(B) ? (uint32_t)(B) : (uint32_t)(A))) + +struct spdk_iscsi_globals g_spdk_iscsi; +static TAILQ_HEAD(, spdk_iscsi_task) g_ut_read_tasks = TAILQ_HEAD_INITIALIZER(g_ut_read_tasks); + +int +spdk_app_get_shm_id(void) +{ + return 0; +} + +uint32_t +spdk_env_get_current_core(void) +{ + return 0; +} + +uint32_t +spdk_env_get_first_core(void) +{ + return 0; +} + +uint32_t +spdk_env_get_last_core(void) +{ + return 0; +} + +uint32_t +spdk_env_get_next_core(uint32_t prev_core) +{ + return 0; +} + +uint64_t spdk_get_ticks(void) +{ + return 0; +} + +uint64_t spdk_get_ticks_hz(void) +{ + return 0; +} + +struct spdk_event * +spdk_event_allocate(uint32_t lcore, spdk_event_fn fn, void *arg1, void *arg2) +{ + return NULL; +} + +void +spdk_event_call(struct spdk_event *event) +{ +} + +int +spdk_sock_getaddr(int sock, char *saddr, int slen, char *caddr, int clen) +{ + return 0; +} + +int +spdk_sock_close(int sock) +{ + return 0; +} + +ssize_t +spdk_sock_recv(int sock, void *buf, size_t len) +{ + return 0; +} + +ssize_t +spdk_sock_writev(int sock, struct iovec *iov, int iovcnt) +{ + return 0; +} + +int +spdk_sock_set_recvlowat(int s, int nbytes) +{ + return 0; +} + +int +spdk_sock_set_recvbuf(int sock, int sz) +{ + return 0; +} + +int +spdk_sock_set_sendbuf(int sock, int sz) +{ + return 0; +} + +void +spdk_scsi_task_put(struct spdk_scsi_task *task) +{ +} + +void +spdk_scsi_dev_free_io_channels(struct spdk_scsi_dev *dev) +{ +} + +int +spdk_scsi_dev_allocate_io_channels(struct spdk_scsi_dev *dev) +{ + return 0; +} + +const char * +spdk_scsi_port_get_name(const struct spdk_scsi_port *port) +{ + return NULL; +} + +void +spdk_put_pdu(struct spdk_iscsi_pdu *pdu) +{ +} + +void +spdk_iscsi_param_free(struct iscsi_param *params) +{ +} + +int +spdk_iscsi_conn_params_init(struct iscsi_param **params) +{ + return 0; +} + +void spdk_clear_all_transfer_task(struct spdk_iscsi_conn *conn, + struct spdk_scsi_lun *lun) +{ +} + +int +spdk_iscsi_build_iovecs(struct spdk_iscsi_conn *conn, struct iovec *iovec, + struct spdk_iscsi_pdu *pdu) +{ + return 0; +} + +bool spdk_iscsi_is_deferred_free_pdu(struct spdk_iscsi_pdu *pdu) +{ + return false; +} + +void spdk_iscsi_task_response(struct spdk_iscsi_conn *conn, + struct spdk_iscsi_task *task) +{ +} + +void +spdk_iscsi_task_mgmt_response(struct spdk_iscsi_conn *conn, + struct spdk_iscsi_task *task) +{ +} + +int spdk_iscsi_send_nopin(struct spdk_iscsi_conn *conn) +{ + return 0; +} + +int +spdk_iscsi_execute(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) +{ + return 0; +} + +void spdk_del_transfer_task(struct spdk_iscsi_conn *conn, uint32_t task_tag) +{ +} + +int spdk_iscsi_conn_handle_queued_datain_tasks(struct spdk_iscsi_conn *conn) +{ + return 0; +} + +int +spdk_iscsi_read_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu **_pdu) +{ + return 0; +} + +void spdk_free_sess(struct spdk_iscsi_sess *sess) +{ +} + +int +spdk_iscsi_tgt_node_cleanup_luns(struct spdk_iscsi_conn *conn, + struct spdk_iscsi_tgt_node *target) +{ + return 0; +} + +void +spdk_iscsi_fini_done(void) +{ +} + +static struct spdk_iscsi_task * +ut_conn_task_get(struct spdk_iscsi_task *parent) +{ + struct spdk_iscsi_task *task; + + task = calloc(1, sizeof(*task)); + SPDK_CU_ASSERT_FATAL(task != NULL); + + if (parent) { + task->parent = parent; + } + return task; +} + +static void +ut_conn_create_read_tasks(int transfer_len) +{ + struct spdk_iscsi_task *task, *subtask; + int32_t remaining_size = 0; + + task = ut_conn_task_get(NULL); + + task->scsi.transfer_len = transfer_len; + task->scsi.offset = 0; + task->scsi.length = DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE, task->scsi.transfer_len); + task->scsi.status = SPDK_SCSI_STATUS_GOOD; + + remaining_size = task->scsi.transfer_len - task->scsi.length; + task->current_datain_offset = 0; + + if (remaining_size == 0) { + TAILQ_INSERT_TAIL(&g_ut_read_tasks, task, link); + return; + } + + while (1) { + if (task->current_datain_offset == 0) { + task->current_datain_offset = task->scsi.length; + TAILQ_INSERT_TAIL(&g_ut_read_tasks, task, link); + continue; + } + + if (task->current_datain_offset < task->scsi.transfer_len) { + remaining_size = task->scsi.transfer_len - task->current_datain_offset; + + subtask = ut_conn_task_get(task); + + subtask->scsi.offset = task->current_datain_offset; + subtask->scsi.length = DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE, remaining_size); + subtask->scsi.status = SPDK_SCSI_STATUS_GOOD; + + task->current_datain_offset += subtask->scsi.length; + + TAILQ_INSERT_TAIL(&g_ut_read_tasks, subtask, link); + } + + if (task->current_datain_offset == task->scsi.transfer_len) { + break; + } + } +} + +static void +read_task_split_in_order_case(void) +{ + struct spdk_iscsi_task *primary, *task, *tmp; + + ut_conn_create_read_tasks(SPDK_BDEV_LARGE_BUF_MAX_SIZE * 8); + + TAILQ_FOREACH(task, &g_ut_read_tasks, link) { + primary = spdk_iscsi_task_get_primary(task); + process_read_task_completion(NULL, task, primary); + } + + primary = TAILQ_FIRST(&g_ut_read_tasks); + SPDK_CU_ASSERT_FATAL(primary != NULL); + + if (primary != NULL) { + CU_ASSERT(primary->bytes_completed == primary->scsi.transfer_len); + } + + TAILQ_FOREACH_SAFE(task, &g_ut_read_tasks, link, tmp) { + TAILQ_REMOVE(&g_ut_read_tasks, task, link); + free(task); + } + + CU_ASSERT(TAILQ_EMPTY(&g_ut_read_tasks)); +} + +int +main(int argc, char **argv) +{ + CU_pSuite suite = NULL; + unsigned int num_failures; + + if (CU_initialize_registry() != CUE_SUCCESS) { + return CU_get_error(); + } + + suite = CU_add_suite("conn_suite", NULL, NULL); + if (suite == NULL) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if ( + CU_add_test(suite, "read task split in order", read_task_split_in_order_case) == NULL + ) { + CU_cleanup_registry(); + return CU_get_error(); + } + + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_basic_run_tests(); + num_failures = CU_get_number_of_failures(); + CU_cleanup_registry(); + return num_failures; +} diff --git a/unittest.sh b/unittest.sh index 4e7fcd29d8..9b8cead885 100755 --- a/unittest.sh +++ b/unittest.sh @@ -95,6 +95,7 @@ $valgrind test/unit/lib/scsi/scsi_bdev.c/scsi_bdev_ut $valgrind test/unit/lib/lvol/lvol.c/lvol_ut +$valgrind test/unit/lib/iscsi/conn.c/conn_ut $valgrind test/unit/lib/iscsi/param.c/param_ut $valgrind test/unit/lib/iscsi/tgt_node.c/tgt_node_ut test/unit/lib/iscsi/tgt_node.c/tgt_node.conf $valgrind test/unit/lib/iscsi/iscsi.c/iscsi_ut