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 #include "spdk/string.h" 36 37 #include "vbdev_lvol.c" 38 39 #define SPDK_BS_PAGE_SIZE 0x1000 40 41 int g_lvolerrno; 42 int g_lvserrno; 43 int g_cluster_size; 44 struct spdk_lvol_store *g_lvs = NULL; 45 struct spdk_lvol *g_lvol = NULL; 46 struct lvol_store_bdev *g_lvs_bdev = NULL; 47 struct spdk_bdev *g_base_bdev = NULL; 48 49 50 static struct spdk_bdev g_bdev = {}; 51 static struct spdk_bs_dev *g_bs_dev = NULL; 52 static struct spdk_lvol_store *g_lvol_store = NULL; 53 bool lvol_store_initialize_fail = false; 54 bool lvol_store_initialize_cb_fail = false; 55 bool lvol_already_opened = false; 56 57 int 58 spdk_bs_bdev_claim(struct spdk_bs_dev *bs_dev, struct spdk_bdev_module_if *module) 59 { 60 if (lvol_already_opened == true) 61 return -1; 62 63 lvol_already_opened = true; 64 65 return 0; 66 } 67 68 void 69 spdk_vbdev_unregister(struct spdk_bdev *vbdev) 70 { 71 SPDK_CU_ASSERT_FATAL(vbdev != NULL); 72 vbdev->fn_table->destruct(vbdev->ctxt); 73 } 74 75 uint64_t 76 spdk_bs_get_page_size(struct spdk_blob_store *bs) 77 { 78 return SPDK_BS_PAGE_SIZE; 79 } 80 81 static void 82 bdev_blob_destroy(struct spdk_bs_dev *bs_dev) 83 { 84 CU_ASSERT(g_bs_dev != NULL); 85 CU_ASSERT(bs_dev != NULL); 86 CU_ASSERT(g_bs_dev == bs_dev); 87 free(bs_dev); 88 g_bs_dev = NULL; 89 lvol_already_opened = false; 90 } 91 92 struct spdk_bs_dev * 93 spdk_bdev_create_bs_dev(struct spdk_bdev *bdev, spdk_bdev_remove_cb_t remove_cb, void *remove_ctx) 94 { 95 struct spdk_bs_dev *bs_dev; 96 97 if (lvol_already_opened == true) 98 return NULL; 99 100 bs_dev = calloc(1, sizeof(*bs_dev)); 101 SPDK_CU_ASSERT_FATAL(bs_dev != NULL); 102 bs_dev->destroy = bdev_blob_destroy; 103 104 CU_ASSERT(g_bs_dev == NULL); 105 g_bs_dev = bs_dev; 106 return bs_dev; 107 } 108 109 int 110 spdk_lvs_init(struct spdk_bs_dev *bs_dev, struct spdk_lvs_opts *o, 111 spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg) 112 { 113 struct spdk_lvol_store *lvs; 114 int error = 0; 115 116 if (lvol_store_initialize_fail) 117 return -1; 118 119 if (lvol_store_initialize_cb_fail) { 120 bs_dev->destroy(bs_dev); 121 lvs = NULL; 122 error = -1; 123 } else { 124 lvs = calloc(1, sizeof(*lvs)); 125 SPDK_CU_ASSERT_FATAL(lvs != NULL); 126 lvs->bs_dev = bs_dev; 127 error = 0; 128 } 129 cb_fn(cb_arg, lvs, error); 130 131 return 0; 132 } 133 134 int 135 spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, void *cb_arg) 136 { 137 g_lvol_store = NULL; 138 free(lvs); 139 140 g_bs_dev->destroy(g_bs_dev); 141 142 if (cb_fn != NULL) 143 cb_fn(cb_arg, 0); 144 145 return 0; 146 } 147 148 int 149 spdk_lvol_resize(struct spdk_lvol *lvol, size_t sz, 150 spdk_lvol_op_complete cb_fn, void *cb_arg) 151 { 152 cb_fn(cb_arg, 0); 153 154 return 0; 155 } 156 157 uint64_t 158 spdk_bs_get_cluster_size(struct spdk_blob_store *bs) 159 { 160 return g_cluster_size; 161 } 162 163 struct spdk_bdev * 164 spdk_bdev_get_by_name(const char *bdev_name) 165 { 166 if (!strcmp(g_base_bdev->name, bdev_name)) { 167 return g_base_bdev; 168 } 169 170 return NULL; 171 } 172 173 void 174 spdk_lvol_close(struct spdk_lvol *lvol) 175 { 176 struct spdk_lvs_req *destruct_req; 177 178 SPDK_CU_ASSERT_FATAL(lvol == g_lvol); 179 180 TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link); 181 182 destruct_req = lvol->lvol_store->destruct_req; 183 if (destruct_req && TAILQ_EMPTY(&lvol->lvol_store->lvols)) { 184 spdk_lvs_unload(lvol->lvol_store, destruct_req->cb_fn, destruct_req->cb_arg); 185 free(destruct_req); 186 } 187 188 free(lvol->name); 189 free(lvol); 190 g_lvol = NULL; 191 } 192 193 void 194 spdk_lvol_destroy(struct spdk_lvol *lvol) 195 { 196 /* Lvol destroy and close are effectively the same from UT perspective */ 197 spdk_lvol_close(lvol); 198 } 199 200 void 201 spdk_bdev_io_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status status) 202 { 203 } 204 205 struct spdk_io_channel *spdk_lvol_get_io_channel(struct spdk_lvol *lvol) 206 { 207 return NULL; 208 } 209 210 void 211 spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb cb, uint64_t len) 212 { 213 } 214 215 void 216 spdk_bs_io_read_blob(struct spdk_blob *blob, struct spdk_io_channel *channel, 217 void *payload, uint64_t offset, uint64_t length, 218 spdk_blob_op_complete cb_fn, void *cb_arg) 219 { 220 } 221 222 void 223 spdk_bs_io_write_blob(struct spdk_blob *blob, struct spdk_io_channel *channel, 224 void *payload, uint64_t offset, uint64_t length, 225 spdk_blob_op_complete cb_fn, void *cb_arg) 226 { 227 } 228 229 void 230 spdk_bs_io_writev_blob(struct spdk_blob *blob, struct spdk_io_channel *channel, 231 struct iovec *iov, int iovcnt, uint64_t offset, uint64_t length, 232 spdk_blob_op_complete cb_fn, void *cb_arg) 233 { 234 } 235 236 void 237 spdk_bs_io_readv_blob(struct spdk_blob *blob, struct spdk_io_channel *channel, 238 struct iovec *iov, int iovcnt, uint64_t offset, uint64_t length, 239 spdk_blob_op_complete cb_fn, void *cb_arg) 240 { 241 } 242 243 void 244 spdk_bs_io_flush_channel(struct spdk_io_channel *channel, spdk_blob_op_complete cb_fn, void *cb_arg) 245 { 246 } 247 248 void 249 spdk_bdev_module_list_add(struct spdk_bdev_module_if *bdev_module) 250 { 251 } 252 253 int 254 spdk_json_write_name(struct spdk_json_write_ctx *w, const char *name) 255 { 256 return 0; 257 } 258 259 int 260 spdk_json_write_string(struct spdk_json_write_ctx *w, const char *val) 261 { 262 return 0; 263 } 264 265 int 266 spdk_json_write_object_begin(struct spdk_json_write_ctx *w) 267 { 268 return 0; 269 } 270 271 int 272 spdk_json_write_object_end(struct spdk_json_write_ctx *w) 273 { 274 return 0; 275 } 276 277 const char * 278 spdk_bdev_get_name(const struct spdk_bdev *bdev) 279 { 280 return "test"; 281 } 282 283 void 284 spdk_vbdev_register(struct spdk_bdev *vbdev, struct spdk_bdev **base_bdevs, int base_bdev_count) 285 { 286 } 287 288 void 289 spdk_bdev_module_examine_done(struct spdk_bdev_module_if *module) 290 { 291 } 292 293 int 294 spdk_lvol_create(struct spdk_lvol_store *lvs, size_t sz, spdk_lvol_op_with_handle_complete cb_fn, 295 void *cb_arg) 296 { 297 struct spdk_lvol *lvol = calloc(1, sizeof(*lvol)); 298 299 SPDK_CU_ASSERT_FATAL(lvol != NULL); 300 301 lvol->lvol_store = lvs; 302 lvol->name = spdk_sprintf_alloc("%s", "UNIT_TEST_UUID"); 303 SPDK_CU_ASSERT_FATAL(lvol->name != NULL); 304 305 TAILQ_INIT(&lvs->lvols); 306 TAILQ_INSERT_TAIL(&lvol->lvol_store->lvols, lvol, link); 307 308 cb_fn(cb_arg, lvol, 0); 309 310 return 0; 311 } 312 313 static void 314 lvol_store_op_complete(void *cb_arg, int lvserrno) 315 { 316 g_lvserrno = lvserrno; 317 return; 318 } 319 320 static void 321 lvol_store_op_with_handle_complete(void *cb_arg, struct spdk_lvol_store *lvs, int lvserrno) 322 { 323 g_lvserrno = lvserrno; 324 g_lvol_store = lvs; 325 return; 326 } 327 328 static void 329 vbdev_lvol_create_complete(void *cb_arg, struct spdk_lvol *lvol, int lvolerrno) 330 { 331 g_lvolerrno = lvolerrno; 332 g_lvol = lvol; 333 } 334 335 static void 336 vbdev_lvol_resize_complete(void *cb_arg, int lvolerrno) 337 { 338 g_lvolerrno = lvolerrno; 339 } 340 341 static void 342 ut_lvs_destroy(void) 343 { 344 int rc = 0; 345 int sz = 10; 346 struct spdk_lvol_store *lvs; 347 348 /* Lvol store is succesfully created */ 349 rc = vbdev_lvs_create(&g_bdev, 0, lvol_store_op_with_handle_complete, NULL); 350 CU_ASSERT(rc == 0); 351 CU_ASSERT(g_lvserrno == 0); 352 SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL); 353 CU_ASSERT(g_bs_dev != NULL); 354 355 lvs = g_lvol_store; 356 g_lvol_store = NULL; 357 358 uuid_generate_time(lvs->uuid); 359 360 /* Suuccessfully create lvol, which should be destroyed with lvs later */ 361 g_lvolerrno = -1; 362 rc = vbdev_lvol_create(lvs->uuid, sz, vbdev_lvol_create_complete, NULL); 363 CU_ASSERT(rc == 0); 364 CU_ASSERT(g_lvolerrno == 0); 365 SPDK_CU_ASSERT_FATAL(g_lvol != NULL); 366 367 /* Destroy lvol store */ 368 vbdev_lvs_destruct(lvs, lvol_store_op_complete, NULL); 369 CU_ASSERT(g_lvserrno == 0); 370 CU_ASSERT(g_lvol_store == NULL); 371 CU_ASSERT(g_lvol == NULL); 372 } 373 374 static void 375 ut_lvol_init(void) 376 { 377 uuid_t wrong_uuid; 378 int sz = 10; 379 int rc; 380 381 g_lvs = calloc(1, sizeof(*g_lvs)); 382 SPDK_CU_ASSERT_FATAL(g_lvs != NULL); 383 g_lvs_bdev = calloc(1, sizeof(*g_lvs_bdev)); 384 SPDK_CU_ASSERT_FATAL(g_lvs_bdev != NULL); 385 g_base_bdev = calloc(1, sizeof(*g_base_bdev)); 386 SPDK_CU_ASSERT_FATAL(g_base_bdev != NULL); 387 388 g_lvs_bdev->lvs = g_lvs; 389 g_lvs_bdev->bdev = g_base_bdev; 390 391 uuid_generate_time(g_lvs->uuid); 392 uuid_generate_time(wrong_uuid); 393 394 /* Incorrect uuid set */ 395 g_lvolerrno = 0; 396 rc = vbdev_lvol_create(wrong_uuid, sz, vbdev_lvol_create_complete, NULL); 397 CU_ASSERT(rc == -ENODEV); 398 399 TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores); 400 401 /* Successful lvol create */ 402 g_lvolerrno = -1; 403 rc = vbdev_lvol_create(g_lvs->uuid, sz, vbdev_lvol_create_complete, NULL); 404 SPDK_CU_ASSERT_FATAL(rc == 0); 405 CU_ASSERT(g_lvol != NULL); 406 CU_ASSERT(g_lvolerrno == 0); 407 408 /* Successful lvol destruct */ 409 vbdev_lvol_destruct(g_lvol); 410 CU_ASSERT(g_lvol == NULL); 411 412 TAILQ_REMOVE(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores); 413 414 free(g_lvs); 415 free(g_lvs_bdev); 416 free(g_base_bdev); 417 418 419 } 420 421 static void 422 ut_lvol_hotremove(void) 423 { 424 int rc = 0; 425 426 lvol_store_initialize_fail = false; 427 lvol_store_initialize_cb_fail = false; 428 lvol_already_opened = false; 429 g_bs_dev = NULL; 430 431 /* Lvol store is succesfully created */ 432 rc = vbdev_lvs_create(&g_bdev, 0, lvol_store_op_with_handle_complete, NULL); 433 CU_ASSERT(rc == 0); 434 CU_ASSERT(g_lvserrno == 0); 435 CU_ASSERT(g_lvol_store != NULL); 436 CU_ASSERT(g_bs_dev != NULL); 437 438 /* Hot remove callback with NULL - stability check */ 439 vbdev_lvs_hotremove_cb(NULL); 440 441 /* Hot remove lvs on bdev removal */ 442 vbdev_lvs_hotremove_cb(&g_bdev); 443 444 CU_ASSERT(g_lvol_store == NULL); 445 CU_ASSERT(TAILQ_EMPTY(&g_spdk_lvol_pairs)); 446 447 } 448 449 static void 450 ut_lvol_resize(void) 451 { 452 int sz = 10; 453 int rc = 0; 454 455 g_lvs = calloc(1, sizeof(*g_lvs)); 456 g_lvs_bdev = calloc(1, sizeof(*g_lvs_bdev)); 457 g_base_bdev = calloc(1, sizeof(*g_base_bdev)); 458 g_lvs_bdev->lvs = g_lvs; 459 g_lvs_bdev->bdev = g_base_bdev; 460 461 462 uuid_generate_time(g_lvs->uuid); 463 g_base_bdev->blocklen = 4096; 464 TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores); 465 466 /* Successful lvol create */ 467 g_lvolerrno = -1; 468 rc = vbdev_lvol_create(g_lvs->uuid, sz, vbdev_lvol_create_complete, NULL); 469 CU_ASSERT(rc == 0); 470 CU_ASSERT(g_lvolerrno == 0); 471 SPDK_CU_ASSERT_FATAL(g_lvol != NULL); 472 473 g_base_bdev->ctxt = g_lvol; 474 475 g_base_bdev->name = spdk_sprintf_alloc("%s", g_lvol->name); 476 477 /* Successful lvol resize */ 478 rc = vbdev_lvol_resize(g_lvol->name, 20, vbdev_lvol_resize_complete, NULL); 479 CU_ASSERT(rc == 0); 480 CU_ASSERT(g_base_bdev->blockcnt == 20 * g_cluster_size / g_base_bdev->blocklen); 481 482 /* Resize with wrong bdev name */ 483 rc = vbdev_lvol_resize("wrong name", 20, vbdev_lvol_resize_complete, NULL); 484 CU_ASSERT(rc != 0); 485 486 /* Resize with correct bdev name, but wrong lvol name */ 487 free(g_lvol->name); 488 g_lvol->name = strdup("wrong name"); 489 SPDK_CU_ASSERT_FATAL(g_lvol->name != NULL); 490 rc = vbdev_lvol_resize(g_base_bdev->name, 20, vbdev_lvol_resize_complete, NULL); 491 CU_ASSERT(rc != 0); 492 493 /* Successful lvol destruct */ 494 vbdev_lvol_destruct(g_lvol); 495 CU_ASSERT(g_lvol == NULL); 496 497 TAILQ_REMOVE(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores); 498 free(g_lvs); 499 free(g_lvs_bdev); 500 free(g_base_bdev->name); 501 free(g_base_bdev); 502 } 503 504 static void 505 ut_lvs_init(void) 506 { 507 int rc = 0; 508 struct spdk_lvol_store *lvs; 509 struct spdk_bs_dev *bs_dev_temp; 510 511 /* spdk_lvs_init() fails */ 512 lvol_store_initialize_fail = true; 513 514 rc = vbdev_lvs_create(&g_bdev, 0, lvol_store_op_with_handle_complete, NULL); 515 CU_ASSERT(rc != 0); 516 CU_ASSERT(g_lvserrno == 0); 517 CU_ASSERT(g_lvol_store == NULL); 518 CU_ASSERT(g_bs_dev == NULL); 519 520 lvol_store_initialize_fail = false; 521 522 /* spdk_lvs_init_cb() fails */ 523 lvol_store_initialize_cb_fail = true; 524 525 rc = vbdev_lvs_create(&g_bdev, 0, lvol_store_op_with_handle_complete, NULL); 526 CU_ASSERT(rc == 0); 527 CU_ASSERT(g_lvserrno != 0); 528 CU_ASSERT(g_lvol_store == NULL); 529 CU_ASSERT(g_bs_dev == NULL); 530 531 lvol_store_initialize_cb_fail = false; 532 533 /* Lvol store is succesfully created */ 534 rc = vbdev_lvs_create(&g_bdev, 0, lvol_store_op_with_handle_complete, NULL); 535 CU_ASSERT(rc == 0); 536 CU_ASSERT(g_lvserrno == 0); 537 CU_ASSERT(g_lvol_store != NULL); 538 CU_ASSERT(g_bs_dev != NULL); 539 540 lvs = g_lvol_store; 541 g_lvol_store = NULL; 542 bs_dev_temp = g_bs_dev; 543 g_bs_dev = NULL; 544 545 /* Bdev with lvol store already claimed */ 546 rc = vbdev_lvs_create(&g_bdev, 0, lvol_store_op_with_handle_complete, NULL); 547 CU_ASSERT(rc != 0); 548 CU_ASSERT(g_lvserrno == 0); 549 CU_ASSERT(g_lvol_store == NULL); 550 CU_ASSERT(g_bs_dev == NULL); 551 552 /* Destruct lvol store */ 553 g_bs_dev = bs_dev_temp; 554 555 vbdev_lvs_destruct(lvs, lvol_store_op_complete, NULL); 556 CU_ASSERT(g_lvserrno == 0); 557 CU_ASSERT(g_lvol_store == NULL); 558 CU_ASSERT(g_bs_dev == NULL); 559 free(g_bs_dev); 560 561 } 562 563 int main(int argc, char **argv) 564 { 565 CU_pSuite suite = NULL; 566 unsigned int num_failures; 567 568 if (CU_initialize_registry() != CUE_SUCCESS) { 569 return CU_get_error(); 570 } 571 572 suite = CU_add_suite("lvol", NULL, NULL); 573 if (suite == NULL) { 574 CU_cleanup_registry(); 575 return CU_get_error(); 576 } 577 578 if ( 579 CU_add_test(suite, "ut_lvs_init", ut_lvs_init) == NULL || 580 CU_add_test(suite, "ut_lvol_init", ut_lvol_init) == NULL || 581 CU_add_test(suite, "ut_lvs_destroy", ut_lvs_destroy) == NULL || 582 CU_add_test(suite, "ut_lvol_resize", ut_lvol_resize) == NULL || 583 CU_add_test(suite, "lvol_hotremove", ut_lvol_hotremove) == NULL 584 ) { 585 CU_cleanup_registry(); 586 return CU_get_error(); 587 } 588 589 CU_basic_set_mode(CU_BRM_VERBOSE); 590 CU_basic_run_tests(); 591 num_failures = CU_get_number_of_failures(); 592 CU_cleanup_registry(); 593 return num_failures; 594 } 595