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