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