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 static struct spdk_bdev_fn_table fn_table = { 81 .destruct = stub_destruct, 82 }; 83 84 struct spdk_bdev_module bdev_ut_if = { 85 .name = "bdev_ut", 86 }; 87 88 static void vbdev_ut_examine(struct spdk_bdev *bdev); 89 90 struct spdk_bdev_module vbdev_ut_if = { 91 .name = "vbdev_ut", 92 .examine = vbdev_ut_examine, 93 }; 94 95 SPDK_BDEV_MODULE_REGISTER(&bdev_ut_if) 96 SPDK_BDEV_MODULE_REGISTER(&vbdev_ut_if) 97 98 static void 99 vbdev_ut_examine(struct spdk_bdev *bdev) 100 { 101 spdk_bdev_module_examine_done(&vbdev_ut_if); 102 } 103 104 static bool 105 is_vbdev(struct spdk_bdev *base, struct spdk_bdev *vbdev) 106 { 107 size_t i; 108 int found = 0; 109 110 for (i = 0; i < base->vbdevs_cnt; i++) { 111 found += base->vbdevs[i] == vbdev; 112 } 113 114 CU_ASSERT(found <= 1); 115 return !!found; 116 } 117 118 static bool 119 is_base_bdev(struct spdk_bdev *base, struct spdk_bdev *vbdev) 120 { 121 size_t i; 122 int found = 0; 123 124 for (i = 0; i < vbdev->base_bdevs_cnt; i++) { 125 found += vbdev->base_bdevs[i] == base; 126 } 127 128 CU_ASSERT(found <= 1); 129 return !!found; 130 } 131 132 static bool 133 check_base_and_vbdev(struct spdk_bdev *base, struct spdk_bdev *vbdev) 134 { 135 bool _is_vbdev = is_vbdev(base, vbdev); 136 bool _is_base = is_base_bdev(base, vbdev); 137 138 CU_ASSERT(_is_vbdev == _is_base); 139 140 return _is_base && _is_vbdev; 141 } 142 143 static struct spdk_bdev * 144 allocate_bdev(char *name) 145 { 146 struct spdk_bdev *bdev; 147 int rc; 148 149 bdev = calloc(1, sizeof(*bdev)); 150 SPDK_CU_ASSERT_FATAL(bdev != NULL); 151 152 bdev->name = name; 153 bdev->fn_table = &fn_table; 154 bdev->module = &bdev_ut_if; 155 156 rc = spdk_bdev_register(bdev); 157 CU_ASSERT(rc == 0); 158 CU_ASSERT(bdev->base_bdevs_cnt == 0); 159 CU_ASSERT(bdev->vbdevs_cnt == 0); 160 161 return bdev; 162 } 163 164 static struct spdk_bdev * 165 allocate_vbdev(char *name, struct spdk_bdev *base1, struct spdk_bdev *base2) 166 { 167 struct spdk_bdev *bdev; 168 struct spdk_bdev *array[2]; 169 int rc; 170 171 bdev = calloc(1, sizeof(*bdev)); 172 SPDK_CU_ASSERT_FATAL(bdev != NULL); 173 174 bdev->name = name; 175 bdev->fn_table = &fn_table; 176 bdev->module = &vbdev_ut_if; 177 178 /* vbdev must have at least one base bdev */ 179 CU_ASSERT(base1 != NULL); 180 181 array[0] = base1; 182 array[1] = base2; 183 184 rc = spdk_vbdev_register(bdev, array, base2 == NULL ? 1 : 2); 185 CU_ASSERT(rc == 0); 186 CU_ASSERT(bdev->base_bdevs_cnt > 0); 187 CU_ASSERT(bdev->vbdevs_cnt == 0); 188 189 CU_ASSERT(check_base_and_vbdev(base1, bdev) == true); 190 191 if (base2) { 192 CU_ASSERT(check_base_and_vbdev(base2, bdev) == true); 193 } 194 195 return bdev; 196 } 197 198 static void 199 free_bdev(struct spdk_bdev *bdev) 200 { 201 spdk_bdev_unregister(bdev, NULL, NULL); 202 memset(bdev, 0xFF, sizeof(*bdev)); 203 free(bdev); 204 } 205 206 static void 207 free_vbdev(struct spdk_bdev *bdev) 208 { 209 CU_ASSERT(bdev->base_bdevs_cnt != 0); 210 spdk_bdev_unregister(bdev, NULL, NULL); 211 memset(bdev, 0xFF, sizeof(*bdev)); 212 free(bdev); 213 } 214 215 static void 216 get_device_stat_cb(struct spdk_bdev *bdev, struct spdk_bdev_io_stat *stat, void *cb_arg, int rc) 217 { 218 const char *bdev_name; 219 220 CU_ASSERT(bdev != NULL); 221 CU_ASSERT(rc == 0); 222 bdev_name = spdk_bdev_get_name(bdev); 223 CU_ASSERT_STRING_EQUAL(bdev_name, "bdev0"); 224 225 free(stat); 226 free_bdev(bdev); 227 } 228 229 static void 230 get_device_stat_test(void) 231 { 232 struct spdk_bdev *bdev; 233 struct spdk_bdev_io_stat *stat; 234 235 bdev = allocate_bdev("bdev0"); 236 stat = calloc(1, sizeof(struct spdk_bdev_io_stat)); 237 if (stat == NULL) { 238 free_bdev(bdev); 239 return; 240 } 241 spdk_bdev_get_device_stat(bdev, stat, get_device_stat_cb, NULL); 242 } 243 244 static void 245 open_write_test(void) 246 { 247 struct spdk_bdev *bdev[9]; 248 struct spdk_bdev_desc *desc[9] = {}; 249 int rc; 250 251 /* 252 * Create a tree of bdevs to test various open w/ write cases. 253 * 254 * bdev0 through bdev3 are physical block devices, such as NVMe 255 * namespaces or Ceph block devices. 256 * 257 * bdev4 is a virtual bdev with multiple base bdevs. This models 258 * caching or RAID use cases. 259 * 260 * bdev5 through bdev7 are all virtual bdevs with the same base 261 * bdev (except bdev7). This models partitioning or logical volume 262 * use cases. 263 * 264 * bdev7 is a virtual bdev with multiple base bdevs. One of base bdevs 265 * (bdev2) is shared with other virtual bdevs: bdev5 and bdev6. This 266 * models caching, RAID, partitioning or logical volumes use cases. 267 * 268 * bdev8 is a virtual bdev with multiple base bdevs, but these 269 * base bdevs are themselves virtual bdevs. 270 * 271 * bdev8 272 * | 273 * +----------+ 274 * | | 275 * bdev4 bdev5 bdev6 bdev7 276 * | | | | 277 * +---+---+ +---+ + +---+---+ 278 * | | \ | / \ 279 * bdev0 bdev1 bdev2 bdev3 280 */ 281 282 bdev[0] = allocate_bdev("bdev0"); 283 rc = spdk_bdev_module_claim_bdev(bdev[0], NULL, &bdev_ut_if); 284 CU_ASSERT(rc == 0); 285 286 bdev[1] = allocate_bdev("bdev1"); 287 rc = spdk_bdev_module_claim_bdev(bdev[1], NULL, &bdev_ut_if); 288 CU_ASSERT(rc == 0); 289 290 bdev[2] = allocate_bdev("bdev2"); 291 rc = spdk_bdev_module_claim_bdev(bdev[2], NULL, &bdev_ut_if); 292 CU_ASSERT(rc == 0); 293 294 bdev[3] = allocate_bdev("bdev3"); 295 rc = spdk_bdev_module_claim_bdev(bdev[3], NULL, &bdev_ut_if); 296 CU_ASSERT(rc == 0); 297 298 bdev[4] = allocate_vbdev("bdev4", bdev[0], bdev[1]); 299 rc = spdk_bdev_module_claim_bdev(bdev[4], NULL, &bdev_ut_if); 300 CU_ASSERT(rc == 0); 301 302 bdev[5] = allocate_vbdev("bdev5", bdev[2], NULL); 303 rc = spdk_bdev_module_claim_bdev(bdev[5], NULL, &bdev_ut_if); 304 CU_ASSERT(rc == 0); 305 306 bdev[6] = allocate_vbdev("bdev6", bdev[2], NULL); 307 308 bdev[7] = allocate_vbdev("bdev7", bdev[2], bdev[3]); 309 310 bdev[8] = allocate_vbdev("bdev8", bdev[4], bdev[5]); 311 312 /* Check tree */ 313 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[4]) == true); 314 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[5]) == false); 315 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[6]) == false); 316 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[7]) == false); 317 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[8]) == false); 318 319 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[4]) == true); 320 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[5]) == false); 321 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[6]) == false); 322 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[7]) == false); 323 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[8]) == false); 324 325 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[4]) == false); 326 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[5]) == true); 327 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[6]) == true); 328 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[7]) == true); 329 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[8]) == false); 330 331 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[4]) == false); 332 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[5]) == false); 333 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[6]) == false); 334 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[7]) == true); 335 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[8]) == false); 336 337 /* Open bdev0 read-only. This should succeed. */ 338 rc = spdk_bdev_open(bdev[0], false, NULL, NULL, &desc[0]); 339 CU_ASSERT(rc == 0); 340 CU_ASSERT(desc[0] != NULL); 341 spdk_bdev_close(desc[0]); 342 343 /* 344 * Open bdev1 read/write. This should fail since bdev1 has been claimed 345 * by a vbdev module. 346 */ 347 rc = spdk_bdev_open(bdev[1], true, NULL, NULL, &desc[1]); 348 CU_ASSERT(rc == -EPERM); 349 350 /* 351 * Open bdev4 read/write. This should fail since bdev3 has been claimed 352 * by a vbdev module. 353 */ 354 rc = spdk_bdev_open(bdev[4], true, NULL, NULL, &desc[4]); 355 CU_ASSERT(rc == -EPERM); 356 357 /* Open bdev4 read-only. This should succeed. */ 358 rc = spdk_bdev_open(bdev[4], false, NULL, NULL, &desc[4]); 359 CU_ASSERT(rc == 0); 360 CU_ASSERT(desc[4] != NULL); 361 spdk_bdev_close(desc[4]); 362 363 /* 364 * Open bdev8 read/write. This should succeed since it is a leaf 365 * bdev. 366 */ 367 rc = spdk_bdev_open(bdev[8], true, NULL, NULL, &desc[8]); 368 CU_ASSERT(rc == 0); 369 CU_ASSERT(desc[8] != NULL); 370 spdk_bdev_close(desc[8]); 371 372 /* 373 * Open bdev5 read/write. This should fail since bdev4 has been claimed 374 * by a vbdev module. 375 */ 376 rc = spdk_bdev_open(bdev[5], true, NULL, NULL, &desc[5]); 377 CU_ASSERT(rc == -EPERM); 378 379 /* Open bdev4 read-only. This should succeed. */ 380 rc = spdk_bdev_open(bdev[5], false, NULL, NULL, &desc[5]); 381 CU_ASSERT(rc == 0); 382 CU_ASSERT(desc[5] != NULL); 383 spdk_bdev_close(desc[5]); 384 385 free_vbdev(bdev[8]); 386 387 free_vbdev(bdev[5]); 388 free_vbdev(bdev[6]); 389 free_vbdev(bdev[7]); 390 391 free_vbdev(bdev[4]); 392 393 free_bdev(bdev[0]); 394 free_bdev(bdev[1]); 395 free_bdev(bdev[2]); 396 free_bdev(bdev[3]); 397 } 398 399 static void 400 bytes_to_blocks_test(void) 401 { 402 struct spdk_bdev bdev; 403 uint64_t offset_blocks, num_blocks; 404 405 memset(&bdev, 0, sizeof(bdev)); 406 407 bdev.blocklen = 512; 408 409 /* All parameters valid */ 410 offset_blocks = 0; 411 num_blocks = 0; 412 CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 1024, &num_blocks) == 0); 413 CU_ASSERT(offset_blocks == 1); 414 CU_ASSERT(num_blocks == 2); 415 416 /* Offset not a block multiple */ 417 CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 3, &offset_blocks, 512, &num_blocks) != 0); 418 419 /* Length not a block multiple */ 420 CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 3, &num_blocks) != 0); 421 } 422 423 static void 424 num_blocks_test(void) 425 { 426 struct spdk_bdev bdev; 427 struct spdk_bdev_desc *desc; 428 429 memset(&bdev, 0, sizeof(bdev)); 430 bdev.name = "num_blocks"; 431 bdev.fn_table = &fn_table; 432 bdev.module = &bdev_ut_if; 433 spdk_bdev_register(&bdev); 434 spdk_bdev_notify_blockcnt_change(&bdev, 50); 435 436 /* Growing block number */ 437 CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 70) == 0); 438 /* Shrinking block number */ 439 CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 30) == 0); 440 441 /* In case bdev opened */ 442 spdk_bdev_open(&bdev, false, NULL, NULL, &desc); 443 444 /* Growing block number */ 445 CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 80) == 0); 446 /* Shrinking block number */ 447 CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 20) != 0); 448 449 spdk_bdev_close(desc); 450 spdk_bdev_unregister(&bdev, NULL, NULL); 451 } 452 453 static void 454 io_valid_test(void) 455 { 456 struct spdk_bdev bdev; 457 458 memset(&bdev, 0, sizeof(bdev)); 459 460 bdev.blocklen = 512; 461 spdk_bdev_notify_blockcnt_change(&bdev, 100); 462 463 /* All parameters valid */ 464 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 1, 2) == true); 465 466 /* Last valid block */ 467 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 1) == true); 468 469 /* Offset past end of bdev */ 470 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 100, 1) == false); 471 472 /* Offset + length past end of bdev */ 473 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 2) == false); 474 475 /* Offset near end of uint64_t range (2^64 - 1) */ 476 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 18446744073709551615ULL, 1) == false); 477 } 478 479 static void 480 alias_add_del_test(void) 481 { 482 struct spdk_bdev *bdev[2]; 483 int rc; 484 485 /* Creating and registering bdevs */ 486 bdev[0] = allocate_bdev("bdev0"); 487 SPDK_CU_ASSERT_FATAL(bdev[0] != 0); 488 489 bdev[1] = allocate_bdev("bdev1"); 490 SPDK_CU_ASSERT_FATAL(bdev[1] != 0); 491 492 /* 493 * Trying adding an alias identical to name. 494 * Alias is identical to name, so it can not be added to aliases list 495 */ 496 rc = spdk_bdev_alias_add(bdev[0], bdev[0]->name); 497 CU_ASSERT(rc == -EEXIST); 498 499 /* 500 * Trying to add empty alias, 501 * this one should fail 502 */ 503 rc = spdk_bdev_alias_add(bdev[0], NULL); 504 CU_ASSERT(rc == -EINVAL); 505 506 /* Trying adding same alias to two different registered bdevs */ 507 508 /* Alias is used first time, so this one should pass */ 509 rc = spdk_bdev_alias_add(bdev[0], "proper alias 0"); 510 CU_ASSERT(rc == 0); 511 512 /* Alias was added to another bdev, so this one should fail */ 513 rc = spdk_bdev_alias_add(bdev[1], "proper alias 0"); 514 CU_ASSERT(rc == -EEXIST); 515 516 /* Alias is used first time, so this one should pass */ 517 rc = spdk_bdev_alias_add(bdev[1], "proper alias 1"); 518 CU_ASSERT(rc == 0); 519 520 /* Trying removing an alias from registered bdevs */ 521 522 /* Alias is not on a bdev aliases list, so this one should fail */ 523 rc = spdk_bdev_alias_del(bdev[0], "not existing"); 524 CU_ASSERT(rc == -ENOENT); 525 526 /* Alias is present on a bdev aliases list, so this one should pass */ 527 rc = spdk_bdev_alias_del(bdev[0], "proper alias 0"); 528 CU_ASSERT(rc == 0); 529 530 /* Alias is present on a bdev aliases list, so this one should pass */ 531 rc = spdk_bdev_alias_del(bdev[1], "proper alias 1"); 532 CU_ASSERT(rc == 0); 533 534 /* Trying to remove name instead of alias, so this one should fail, name cannot be changed or removed */ 535 rc = spdk_bdev_alias_del(bdev[0], bdev[0]->name); 536 CU_ASSERT(rc != 0); 537 538 /* Unregister and free bdevs */ 539 spdk_bdev_unregister(bdev[0], NULL, NULL); 540 spdk_bdev_unregister(bdev[1], NULL, NULL); 541 542 free(bdev[0]); 543 free(bdev[1]); 544 } 545 546 int 547 main(int argc, char **argv) 548 { 549 CU_pSuite suite = NULL; 550 unsigned int num_failures; 551 552 if (CU_initialize_registry() != CUE_SUCCESS) { 553 return CU_get_error(); 554 } 555 556 suite = CU_add_suite("bdev", null_init, null_clean); 557 if (suite == NULL) { 558 CU_cleanup_registry(); 559 return CU_get_error(); 560 } 561 562 if ( 563 CU_add_test(suite, "bytes_to_blocks_test", bytes_to_blocks_test) == NULL || 564 CU_add_test(suite, "num_blocks_test", num_blocks_test) == NULL || 565 CU_add_test(suite, "io_valid", io_valid_test) == NULL || 566 CU_add_test(suite, "open_write", open_write_test) == NULL || 567 CU_add_test(suite, "alias_add_del", alias_add_del_test) == NULL || 568 CU_add_test(suite, "get_device_stat", get_device_stat_test) == NULL 569 ) { 570 CU_cleanup_registry(); 571 return CU_get_error(); 572 } 573 574 spdk_allocate_thread(_bdev_send_msg, NULL, NULL, NULL, "thread0"); 575 CU_basic_set_mode(CU_BRM_VERBOSE); 576 CU_basic_run_tests(); 577 num_failures = CU_get_number_of_failures(); 578 CU_cleanup_registry(); 579 spdk_free_thread(); 580 return num_failures; 581 } 582