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 open_write_test(void) 225 { 226 struct spdk_bdev *bdev[9]; 227 struct spdk_bdev_desc *desc[9] = {}; 228 int rc; 229 230 /* 231 * Create a tree of bdevs to test various open w/ write cases. 232 * 233 * bdev0 through bdev3 are physical block devices, such as NVMe 234 * namespaces or Ceph block devices. 235 * 236 * bdev4 is a virtual bdev with multiple base bdevs. This models 237 * caching or RAID use cases. 238 * 239 * bdev5 through bdev7 are all virtual bdevs with the same base 240 * bdev (except bdev7). This models partitioning or logical volume 241 * use cases. 242 * 243 * bdev7 is a virtual bdev with multiple base bdevs. One of base bdevs 244 * (bdev2) is shared with other virtual bdevs: bdev5 and bdev6. This 245 * models caching, RAID, partitioning or logical volumes use cases. 246 * 247 * bdev8 is a virtual bdev with multiple base bdevs, but these 248 * base bdevs are themselves virtual bdevs. 249 * 250 * bdev8 251 * | 252 * +----------+ 253 * | | 254 * bdev4 bdev5 bdev6 bdev7 255 * | | | | 256 * +---+---+ +---+ + +---+---+ 257 * | | \ | / \ 258 * bdev0 bdev1 bdev2 bdev3 259 */ 260 261 bdev[0] = allocate_bdev("bdev0"); 262 rc = spdk_bdev_module_claim_bdev(bdev[0], NULL, &bdev_ut_if); 263 CU_ASSERT(rc == 0); 264 265 bdev[1] = allocate_bdev("bdev1"); 266 rc = spdk_bdev_module_claim_bdev(bdev[1], NULL, &bdev_ut_if); 267 CU_ASSERT(rc == 0); 268 269 bdev[2] = allocate_bdev("bdev2"); 270 rc = spdk_bdev_module_claim_bdev(bdev[2], NULL, &bdev_ut_if); 271 CU_ASSERT(rc == 0); 272 273 bdev[3] = allocate_bdev("bdev3"); 274 rc = spdk_bdev_module_claim_bdev(bdev[3], NULL, &bdev_ut_if); 275 CU_ASSERT(rc == 0); 276 277 bdev[4] = allocate_vbdev("bdev4", bdev[0], bdev[1]); 278 rc = spdk_bdev_module_claim_bdev(bdev[4], NULL, &bdev_ut_if); 279 CU_ASSERT(rc == 0); 280 281 bdev[5] = allocate_vbdev("bdev5", bdev[2], NULL); 282 rc = spdk_bdev_module_claim_bdev(bdev[5], NULL, &bdev_ut_if); 283 CU_ASSERT(rc == 0); 284 285 bdev[6] = allocate_vbdev("bdev6", bdev[2], NULL); 286 287 bdev[7] = allocate_vbdev("bdev7", bdev[2], bdev[3]); 288 289 bdev[8] = allocate_vbdev("bdev8", bdev[4], bdev[5]); 290 291 /* Check tree */ 292 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[4]) == true); 293 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[5]) == false); 294 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[6]) == false); 295 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[7]) == false); 296 CU_ASSERT(check_base_and_vbdev(bdev[0], bdev[8]) == false); 297 298 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[4]) == true); 299 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[5]) == false); 300 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[6]) == false); 301 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[7]) == false); 302 CU_ASSERT(check_base_and_vbdev(bdev[1], bdev[8]) == false); 303 304 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[4]) == false); 305 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[5]) == true); 306 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[6]) == true); 307 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[7]) == true); 308 CU_ASSERT(check_base_and_vbdev(bdev[2], bdev[8]) == false); 309 310 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[4]) == false); 311 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[5]) == false); 312 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[6]) == false); 313 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[7]) == true); 314 CU_ASSERT(check_base_and_vbdev(bdev[3], bdev[8]) == false); 315 316 /* Open bdev0 read-only. This should succeed. */ 317 rc = spdk_bdev_open(bdev[0], false, NULL, NULL, &desc[0]); 318 CU_ASSERT(rc == 0); 319 CU_ASSERT(desc[0] != NULL); 320 spdk_bdev_close(desc[0]); 321 322 /* 323 * Open bdev1 read/write. This should fail since bdev1 has been claimed 324 * by a vbdev module. 325 */ 326 rc = spdk_bdev_open(bdev[1], true, NULL, NULL, &desc[1]); 327 CU_ASSERT(rc == -EPERM); 328 329 /* 330 * Open bdev4 read/write. This should fail since bdev3 has been claimed 331 * by a vbdev module. 332 */ 333 rc = spdk_bdev_open(bdev[4], true, NULL, NULL, &desc[4]); 334 CU_ASSERT(rc == -EPERM); 335 336 /* Open bdev4 read-only. This should succeed. */ 337 rc = spdk_bdev_open(bdev[4], false, NULL, NULL, &desc[4]); 338 CU_ASSERT(rc == 0); 339 CU_ASSERT(desc[4] != NULL); 340 spdk_bdev_close(desc[4]); 341 342 /* 343 * Open bdev8 read/write. This should succeed since it is a leaf 344 * bdev. 345 */ 346 rc = spdk_bdev_open(bdev[8], true, NULL, NULL, &desc[8]); 347 CU_ASSERT(rc == 0); 348 CU_ASSERT(desc[8] != NULL); 349 spdk_bdev_close(desc[8]); 350 351 /* 352 * Open bdev5 read/write. This should fail since bdev4 has been claimed 353 * by a vbdev module. 354 */ 355 rc = spdk_bdev_open(bdev[5], true, NULL, NULL, &desc[5]); 356 CU_ASSERT(rc == -EPERM); 357 358 /* Open bdev4 read-only. This should succeed. */ 359 rc = spdk_bdev_open(bdev[5], false, NULL, NULL, &desc[5]); 360 CU_ASSERT(rc == 0); 361 CU_ASSERT(desc[5] != NULL); 362 spdk_bdev_close(desc[5]); 363 364 free_vbdev(bdev[8]); 365 366 free_vbdev(bdev[5]); 367 free_vbdev(bdev[6]); 368 free_vbdev(bdev[7]); 369 370 free_vbdev(bdev[4]); 371 372 free_bdev(bdev[0]); 373 free_bdev(bdev[1]); 374 free_bdev(bdev[2]); 375 free_bdev(bdev[3]); 376 } 377 378 static void 379 bytes_to_blocks_test(void) 380 { 381 struct spdk_bdev bdev; 382 uint64_t offset_blocks, num_blocks; 383 384 memset(&bdev, 0, sizeof(bdev)); 385 386 bdev.blocklen = 512; 387 388 /* All parameters valid */ 389 offset_blocks = 0; 390 num_blocks = 0; 391 CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 1024, &num_blocks) == 0); 392 CU_ASSERT(offset_blocks == 1); 393 CU_ASSERT(num_blocks == 2); 394 395 /* Offset not a block multiple */ 396 CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 3, &offset_blocks, 512, &num_blocks) != 0); 397 398 /* Length not a block multiple */ 399 CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 3, &num_blocks) != 0); 400 } 401 402 static void 403 num_blocks_test(void) 404 { 405 struct spdk_bdev bdev; 406 struct spdk_bdev_desc *desc; 407 408 memset(&bdev, 0, sizeof(bdev)); 409 bdev.name = "num_blocks"; 410 bdev.fn_table = &fn_table; 411 bdev.module = &bdev_ut_if; 412 spdk_bdev_register(&bdev); 413 spdk_bdev_notify_blockcnt_change(&bdev, 50); 414 415 /* Growing block number */ 416 CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 70) == 0); 417 /* Shrinking block number */ 418 CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 30) == 0); 419 420 /* In case bdev opened */ 421 spdk_bdev_open(&bdev, false, NULL, NULL, &desc); 422 423 /* Growing block number */ 424 CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 80) == 0); 425 /* Shrinking block number */ 426 CU_ASSERT(spdk_bdev_notify_blockcnt_change(&bdev, 20) != 0); 427 428 spdk_bdev_close(desc); 429 spdk_bdev_unregister(&bdev, NULL, NULL); 430 } 431 432 static void 433 io_valid_test(void) 434 { 435 struct spdk_bdev bdev; 436 437 memset(&bdev, 0, sizeof(bdev)); 438 439 bdev.blocklen = 512; 440 spdk_bdev_notify_blockcnt_change(&bdev, 100); 441 442 /* All parameters valid */ 443 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 1, 2) == true); 444 445 /* Last valid block */ 446 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 1) == true); 447 448 /* Offset past end of bdev */ 449 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 100, 1) == false); 450 451 /* Offset + length past end of bdev */ 452 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 2) == false); 453 454 /* Offset near end of uint64_t range (2^64 - 1) */ 455 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 18446744073709551615ULL, 1) == false); 456 } 457 458 static void 459 alias_add_del_test(void) 460 { 461 struct spdk_bdev *bdev[2]; 462 int rc; 463 464 /* Creating and registering bdevs */ 465 bdev[0] = allocate_bdev("bdev0"); 466 SPDK_CU_ASSERT_FATAL(bdev[0] != 0); 467 468 bdev[1] = allocate_bdev("bdev1"); 469 SPDK_CU_ASSERT_FATAL(bdev[1] != 0); 470 471 /* 472 * Trying adding an alias identical to name. 473 * Alias is identical to name, so it can not be added to aliases list 474 */ 475 rc = spdk_bdev_alias_add(bdev[0], bdev[0]->name); 476 CU_ASSERT(rc == -EEXIST); 477 478 /* 479 * Trying to add empty alias, 480 * this one should fail 481 */ 482 rc = spdk_bdev_alias_add(bdev[0], NULL); 483 CU_ASSERT(rc == -EINVAL); 484 485 /* Trying adding same alias to two different registered bdevs */ 486 487 /* Alias is used first time, so this one should pass */ 488 rc = spdk_bdev_alias_add(bdev[0], "proper alias 0"); 489 CU_ASSERT(rc == 0); 490 491 /* Alias was added to another bdev, so this one should fail */ 492 rc = spdk_bdev_alias_add(bdev[1], "proper alias 0"); 493 CU_ASSERT(rc == -EEXIST); 494 495 /* Alias is used first time, so this one should pass */ 496 rc = spdk_bdev_alias_add(bdev[1], "proper alias 1"); 497 CU_ASSERT(rc == 0); 498 499 /* Trying removing an alias from registered bdevs */ 500 501 /* Alias is not on a bdev aliases list, so this one should fail */ 502 rc = spdk_bdev_alias_del(bdev[0], "not existing"); 503 CU_ASSERT(rc == -ENOENT); 504 505 /* Alias is present on a bdev aliases list, so this one should pass */ 506 rc = spdk_bdev_alias_del(bdev[0], "proper alias 0"); 507 CU_ASSERT(rc == 0); 508 509 /* Alias is present on a bdev aliases list, so this one should pass */ 510 rc = spdk_bdev_alias_del(bdev[1], "proper alias 1"); 511 CU_ASSERT(rc == 0); 512 513 /* Trying to remove name instead of alias, so this one should fail, name cannot be changed or removed */ 514 rc = spdk_bdev_alias_del(bdev[0], bdev[0]->name); 515 CU_ASSERT(rc != 0); 516 517 /* Unregister and free bdevs */ 518 spdk_bdev_unregister(bdev[0], NULL, NULL); 519 spdk_bdev_unregister(bdev[1], NULL, NULL); 520 521 free(bdev[0]); 522 free(bdev[1]); 523 } 524 525 int 526 main(int argc, char **argv) 527 { 528 CU_pSuite suite = NULL; 529 unsigned int num_failures; 530 531 if (CU_initialize_registry() != CUE_SUCCESS) { 532 return CU_get_error(); 533 } 534 535 suite = CU_add_suite("bdev", null_init, null_clean); 536 if (suite == NULL) { 537 CU_cleanup_registry(); 538 return CU_get_error(); 539 } 540 541 if ( 542 CU_add_test(suite, "bytes_to_blocks_test", bytes_to_blocks_test) == NULL || 543 CU_add_test(suite, "num_blocks_test", num_blocks_test) == NULL || 544 CU_add_test(suite, "io_valid", io_valid_test) == NULL || 545 CU_add_test(suite, "open_write", open_write_test) == NULL || 546 CU_add_test(suite, "alias_add_del", alias_add_del_test) == NULL 547 ) { 548 CU_cleanup_registry(); 549 return CU_get_error(); 550 } 551 552 spdk_allocate_thread(_bdev_send_msg, NULL, NULL, NULL, "thread0"); 553 CU_basic_set_mode(CU_BRM_VERBOSE); 554 CU_basic_run_tests(); 555 num_failures = CU_get_number_of_failures(); 556 CU_cleanup_registry(); 557 spdk_free_thread(); 558 return num_failures; 559 } 560