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