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