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) 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 lvs = NULL; 109 error = -1; 110 } else { 111 lvs = calloc(1, sizeof(*lvs)); 112 lvs->bs_dev = bs_dev; 113 error = 0; 114 } 115 cb_fn(cb_arg, lvs, error); 116 117 return 0; 118 } 119 120 int 121 spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, 122 void *cb_arg) 123 { 124 struct spdk_lvol_store_req *req = cb_arg; 125 free(req); 126 free(lvs); 127 128 return 0; 129 } 130 131 int 132 spdk_lvol_resize(struct spdk_lvol *lvol, size_t sz, 133 spdk_lvol_op_complete cb_fn, void *cb_arg) 134 { 135 cb_fn(cb_arg, 0); 136 137 return 0; 138 } 139 140 uint64_t 141 spdk_bs_get_cluster_size(struct spdk_blob_store *bs) 142 { 143 return g_cluster_size; 144 } 145 146 struct spdk_bdev * 147 spdk_bdev_get_by_name(const char *bdev_name) 148 { 149 if (!strcmp(g_base_bdev->name, bdev_name)) { 150 return g_base_bdev; 151 } 152 153 return NULL; 154 } 155 156 void 157 spdk_lvol_close(struct spdk_lvol *lvol) 158 { 159 } 160 161 void 162 spdk_lvol_destroy(struct spdk_lvol *lvol) 163 { 164 SPDK_CU_ASSERT_FATAL(lvol == g_lvol); 165 free(lvol->name); 166 free(lvol); 167 g_lvol = NULL; 168 } 169 170 bool 171 spdk_is_bdev_opened(struct spdk_bdev *bdev) 172 { 173 struct spdk_bdev *base; 174 175 if (bdev->bdev_opened) { 176 return true; 177 } 178 179 TAILQ_FOREACH(base, &bdev->base_bdevs, base_bdev_link) { 180 if (spdk_is_bdev_opened(base)) { 181 return true; 182 } 183 } 184 185 return false; 186 } 187 188 void 189 spdk_bdev_io_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status status) 190 { 191 } 192 193 struct spdk_io_channel *spdk_lvol_get_io_channel(struct spdk_lvol *lvol) 194 { 195 return NULL; 196 } 197 198 void 199 spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb cb) 200 { 201 } 202 203 void 204 spdk_bs_io_read_blob(struct spdk_blob *blob, struct spdk_io_channel *channel, 205 void *payload, uint64_t offset, uint64_t length, 206 spdk_blob_op_complete cb_fn, void *cb_arg) 207 { 208 } 209 210 void 211 spdk_bs_io_write_blob(struct spdk_blob *blob, struct spdk_io_channel *channel, 212 void *payload, uint64_t offset, uint64_t length, 213 spdk_blob_op_complete cb_fn, void *cb_arg) 214 { 215 } 216 217 void 218 spdk_bs_io_writev_blob(struct spdk_blob *blob, struct spdk_io_channel *channel, 219 struct iovec *iov, int iovcnt, uint64_t offset, uint64_t length, 220 spdk_blob_op_complete cb_fn, void *cb_arg) 221 { 222 } 223 224 void 225 spdk_bs_io_readv_blob(struct spdk_blob *blob, struct spdk_io_channel *channel, 226 struct iovec *iov, int iovcnt, uint64_t offset, uint64_t length, 227 spdk_blob_op_complete cb_fn, void *cb_arg) 228 { 229 } 230 231 void 232 spdk_bs_io_flush_channel(struct spdk_io_channel *channel, spdk_blob_op_complete cb_fn, void *cb_arg) 233 { 234 } 235 236 void 237 spdk_bdev_module_list_add(struct spdk_bdev_module_if *bdev_module) 238 { 239 } 240 241 int 242 spdk_json_write_name(struct spdk_json_write_ctx *w, const char *name) 243 { 244 return 0; 245 } 246 247 int 248 spdk_json_write_string(struct spdk_json_write_ctx *w, const char *val) 249 { 250 return 0; 251 } 252 253 const char * 254 spdk_bdev_get_name(const struct spdk_bdev *bdev) 255 { 256 return "test"; 257 } 258 259 void 260 spdk_bdev_register(struct spdk_bdev *bdev) 261 { 262 } 263 264 void 265 spdk_bdev_module_examine_done(struct spdk_bdev_module_if *module) 266 { 267 } 268 269 int 270 spdk_lvol_create(struct spdk_lvol_store *lvs, size_t sz, spdk_lvol_op_with_handle_complete cb_fn, 271 void *cb_arg) 272 { 273 struct spdk_lvol *lvol = calloc(1, sizeof(*lvol)); 274 275 SPDK_CU_ASSERT_FATAL(lvol != NULL); 276 277 278 lvol->lvol_store = lvs; 279 lvol->sz = sz * 1024 * 1024; 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 static void 365 ut_lvol_resize(void) 366 { 367 int sz = 10; 368 int rc = 0; 369 370 g_lvs = calloc(1, sizeof(*g_lvs)); 371 g_lvs_bdev = calloc(1, sizeof(*g_lvs_bdev)); 372 g_base_bdev = calloc(1, sizeof(*g_base_bdev)); 373 g_lvs_bdev->lvs = g_lvs; 374 g_lvs_bdev->bdev = g_base_bdev; 375 376 377 uuid_generate_time(g_lvs->uuid); 378 g_base_bdev->blocklen = 4096; 379 TAILQ_INSERT_TAIL(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores); 380 381 /* Successful lvol create */ 382 g_lvolerrno = -1; 383 rc = vbdev_lvol_create(g_lvs->uuid, sz, vbdev_lvol_create_complete, NULL); 384 CU_ASSERT(rc == 0); 385 CU_ASSERT(g_lvolerrno == 0); 386 SPDK_CU_ASSERT_FATAL(g_lvol != NULL); 387 388 g_base_bdev->bdev_opened = false; 389 g_base_bdev->ctxt = g_lvol; 390 391 g_base_bdev->name = spdk_sprintf_alloc("%s", g_lvol->name); 392 393 /* Successful lvol resize */ 394 rc = vbdev_lvol_resize(g_lvol->name, 20, vbdev_lvol_resize_complete, NULL); 395 CU_ASSERT(rc == 0); 396 CU_ASSERT(g_base_bdev->blockcnt == 20 * g_cluster_size / g_base_bdev->blocklen); 397 398 /* Resize while bdev is open */ 399 g_base_bdev->bdev_opened = true; 400 rc = vbdev_lvol_resize(g_lvol->name, 20, vbdev_lvol_resize_complete, NULL); 401 CU_ASSERT(rc != 0); 402 403 /* Resize with wrong bdev name */ 404 g_base_bdev->bdev_opened = false; 405 rc = vbdev_lvol_resize("wrong name", 20, vbdev_lvol_resize_complete, NULL); 406 CU_ASSERT(rc != 0); 407 408 /* Resize with correct bdev name, but wrong lvol name */ 409 sprintf(g_lvol->name, "wrong name"); 410 rc = vbdev_lvol_resize(g_base_bdev->name, 20, vbdev_lvol_resize_complete, NULL); 411 CU_ASSERT(rc != 0); 412 413 /* Successful lvol destruct */ 414 vbdev_lvol_destruct(g_lvol); 415 CU_ASSERT(g_lvol == NULL); 416 417 TAILQ_REMOVE(&g_spdk_lvol_pairs, g_lvs_bdev, lvol_stores); 418 free(g_lvs); 419 free(g_lvs_bdev); 420 free(g_base_bdev->name); 421 free(g_base_bdev); 422 } 423 424 static void 425 ut_lvs_init(void) 426 { 427 int rc = 0; 428 struct spdk_lvol_store *lvs; 429 struct spdk_bs_dev *bs_dev_temp; 430 431 /* spdk_lvs_init() fails */ 432 lvol_store_initialize_fail = true; 433 434 rc = vbdev_lvs_create(&g_bdev, lvol_store_op_with_handle_complete, NULL); 435 CU_ASSERT(rc != 0); 436 CU_ASSERT(g_lvserrno == 0); 437 CU_ASSERT(g_lvol_store == NULL); 438 CU_ASSERT(g_bs_dev == NULL); 439 440 lvol_store_initialize_fail = false; 441 442 /* spdk_lvs_init_cb() fails */ 443 lvol_store_initialize_cb_fail = true; 444 445 rc = vbdev_lvs_create(&g_bdev, lvol_store_op_with_handle_complete, NULL); 446 CU_ASSERT(rc == 0); 447 CU_ASSERT(g_lvserrno != 0); 448 CU_ASSERT(g_lvol_store == NULL); 449 CU_ASSERT(g_bs_dev == NULL); 450 451 lvol_store_initialize_cb_fail = false; 452 453 /* Lvol store is succesfully created */ 454 rc = vbdev_lvs_create(&g_bdev, lvol_store_op_with_handle_complete, NULL); 455 CU_ASSERT(rc == 0); 456 CU_ASSERT(g_lvserrno == 0); 457 CU_ASSERT(g_lvol_store != NULL); 458 CU_ASSERT(g_bs_dev != NULL); 459 460 lvs = g_lvol_store; 461 g_lvol_store = NULL; 462 bs_dev_temp = g_bs_dev; 463 g_bs_dev = NULL; 464 465 /* Bdev with lvol store already claimed */ 466 rc = vbdev_lvs_create(&g_bdev, lvol_store_op_with_handle_complete, NULL); 467 CU_ASSERT(rc != 0); 468 CU_ASSERT(g_lvserrno == 0); 469 CU_ASSERT(g_lvol_store == NULL); 470 CU_ASSERT(g_bs_dev == NULL); 471 472 /* Destruct lvol store */ 473 g_bs_dev = bs_dev_temp; 474 475 vbdev_lvs_destruct(lvs, lvol_store_op_complete, NULL); 476 CU_ASSERT(g_lvserrno == 0); 477 CU_ASSERT(g_lvol_store == NULL); 478 free(g_bs_dev); 479 480 } 481 482 int main(int argc, char **argv) 483 { 484 CU_pSuite suite = NULL; 485 unsigned int num_failures; 486 487 if (CU_initialize_registry() != CUE_SUCCESS) { 488 return CU_get_error(); 489 } 490 491 suite = CU_add_suite("lvol", NULL, NULL); 492 if (suite == NULL) { 493 CU_cleanup_registry(); 494 return CU_get_error(); 495 } 496 497 if ( 498 CU_add_test(suite, "ut_lvs_init", ut_lvs_init) == NULL || 499 CU_add_test(suite, "ut_lvol_init", ut_lvol_init) == NULL || 500 CU_add_test(suite, "ut_lvol_resize", ut_lvol_resize) == NULL 501 ) { 502 CU_cleanup_registry(); 503 return CU_get_error(); 504 } 505 506 CU_basic_set_mode(CU_BRM_VERBOSE); 507 CU_basic_run_tests(); 508 num_failures = CU_get_number_of_failures(); 509 CU_cleanup_registry(); 510 return num_failures; 511 } 512