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