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_cunit.h" 35 36 #include "common/lib/test_env.c" 37 #include "unit/lib/json_mock.c" 38 39 /* HACK: disable VTune integration so the unit test doesn't need VTune headers and libs to build */ 40 #undef SPDK_CONFIG_VTUNE 41 42 #include "bdev/bdev.c" 43 44 DEFINE_STUB(spdk_conf_find_section, struct spdk_conf_section *, (struct spdk_conf *cp, 45 const char *name), NULL); 46 DEFINE_STUB(spdk_conf_section_get_nmval, char *, 47 (struct spdk_conf_section *sp, const char *key, int idx1, int idx2), NULL); 48 DEFINE_STUB(spdk_conf_section_get_intval, int, (struct spdk_conf_section *sp, const char *key), -1); 49 50 static void 51 _bdev_send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx) 52 { 53 fn(ctx); 54 } 55 56 void 57 spdk_scsi_nvme_translate(const struct spdk_bdev_io *bdev_io, 58 int *sc, int *sk, int *asc, int *ascq) 59 { 60 } 61 62 static int 63 null_init(void) 64 { 65 return 0; 66 } 67 68 static int 69 null_clean(void) 70 { 71 return 0; 72 } 73 74 static int 75 stub_destruct(void *ctx) 76 { 77 return 0; 78 } 79 80 struct bdev_ut_channel { 81 TAILQ_HEAD(, spdk_bdev_io) outstanding_io; 82 uint32_t outstanding_io_count; 83 }; 84 85 static uint32_t g_bdev_ut_io_device; 86 static struct bdev_ut_channel *g_bdev_ut_channel; 87 88 static void 89 stub_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io) 90 { 91 struct bdev_ut_channel *ch = spdk_io_channel_get_ctx(_ch); 92 93 TAILQ_INSERT_TAIL(&ch->outstanding_io, bdev_io, module_link); 94 ch->outstanding_io_count++; 95 } 96 97 static uint32_t 98 stub_complete_io(uint32_t num_to_complete) 99 { 100 struct bdev_ut_channel *ch = g_bdev_ut_channel; 101 struct spdk_bdev_io *bdev_io; 102 uint32_t num_completed = 0; 103 104 while (num_completed < num_to_complete) { 105 if (TAILQ_EMPTY(&ch->outstanding_io)) { 106 break; 107 } 108 bdev_io = TAILQ_FIRST(&ch->outstanding_io); 109 TAILQ_REMOVE(&ch->outstanding_io, bdev_io, module_link); 110 ch->outstanding_io_count--; 111 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS); 112 num_completed++; 113 } 114 115 return num_completed; 116 } 117 118 static struct spdk_io_channel * 119 bdev_ut_get_io_channel(void *ctx) 120 { 121 return spdk_get_io_channel(&g_bdev_ut_io_device); 122 } 123 124 static struct spdk_bdev_fn_table fn_table = { 125 .destruct = stub_destruct, 126 .submit_request = stub_submit_request, 127 .get_io_channel = bdev_ut_get_io_channel, 128 }; 129 130 static int 131 bdev_ut_create_ch(void *io_device, void *ctx_buf) 132 { 133 struct bdev_ut_channel *ch = ctx_buf; 134 135 CU_ASSERT(g_bdev_ut_channel == NULL); 136 g_bdev_ut_channel = ch; 137 138 TAILQ_INIT(&ch->outstanding_io); 139 ch->outstanding_io_count = 0; 140 return 0; 141 } 142 143 static void 144 bdev_ut_destroy_ch(void *io_device, void *ctx_buf) 145 { 146 CU_ASSERT(g_bdev_ut_channel != NULL); 147 g_bdev_ut_channel = NULL; 148 } 149 150 static int 151 bdev_ut_module_init(void) 152 { 153 spdk_io_device_register(&g_bdev_ut_io_device, bdev_ut_create_ch, bdev_ut_destroy_ch, 154 sizeof(struct bdev_ut_channel)); 155 return 0; 156 } 157 158 static void 159 bdev_ut_module_fini(void) 160 { 161 } 162 163 struct spdk_bdev_module bdev_ut_if = { 164 .name = "bdev_ut", 165 .module_init = bdev_ut_module_init, 166 .module_fini = bdev_ut_module_fini, 167 }; 168 169 static void vbdev_ut_examine(struct spdk_bdev *bdev); 170 171 static int 172 vbdev_ut_module_init(void) 173 { 174 return 0; 175 } 176 177 static void 178 vbdev_ut_module_fini(void) 179 { 180 } 181 182 struct spdk_bdev_module vbdev_ut_if = { 183 .name = "vbdev_ut", 184 .examine = vbdev_ut_examine, 185 .module_init = vbdev_ut_module_init, 186 .module_fini = vbdev_ut_module_fini, 187 }; 188 189 SPDK_BDEV_MODULE_REGISTER(&bdev_ut_if) 190 SPDK_BDEV_MODULE_REGISTER(&vbdev_ut_if) 191 192 static void 193 vbdev_ut_examine(struct spdk_bdev *bdev) 194 { 195 spdk_bdev_module_examine_done(&vbdev_ut_if); 196 } 197 198 static bool 199 is_vbdev(struct spdk_bdev *base, struct spdk_bdev *vbdev) 200 { 201 size_t i; 202 int found = 0; 203 204 for (i = 0; i < base->vbdevs_cnt; i++) { 205 found += base->vbdevs[i] == vbdev; 206 } 207 208 CU_ASSERT(found <= 1); 209 return !!found; 210 } 211 212 static bool 213 is_base_bdev(struct spdk_bdev *base, struct spdk_bdev *vbdev) 214 { 215 size_t i; 216 int found = 0; 217 218 for (i = 0; i < vbdev->base_bdevs_cnt; i++) { 219 found += vbdev->base_bdevs[i] == base; 220 } 221 222 CU_ASSERT(found <= 1); 223 return !!found; 224 } 225 226 static bool 227 check_base_and_vbdev(struct spdk_bdev *base, struct spdk_bdev *vbdev) 228 { 229 bool _is_vbdev = is_vbdev(base, vbdev); 230 bool _is_base = is_base_bdev(base, vbdev); 231 232 CU_ASSERT(_is_vbdev == _is_base); 233 234 return _is_base && _is_vbdev; 235 } 236 237 static struct spdk_bdev * 238 allocate_bdev(char *name) 239 { 240 struct spdk_bdev *bdev; 241 int rc; 242 243 bdev = calloc(1, sizeof(*bdev)); 244 SPDK_CU_ASSERT_FATAL(bdev != NULL); 245 246 bdev->name = name; 247 bdev->fn_table = &fn_table; 248 bdev->module = &bdev_ut_if; 249 bdev->blockcnt = 1; 250 251 rc = spdk_bdev_register(bdev); 252 CU_ASSERT(rc == 0); 253 CU_ASSERT(bdev->base_bdevs_cnt == 0); 254 CU_ASSERT(bdev->vbdevs_cnt == 0); 255 256 return bdev; 257 } 258 259 static struct spdk_bdev * 260 allocate_vbdev(char *name, struct spdk_bdev *base1, struct spdk_bdev *base2) 261 { 262 struct spdk_bdev *bdev; 263 struct spdk_bdev *array[2]; 264 int rc; 265 266 bdev = calloc(1, sizeof(*bdev)); 267 SPDK_CU_ASSERT_FATAL(bdev != NULL); 268 269 bdev->name = name; 270 bdev->fn_table = &fn_table; 271 bdev->module = &vbdev_ut_if; 272 273 /* vbdev must have at least one base bdev */ 274 CU_ASSERT(base1 != NULL); 275 276 array[0] = base1; 277 array[1] = base2; 278 279 rc = spdk_vbdev_register(bdev, array, base2 == NULL ? 1 : 2); 280 CU_ASSERT(rc == 0); 281 CU_ASSERT(bdev->base_bdevs_cnt > 0); 282 CU_ASSERT(bdev->vbdevs_cnt == 0); 283 284 CU_ASSERT(check_base_and_vbdev(base1, bdev) == true); 285 286 if (base2) { 287 CU_ASSERT(check_base_and_vbdev(base2, bdev) == true); 288 } 289 290 return bdev; 291 } 292 293 static void 294 free_bdev(struct spdk_bdev *bdev) 295 { 296 spdk_bdev_unregister(bdev, NULL, NULL); 297 memset(bdev, 0xFF, sizeof(*bdev)); 298 free(bdev); 299 } 300 301 static void 302 free_vbdev(struct spdk_bdev *bdev) 303 { 304 CU_ASSERT(bdev->base_bdevs_cnt != 0); 305 spdk_bdev_unregister(bdev, NULL, NULL); 306 memset(bdev, 0xFF, sizeof(*bdev)); 307 free(bdev); 308 } 309 310 static void 311 get_device_stat_cb(struct spdk_bdev *bdev, struct spdk_bdev_io_stat *stat, void *cb_arg, int rc) 312 { 313 const char *bdev_name; 314 315 CU_ASSERT(bdev != NULL); 316 CU_ASSERT(rc == 0); 317 bdev_name = spdk_bdev_get_name(bdev); 318 CU_ASSERT_STRING_EQUAL(bdev_name, "bdev0"); 319 320 free(stat); 321 free_bdev(bdev); 322 } 323 324 static void 325 get_device_stat_test(void) 326 { 327 struct spdk_bdev *bdev; 328 struct spdk_bdev_io_stat *stat; 329 330 bdev = allocate_bdev("bdev0"); 331 stat = calloc(1, sizeof(struct spdk_bdev_io_stat)); 332 if (stat == NULL) { 333 free_bdev(bdev); 334 return; 335 } 336 spdk_bdev_get_device_stat(bdev, stat, get_device_stat_cb, NULL); 337 } 338 339 static void 340 open_write_test(void) 341 { 342 struct spdk_bdev *bdev[9]; 343 struct spdk_bdev_desc *desc[9] = {}; 344 int rc; 345 346 /* 347 * Create a tree of bdevs to test various open w/ write cases. 348 * 349 * bdev0 through bdev3 are physical block devices, such as NVMe 350 * namespaces or Ceph block devices. 351 * 352 * bdev4 is a virtual bdev with multiple base bdevs. This models 353 * caching or RAID use cases. 354 * 355 * bdev5 through bdev7 are all virtual bdevs with the same base 356 * bdev (except bdev7). This models partitioning or logical volume 357 * use cases. 358 * 359 * bdev7 is a virtual bdev with multiple base bdevs. One of base bdevs 360 * (bdev2) is shared with other virtual bdevs: bdev5 and bdev6. This 361 * models caching, RAID, partitioning or logical volumes use cases. 362 * 363 * bdev8 is a virtual bdev with multiple base bdevs, but these 364 * base bdevs are themselves virtual bdevs. 365 * 366 * bdev8 367 * | 368 * +----------+ 369 * | | 370 * bdev4 bdev5 bdev6 bdev7 371 * | | | | 372 * +---+---+ +---+ + +---+---+ 373 * | | \ | / \ 374 * bdev0 bdev1 bdev2 bdev3 375 */ 376 377 bdev[0] = allocate_bdev("bdev0"); 378 rc = spdk_bdev_module_claim_bdev(bdev[0], NULL, &bdev_ut_if); 379 CU_ASSERT(rc == 0); 380 381 bdev[1] = allocate_bdev("bdev1"); 382 rc = spdk_bdev_module_claim_bdev(bdev[1], NULL, &bdev_ut_if); 383 CU_ASSERT(rc == 0); 384 385 bdev[2] = allocate_bdev("bdev2"); 386 rc = spdk_bdev_module_claim_bdev(bdev[2], NULL, &bdev_ut_if); 387 CU_ASSERT(rc == 0); 388 389 bdev[3] = allocate_bdev("bdev3"); 390 rc = spdk_bdev_module_claim_bdev(bdev[3], NULL, &bdev_ut_if); 391 CU_ASSERT(rc == 0); 392 393 bdev[4] = allocate_vbdev("bdev4", bdev[0], bdev[1]); 394 rc = spdk_bdev_module_claim_bdev(bdev[4], NULL, &bdev_ut_if); 395 CU_ASSERT(rc == 0); 396 397 bdev[5] = allocate_vbdev("bdev5", bdev[2], NULL); 398 rc = spdk_bdev_module_claim_bdev(bdev[5], NULL, &bdev_ut_if); 399 CU_ASSERT(rc == 0); 400 401 bdev[6] = allocate_vbdev("bdev6", bdev[2], NULL); 402 403 bdev[7] = allocate_vbdev("bdev7", bdev[2], bdev[3]); 404 405 bdev[8] = allocate_vbdev("bdev8", bdev[4], bdev[5]); 406 407 /* Check tree */ 408 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[4]) == true); 409 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[5]) == false); 410 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[6]) == false); 411 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[7]) == false); 412 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[8]) == false); 413 414 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[4]) == true); 415 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[5]) == false); 416 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[6]) == false); 417 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[7]) == false); 418 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[8]) == false); 419 420 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[4]) == false); 421 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[5]) == true); 422 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[6]) == true); 423 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[7]) == true); 424 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[8]) == false); 425 426 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[4]) == false); 427 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[5]) == false); 428 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[6]) == false); 429 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[7]) == true); 430 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[8]) == false); 431 432 /* Open bdev0 read-only. This should succeed. */ 433 rc = spdk_bdev_open(bdev[0], false, NULL, NULL, &desc[0]); 434 CU_ASSERT(rc == 0); 435 CU_ASSERT(desc[0] != NULL); 436 spdk_bdev_close(desc[0]); 437 438 /* 439 * Open bdev1 read/write. This should fail since bdev1 has been claimed 440 * by a vbdev module. 441 */ 442 rc = spdk_bdev_open(bdev[1], true, NULL, NULL, &desc[1]); 443 CU_ASSERT(rc == -EPERM); 444 445 /* 446 * Open bdev4 read/write. This should fail since bdev3 has been claimed 447 * by a vbdev module. 448 */ 449 rc = spdk_bdev_open(bdev[4], true, NULL, NULL, &desc[4]); 450 CU_ASSERT(rc == -EPERM); 451 452 /* Open bdev4 read-only. This should succeed. */ 453 rc = spdk_bdev_open(bdev[4], false, NULL, NULL, &desc[4]); 454 CU_ASSERT(rc == 0); 455 CU_ASSERT(desc[4] != NULL); 456 spdk_bdev_close(desc[4]); 457 458 /* 459 * Open bdev8 read/write. This should succeed since it is a leaf 460 * bdev. 461 */ 462 rc = spdk_bdev_open(bdev[8], true, NULL, NULL, &desc[8]); 463 CU_ASSERT(rc == 0); 464 CU_ASSERT(desc[8] != NULL); 465 spdk_bdev_close(desc[8]); 466 467 /* 468 * Open bdev5 read/write. This should fail since bdev4 has been claimed 469 * by a vbdev module. 470 */ 471 rc = spdk_bdev_open(bdev[5], true, NULL, NULL, &desc[5]); 472 CU_ASSERT(rc == -EPERM); 473 474 /* Open bdev4 read-only. This should succeed. */ 475 rc = spdk_bdev_open(bdev[5], false, NULL, NULL, &desc[5]); 476 CU_ASSERT(rc == 0); 477 CU_ASSERT(desc[5] != NULL); 478 spdk_bdev_close(desc[5]); 479 480 free_vbdev(bdev[8]); 481 482 free_vbdev(bdev[5]); 483 free_vbdev(bdev[6]); 484 free_vbdev(bdev[7]); 485 486 free_vbdev(bdev[4]); 487 488 free_bdev(bdev[0]); 489 free_bdev(bdev[1]); 490 free_bdev(bdev[2]); 491 free_bdev(bdev[3]); 492 } 493 494 static void 495 bytes_to_blocks_test(void) 496 { 497 struct spdk_bdev bdev; 498 uint64_t offset_blocks, num_blocks; 499 500 memset(&bdev, 0, sizeof(bdev)); 501 502 bdev.blocklen = 512; 503 504 /* All parameters valid */ 505 offset_blocks = 0; 506 num_blocks = 0; 507 CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 1024, &num_blocks) == 0); 508 CU_ASSERT(offset_blocks == 1); 509 CU_ASSERT(num_blocks == 2); 510 511 /* Offset not a block multiple */ 512 CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 3, &offset_blocks, 512, &num_blocks) != 0); 513 514 /* Length not a block multiple */ 515 CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 3, &num_blocks) != 0); 516 } 517 518 static void 519 num_blocks_test(void) 520 { 521 struct spdk_bdev bdev; 522 struct spdk_bdev_desc *desc; 523 524 memset(&bdev, 0, sizeof(bdev)); 525 bdev.name = "num_blocks"; 526 bdev.fn_table = &fn_table; 527 bdev.module = &bdev_ut_if; 528 spdk_bdev_register(&bdev); 529 spdk_bdev_notify_blockcnt_change(&bdev, 50); 530 531 /* Growing block number */ 532 CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 70) == 0); 533 /* Shrinking block number */ 534 CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 30) == 0); 535 536 /* In case bdev opened */ 537 spdk_bdev_open(&bdev, false, NULL, NULL, &desc); 538 539 /* Growing block number */ 540 CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 80) == 0); 541 /* Shrinking block number */ 542 CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 20) != 0); 543 544 spdk_bdev_close(desc); 545 spdk_bdev_unregister(&bdev, NULL, NULL); 546 } 547 548 static void 549 io_valid_test(void) 550 { 551 struct spdk_bdev bdev; 552 553 memset(&bdev, 0, sizeof(bdev)); 554 555 bdev.blocklen = 512; 556 spdk_bdev_notify_blockcnt_change(&bdev, 100); 557 558 /* All parameters valid */ 559 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 1, 2) == true); 560 561 /* Last valid block */ 562 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 1) == true); 563 564 /* Offset past end of bdev */ 565 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 100, 1) == false); 566 567 /* Offset + length past end of bdev */ 568 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 2) == false); 569 570 /* Offset near end of uint64_t range (2^64 - 1) */ 571 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 18446744073709551615ULL, 1) == false); 572 } 573 574 static void 575 alias_add_del_test(void) 576 { 577 struct spdk_bdev *bdev[2]; 578 int rc; 579 580 /* Creating and registering bdevs */ 581 bdev[0] = allocate_bdev("bdev0"); 582 SPDK_CU_ASSERT_FATAL(bdev[0] != 0); 583 584 bdev[1] = allocate_bdev("bdev1"); 585 SPDK_CU_ASSERT_FATAL(bdev[1] != 0); 586 587 /* 588 * Trying adding an alias identical to name. 589 * Alias is identical to name, so it can not be added to aliases list 590 */ 591 rc = spdk_bdev_alias_add(bdev[0], bdev[0]->name); 592 CU_ASSERT(rc == -EEXIST); 593 594 /* 595 * Trying to add empty alias, 596 * this one should fail 597 */ 598 rc = spdk_bdev_alias_add(bdev[0], NULL); 599 CU_ASSERT(rc == -EINVAL); 600 601 /* Trying adding same alias to two different registered bdevs */ 602 603 /* Alias is used first time, so this one should pass */ 604 rc = spdk_bdev_alias_add(bdev[0], "proper alias 0"); 605 CU_ASSERT(rc == 0); 606 607 /* Alias was added to another bdev, so this one should fail */ 608 rc = spdk_bdev_alias_add(bdev[1], "proper alias 0"); 609 CU_ASSERT(rc == -EEXIST); 610 611 /* Alias is used first time, so this one should pass */ 612 rc = spdk_bdev_alias_add(bdev[1], "proper alias 1"); 613 CU_ASSERT(rc == 0); 614 615 /* Trying removing an alias from registered bdevs */ 616 617 /* Alias is not on a bdev aliases list, so this one should fail */ 618 rc = spdk_bdev_alias_del(bdev[0], "not existing"); 619 CU_ASSERT(rc == -ENOENT); 620 621 /* Alias is present on a bdev aliases list, so this one should pass */ 622 rc = spdk_bdev_alias_del(bdev[0], "proper alias 0"); 623 CU_ASSERT(rc == 0); 624 625 /* Alias is present on a bdev aliases list, so this one should pass */ 626 rc = spdk_bdev_alias_del(bdev[1], "proper alias 1"); 627 CU_ASSERT(rc == 0); 628 629 /* Trying to remove name instead of alias, so this one should fail, name cannot be changed or removed */ 630 rc = spdk_bdev_alias_del(bdev[0], bdev[0]->name); 631 CU_ASSERT(rc != 0); 632 633 /* Unregister and free bdevs */ 634 spdk_bdev_unregister(bdev[0], NULL, NULL); 635 spdk_bdev_unregister(bdev[1], NULL, NULL); 636 637 free(bdev[0]); 638 free(bdev[1]); 639 } 640 641 static void 642 io_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 643 { 644 spdk_bdev_free_io(bdev_io); 645 } 646 647 static void 648 bdev_init_cb(void *arg, int rc) 649 { 650 CU_ASSERT(rc == 0); 651 } 652 653 struct bdev_ut_io_wait_entry { 654 struct spdk_bdev_io_wait_entry entry; 655 struct spdk_io_channel *io_ch; 656 struct spdk_bdev_desc *desc; 657 bool submitted; 658 }; 659 660 static void 661 io_wait_cb(void *arg) 662 { 663 struct bdev_ut_io_wait_entry *entry = arg; 664 int rc; 665 666 rc = spdk_bdev_read_blocks(entry->desc, entry->io_ch, NULL, 0, 1, io_done, NULL); 667 CU_ASSERT(rc == 0); 668 entry->submitted = true; 669 } 670 671 static void 672 bdev_io_wait_test(void) 673 { 674 struct spdk_bdev *bdev; 675 struct spdk_bdev_desc *desc; 676 struct spdk_io_channel *io_ch; 677 struct spdk_bdev_opts bdev_opts = { 678 .bdev_io_pool_size = 4, 679 .bdev_io_cache_size = 2, 680 }; 681 struct bdev_ut_io_wait_entry io_wait_entry; 682 struct bdev_ut_io_wait_entry io_wait_entry2; 683 int rc; 684 685 rc = spdk_bdev_set_opts(&bdev_opts); 686 CU_ASSERT(rc == 0); 687 spdk_bdev_initialize(bdev_init_cb, NULL); 688 689 bdev = allocate_bdev("bdev0"); 690 691 rc = spdk_bdev_open(bdev, true, NULL, NULL, &desc); 692 CU_ASSERT(rc == 0); 693 CU_ASSERT(desc != NULL); 694 io_ch = spdk_bdev_get_io_channel(desc); 695 CU_ASSERT(io_ch != NULL); 696 697 rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 698 CU_ASSERT(rc == 0); 699 rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 700 CU_ASSERT(rc == 0); 701 rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 702 CU_ASSERT(rc == 0); 703 rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 704 CU_ASSERT(rc == 0); 705 CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 706 707 rc = spdk_bdev_read_blocks(desc, io_ch, NULL, 0, 1, io_done, NULL); 708 CU_ASSERT(rc == -ENOMEM); 709 710 io_wait_entry.entry.bdev = bdev; 711 io_wait_entry.entry.cb_fn = io_wait_cb; 712 io_wait_entry.entry.cb_arg = &io_wait_entry; 713 io_wait_entry.io_ch = io_ch; 714 io_wait_entry.desc = desc; 715 io_wait_entry.submitted = false; 716 /* Cannot use the same io_wait_entry for two different calls. */ 717 memcpy(&io_wait_entry2, &io_wait_entry, sizeof(io_wait_entry)); 718 io_wait_entry2.entry.cb_arg = &io_wait_entry2; 719 720 /* Queue two I/O waits. */ 721 rc = spdk_bdev_queue_io_wait(bdev, io_ch, &io_wait_entry.entry); 722 CU_ASSERT(rc == 0); 723 CU_ASSERT(io_wait_entry.submitted == false); 724 rc = spdk_bdev_queue_io_wait(bdev, io_ch, &io_wait_entry2.entry); 725 CU_ASSERT(rc == 0); 726 CU_ASSERT(io_wait_entry2.submitted == false); 727 728 stub_complete_io(1); 729 CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 730 CU_ASSERT(io_wait_entry.submitted == true); 731 CU_ASSERT(io_wait_entry2.submitted == false); 732 733 stub_complete_io(1); 734 CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 4); 735 CU_ASSERT(io_wait_entry2.submitted == true); 736 737 stub_complete_io(4); 738 CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0); 739 740 spdk_put_io_channel(io_ch); 741 spdk_bdev_close(desc); 742 free_bdev(bdev); 743 } 744 745 int 746 main(int argc, char **argv) 747 { 748 CU_pSuite suite = NULL; 749 unsigned int num_failures; 750 751 if (CU_initialize_registry() != CUE_SUCCESS) { 752 return CU_get_error(); 753 } 754 755 suite = CU_add_suite("bdev", null_init, null_clean); 756 if (suite == NULL) { 757 CU_cleanup_registry(); 758 return CU_get_error(); 759 } 760 761 if ( 762 CU_add_test(suite, "bytes_to_blocks_test", bytes_to_blocks_test) == NULL || 763 CU_add_test(suite, "num_blocks_test", num_blocks_test) == NULL || 764 CU_add_test(suite, "io_valid", io_valid_test) == NULL || 765 CU_add_test(suite, "open_write", open_write_test) == NULL || 766 CU_add_test(suite, "alias_add_del", alias_add_del_test) == NULL || 767 CU_add_test(suite, "get_device_stat", get_device_stat_test) == NULL || 768 CU_add_test(suite, "bdev_io_wait", bdev_io_wait_test) == NULL 769 ) { 770 CU_cleanup_registry(); 771 return CU_get_error(); 772 } 773 774 spdk_allocate_thread(_bdev_send_msg, NULL, NULL, NULL, "thread0"); 775 CU_basic_set_mode(CU_BRM_VERBOSE); 776 CU_basic_run_tests(); 777 num_failures = CU_get_number_of_failures(); 778 CU_cleanup_registry(); 779 spdk_free_thread(); 780 return num_failures; 781 } 782