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