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