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.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 spdk_vbdev_unregister(bdev, NULL, NULL); 142 free(bdev); 143 } 144 145 static void 146 open_write_test(void) 147 { 148 struct spdk_bdev *bdev[8]; 149 struct spdk_bdev_desc *desc[8] = {}; 150 int rc; 151 152 /* 153 * Create a tree of bdevs to test various open w/ write cases. 154 * 155 * bdev0 through bdev2 are physical block devices, such as NVMe 156 * namespaces or Ceph block devices. 157 * 158 * bdev3 is a virtual bdev with multiple base bdevs. This models 159 * caching or RAID use cases. 160 * 161 * bdev4 through bdev6 are all virtual bdevs with the same base 162 * bdev. This models partitioning or logical volume use cases. 163 * 164 * bdev7 is a virtual bdev with multiple base bdevs, but these 165 * base bdevs are themselves virtual bdevs. 166 * 167 * bdev7 168 * | 169 * +----------+ 170 * | | 171 * bdev3 bdev4 bdev5 bdev6 172 * | | | | 173 * +---+---+ +-------+-------+ 174 * | | | 175 * bdev0 bdev1 bdev2 176 */ 177 178 bdev[0] = allocate_bdev("bdev0"); 179 rc = spdk_bdev_module_claim_bdev(bdev[0], NULL, SPDK_GET_BDEV_MODULE(bdev_ut)); 180 CU_ASSERT(rc == 0); 181 182 bdev[1] = allocate_bdev("bdev1"); 183 rc = spdk_bdev_module_claim_bdev(bdev[1], NULL, SPDK_GET_BDEV_MODULE(bdev_ut)); 184 CU_ASSERT(rc == 0); 185 186 bdev[2] = allocate_bdev("bdev2"); 187 rc = spdk_bdev_module_claim_bdev(bdev[2], NULL, SPDK_GET_BDEV_MODULE(bdev_ut)); 188 CU_ASSERT(rc == 0); 189 190 bdev[3] = allocate_vbdev("bdev3", bdev[0], bdev[1]); 191 rc = spdk_bdev_module_claim_bdev(bdev[3], NULL, SPDK_GET_BDEV_MODULE(bdev_ut)); 192 CU_ASSERT(rc == 0); 193 194 bdev[4] = allocate_vbdev("bdev4", bdev[2], NULL); 195 rc = spdk_bdev_module_claim_bdev(bdev[4], NULL, SPDK_GET_BDEV_MODULE(bdev_ut)); 196 CU_ASSERT(rc == 0); 197 198 bdev[5] = allocate_vbdev("bdev5", bdev[2], NULL); 199 bdev[6] = allocate_vbdev("bdev6", bdev[2], NULL); 200 201 bdev[7] = allocate_vbdev("bdev7", bdev[3], bdev[4]); 202 203 /* Open bdev0 read-only. This should succeed. */ 204 rc = spdk_bdev_open(bdev[0], false, NULL, NULL, &desc[0]); 205 CU_ASSERT(rc == 0); 206 CU_ASSERT(desc[0] != NULL); 207 spdk_bdev_close(desc[0]); 208 209 /* 210 * Open bdev1 read/write. This should fail since bdev1 has been claimed 211 * by a vbdev module. 212 */ 213 rc = spdk_bdev_open(bdev[1], true, NULL, NULL, &desc[1]); 214 CU_ASSERT(rc == -EPERM); 215 216 /* 217 * Open bdev3 read/write. This should fail since bdev3 has been claimed 218 * by a vbdev module. 219 */ 220 rc = spdk_bdev_open(bdev[3], true, NULL, NULL, &desc[3]); 221 CU_ASSERT(rc == -EPERM); 222 223 /* Open bdev3 read-only. This should succeed. */ 224 rc = spdk_bdev_open(bdev[3], false, NULL, NULL, &desc[3]); 225 CU_ASSERT(rc == 0); 226 CU_ASSERT(desc[3] != NULL); 227 spdk_bdev_close(desc[3]); 228 229 /* 230 * Open bdev7 read/write. This should succeed since it is a leaf 231 * bdev. 232 */ 233 rc = spdk_bdev_open(bdev[7], true, NULL, NULL, &desc[7]); 234 CU_ASSERT(rc == 0); 235 CU_ASSERT(desc[7] != NULL); 236 spdk_bdev_close(desc[7]); 237 238 /* 239 * Open bdev4 read/write. This should fail since bdev4 has been claimed 240 * by a vbdev module. 241 */ 242 rc = spdk_bdev_open(bdev[4], true, NULL, NULL, &desc[4]); 243 CU_ASSERT(rc == -EPERM); 244 245 /* Open bdev4 read-only. This should succeed. */ 246 rc = spdk_bdev_open(bdev[4], false, NULL, NULL, &desc[4]); 247 CU_ASSERT(rc == 0); 248 CU_ASSERT(desc[4] != NULL); 249 spdk_bdev_close(desc[4]); 250 251 free_vbdev(bdev[7]); 252 253 free_vbdev(bdev[3]); 254 free_vbdev(bdev[4]); 255 free_vbdev(bdev[5]); 256 free_vbdev(bdev[6]); 257 258 free_bdev(bdev[0]); 259 free_bdev(bdev[1]); 260 free_bdev(bdev[2]); 261 262 } 263 264 static void 265 bytes_to_blocks_test(void) 266 { 267 struct spdk_bdev bdev; 268 uint64_t offset_blocks, num_blocks; 269 270 memset(&bdev, 0, sizeof(bdev)); 271 272 bdev.blocklen = 512; 273 274 /* All parameters valid */ 275 offset_blocks = 0; 276 num_blocks = 0; 277 CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 1024, &num_blocks) == 0); 278 CU_ASSERT(offset_blocks == 1); 279 CU_ASSERT(num_blocks == 2); 280 281 /* Offset not a block multiple */ 282 CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 3, &offset_blocks, 512, &num_blocks) != 0); 283 284 /* Length not a block multiple */ 285 CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 3, &num_blocks) != 0); 286 } 287 288 static void 289 io_valid_test(void) 290 { 291 struct spdk_bdev bdev; 292 293 memset(&bdev, 0, sizeof(bdev)); 294 295 bdev.blocklen = 512; 296 bdev.blockcnt = 100; 297 298 /* All parameters valid */ 299 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 1, 2) == true); 300 301 /* Last valid block */ 302 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 1) == true); 303 304 /* Offset past end of bdev */ 305 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 100, 1) == false); 306 307 /* Offset + length past end of bdev */ 308 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 2) == false); 309 310 /* Offset near end of uint64_t range (2^64 - 1) */ 311 CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 18446744073709551615ULL, 1) == false); 312 } 313 314 static int 315 __destruct(void *ctx) 316 { 317 return 0; 318 } 319 320 static struct spdk_bdev_fn_table base_fn_table = { 321 .destruct = __destruct, 322 }; 323 static struct spdk_bdev_fn_table part_fn_table = { 324 .destruct = __destruct, 325 }; 326 327 static void 328 __base_free(struct spdk_bdev_part_base *base) 329 { 330 free(base); 331 } 332 333 static void 334 part_test(void) 335 { 336 struct spdk_bdev_part_base *base; 337 struct spdk_bdev_part part1, part2; 338 struct spdk_bdev bdev_base = {}; 339 SPDK_BDEV_PART_TAILQ tailq = TAILQ_HEAD_INITIALIZER(tailq); 340 int rc; 341 342 base = calloc(1, sizeof(*base)); 343 SPDK_CU_ASSERT_FATAL(base != NULL); 344 345 bdev_base.name = "base"; 346 bdev_base.fn_table = &base_fn_table; 347 bdev_base.module = SPDK_GET_BDEV_MODULE(bdev_ut); 348 rc = spdk_bdev_register(&bdev_base); 349 CU_ASSERT(rc == 0); 350 spdk_bdev_part_base_construct(base, &bdev_base, NULL, SPDK_GET_BDEV_MODULE(vbdev_ut), 351 &part_fn_table, &tailq, __base_free, 0, NULL, NULL); 352 353 spdk_bdev_part_construct(&part1, base, "test1", 0, 100, "test"); 354 spdk_bdev_part_construct(&part2, base, "test2", 100, 100, "test"); 355 356 spdk_bdev_part_base_hotremove(&bdev_base, &tailq); 357 358 /* 359 * The base device was removed - ensure that the partition vbdevs were 360 * removed from the base's vbdev list. 361 */ 362 CU_ASSERT(TAILQ_EMPTY(&bdev_base.vbdevs)); 363 364 spdk_bdev_part_base_free(base); 365 spdk_bdev_unregister(&bdev_base, NULL, NULL); 366 } 367 368 static void 369 alias_add_del_test(void) 370 { 371 struct spdk_bdev *bdev[2]; 372 int rc; 373 374 /* Creating and registering bdevs */ 375 bdev[0] = allocate_bdev("bdev0"); 376 SPDK_CU_ASSERT_FATAL(bdev[0] != 0); 377 378 bdev[1] = allocate_bdev("bdev1"); 379 SPDK_CU_ASSERT_FATAL(bdev[1] != 0); 380 381 /* 382 * Trying adding an alias identical to name. 383 * Alias is identical to name, so it can not be added to aliases list 384 */ 385 rc = spdk_bdev_alias_add(bdev[0], bdev[0]->name); 386 CU_ASSERT(rc == -EEXIST); 387 388 /* 389 * Trying to add empty alias, 390 * this one should fail 391 */ 392 rc = spdk_bdev_alias_add(bdev[0], NULL); 393 CU_ASSERT(rc == -EINVAL); 394 395 /* Trying adding same alias to two different registered bdevs */ 396 397 /* Alias is used first time, so this one should pass */ 398 rc = spdk_bdev_alias_add(bdev[0], "proper alias 0"); 399 CU_ASSERT(rc == 0); 400 401 /* Alias was added to another bdev, so this one should fail */ 402 rc = spdk_bdev_alias_add(bdev[1], "proper alias 0"); 403 CU_ASSERT(rc == -EEXIST); 404 405 /* Alias is used first time, so this one should pass */ 406 rc = spdk_bdev_alias_add(bdev[1], "proper alias 1"); 407 CU_ASSERT(rc == 0); 408 409 /* Trying removing an alias from registered bdevs */ 410 411 /* Alias is not on a bdev aliases list, so this one should fail */ 412 rc = spdk_bdev_alias_del(bdev[0], "not existing"); 413 CU_ASSERT(rc == -ENOENT); 414 415 /* Alias is present on a bdev aliases list, so this one should pass */ 416 rc = spdk_bdev_alias_del(bdev[0], "proper alias 0"); 417 CU_ASSERT(rc == 0); 418 419 /* Alias is present on a bdev aliases list, so this one should pass */ 420 rc = spdk_bdev_alias_del(bdev[1], "proper alias 1"); 421 CU_ASSERT(rc == 0); 422 423 /* Trying to remove name instead of alias, so this one should fail, name cannot be changed or removed */ 424 rc = spdk_bdev_alias_del(bdev[0], bdev[0]->name); 425 CU_ASSERT(rc != 0); 426 427 /* Unregister and free bdevs */ 428 spdk_bdev_unregister(bdev[0], NULL, NULL); 429 spdk_bdev_unregister(bdev[1], NULL, NULL); 430 431 free(bdev[0]); 432 free(bdev[1]); 433 } 434 435 int 436 main(int argc, char **argv) 437 { 438 CU_pSuite suite = NULL; 439 unsigned int num_failures; 440 441 if (CU_initialize_registry() != CUE_SUCCESS) { 442 return CU_get_error(); 443 } 444 445 suite = CU_add_suite("bdev", null_init, null_clean); 446 if (suite == NULL) { 447 CU_cleanup_registry(); 448 return CU_get_error(); 449 } 450 451 if ( 452 CU_add_test(suite, "bytes_to_blocks_test", bytes_to_blocks_test) == NULL || 453 CU_add_test(suite, "io_valid", io_valid_test) == NULL || 454 CU_add_test(suite, "open_write", open_write_test) == NULL || 455 CU_add_test(suite, "part", part_test) == NULL || 456 CU_add_test(suite, "alias_add_del", alias_add_del_test) == NULL 457 ) { 458 CU_cleanup_registry(); 459 return CU_get_error(); 460 } 461 462 CU_basic_set_mode(CU_BRM_VERBOSE); 463 CU_basic_run_tests(); 464 num_failures = CU_get_number_of_failures(); 465 CU_cleanup_registry(); 466 return num_failures; 467 } 468