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