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