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