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: 559 605 92.4 %
Date: 2024-12-17 01:13:47 Functions: 24 61 39.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 906 1846 49.1 %

           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                 :          6 : 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                 :         30 : iscsi_task_get(struct spdk_iscsi_conn *conn,
      83                 :            :                struct spdk_iscsi_task *parent,
      84                 :            :                spdk_scsi_task_cpl cpl_fn)
      85                 :            : {
      86                 :          5 :         struct spdk_iscsi_task *task;
      87                 :            : 
      88                 :         30 :         task = g_new_task;
      89         [ +  + ]:         30 :         if (task == NULL) {
      90                 :          0 :                 return NULL;
      91                 :            :         }
      92         [ +  + ]:         30 :         memset(task, 0, sizeof(*task));
      93                 :            : 
      94   [ +  -  +  -  :         30 :         task->scsi.ref = 1;
                   +  - ]
      95   [ +  -  +  - ]:         30 :         task->conn = conn;
      96   [ +  -  +  -  :         30 :         task->scsi.cpl_fn = cpl_fn;
                   +  - ]
      97         [ +  + ]:         30 :         if (parent) {
      98   [ +  -  +  - ]:         30 :                 parent->scsi.ref++;
      99   [ +  -  +  - ]:         30 :                 task->parent = parent;
     100   [ +  -  +  -  :         30 :                 task->scsi.dxfer_dir = parent->scsi.dxfer_dir;
          +  -  +  -  +  
                -  +  - ]
     101   [ +  -  +  -  :         30 :                 task->scsi.transfer_len = parent->scsi.transfer_len;
          +  -  +  -  +  
                -  +  - ]
     102   [ +  -  +  -  :         30 :                 task->scsi.lun = parent->scsi.lun;
          +  -  +  -  +  
                -  +  - ]
     103   [ +  -  +  +  :         30 :                 if (conn && (task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV)) {
          +  -  +  -  +  
                      + ]
     104         [ +  - ]:         12 :                         conn->data_in_cnt++;
     105                 :          2 :                 }
     106                 :          5 :         }
     107                 :            : 
     108                 :         30 :         return task;
     109                 :          5 : }
     110                 :            : 
     111                 :            : void
     112                 :        492 : spdk_scsi_task_put(struct spdk_scsi_task *scsi_task)
     113                 :            : {
     114                 :         82 :         struct spdk_iscsi_task *task;
     115                 :            : 
     116   [ +  -  +  - ]:        492 :         CU_ASSERT(scsi_task->ref > 0);
     117         [ +  - ]:        492 :         scsi_task->ref--;
     118                 :            : 
     119                 :        492 :         task = iscsi_task_from_scsi_task(scsi_task);
     120   [ +  +  +  -  :        492 :         if (task->parent) {
                   +  + ]
     121   [ +  -  +  -  :        180 :                 spdk_scsi_task_put(&task->parent->scsi);
                   +  - ]
     122                 :         30 :         }
     123                 :        492 : }
     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                 :         42 : spdk_scsi_task_copy_status(struct spdk_scsi_task *dst,
     157                 :            :                            struct spdk_scsi_task *src)
     158                 :            : {
     159   [ +  -  +  -  :         42 :         dst->status = src->status;
             +  -  +  - ]
     160                 :         42 : }
     161                 :            : 
     162                 :         30 : 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                 :         30 : DEFINE_STUB_V(spdk_scsi_task_process_abort, (struct spdk_scsi_task *task));
     167                 :            : 
     168                 :         60 : 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                 :        168 : 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                 :          6 : iscsi_del_transfer_task(struct spdk_iscsi_conn *conn, uint32_t task_tag)
     194                 :            : {
     195                 :          1 :         struct spdk_iscsi_task *task;
     196                 :            : 
     197   [ +  -  +  -  :          6 :         task = TAILQ_FIRST(&conn->active_r2t_tasks);
                   +  - ]
     198   [ +  -  +  +  :          6 :         if (task == NULL || task->tag != task_tag) {
             +  -  -  + ]
     199                 :          0 :                 return false;
     200                 :            :         }
     201                 :            : 
     202   [ +  +  +  -  :          6 :         TAILQ_REMOVE(&conn->active_r2t_tasks, task, link);
          +  -  +  -  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     203   [ +  -  +  - ]:          6 :         task->is_r2t_active = false;
     204                 :          6 :         iscsi_task_put(task);
     205                 :            : 
     206                 :          6 :         return true;
     207                 :          1 : }
     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                 :         96 : ut_conn_task_get(struct spdk_iscsi_task *parent)
     224                 :            : {
     225                 :         16 :         struct spdk_iscsi_task *task;
     226                 :            : 
     227                 :         96 :         task = calloc(1, sizeof(*task));
     228   [ +  +  #  # ]:         96 :         SPDK_CU_ASSERT_FATAL(task != NULL);
     229                 :            : 
     230   [ +  -  +  -  :         96 :         task->scsi.ref = 1;
                   +  - ]
     231                 :            : 
     232         [ +  + ]:         96 :         if (parent) {
     233   [ +  -  +  - ]:         96 :                 task->parent = parent;
     234   [ +  -  +  - ]:         96 :                 parent->scsi.ref++;
     235                 :         16 :         }
     236                 :        112 :         return task;
     237                 :         16 : }
     238                 :            : 
     239                 :            : static void
     240                 :         12 : ut_conn_create_read_tasks(struct spdk_iscsi_task *primary)
     241                 :            : {
     242                 :          2 :         struct spdk_iscsi_task *subtask;
     243                 :         12 :         uint32_t remaining_size = 0;
     244                 :            : 
     245                 :         16 :         while (1) {
     246   [ +  -  +  -  :         96 :                 if (primary->current_data_offset < primary->scsi.transfer_len) {
          +  -  +  -  +  
                -  -  + ]
     247   [ +  -  +  -  :         96 :                         remaining_size = primary->scsi.transfer_len - primary->current_data_offset;
          +  -  +  -  +  
                      - ]
     248                 :            : 
     249                 :         96 :                         subtask = ut_conn_task_get(primary);
     250                 :            : 
     251   [ +  -  +  -  :         96 :                         subtask->scsi.offset = primary->current_data_offset;
          +  -  +  -  +  
                      - ]
     252   [ +  +  +  -  :         96 :                         subtask->scsi.length = spdk_min(SPDK_BDEV_LARGE_BUF_MAX_SIZE, remaining_size);
             +  -  +  - ]
     253   [ +  -  +  -  :         96 :                         subtask->scsi.status = SPDK_SCSI_STATUS_GOOD;
                   +  - ]
     254                 :            : 
     255   [ +  -  +  -  :         96 :                         primary->current_data_offset += subtask->scsi.length;
          +  -  +  -  +  
                      - ]
     256                 :            : 
     257   [ +  -  +  -  :         96 :                         TAILQ_INSERT_TAIL(&g_ut_read_tasks, subtask, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     258                 :         16 :                 }
     259                 :            : 
     260   [ +  +  +  -  :         96 :                 if (primary->current_data_offset == primary->scsi.transfer_len) {
          +  -  +  -  +  
                -  +  + ]
     261                 :         12 :                         break;
     262                 :            :                 }
     263                 :            :         }
     264                 :         12 : }
     265                 :            : 
     266                 :            : static void
     267                 :          6 : read_task_split_in_order_case(void)
     268                 :            : {
     269                 :          6 :         struct spdk_iscsi_task primary = {};
     270                 :          1 :         struct spdk_iscsi_task *task, *tmp;
     271                 :          6 :         struct spdk_iscsi_conn conn = {};
     272                 :          6 :         struct spdk_iscsi_sess sess = {};
     273                 :            : 
     274         [ +  - ]:          6 :         conn.sess = &sess;
     275   [ +  -  +  -  :          6 :         conn.sess->DataSequenceInOrder = true;
                   +  - ]
     276                 :            : 
     277         [ +  - ]:          6 :         primary.scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 8;
     278   [ +  -  +  -  :          6 :         TAILQ_INIT(&primary.subtask_list);
          +  -  +  -  +  
                      - ]
     279         [ +  - ]:          6 :         primary.current_data_offset = 0;
     280         [ +  - ]:          6 :         primary.bytes_completed = 0;
     281         [ +  - ]:          6 :         primary.scsi.ref = 1;
     282                 :            : 
     283                 :          6 :         ut_conn_create_read_tasks(&primary);
     284   [ +  +  #  # ]:          6 :         SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_ut_read_tasks));
     285                 :            : 
     286   [ +  +  +  -  :         54 :         TAILQ_FOREACH(task, &g_ut_read_tasks, link) {
             +  -  +  - ]
     287                 :         48 :                 CU_ASSERT(&primary == iscsi_task_get_primary(task));
     288                 :         48 :                 process_read_task_completion(&conn, task, &primary);
     289                 :          8 :         }
     290                 :            : 
     291   [ +  -  +  - ]:          6 :         CU_ASSERT(primary.bytes_completed == primary.scsi.transfer_len);
     292         [ +  - ]:          6 :         CU_ASSERT(primary.scsi.ref == 0);
     293                 :            : 
     294   [ +  +  +  -  :         54 :         TAILQ_FOREACH_SAFE(task, &g_ut_read_tasks, link, tmp) {
          +  -  +  -  +  
                      + ]
     295   [ +  -  +  -  :         48 :                 CU_ASSERT(task->scsi.ref == 0);
                   +  - ]
     296   [ +  +  +  -  :         48 :                 TAILQ_REMOVE(&g_ut_read_tasks, task, link);
          +  -  +  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     297                 :         48 :                 free(task);
     298                 :          8 :         }
     299                 :            : 
     300                 :          6 : }
     301                 :            : 
     302                 :            : static void
     303                 :          6 : read_task_split_reverse_order_case(void)
     304                 :            : {
     305                 :          6 :         struct spdk_iscsi_task primary = {};
     306                 :          1 :         struct spdk_iscsi_task *task, *tmp;
     307                 :          6 :         struct spdk_iscsi_conn conn = {};
     308                 :          6 :         struct spdk_iscsi_sess sess = {};
     309                 :            : 
     310         [ +  - ]:          6 :         conn.sess = &sess;
     311   [ +  -  +  -  :          6 :         conn.sess->DataSequenceInOrder = true;
                   +  - ]
     312                 :            : 
     313         [ +  - ]:          6 :         primary.scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 8;
     314   [ +  -  +  -  :          6 :         TAILQ_INIT(&primary.subtask_list);
          +  -  +  -  +  
                      - ]
     315         [ +  - ]:          6 :         primary.current_data_offset = 0;
     316         [ +  - ]:          6 :         primary.bytes_completed = 0;
     317         [ +  - ]:          6 :         primary.scsi.ref = 1;
     318                 :            : 
     319                 :          6 :         ut_conn_create_read_tasks(&primary);
     320   [ +  +  #  # ]:          6 :         SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_ut_read_tasks));
     321                 :            : 
     322   [ +  +  +  -  :         54 :         TAILQ_FOREACH_REVERSE(task, &g_ut_read_tasks, read_tasks_head, link) {
          +  -  +  -  +  
          +  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     323                 :         48 :                 CU_ASSERT(&primary == iscsi_task_get_primary(task));
     324                 :         48 :                 process_read_task_completion(&conn, task, &primary);
     325                 :          8 :         }
     326                 :            : 
     327   [ +  -  +  - ]:          6 :         CU_ASSERT(primary.bytes_completed == primary.scsi.transfer_len);
     328         [ +  - ]:          6 :         CU_ASSERT(primary.scsi.ref == 0);
     329                 :            : 
     330   [ +  +  +  -  :         54 :         TAILQ_FOREACH_SAFE(task, &g_ut_read_tasks, link, tmp) {
          +  -  +  -  +  
                      + ]
     331   [ +  -  +  -  :         48 :                 CU_ASSERT(task->scsi.ref == 0);
                   +  - ]
     332   [ +  +  +  -  :         48 :                 TAILQ_REMOVE(&g_ut_read_tasks, task, link);
          +  -  +  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     333                 :         48 :                 free(task);
     334                 :          8 :         }
     335                 :          6 : }
     336                 :            : 
     337                 :            : static void
     338                 :          6 : propagate_scsi_error_status_for_split_read_tasks(void)
     339                 :            : {
     340                 :          6 :         struct spdk_iscsi_task primary = {};
     341                 :          6 :         struct spdk_iscsi_task task1 = {}, task2 = {}, task3 = {}, task4 = {}, task5 = {}, task6 = {};
     342                 :            : 
     343                 :          6 :         struct spdk_iscsi_conn conn = {};
     344                 :          6 :         struct spdk_iscsi_sess sess = {};
     345                 :            : 
     346         [ +  - ]:          6 :         conn.sess = &sess;
     347   [ +  -  +  -  :          6 :         conn.sess->DataSequenceInOrder = true;
                   +  - ]
     348                 :            : 
     349         [ +  - ]:          6 :         primary.scsi.transfer_len = 512 * 6;
     350                 :          6 :         primary.scsi.status = SPDK_SCSI_STATUS_GOOD;
     351   [ +  -  +  -  :          6 :         TAILQ_INIT(&primary.subtask_list);
          +  -  +  -  +  
                      - ]
     352         [ +  - ]:          6 :         primary.scsi.ref = 7;
     353                 :            : 
     354         [ +  - ]:          6 :         task1.scsi.offset = 0;
     355         [ +  - ]:          6 :         task1.scsi.length = 512;
     356                 :          6 :         task1.scsi.status = SPDK_SCSI_STATUS_GOOD;
     357         [ +  - ]:          6 :         task1.scsi.ref = 1;
     358         [ +  - ]:          6 :         task1.parent = &primary;
     359                 :            : 
     360         [ +  - ]:          6 :         task2.scsi.offset = 512;
     361         [ +  - ]:          6 :         task2.scsi.length = 512;
     362                 :          6 :         task2.scsi.status = SPDK_SCSI_STATUS_CHECK_CONDITION;
     363         [ +  - ]:          6 :         task2.scsi.ref = 1;
     364         [ +  - ]:          6 :         task2.parent = &primary;
     365                 :            : 
     366         [ +  - ]:          6 :         task3.scsi.offset = 512 * 2;
     367         [ +  - ]:          6 :         task3.scsi.length = 512;
     368                 :          6 :         task3.scsi.status = SPDK_SCSI_STATUS_GOOD;
     369         [ +  - ]:          6 :         task3.scsi.ref = 1;
     370         [ +  - ]:          6 :         task3.parent = &primary;
     371                 :            : 
     372         [ +  - ]:          6 :         task4.scsi.offset = 512 * 3;
     373         [ +  - ]:          6 :         task4.scsi.length = 512;
     374                 :          6 :         task4.scsi.status = SPDK_SCSI_STATUS_GOOD;
     375         [ +  - ]:          6 :         task4.scsi.ref = 1;
     376         [ +  - ]:          6 :         task4.parent = &primary;
     377                 :            : 
     378         [ +  - ]:          6 :         task5.scsi.offset = 512 * 4;
     379         [ +  - ]:          6 :         task5.scsi.length = 512;
     380                 :          6 :         task5.scsi.status = SPDK_SCSI_STATUS_GOOD;
     381         [ +  - ]:          6 :         task5.scsi.ref = 1;
     382         [ +  - ]:          6 :         task5.parent = &primary;
     383                 :            : 
     384         [ +  - ]:          6 :         task6.scsi.offset = 512 * 5;
     385         [ +  - ]:          6 :         task6.scsi.length = 512;
     386                 :          6 :         task6.scsi.status = SPDK_SCSI_STATUS_GOOD;
     387         [ +  - ]:          6 :         task6.scsi.ref = 1;
     388         [ +  - ]:          6 :         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                 :          6 :         process_read_task_completion(&conn, &task4, &primary);
     395                 :          6 :         process_read_task_completion(&conn, &task3, &primary);
     396                 :          6 :         process_read_task_completion(&conn, &task2, &primary);
     397                 :          6 :         process_read_task_completion(&conn, &task1, &primary);
     398                 :          6 :         process_read_task_completion(&conn, &task5, &primary);
     399                 :          6 :         process_read_task_completion(&conn, &task6, &primary);
     400                 :            : 
     401                 :          6 :         CU_ASSERT(primary.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     402                 :          6 :         CU_ASSERT(task1.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     403                 :          6 :         CU_ASSERT(task2.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     404                 :          6 :         CU_ASSERT(task3.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     405                 :          6 :         CU_ASSERT(task4.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     406                 :          6 :         CU_ASSERT(task5.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     407                 :          6 :         CU_ASSERT(task6.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     408   [ +  -  +  - ]:          6 :         CU_ASSERT(primary.bytes_completed == primary.scsi.transfer_len);
     409   [ +  -  +  - ]:          6 :         CU_ASSERT(TAILQ_EMPTY(&primary.subtask_list));
     410         [ +  - ]:          6 :         CU_ASSERT(primary.scsi.ref == 0);
     411         [ +  - ]:          6 :         CU_ASSERT(task1.scsi.ref == 0);
     412         [ +  - ]:          6 :         CU_ASSERT(task2.scsi.ref == 0);
     413         [ +  - ]:          6 :         CU_ASSERT(task3.scsi.ref == 0);
     414         [ +  - ]:          6 :         CU_ASSERT(task4.scsi.ref == 0);
     415         [ +  - ]:          6 :         CU_ASSERT(task5.scsi.ref == 0);
     416         [ +  - ]:          6 :         CU_ASSERT(task6.scsi.ref == 0);
     417                 :          6 : }
     418                 :            : 
     419                 :            : static void
     420                 :          6 : process_non_read_task_completion_test(void)
     421                 :            : {
     422                 :          6 :         struct spdk_iscsi_conn conn = {};
     423                 :          6 :         struct spdk_iscsi_task primary = {};
     424                 :          6 :         struct spdk_iscsi_task task = {};
     425                 :            : 
     426   [ +  -  +  -  :          6 :         TAILQ_INIT(&conn.active_r2t_tasks);
          +  -  +  -  +  
                      - ]
     427                 :            : 
     428         [ +  - ]:          6 :         primary.bytes_completed = 0;
     429         [ +  - ]:          6 :         primary.scsi.transfer_len = 4096 * 3;
     430                 :          6 :         primary.scsi.status = SPDK_SCSI_STATUS_GOOD;
     431         [ +  - ]:          6 :         primary.scsi.ref = 1;
     432   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.active_r2t_tasks, &primary, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     433         [ +  - ]:          6 :         primary.is_r2t_active = true;
     434         [ +  - ]:          6 :         primary.tag = 1;
     435                 :            : 
     436                 :            :         /* First subtask which failed. */
     437         [ +  - ]:          6 :         task.scsi.length = 4096;
     438         [ +  - ]:          6 :         task.scsi.data_transferred = 4096;
     439                 :          6 :         task.scsi.status = SPDK_SCSI_STATUS_CHECK_CONDITION;
     440         [ +  - ]:          6 :         task.scsi.ref = 1;
     441         [ +  - ]:          6 :         task.parent = &primary;
     442                 :          6 :         primary.scsi.ref++;
     443                 :            : 
     444                 :          6 :         process_non_read_task_completion(&conn, &task, &primary);
     445   [ +  -  +  - ]:          6 :         CU_ASSERT(!TAILQ_EMPTY(&conn.active_r2t_tasks));
     446         [ +  - ]:          6 :         CU_ASSERT(primary.bytes_completed == 4096);
     447         [ +  - ]:          6 :         CU_ASSERT(primary.scsi.data_transferred == 0);
     448                 :          6 :         CU_ASSERT(primary.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     449         [ +  - ]:          6 :         CU_ASSERT(task.scsi.ref == 0);
     450         [ +  - ]:          6 :         CU_ASSERT(primary.scsi.ref == 1);
     451                 :            : 
     452                 :            :         /* Second subtask which succeeded. */
     453         [ +  - ]:          6 :         task.scsi.length = 4096;
     454         [ +  - ]:          6 :         task.scsi.data_transferred = 4096;
     455                 :          6 :         task.scsi.status = SPDK_SCSI_STATUS_GOOD;
     456         [ +  - ]:          6 :         task.scsi.ref = 1;
     457         [ +  - ]:          6 :         task.parent = &primary;
     458                 :          6 :         primary.scsi.ref++;
     459                 :            : 
     460                 :          6 :         process_non_read_task_completion(&conn, &task, &primary);
     461   [ +  -  +  - ]:          6 :         CU_ASSERT(!TAILQ_EMPTY(&conn.active_r2t_tasks));
     462         [ +  - ]:          6 :         CU_ASSERT(primary.bytes_completed == 4096 * 2);
     463         [ +  - ]:          6 :         CU_ASSERT(primary.scsi.data_transferred == 4096);
     464                 :          6 :         CU_ASSERT(primary.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     465         [ +  - ]:          6 :         CU_ASSERT(task.scsi.ref == 0);
     466         [ +  - ]:          6 :         CU_ASSERT(primary.scsi.ref == 1);
     467                 :            : 
     468                 :            :         /* Third and final subtask which succeeded. */
     469         [ +  - ]:          6 :         task.scsi.length = 4096;
     470         [ +  - ]:          6 :         task.scsi.data_transferred = 4096;
     471                 :          6 :         task.scsi.status = SPDK_SCSI_STATUS_GOOD;
     472         [ +  - ]:          6 :         task.scsi.ref = 1;
     473         [ +  - ]:          6 :         task.parent = &primary;
     474                 :          6 :         primary.scsi.ref++;
     475                 :            : 
     476                 :          6 :         process_non_read_task_completion(&conn, &task, &primary);
     477   [ +  -  +  - ]:          6 :         CU_ASSERT(TAILQ_EMPTY(&conn.active_r2t_tasks));
     478         [ +  - ]:          6 :         CU_ASSERT(primary.bytes_completed == 4096 * 3);
     479         [ +  - ]:          6 :         CU_ASSERT(primary.scsi.data_transferred == 4096 * 2);
     480                 :          6 :         CU_ASSERT(primary.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     481         [ +  - ]:          6 :         CU_ASSERT(task.scsi.ref == 0);
     482         [ +  - ]:          6 :         CU_ASSERT(primary.scsi.ref == 0);
     483                 :            : 
     484                 :            :         /* A tricky case that the R2T was already terminated when the last task completed. */
     485         [ +  - ]:          6 :         primary.scsi.ref = 0;
     486         [ +  - ]:          6 :         primary.bytes_completed = 4096 * 2;
     487         [ +  - ]:          6 :         primary.scsi.data_transferred = 4096 * 2;
     488         [ +  - ]:          6 :         primary.scsi.transfer_len = 4096 * 3;
     489                 :          6 :         primary.scsi.status = SPDK_SCSI_STATUS_CHECK_CONDITION;
     490         [ +  - ]:          6 :         primary.is_r2t_active = false;
     491         [ +  - ]:          6 :         task.scsi.length = 4096;
     492         [ +  - ]:          6 :         task.scsi.data_transferred = 4096;
     493                 :          6 :         task.scsi.status = SPDK_SCSI_STATUS_GOOD;
     494         [ +  - ]:          6 :         task.scsi.ref = 1;
     495         [ +  - ]:          6 :         task.parent = &primary;
     496                 :          6 :         primary.scsi.ref++;
     497                 :            : 
     498                 :          6 :         process_non_read_task_completion(&conn, &task, &primary);
     499         [ +  - ]:          6 :         CU_ASSERT(primary.bytes_completed == 4096 * 3);
     500         [ +  - ]:          6 :         CU_ASSERT(primary.scsi.data_transferred == 4096 * 3);
     501                 :          6 :         CU_ASSERT(primary.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
     502         [ +  - ]:          6 :         CU_ASSERT(primary.scsi.ref == 0);
     503                 :          6 : }
     504                 :            : 
     505                 :            : static bool
     506                 :         18 : dequeue_pdu(void *_head, struct spdk_iscsi_pdu *pdu)
     507                 :            : {
     508                 :         18 :         TAILQ_HEAD(queued_pdus, spdk_iscsi_pdu) *head = _head;
     509                 :          3 :         struct spdk_iscsi_pdu *tmp;
     510                 :            : 
     511   [ +  +  +  -  :         18 :         TAILQ_FOREACH(tmp, head, tailq) {
          -  +  #  #  #  
                #  #  # ]
     512         [ #  # ]:          0 :                 if (tmp == pdu) {
     513   [ #  #  #  #  :          0 :                         TAILQ_REMOVE(head, tmp, tailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     514                 :          0 :                         return true;
     515                 :            :                 }
     516                 :          0 :         }
     517                 :         18 :         return false;
     518                 :          3 : }
     519                 :            : 
     520                 :            : static bool
     521                 :         18 : dequeue_task(void *_head, struct spdk_iscsi_task *task)
     522                 :            : {
     523                 :         18 :         TAILQ_HEAD(queued_tasks, spdk_iscsi_task) *head = _head;
     524                 :          3 :         struct spdk_iscsi_task *tmp;
     525                 :            : 
     526   [ +  +  +  -  :         30 :         TAILQ_FOREACH(tmp, head, link) {
          +  +  +  -  +  
                -  +  - ]
     527         [ +  + ]:         18 :                 if (tmp == task) {
     528   [ +  +  +  -  :          6 :                         TAILQ_REMOVE(head, tmp, link);
          +  -  -  +  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  -  +  -  
          +  -  +  -  +  
          -  +  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     529                 :          6 :                         return true;
     530                 :            :                 }
     531                 :          2 :         }
     532                 :         12 :         return false;
     533                 :          3 : }
     534                 :            : 
     535                 :            : static void
     536                 :         60 : iscsi_conn_pdu_dummy_complete(void *arg)
     537                 :            : {
     538                 :         60 : }
     539                 :            : 
     540                 :            : static void
     541                 :          6 : free_tasks_on_connection(void)
     542                 :            : {
     543                 :          6 :         struct spdk_iscsi_conn conn = {};
     544                 :          6 :         struct spdk_iscsi_pdu pdu1 = {}, pdu2 = {}, pdu3 = {}, pdu4 = {};
     545                 :          6 :         struct spdk_iscsi_task task1 = {}, task2 = {}, task3 = {};
     546                 :          6 :         struct spdk_scsi_lun lun1 = {}, lun2 = {};
     547                 :            : 
     548   [ +  -  +  -  :          6 :         TAILQ_INIT(&conn.write_pdu_list);
          +  -  +  -  +  
                      - ]
     549   [ +  -  +  -  :          6 :         TAILQ_INIT(&conn.snack_pdu_list);
          +  -  +  -  +  
                      - ]
     550   [ +  -  +  -  :          6 :         TAILQ_INIT(&conn.queued_datain_tasks);
          +  -  +  -  +  
                      - ]
     551   [ +  -  +  - ]:          6 :         conn.data_in_cnt = g_iscsi.MaxLargeDataInPerConnection;
     552                 :            : 
     553         [ +  - ]:          6 :         pdu1.task = &task1;
     554         [ +  - ]:          6 :         pdu2.task = &task2;
     555         [ +  - ]:          6 :         pdu3.task = &task3;
     556                 :            : 
     557         [ +  - ]:          6 :         pdu1.cb_fn = iscsi_conn_pdu_dummy_complete;
     558         [ +  - ]:          6 :         pdu2.cb_fn = iscsi_conn_pdu_dummy_complete;
     559         [ +  - ]:          6 :         pdu3.cb_fn = iscsi_conn_pdu_dummy_complete;
     560         [ +  - ]:          6 :         pdu4.cb_fn = iscsi_conn_pdu_dummy_complete;
     561                 :            : 
     562         [ +  - ]:          6 :         task1.scsi.lun = &lun1;
     563         [ +  - ]:          6 :         task2.scsi.lun = &lun2;
     564                 :            : 
     565         [ +  - ]:          6 :         task1.is_queued = false;
     566         [ +  - ]:          6 :         task2.is_queued = false;
     567         [ +  - ]:          6 :         task3.is_queued = true;
     568                 :            : 
     569                 :            :         /* Test conn->write_pdu_list. */
     570                 :            : 
     571         [ +  - ]:          6 :         task1.scsi.ref = 1;
     572         [ +  - ]:          6 :         task2.scsi.ref = 1;
     573         [ +  - ]:          6 :         task3.scsi.ref = 1;
     574   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu1, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     575   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu2, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     576   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu3, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     577   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu4, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     578                 :            : 
     579                 :            :         /* Free all PDUs when exiting connection. */
     580                 :          6 :         iscsi_conn_free_tasks(&conn);
     581                 :            : 
     582   [ +  -  +  - ]:          6 :         CU_ASSERT(TAILQ_EMPTY(&conn.write_pdu_list));
     583         [ +  - ]:          6 :         CU_ASSERT(task1.scsi.ref == 0);
     584         [ +  - ]:          6 :         CU_ASSERT(task2.scsi.ref == 0);
     585         [ +  - ]:          6 :         CU_ASSERT(task3.scsi.ref == 0);
     586                 :            : 
     587                 :            :         /* Test conn->snack_pdu_list */
     588                 :            : 
     589         [ +  - ]:          6 :         task1.scsi.ref = 1;
     590         [ +  - ]:          6 :         task2.scsi.ref = 1;
     591         [ +  - ]:          6 :         task3.scsi.ref = 1;
     592         [ +  - ]:          6 :         pdu1.cb_fn = iscsi_conn_pdu_dummy_complete;
     593         [ +  - ]:          6 :         pdu2.cb_fn = iscsi_conn_pdu_dummy_complete;
     594         [ +  - ]:          6 :         pdu3.cb_fn = iscsi_conn_pdu_dummy_complete;
     595   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.snack_pdu_list, &pdu1, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     596   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.snack_pdu_list, &pdu2, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     597   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.snack_pdu_list, &pdu3, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     598                 :            : 
     599                 :            :         /* Free all PDUs and associated tasks when exiting connection. */
     600                 :          6 :         iscsi_conn_free_tasks(&conn);
     601                 :            : 
     602                 :          6 :         CU_ASSERT(!dequeue_pdu(&conn.snack_pdu_list, &pdu1));
     603                 :          6 :         CU_ASSERT(!dequeue_pdu(&conn.snack_pdu_list, &pdu2));
     604                 :          6 :         CU_ASSERT(!dequeue_pdu(&conn.snack_pdu_list, &pdu3));
     605         [ +  - ]:          6 :         CU_ASSERT(task1.scsi.ref == 0);
     606         [ +  - ]:          6 :         CU_ASSERT(task2.scsi.ref == 0);
     607         [ +  - ]:          6 :         CU_ASSERT(task3.scsi.ref == 0);
     608                 :            : 
     609                 :            :         /* Test conn->queued_datain_tasks */
     610                 :            : 
     611         [ +  - ]:          6 :         task1.scsi.ref = 1;
     612         [ +  - ]:          6 :         task2.scsi.ref = 1;
     613         [ +  - ]:          6 :         task3.scsi.ref = 1;
     614   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task1, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     615   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task2, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     616   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task3, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     617                 :            : 
     618                 :            :         /* Free all tasks which is not queued when exiting connection. */
     619                 :          6 :         iscsi_conn_free_tasks(&conn);
     620                 :            : 
     621                 :          6 :         CU_ASSERT(!dequeue_task(&conn.queued_datain_tasks, &task1));
     622                 :          6 :         CU_ASSERT(!dequeue_task(&conn.queued_datain_tasks, &task2));
     623                 :          6 :         CU_ASSERT(dequeue_task(&conn.queued_datain_tasks, &task3));
     624         [ +  - ]:          6 :         CU_ASSERT(task1.scsi.ref == 0);
     625         [ +  - ]:          6 :         CU_ASSERT(task2.scsi.ref == 0);
     626         [ +  - ]:          6 :         CU_ASSERT(task3.scsi.ref == 1);
     627                 :          6 : }
     628                 :            : 
     629                 :            : static void
     630                 :          6 : free_tasks_with_queued_datain(void)
     631                 :            : {
     632                 :          6 :         struct spdk_iscsi_conn conn = {};
     633                 :          6 :         struct spdk_iscsi_pdu pdu1 = {}, pdu2 = {}, pdu3 = {}, pdu4 = {}, pdu5 = {}, pdu6 = {};
     634                 :          6 :         struct spdk_iscsi_task task1 = {}, task2 = {}, task3 = {}, task4 = {}, task5 = {}, task6 = {};
     635                 :            : 
     636   [ +  -  +  -  :          6 :         TAILQ_INIT(&conn.write_pdu_list);
          +  -  +  -  +  
                      - ]
     637   [ +  -  +  -  :          6 :         TAILQ_INIT(&conn.snack_pdu_list);
          +  -  +  -  +  
                      - ]
     638   [ +  -  +  -  :          6 :         TAILQ_INIT(&conn.queued_datain_tasks);
          +  -  +  -  +  
                      - ]
     639                 :            : 
     640         [ +  - ]:          6 :         pdu1.task = &task1;
     641         [ +  - ]:          6 :         pdu2.task = &task2;
     642         [ +  - ]:          6 :         pdu3.task = &task3;
     643         [ +  - ]:          6 :         pdu1.cb_fn = iscsi_conn_pdu_dummy_complete;
     644         [ +  - ]:          6 :         pdu2.cb_fn = iscsi_conn_pdu_dummy_complete;
     645         [ +  - ]:          6 :         pdu3.cb_fn = iscsi_conn_pdu_dummy_complete;
     646                 :            : 
     647         [ +  - ]:          6 :         task1.scsi.ref = 1;
     648         [ +  - ]:          6 :         task2.scsi.ref = 1;
     649         [ +  - ]:          6 :         task3.scsi.ref = 1;
     650                 :            : 
     651                 :          6 :         pdu3.bhs.opcode = ISCSI_OP_SCSI_DATAIN;
     652         [ +  - ]:          6 :         task3.scsi.offset = 1;
     653         [ +  - ]:          6 :         conn.data_in_cnt = 1;
     654                 :            : 
     655   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu1, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     656   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu2, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     657   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.write_pdu_list, &pdu3, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     658                 :            : 
     659         [ +  - ]:          6 :         task4.scsi.ref = 1;
     660         [ +  - ]:          6 :         task5.scsi.ref = 1;
     661         [ +  - ]:          6 :         task6.scsi.ref = 1;
     662                 :            : 
     663         [ +  - ]:          6 :         task4.pdu = &pdu4;
     664         [ +  - ]:          6 :         task5.pdu = &pdu5;
     665         [ +  - ]:          6 :         task6.pdu = &pdu6;
     666         [ +  - ]:          6 :         pdu4.cb_fn = iscsi_conn_pdu_dummy_complete;
     667         [ +  - ]:          6 :         pdu5.cb_fn = iscsi_conn_pdu_dummy_complete;
     668         [ +  - ]:          6 :         pdu6.cb_fn = iscsi_conn_pdu_dummy_complete;
     669                 :            : 
     670   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task4, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     671   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task5, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     672   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task6, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     673                 :            : 
     674                 :          6 :         iscsi_conn_free_tasks(&conn);
     675                 :            : 
     676   [ +  -  +  - ]:          6 :         CU_ASSERT(TAILQ_EMPTY(&conn.write_pdu_list));
     677   [ +  -  +  - ]:          6 :         CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
     678                 :          6 : }
     679                 :            : 
     680                 :            : static void
     681                 :          6 : abort_queued_datain_task_test(void)
     682                 :            : {
     683                 :          6 :         struct spdk_iscsi_conn conn = {};
     684                 :          6 :         struct spdk_iscsi_task task = {}, subtask = {};
     685                 :          6 :         struct spdk_iscsi_pdu pdu = {};
     686                 :          1 :         struct iscsi_bhs_scsi_req *scsi_req;
     687                 :          1 :         int rc;
     688                 :            : 
     689                 :          6 :         struct spdk_iscsi_sess sess = {};
     690                 :            : 
     691         [ +  - ]:          6 :         conn.sess = &sess;
     692   [ +  -  +  -  :          6 :         conn.sess->DataSequenceInOrder = true;
                   +  - ]
     693                 :            : 
     694   [ +  -  +  -  :          6 :         TAILQ_INIT(&conn.queued_datain_tasks);
          +  -  +  -  +  
                      - ]
     695         [ +  - ]:          6 :         task.scsi.ref = 1;
     696         [ +  - ]:          6 :         task.scsi.dxfer_dir = SPDK_SCSI_DIR_FROM_DEV;
     697         [ +  - ]:          6 :         task.pdu = &pdu;
     698   [ +  -  +  -  :          6 :         TAILQ_INIT(&task.subtask_list);
          +  -  +  -  +  
                      - ]
     699                 :          6 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu.bhs;
     700         [ +  - ]:          6 :         scsi_req->read_bit = 1;
     701                 :            : 
     702                 :          6 :         g_new_task = &subtask;
     703                 :            : 
     704                 :            :         /* Case1: Queue one task, and this task is not executed */
     705         [ +  - ]:          6 :         task.scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3;
     706         [ +  - ]:          6 :         task.scsi.offset = 0;
     707   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     708                 :            : 
     709                 :            :         /* No slots for sub read tasks */
     710   [ +  -  +  - ]:          6 :         conn.data_in_cnt = g_iscsi.MaxLargeDataInPerConnection;
     711                 :          6 :         rc = _iscsi_conn_abort_queued_datain_task(&conn, &task);
     712                 :          6 :         CU_ASSERT(rc != 0);
     713   [ +  -  +  - ]:          6 :         CU_ASSERT(!TAILQ_EMPTY(&conn.queued_datain_tasks));
     714                 :            : 
     715                 :            :         /* Have slots for sub read tasks */
     716         [ +  - ]:          6 :         conn.data_in_cnt = 0;
     717                 :          6 :         rc = _iscsi_conn_abort_queued_datain_task(&conn, &task);
     718                 :          6 :         CU_ASSERT(rc == 0);
     719   [ +  -  +  - ]:          6 :         CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
     720         [ +  - ]:          6 :         CU_ASSERT(task.current_data_offset == SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3);
     721         [ +  - ]:          6 :         CU_ASSERT(task.scsi.ref == 0);
     722         [ +  - ]:          6 :         CU_ASSERT(subtask.scsi.offset == 0);
     723         [ +  - ]:          6 :         CU_ASSERT(subtask.scsi.length == SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3);
     724         [ +  - ]:          6 :         CU_ASSERT(subtask.scsi.ref == 0);
     725                 :            : 
     726                 :            :         /* Case2: Queue one task, and this task is partially executed */
     727         [ +  - ]:          6 :         task.scsi.ref = 1;
     728         [ +  - ]:          6 :         task.scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3;
     729         [ +  - ]:          6 :         task.current_data_offset = SPDK_BDEV_LARGE_BUF_MAX_SIZE;
     730   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     731                 :            : 
     732                 :            :         /* No slots for sub read tasks */
     733   [ +  -  +  - ]:          6 :         conn.data_in_cnt = g_iscsi.MaxLargeDataInPerConnection;
     734                 :          6 :         rc = _iscsi_conn_abort_queued_datain_task(&conn, &task);
     735                 :          6 :         CU_ASSERT(rc != 0);
     736   [ +  -  +  - ]:          6 :         CU_ASSERT(!TAILQ_EMPTY(&conn.queued_datain_tasks));
     737                 :            : 
     738                 :            :         /* have slots for sub read tasks */
     739         [ +  - ]:          6 :         conn.data_in_cnt = 0;
     740                 :          6 :         rc = _iscsi_conn_abort_queued_datain_task(&conn, &task);
     741                 :          6 :         CU_ASSERT(rc == 0);
     742         [ +  - ]:          6 :         CU_ASSERT(task.current_data_offset == SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3);
     743         [ +  - ]:          6 :         CU_ASSERT(task.scsi.ref == 2);
     744   [ +  -  +  - ]:          6 :         CU_ASSERT(TAILQ_FIRST(&task.subtask_list) == &subtask);
     745         [ +  - ]:          6 :         CU_ASSERT(subtask.scsi.offset == SPDK_BDEV_LARGE_BUF_MAX_SIZE);
     746         [ +  - ]:          6 :         CU_ASSERT(subtask.scsi.length == SPDK_BDEV_LARGE_BUF_MAX_SIZE * 2);
     747         [ +  - ]:          6 :         CU_ASSERT(subtask.scsi.ref == 1);
     748                 :            : 
     749                 :          6 :         g_new_task = NULL;
     750                 :          6 : }
     751                 :            : 
     752                 :            : static bool
     753                 :         66 : datain_task_is_queued(struct spdk_iscsi_conn *conn,
     754                 :            :                       struct spdk_iscsi_task *task)
     755                 :            : {
     756                 :         11 :         struct spdk_iscsi_task *tmp;
     757                 :            : 
     758   [ +  +  +  -  :        210 :         TAILQ_FOREACH(tmp, &conn->queued_datain_tasks, link) {
          +  -  +  +  +  
             -  +  -  +  
                      - ]
     759         [ +  + ]:        192 :                 if (tmp == task) {
     760                 :         48 :                         return true;
     761                 :            :                 }
     762                 :         24 :         }
     763                 :         18 :         return false;
     764                 :         11 : }
     765                 :            : static void
     766                 :          6 : abort_queued_datain_tasks_test(void)
     767                 :            : {
     768                 :          6 :         struct spdk_iscsi_conn conn = {};
     769                 :          6 :         struct spdk_iscsi_task task1 = {}, task2 = {}, task3 = {}, task4 = {}, task5 = {}, task6 = {};
     770                 :          6 :         struct spdk_iscsi_task subtask = {};
     771                 :          6 :         struct spdk_iscsi_pdu pdu1 = {}, pdu2 = {}, pdu3 = {}, pdu4 = {}, pdu5 = {}, pdu6 = {};
     772                 :          6 :         struct spdk_iscsi_pdu mgmt_pdu1 = {}, mgmt_pdu2 = {};
     773                 :          6 :         struct spdk_scsi_lun lun1 = {}, lun2 = {};
     774                 :          1 :         uint32_t alloc_cmd_sn;
     775                 :          1 :         struct iscsi_bhs_scsi_req *scsi_req;
     776                 :          1 :         int rc;
     777                 :          6 :         struct spdk_iscsi_sess sess = {};
     778                 :            : 
     779   [ +  -  +  -  :          6 :         TAILQ_INIT(&conn.queued_datain_tasks);
          +  -  +  -  +  
                      - ]
     780         [ +  - ]:          6 :         conn.data_in_cnt = 0;
     781                 :            : 
     782         [ +  - ]:          6 :         conn.sess = &sess;
     783   [ +  -  +  -  :          6 :         conn.sess->DataSequenceInOrder = true;
                   +  - ]
     784                 :            : 
     785                 :          6 :         g_new_task = &subtask;
     786                 :            : 
     787                 :          6 :         alloc_cmd_sn = 88;
     788                 :            : 
     789         [ +  - ]:          6 :         pdu1.cmd_sn = alloc_cmd_sn;
     790                 :          6 :         alloc_cmd_sn++;
     791                 :          6 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu1.bhs;
     792         [ +  - ]:          6 :         scsi_req->read_bit = 1;
     793         [ +  - ]:          6 :         task1.scsi.ref = 1;
     794         [ +  - ]:          6 :         task1.current_data_offset = 0;
     795         [ +  - ]:          6 :         task1.scsi.transfer_len = 512;
     796         [ +  - ]:          6 :         task1.scsi.lun = &lun1;
     797                 :          6 :         iscsi_task_set_pdu(&task1, &pdu1);
     798   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task1, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     799                 :            : 
     800         [ +  - ]:          6 :         pdu2.cmd_sn = alloc_cmd_sn;
     801                 :          6 :         alloc_cmd_sn++;
     802                 :          6 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu2.bhs;
     803         [ +  - ]:          6 :         scsi_req->read_bit = 1;
     804         [ +  - ]:          6 :         task2.scsi.ref = 1;
     805         [ +  - ]:          6 :         task2.current_data_offset = 0;
     806         [ +  - ]:          6 :         task2.scsi.transfer_len = 512;
     807         [ +  - ]:          6 :         task2.scsi.lun = &lun2;
     808                 :          6 :         iscsi_task_set_pdu(&task2, &pdu2);
     809   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task2, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     810                 :            : 
     811         [ +  - ]:          6 :         mgmt_pdu1.cmd_sn = alloc_cmd_sn;
     812                 :          6 :         alloc_cmd_sn++;
     813                 :            : 
     814         [ +  - ]:          6 :         pdu3.cmd_sn = alloc_cmd_sn;
     815                 :          6 :         alloc_cmd_sn++;
     816                 :          6 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu3.bhs;
     817         [ +  - ]:          6 :         scsi_req->read_bit = 1;
     818         [ +  - ]:          6 :         task3.scsi.ref = 1;
     819         [ +  - ]:          6 :         task3.current_data_offset = 0;
     820         [ +  - ]:          6 :         task3.scsi.transfer_len = 512;
     821         [ +  - ]:          6 :         task3.scsi.lun = &lun1;
     822                 :          6 :         iscsi_task_set_pdu(&task3, &pdu3);
     823   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task3, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     824                 :            : 
     825         [ +  - ]:          6 :         pdu4.cmd_sn = alloc_cmd_sn;
     826                 :          6 :         alloc_cmd_sn++;
     827                 :          6 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu4.bhs;
     828         [ +  - ]:          6 :         scsi_req->read_bit = 1;
     829         [ +  - ]:          6 :         task4.scsi.ref = 1;
     830         [ +  - ]:          6 :         task4.current_data_offset = 0;
     831         [ +  - ]:          6 :         task4.scsi.transfer_len = 512;
     832         [ +  - ]:          6 :         task4.scsi.lun = &lun2;
     833                 :          6 :         iscsi_task_set_pdu(&task4, &pdu4);
     834   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task4, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     835                 :            : 
     836         [ +  - ]:          6 :         pdu5.cmd_sn = alloc_cmd_sn;
     837                 :          6 :         alloc_cmd_sn++;
     838                 :          6 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu5.bhs;
     839         [ +  - ]:          6 :         scsi_req->read_bit = 1;
     840         [ +  - ]:          6 :         task5.scsi.ref = 1;
     841         [ +  - ]:          6 :         task5.current_data_offset = 0;
     842         [ +  - ]:          6 :         task5.scsi.transfer_len = 512;
     843         [ +  - ]:          6 :         task5.scsi.lun = &lun1;
     844                 :          6 :         iscsi_task_set_pdu(&task5, &pdu5);
     845   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task5, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     846                 :            : 
     847         [ +  - ]:          6 :         mgmt_pdu2.cmd_sn = alloc_cmd_sn;
     848                 :          6 :         alloc_cmd_sn++;
     849                 :            : 
     850         [ +  - ]:          6 :         pdu6.cmd_sn = alloc_cmd_sn;
     851                 :          6 :         alloc_cmd_sn++;
     852                 :          6 :         scsi_req = (struct iscsi_bhs_scsi_req *)&pdu6.bhs;
     853         [ +  - ]:          6 :         scsi_req->read_bit = 1;
     854         [ +  - ]:          6 :         task6.scsi.ref = 1;
     855         [ +  - ]:          6 :         task6.current_data_offset = 0;
     856         [ +  - ]:          6 :         task6.scsi.transfer_len = 512;
     857         [ +  - ]:          6 :         task6.scsi.lun = &lun2;
     858                 :          6 :         iscsi_task_set_pdu(&task6, &pdu6);
     859   [ +  -  +  -  :          6 :         TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, &task6, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     860                 :            : 
     861                 :          6 :         rc = iscsi_conn_abort_queued_datain_tasks(&conn, &lun1, &mgmt_pdu1);
     862                 :          6 :         CU_ASSERT(rc == 0);
     863                 :          6 :         CU_ASSERT(!datain_task_is_queued(&conn, &task1));
     864                 :          6 :         CU_ASSERT(datain_task_is_queued(&conn, &task2));
     865                 :          6 :         CU_ASSERT(datain_task_is_queued(&conn, &task3));
     866                 :          6 :         CU_ASSERT(datain_task_is_queued(&conn, &task4));
     867                 :          6 :         CU_ASSERT(datain_task_is_queued(&conn, &task5));
     868                 :          6 :         CU_ASSERT(datain_task_is_queued(&conn, &task6));
     869                 :            : 
     870                 :          6 :         rc = iscsi_conn_abort_queued_datain_tasks(&conn, &lun2, &mgmt_pdu2);
     871                 :          6 :         CU_ASSERT(rc == 0);
     872                 :          6 :         CU_ASSERT(!datain_task_is_queued(&conn, &task2));
     873                 :          6 :         CU_ASSERT(datain_task_is_queued(&conn, &task3));
     874                 :          6 :         CU_ASSERT(!datain_task_is_queued(&conn, &task4));
     875                 :          6 :         CU_ASSERT(datain_task_is_queued(&conn, &task5));
     876                 :          6 :         CU_ASSERT(datain_task_is_queued(&conn, &task6));
     877                 :            : 
     878         [ +  - ]:          6 :         CU_ASSERT(task1.scsi.ref == 0);
     879         [ +  - ]:          6 :         CU_ASSERT(task2.scsi.ref == 0);
     880         [ +  - ]:          6 :         CU_ASSERT(task3.scsi.ref == 1);
     881         [ +  - ]:          6 :         CU_ASSERT(task4.scsi.ref == 0);
     882         [ +  - ]:          6 :         CU_ASSERT(task5.scsi.ref == 1);
     883         [ +  - ]:          6 :         CU_ASSERT(task6.scsi.ref == 1);
     884         [ +  - ]:          6 :         CU_ASSERT(subtask.scsi.ref == 0);
     885                 :            : 
     886                 :          6 :         g_new_task = NULL;
     887                 :          6 : }
     888                 :            : 
     889                 :            : int
     890                 :          6 : main(int argc, char **argv)
     891                 :            : {
     892                 :          6 :         CU_pSuite       suite = NULL;
     893                 :          1 :         unsigned int    num_failures;
     894                 :            : 
     895                 :          6 :         CU_initialize_registry();
     896                 :            : 
     897                 :          6 :         suite = CU_add_suite("conn_suite", NULL, NULL);
     898                 :            : 
     899                 :          6 :         CU_ADD_TEST(suite, read_task_split_in_order_case);
     900                 :          6 :         CU_ADD_TEST(suite, read_task_split_reverse_order_case);
     901                 :          6 :         CU_ADD_TEST(suite, propagate_scsi_error_status_for_split_read_tasks);
     902                 :          6 :         CU_ADD_TEST(suite, process_non_read_task_completion_test);
     903                 :          6 :         CU_ADD_TEST(suite, free_tasks_on_connection);
     904                 :          6 :         CU_ADD_TEST(suite, free_tasks_with_queued_datain);
     905                 :          6 :         CU_ADD_TEST(suite, abort_queued_datain_task_test);
     906                 :          6 :         CU_ADD_TEST(suite, abort_queued_datain_tasks_test);
     907                 :            : 
     908                 :          6 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
     909                 :          6 :         CU_cleanup_registry();
     910                 :          7 :         return num_failures;
     911                 :          1 : }

Generated by: LCOV version 1.14