LCOV - code coverage report
Current view: top level - spdk/test/unit/lib/iscsi/conn.c - conn_ut.c (source / functions) Hit Total Coverage
Test: Combined Lines: 524 569 92.1 %
Date: 2024-07-15 13:26:16 Functions: 24 86 27.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 40 110 36.4 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2018 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  *   Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
       5                 :            :  */
       6                 :            : 
       7                 :            : #include "spdk/stdinc.h"
       8                 :            : 
       9                 :            : #include "common/lib/test_env.c"
      10                 :            : #include "spdk_internal/cunit.h"
      11                 :            : 
      12                 :            : #include "iscsi/conn.c"
      13                 :            : 
      14                 :            : #include "spdk_internal/mock.h"
      15                 :            : 
      16                 :            : #include "unit/lib/json_mock.c"
      17                 :            : 
      18                 :          4 : SPDK_LOG_REGISTER_COMPONENT(iscsi)
      19                 :            : 
      20         [ #  # ]:          0 : DEFINE_STUB(iscsi_get_pdu, struct spdk_iscsi_pdu *,
      21                 :            :             (struct spdk_iscsi_conn *conn), NULL);
      22         [ #  # ]:          0 : DEFINE_STUB(iscsi_param_eq_val, int,
      23                 :            :             (struct iscsi_param *params, const char *key, const char *val), 0);
      24         [ #  # ]:          0 : DEFINE_STUB(iscsi_pdu_calc_data_digest, uint32_t, (struct spdk_iscsi_pdu *pdu), 0);
      25                 :          0 : DEFINE_STUB_V(spdk_sock_writev_async,
      26                 :            :               (struct spdk_sock *sock, struct spdk_sock_request *req));
      27                 :            : 
      28                 :            : struct spdk_scsi_lun {
      29                 :            :         uint8_t reserved;
      30                 :            : };
      31                 :            : 
      32                 :            : struct spdk_iscsi_globals g_iscsi = {
      33                 :            :         .MaxLargeDataInPerConnection = DEFAULT_MAX_LARGE_DATAIN_PER_CONNECTION,
      34                 :            : };
      35                 :            : 
      36                 :            : static TAILQ_HEAD(read_tasks_head, spdk_iscsi_task) g_ut_read_tasks =
      37                 :            :         TAILQ_HEAD_INITIALIZER(g_ut_read_tasks);
      38                 :            : static struct spdk_iscsi_task *g_new_task = NULL;
      39                 :            : static ssize_t g_sock_writev_bytes = 0;
      40                 :            : 
      41         [ #  # ]:          0 : DEFINE_STUB(spdk_app_get_shm_id, int, (void), 0);
      42                 :            : 
      43         [ #  # ]:          0 : DEFINE_STUB(spdk_sock_getaddr, int,
      44                 :            :             (struct spdk_sock *sock, char *saddr, int slen, uint16_t *sport,
      45                 :            :              char *caddr, int clen, uint16_t *cport),
      46                 :            :             0);
      47                 :            : 
      48                 :            : int
      49                 :          0 : spdk_sock_close(struct spdk_sock **sock)
      50                 :            : {
      51                 :          0 :         *sock = NULL;
      52                 :          0 :         return 0;
      53                 :            : }
      54                 :            : 
      55         [ #  # ]:          0 : DEFINE_STUB(spdk_sock_recv, ssize_t,
      56                 :            :             (struct spdk_sock *sock, void *buf, size_t len), 0);
      57                 :            : 
      58         [ #  # ]:          0 : DEFINE_STUB(spdk_sock_readv, ssize_t,
      59                 :            :             (struct spdk_sock *sock, struct iovec *iov, int iovcnt), 0);
      60                 :            : 
      61                 :            : ssize_t
      62                 :          0 : spdk_sock_writev(struct spdk_sock *sock, struct iovec *iov, int iovcnt)
      63                 :            : {
      64                 :          0 :         return g_sock_writev_bytes;
      65                 :            : }
      66                 :            : 
      67         [ #  # ]:          0 : DEFINE_STUB(spdk_sock_set_recvlowat, int, (struct spdk_sock *s, int nbytes), 0);
      68                 :            : 
      69         [ #  # ]:          0 : DEFINE_STUB(spdk_sock_set_recvbuf, int, (struct spdk_sock *sock, int sz), 0);
      70                 :            : 
      71         [ #  # ]:          0 : DEFINE_STUB(spdk_sock_set_sendbuf, int, (struct spdk_sock *sock, int sz), 0);
      72                 :            : 
      73         [ #  # ]:          0 : DEFINE_STUB(spdk_sock_group_add_sock, int,
      74                 :            :             (struct spdk_sock_group *group, struct spdk_sock *sock,
      75                 :            :              spdk_sock_cb cb_fn, void *cb_arg),
      76                 :            :             0);
      77                 :            : 
      78         [ #  # ]:          0 : DEFINE_STUB(spdk_sock_group_remove_sock, int,
      79                 :            :             (struct spdk_sock_group *group, struct spdk_sock *sock), 0);
      80                 :            : 
      81                 :            : struct spdk_iscsi_task *
      82                 :         20 : iscsi_task_get(struct spdk_iscsi_conn *conn,
      83                 :            :                struct spdk_iscsi_task *parent,
      84                 :            :                spdk_scsi_task_cpl cpl_fn)
      85                 :            : {
      86                 :            :         struct spdk_iscsi_task *task;
      87                 :            : 
      88                 :         20 :         task = g_new_task;
      89         [ -  + ]:         20 :         if (task == NULL) {
      90                 :          0 :                 return NULL;
      91                 :            :         }
      92         [ -  + ]:         20 :         memset(task, 0, sizeof(*task));
      93                 :            : 
      94                 :         20 :         task->scsi.ref = 1;
      95                 :         20 :         task->conn = conn;
      96                 :         20 :         task->scsi.cpl_fn = cpl_fn;
      97         [ +  - ]:         20 :         if (parent) {
      98                 :         20 :                 parent->scsi.ref++;
      99                 :         20 :                 task->parent = parent;
     100                 :         20 :                 task->scsi.dxfer_dir = parent->scsi.dxfer_dir;
     101                 :         20 :                 task->scsi.transfer_len = parent->scsi.transfer_len;
     102                 :         20 :                 task->scsi.lun = parent->scsi.lun;
     103   [ +  -  +  + ]:         20 :                 if (conn && (task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV)) {
     104                 :          8 :                         conn->data_in_cnt++;
     105                 :            :                 }
     106                 :            :         }
     107                 :            : 
     108                 :         20 :         return task;
     109                 :            : }
     110                 :            : 
     111                 :            : void
     112                 :        328 : spdk_scsi_task_put(struct spdk_scsi_task *scsi_task)
     113                 :            : {
     114                 :            :         struct spdk_iscsi_task *task;
     115                 :            : 
     116                 :        328 :         CU_ASSERT(scsi_task->ref > 0);
     117                 :        328 :         scsi_task->ref--;
     118                 :            : 
     119                 :        328 :         task = iscsi_task_from_scsi_task(scsi_task);
     120         [ +  + ]:        328 :         if (task->parent) {
     121                 :        120 :                 spdk_scsi_task_put(&task->parent->scsi);
     122                 :            :         }
     123                 :        328 : }
     124                 :            : 
     125         [ #  # ]:          0 : DEFINE_STUB(spdk_scsi_dev_get_lun, struct spdk_scsi_lun *,
     126                 :            :             (struct spdk_scsi_dev *dev, int lun_id), NULL);
     127                 :            : 
     128         [ #  # ]:          0 : DEFINE_STUB(spdk_scsi_dev_get_first_lun, struct spdk_scsi_lun *,
     129                 :            :             (struct spdk_scsi_dev *dev), NULL);
     130                 :            : 
     131         [ #  # ]:          0 : DEFINE_STUB(spdk_scsi_dev_get_next_lun, struct spdk_scsi_lun *,
     132                 :            :             (struct spdk_scsi_lun *prev_lun), NULL);
     133                 :            : 
     134   [ #  #  #  # ]:          0 : DEFINE_STUB(spdk_scsi_dev_has_pending_tasks, bool,
     135                 :            :             (const struct spdk_scsi_dev *dev, const struct spdk_scsi_port *initiator_port),
     136                 :            :             true);
     137                 :            : 
     138         [ #  # ]:          0 : DEFINE_STUB(spdk_scsi_lun_open, int,
     139                 :            :             (struct spdk_scsi_lun *lun, spdk_scsi_lun_remove_cb_t hotremove_cb,
     140                 :            :              void *hotremove_ctx, struct spdk_scsi_lun_desc **desc),
     141                 :            :             0);
     142                 :            : 
     143                 :          0 : DEFINE_STUB_V(spdk_scsi_lun_close, (struct spdk_scsi_lun_desc *desc));
     144                 :            : 
     145         [ #  # ]:          0 : DEFINE_STUB(spdk_scsi_lun_allocate_io_channel, int,
     146                 :            :             (struct spdk_scsi_lun_desc *desc), 0);
     147                 :            : 
     148                 :          0 : DEFINE_STUB_V(spdk_scsi_lun_free_io_channel, (struct spdk_scsi_lun_desc *desc));
     149                 :            : 
     150         [ #  # ]:          0 : DEFINE_STUB(spdk_scsi_lun_get_id, int, (const struct spdk_scsi_lun *lun), 0);
     151                 :            : 
     152         [ #  # ]:          0 : DEFINE_STUB(spdk_scsi_port_get_name, const char *,
     153                 :            :             (const struct spdk_scsi_port *port), NULL);
     154                 :            : 
     155                 :            : void
     156                 :         28 : spdk_scsi_task_copy_status(struct spdk_scsi_task *dst,
     157                 :            :                            struct spdk_scsi_task *src)
     158                 :            : {
     159                 :         28 :         dst->status = src->status;
     160                 :         28 : }
     161                 :            : 
     162                 :         20 : DEFINE_STUB_V(spdk_scsi_task_set_data, (struct spdk_scsi_task *task, void *data, uint32_t len));
     163                 :            : 
     164                 :          0 : DEFINE_STUB_V(spdk_scsi_task_process_null_lun, (struct spdk_scsi_task *task));
     165                 :            : 
     166                 :         20 : DEFINE_STUB_V(spdk_scsi_task_process_abort, (struct spdk_scsi_task *task));
     167                 :            : 
     168                 :         40 : DEFINE_STUB_V(iscsi_put_pdu, (struct spdk_iscsi_pdu *pdu));
     169                 :            : 
     170                 :          0 : DEFINE_STUB_V(iscsi_param_free, (struct iscsi_param *params));
     171                 :            : 
     172         [ #  # ]:          0 : DEFINE_STUB(iscsi_conn_params_init, int, (struct iscsi_param **params), 0);
     173                 :            : 
     174                 :          0 : DEFINE_STUB_V(iscsi_clear_all_transfer_task,
     175                 :            :               (struct spdk_iscsi_conn *conn, struct spdk_scsi_lun *lun,
     176                 :            :                struct spdk_iscsi_pdu *pdu));
     177                 :            : 
     178         [ #  # ]:          0 : DEFINE_STUB(iscsi_build_iovs, int,
     179                 :            :             (struct spdk_iscsi_conn *conn, struct iovec *iov, int num_iovs,
     180                 :            :              struct spdk_iscsi_pdu *pdu, uint32_t *mapped_length),
     181                 :            :             0);
     182                 :            : 
     183                 :          0 : DEFINE_STUB_V(iscsi_queue_task,
     184                 :            :               (struct spdk_iscsi_conn *conn, struct spdk_iscsi_task *task));
     185                 :            : 
     186                 :        112 : DEFINE_STUB_V(iscsi_task_response,
     187                 :            :               (struct spdk_iscsi_conn *conn, struct spdk_iscsi_task *task));
     188                 :            : 
     189                 :          0 : DEFINE_STUB_V(iscsi_task_mgmt_response,
     190                 :            :               (struct spdk_iscsi_conn *conn, struct spdk_iscsi_task *task));
     191                 :            : 
     192                 :            : bool
     193                 :          4 : iscsi_del_transfer_task(struct spdk_iscsi_conn *conn, uint32_t task_tag)
     194                 :            : {
     195                 :            :         struct spdk_iscsi_task *task;
     196                 :            : 
     197                 :          4 :         task = TAILQ_FIRST(&conn->active_r2t_tasks);
     198   [ +  -  -  + ]:          4 :         if (task == NULL || task->tag != task_tag) {
     199                 :          0 :                 return false;
     200                 :            :         }
     201                 :            : 
     202         [ -  + ]:          4 :         TAILQ_REMOVE(&conn->active_r2t_tasks, task, link);
     203                 :          4 :         task->is_r2t_active = false;
     204                 :          4 :         iscsi_task_put(task);
     205                 :            : 
     206                 :          4 :         return true;
     207                 :            : }
     208                 :            : 
     209         [ #  # ]:          0 : DEFINE_STUB(iscsi_handle_incoming_pdus, int, (struct spdk_iscsi_conn *conn), 0);
     210                 :            : 
     211                 :          0 : DEFINE_STUB_V(iscsi_free_sess, (struct spdk_iscsi_sess *sess));
     212                 :            : 
     213         [ #  # ]:          0 : DEFINE_STUB(iscsi_tgt_node_cleanup_luns, int,
     214                 :            :             (struct spdk_iscsi_conn *conn, struct spdk_iscsi_tgt_node *target),
     215                 :            :             0);
     216                 :            : 
     217         [ #  # ]:          0 : DEFINE_STUB(iscsi_pdu_calc_header_digest, uint32_t,
     218                 :            :             (struct spdk_iscsi_pdu *pdu), 0);
     219                 :            : 
     220                 :          0 : DEFINE_STUB_V(shutdown_iscsi_conns_done, (void));
     221                 :            : 
     222                 :            : static struct spdk_iscsi_task *
     223                 :         64 : ut_conn_task_get(struct spdk_iscsi_task *parent)
     224                 :            : {
     225                 :            :         struct spdk_iscsi_task *task;
     226                 :            : 
     227                 :         64 :         task = calloc(1, sizeof(*task));
     228         [ -  + ]:         64 :         SPDK_CU_ASSERT_FATAL(task != NULL);
     229                 :            : 
     230                 :         64 :         task->scsi.ref = 1;
     231                 :            : 
     232         [ +  - ]:         64 :         if (parent) {
     233                 :         64 :                 task->parent = parent;
     234                 :         64 :                 parent->scsi.ref++;
     235                 :            :         }
     236                 :         64 :         return task;
     237                 :            : }
     238                 :            : 
     239                 :            : static void
     240                 :          8 : ut_conn_create_read_tasks(struct spdk_iscsi_task *primary)
     241                 :            : {
     242                 :            :         struct spdk_iscsi_task *subtask;
     243                 :          8 :         uint32_t remaining_size = 0;
     244                 :            : 
     245                 :            :         while (1) {
     246         [ +  - ]:         64 :                 if (primary->current_data_offset < primary->scsi.transfer_len) {
     247                 :         64 :                         remaining_size = primary->scsi.transfer_len - primary->current_data_offset;
     248                 :            : 
     249                 :         64 :                         subtask = ut_conn_task_get(primary);
     250                 :            : 
     251                 :         64 :                         subtask->scsi.offset = primary->current_data_offset;
     252                 :         64 :                         subtask->scsi.length = spdk_min(SPDK_BDEV_LARGE_BUF_MAX_SIZE, remaining_size);
     253                 :         64 :                         subtask->scsi.status = SPDK_SCSI_STATUS_GOOD;
     254                 :            : 
     255                 :         64 :                         primary->current_data_offset += subtask->scsi.length;
     256                 :            : 
     257                 :         64 :                         TAILQ_INSERT_TAIL(&g_ut_read_tasks, subtask, link);
     258                 :            :                 }
     259                 :            : 
     260         [ +  + ]:         64 :                 if (primary->current_data_offset == primary->scsi.transfer_len) {
     261                 :          8 :                         break;
     262                 :            :                 }
     263                 :            :         }
     264                 :          8 : }
     265                 :            : 
     266                 :            : static void
     267                 :          4 : read_task_split_in_order_case(void)
     268                 :            : {
     269                 :          4 :         struct spdk_iscsi_task primary = {};
     270                 :            :         struct spdk_iscsi_task *task, *tmp;
     271                 :          4 :         struct spdk_iscsi_conn conn = {};
     272                 :          4 :         struct spdk_iscsi_sess sess = {};
     273                 :            : 
     274                 :          4 :         conn.sess = &sess;
     275                 :          4 :         conn.sess->DataSequenceInOrder = true;
     276                 :            : 
     277                 :          4 :         primary.scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 8;
     278                 :          4 :         TAILQ_INIT(&primary.subtask_list);
     279                 :          4 :         primary.current_data_offset = 0;
     280                 :          4 :         primary.bytes_completed = 0;
     281                 :          4 :         primary.scsi.ref = 1;
     282                 :            : 
     283                 :          4 :         ut_conn_create_read_tasks(&primary);
     284         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_ut_read_tasks));
     285                 :            : 
     286         [ +  + ]:         36 :         TAILQ_FOREACH(task, &g_ut_read_tasks, link) {
     287                 :         32 :                 CU_ASSERT(&primary == iscsi_task_get_primary(task));
     288                 :         32 :                 process_read_task_completion(&conn, task, &primary);
     289                 :            :         }
     290                 :            : 
     291                 :          4 :         CU_ASSERT(primary.bytes_completed == primary.scsi.transfer_len);
     292                 :          4 :         CU_ASSERT(primary.scsi.ref == 0);
     293                 :            : 
     294         [ +  + ]:         36 :         TAILQ_FOREACH_SAFE(task, &g_ut_read_tasks, link, tmp) {
     295                 :         32 :                 CU_ASSERT(task->scsi.ref == 0);
     296         [ +  + ]:         32 :                 TAILQ_REMOVE(&g_ut_read_tasks, task, link);
     297                 :         32 :                 free(task);
     298                 :            :         }
     299                 :            : 
     300                 :          4 : }
     301                 :            : 
     302                 :            : static void
     303                 :          4 : read_task_split_reverse_order_case(void)
     304                 :            : {
     305                 :          4 :         struct spdk_iscsi_task primary = {};
     306                 :            :         struct spdk_iscsi_task *task, *tmp;
     307                 :          4 :         struct spdk_iscsi_conn conn = {};
     308                 :          4 :         struct spdk_iscsi_sess sess = {};
     309                 :            : 
     310                 :          4 :         conn.sess = &sess;
     311                 :          4 :         conn.sess->DataSequenceInOrder = true;
     312                 :            : 
     313                 :          4 :         primary.scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 8;
     314                 :          4 :         TAILQ_INIT(&primary.subtask_list);
     315                 :          4 :         primary.current_data_offset = 0;
     316                 :          4 :         primary.bytes_completed = 0;
     317                 :          4 :         primary.scsi.ref = 1;
     318                 :            : 
     319                 :          4 :         ut_conn_create_read_tasks(&primary);
     320         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_ut_read_tasks));
     321                 :            : 
     322         [ +  + ]:         36 :         TAILQ_FOREACH_REVERSE(task, &g_ut_read_tasks, read_tasks_head, link) {
     323                 :         32 :                 CU_ASSERT(&primary == iscsi_task_get_primary(task));
     324                 :         32 :                 process_read_task_completion(&conn, task, &primary);
     325                 :            :         }
     326                 :            : 
     327                 :          4 :         CU_ASSERT(primary.bytes_completed == primary.scsi.transfer_len);
     328                 :          4 :         CU_ASSERT(primary.scsi.ref == 0);
     329                 :            : 
     330         [ +  + ]:         36 :         TAILQ_FOREACH_SAFE(task, &g_ut_read_tasks, link, tmp) {
     331                 :         32 :                 CU_ASSERT(task->scsi.ref == 0);
     332         [ +  + ]:         32 :                 TAILQ_REMOVE(&g_ut_read_tasks, task, link);
     333                 :         32 :                 free(task);
     334                 :            :         }
     335                 :          4 : }
     336                 :            : 
     337                 :            : static void
     338                 :          4 : propagate_scsi_error_status_for_split_read_tasks(void)
     339                 :            : {
     340                 :          4 :         struct spdk_iscsi_task primary = {};
     341                 :          4 :         struct spdk_iscsi_task task1 = {}, task2 = {}, task3 = {}, task4 = {}, task5 = {}, task6 = {};
     342                 :            : 
     343                 :          4 :         struct spdk_iscsi_conn conn = {};
     344                 :          4 :         struct spdk_iscsi_sess sess = {};
     345                 :            : 
     346                 :          4 :         conn.sess = &sess;
     347                 :          4 :         conn.sess->DataSequenceInOrder = true;
     348                 :            : 
     349                 :          4 :         primary.scsi.transfer_len = 512 * 6;
     350                 :          4 :         primary.scsi.status = SPDK_SCSI_STATUS_GOOD;
     351                 :          4 :         TAILQ_INIT(&primary.subtask_list);
     352                 :          4 :         primary.scsi.ref = 7;
     353                 :            : 
     354                 :          4 :         task1.scsi.offset = 0;
     355                 :          4 :         task1.scsi.length = 512;
     356                 :          4 :         task1.scsi.status = SPDK_SCSI_STATUS_GOOD;
     357                 :          4 :         task1.scsi.ref = 1;
     358                 :          4 :         task1.parent = &primary;
     359                 :            : 
     360                 :          4 :         task2.scsi.offset = 512;
     361                 :          4 :         task2.scsi.length = 512;
     362                 :          4 :         task2.scsi.status = SPDK_SCSI_STATUS_CHECK_CONDITION;
     363                 :          4 :         task2.scsi.ref = 1;
     364                 :          4 :         task2.parent = &primary;
     365                 :            : 
     366                 :          4 :         task3.scsi.offset = 512 * 2;
     367                 :          4 :         task3.scsi.length = 512;
     368                 :          4 :         task3.scsi.status = SPDK_SCSI_STATUS_GOOD;
     369                 :          4 :         task3.scsi.ref = 1;
     370                 :          4 :         task3.parent = &primary;
     371                 :            : 
     372                 :          4 :         task4.scsi.offset = 512 * 3;
     373                 :          4 :         task4.scsi.length = 512;
     374                 :          4 :         task4.scsi.status = SPDK_SCSI_STATUS_GOOD;
     375                 :          4 :         task4.scsi.ref = 1;
     376                 :          4 :         task4.parent = &primary;
     377                 :            : 
     378                 :          4 :         task5.scsi.offset = 512 * 4;
     379                 :          4 :         task5.scsi.length = 512;
     380                 :          4 :         task5.scsi.status = SPDK_SCSI_STATUS_GOOD;
     381                 :          4 :         task5.scsi.ref = 1;
     382                 :          4 :         task5.parent = &primary;
     383                 :            : 
     384                 :          4 :         task6.scsi.offset = 512 * 5;
     385                 :          4 :         task6.scsi.length = 512;
     386                 :          4 :         task6.scsi.status = SPDK_SCSI_STATUS_GOOD;
     387                 :          4 :         task6.scsi.ref = 1;
     388                 :          4 :         task6.parent = &primary;
     389                 :            : 
     390                 :            :         /* task2 has check condition status, and verify if the check condition
     391                 :            :          * status is propagated to remaining tasks correctly when these tasks complete
     392                 :            :          * by the following order, task4, task3, task2, task1, primary, task5, and task6.
     393                 :            :          */
     394                 :          4 :         process_read_task_completion(&conn, &task4, &primary);
     395                 :          4 :         process_read_task_completion(&conn, &task3, &primary);
     396                 :          4 :         process_read_task_completion(&conn, &task2, &primary);
     397                 :          4 :         process_read_task_completion(&conn, &task1, &primary);
     398                 :          4 :         process_read_task_completion(&conn, &task5, &primary);
     399                 :          4 :         process_read_task_completion(&conn, &task6, &primary);
     400                 :            : 
     401                 :          4 :         CU_ASSERT(primary.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     402                 :          4 :         CU_ASSERT(task1.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     403                 :          4 :         CU_ASSERT(task2.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     404                 :          4 :         CU_ASSERT(task3.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     405                 :          4 :         CU_ASSERT(task4.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     406                 :          4 :         CU_ASSERT(task5.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     407                 :          4 :         CU_ASSERT(task6.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     408                 :          4 :         CU_ASSERT(primary.bytes_completed == primary.scsi.transfer_len);
     409                 :          4 :         CU_ASSERT(TAILQ_EMPTY(&primary.subtask_list));
     410                 :          4 :         CU_ASSERT(primary.scsi.ref == 0);
     411                 :          4 :         CU_ASSERT(task1.scsi.ref == 0);
     412                 :          4 :         CU_ASSERT(task2.scsi.ref == 0);
     413                 :          4 :         CU_ASSERT(task3.scsi.ref == 0);
     414                 :          4 :         CU_ASSERT(task4.scsi.ref == 0);
     415                 :          4 :         CU_ASSERT(task5.scsi.ref == 0);
     416                 :          4 :         CU_ASSERT(task6.scsi.ref == 0);
     417                 :          4 : }
     418                 :            : 
     419                 :            : static void
     420                 :          4 : process_non_read_task_completion_test(void)
     421                 :            : {
     422                 :          4 :         struct spdk_iscsi_conn conn = {};
     423                 :          4 :         struct spdk_iscsi_task primary = {};
     424                 :          4 :         struct spdk_iscsi_task task = {};
     425                 :            : 
     426                 :          4 :         TAILQ_INIT(&conn.active_r2t_tasks);
     427                 :            : 
     428                 :          4 :         primary.bytes_completed = 0;
     429                 :          4 :         primary.scsi.transfer_len = 4096 * 3;
     430                 :          4 :         primary.scsi.status = SPDK_SCSI_STATUS_GOOD;
     431                 :          4 :         primary.scsi.ref = 1;
     432                 :          4 :         TAILQ_INSERT_TAIL(&conn.active_r2t_tasks, &primary, link);
     433                 :          4 :         primary.is_r2t_active = true;
     434                 :          4 :         primary.tag = 1;
     435                 :            : 
     436                 :            :         /* First subtask which failed. */
     437                 :          4 :         task.scsi.length = 4096;
     438                 :          4 :         task.scsi.data_transferred = 4096;
     439                 :          4 :         task.scsi.status = SPDK_SCSI_STATUS_CHECK_CONDITION;
     440                 :          4 :         task.scsi.ref = 1;
     441                 :          4 :         task.parent = &primary;
     442                 :          4 :         primary.scsi.ref++;
     443                 :            : 
     444                 :          4 :         process_non_read_task_completion(&conn, &task, &primary);
     445                 :          4 :         CU_ASSERT(!TAILQ_EMPTY(&conn.active_r2t_tasks));
     446                 :          4 :         CU_ASSERT(primary.bytes_completed == 4096);
     447                 :          4 :         CU_ASSERT(primary.scsi.data_transferred == 0);
     448                 :          4 :         CU_ASSERT(primary.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     449                 :          4 :         CU_ASSERT(task.scsi.ref == 0);
     450                 :          4 :         CU_ASSERT(primary.scsi.ref == 1);
     451                 :            : 
     452                 :            :         /* Second subtask which succeeded. */
     453                 :          4 :         task.scsi.length = 4096;
     454                 :          4 :         task.scsi.data_transferred = 4096;
     455                 :          4 :         task.scsi.status = SPDK_SCSI_STATUS_GOOD;
     456                 :          4 :         task.scsi.ref = 1;
     457                 :          4 :         task.parent = &primary;
     458                 :          4 :         primary.scsi.ref++;
     459                 :            : 
     460                 :          4 :         process_non_read_task_completion(&conn, &task, &primary);
     461                 :          4 :         CU_ASSERT(!TAILQ_EMPTY(&conn.active_r2t_tasks));
     462                 :          4 :         CU_ASSERT(primary.bytes_completed == 4096 * 2);
     463                 :          4 :         CU_ASSERT(primary.scsi.data_transferred == 4096);
     464                 :          4 :         CU_ASSERT(primary.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     465                 :          4 :         CU_ASSERT(task.scsi.ref == 0);
     466                 :          4 :         CU_ASSERT(primary.scsi.ref == 1);
     467                 :            : 
     468                 :            :         /* Third and final subtask which succeeded. */
     469                 :          4 :         task.scsi.length = 4096;
     470                 :          4 :         task.scsi.data_transferred = 4096;
     471                 :          4 :         task.scsi.status = SPDK_SCSI_STATUS_GOOD;
     472                 :          4 :         task.scsi.ref = 1;
     473                 :          4 :         task.parent = &primary;
     474                 :          4 :         primary.scsi.ref++;
     475                 :            : 
     476                 :          4 :         process_non_read_task_completion(&conn, &task, &primary);
     477                 :          4 :         CU_ASSERT(TAILQ_EMPTY(&conn.active_r2t_tasks));
     478                 :          4 :         CU_ASSERT(primary.bytes_completed == 4096 * 3);
     479                 :          4 :         CU_ASSERT(primary.scsi.data_transferred == 4096 * 2);
     480                 :          4 :         CU_ASSERT(primary.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     481                 :          4 :         CU_ASSERT(task.scsi.ref == 0);
     482                 :          4 :         CU_ASSERT(primary.scsi.ref == 0);
     483                 :            : 
     484                 :            :         /* A tricky case that the R2T was already terminated when the last task completed. */
     485                 :          4 :         primary.scsi.ref = 0;
     486                 :          4 :         primary.bytes_completed = 4096 * 2;
     487                 :          4 :         primary.scsi.data_transferred = 4096 * 2;
     488                 :          4 :         primary.scsi.transfer_len = 4096 * 3;
     489                 :          4 :         primary.scsi.status = SPDK_SCSI_STATUS_CHECK_CONDITION;
     490                 :          4 :         primary.is_r2t_active = false;
     491                 :          4 :         task.scsi.length = 4096;
     492                 :          4 :         task.scsi.data_transferred = 4096;
     493                 :          4 :         task.scsi.status = SPDK_SCSI_STATUS_GOOD;
     494                 :          4 :         task.scsi.ref = 1;
     495                 :          4 :         task.parent = &primary;
     496                 :          4 :         primary.scsi.ref++;
     497                 :            : 
     498                 :          4 :         process_non_read_task_completion(&conn, &task, &primary);
     499                 :          4 :         CU_ASSERT(primary.bytes_completed == 4096 * 3);
     500                 :          4 :         CU_ASSERT(primary.scsi.data_transferred == 4096 * 3);
     501                 :          4 :         CU_ASSERT(primary.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     502                 :          4 :         CU_ASSERT(primary.scsi.ref == 0);
     503                 :          4 : }
     504                 :            : 
     505                 :            : static bool
     506                 :         12 : dequeue_pdu(void *_head, struct spdk_iscsi_pdu *pdu)
     507                 :            : {
     508                 :         12 :         TAILQ_HEAD(queued_pdus, spdk_iscsi_pdu) *head = _head;
     509                 :            :         struct spdk_iscsi_pdu *tmp;
     510                 :            : 
     511         [ -  + ]:         12 :         TAILQ_FOREACH(tmp, head, tailq) {
     512         [ #  # ]:          0 :                 if (tmp == pdu) {
     513         [ #  # ]:          0 :                         TAILQ_REMOVE(head, tmp, tailq);
     514                 :          0 :                         return true;
     515                 :            :                 }
     516                 :            :         }
     517                 :         12 :         return false;
     518                 :            : }
     519                 :            : 
     520                 :            : static bool
     521                 :         12 : dequeue_task(void *_head, struct spdk_iscsi_task *task)
     522                 :            : {
     523                 :         12 :         TAILQ_HEAD(queued_tasks, spdk_iscsi_task) *head = _head;
     524                 :            :         struct spdk_iscsi_task *tmp;
     525                 :            : 
     526         [ +  + ]:         20 :         TAILQ_FOREACH(tmp, head, link) {
     527         [ +  + ]:         12 :                 if (tmp == task) {
     528         [ -  + ]:          4 :                         TAILQ_REMOVE(head, tmp, link);
     529                 :          4 :                         return true;
     530                 :            :                 }
     531                 :            :         }
     532                 :          8 :         return false;
     533                 :            : }
     534                 :            : 
     535                 :            : static void
     536                 :         40 : iscsi_conn_pdu_dummy_complete(void *arg)
     537                 :            : {
     538                 :         40 : }
     539                 :            : 
     540                 :            : static void
     541                 :          4 : free_tasks_on_connection(void)
     542                 :            : {
     543                 :          4 :         struct spdk_iscsi_conn conn = {};
     544                 :          4 :         struct spdk_iscsi_pdu pdu1 = {}, pdu2 = {}, pdu3 = {}, pdu4 = {};
     545                 :          4 :         struct spdk_iscsi_task task1 = {}, task2 = {}, task3 = {};
     546                 :          4 :         struct spdk_scsi_lun lun1 = {}, lun2 = {};
     547                 :            : 
     548                 :          4 :         TAILQ_INIT(&conn.write_pdu_list);
     549                 :          4 :         TAILQ_INIT(&conn.snack_pdu_list);
     550                 :          4 :         TAILQ_INIT(&conn.queued_datain_tasks);
     551                 :          4 :         conn.data_in_cnt = g_iscsi.MaxLargeDataInPerConnection;
     552                 :            : 
     553                 :          4 :         pdu1.task = &task1;
     554                 :          4 :         pdu2.task = &task2;
     555                 :          4 :         pdu3.task = &task3;
     556                 :            : 
     557                 :          4 :         pdu1.cb_fn = iscsi_conn_pdu_dummy_complete;
     558                 :          4 :         pdu2.cb_fn = iscsi_conn_pdu_dummy_complete;
     559                 :          4 :         pdu3.cb_fn = iscsi_conn_pdu_dummy_complete;
     560                 :          4 :         pdu4.cb_fn = iscsi_conn_pdu_dummy_complete;
     561                 :            : 
     562                 :          4 :         task1.scsi.lun = &lun1;
     563                 :          4 :         task2.scsi.lun = &lun2;
     564                 :            : 
     565                 :          4 :         task1.is_queued = false;
     566                 :          4 :         task2.is_queued = false;
     567                 :          4 :         task3.is_queued = true;
     568                 :            : 
     569                 :            :         /* Test conn->write_pdu_list. */
     570                 :            : 
     571                 :          4 :         task1.scsi.ref = 1;
     572                 :          4 :         task2.scsi.ref = 1;
     573                 :          4 :         task3.scsi.ref = 1;
     574                 :          4 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu1, tailq);
     575                 :          4 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu2, tailq);
     576                 :          4 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu3, tailq);
     577                 :          4 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu4, tailq);
     578                 :            : 
     579                 :            :         /* Free all PDUs when exiting connection. */
     580                 :          4 :         iscsi_conn_free_tasks(&conn);
     581                 :            : 
     582                 :          4 :         CU_ASSERT(TAILQ_EMPTY(&conn.write_pdu_list));
     583                 :          4 :         CU_ASSERT(task1.scsi.ref == 0);
     584                 :          4 :         CU_ASSERT(task2.scsi.ref == 0);
     585                 :          4 :         CU_ASSERT(task3.scsi.ref == 0);
     586                 :            : 
     587                 :            :         /* Test conn->snack_pdu_list */
     588                 :            : 
     589                 :          4 :         task1.scsi.ref = 1;
     590                 :          4 :         task2.scsi.ref = 1;
     591                 :          4 :         task3.scsi.ref = 1;
     592                 :          4 :         pdu1.cb_fn = iscsi_conn_pdu_dummy_complete;
     593                 :          4 :         pdu2.cb_fn = iscsi_conn_pdu_dummy_complete;
     594                 :          4 :         pdu3.cb_fn = iscsi_conn_pdu_dummy_complete;
     595                 :          4 :         TAILQ_INSERT_TAIL(&conn.snack_pdu_list, &pdu1, tailq);
     596                 :          4 :         TAILQ_INSERT_TAIL(&conn.snack_pdu_list, &pdu2, tailq);
     597                 :          4 :         TAILQ_INSERT_TAIL(&conn.snack_pdu_list, &pdu3, tailq);
     598                 :            : 
     599                 :            :         /* Free all PDUs and associated tasks when exiting connection. */
     600                 :          4 :         iscsi_conn_free_tasks(&conn);
     601                 :            : 
     602                 :          4 :         CU_ASSERT(!dequeue_pdu(&conn.snack_pdu_list, &pdu1));
     603                 :          4 :         CU_ASSERT(!dequeue_pdu(&conn.snack_pdu_list, &pdu2));
     604                 :          4 :         CU_ASSERT(!dequeue_pdu(&conn.snack_pdu_list, &pdu3));
     605                 :          4 :         CU_ASSERT(task1.scsi.ref == 0);
     606                 :          4 :         CU_ASSERT(task2.scsi.ref == 0);
     607                 :          4 :         CU_ASSERT(task3.scsi.ref == 0);
     608                 :            : 
     609                 :            :         /* Test conn->queued_datain_tasks */
     610                 :            : 
     611                 :          4 :         task1.scsi.ref = 1;
     612                 :          4 :         task2.scsi.ref = 1;
     613                 :          4 :         task3.scsi.ref = 1;
     614                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task1, link);
     615                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task2, link);
     616                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task3, link);
     617                 :            : 
     618                 :            :         /* Free all tasks which is not queued when exiting connection. */
     619                 :          4 :         iscsi_conn_free_tasks(&conn);
     620                 :            : 
     621                 :          4 :         CU_ASSERT(!dequeue_task(&conn.queued_datain_tasks, &task1));
     622                 :          4 :         CU_ASSERT(!dequeue_task(&conn.queued_datain_tasks, &task2));
     623                 :          4 :         CU_ASSERT(dequeue_task(&conn.queued_datain_tasks, &task3));
     624                 :          4 :         CU_ASSERT(task1.scsi.ref == 0);
     625                 :          4 :         CU_ASSERT(task2.scsi.ref == 0);
     626                 :          4 :         CU_ASSERT(task3.scsi.ref == 1);
     627                 :          4 : }
     628                 :            : 
     629                 :            : static void
     630                 :          4 : free_tasks_with_queued_datain(void)
     631                 :            : {
     632                 :          4 :         struct spdk_iscsi_conn conn = {};
     633                 :          4 :         struct spdk_iscsi_pdu pdu1 = {}, pdu2 = {}, pdu3 = {}, pdu4 = {}, pdu5 = {}, pdu6 = {};
     634                 :          4 :         struct spdk_iscsi_task task1 = {}, task2 = {}, task3 = {}, task4 = {}, task5 = {}, task6 = {};
     635                 :            : 
     636                 :          4 :         TAILQ_INIT(&conn.write_pdu_list);
     637                 :          4 :         TAILQ_INIT(&conn.snack_pdu_list);
     638                 :          4 :         TAILQ_INIT(&conn.queued_datain_tasks);
     639                 :            : 
     640                 :          4 :         pdu1.task = &task1;
     641                 :          4 :         pdu2.task = &task2;
     642                 :          4 :         pdu3.task = &task3;
     643                 :          4 :         pdu1.cb_fn = iscsi_conn_pdu_dummy_complete;
     644                 :          4 :         pdu2.cb_fn = iscsi_conn_pdu_dummy_complete;
     645                 :          4 :         pdu3.cb_fn = iscsi_conn_pdu_dummy_complete;
     646                 :            : 
     647                 :          4 :         task1.scsi.ref = 1;
     648                 :          4 :         task2.scsi.ref = 1;
     649                 :          4 :         task3.scsi.ref = 1;
     650                 :            : 
     651                 :          4 :         pdu3.bhs.opcode = ISCSI_OP_SCSI_DATAIN;
     652                 :          4 :         task3.scsi.offset = 1;
     653                 :          4 :         conn.data_in_cnt = 1;
     654                 :            : 
     655                 :          4 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu1, tailq);
     656                 :          4 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu2, tailq);
     657                 :          4 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu3, tailq);
     658                 :            : 
     659                 :          4 :         task4.scsi.ref = 1;
     660                 :          4 :         task5.scsi.ref = 1;
     661                 :          4 :         task6.scsi.ref = 1;
     662                 :            : 
     663                 :          4 :         task4.pdu = &pdu4;
     664                 :          4 :         task5.pdu = &pdu5;
     665                 :          4 :         task6.pdu = &pdu6;
     666                 :          4 :         pdu4.cb_fn = iscsi_conn_pdu_dummy_complete;
     667                 :          4 :         pdu5.cb_fn = iscsi_conn_pdu_dummy_complete;
     668                 :          4 :         pdu6.cb_fn = iscsi_conn_pdu_dummy_complete;
     669                 :            : 
     670                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task4, link);
     671                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task5, link);
     672                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task6, link);
     673                 :            : 
     674                 :          4 :         iscsi_conn_free_tasks(&conn);
     675                 :            : 
     676                 :          4 :         CU_ASSERT(TAILQ_EMPTY(&conn.write_pdu_list));
     677                 :          4 :         CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
     678                 :          4 : }
     679                 :            : 
     680                 :            : static void
     681                 :          4 : abort_queued_datain_task_test(void)
     682                 :            : {
     683                 :          4 :         struct spdk_iscsi_conn conn = {};
     684                 :          4 :         struct spdk_iscsi_task task = {}, subtask = {};
     685                 :          4 :         struct spdk_iscsi_pdu pdu = {};
     686                 :            :         struct iscsi_bhs_scsi_req *scsi_req;
     687                 :            :         int rc;
     688                 :            : 
     689                 :          4 :         struct spdk_iscsi_sess sess = {};
     690                 :            : 
     691                 :          4 :         conn.sess = &sess;
     692                 :          4 :         conn.sess->DataSequenceInOrder = true;
     693                 :            : 
     694                 :          4 :         TAILQ_INIT(&conn.queued_datain_tasks);
     695                 :          4 :         task.scsi.ref = 1;
     696                 :          4 :         task.scsi.dxfer_dir = SPDK_SCSI_DIR_FROM_DEV;
     697                 :          4 :         task.pdu = &pdu;
     698                 :          4 :         TAILQ_INIT(&task.subtask_list);
     699                 :          4 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu.bhs;
     700                 :          4 :         scsi_req->read_bit = 1;
     701                 :            : 
     702                 :          4 :         g_new_task = &subtask;
     703                 :            : 
     704                 :            :         /* Case1: Queue one task, and this task is not executed */
     705                 :          4 :         task.scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3;
     706                 :          4 :         task.scsi.offset = 0;
     707                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task, link);
     708                 :            : 
     709                 :            :         /* No slots for sub read tasks */
     710                 :          4 :         conn.data_in_cnt = g_iscsi.MaxLargeDataInPerConnection;
     711                 :          4 :         rc = _iscsi_conn_abort_queued_datain_task(&conn, &task);
     712                 :          4 :         CU_ASSERT(rc != 0);
     713                 :          4 :         CU_ASSERT(!TAILQ_EMPTY(&conn.queued_datain_tasks));
     714                 :            : 
     715                 :            :         /* Have slots for sub read tasks */
     716                 :          4 :         conn.data_in_cnt = 0;
     717                 :          4 :         rc = _iscsi_conn_abort_queued_datain_task(&conn, &task);
     718                 :          4 :         CU_ASSERT(rc == 0);
     719                 :          4 :         CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
     720                 :          4 :         CU_ASSERT(task.current_data_offset == SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3);
     721                 :          4 :         CU_ASSERT(task.scsi.ref == 0);
     722                 :          4 :         CU_ASSERT(subtask.scsi.offset == 0);
     723                 :          4 :         CU_ASSERT(subtask.scsi.length == SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3);
     724                 :          4 :         CU_ASSERT(subtask.scsi.ref == 0);
     725                 :            : 
     726                 :            :         /* Case2: Queue one task, and this task is partially executed */
     727                 :          4 :         task.scsi.ref = 1;
     728                 :          4 :         task.scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3;
     729                 :          4 :         task.current_data_offset = SPDK_BDEV_LARGE_BUF_MAX_SIZE;
     730                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task, link);
     731                 :            : 
     732                 :            :         /* No slots for sub read tasks */
     733                 :          4 :         conn.data_in_cnt = g_iscsi.MaxLargeDataInPerConnection;
     734                 :          4 :         rc = _iscsi_conn_abort_queued_datain_task(&conn, &task);
     735                 :          4 :         CU_ASSERT(rc != 0);
     736                 :          4 :         CU_ASSERT(!TAILQ_EMPTY(&conn.queued_datain_tasks));
     737                 :            : 
     738                 :            :         /* have slots for sub read tasks */
     739                 :          4 :         conn.data_in_cnt = 0;
     740                 :          4 :         rc = _iscsi_conn_abort_queued_datain_task(&conn, &task);
     741                 :          4 :         CU_ASSERT(rc == 0);
     742                 :          4 :         CU_ASSERT(task.current_data_offset == SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3);
     743                 :          4 :         CU_ASSERT(task.scsi.ref == 2);
     744                 :          4 :         CU_ASSERT(TAILQ_FIRST(&task.subtask_list) == &subtask);
     745                 :          4 :         CU_ASSERT(subtask.scsi.offset == SPDK_BDEV_LARGE_BUF_MAX_SIZE);
     746                 :          4 :         CU_ASSERT(subtask.scsi.length == SPDK_BDEV_LARGE_BUF_MAX_SIZE * 2);
     747                 :          4 :         CU_ASSERT(subtask.scsi.ref == 1);
     748                 :            : 
     749                 :          4 :         g_new_task = NULL;
     750                 :          4 : }
     751                 :            : 
     752                 :            : static bool
     753                 :         44 : datain_task_is_queued(struct spdk_iscsi_conn *conn,
     754                 :            :                       struct spdk_iscsi_task *task)
     755                 :            : {
     756                 :            :         struct spdk_iscsi_task *tmp;
     757                 :            : 
     758         [ +  + ]:        140 :         TAILQ_FOREACH(tmp, &conn->queued_datain_tasks, link) {
     759         [ +  + ]:        128 :                 if (tmp == task) {
     760                 :         32 :                         return true;
     761                 :            :                 }
     762                 :            :         }
     763                 :         12 :         return false;
     764                 :            : }
     765                 :            : static void
     766                 :          4 : abort_queued_datain_tasks_test(void)
     767                 :            : {
     768                 :          4 :         struct spdk_iscsi_conn conn = {};
     769                 :          4 :         struct spdk_iscsi_task task1 = {}, task2 = {}, task3 = {}, task4 = {}, task5 = {}, task6 = {};
     770                 :          4 :         struct spdk_iscsi_task subtask = {};
     771                 :          4 :         struct spdk_iscsi_pdu pdu1 = {}, pdu2 = {}, pdu3 = {}, pdu4 = {}, pdu5 = {}, pdu6 = {};
     772                 :          4 :         struct spdk_iscsi_pdu mgmt_pdu1 = {}, mgmt_pdu2 = {};
     773                 :          4 :         struct spdk_scsi_lun lun1 = {}, lun2 = {};
     774                 :            :         uint32_t alloc_cmd_sn;
     775                 :            :         struct iscsi_bhs_scsi_req *scsi_req;
     776                 :            :         int rc;
     777                 :          4 :         struct spdk_iscsi_sess sess = {};
     778                 :            : 
     779                 :          4 :         TAILQ_INIT(&conn.queued_datain_tasks);
     780                 :          4 :         conn.data_in_cnt = 0;
     781                 :            : 
     782                 :          4 :         conn.sess = &sess;
     783                 :          4 :         conn.sess->DataSequenceInOrder = true;
     784                 :            : 
     785                 :          4 :         g_new_task = &subtask;
     786                 :            : 
     787                 :          4 :         alloc_cmd_sn = 88;
     788                 :            : 
     789                 :          4 :         pdu1.cmd_sn = alloc_cmd_sn;
     790                 :          4 :         alloc_cmd_sn++;
     791                 :          4 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu1.bhs;
     792                 :          4 :         scsi_req->read_bit = 1;
     793                 :          4 :         task1.scsi.ref = 1;
     794                 :          4 :         task1.current_data_offset = 0;
     795                 :          4 :         task1.scsi.transfer_len = 512;
     796                 :          4 :         task1.scsi.lun = &lun1;
     797                 :          4 :         iscsi_task_set_pdu(&task1, &pdu1);
     798                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task1, link);
     799                 :            : 
     800                 :          4 :         pdu2.cmd_sn = alloc_cmd_sn;
     801                 :          4 :         alloc_cmd_sn++;
     802                 :          4 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu2.bhs;
     803                 :          4 :         scsi_req->read_bit = 1;
     804                 :          4 :         task2.scsi.ref = 1;
     805                 :          4 :         task2.current_data_offset = 0;
     806                 :          4 :         task2.scsi.transfer_len = 512;
     807                 :          4 :         task2.scsi.lun = &lun2;
     808                 :          4 :         iscsi_task_set_pdu(&task2, &pdu2);
     809                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task2, link);
     810                 :            : 
     811                 :          4 :         mgmt_pdu1.cmd_sn = alloc_cmd_sn;
     812                 :          4 :         alloc_cmd_sn++;
     813                 :            : 
     814                 :          4 :         pdu3.cmd_sn = alloc_cmd_sn;
     815                 :          4 :         alloc_cmd_sn++;
     816                 :          4 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu3.bhs;
     817                 :          4 :         scsi_req->read_bit = 1;
     818                 :          4 :         task3.scsi.ref = 1;
     819                 :          4 :         task3.current_data_offset = 0;
     820                 :          4 :         task3.scsi.transfer_len = 512;
     821                 :          4 :         task3.scsi.lun = &lun1;
     822                 :          4 :         iscsi_task_set_pdu(&task3, &pdu3);
     823                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task3, link);
     824                 :            : 
     825                 :          4 :         pdu4.cmd_sn = alloc_cmd_sn;
     826                 :          4 :         alloc_cmd_sn++;
     827                 :          4 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu4.bhs;
     828                 :          4 :         scsi_req->read_bit = 1;
     829                 :          4 :         task4.scsi.ref = 1;
     830                 :          4 :         task4.current_data_offset = 0;
     831                 :          4 :         task4.scsi.transfer_len = 512;
     832                 :          4 :         task4.scsi.lun = &lun2;
     833                 :          4 :         iscsi_task_set_pdu(&task4, &pdu4);
     834                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task4, link);
     835                 :            : 
     836                 :          4 :         pdu5.cmd_sn = alloc_cmd_sn;
     837                 :          4 :         alloc_cmd_sn++;
     838                 :          4 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu5.bhs;
     839                 :          4 :         scsi_req->read_bit = 1;
     840                 :          4 :         task5.scsi.ref = 1;
     841                 :          4 :         task5.current_data_offset = 0;
     842                 :          4 :         task5.scsi.transfer_len = 512;
     843                 :          4 :         task5.scsi.lun = &lun1;
     844                 :          4 :         iscsi_task_set_pdu(&task5, &pdu5);
     845                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task5, link);
     846                 :            : 
     847                 :          4 :         mgmt_pdu2.cmd_sn = alloc_cmd_sn;
     848                 :          4 :         alloc_cmd_sn++;
     849                 :            : 
     850                 :          4 :         pdu6.cmd_sn = alloc_cmd_sn;
     851                 :          4 :         alloc_cmd_sn++;
     852                 :          4 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu6.bhs;
     853                 :          4 :         scsi_req->read_bit = 1;
     854                 :          4 :         task6.scsi.ref = 1;
     855                 :          4 :         task6.current_data_offset = 0;
     856                 :          4 :         task6.scsi.transfer_len = 512;
     857                 :          4 :         task6.scsi.lun = &lun2;
     858                 :          4 :         iscsi_task_set_pdu(&task6, &pdu6);
     859                 :          4 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task6, link);
     860                 :            : 
     861                 :          4 :         rc = iscsi_conn_abort_queued_datain_tasks(&conn, &lun1, &mgmt_pdu1);
     862                 :          4 :         CU_ASSERT(rc == 0);
     863                 :          4 :         CU_ASSERT(!datain_task_is_queued(&conn, &task1));
     864                 :          4 :         CU_ASSERT(datain_task_is_queued(&conn, &task2));
     865                 :          4 :         CU_ASSERT(datain_task_is_queued(&conn, &task3));
     866                 :          4 :         CU_ASSERT(datain_task_is_queued(&conn, &task4));
     867                 :          4 :         CU_ASSERT(datain_task_is_queued(&conn, &task5));
     868                 :          4 :         CU_ASSERT(datain_task_is_queued(&conn, &task6));
     869                 :            : 
     870                 :          4 :         rc = iscsi_conn_abort_queued_datain_tasks(&conn, &lun2, &mgmt_pdu2);
     871                 :          4 :         CU_ASSERT(rc == 0);
     872                 :          4 :         CU_ASSERT(!datain_task_is_queued(&conn, &task2));
     873                 :          4 :         CU_ASSERT(datain_task_is_queued(&conn, &task3));
     874                 :          4 :         CU_ASSERT(!datain_task_is_queued(&conn, &task4));
     875                 :          4 :         CU_ASSERT(datain_task_is_queued(&conn, &task5));
     876                 :          4 :         CU_ASSERT(datain_task_is_queued(&conn, &task6));
     877                 :            : 
     878                 :          4 :         CU_ASSERT(task1.scsi.ref == 0);
     879                 :          4 :         CU_ASSERT(task2.scsi.ref == 0);
     880                 :          4 :         CU_ASSERT(task3.scsi.ref == 1);
     881                 :          4 :         CU_ASSERT(task4.scsi.ref == 0);
     882                 :          4 :         CU_ASSERT(task5.scsi.ref == 1);
     883                 :          4 :         CU_ASSERT(task6.scsi.ref == 1);
     884                 :          4 :         CU_ASSERT(subtask.scsi.ref == 0);
     885                 :            : 
     886                 :          4 :         g_new_task = NULL;
     887                 :          4 : }
     888                 :            : 
     889                 :            : int
     890                 :          4 : main(int argc, char **argv)
     891                 :            : {
     892                 :          4 :         CU_pSuite       suite = NULL;
     893                 :            :         unsigned int    num_failures;
     894                 :            : 
     895                 :          4 :         CU_initialize_registry();
     896                 :            : 
     897                 :          4 :         suite = CU_add_suite("conn_suite", NULL, NULL);
     898                 :            : 
     899                 :          4 :         CU_ADD_TEST(suite, read_task_split_in_order_case);
     900                 :          4 :         CU_ADD_TEST(suite, read_task_split_reverse_order_case);
     901                 :          4 :         CU_ADD_TEST(suite, propagate_scsi_error_status_for_split_read_tasks);
     902                 :          4 :         CU_ADD_TEST(suite, process_non_read_task_completion_test);
     903                 :          4 :         CU_ADD_TEST(suite, free_tasks_on_connection);
     904                 :          4 :         CU_ADD_TEST(suite, free_tasks_with_queued_datain);
     905                 :          4 :         CU_ADD_TEST(suite, abort_queued_datain_task_test);
     906                 :          4 :         CU_ADD_TEST(suite, abort_queued_datain_tasks_test);
     907                 :            : 
     908                 :          4 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
     909                 :          4 :         CU_cleanup_registry();
     910                 :          4 :         return num_failures;
     911                 :            : }

Generated by: LCOV version 1.14