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 "spdk_cunit.h" 37 38 #include "scsi/task.c" 39 #include "scsi/lun.c" 40 41 #include "spdk_internal/mock.h" 42 43 /* Unit test bdev mockup */ 44 struct spdk_bdev { 45 int x; 46 }; 47 48 SPDK_LOG_REGISTER_COMPONENT("scsi", SPDK_LOG_SCSI) 49 50 struct spdk_scsi_globals g_spdk_scsi; 51 52 static bool g_lun_execute_fail = false; 53 static int g_lun_execute_status = SPDK_SCSI_TASK_PENDING; 54 static uint32_t g_task_count = 0; 55 56 struct spdk_poller * 57 spdk_poller_register(spdk_poller_fn fn, 58 void *arg, 59 uint64_t period_microseconds) 60 { 61 return NULL; 62 } 63 64 void 65 spdk_poller_unregister(struct spdk_poller **ppoller) 66 { 67 } 68 69 void 70 spdk_thread_send_msg(const struct spdk_thread *thread, spdk_thread_fn fn, void *ctx) 71 { 72 } 73 74 void spdk_trace_record(uint16_t tpoint_id, uint16_t poller_id, uint32_t size, 75 uint64_t object_id, uint64_t arg1) 76 { 77 } 78 79 static void 80 spdk_lun_ut_cpl_task(struct spdk_scsi_task *task) 81 { 82 SPDK_CU_ASSERT_FATAL(g_task_count > 0); 83 g_task_count--; 84 } 85 86 static void 87 spdk_lun_ut_free_task(struct spdk_scsi_task *task) 88 { 89 } 90 91 static void 92 ut_init_task(struct spdk_scsi_task *task) 93 { 94 memset(task, 0, sizeof(*task)); 95 spdk_scsi_task_construct(task, spdk_lun_ut_cpl_task, 96 spdk_lun_ut_free_task); 97 g_task_count++; 98 } 99 100 void * 101 spdk_dma_malloc(size_t size, size_t align, uint64_t *phys_addr) 102 { 103 void *buf = malloc(size); 104 if (phys_addr) { 105 *phys_addr = (uint64_t)buf; 106 } 107 return buf; 108 } 109 110 void * 111 spdk_dma_zmalloc(size_t size, size_t align, uint64_t *phys_addr) 112 { 113 void *buf = calloc(size, 1); 114 if (phys_addr) { 115 *phys_addr = (uint64_t)buf; 116 } 117 return buf; 118 } 119 120 void 121 spdk_dma_free(void *buf) 122 { 123 free(buf); 124 } 125 126 void 127 spdk_bdev_free_io(struct spdk_bdev_io *bdev_io) 128 { 129 CU_ASSERT(0); 130 } 131 132 int 133 spdk_bdev_open(struct spdk_bdev *bdev, bool write, spdk_bdev_remove_cb_t remove_cb, 134 void *remove_ctx, struct spdk_bdev_desc **desc) 135 { 136 return 0; 137 } 138 139 void 140 spdk_bdev_close(struct spdk_bdev_desc *desc) 141 { 142 } 143 144 const char * 145 spdk_bdev_get_name(const struct spdk_bdev *bdev) 146 { 147 return "test"; 148 } 149 150 void spdk_scsi_dev_queue_mgmt_task(struct spdk_scsi_dev *dev, 151 struct spdk_scsi_task *task, 152 enum spdk_scsi_task_func func) 153 { 154 } 155 156 void spdk_scsi_dev_delete_lun(struct spdk_scsi_dev *dev, 157 struct spdk_scsi_lun *lun) 158 { 159 return; 160 } 161 162 int 163 spdk_bdev_scsi_reset(struct spdk_scsi_task *task) 164 { 165 return 0; 166 } 167 168 int 169 spdk_bdev_scsi_execute(struct spdk_scsi_task *task) 170 { 171 if (g_lun_execute_fail) { 172 return -EINVAL; 173 } else { 174 task->status = SPDK_SCSI_STATUS_GOOD; 175 176 if (g_lun_execute_status == SPDK_SCSI_TASK_PENDING) { 177 return g_lun_execute_status; 178 } else if (g_lun_execute_status == SPDK_SCSI_TASK_COMPLETE) { 179 return g_lun_execute_status; 180 } else { 181 return 0; 182 } 183 } 184 } 185 186 struct spdk_io_channel * 187 spdk_bdev_get_io_channel(struct spdk_bdev_desc *desc) 188 { 189 return NULL; 190 } 191 192 void 193 spdk_put_io_channel(struct spdk_io_channel *ch) 194 { 195 } 196 197 DEFINE_STUB(spdk_io_channel_get_thread, struct spdk_thread *, (struct spdk_io_channel *ch), NULL) 198 DEFINE_STUB(spdk_get_thread, struct spdk_thread *, (void), NULL) 199 200 static _spdk_scsi_lun * 201 lun_construct(void) 202 { 203 struct spdk_scsi_lun *lun; 204 struct spdk_bdev bdev; 205 206 lun = spdk_scsi_lun_construct(&bdev, NULL, NULL); 207 208 SPDK_CU_ASSERT_FATAL(lun != NULL); 209 return lun; 210 } 211 212 static void 213 lun_destruct(struct spdk_scsi_lun *lun) 214 { 215 /* LUN will defer its removal if there are any unfinished tasks */ 216 SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&lun->tasks)); 217 218 spdk_scsi_lun_destruct(lun); 219 } 220 221 static void 222 lun_task_mgmt_execute_null_task(void) 223 { 224 int rc; 225 226 rc = spdk_scsi_lun_task_mgmt_execute(NULL, SPDK_SCSI_TASK_FUNC_ABORT_TASK); 227 228 /* returns -1 since we passed NULL for the task */ 229 CU_ASSERT_TRUE(rc < 0); 230 CU_ASSERT_EQUAL(g_task_count, 0); 231 } 232 233 static void 234 lun_task_mgmt_execute_abort_task_null_lun_failure(void) 235 { 236 struct spdk_scsi_task mgmt_task = { 0 }; 237 struct spdk_scsi_port initiator_port = { 0 }; 238 int rc; 239 240 ut_init_task(&mgmt_task); 241 mgmt_task.lun = NULL; 242 mgmt_task.initiator_port = &initiator_port; 243 244 rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task, SPDK_SCSI_TASK_FUNC_ABORT_TASK); 245 246 /* returns -1 since we passed NULL for LUN */ 247 CU_ASSERT_TRUE(rc < 0); 248 CU_ASSERT_EQUAL(g_task_count, 0); 249 } 250 251 static void 252 lun_task_mgmt_execute_abort_task_not_supported(void) 253 { 254 struct spdk_scsi_lun *lun; 255 struct spdk_scsi_task task = { 0 }; 256 struct spdk_scsi_task mgmt_task = { 0 }; 257 struct spdk_scsi_port initiator_port = { 0 }; 258 struct spdk_scsi_dev dev = { 0 }; 259 uint8_t cdb[6] = { 0 }; 260 int rc; 261 262 lun = lun_construct(); 263 lun->dev = &dev; 264 265 ut_init_task(&mgmt_task); 266 mgmt_task.lun = lun; 267 mgmt_task.initiator_port = &initiator_port; 268 269 /* Params to add regular task to the lun->tasks */ 270 ut_init_task(&task); 271 task.lun = lun; 272 task.cdb = cdb; 273 274 spdk_scsi_lun_execute_task(lun, &task); 275 276 /* task should now be on the tasks list */ 277 CU_ASSERT(!TAILQ_EMPTY(&lun->tasks)); 278 279 rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task, SPDK_SCSI_TASK_FUNC_ABORT_TASK); 280 281 /* returns -1 since task abort is not supported */ 282 CU_ASSERT_TRUE(rc < 0); 283 CU_ASSERT(mgmt_task.response == SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED); 284 285 /* task is still on the tasks list */ 286 CU_ASSERT_EQUAL(g_task_count, 1); 287 288 spdk_scsi_lun_complete_task(lun, &task); 289 CU_ASSERT_EQUAL(g_task_count, 0); 290 291 lun_destruct(lun); 292 } 293 294 static void 295 lun_task_mgmt_execute_abort_task_all_null_lun_failure(void) 296 { 297 struct spdk_scsi_task mgmt_task = { 0 }; 298 struct spdk_scsi_port initiator_port = { 0 }; 299 int rc; 300 301 ut_init_task(&mgmt_task); 302 mgmt_task.lun = NULL; 303 mgmt_task.initiator_port = &initiator_port; 304 305 rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task, SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET); 306 307 /* Returns -1 since we passed NULL for lun */ 308 CU_ASSERT_TRUE(rc < 0); 309 310 CU_ASSERT_EQUAL(g_task_count, 0); 311 } 312 313 static void 314 lun_task_mgmt_execute_abort_task_all_not_supported(void) 315 { 316 struct spdk_scsi_lun *lun; 317 struct spdk_scsi_task task = { 0 }; 318 struct spdk_scsi_task mgmt_task = { 0 }; 319 struct spdk_scsi_port initiator_port = { 0 }; 320 struct spdk_scsi_dev dev = { 0 }; 321 int rc; 322 uint8_t cdb[6] = { 0 }; 323 324 lun = lun_construct(); 325 lun->dev = &dev; 326 327 ut_init_task(&mgmt_task); 328 mgmt_task.lun = lun; 329 mgmt_task.initiator_port = &initiator_port; 330 331 /* Params to add regular task to the lun->tasks */ 332 ut_init_task(&task); 333 task.initiator_port = &initiator_port; 334 task.lun = lun; 335 task.cdb = cdb; 336 337 spdk_scsi_lun_execute_task(lun, &task); 338 339 /* task should now be on the tasks list */ 340 CU_ASSERT(!TAILQ_EMPTY(&lun->tasks)); 341 342 rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task, SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET); 343 344 /* returns -1 since task abort is not supported */ 345 CU_ASSERT_TRUE(rc < 0); 346 CU_ASSERT(mgmt_task.response == SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED); 347 348 /* task is still on the tasks list */ 349 CU_ASSERT_EQUAL(g_task_count, 1); 350 351 spdk_scsi_lun_complete_task(lun, &task); 352 353 CU_ASSERT_EQUAL(g_task_count, 0); 354 355 lun_destruct(lun); 356 } 357 358 static void 359 lun_task_mgmt_execute_lun_reset_failure(void) 360 { 361 struct spdk_scsi_task mgmt_task = { 0 }; 362 int rc; 363 364 ut_init_task(&mgmt_task); 365 mgmt_task.lun = NULL; 366 367 rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task, SPDK_SCSI_TASK_FUNC_LUN_RESET); 368 369 /* Returns -1 since we passed NULL for lun */ 370 CU_ASSERT_TRUE(rc < 0); 371 372 CU_ASSERT_EQUAL(g_task_count, 0); 373 } 374 375 static void 376 lun_task_mgmt_execute_lun_reset(void) 377 { 378 struct spdk_scsi_lun *lun; 379 struct spdk_scsi_task mgmt_task = { 0 }; 380 struct spdk_scsi_dev dev = { 0 }; 381 int rc; 382 383 lun = lun_construct(); 384 lun->dev = &dev; 385 386 ut_init_task(&mgmt_task); 387 mgmt_task.lun = lun; 388 389 rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task, SPDK_SCSI_TASK_FUNC_LUN_RESET); 390 391 /* Returns success */ 392 CU_ASSERT_EQUAL(rc, 0); 393 394 lun_destruct(lun); 395 396 /* task is still on the tasks list */ 397 CU_ASSERT_EQUAL(g_task_count, 1); 398 g_task_count = 0; 399 } 400 401 static void 402 lun_task_mgmt_execute_invalid_case(void) 403 { 404 struct spdk_scsi_lun *lun; 405 struct spdk_scsi_task mgmt_task = { 0 }; 406 struct spdk_scsi_dev dev = { 0 }; 407 int rc; 408 409 lun = lun_construct(); 410 lun->dev = &dev; 411 412 ut_init_task(&mgmt_task); 413 /* Pass an invalid value to the switch statement */ 414 rc = spdk_scsi_lun_task_mgmt_execute(&mgmt_task, 5); 415 416 /* Returns -1 on passing an invalid value to the switch case */ 417 CU_ASSERT_TRUE(rc < 0); 418 419 lun_destruct(lun); 420 421 CU_ASSERT_EQUAL(g_task_count, 0); 422 } 423 424 static void 425 lun_append_task_null_lun_task_cdb_spc_inquiry(void) 426 { 427 struct spdk_scsi_task task = { 0 }; 428 uint8_t cdb[6] = { 0 }; 429 430 ut_init_task(&task); 431 task.cdb = cdb; 432 task.cdb[0] = SPDK_SPC_INQUIRY; 433 /* alloc_len >= 4096 */ 434 task.cdb[3] = 0xFF; 435 task.cdb[4] = 0xFF; 436 task.lun = NULL; 437 438 spdk_scsi_task_process_null_lun(&task); 439 440 CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_GOOD); 441 442 spdk_scsi_task_put(&task); 443 444 /* spdk_scsi_task_process_null_lun() does not call cpl_fn */ 445 CU_ASSERT_EQUAL(g_task_count, 1); 446 g_task_count = 0; 447 } 448 449 static void 450 lun_append_task_null_lun_alloc_len_lt_4096(void) 451 { 452 struct spdk_scsi_task task = { 0 }; 453 uint8_t cdb[6] = { 0 }; 454 455 ut_init_task(&task); 456 task.cdb = cdb; 457 task.cdb[0] = SPDK_SPC_INQUIRY; 458 /* alloc_len < 4096 */ 459 task.cdb[3] = 0; 460 task.cdb[4] = 0; 461 /* alloc_len is set to a minimal value of 4096 462 * Hence, buf of size 4096 is allocated */ 463 spdk_scsi_task_process_null_lun(&task); 464 465 CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_GOOD); 466 467 spdk_scsi_task_put(&task); 468 469 /* spdk_scsi_task_process_null_lun() does not call cpl_fn */ 470 CU_ASSERT_EQUAL(g_task_count, 1); 471 g_task_count = 0; 472 } 473 474 static void 475 lun_append_task_null_lun_not_supported(void) 476 { 477 struct spdk_scsi_task task = { 0 }; 478 uint8_t cdb[6] = { 0 }; 479 480 ut_init_task(&task); 481 task.cdb = cdb; 482 task.lun = NULL; 483 484 spdk_scsi_task_process_null_lun(&task); 485 486 CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION); 487 /* LUN not supported; task's data transferred should be 0 */ 488 CU_ASSERT_EQUAL(task.data_transferred, 0); 489 490 /* spdk_scsi_task_process_null_lun() does not call cpl_fn */ 491 CU_ASSERT_EQUAL(g_task_count, 1); 492 g_task_count = 0; 493 } 494 495 static void 496 lun_execute_scsi_task_pending(void) 497 { 498 struct spdk_scsi_lun *lun; 499 struct spdk_scsi_task task = { 0 }; 500 struct spdk_scsi_dev dev = { 0 }; 501 502 lun = lun_construct(); 503 504 ut_init_task(&task); 505 task.lun = lun; 506 lun->dev = &dev; 507 508 g_lun_execute_fail = false; 509 g_lun_execute_status = SPDK_SCSI_TASK_PENDING; 510 511 /* the tasks list should still be empty since it has not been 512 executed yet 513 */ 514 CU_ASSERT(TAILQ_EMPTY(&lun->tasks)); 515 516 spdk_scsi_lun_execute_task(lun, &task); 517 518 /* Assert the task has been successfully added to the tasks queue */ 519 CU_ASSERT(!TAILQ_EMPTY(&lun->tasks)); 520 521 /* task is still on the tasks list */ 522 CU_ASSERT_EQUAL(g_task_count, 1); 523 524 /* Need to complete task so LUN might be removed right now */ 525 spdk_scsi_lun_complete_task(lun, &task); 526 527 CU_ASSERT_EQUAL(g_task_count, 0); 528 529 lun_destruct(lun); 530 } 531 532 static void 533 lun_execute_scsi_task_complete(void) 534 { 535 struct spdk_scsi_lun *lun; 536 struct spdk_scsi_task task = { 0 }; 537 struct spdk_scsi_dev dev = { 0 }; 538 539 lun = lun_construct(); 540 541 ut_init_task(&task); 542 task.lun = lun; 543 lun->dev = &dev; 544 545 g_lun_execute_fail = false; 546 g_lun_execute_status = SPDK_SCSI_TASK_COMPLETE; 547 548 /* the tasks list should still be empty since it has not been 549 executed yet 550 */ 551 CU_ASSERT(TAILQ_EMPTY(&lun->tasks)); 552 553 spdk_scsi_lun_execute_task(lun, &task); 554 555 /* Assert the task has not been added to the tasks queue */ 556 CU_ASSERT(TAILQ_EMPTY(&lun->tasks)); 557 558 lun_destruct(lun); 559 560 CU_ASSERT_EQUAL(g_task_count, 0); 561 } 562 563 static void 564 lun_destruct_success(void) 565 { 566 struct spdk_scsi_lun *lun; 567 568 lun = lun_construct(); 569 570 spdk_scsi_lun_destruct(lun); 571 572 CU_ASSERT_EQUAL(g_task_count, 0); 573 } 574 575 static void 576 lun_construct_null_ctx(void) 577 { 578 struct spdk_scsi_lun *lun; 579 580 lun = spdk_scsi_lun_construct(NULL, NULL, NULL); 581 582 /* lun should be NULL since we passed NULL for the ctx pointer. */ 583 CU_ASSERT(lun == NULL); 584 CU_ASSERT_EQUAL(g_task_count, 0); 585 } 586 587 static void 588 lun_construct_success(void) 589 { 590 struct spdk_scsi_lun *lun = lun_construct(); 591 592 lun_destruct(lun); 593 594 CU_ASSERT_EQUAL(g_task_count, 0); 595 } 596 597 int 598 main(int argc, char **argv) 599 { 600 CU_pSuite suite = NULL; 601 unsigned int num_failures; 602 int rc; 603 604 if (CU_initialize_registry() != CUE_SUCCESS) { 605 return CU_get_error(); 606 } 607 608 suite = CU_add_suite("lun_suite", NULL, NULL); 609 if (suite == NULL) { 610 CU_cleanup_registry(); 611 return CU_get_error(); 612 } 613 614 if ( 615 CU_add_test(suite, "task management - null task failure", 616 lun_task_mgmt_execute_null_task) == NULL 617 || CU_add_test(suite, "task management abort task - null lun failure", 618 lun_task_mgmt_execute_abort_task_null_lun_failure) == NULL 619 || CU_add_test(suite, "task management abort task - not supported", 620 lun_task_mgmt_execute_abort_task_not_supported) == NULL 621 || CU_add_test(suite, "task management abort task set - null lun failure", 622 lun_task_mgmt_execute_abort_task_all_null_lun_failure) == NULL 623 || CU_add_test(suite, "task management abort task set - success", 624 lun_task_mgmt_execute_abort_task_all_not_supported) == NULL 625 || CU_add_test(suite, "task management - lun reset failure", 626 lun_task_mgmt_execute_lun_reset_failure) == NULL 627 || CU_add_test(suite, "task management - lun reset success", 628 lun_task_mgmt_execute_lun_reset) == NULL 629 || CU_add_test(suite, "task management - invalid option", 630 lun_task_mgmt_execute_invalid_case) == NULL 631 || CU_add_test(suite, "append task - null lun SPDK_SPC_INQUIRY", 632 lun_append_task_null_lun_task_cdb_spc_inquiry) == NULL 633 || CU_add_test(suite, "append task - allocated length less than 4096", 634 lun_append_task_null_lun_alloc_len_lt_4096) == NULL 635 || CU_add_test(suite, "append task - unsupported lun", 636 lun_append_task_null_lun_not_supported) == NULL 637 || CU_add_test(suite, "execute task - scsi task pending", 638 lun_execute_scsi_task_pending) == NULL 639 || CU_add_test(suite, "execute task - scsi task complete", 640 lun_execute_scsi_task_complete) == NULL 641 || CU_add_test(suite, "destruct task - success", lun_destruct_success) == NULL 642 || CU_add_test(suite, "construct - null ctx", lun_construct_null_ctx) == NULL 643 || CU_add_test(suite, "construct - success", lun_construct_success) == NULL 644 ) { 645 CU_cleanup_registry(); 646 return CU_get_error(); 647 } 648 649 CU_basic_set_mode(CU_BRM_VERBOSE); 650 CU_basic_run_tests(); 651 num_failures = CU_get_number_of_failures(); 652 653 if (argc > 1) { 654 rc = spdk_cunit_print_results(argv[1]); 655 if (rc != 0) { 656 CU_cleanup_registry(); 657 return rc; 658 } 659 } 660 661 CU_cleanup_registry(); 662 return num_failures; 663 } 664