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