1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2017 Intel Corporation. 3 * All rights reserved. 4 * Copyright (c) 2021-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 5 */ 6 7 #include "spdk/stdinc.h" 8 9 #include "spdk_internal/cunit.h" 10 #include "spdk/blob.h" 11 #include "spdk/string.h" 12 13 #include "common/lib/ut_multithread.c" 14 #include "../bs_dev_common.c" 15 #include "thread/thread.c" 16 #include "blob/blobstore.c" 17 #include "blob/request.c" 18 #include "blob/zeroes.c" 19 #include "blob/blob_bs_dev.c" 20 #include "esnap_dev.c" 21 22 struct spdk_blob_store *g_bs; 23 spdk_blob_id g_blobid; 24 struct spdk_blob *g_blob, *g_blob2; 25 int g_bserrno, g_bserrno2; 26 struct spdk_xattr_names *g_names; 27 int g_done; 28 char *g_xattr_names[] = {"first", "second", "third"}; 29 char *g_xattr_values[] = {"one", "two", "three"}; 30 uint64_t g_ctx = 1729; 31 bool g_use_extent_table = false; 32 33 struct spdk_bs_super_block_ver1 { 34 uint8_t signature[8]; 35 uint32_t version; 36 uint32_t length; 37 uint32_t clean; /* If there was a clean shutdown, this is 1. */ 38 spdk_blob_id super_blob; 39 40 uint32_t cluster_size; /* In bytes */ 41 42 uint32_t used_page_mask_start; /* Offset from beginning of disk, in pages */ 43 uint32_t used_page_mask_len; /* Count, in pages */ 44 45 uint32_t used_cluster_mask_start; /* Offset from beginning of disk, in pages */ 46 uint32_t used_cluster_mask_len; /* Count, in pages */ 47 48 uint32_t md_start; /* Offset from beginning of disk, in pages */ 49 uint32_t md_len; /* Count, in pages */ 50 51 uint8_t reserved[4036]; 52 uint32_t crc; 53 } __attribute__((packed)); 54 SPDK_STATIC_ASSERT(sizeof(struct spdk_bs_super_block_ver1) == 0x1000, "Invalid super block size"); 55 56 static struct spdk_blob *ut_blob_create_and_open(struct spdk_blob_store *bs, 57 struct spdk_blob_opts *blob_opts); 58 static void ut_blob_close_and_delete(struct spdk_blob_store *bs, struct spdk_blob *blob); 59 static void suite_blob_setup(void); 60 static void suite_blob_cleanup(void); 61 62 DEFINE_STUB(spdk_memory_domain_memzero, int, (struct spdk_memory_domain *src_domain, 63 void *src_domain_ctx, struct iovec *iov, uint32_t iovcnt, void (*cpl_cb)(void *, int), 64 void *cpl_cb_arg), 0); 65 66 static bool 67 is_esnap_clone(struct spdk_blob *_blob, const void *id, size_t id_len) 68 { 69 const void *val = NULL; 70 size_t len = 0; 71 bool c0, c1, c2, c3; 72 73 CU_ASSERT(blob_get_xattr_value(_blob, BLOB_EXTERNAL_SNAPSHOT_ID, &val, &len, 74 true) == 0); 75 CU_ASSERT((c0 = (len == id_len))); 76 CU_ASSERT((c1 = (val != NULL && memcmp(val, id, len) == 0))); 77 CU_ASSERT((c2 = !!(_blob->invalid_flags & SPDK_BLOB_EXTERNAL_SNAPSHOT))); 78 CU_ASSERT((c3 = (_blob->parent_id == SPDK_BLOBID_EXTERNAL_SNAPSHOT))); 79 80 return c0 && c1 && c2 && c3; 81 } 82 83 static bool 84 is_not_esnap_clone(struct spdk_blob *_blob) 85 { 86 const void *val = NULL; 87 size_t len = 0; 88 bool c1, c2, c3, c4; 89 90 CU_ASSERT((c1 = (blob_get_xattr_value(_blob, BLOB_EXTERNAL_SNAPSHOT_ID, &val, &len, 91 true) == -ENOENT))); 92 CU_ASSERT((c2 = (val == NULL))); 93 CU_ASSERT((c3 = ((_blob->invalid_flags & SPDK_BLOB_EXTERNAL_SNAPSHOT) == 0))); 94 CU_ASSERT((c4 = (_blob->parent_id != SPDK_BLOBID_EXTERNAL_SNAPSHOT))); 95 96 return c1 && c2 && c3 && c4; 97 } 98 99 #define UT_ASSERT_IS_ESNAP_CLONE(_blob, _id, _len) CU_ASSERT(is_esnap_clone(_blob, _id, _len)) 100 #define UT_ASSERT_IS_NOT_ESNAP_CLONE(_blob) CU_ASSERT(is_not_esnap_clone(_blob)) 101 102 static void 103 _get_xattr_value(void *arg, const char *name, 104 const void **value, size_t *value_len) 105 { 106 uint64_t i; 107 108 SPDK_CU_ASSERT_FATAL(value_len != NULL); 109 SPDK_CU_ASSERT_FATAL(value != NULL); 110 CU_ASSERT(arg == &g_ctx); 111 112 for (i = 0; i < sizeof(g_xattr_names); i++) { 113 if (!strcmp(name, g_xattr_names[i])) { 114 *value_len = strlen(g_xattr_values[i]); 115 *value = g_xattr_values[i]; 116 break; 117 } 118 } 119 } 120 121 static void 122 _get_xattr_value_null(void *arg, const char *name, 123 const void **value, size_t *value_len) 124 { 125 SPDK_CU_ASSERT_FATAL(value_len != NULL); 126 SPDK_CU_ASSERT_FATAL(value != NULL); 127 CU_ASSERT(arg == NULL); 128 129 *value_len = 0; 130 *value = NULL; 131 } 132 133 static int 134 _get_snapshots_count(struct spdk_blob_store *bs) 135 { 136 struct spdk_blob_list *snapshot = NULL; 137 int count = 0; 138 139 TAILQ_FOREACH(snapshot, &bs->snapshots, link) { 140 count += 1; 141 } 142 143 return count; 144 } 145 146 static void 147 ut_spdk_blob_opts_init(struct spdk_blob_opts *opts) 148 { 149 spdk_blob_opts_init(opts, sizeof(*opts)); 150 opts->use_extent_table = g_use_extent_table; 151 } 152 153 static void 154 bs_op_complete(void *cb_arg, int bserrno) 155 { 156 g_bserrno = bserrno; 157 } 158 159 static void 160 bs_op_with_handle_complete(void *cb_arg, struct spdk_blob_store *bs, 161 int bserrno) 162 { 163 g_bs = bs; 164 g_bserrno = bserrno; 165 } 166 167 static void 168 blob_op_complete(void *cb_arg, int bserrno) 169 { 170 if (cb_arg != NULL) { 171 int *errp = cb_arg; 172 173 *errp = bserrno; 174 } 175 g_bserrno = bserrno; 176 } 177 178 static void 179 blob_op_with_id_complete(void *cb_arg, spdk_blob_id blobid, int bserrno) 180 { 181 g_blobid = blobid; 182 g_bserrno = bserrno; 183 } 184 185 static void 186 blob_op_with_handle_complete(void *cb_arg, struct spdk_blob *blb, int bserrno) 187 { 188 g_blob = blb; 189 g_bserrno = bserrno; 190 } 191 192 static void 193 blob_op_with_handle_complete2(void *cb_arg, struct spdk_blob *blob, int bserrno) 194 { 195 if (g_blob == NULL) { 196 g_blob = blob; 197 g_bserrno = bserrno; 198 } else { 199 g_blob2 = blob; 200 g_bserrno2 = bserrno; 201 } 202 } 203 204 static void 205 ut_bs_reload(struct spdk_blob_store **bs, struct spdk_bs_opts *opts) 206 { 207 struct spdk_bs_dev *dev; 208 209 /* Unload the blob store */ 210 spdk_bs_unload(*bs, bs_op_complete, NULL); 211 poll_threads(); 212 CU_ASSERT(g_bserrno == 0); 213 214 dev = init_dev(); 215 /* Load an existing blob store */ 216 spdk_bs_load(dev, opts, bs_op_with_handle_complete, NULL); 217 poll_threads(); 218 CU_ASSERT(g_bserrno == 0); 219 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 220 *bs = g_bs; 221 222 g_bserrno = -1; 223 } 224 225 static void 226 ut_bs_dirty_load(struct spdk_blob_store **bs, struct spdk_bs_opts *opts) 227 { 228 struct spdk_bs_dev *dev; 229 230 /* Dirty shutdown */ 231 bs_free(*bs); 232 233 dev = init_dev(); 234 /* Load an existing blob store */ 235 spdk_bs_load(dev, opts, bs_op_with_handle_complete, NULL); 236 poll_threads(); 237 CU_ASSERT(g_bserrno == 0); 238 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 239 *bs = g_bs; 240 241 g_bserrno = -1; 242 } 243 244 static void 245 blob_init(void) 246 { 247 struct spdk_blob_store *bs; 248 struct spdk_bs_dev *dev; 249 250 dev = init_dev(); 251 252 /* should fail for an unsupported blocklen */ 253 dev->blocklen = 500; 254 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 255 poll_threads(); 256 CU_ASSERT(g_bserrno == -EINVAL); 257 258 dev = init_dev(); 259 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 260 poll_threads(); 261 CU_ASSERT(g_bserrno == 0); 262 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 263 bs = g_bs; 264 265 spdk_bs_unload(bs, bs_op_complete, NULL); 266 poll_threads(); 267 CU_ASSERT(g_bserrno == 0); 268 g_bs = NULL; 269 } 270 271 static void 272 blob_super(void) 273 { 274 struct spdk_blob_store *bs = g_bs; 275 spdk_blob_id blobid; 276 struct spdk_blob_opts blob_opts; 277 278 /* Get the super blob without having set one */ 279 spdk_bs_get_super(bs, blob_op_with_id_complete, NULL); 280 poll_threads(); 281 CU_ASSERT(g_bserrno == -ENOENT); 282 CU_ASSERT(g_blobid == SPDK_BLOBID_INVALID); 283 284 /* Create a blob */ 285 ut_spdk_blob_opts_init(&blob_opts); 286 spdk_bs_create_blob_ext(bs, &blob_opts, blob_op_with_id_complete, NULL); 287 poll_threads(); 288 CU_ASSERT(g_bserrno == 0); 289 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 290 blobid = g_blobid; 291 292 /* Set the blob as the super blob */ 293 spdk_bs_set_super(bs, blobid, blob_op_complete, NULL); 294 poll_threads(); 295 CU_ASSERT(g_bserrno == 0); 296 297 /* Get the super blob */ 298 spdk_bs_get_super(bs, blob_op_with_id_complete, NULL); 299 poll_threads(); 300 CU_ASSERT(g_bserrno == 0); 301 CU_ASSERT(blobid == g_blobid); 302 } 303 304 static void 305 blob_open(void) 306 { 307 struct spdk_blob_store *bs = g_bs; 308 struct spdk_blob *blob; 309 struct spdk_blob_opts blob_opts; 310 spdk_blob_id blobid, blobid2; 311 312 ut_spdk_blob_opts_init(&blob_opts); 313 spdk_bs_create_blob_ext(bs, &blob_opts, blob_op_with_id_complete, NULL); 314 poll_threads(); 315 CU_ASSERT(g_bserrno == 0); 316 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 317 blobid = g_blobid; 318 319 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 320 poll_threads(); 321 CU_ASSERT(g_bserrno == 0); 322 CU_ASSERT(g_blob != NULL); 323 blob = g_blob; 324 325 blobid2 = spdk_blob_get_id(blob); 326 CU_ASSERT(blobid == blobid2); 327 328 /* Try to open file again. It should return success. */ 329 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 330 poll_threads(); 331 CU_ASSERT(g_bserrno == 0); 332 CU_ASSERT(blob == g_blob); 333 334 spdk_blob_close(blob, blob_op_complete, NULL); 335 poll_threads(); 336 CU_ASSERT(g_bserrno == 0); 337 338 /* 339 * Close the file a second time, releasing the second reference. This 340 * should succeed. 341 */ 342 blob = g_blob; 343 spdk_blob_close(blob, blob_op_complete, NULL); 344 poll_threads(); 345 CU_ASSERT(g_bserrno == 0); 346 347 /* 348 * Try to open file again. It should succeed. This tests the case 349 * where the file is opened, closed, then re-opened again. 350 */ 351 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 352 poll_threads(); 353 CU_ASSERT(g_bserrno == 0); 354 CU_ASSERT(g_blob != NULL); 355 blob = g_blob; 356 spdk_blob_close(blob, blob_op_complete, NULL); 357 poll_threads(); 358 CU_ASSERT(g_bserrno == 0); 359 360 /* Try to open file twice in succession. This should return the same 361 * blob object. 362 */ 363 g_blob = NULL; 364 g_blob2 = NULL; 365 g_bserrno = -1; 366 g_bserrno2 = -1; 367 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete2, NULL); 368 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete2, NULL); 369 poll_threads(); 370 CU_ASSERT(g_bserrno == 0); 371 CU_ASSERT(g_bserrno2 == 0); 372 CU_ASSERT(g_blob != NULL); 373 CU_ASSERT(g_blob2 != NULL); 374 CU_ASSERT(g_blob == g_blob2); 375 376 g_bserrno = -1; 377 spdk_blob_close(g_blob, blob_op_complete, NULL); 378 poll_threads(); 379 CU_ASSERT(g_bserrno == 0); 380 381 ut_blob_close_and_delete(bs, g_blob); 382 } 383 384 static void 385 blob_create(void) 386 { 387 struct spdk_blob_store *bs = g_bs; 388 struct spdk_blob *blob; 389 struct spdk_blob_opts opts; 390 spdk_blob_id blobid; 391 392 /* Create blob with 10 clusters */ 393 394 ut_spdk_blob_opts_init(&opts); 395 opts.num_clusters = 10; 396 397 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 398 poll_threads(); 399 CU_ASSERT(g_bserrno == 0); 400 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 401 blobid = g_blobid; 402 403 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 404 poll_threads(); 405 CU_ASSERT(g_bserrno == 0); 406 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 407 blob = g_blob; 408 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 409 410 spdk_blob_close(blob, blob_op_complete, NULL); 411 poll_threads(); 412 CU_ASSERT(g_bserrno == 0); 413 414 /* Create blob with 0 clusters */ 415 416 ut_spdk_blob_opts_init(&opts); 417 opts.num_clusters = 0; 418 419 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 420 poll_threads(); 421 CU_ASSERT(g_bserrno == 0); 422 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 423 blobid = g_blobid; 424 425 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 426 poll_threads(); 427 CU_ASSERT(g_bserrno == 0); 428 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 429 blob = g_blob; 430 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 0); 431 432 spdk_blob_close(blob, blob_op_complete, NULL); 433 poll_threads(); 434 CU_ASSERT(g_bserrno == 0); 435 436 /* Create blob with default options (opts == NULL) */ 437 438 spdk_bs_create_blob_ext(bs, NULL, blob_op_with_id_complete, NULL); 439 poll_threads(); 440 CU_ASSERT(g_bserrno == 0); 441 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 442 blobid = g_blobid; 443 444 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 445 poll_threads(); 446 CU_ASSERT(g_bserrno == 0); 447 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 448 blob = g_blob; 449 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 0); 450 451 spdk_blob_close(blob, blob_op_complete, NULL); 452 poll_threads(); 453 CU_ASSERT(g_bserrno == 0); 454 455 /* Try to create blob with size larger than blobstore */ 456 457 ut_spdk_blob_opts_init(&opts); 458 opts.num_clusters = bs->total_clusters + 1; 459 460 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 461 poll_threads(); 462 CU_ASSERT(g_bserrno == -ENOSPC); 463 } 464 465 static void 466 blob_create_zero_extent(void) 467 { 468 struct spdk_blob_store *bs = g_bs; 469 struct spdk_blob *blob; 470 spdk_blob_id blobid; 471 472 /* Create blob with default options (opts == NULL) */ 473 spdk_bs_create_blob_ext(bs, NULL, blob_op_with_id_complete, NULL); 474 poll_threads(); 475 CU_ASSERT(g_bserrno == 0); 476 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 477 blobid = g_blobid; 478 479 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 480 poll_threads(); 481 CU_ASSERT(g_bserrno == 0); 482 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 483 blob = g_blob; 484 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 0); 485 CU_ASSERT(blob->extent_table_found == true); 486 CU_ASSERT(blob->active.extent_pages_array_size == 0); 487 CU_ASSERT(blob->active.extent_pages == NULL); 488 489 spdk_blob_close(blob, blob_op_complete, NULL); 490 poll_threads(); 491 CU_ASSERT(g_bserrno == 0); 492 493 /* Create blob with NULL internal options */ 494 bs_create_blob(bs, NULL, NULL, blob_op_with_id_complete, NULL); 495 poll_threads(); 496 CU_ASSERT(g_bserrno == 0); 497 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 498 blobid = g_blobid; 499 500 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 501 poll_threads(); 502 CU_ASSERT(g_bserrno == 0); 503 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 504 blob = g_blob; 505 CU_ASSERT(TAILQ_FIRST(&blob->xattrs_internal) == NULL); 506 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 0); 507 CU_ASSERT(blob->extent_table_found == true); 508 CU_ASSERT(blob->active.extent_pages_array_size == 0); 509 CU_ASSERT(blob->active.extent_pages == NULL); 510 511 spdk_blob_close(blob, blob_op_complete, NULL); 512 poll_threads(); 513 CU_ASSERT(g_bserrno == 0); 514 } 515 516 /* 517 * Create and delete one blob in a loop over and over again. This helps ensure 518 * that the internal bit masks tracking used clusters and md_pages are being 519 * tracked correctly. 520 */ 521 static void 522 blob_create_loop(void) 523 { 524 struct spdk_blob_store *bs = g_bs; 525 struct spdk_blob_opts opts; 526 uint32_t i, loop_count; 527 528 loop_count = 4 * spdk_max(spdk_bit_array_capacity(bs->used_md_pages), 529 spdk_bit_pool_capacity(bs->used_clusters)); 530 531 for (i = 0; i < loop_count; i++) { 532 ut_spdk_blob_opts_init(&opts); 533 opts.num_clusters = 1; 534 g_bserrno = -1; 535 g_blobid = SPDK_BLOBID_INVALID; 536 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 537 poll_threads(); 538 CU_ASSERT(g_bserrno == 0); 539 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 540 spdk_bs_delete_blob(bs, g_blobid, blob_op_complete, NULL); 541 poll_threads(); 542 CU_ASSERT(g_bserrno == 0); 543 } 544 } 545 546 static void 547 blob_create_fail(void) 548 { 549 struct spdk_blob_store *bs = g_bs; 550 struct spdk_blob_opts opts; 551 spdk_blob_id blobid; 552 uint32_t used_blobids_count = spdk_bit_array_count_set(bs->used_blobids); 553 uint32_t used_md_pages_count = spdk_bit_array_count_set(bs->used_md_pages); 554 555 /* NULL callback */ 556 ut_spdk_blob_opts_init(&opts); 557 opts.xattrs.names = g_xattr_names; 558 opts.xattrs.get_value = NULL; 559 opts.xattrs.count = 1; 560 opts.xattrs.ctx = &g_ctx; 561 562 blobid = spdk_bit_array_find_first_clear(bs->used_md_pages, 0); 563 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 564 poll_threads(); 565 CU_ASSERT(g_bserrno == -EINVAL); 566 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 567 CU_ASSERT(spdk_bit_array_count_set(bs->used_blobids) == used_blobids_count); 568 CU_ASSERT(spdk_bit_array_count_set(bs->used_md_pages) == used_md_pages_count); 569 570 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 571 poll_threads(); 572 CU_ASSERT(g_bserrno == -ENOENT); 573 SPDK_CU_ASSERT_FATAL(g_blob == NULL); 574 575 ut_bs_reload(&bs, NULL); 576 CU_ASSERT(spdk_bit_array_count_set(bs->used_blobids) == used_blobids_count); 577 CU_ASSERT(spdk_bit_array_count_set(bs->used_md_pages) == used_md_pages_count); 578 579 spdk_bs_iter_first(bs, blob_op_with_handle_complete, NULL); 580 poll_threads(); 581 CU_ASSERT(g_blob == NULL); 582 CU_ASSERT(g_bserrno == -ENOENT); 583 } 584 585 static void 586 blob_create_internal(void) 587 { 588 struct spdk_blob_store *bs = g_bs; 589 struct spdk_blob *blob; 590 struct spdk_blob_opts opts; 591 struct spdk_blob_xattr_opts internal_xattrs; 592 const void *value; 593 size_t value_len; 594 spdk_blob_id blobid; 595 int rc; 596 597 /* Create blob with custom xattrs */ 598 599 ut_spdk_blob_opts_init(&opts); 600 blob_xattrs_init(&internal_xattrs); 601 internal_xattrs.count = 3; 602 internal_xattrs.names = g_xattr_names; 603 internal_xattrs.get_value = _get_xattr_value; 604 internal_xattrs.ctx = &g_ctx; 605 606 bs_create_blob(bs, &opts, &internal_xattrs, blob_op_with_id_complete, NULL); 607 poll_threads(); 608 CU_ASSERT(g_bserrno == 0); 609 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 610 blobid = g_blobid; 611 612 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 613 poll_threads(); 614 CU_ASSERT(g_bserrno == 0); 615 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 616 blob = g_blob; 617 618 rc = blob_get_xattr_value(blob, g_xattr_names[0], &value, &value_len, true); 619 CU_ASSERT(rc == 0); 620 SPDK_CU_ASSERT_FATAL(value != NULL); 621 CU_ASSERT(value_len == strlen(g_xattr_values[0])); 622 CU_ASSERT_NSTRING_EQUAL_FATAL(value, g_xattr_values[0], value_len); 623 624 rc = blob_get_xattr_value(blob, g_xattr_names[1], &value, &value_len, true); 625 CU_ASSERT(rc == 0); 626 SPDK_CU_ASSERT_FATAL(value != NULL); 627 CU_ASSERT(value_len == strlen(g_xattr_values[1])); 628 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[1], value_len); 629 630 rc = blob_get_xattr_value(blob, g_xattr_names[2], &value, &value_len, true); 631 CU_ASSERT(rc == 0); 632 SPDK_CU_ASSERT_FATAL(value != NULL); 633 CU_ASSERT(value_len == strlen(g_xattr_values[2])); 634 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[2], value_len); 635 636 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[0], &value, &value_len); 637 CU_ASSERT(rc != 0); 638 639 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[1], &value, &value_len); 640 CU_ASSERT(rc != 0); 641 642 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[2], &value, &value_len); 643 CU_ASSERT(rc != 0); 644 645 spdk_blob_close(blob, blob_op_complete, NULL); 646 poll_threads(); 647 CU_ASSERT(g_bserrno == 0); 648 649 /* Create blob with NULL internal options */ 650 651 bs_create_blob(bs, NULL, NULL, blob_op_with_id_complete, NULL); 652 poll_threads(); 653 CU_ASSERT(g_bserrno == 0); 654 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 655 blobid = g_blobid; 656 657 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 658 poll_threads(); 659 CU_ASSERT(g_bserrno == 0); 660 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 661 CU_ASSERT(TAILQ_FIRST(&g_blob->xattrs_internal) == NULL); 662 CU_ASSERT(spdk_blob_get_num_clusters(g_blob) == 0); 663 664 blob = g_blob; 665 666 spdk_blob_close(blob, blob_op_complete, NULL); 667 poll_threads(); 668 CU_ASSERT(g_bserrno == 0); 669 } 670 671 static void 672 blob_thin_provision(void) 673 { 674 struct spdk_blob_store *bs; 675 struct spdk_bs_dev *dev; 676 struct spdk_blob *blob; 677 struct spdk_blob_opts opts; 678 struct spdk_bs_opts bs_opts; 679 spdk_blob_id blobid; 680 681 dev = init_dev(); 682 spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); 683 snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE"); 684 685 /* Initialize a new blob store */ 686 spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL); 687 poll_threads(); 688 CU_ASSERT(g_bserrno == 0); 689 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 690 691 bs = g_bs; 692 693 /* Create blob with thin provisioning enabled */ 694 695 ut_spdk_blob_opts_init(&opts); 696 opts.thin_provision = true; 697 opts.num_clusters = 10; 698 699 blob = ut_blob_create_and_open(bs, &opts); 700 blobid = spdk_blob_get_id(blob); 701 CU_ASSERT(blob->invalid_flags & SPDK_BLOB_THIN_PROV); 702 /* In thin provisioning with num_clusters is set, if not using the 703 * extent table, there is no allocation. If extent table is used, 704 * there is related allocation happened. */ 705 if (blob->extent_table_found == true) { 706 CU_ASSERT(blob->active.extent_pages_array_size > 0); 707 CU_ASSERT(blob->active.extent_pages != NULL); 708 } else { 709 CU_ASSERT(blob->active.extent_pages_array_size == 0); 710 CU_ASSERT(blob->active.extent_pages == NULL); 711 } 712 713 spdk_blob_close(blob, blob_op_complete, NULL); 714 CU_ASSERT(g_bserrno == 0); 715 716 /* Do not shut down cleanly. This makes sure that when we load again 717 * and try to recover a valid used_cluster map, that blobstore will 718 * ignore clusters with index 0 since these are unallocated clusters. 719 */ 720 ut_bs_dirty_load(&bs, &bs_opts); 721 722 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 723 poll_threads(); 724 CU_ASSERT(g_bserrno == 0); 725 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 726 blob = g_blob; 727 CU_ASSERT(blob->invalid_flags & SPDK_BLOB_THIN_PROV); 728 729 ut_blob_close_and_delete(bs, blob); 730 731 spdk_bs_unload(bs, bs_op_complete, NULL); 732 poll_threads(); 733 CU_ASSERT(g_bserrno == 0); 734 g_bs = NULL; 735 } 736 737 static void 738 blob_snapshot(void) 739 { 740 struct spdk_blob_store *bs = g_bs; 741 struct spdk_blob *blob; 742 struct spdk_blob *snapshot, *snapshot2; 743 struct spdk_blob_bs_dev *blob_bs_dev; 744 struct spdk_blob_opts opts; 745 struct spdk_blob_xattr_opts xattrs; 746 spdk_blob_id blobid; 747 spdk_blob_id snapshotid; 748 spdk_blob_id snapshotid2; 749 const void *value; 750 size_t value_len; 751 int rc; 752 spdk_blob_id ids[2]; 753 size_t count; 754 755 /* Create blob with 10 clusters */ 756 ut_spdk_blob_opts_init(&opts); 757 opts.num_clusters = 10; 758 759 blob = ut_blob_create_and_open(bs, &opts); 760 blobid = spdk_blob_get_id(blob); 761 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 762 763 /* Create snapshot from blob */ 764 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 0); 765 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 766 poll_threads(); 767 CU_ASSERT(g_bserrno == 0); 768 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 769 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 1); 770 snapshotid = g_blobid; 771 772 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 773 poll_threads(); 774 CU_ASSERT(g_bserrno == 0); 775 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 776 snapshot = g_blob; 777 CU_ASSERT(snapshot->data_ro == true); 778 CU_ASSERT(snapshot->md_ro == true); 779 CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 10); 780 781 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 782 CU_ASSERT(blob->invalid_flags & SPDK_BLOB_THIN_PROV); 783 CU_ASSERT(spdk_mem_all_zero(blob->active.clusters, 784 blob->active.num_clusters * sizeof(blob->active.clusters[0]))); 785 786 /* Try to create snapshot from clone with xattrs */ 787 xattrs.names = g_xattr_names; 788 xattrs.get_value = _get_xattr_value; 789 xattrs.count = 3; 790 xattrs.ctx = &g_ctx; 791 spdk_bs_create_snapshot(bs, blobid, &xattrs, blob_op_with_id_complete, NULL); 792 poll_threads(); 793 CU_ASSERT(g_bserrno == 0); 794 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 795 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 2); 796 snapshotid2 = g_blobid; 797 798 spdk_bs_open_blob(bs, snapshotid2, blob_op_with_handle_complete, NULL); 799 CU_ASSERT(g_bserrno == 0); 800 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 801 snapshot2 = g_blob; 802 CU_ASSERT(snapshot2->data_ro == true); 803 CU_ASSERT(snapshot2->md_ro == true); 804 CU_ASSERT(spdk_blob_get_num_clusters(snapshot2) == 10); 805 806 /* Confirm that blob is backed by snapshot2 and snapshot2 is backed by snapshot */ 807 CU_ASSERT(snapshot->back_bs_dev == NULL); 808 SPDK_CU_ASSERT_FATAL(blob->back_bs_dev != NULL); 809 SPDK_CU_ASSERT_FATAL(snapshot2->back_bs_dev != NULL); 810 811 blob_bs_dev = (struct spdk_blob_bs_dev *)blob->back_bs_dev; 812 CU_ASSERT(blob_bs_dev->blob == snapshot2); 813 814 blob_bs_dev = (struct spdk_blob_bs_dev *)snapshot2->back_bs_dev; 815 CU_ASSERT(blob_bs_dev->blob == snapshot); 816 817 rc = spdk_blob_get_xattr_value(snapshot2, g_xattr_names[0], &value, &value_len); 818 CU_ASSERT(rc == 0); 819 SPDK_CU_ASSERT_FATAL(value != NULL); 820 CU_ASSERT(value_len == strlen(g_xattr_values[0])); 821 CU_ASSERT_NSTRING_EQUAL_FATAL(value, g_xattr_values[0], value_len); 822 823 rc = spdk_blob_get_xattr_value(snapshot2, g_xattr_names[1], &value, &value_len); 824 CU_ASSERT(rc == 0); 825 SPDK_CU_ASSERT_FATAL(value != NULL); 826 CU_ASSERT(value_len == strlen(g_xattr_values[1])); 827 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[1], value_len); 828 829 rc = spdk_blob_get_xattr_value(snapshot2, g_xattr_names[2], &value, &value_len); 830 CU_ASSERT(rc == 0); 831 SPDK_CU_ASSERT_FATAL(value != NULL); 832 CU_ASSERT(value_len == strlen(g_xattr_values[2])); 833 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[2], value_len); 834 835 /* Confirm that blob is clone of snapshot2, and snapshot2 is clone of snapshot */ 836 count = 2; 837 CU_ASSERT(spdk_blob_get_clones(bs, snapshotid2, ids, &count) == 0); 838 CU_ASSERT(count == 1); 839 CU_ASSERT(ids[0] == blobid); 840 841 count = 2; 842 CU_ASSERT(spdk_blob_get_clones(bs, snapshotid, ids, &count) == 0); 843 CU_ASSERT(count == 1); 844 CU_ASSERT(ids[0] == snapshotid2); 845 846 /* Try to create snapshot from snapshot */ 847 spdk_bs_create_snapshot(bs, snapshotid, NULL, blob_op_with_id_complete, NULL); 848 poll_threads(); 849 CU_ASSERT(g_bserrno == -EINVAL); 850 CU_ASSERT(g_blobid == SPDK_BLOBID_INVALID); 851 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 2); 852 853 /* Delete blob and confirm that it is no longer on snapshot2 clone list */ 854 ut_blob_close_and_delete(bs, blob); 855 count = 2; 856 CU_ASSERT(spdk_blob_get_clones(bs, snapshotid2, ids, &count) == 0); 857 CU_ASSERT(count == 0); 858 859 /* Delete snapshot2 and confirm that it is no longer on snapshot clone list */ 860 ut_blob_close_and_delete(bs, snapshot2); 861 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 1); 862 count = 2; 863 CU_ASSERT(spdk_blob_get_clones(bs, snapshotid2, ids, &count) == 0); 864 CU_ASSERT(count == 0); 865 866 ut_blob_close_and_delete(bs, snapshot); 867 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 0); 868 } 869 870 static void 871 blob_snapshot_freeze_io(void) 872 { 873 struct spdk_io_channel *channel; 874 struct spdk_bs_channel *bs_channel; 875 struct spdk_blob_store *bs = g_bs; 876 struct spdk_blob *blob; 877 struct spdk_blob_opts opts; 878 spdk_blob_id blobid; 879 uint32_t num_of_pages = 10; 880 uint8_t payload_read[num_of_pages * SPDK_BS_PAGE_SIZE]; 881 uint8_t payload_write[num_of_pages * SPDK_BS_PAGE_SIZE]; 882 uint8_t payload_zero[num_of_pages * SPDK_BS_PAGE_SIZE]; 883 884 memset(payload_write, 0xE5, sizeof(payload_write)); 885 memset(payload_read, 0x00, sizeof(payload_read)); 886 memset(payload_zero, 0x00, sizeof(payload_zero)); 887 888 /* Test freeze I/O during snapshot */ 889 channel = spdk_bs_alloc_io_channel(bs); 890 bs_channel = spdk_io_channel_get_ctx(channel); 891 892 /* Create blob with 10 clusters */ 893 ut_spdk_blob_opts_init(&opts); 894 opts.num_clusters = 10; 895 opts.thin_provision = false; 896 897 blob = ut_blob_create_and_open(bs, &opts); 898 blobid = spdk_blob_get_id(blob); 899 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 900 901 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 902 903 /* This is implementation specific. 904 * Flag 'frozen_io' is set in _spdk_bs_snapshot_freeze_cpl callback. 905 * Four async I/O operations happen before that. */ 906 poll_thread_times(0, 5); 907 908 CU_ASSERT(TAILQ_EMPTY(&bs_channel->queued_io)); 909 910 /* Blob I/O should be frozen here */ 911 CU_ASSERT(blob->frozen_refcnt == 1); 912 913 /* Write to the blob */ 914 spdk_blob_io_write(blob, channel, payload_write, 0, num_of_pages, blob_op_complete, NULL); 915 916 /* Verify that I/O is queued */ 917 CU_ASSERT(!TAILQ_EMPTY(&bs_channel->queued_io)); 918 /* Verify that payload is not written to disk, at this point the blobs already switched */ 919 CU_ASSERT(blob->active.clusters[0] == 0); 920 921 /* Finish all operations including spdk_bs_create_snapshot */ 922 poll_threads(); 923 924 /* Verify snapshot */ 925 CU_ASSERT(g_bserrno == 0); 926 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 927 928 /* Verify that blob has unset frozen_io */ 929 CU_ASSERT(blob->frozen_refcnt == 0); 930 931 /* Verify that postponed I/O completed successfully by comparing payload */ 932 spdk_blob_io_read(blob, channel, payload_read, 0, num_of_pages, blob_op_complete, NULL); 933 poll_threads(); 934 CU_ASSERT(g_bserrno == 0); 935 CU_ASSERT(memcmp(payload_write, payload_read, num_of_pages * SPDK_BS_PAGE_SIZE) == 0); 936 937 spdk_bs_free_io_channel(channel); 938 poll_threads(); 939 940 ut_blob_close_and_delete(bs, blob); 941 } 942 943 static void 944 blob_clone(void) 945 { 946 struct spdk_blob_store *bs = g_bs; 947 struct spdk_blob_opts opts; 948 struct spdk_blob *blob, *snapshot, *clone; 949 spdk_blob_id blobid, cloneid, snapshotid; 950 struct spdk_blob_xattr_opts xattrs; 951 const void *value; 952 size_t value_len; 953 int rc; 954 955 /* Create blob with 10 clusters */ 956 957 ut_spdk_blob_opts_init(&opts); 958 opts.num_clusters = 10; 959 960 blob = ut_blob_create_and_open(bs, &opts); 961 blobid = spdk_blob_get_id(blob); 962 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 963 964 /* Create snapshot */ 965 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 966 poll_threads(); 967 CU_ASSERT(g_bserrno == 0); 968 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 969 snapshotid = g_blobid; 970 971 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 972 poll_threads(); 973 CU_ASSERT(g_bserrno == 0); 974 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 975 snapshot = g_blob; 976 CU_ASSERT(snapshot->data_ro == true); 977 CU_ASSERT(snapshot->md_ro == true); 978 CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 10); 979 980 spdk_blob_close(snapshot, blob_op_complete, NULL); 981 poll_threads(); 982 CU_ASSERT(g_bserrno == 0); 983 984 /* Create clone from snapshot with xattrs */ 985 xattrs.names = g_xattr_names; 986 xattrs.get_value = _get_xattr_value; 987 xattrs.count = 3; 988 xattrs.ctx = &g_ctx; 989 990 spdk_bs_create_clone(bs, snapshotid, &xattrs, blob_op_with_id_complete, NULL); 991 poll_threads(); 992 CU_ASSERT(g_bserrno == 0); 993 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 994 cloneid = g_blobid; 995 996 spdk_bs_open_blob(bs, cloneid, blob_op_with_handle_complete, NULL); 997 poll_threads(); 998 CU_ASSERT(g_bserrno == 0); 999 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 1000 clone = g_blob; 1001 CU_ASSERT(clone->data_ro == false); 1002 CU_ASSERT(clone->md_ro == false); 1003 CU_ASSERT(spdk_blob_get_num_clusters(clone) == 10); 1004 1005 rc = spdk_blob_get_xattr_value(clone, g_xattr_names[0], &value, &value_len); 1006 CU_ASSERT(rc == 0); 1007 SPDK_CU_ASSERT_FATAL(value != NULL); 1008 CU_ASSERT(value_len == strlen(g_xattr_values[0])); 1009 CU_ASSERT_NSTRING_EQUAL_FATAL(value, g_xattr_values[0], value_len); 1010 1011 rc = spdk_blob_get_xattr_value(clone, g_xattr_names[1], &value, &value_len); 1012 CU_ASSERT(rc == 0); 1013 SPDK_CU_ASSERT_FATAL(value != NULL); 1014 CU_ASSERT(value_len == strlen(g_xattr_values[1])); 1015 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[1], value_len); 1016 1017 rc = spdk_blob_get_xattr_value(clone, g_xattr_names[2], &value, &value_len); 1018 CU_ASSERT(rc == 0); 1019 SPDK_CU_ASSERT_FATAL(value != NULL); 1020 CU_ASSERT(value_len == strlen(g_xattr_values[2])); 1021 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[2], value_len); 1022 1023 1024 spdk_blob_close(clone, blob_op_complete, NULL); 1025 poll_threads(); 1026 CU_ASSERT(g_bserrno == 0); 1027 1028 /* Try to create clone from not read only blob */ 1029 spdk_bs_create_clone(bs, blobid, NULL, blob_op_with_id_complete, NULL); 1030 poll_threads(); 1031 CU_ASSERT(g_bserrno == -EINVAL); 1032 CU_ASSERT(g_blobid == SPDK_BLOBID_INVALID); 1033 1034 /* Mark blob as read only */ 1035 spdk_blob_set_read_only(blob); 1036 spdk_blob_sync_md(blob, blob_op_complete, NULL); 1037 poll_threads(); 1038 CU_ASSERT(g_bserrno == 0); 1039 1040 /* Create clone from read only blob */ 1041 spdk_bs_create_clone(bs, blobid, NULL, blob_op_with_id_complete, NULL); 1042 poll_threads(); 1043 CU_ASSERT(g_bserrno == 0); 1044 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1045 cloneid = g_blobid; 1046 1047 spdk_bs_open_blob(bs, cloneid, blob_op_with_handle_complete, NULL); 1048 poll_threads(); 1049 CU_ASSERT(g_bserrno == 0); 1050 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 1051 clone = g_blob; 1052 CU_ASSERT(clone->data_ro == false); 1053 CU_ASSERT(clone->md_ro == false); 1054 CU_ASSERT(spdk_blob_get_num_clusters(clone) == 10); 1055 1056 ut_blob_close_and_delete(bs, clone); 1057 ut_blob_close_and_delete(bs, blob); 1058 } 1059 1060 static void 1061 _blob_inflate(bool decouple_parent) 1062 { 1063 struct spdk_blob_store *bs = g_bs; 1064 struct spdk_blob_opts opts; 1065 struct spdk_blob *blob, *snapshot; 1066 spdk_blob_id blobid, snapshotid; 1067 struct spdk_io_channel *channel; 1068 uint64_t free_clusters; 1069 1070 channel = spdk_bs_alloc_io_channel(bs); 1071 SPDK_CU_ASSERT_FATAL(channel != NULL); 1072 1073 /* Create blob with 10 clusters */ 1074 1075 ut_spdk_blob_opts_init(&opts); 1076 opts.num_clusters = 10; 1077 opts.thin_provision = true; 1078 1079 blob = ut_blob_create_and_open(bs, &opts); 1080 blobid = spdk_blob_get_id(blob); 1081 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 1082 CU_ASSERT(spdk_blob_is_thin_provisioned(blob) == true); 1083 1084 /* 1) Blob with no parent */ 1085 if (decouple_parent) { 1086 /* Decouple parent of blob with no parent (should fail) */ 1087 spdk_bs_blob_decouple_parent(bs, channel, blobid, blob_op_complete, NULL); 1088 poll_threads(); 1089 CU_ASSERT(g_bserrno != 0); 1090 } else { 1091 /* Inflate of thin blob with no parent should made it thick */ 1092 spdk_bs_inflate_blob(bs, channel, blobid, blob_op_complete, NULL); 1093 poll_threads(); 1094 CU_ASSERT(g_bserrno == 0); 1095 CU_ASSERT(spdk_blob_is_thin_provisioned(blob) == false); 1096 } 1097 1098 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 1099 poll_threads(); 1100 CU_ASSERT(g_bserrno == 0); 1101 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1102 snapshotid = g_blobid; 1103 1104 CU_ASSERT(spdk_blob_is_thin_provisioned(blob) == true); 1105 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 1106 1107 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 1108 poll_threads(); 1109 CU_ASSERT(g_bserrno == 0); 1110 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 1111 snapshot = g_blob; 1112 CU_ASSERT(snapshot->data_ro == true); 1113 CU_ASSERT(snapshot->md_ro == true); 1114 CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 10); 1115 1116 spdk_blob_close(snapshot, blob_op_complete, NULL); 1117 poll_threads(); 1118 CU_ASSERT(g_bserrno == 0); 1119 1120 free_clusters = spdk_bs_free_cluster_count(bs); 1121 1122 /* 2) Blob with parent */ 1123 if (!decouple_parent) { 1124 /* Do full blob inflation */ 1125 spdk_bs_inflate_blob(bs, channel, blobid, blob_op_complete, NULL); 1126 poll_threads(); 1127 CU_ASSERT(g_bserrno == 0); 1128 /* all 10 clusters should be allocated */ 1129 CU_ASSERT(spdk_bs_free_cluster_count(bs) == free_clusters - 10); 1130 } else { 1131 /* Decouple parent of blob */ 1132 spdk_bs_blob_decouple_parent(bs, channel, blobid, blob_op_complete, NULL); 1133 poll_threads(); 1134 CU_ASSERT(g_bserrno == 0); 1135 /* when only parent is removed, none of the clusters should be allocated */ 1136 CU_ASSERT(spdk_bs_free_cluster_count(bs) == free_clusters); 1137 } 1138 1139 /* Now, it should be possible to delete snapshot */ 1140 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL); 1141 poll_threads(); 1142 CU_ASSERT(g_bserrno == 0); 1143 1144 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 1145 CU_ASSERT(spdk_blob_is_thin_provisioned(blob) == decouple_parent); 1146 1147 spdk_bs_free_io_channel(channel); 1148 poll_threads(); 1149 1150 ut_blob_close_and_delete(bs, blob); 1151 } 1152 1153 static void 1154 blob_inflate(void) 1155 { 1156 _blob_inflate(false); 1157 _blob_inflate(true); 1158 } 1159 1160 static void 1161 blob_delete(void) 1162 { 1163 struct spdk_blob_store *bs = g_bs; 1164 struct spdk_blob_opts blob_opts; 1165 spdk_blob_id blobid; 1166 1167 /* Create a blob and then delete it. */ 1168 ut_spdk_blob_opts_init(&blob_opts); 1169 spdk_bs_create_blob_ext(bs, &blob_opts, blob_op_with_id_complete, NULL); 1170 poll_threads(); 1171 CU_ASSERT(g_bserrno == 0); 1172 CU_ASSERT(g_blobid > 0); 1173 blobid = g_blobid; 1174 1175 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); 1176 poll_threads(); 1177 CU_ASSERT(g_bserrno == 0); 1178 1179 /* Try to open the blob */ 1180 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 1181 poll_threads(); 1182 CU_ASSERT(g_bserrno == -ENOENT); 1183 } 1184 1185 static void 1186 blob_resize_test(void) 1187 { 1188 struct spdk_blob_store *bs = g_bs; 1189 struct spdk_blob *blob; 1190 uint64_t free_clusters; 1191 1192 free_clusters = spdk_bs_free_cluster_count(bs); 1193 1194 blob = ut_blob_create_and_open(bs, NULL); 1195 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 1196 1197 /* Confirm that resize fails if blob is marked read-only. */ 1198 blob->md_ro = true; 1199 spdk_blob_resize(blob, 5, blob_op_complete, NULL); 1200 poll_threads(); 1201 CU_ASSERT(g_bserrno == -EPERM); 1202 blob->md_ro = false; 1203 1204 /* The blob started at 0 clusters. Resize it to be 5. */ 1205 spdk_blob_resize(blob, 5, blob_op_complete, NULL); 1206 poll_threads(); 1207 CU_ASSERT(g_bserrno == 0); 1208 CU_ASSERT((free_clusters - 5) == spdk_bs_free_cluster_count(bs)); 1209 1210 /* Shrink the blob to 3 clusters. This will not actually release 1211 * the old clusters until the blob is synced. 1212 */ 1213 spdk_blob_resize(blob, 3, blob_op_complete, NULL); 1214 poll_threads(); 1215 CU_ASSERT(g_bserrno == 0); 1216 /* Verify there are still 5 clusters in use */ 1217 CU_ASSERT((free_clusters - 5) == spdk_bs_free_cluster_count(bs)); 1218 1219 spdk_blob_sync_md(blob, blob_op_complete, NULL); 1220 poll_threads(); 1221 CU_ASSERT(g_bserrno == 0); 1222 /* Now there are only 3 clusters in use */ 1223 CU_ASSERT((free_clusters - 3) == spdk_bs_free_cluster_count(bs)); 1224 1225 /* Resize the blob to be 10 clusters. Growth takes effect immediately. */ 1226 spdk_blob_resize(blob, 10, blob_op_complete, NULL); 1227 poll_threads(); 1228 CU_ASSERT(g_bserrno == 0); 1229 CU_ASSERT((free_clusters - 10) == spdk_bs_free_cluster_count(bs)); 1230 1231 /* Try to resize the blob to size larger than blobstore. */ 1232 spdk_blob_resize(blob, bs->total_clusters + 1, blob_op_complete, NULL); 1233 poll_threads(); 1234 CU_ASSERT(g_bserrno == -ENOSPC); 1235 1236 ut_blob_close_and_delete(bs, blob); 1237 } 1238 1239 static void 1240 blob_read_only(void) 1241 { 1242 struct spdk_blob_store *bs; 1243 struct spdk_bs_dev *dev; 1244 struct spdk_blob *blob; 1245 struct spdk_bs_opts opts; 1246 spdk_blob_id blobid; 1247 int rc; 1248 1249 dev = init_dev(); 1250 spdk_bs_opts_init(&opts, sizeof(opts)); 1251 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 1252 1253 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1254 poll_threads(); 1255 CU_ASSERT(g_bserrno == 0); 1256 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1257 bs = g_bs; 1258 1259 blob = ut_blob_create_and_open(bs, NULL); 1260 blobid = spdk_blob_get_id(blob); 1261 1262 rc = spdk_blob_set_read_only(blob); 1263 CU_ASSERT(rc == 0); 1264 1265 CU_ASSERT(blob->data_ro == false); 1266 CU_ASSERT(blob->md_ro == false); 1267 1268 spdk_blob_sync_md(blob, bs_op_complete, NULL); 1269 poll_threads(); 1270 1271 CU_ASSERT(blob->data_ro == true); 1272 CU_ASSERT(blob->md_ro == true); 1273 CU_ASSERT(blob->data_ro_flags & SPDK_BLOB_READ_ONLY); 1274 1275 spdk_blob_close(blob, blob_op_complete, NULL); 1276 poll_threads(); 1277 CU_ASSERT(g_bserrno == 0); 1278 1279 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 1280 poll_threads(); 1281 CU_ASSERT(g_bserrno == 0); 1282 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 1283 blob = g_blob; 1284 1285 CU_ASSERT(blob->data_ro == true); 1286 CU_ASSERT(blob->md_ro == true); 1287 CU_ASSERT(blob->data_ro_flags & SPDK_BLOB_READ_ONLY); 1288 1289 spdk_blob_close(blob, blob_op_complete, NULL); 1290 poll_threads(); 1291 CU_ASSERT(g_bserrno == 0); 1292 1293 ut_bs_reload(&bs, &opts); 1294 1295 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 1296 poll_threads(); 1297 CU_ASSERT(g_bserrno == 0); 1298 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 1299 blob = g_blob; 1300 1301 CU_ASSERT(blob->data_ro == true); 1302 CU_ASSERT(blob->md_ro == true); 1303 CU_ASSERT(blob->data_ro_flags & SPDK_BLOB_READ_ONLY); 1304 1305 ut_blob_close_and_delete(bs, blob); 1306 1307 spdk_bs_unload(bs, bs_op_complete, NULL); 1308 poll_threads(); 1309 CU_ASSERT(g_bserrno == 0); 1310 } 1311 1312 static void 1313 channel_ops(void) 1314 { 1315 struct spdk_blob_store *bs = g_bs; 1316 struct spdk_io_channel *channel; 1317 1318 channel = spdk_bs_alloc_io_channel(bs); 1319 CU_ASSERT(channel != NULL); 1320 1321 spdk_bs_free_io_channel(channel); 1322 poll_threads(); 1323 } 1324 1325 static void 1326 blob_write(void) 1327 { 1328 struct spdk_blob_store *bs = g_bs; 1329 struct spdk_blob *blob = g_blob; 1330 struct spdk_io_channel *channel; 1331 uint64_t pages_per_cluster; 1332 uint8_t payload[10 * 4096]; 1333 1334 pages_per_cluster = spdk_bs_get_cluster_size(bs) / spdk_bs_get_page_size(bs); 1335 1336 channel = spdk_bs_alloc_io_channel(bs); 1337 CU_ASSERT(channel != NULL); 1338 1339 /* Write to a blob with 0 size */ 1340 spdk_blob_io_write(blob, channel, payload, 0, 1, blob_op_complete, NULL); 1341 poll_threads(); 1342 CU_ASSERT(g_bserrno == -EINVAL); 1343 1344 /* Resize the blob */ 1345 spdk_blob_resize(blob, 5, blob_op_complete, NULL); 1346 poll_threads(); 1347 CU_ASSERT(g_bserrno == 0); 1348 1349 /* Confirm that write fails if blob is marked read-only. */ 1350 blob->data_ro = true; 1351 spdk_blob_io_write(blob, channel, payload, 0, 1, blob_op_complete, NULL); 1352 poll_threads(); 1353 CU_ASSERT(g_bserrno == -EPERM); 1354 blob->data_ro = false; 1355 1356 /* Write to the blob */ 1357 spdk_blob_io_write(blob, channel, payload, 0, 1, blob_op_complete, NULL); 1358 poll_threads(); 1359 CU_ASSERT(g_bserrno == 0); 1360 1361 /* Write starting beyond the end */ 1362 spdk_blob_io_write(blob, channel, payload, 5 * pages_per_cluster, 1, blob_op_complete, 1363 NULL); 1364 poll_threads(); 1365 CU_ASSERT(g_bserrno == -EINVAL); 1366 1367 /* Write starting at a valid location but going off the end */ 1368 spdk_blob_io_write(blob, channel, payload, 4 * pages_per_cluster, pages_per_cluster + 1, 1369 blob_op_complete, NULL); 1370 poll_threads(); 1371 CU_ASSERT(g_bserrno == -EINVAL); 1372 1373 spdk_bs_free_io_channel(channel); 1374 poll_threads(); 1375 } 1376 1377 static void 1378 blob_read(void) 1379 { 1380 struct spdk_blob_store *bs = g_bs; 1381 struct spdk_blob *blob = g_blob; 1382 struct spdk_io_channel *channel; 1383 uint64_t pages_per_cluster; 1384 uint8_t payload[10 * 4096]; 1385 1386 pages_per_cluster = spdk_bs_get_cluster_size(bs) / spdk_bs_get_page_size(bs); 1387 1388 channel = spdk_bs_alloc_io_channel(bs); 1389 CU_ASSERT(channel != NULL); 1390 1391 /* Read from a blob with 0 size */ 1392 spdk_blob_io_read(blob, channel, payload, 0, 1, blob_op_complete, NULL); 1393 poll_threads(); 1394 CU_ASSERT(g_bserrno == -EINVAL); 1395 1396 /* Resize the blob */ 1397 spdk_blob_resize(blob, 5, blob_op_complete, NULL); 1398 poll_threads(); 1399 CU_ASSERT(g_bserrno == 0); 1400 1401 /* Confirm that read passes if blob is marked read-only. */ 1402 blob->data_ro = true; 1403 spdk_blob_io_read(blob, channel, payload, 0, 1, blob_op_complete, NULL); 1404 poll_threads(); 1405 CU_ASSERT(g_bserrno == 0); 1406 blob->data_ro = false; 1407 1408 /* Read from the blob */ 1409 spdk_blob_io_read(blob, channel, payload, 0, 1, blob_op_complete, NULL); 1410 poll_threads(); 1411 CU_ASSERT(g_bserrno == 0); 1412 1413 /* Read starting beyond the end */ 1414 spdk_blob_io_read(blob, channel, payload, 5 * pages_per_cluster, 1, blob_op_complete, 1415 NULL); 1416 poll_threads(); 1417 CU_ASSERT(g_bserrno == -EINVAL); 1418 1419 /* Read starting at a valid location but going off the end */ 1420 spdk_blob_io_read(blob, channel, payload, 4 * pages_per_cluster, pages_per_cluster + 1, 1421 blob_op_complete, NULL); 1422 poll_threads(); 1423 CU_ASSERT(g_bserrno == -EINVAL); 1424 1425 spdk_bs_free_io_channel(channel); 1426 poll_threads(); 1427 } 1428 1429 static void 1430 blob_rw_verify(void) 1431 { 1432 struct spdk_blob_store *bs = g_bs; 1433 struct spdk_blob *blob = g_blob; 1434 struct spdk_io_channel *channel; 1435 uint8_t payload_read[10 * 4096]; 1436 uint8_t payload_write[10 * 4096]; 1437 1438 channel = spdk_bs_alloc_io_channel(bs); 1439 CU_ASSERT(channel != NULL); 1440 1441 spdk_blob_resize(blob, 32, blob_op_complete, NULL); 1442 poll_threads(); 1443 CU_ASSERT(g_bserrno == 0); 1444 1445 memset(payload_write, 0xE5, sizeof(payload_write)); 1446 spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL); 1447 poll_threads(); 1448 CU_ASSERT(g_bserrno == 0); 1449 1450 memset(payload_read, 0x00, sizeof(payload_read)); 1451 spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL); 1452 poll_threads(); 1453 CU_ASSERT(g_bserrno == 0); 1454 CU_ASSERT(memcmp(payload_write, payload_read, 4 * 4096) == 0); 1455 1456 spdk_bs_free_io_channel(channel); 1457 poll_threads(); 1458 } 1459 1460 static void 1461 blob_rw_verify_iov(void) 1462 { 1463 struct spdk_blob_store *bs = g_bs; 1464 struct spdk_blob *blob; 1465 struct spdk_io_channel *channel; 1466 uint8_t payload_read[10 * 4096]; 1467 uint8_t payload_write[10 * 4096]; 1468 struct iovec iov_read[3]; 1469 struct iovec iov_write[3]; 1470 void *buf; 1471 1472 channel = spdk_bs_alloc_io_channel(bs); 1473 CU_ASSERT(channel != NULL); 1474 1475 blob = ut_blob_create_and_open(bs, NULL); 1476 1477 spdk_blob_resize(blob, 2, blob_op_complete, NULL); 1478 poll_threads(); 1479 CU_ASSERT(g_bserrno == 0); 1480 1481 /* 1482 * Manually adjust the offset of the blob's second cluster. This allows 1483 * us to make sure that the readv/write code correctly accounts for I/O 1484 * that cross cluster boundaries. Start by asserting that the allocated 1485 * clusters are where we expect before modifying the second cluster. 1486 */ 1487 CU_ASSERT(blob->active.clusters[0] == 1 * 256); 1488 CU_ASSERT(blob->active.clusters[1] == 2 * 256); 1489 blob->active.clusters[1] = 3 * 256; 1490 1491 memset(payload_write, 0xE5, sizeof(payload_write)); 1492 iov_write[0].iov_base = payload_write; 1493 iov_write[0].iov_len = 1 * 4096; 1494 iov_write[1].iov_base = payload_write + 1 * 4096; 1495 iov_write[1].iov_len = 5 * 4096; 1496 iov_write[2].iov_base = payload_write + 6 * 4096; 1497 iov_write[2].iov_len = 4 * 4096; 1498 /* 1499 * Choose a page offset just before the cluster boundary. The first 6 pages of payload 1500 * will get written to the first cluster, the last 4 to the second cluster. 1501 */ 1502 spdk_blob_io_writev(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL); 1503 poll_threads(); 1504 CU_ASSERT(g_bserrno == 0); 1505 1506 memset(payload_read, 0xAA, sizeof(payload_read)); 1507 iov_read[0].iov_base = payload_read; 1508 iov_read[0].iov_len = 3 * 4096; 1509 iov_read[1].iov_base = payload_read + 3 * 4096; 1510 iov_read[1].iov_len = 4 * 4096; 1511 iov_read[2].iov_base = payload_read + 7 * 4096; 1512 iov_read[2].iov_len = 3 * 4096; 1513 spdk_blob_io_readv(blob, channel, iov_read, 3, 250, 10, blob_op_complete, NULL); 1514 poll_threads(); 1515 CU_ASSERT(g_bserrno == 0); 1516 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0); 1517 1518 buf = calloc(1, 256 * 4096); 1519 SPDK_CU_ASSERT_FATAL(buf != NULL); 1520 /* Check that cluster 2 on "disk" was not modified. */ 1521 CU_ASSERT(memcmp(buf, &g_dev_buffer[512 * 4096], 256 * 4096) == 0); 1522 free(buf); 1523 1524 spdk_blob_close(blob, blob_op_complete, NULL); 1525 poll_threads(); 1526 CU_ASSERT(g_bserrno == 0); 1527 1528 spdk_bs_free_io_channel(channel); 1529 poll_threads(); 1530 } 1531 1532 static uint32_t 1533 bs_channel_get_req_count(struct spdk_io_channel *_channel) 1534 { 1535 struct spdk_bs_channel *channel = spdk_io_channel_get_ctx(_channel); 1536 struct spdk_bs_request_set *set; 1537 uint32_t count = 0; 1538 1539 TAILQ_FOREACH(set, &channel->reqs, link) { 1540 count++; 1541 } 1542 1543 return count; 1544 } 1545 1546 static void 1547 blob_rw_verify_iov_nomem(void) 1548 { 1549 struct spdk_blob_store *bs = g_bs; 1550 struct spdk_blob *blob = g_blob; 1551 struct spdk_io_channel *channel; 1552 uint8_t payload_write[10 * 4096]; 1553 struct iovec iov_write[3]; 1554 uint32_t req_count; 1555 1556 channel = spdk_bs_alloc_io_channel(bs); 1557 CU_ASSERT(channel != NULL); 1558 1559 spdk_blob_resize(blob, 2, blob_op_complete, NULL); 1560 poll_threads(); 1561 CU_ASSERT(g_bserrno == 0); 1562 1563 /* 1564 * Choose a page offset just before the cluster boundary. The first 6 pages of payload 1565 * will get written to the first cluster, the last 4 to the second cluster. 1566 */ 1567 iov_write[0].iov_base = payload_write; 1568 iov_write[0].iov_len = 1 * 4096; 1569 iov_write[1].iov_base = payload_write + 1 * 4096; 1570 iov_write[1].iov_len = 5 * 4096; 1571 iov_write[2].iov_base = payload_write + 6 * 4096; 1572 iov_write[2].iov_len = 4 * 4096; 1573 MOCK_SET(calloc, NULL); 1574 req_count = bs_channel_get_req_count(channel); 1575 spdk_blob_io_writev(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL); 1576 poll_threads(); 1577 CU_ASSERT(g_bserrno = -ENOMEM); 1578 CU_ASSERT(req_count == bs_channel_get_req_count(channel)); 1579 MOCK_CLEAR(calloc); 1580 1581 spdk_bs_free_io_channel(channel); 1582 poll_threads(); 1583 } 1584 1585 static void 1586 blob_rw_iov_read_only(void) 1587 { 1588 struct spdk_blob_store *bs = g_bs; 1589 struct spdk_blob *blob = g_blob; 1590 struct spdk_io_channel *channel; 1591 uint8_t payload_read[4096]; 1592 uint8_t payload_write[4096]; 1593 struct iovec iov_read; 1594 struct iovec iov_write; 1595 1596 channel = spdk_bs_alloc_io_channel(bs); 1597 CU_ASSERT(channel != NULL); 1598 1599 spdk_blob_resize(blob, 2, blob_op_complete, NULL); 1600 poll_threads(); 1601 CU_ASSERT(g_bserrno == 0); 1602 1603 /* Verify that writev failed if read_only flag is set. */ 1604 blob->data_ro = true; 1605 iov_write.iov_base = payload_write; 1606 iov_write.iov_len = sizeof(payload_write); 1607 spdk_blob_io_writev(blob, channel, &iov_write, 1, 0, 1, blob_op_complete, NULL); 1608 poll_threads(); 1609 CU_ASSERT(g_bserrno == -EPERM); 1610 1611 /* Verify that reads pass if data_ro flag is set. */ 1612 iov_read.iov_base = payload_read; 1613 iov_read.iov_len = sizeof(payload_read); 1614 spdk_blob_io_readv(blob, channel, &iov_read, 1, 0, 1, blob_op_complete, NULL); 1615 poll_threads(); 1616 CU_ASSERT(g_bserrno == 0); 1617 1618 spdk_bs_free_io_channel(channel); 1619 poll_threads(); 1620 } 1621 1622 static void 1623 _blob_io_read_no_split(struct spdk_blob *blob, struct spdk_io_channel *channel, 1624 uint8_t *payload, uint64_t offset, uint64_t length, 1625 spdk_blob_op_complete cb_fn, void *cb_arg) 1626 { 1627 uint64_t i; 1628 uint8_t *buf; 1629 uint64_t page_size = spdk_bs_get_page_size(blob->bs); 1630 1631 /* To be sure that operation is NOT split, read one page at the time */ 1632 buf = payload; 1633 for (i = 0; i < length; i++) { 1634 spdk_blob_io_read(blob, channel, buf, i + offset, 1, blob_op_complete, NULL); 1635 poll_threads(); 1636 if (g_bserrno != 0) { 1637 /* Pass the error code up */ 1638 break; 1639 } 1640 buf += page_size; 1641 } 1642 1643 cb_fn(cb_arg, g_bserrno); 1644 } 1645 1646 static void 1647 _blob_io_write_no_split(struct spdk_blob *blob, struct spdk_io_channel *channel, 1648 uint8_t *payload, uint64_t offset, uint64_t length, 1649 spdk_blob_op_complete cb_fn, void *cb_arg) 1650 { 1651 uint64_t i; 1652 uint8_t *buf; 1653 uint64_t page_size = spdk_bs_get_page_size(blob->bs); 1654 1655 /* To be sure that operation is NOT split, write one page at the time */ 1656 buf = payload; 1657 for (i = 0; i < length; i++) { 1658 spdk_blob_io_write(blob, channel, buf, i + offset, 1, blob_op_complete, NULL); 1659 poll_threads(); 1660 if (g_bserrno != 0) { 1661 /* Pass the error code up */ 1662 break; 1663 } 1664 buf += page_size; 1665 } 1666 1667 cb_fn(cb_arg, g_bserrno); 1668 } 1669 1670 static void 1671 blob_operation_split_rw(void) 1672 { 1673 struct spdk_blob_store *bs = g_bs; 1674 struct spdk_blob *blob; 1675 struct spdk_io_channel *channel; 1676 struct spdk_blob_opts opts; 1677 uint64_t cluster_size; 1678 1679 uint64_t payload_size; 1680 uint8_t *payload_read; 1681 uint8_t *payload_write; 1682 uint8_t *payload_pattern; 1683 1684 uint64_t page_size; 1685 uint64_t pages_per_cluster; 1686 uint64_t pages_per_payload; 1687 1688 uint64_t i; 1689 1690 cluster_size = spdk_bs_get_cluster_size(bs); 1691 page_size = spdk_bs_get_page_size(bs); 1692 pages_per_cluster = cluster_size / page_size; 1693 pages_per_payload = pages_per_cluster * 5; 1694 payload_size = cluster_size * 5; 1695 1696 payload_read = malloc(payload_size); 1697 SPDK_CU_ASSERT_FATAL(payload_read != NULL); 1698 1699 payload_write = malloc(payload_size); 1700 SPDK_CU_ASSERT_FATAL(payload_write != NULL); 1701 1702 payload_pattern = malloc(payload_size); 1703 SPDK_CU_ASSERT_FATAL(payload_pattern != NULL); 1704 1705 /* Prepare random pattern to write */ 1706 memset(payload_pattern, 0xFF, payload_size); 1707 for (i = 0; i < pages_per_payload; i++) { 1708 *((uint64_t *)(payload_pattern + page_size * i)) = (i + 1); 1709 } 1710 1711 channel = spdk_bs_alloc_io_channel(bs); 1712 SPDK_CU_ASSERT_FATAL(channel != NULL); 1713 1714 /* Create blob */ 1715 ut_spdk_blob_opts_init(&opts); 1716 opts.thin_provision = false; 1717 opts.num_clusters = 5; 1718 1719 blob = ut_blob_create_and_open(bs, &opts); 1720 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5); 1721 1722 /* Initial read should return zeroed payload */ 1723 memset(payload_read, 0xFF, payload_size); 1724 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload, blob_op_complete, NULL); 1725 poll_threads(); 1726 CU_ASSERT(g_bserrno == 0); 1727 CU_ASSERT(spdk_mem_all_zero(payload_read, payload_size)); 1728 1729 /* Fill whole blob except last page */ 1730 spdk_blob_io_write(blob, channel, payload_pattern, 0, pages_per_payload - 1, 1731 blob_op_complete, NULL); 1732 poll_threads(); 1733 CU_ASSERT(g_bserrno == 0); 1734 1735 /* Write last page with a pattern */ 1736 spdk_blob_io_write(blob, channel, payload_pattern, pages_per_payload - 1, 1, 1737 blob_op_complete, NULL); 1738 poll_threads(); 1739 CU_ASSERT(g_bserrno == 0); 1740 1741 /* Read whole blob and check consistency */ 1742 memset(payload_read, 0xFF, payload_size); 1743 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload, blob_op_complete, NULL); 1744 poll_threads(); 1745 CU_ASSERT(g_bserrno == 0); 1746 CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size - page_size) == 0); 1747 CU_ASSERT(memcmp(payload_pattern, payload_read + payload_size - page_size, page_size) == 0); 1748 1749 /* Fill whole blob except first page */ 1750 spdk_blob_io_write(blob, channel, payload_pattern, 1, pages_per_payload - 1, 1751 blob_op_complete, NULL); 1752 poll_threads(); 1753 CU_ASSERT(g_bserrno == 0); 1754 1755 /* Write first page with a pattern */ 1756 spdk_blob_io_write(blob, channel, payload_pattern, 0, 1, 1757 blob_op_complete, NULL); 1758 poll_threads(); 1759 CU_ASSERT(g_bserrno == 0); 1760 1761 /* Read whole blob and check consistency */ 1762 memset(payload_read, 0xFF, payload_size); 1763 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload, blob_op_complete, NULL); 1764 poll_threads(); 1765 CU_ASSERT(g_bserrno == 0); 1766 CU_ASSERT(memcmp(payload_pattern, payload_read + page_size, payload_size - page_size) == 0); 1767 CU_ASSERT(memcmp(payload_pattern, payload_read, page_size) == 0); 1768 1769 1770 /* Fill whole blob with a pattern (5 clusters) */ 1771 1772 /* 1. Read test. */ 1773 _blob_io_write_no_split(blob, channel, payload_pattern, 0, pages_per_payload, 1774 blob_op_complete, NULL); 1775 poll_threads(); 1776 CU_ASSERT(g_bserrno == 0); 1777 1778 memset(payload_read, 0xFF, payload_size); 1779 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload, blob_op_complete, NULL); 1780 poll_threads(); 1781 poll_threads(); 1782 CU_ASSERT(g_bserrno == 0); 1783 CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size) == 0); 1784 1785 /* 2. Write test. */ 1786 spdk_blob_io_write(blob, channel, payload_pattern, 0, pages_per_payload, 1787 blob_op_complete, NULL); 1788 poll_threads(); 1789 CU_ASSERT(g_bserrno == 0); 1790 1791 memset(payload_read, 0xFF, payload_size); 1792 _blob_io_read_no_split(blob, channel, payload_read, 0, pages_per_payload, blob_op_complete, NULL); 1793 poll_threads(); 1794 CU_ASSERT(g_bserrno == 0); 1795 CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size) == 0); 1796 1797 spdk_bs_free_io_channel(channel); 1798 poll_threads(); 1799 1800 g_blob = NULL; 1801 g_blobid = 0; 1802 1803 free(payload_read); 1804 free(payload_write); 1805 free(payload_pattern); 1806 1807 ut_blob_close_and_delete(bs, blob); 1808 } 1809 1810 static void 1811 blob_operation_split_rw_iov(void) 1812 { 1813 struct spdk_blob_store *bs = g_bs; 1814 struct spdk_blob *blob; 1815 struct spdk_io_channel *channel; 1816 struct spdk_blob_opts opts; 1817 uint64_t cluster_size; 1818 1819 uint64_t payload_size; 1820 uint8_t *payload_read; 1821 uint8_t *payload_write; 1822 uint8_t *payload_pattern; 1823 1824 uint64_t page_size; 1825 uint64_t pages_per_cluster; 1826 uint64_t pages_per_payload; 1827 1828 struct iovec iov_read[2]; 1829 struct iovec iov_write[2]; 1830 1831 uint64_t i, j; 1832 1833 cluster_size = spdk_bs_get_cluster_size(bs); 1834 page_size = spdk_bs_get_page_size(bs); 1835 pages_per_cluster = cluster_size / page_size; 1836 pages_per_payload = pages_per_cluster * 5; 1837 payload_size = cluster_size * 5; 1838 1839 payload_read = malloc(payload_size); 1840 SPDK_CU_ASSERT_FATAL(payload_read != NULL); 1841 1842 payload_write = malloc(payload_size); 1843 SPDK_CU_ASSERT_FATAL(payload_write != NULL); 1844 1845 payload_pattern = malloc(payload_size); 1846 SPDK_CU_ASSERT_FATAL(payload_pattern != NULL); 1847 1848 /* Prepare random pattern to write */ 1849 for (i = 0; i < pages_per_payload; i++) { 1850 for (j = 0; j < page_size / sizeof(uint64_t); j++) { 1851 uint64_t *tmp; 1852 1853 tmp = (uint64_t *)payload_pattern; 1854 tmp += ((page_size * i) / sizeof(uint64_t)) + j; 1855 *tmp = i + 1; 1856 } 1857 } 1858 1859 channel = spdk_bs_alloc_io_channel(bs); 1860 SPDK_CU_ASSERT_FATAL(channel != NULL); 1861 1862 /* Create blob */ 1863 ut_spdk_blob_opts_init(&opts); 1864 opts.thin_provision = false; 1865 opts.num_clusters = 5; 1866 1867 blob = ut_blob_create_and_open(bs, &opts); 1868 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5); 1869 1870 /* Initial read should return zeroes payload */ 1871 memset(payload_read, 0xFF, payload_size); 1872 iov_read[0].iov_base = payload_read; 1873 iov_read[0].iov_len = cluster_size * 3; 1874 iov_read[1].iov_base = payload_read + cluster_size * 3; 1875 iov_read[1].iov_len = cluster_size * 2; 1876 spdk_blob_io_readv(blob, channel, iov_read, 2, 0, pages_per_payload, blob_op_complete, NULL); 1877 poll_threads(); 1878 CU_ASSERT(g_bserrno == 0); 1879 CU_ASSERT(spdk_mem_all_zero(payload_read, payload_size)); 1880 1881 /* First of iovs fills whole blob except last page and second of iovs writes last page 1882 * with a pattern. */ 1883 iov_write[0].iov_base = payload_pattern; 1884 iov_write[0].iov_len = payload_size - page_size; 1885 iov_write[1].iov_base = payload_pattern; 1886 iov_write[1].iov_len = page_size; 1887 spdk_blob_io_writev(blob, channel, iov_write, 2, 0, pages_per_payload, blob_op_complete, NULL); 1888 poll_threads(); 1889 CU_ASSERT(g_bserrno == 0); 1890 1891 /* Read whole blob and check consistency */ 1892 memset(payload_read, 0xFF, payload_size); 1893 iov_read[0].iov_base = payload_read; 1894 iov_read[0].iov_len = cluster_size * 2; 1895 iov_read[1].iov_base = payload_read + cluster_size * 2; 1896 iov_read[1].iov_len = cluster_size * 3; 1897 spdk_blob_io_readv(blob, channel, iov_read, 2, 0, pages_per_payload, blob_op_complete, NULL); 1898 poll_threads(); 1899 CU_ASSERT(g_bserrno == 0); 1900 CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size - page_size) == 0); 1901 CU_ASSERT(memcmp(payload_pattern, payload_read + payload_size - page_size, page_size) == 0); 1902 1903 /* First of iovs fills only first page and second of iovs writes whole blob except 1904 * first page with a pattern. */ 1905 iov_write[0].iov_base = payload_pattern; 1906 iov_write[0].iov_len = page_size; 1907 iov_write[1].iov_base = payload_pattern; 1908 iov_write[1].iov_len = payload_size - page_size; 1909 spdk_blob_io_writev(blob, channel, iov_write, 2, 0, pages_per_payload, blob_op_complete, NULL); 1910 poll_threads(); 1911 CU_ASSERT(g_bserrno == 0); 1912 1913 /* Read whole blob and check consistency */ 1914 memset(payload_read, 0xFF, payload_size); 1915 iov_read[0].iov_base = payload_read; 1916 iov_read[0].iov_len = cluster_size * 4; 1917 iov_read[1].iov_base = payload_read + cluster_size * 4; 1918 iov_read[1].iov_len = cluster_size; 1919 spdk_blob_io_readv(blob, channel, iov_read, 2, 0, pages_per_payload, blob_op_complete, NULL); 1920 poll_threads(); 1921 CU_ASSERT(g_bserrno == 0); 1922 CU_ASSERT(memcmp(payload_pattern, payload_read + page_size, payload_size - page_size) == 0); 1923 CU_ASSERT(memcmp(payload_pattern, payload_read, page_size) == 0); 1924 1925 1926 /* Fill whole blob with a pattern (5 clusters) */ 1927 1928 /* 1. Read test. */ 1929 _blob_io_write_no_split(blob, channel, payload_pattern, 0, pages_per_payload, 1930 blob_op_complete, NULL); 1931 poll_threads(); 1932 CU_ASSERT(g_bserrno == 0); 1933 1934 memset(payload_read, 0xFF, payload_size); 1935 iov_read[0].iov_base = payload_read; 1936 iov_read[0].iov_len = cluster_size; 1937 iov_read[1].iov_base = payload_read + cluster_size; 1938 iov_read[1].iov_len = cluster_size * 4; 1939 spdk_blob_io_readv(blob, channel, iov_read, 2, 0, pages_per_payload, blob_op_complete, NULL); 1940 poll_threads(); 1941 CU_ASSERT(g_bserrno == 0); 1942 CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size) == 0); 1943 1944 /* 2. Write test. */ 1945 iov_write[0].iov_base = payload_read; 1946 iov_write[0].iov_len = cluster_size * 2; 1947 iov_write[1].iov_base = payload_read + cluster_size * 2; 1948 iov_write[1].iov_len = cluster_size * 3; 1949 spdk_blob_io_writev(blob, channel, iov_write, 2, 0, pages_per_payload, blob_op_complete, NULL); 1950 poll_threads(); 1951 CU_ASSERT(g_bserrno == 0); 1952 1953 memset(payload_read, 0xFF, payload_size); 1954 _blob_io_read_no_split(blob, channel, payload_read, 0, pages_per_payload, blob_op_complete, NULL); 1955 poll_threads(); 1956 CU_ASSERT(g_bserrno == 0); 1957 CU_ASSERT(memcmp(payload_pattern, payload_read, payload_size) == 0); 1958 1959 spdk_bs_free_io_channel(channel); 1960 poll_threads(); 1961 1962 g_blob = NULL; 1963 g_blobid = 0; 1964 1965 free(payload_read); 1966 free(payload_write); 1967 free(payload_pattern); 1968 1969 ut_blob_close_and_delete(bs, blob); 1970 } 1971 1972 static void 1973 blob_unmap(void) 1974 { 1975 struct spdk_blob_store *bs = g_bs; 1976 struct spdk_blob *blob; 1977 struct spdk_io_channel *channel; 1978 struct spdk_blob_opts opts; 1979 uint8_t payload[4096]; 1980 int i; 1981 1982 channel = spdk_bs_alloc_io_channel(bs); 1983 CU_ASSERT(channel != NULL); 1984 1985 ut_spdk_blob_opts_init(&opts); 1986 opts.num_clusters = 10; 1987 1988 blob = ut_blob_create_and_open(bs, &opts); 1989 1990 spdk_blob_resize(blob, 10, blob_op_complete, NULL); 1991 poll_threads(); 1992 CU_ASSERT(g_bserrno == 0); 1993 1994 memset(payload, 0, sizeof(payload)); 1995 payload[0] = 0xFF; 1996 1997 /* 1998 * Set first byte of every cluster to 0xFF. 1999 * First cluster on device is reserved so let's start from cluster number 1 2000 */ 2001 for (i = 1; i < 11; i++) { 2002 g_dev_buffer[i * SPDK_BLOB_OPTS_CLUSTER_SZ] = 0xFF; 2003 } 2004 2005 /* Confirm writes */ 2006 for (i = 0; i < 10; i++) { 2007 payload[0] = 0; 2008 spdk_blob_io_read(blob, channel, &payload, i * SPDK_BLOB_OPTS_CLUSTER_SZ / 4096, 1, 2009 blob_op_complete, NULL); 2010 poll_threads(); 2011 CU_ASSERT(g_bserrno == 0); 2012 CU_ASSERT(payload[0] == 0xFF); 2013 } 2014 2015 /* Mark some clusters as unallocated */ 2016 blob->active.clusters[1] = 0; 2017 blob->active.clusters[2] = 0; 2018 blob->active.clusters[3] = 0; 2019 blob->active.clusters[6] = 0; 2020 blob->active.clusters[8] = 0; 2021 2022 /* Unmap clusters by resizing to 0 */ 2023 spdk_blob_resize(blob, 0, blob_op_complete, NULL); 2024 poll_threads(); 2025 CU_ASSERT(g_bserrno == 0); 2026 2027 spdk_blob_sync_md(blob, blob_op_complete, NULL); 2028 poll_threads(); 2029 CU_ASSERT(g_bserrno == 0); 2030 2031 /* Confirm that only 'allocated' clusters were unmapped */ 2032 for (i = 1; i < 11; i++) { 2033 switch (i) { 2034 case 2: 2035 case 3: 2036 case 4: 2037 case 7: 2038 case 9: 2039 CU_ASSERT(g_dev_buffer[i * SPDK_BLOB_OPTS_CLUSTER_SZ] == 0xFF); 2040 break; 2041 default: 2042 CU_ASSERT(g_dev_buffer[i * SPDK_BLOB_OPTS_CLUSTER_SZ] == 0); 2043 break; 2044 } 2045 } 2046 2047 spdk_bs_free_io_channel(channel); 2048 poll_threads(); 2049 2050 ut_blob_close_and_delete(bs, blob); 2051 } 2052 2053 static void 2054 blob_iter(void) 2055 { 2056 struct spdk_blob_store *bs = g_bs; 2057 struct spdk_blob *blob; 2058 spdk_blob_id blobid; 2059 struct spdk_blob_opts blob_opts; 2060 2061 spdk_bs_iter_first(bs, blob_op_with_handle_complete, NULL); 2062 poll_threads(); 2063 CU_ASSERT(g_blob == NULL); 2064 CU_ASSERT(g_bserrno == -ENOENT); 2065 2066 ut_spdk_blob_opts_init(&blob_opts); 2067 spdk_bs_create_blob_ext(bs, &blob_opts, blob_op_with_id_complete, NULL); 2068 poll_threads(); 2069 CU_ASSERT(g_bserrno == 0); 2070 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2071 blobid = g_blobid; 2072 2073 spdk_bs_iter_first(bs, blob_op_with_handle_complete, NULL); 2074 poll_threads(); 2075 CU_ASSERT(g_blob != NULL); 2076 CU_ASSERT(g_bserrno == 0); 2077 blob = g_blob; 2078 CU_ASSERT(spdk_blob_get_id(blob) == blobid); 2079 2080 spdk_bs_iter_next(bs, blob, blob_op_with_handle_complete, NULL); 2081 poll_threads(); 2082 CU_ASSERT(g_blob == NULL); 2083 CU_ASSERT(g_bserrno == -ENOENT); 2084 } 2085 2086 static void 2087 blob_xattr(void) 2088 { 2089 struct spdk_blob_store *bs = g_bs; 2090 struct spdk_blob *blob = g_blob; 2091 spdk_blob_id blobid = spdk_blob_get_id(blob); 2092 uint64_t length; 2093 int rc; 2094 const char *name1, *name2; 2095 const void *value; 2096 size_t value_len; 2097 struct spdk_xattr_names *names; 2098 2099 /* Test that set_xattr fails if md_ro flag is set. */ 2100 blob->md_ro = true; 2101 rc = spdk_blob_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1); 2102 CU_ASSERT(rc == -EPERM); 2103 2104 blob->md_ro = false; 2105 rc = spdk_blob_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1); 2106 CU_ASSERT(rc == 0); 2107 2108 length = 2345; 2109 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 2110 CU_ASSERT(rc == 0); 2111 2112 /* Overwrite "length" xattr. */ 2113 length = 3456; 2114 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 2115 CU_ASSERT(rc == 0); 2116 2117 /* get_xattr should still work even if md_ro flag is set. */ 2118 value = NULL; 2119 blob->md_ro = true; 2120 rc = spdk_blob_get_xattr_value(blob, "length", &value, &value_len); 2121 CU_ASSERT(rc == 0); 2122 SPDK_CU_ASSERT_FATAL(value != NULL); 2123 CU_ASSERT(*(uint64_t *)value == length); 2124 CU_ASSERT(value_len == 8); 2125 blob->md_ro = false; 2126 2127 rc = spdk_blob_get_xattr_value(blob, "foobar", &value, &value_len); 2128 CU_ASSERT(rc == -ENOENT); 2129 2130 names = NULL; 2131 rc = spdk_blob_get_xattr_names(blob, &names); 2132 CU_ASSERT(rc == 0); 2133 SPDK_CU_ASSERT_FATAL(names != NULL); 2134 CU_ASSERT(spdk_xattr_names_get_count(names) == 2); 2135 name1 = spdk_xattr_names_get_name(names, 0); 2136 SPDK_CU_ASSERT_FATAL(name1 != NULL); 2137 CU_ASSERT(!strcmp(name1, "name") || !strcmp(name1, "length")); 2138 name2 = spdk_xattr_names_get_name(names, 1); 2139 SPDK_CU_ASSERT_FATAL(name2 != NULL); 2140 CU_ASSERT(!strcmp(name2, "name") || !strcmp(name2, "length")); 2141 CU_ASSERT(strcmp(name1, name2)); 2142 spdk_xattr_names_free(names); 2143 2144 /* Confirm that remove_xattr fails if md_ro is set to true. */ 2145 blob->md_ro = true; 2146 rc = spdk_blob_remove_xattr(blob, "name"); 2147 CU_ASSERT(rc == -EPERM); 2148 2149 blob->md_ro = false; 2150 rc = spdk_blob_remove_xattr(blob, "name"); 2151 CU_ASSERT(rc == 0); 2152 2153 rc = spdk_blob_remove_xattr(blob, "foobar"); 2154 CU_ASSERT(rc == -ENOENT); 2155 2156 /* Set internal xattr */ 2157 length = 7898; 2158 rc = blob_set_xattr(blob, "internal", &length, sizeof(length), true); 2159 CU_ASSERT(rc == 0); 2160 rc = blob_get_xattr_value(blob, "internal", &value, &value_len, true); 2161 CU_ASSERT(rc == 0); 2162 CU_ASSERT(*(uint64_t *)value == length); 2163 /* try to get public xattr with same name */ 2164 rc = spdk_blob_get_xattr_value(blob, "internal", &value, &value_len); 2165 CU_ASSERT(rc != 0); 2166 rc = blob_get_xattr_value(blob, "internal", &value, &value_len, false); 2167 CU_ASSERT(rc != 0); 2168 /* Check if SPDK_BLOB_INTERNAL_XATTR is set */ 2169 CU_ASSERT((blob->invalid_flags & SPDK_BLOB_INTERNAL_XATTR) == 2170 SPDK_BLOB_INTERNAL_XATTR); 2171 2172 spdk_blob_close(blob, blob_op_complete, NULL); 2173 poll_threads(); 2174 2175 /* Check if xattrs are persisted */ 2176 ut_bs_reload(&bs, NULL); 2177 2178 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 2179 poll_threads(); 2180 CU_ASSERT(g_bserrno == 0); 2181 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2182 blob = g_blob; 2183 2184 rc = blob_get_xattr_value(blob, "internal", &value, &value_len, true); 2185 CU_ASSERT(rc == 0); 2186 CU_ASSERT(*(uint64_t *)value == length); 2187 2188 /* try to get internal xattr trough public call */ 2189 rc = spdk_blob_get_xattr_value(blob, "internal", &value, &value_len); 2190 CU_ASSERT(rc != 0); 2191 2192 rc = blob_remove_xattr(blob, "internal", true); 2193 CU_ASSERT(rc == 0); 2194 2195 CU_ASSERT((blob->invalid_flags & SPDK_BLOB_INTERNAL_XATTR) == 0); 2196 } 2197 2198 static void 2199 blob_parse_md(void) 2200 { 2201 struct spdk_blob_store *bs = g_bs; 2202 struct spdk_blob *blob; 2203 int rc; 2204 uint32_t used_pages; 2205 size_t xattr_length; 2206 char *xattr; 2207 2208 used_pages = spdk_bit_array_count_set(bs->used_md_pages); 2209 blob = ut_blob_create_and_open(bs, NULL); 2210 2211 /* Create large extent to force more than 1 page of metadata. */ 2212 xattr_length = SPDK_BS_MAX_DESC_SIZE - sizeof(struct spdk_blob_md_descriptor_xattr) - 2213 strlen("large_xattr"); 2214 xattr = calloc(xattr_length, sizeof(char)); 2215 SPDK_CU_ASSERT_FATAL(xattr != NULL); 2216 rc = spdk_blob_set_xattr(blob, "large_xattr", xattr, xattr_length); 2217 free(xattr); 2218 SPDK_CU_ASSERT_FATAL(rc == 0); 2219 2220 spdk_blob_sync_md(blob, blob_op_complete, NULL); 2221 poll_threads(); 2222 2223 /* Delete the blob and verify that number of pages returned to before its creation. */ 2224 SPDK_CU_ASSERT_FATAL(used_pages != spdk_bit_array_count_set(bs->used_md_pages)); 2225 ut_blob_close_and_delete(bs, blob); 2226 SPDK_CU_ASSERT_FATAL(used_pages == spdk_bit_array_count_set(bs->used_md_pages)); 2227 } 2228 2229 static void 2230 bs_load(void) 2231 { 2232 struct spdk_blob_store *bs; 2233 struct spdk_bs_dev *dev; 2234 spdk_blob_id blobid; 2235 struct spdk_blob *blob; 2236 struct spdk_bs_super_block *super_block; 2237 uint64_t length; 2238 int rc; 2239 const void *value; 2240 size_t value_len; 2241 struct spdk_bs_opts opts; 2242 struct spdk_blob_opts blob_opts; 2243 2244 dev = init_dev(); 2245 spdk_bs_opts_init(&opts, sizeof(opts)); 2246 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 2247 2248 /* Initialize a new blob store */ 2249 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 2250 poll_threads(); 2251 CU_ASSERT(g_bserrno == 0); 2252 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2253 bs = g_bs; 2254 2255 /* Try to open a blobid that does not exist */ 2256 spdk_bs_open_blob(bs, 0, blob_op_with_handle_complete, NULL); 2257 poll_threads(); 2258 CU_ASSERT(g_bserrno == -ENOENT); 2259 CU_ASSERT(g_blob == NULL); 2260 2261 /* Create a blob */ 2262 blob = ut_blob_create_and_open(bs, NULL); 2263 blobid = spdk_blob_get_id(blob); 2264 2265 /* Try again to open valid blob but without the upper bit set */ 2266 spdk_bs_open_blob(bs, blobid & 0xFFFFFFFF, blob_op_with_handle_complete, NULL); 2267 poll_threads(); 2268 CU_ASSERT(g_bserrno == -ENOENT); 2269 CU_ASSERT(g_blob == NULL); 2270 2271 /* Set some xattrs */ 2272 rc = spdk_blob_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1); 2273 CU_ASSERT(rc == 0); 2274 2275 length = 2345; 2276 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 2277 CU_ASSERT(rc == 0); 2278 2279 /* Resize the blob */ 2280 spdk_blob_resize(blob, 10, blob_op_complete, NULL); 2281 poll_threads(); 2282 CU_ASSERT(g_bserrno == 0); 2283 2284 spdk_blob_close(blob, blob_op_complete, NULL); 2285 poll_threads(); 2286 CU_ASSERT(g_bserrno == 0); 2287 blob = NULL; 2288 g_blob = NULL; 2289 g_blobid = SPDK_BLOBID_INVALID; 2290 2291 /* Unload the blob store */ 2292 spdk_bs_unload(bs, bs_op_complete, NULL); 2293 poll_threads(); 2294 CU_ASSERT(g_bserrno == 0); 2295 g_bs = NULL; 2296 g_blob = NULL; 2297 g_blobid = 0; 2298 2299 super_block = (struct spdk_bs_super_block *)g_dev_buffer; 2300 CU_ASSERT(super_block->clean == 1); 2301 2302 /* Load should fail for device with an unsupported blocklen */ 2303 dev = init_dev(); 2304 dev->blocklen = SPDK_BS_PAGE_SIZE * 2; 2305 spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL); 2306 poll_threads(); 2307 CU_ASSERT(g_bserrno == -EINVAL); 2308 2309 /* Load should when max_md_ops is set to zero */ 2310 dev = init_dev(); 2311 spdk_bs_opts_init(&opts, sizeof(opts)); 2312 opts.max_md_ops = 0; 2313 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2314 poll_threads(); 2315 CU_ASSERT(g_bserrno == -EINVAL); 2316 2317 /* Load should when max_channel_ops is set to zero */ 2318 dev = init_dev(); 2319 spdk_bs_opts_init(&opts, sizeof(opts)); 2320 opts.max_channel_ops = 0; 2321 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2322 poll_threads(); 2323 CU_ASSERT(g_bserrno == -EINVAL); 2324 2325 /* Load an existing blob store */ 2326 dev = init_dev(); 2327 spdk_bs_opts_init(&opts, sizeof(opts)); 2328 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 2329 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2330 poll_threads(); 2331 CU_ASSERT(g_bserrno == 0); 2332 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2333 bs = g_bs; 2334 2335 super_block = (struct spdk_bs_super_block *)g_dev_buffer; 2336 CU_ASSERT(super_block->clean == 1); 2337 CU_ASSERT(super_block->size == dev->blockcnt * dev->blocklen); 2338 2339 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 2340 poll_threads(); 2341 CU_ASSERT(g_bserrno == 0); 2342 CU_ASSERT(g_blob != NULL); 2343 blob = g_blob; 2344 2345 /* Verify that blobstore is marked dirty after first metadata sync */ 2346 spdk_blob_sync_md(blob, blob_op_complete, NULL); 2347 CU_ASSERT(super_block->clean == 1); 2348 2349 /* Get the xattrs */ 2350 value = NULL; 2351 rc = spdk_blob_get_xattr_value(blob, "length", &value, &value_len); 2352 CU_ASSERT(rc == 0); 2353 SPDK_CU_ASSERT_FATAL(value != NULL); 2354 CU_ASSERT(*(uint64_t *)value == length); 2355 CU_ASSERT(value_len == 8); 2356 2357 rc = spdk_blob_get_xattr_value(blob, "foobar", &value, &value_len); 2358 CU_ASSERT(rc == -ENOENT); 2359 2360 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 2361 2362 spdk_blob_close(blob, blob_op_complete, NULL); 2363 poll_threads(); 2364 CU_ASSERT(g_bserrno == 0); 2365 blob = NULL; 2366 g_blob = NULL; 2367 2368 spdk_bs_unload(bs, bs_op_complete, NULL); 2369 poll_threads(); 2370 CU_ASSERT(g_bserrno == 0); 2371 g_bs = NULL; 2372 2373 /* Load should fail: bdev size < saved size */ 2374 dev = init_dev(); 2375 dev->blockcnt /= 2; 2376 2377 spdk_bs_opts_init(&opts, sizeof(opts)); 2378 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 2379 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2380 poll_threads(); 2381 2382 CU_ASSERT(g_bserrno == -EILSEQ); 2383 2384 /* Load should succeed: bdev size > saved size */ 2385 dev = init_dev(); 2386 dev->blockcnt *= 4; 2387 2388 spdk_bs_opts_init(&opts, sizeof(opts)); 2389 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 2390 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2391 poll_threads(); 2392 CU_ASSERT(g_bserrno == 0); 2393 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2394 bs = g_bs; 2395 2396 CU_ASSERT(g_bserrno == 0); 2397 spdk_bs_unload(bs, bs_op_complete, NULL); 2398 poll_threads(); 2399 2400 2401 /* Test compatibility mode */ 2402 2403 dev = init_dev(); 2404 super_block->size = 0; 2405 super_block->crc = blob_md_page_calc_crc(super_block); 2406 2407 spdk_bs_opts_init(&opts, sizeof(opts)); 2408 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 2409 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2410 poll_threads(); 2411 CU_ASSERT(g_bserrno == 0); 2412 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2413 bs = g_bs; 2414 2415 /* Create a blob */ 2416 ut_spdk_blob_opts_init(&blob_opts); 2417 spdk_bs_create_blob_ext(bs, &blob_opts, blob_op_with_id_complete, NULL); 2418 poll_threads(); 2419 CU_ASSERT(g_bserrno == 0); 2420 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2421 2422 /* Blobstore should update number of blocks in super_block */ 2423 CU_ASSERT(super_block->size == dev->blockcnt * dev->blocklen); 2424 CU_ASSERT(super_block->clean == 0); 2425 2426 spdk_bs_unload(bs, bs_op_complete, NULL); 2427 poll_threads(); 2428 CU_ASSERT(g_bserrno == 0); 2429 CU_ASSERT(super_block->clean == 1); 2430 g_bs = NULL; 2431 2432 } 2433 2434 static void 2435 bs_load_pending_removal(void) 2436 { 2437 struct spdk_blob_store *bs = g_bs; 2438 struct spdk_blob_opts opts; 2439 struct spdk_blob *blob, *snapshot; 2440 spdk_blob_id blobid, snapshotid; 2441 const void *value; 2442 size_t value_len; 2443 int rc; 2444 2445 /* Create blob */ 2446 ut_spdk_blob_opts_init(&opts); 2447 opts.num_clusters = 10; 2448 2449 blob = ut_blob_create_and_open(bs, &opts); 2450 blobid = spdk_blob_get_id(blob); 2451 2452 /* Create snapshot */ 2453 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 2454 poll_threads(); 2455 CU_ASSERT(g_bserrno == 0); 2456 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2457 snapshotid = g_blobid; 2458 2459 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 2460 poll_threads(); 2461 CU_ASSERT(g_bserrno == 0); 2462 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2463 snapshot = g_blob; 2464 2465 /* Set SNAPSHOT_PENDING_REMOVAL xattr */ 2466 snapshot->md_ro = false; 2467 rc = blob_set_xattr(snapshot, SNAPSHOT_PENDING_REMOVAL, &blobid, sizeof(spdk_blob_id), true); 2468 CU_ASSERT(rc == 0); 2469 snapshot->md_ro = true; 2470 2471 spdk_blob_close(snapshot, blob_op_complete, NULL); 2472 poll_threads(); 2473 CU_ASSERT(g_bserrno == 0); 2474 2475 spdk_blob_close(blob, blob_op_complete, NULL); 2476 poll_threads(); 2477 CU_ASSERT(g_bserrno == 0); 2478 2479 /* Reload blobstore */ 2480 ut_bs_reload(&bs, NULL); 2481 2482 /* Snapshot should not be removed as blob is still pointing to it */ 2483 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 2484 poll_threads(); 2485 CU_ASSERT(g_bserrno == 0); 2486 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2487 snapshot = g_blob; 2488 2489 /* SNAPSHOT_PENDING_REMOVAL xattr should be removed during load */ 2490 rc = spdk_blob_get_xattr_value(snapshot, SNAPSHOT_PENDING_REMOVAL, &value, &value_len); 2491 CU_ASSERT(rc != 0); 2492 2493 /* Set SNAPSHOT_PENDING_REMOVAL xattr again */ 2494 snapshot->md_ro = false; 2495 rc = blob_set_xattr(snapshot, SNAPSHOT_PENDING_REMOVAL, &blobid, sizeof(spdk_blob_id), true); 2496 CU_ASSERT(rc == 0); 2497 snapshot->md_ro = true; 2498 2499 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 2500 poll_threads(); 2501 CU_ASSERT(g_bserrno == 0); 2502 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2503 blob = g_blob; 2504 2505 /* Remove parent_id from blob by removing BLOB_SNAPSHOT xattr */ 2506 blob_remove_xattr(blob, BLOB_SNAPSHOT, true); 2507 2508 spdk_blob_sync_md(blob, blob_op_complete, NULL); 2509 poll_threads(); 2510 CU_ASSERT(g_bserrno == 0); 2511 2512 spdk_blob_close(snapshot, blob_op_complete, NULL); 2513 poll_threads(); 2514 CU_ASSERT(g_bserrno == 0); 2515 2516 spdk_blob_close(blob, blob_op_complete, NULL); 2517 poll_threads(); 2518 CU_ASSERT(g_bserrno == 0); 2519 2520 /* Reload blobstore */ 2521 ut_bs_reload(&bs, NULL); 2522 2523 /* Snapshot should be removed as blob is not pointing to it anymore */ 2524 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 2525 poll_threads(); 2526 CU_ASSERT(g_bserrno != 0); 2527 } 2528 2529 static void 2530 bs_load_custom_cluster_size(void) 2531 { 2532 struct spdk_blob_store *bs; 2533 struct spdk_bs_dev *dev; 2534 struct spdk_bs_super_block *super_block; 2535 struct spdk_bs_opts opts; 2536 uint32_t custom_cluster_size = 4194304; /* 4MiB */ 2537 uint32_t cluster_sz; 2538 uint64_t total_clusters; 2539 2540 dev = init_dev(); 2541 spdk_bs_opts_init(&opts, sizeof(opts)); 2542 opts.cluster_sz = custom_cluster_size; 2543 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 2544 2545 /* Initialize a new blob store */ 2546 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 2547 poll_threads(); 2548 CU_ASSERT(g_bserrno == 0); 2549 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2550 bs = g_bs; 2551 cluster_sz = bs->cluster_sz; 2552 total_clusters = bs->total_clusters; 2553 2554 /* Unload the blob store */ 2555 spdk_bs_unload(bs, bs_op_complete, NULL); 2556 poll_threads(); 2557 CU_ASSERT(g_bserrno == 0); 2558 g_bs = NULL; 2559 g_blob = NULL; 2560 g_blobid = 0; 2561 2562 super_block = (struct spdk_bs_super_block *)g_dev_buffer; 2563 CU_ASSERT(super_block->clean == 1); 2564 2565 /* Load an existing blob store */ 2566 dev = init_dev(); 2567 spdk_bs_opts_init(&opts, sizeof(opts)); 2568 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 2569 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2570 poll_threads(); 2571 CU_ASSERT(g_bserrno == 0); 2572 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2573 bs = g_bs; 2574 /* Compare cluster size and number to one after initialization */ 2575 CU_ASSERT(cluster_sz == bs->cluster_sz); 2576 CU_ASSERT(total_clusters == bs->total_clusters); 2577 2578 super_block = (struct spdk_bs_super_block *)g_dev_buffer; 2579 CU_ASSERT(super_block->clean == 1); 2580 CU_ASSERT(super_block->size == dev->blockcnt * dev->blocklen); 2581 2582 spdk_bs_unload(bs, bs_op_complete, NULL); 2583 poll_threads(); 2584 CU_ASSERT(g_bserrno == 0); 2585 CU_ASSERT(super_block->clean == 1); 2586 g_bs = NULL; 2587 } 2588 2589 static void 2590 bs_load_after_failed_grow(void) 2591 { 2592 struct spdk_blob_store *bs; 2593 struct spdk_bs_dev *dev; 2594 struct spdk_bs_super_block *super_block; 2595 struct spdk_bs_opts opts; 2596 struct spdk_bs_md_mask *mask; 2597 struct spdk_blob_opts blob_opts; 2598 struct spdk_blob *blob, *snapshot; 2599 spdk_blob_id blobid, snapshotid; 2600 uint64_t total_data_clusters; 2601 2602 dev = init_dev(); 2603 spdk_bs_opts_init(&opts, sizeof(opts)); 2604 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 2605 /* 2606 * The bdev_size is 64M, cluster_sz is 1M, so there are 64 clusters. The 2607 * blobstore will create 64 md pages by default. We set num_md_pages to 128, 2608 * thus the blobstore could grow to the double size. 2609 */ 2610 opts.num_md_pages = 128; 2611 2612 /* Initialize a new blob store */ 2613 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 2614 poll_threads(); 2615 CU_ASSERT(g_bserrno == 0); 2616 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2617 bs = g_bs; 2618 2619 /* Create blob */ 2620 ut_spdk_blob_opts_init(&blob_opts); 2621 blob_opts.num_clusters = 10; 2622 2623 blob = ut_blob_create_and_open(bs, &blob_opts); 2624 blobid = spdk_blob_get_id(blob); 2625 2626 /* Create snapshot */ 2627 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 2628 poll_threads(); 2629 CU_ASSERT(g_bserrno == 0); 2630 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2631 snapshotid = g_blobid; 2632 2633 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 2634 poll_threads(); 2635 CU_ASSERT(g_bserrno == 0); 2636 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2637 snapshot = g_blob; 2638 2639 spdk_blob_close(snapshot, blob_op_complete, NULL); 2640 poll_threads(); 2641 CU_ASSERT(g_bserrno == 0); 2642 2643 spdk_blob_close(blob, blob_op_complete, NULL); 2644 poll_threads(); 2645 CU_ASSERT(g_bserrno == 0); 2646 2647 total_data_clusters = bs->total_data_clusters; 2648 CU_ASSERT(bs->num_free_clusters + 10 == total_data_clusters); 2649 2650 /* Unload the blob store */ 2651 spdk_bs_unload(bs, bs_op_complete, NULL); 2652 poll_threads(); 2653 CU_ASSERT(g_bserrno == 0); 2654 g_bs = NULL; 2655 g_blob = NULL; 2656 g_blobid = 0; 2657 2658 super_block = (struct spdk_bs_super_block *)g_dev_buffer; 2659 CU_ASSERT(super_block->clean == 1); 2660 2661 mask = (struct spdk_bs_md_mask *)(g_dev_buffer + super_block->used_cluster_mask_start * 4096); 2662 CU_ASSERT(mask->type == SPDK_MD_MASK_TYPE_USED_CLUSTERS); 2663 CU_ASSERT(mask->length == super_block->size / super_block->cluster_size); 2664 2665 /* 2666 * We change the mask->length to emulate this scenario: A spdk_bs_grow failed after it changed 2667 * the used_cluster bitmap length, but it didn't change the super block yet. 2668 */ 2669 mask->length *= 2; 2670 2671 /* Load an existing blob store */ 2672 dev = init_dev(); 2673 dev->blockcnt *= 2; 2674 spdk_bs_opts_init(&opts, sizeof(opts)); 2675 opts.clear_method = BS_CLEAR_WITH_NONE; 2676 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 2677 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2678 poll_threads(); 2679 CU_ASSERT(g_bserrno == 0); 2680 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2681 bs = g_bs; 2682 2683 /* Check the capacity is the same as before */ 2684 CU_ASSERT(bs->total_data_clusters == total_data_clusters); 2685 CU_ASSERT(bs->num_free_clusters + 10 == total_data_clusters); 2686 2687 /* Check the blob and the snapshot are still available */ 2688 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 2689 poll_threads(); 2690 CU_ASSERT(g_bserrno == 0); 2691 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2692 blob = g_blob; 2693 2694 spdk_blob_close(blob, blob_op_complete, NULL); 2695 poll_threads(); 2696 CU_ASSERT(g_bserrno == 0); 2697 2698 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 2699 poll_threads(); 2700 CU_ASSERT(g_bserrno == 0); 2701 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2702 snapshot = g_blob; 2703 2704 spdk_blob_close(snapshot, blob_op_complete, NULL); 2705 poll_threads(); 2706 CU_ASSERT(g_bserrno == 0); 2707 2708 spdk_bs_unload(bs, bs_op_complete, NULL); 2709 poll_threads(); 2710 CU_ASSERT(g_bserrno == 0); 2711 CU_ASSERT(super_block->clean == 1); 2712 g_bs = NULL; 2713 } 2714 2715 static void 2716 bs_type(void) 2717 { 2718 struct spdk_blob_store *bs; 2719 struct spdk_bs_dev *dev; 2720 struct spdk_bs_opts opts; 2721 2722 dev = init_dev(); 2723 spdk_bs_opts_init(&opts, sizeof(opts)); 2724 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 2725 2726 /* Initialize a new blob store */ 2727 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 2728 poll_threads(); 2729 CU_ASSERT(g_bserrno == 0); 2730 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2731 bs = g_bs; 2732 2733 /* Unload the blob store */ 2734 spdk_bs_unload(bs, bs_op_complete, NULL); 2735 poll_threads(); 2736 CU_ASSERT(g_bserrno == 0); 2737 g_bs = NULL; 2738 g_blob = NULL; 2739 g_blobid = 0; 2740 2741 /* Load non existing blobstore type */ 2742 dev = init_dev(); 2743 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "NONEXISTING"); 2744 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2745 poll_threads(); 2746 CU_ASSERT(g_bserrno != 0); 2747 2748 /* Load with empty blobstore type */ 2749 dev = init_dev(); 2750 memset(opts.bstype.bstype, 0, sizeof(opts.bstype.bstype)); 2751 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2752 poll_threads(); 2753 CU_ASSERT(g_bserrno == 0); 2754 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2755 bs = g_bs; 2756 2757 spdk_bs_unload(bs, bs_op_complete, NULL); 2758 poll_threads(); 2759 CU_ASSERT(g_bserrno == 0); 2760 g_bs = NULL; 2761 2762 /* Initialize a new blob store with empty bstype */ 2763 dev = init_dev(); 2764 memset(opts.bstype.bstype, 0, sizeof(opts.bstype.bstype)); 2765 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 2766 poll_threads(); 2767 CU_ASSERT(g_bserrno == 0); 2768 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2769 bs = g_bs; 2770 2771 spdk_bs_unload(bs, bs_op_complete, NULL); 2772 poll_threads(); 2773 CU_ASSERT(g_bserrno == 0); 2774 g_bs = NULL; 2775 2776 /* Load non existing blobstore type */ 2777 dev = init_dev(); 2778 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "NONEXISTING"); 2779 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2780 poll_threads(); 2781 CU_ASSERT(g_bserrno != 0); 2782 2783 /* Load with empty blobstore type */ 2784 dev = init_dev(); 2785 memset(opts.bstype.bstype, 0, sizeof(opts.bstype.bstype)); 2786 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2787 poll_threads(); 2788 CU_ASSERT(g_bserrno == 0); 2789 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2790 bs = g_bs; 2791 2792 spdk_bs_unload(bs, bs_op_complete, NULL); 2793 poll_threads(); 2794 CU_ASSERT(g_bserrno == 0); 2795 g_bs = NULL; 2796 } 2797 2798 static void 2799 bs_super_block(void) 2800 { 2801 struct spdk_blob_store *bs; 2802 struct spdk_bs_dev *dev; 2803 struct spdk_bs_super_block *super_block; 2804 struct spdk_bs_opts opts; 2805 struct spdk_bs_super_block_ver1 super_block_v1; 2806 2807 dev = init_dev(); 2808 spdk_bs_opts_init(&opts, sizeof(opts)); 2809 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 2810 2811 /* Initialize a new blob store */ 2812 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 2813 poll_threads(); 2814 CU_ASSERT(g_bserrno == 0); 2815 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2816 bs = g_bs; 2817 2818 /* Unload the blob store */ 2819 spdk_bs_unload(bs, bs_op_complete, NULL); 2820 poll_threads(); 2821 CU_ASSERT(g_bserrno == 0); 2822 g_bs = NULL; 2823 g_blob = NULL; 2824 g_blobid = 0; 2825 2826 /* Load an existing blob store with version newer than supported */ 2827 super_block = (struct spdk_bs_super_block *)g_dev_buffer; 2828 super_block->version++; 2829 2830 dev = init_dev(); 2831 memset(opts.bstype.bstype, 0, sizeof(opts.bstype.bstype)); 2832 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2833 poll_threads(); 2834 CU_ASSERT(g_bserrno != 0); 2835 2836 /* Create a new blob store with super block version 1 */ 2837 dev = init_dev(); 2838 super_block_v1.version = 1; 2839 memcpy(super_block_v1.signature, "SPDKBLOB", sizeof(super_block_v1.signature)); 2840 super_block_v1.length = 0x1000; 2841 super_block_v1.clean = 1; 2842 super_block_v1.super_blob = 0xFFFFFFFFFFFFFFFF; 2843 super_block_v1.cluster_size = 0x100000; 2844 super_block_v1.used_page_mask_start = 0x01; 2845 super_block_v1.used_page_mask_len = 0x01; 2846 super_block_v1.used_cluster_mask_start = 0x02; 2847 super_block_v1.used_cluster_mask_len = 0x01; 2848 super_block_v1.md_start = 0x03; 2849 super_block_v1.md_len = 0x40; 2850 memset(super_block_v1.reserved, 0, 4036); 2851 super_block_v1.crc = blob_md_page_calc_crc(&super_block_v1); 2852 memcpy(g_dev_buffer, &super_block_v1, sizeof(struct spdk_bs_super_block_ver1)); 2853 2854 memset(opts.bstype.bstype, 0, sizeof(opts.bstype.bstype)); 2855 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2856 poll_threads(); 2857 CU_ASSERT(g_bserrno == 0); 2858 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2859 bs = g_bs; 2860 2861 spdk_bs_unload(bs, bs_op_complete, NULL); 2862 poll_threads(); 2863 CU_ASSERT(g_bserrno == 0); 2864 g_bs = NULL; 2865 } 2866 2867 static void 2868 bs_test_recover_cluster_count(void) 2869 { 2870 struct spdk_blob_store *bs; 2871 struct spdk_bs_dev *dev; 2872 struct spdk_bs_super_block super_block; 2873 struct spdk_bs_opts opts; 2874 2875 dev = init_dev(); 2876 spdk_bs_opts_init(&opts, sizeof(opts)); 2877 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 2878 2879 super_block.version = 3; 2880 memcpy(super_block.signature, "SPDKBLOB", sizeof(super_block.signature)); 2881 super_block.length = 0x1000; 2882 super_block.clean = 0; 2883 super_block.super_blob = 0xFFFFFFFFFFFFFFFF; 2884 super_block.cluster_size = 4096; 2885 super_block.used_page_mask_start = 0x01; 2886 super_block.used_page_mask_len = 0x01; 2887 super_block.used_cluster_mask_start = 0x02; 2888 super_block.used_cluster_mask_len = 0x01; 2889 super_block.used_blobid_mask_start = 0x03; 2890 super_block.used_blobid_mask_len = 0x01; 2891 super_block.md_start = 0x04; 2892 super_block.md_len = 0x40; 2893 memset(super_block.bstype.bstype, 0, sizeof(super_block.bstype.bstype)); 2894 super_block.size = dev->blockcnt * dev->blocklen; 2895 super_block.io_unit_size = 0x1000; 2896 memset(super_block.reserved, 0, 4000); 2897 super_block.crc = blob_md_page_calc_crc(&super_block); 2898 memcpy(g_dev_buffer, &super_block, sizeof(struct spdk_bs_super_block)); 2899 2900 memset(opts.bstype.bstype, 0, sizeof(opts.bstype.bstype)); 2901 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2902 poll_threads(); 2903 CU_ASSERT(g_bserrno == 0); 2904 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2905 bs = g_bs; 2906 CU_ASSERT(bs->num_free_clusters == bs->total_clusters - (super_block.md_start + 2907 super_block.md_len)); 2908 2909 spdk_bs_unload(bs, bs_op_complete, NULL); 2910 poll_threads(); 2911 CU_ASSERT(g_bserrno == 0); 2912 g_bs = NULL; 2913 } 2914 2915 static void 2916 bs_test_grow(void) 2917 { 2918 struct spdk_blob_store *bs; 2919 struct spdk_bs_dev *dev; 2920 struct spdk_bs_super_block super_block; 2921 struct spdk_bs_opts opts; 2922 struct spdk_bs_md_mask mask; 2923 uint64_t bdev_size; 2924 2925 dev = init_dev(); 2926 bdev_size = dev->blockcnt * dev->blocklen; 2927 spdk_bs_opts_init(&opts, sizeof(opts)); 2928 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 2929 poll_threads(); 2930 CU_ASSERT(g_bserrno == 0); 2931 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2932 bs = g_bs; 2933 2934 spdk_bs_unload(bs, bs_op_complete, NULL); 2935 poll_threads(); 2936 CU_ASSERT(g_bserrno == 0); 2937 g_bs = NULL; 2938 2939 /* 2940 * To make sure all the metadata are updated to the disk, 2941 * we check the g_dev_buffer after spdk_bs_unload. 2942 */ 2943 memcpy(&super_block, g_dev_buffer, sizeof(struct spdk_bs_super_block)); 2944 CU_ASSERT(super_block.size == bdev_size); 2945 2946 /* 2947 * Make sure the used_cluster mask is correct. 2948 */ 2949 memcpy(&mask, g_dev_buffer + super_block.used_cluster_mask_start * 4096, 2950 sizeof(struct spdk_bs_md_mask)); 2951 CU_ASSERT(mask.type == SPDK_MD_MASK_TYPE_USED_CLUSTERS); 2952 CU_ASSERT(mask.length == bdev_size / (1 * 1024 * 1024)); 2953 2954 /* 2955 * The default dev size is 64M, here we set the dev size to 128M, 2956 * then the blobstore will adjust the metadata according to the new size. 2957 * The dev size is larger than the g_dev_buffer size, so we set clear_method 2958 * to NONE, or the blobstore will try to clear the dev and will write beyond 2959 * the end of g_dev_buffer. 2960 */ 2961 dev = init_dev(); 2962 dev->blockcnt = (128L * 1024L * 1024L) / dev->blocklen; 2963 bdev_size = dev->blockcnt * dev->blocklen; 2964 spdk_bs_opts_init(&opts, sizeof(opts)); 2965 opts.clear_method = BS_CLEAR_WITH_NONE; 2966 spdk_bs_grow(dev, &opts, bs_op_with_handle_complete, NULL); 2967 poll_threads(); 2968 CU_ASSERT(g_bserrno == 0); 2969 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2970 bs = g_bs; 2971 2972 /* 2973 * After spdk_bs_grow, all metadata are updated to the disk. 2974 * So we can check g_dev_buffer now. 2975 */ 2976 memcpy(&super_block, g_dev_buffer, sizeof(struct spdk_bs_super_block)); 2977 CU_ASSERT(super_block.size == bdev_size); 2978 2979 /* 2980 * Make sure the used_cluster mask has been updated according to the bdev size 2981 */ 2982 memcpy(&mask, g_dev_buffer + super_block.used_cluster_mask_start * 4096, 2983 sizeof(struct spdk_bs_md_mask)); 2984 CU_ASSERT(mask.type == SPDK_MD_MASK_TYPE_USED_CLUSTERS); 2985 CU_ASSERT(mask.length == bdev_size / (1 * 1024 * 1024)); 2986 2987 spdk_bs_unload(bs, bs_op_complete, NULL); 2988 poll_threads(); 2989 CU_ASSERT(g_bserrno == 0); 2990 g_bs = NULL; 2991 } 2992 2993 /* 2994 * Create a blobstore and then unload it. 2995 */ 2996 static void 2997 bs_unload(void) 2998 { 2999 struct spdk_blob_store *bs = g_bs; 3000 struct spdk_blob *blob; 3001 3002 /* Create a blob and open it. */ 3003 blob = ut_blob_create_and_open(bs, NULL); 3004 3005 /* Try to unload blobstore, should fail with open blob */ 3006 g_bserrno = -1; 3007 spdk_bs_unload(bs, bs_op_complete, NULL); 3008 poll_threads(); 3009 CU_ASSERT(g_bserrno == -EBUSY); 3010 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 3011 3012 /* Close the blob, then successfully unload blobstore */ 3013 g_bserrno = -1; 3014 spdk_blob_close(blob, blob_op_complete, NULL); 3015 poll_threads(); 3016 CU_ASSERT(g_bserrno == 0); 3017 } 3018 3019 /* 3020 * Create a blobstore with a cluster size different than the default, and ensure it is 3021 * persisted. 3022 */ 3023 static void 3024 bs_cluster_sz(void) 3025 { 3026 struct spdk_blob_store *bs; 3027 struct spdk_bs_dev *dev; 3028 struct spdk_bs_opts opts; 3029 uint32_t cluster_sz; 3030 3031 /* Set cluster size to zero */ 3032 dev = init_dev(); 3033 spdk_bs_opts_init(&opts, sizeof(opts)); 3034 opts.cluster_sz = 0; 3035 3036 /* Initialize a new blob store */ 3037 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 3038 poll_threads(); 3039 CU_ASSERT(g_bserrno == -EINVAL); 3040 SPDK_CU_ASSERT_FATAL(g_bs == NULL); 3041 3042 /* 3043 * Set cluster size to blobstore page size, 3044 * to work it is required to be at least twice the blobstore page size. 3045 */ 3046 dev = init_dev(); 3047 spdk_bs_opts_init(&opts, sizeof(opts)); 3048 opts.cluster_sz = SPDK_BS_PAGE_SIZE; 3049 3050 /* Initialize a new blob store */ 3051 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 3052 poll_threads(); 3053 CU_ASSERT(g_bserrno == -ENOMEM); 3054 SPDK_CU_ASSERT_FATAL(g_bs == NULL); 3055 3056 /* 3057 * Set cluster size to lower than page size, 3058 * to work it is required to be at least twice the blobstore page size. 3059 */ 3060 dev = init_dev(); 3061 spdk_bs_opts_init(&opts, sizeof(opts)); 3062 opts.cluster_sz = SPDK_BS_PAGE_SIZE - 1; 3063 3064 /* Initialize a new blob store */ 3065 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 3066 poll_threads(); 3067 CU_ASSERT(g_bserrno == -EINVAL); 3068 SPDK_CU_ASSERT_FATAL(g_bs == NULL); 3069 3070 /* Set cluster size to twice the default */ 3071 dev = init_dev(); 3072 spdk_bs_opts_init(&opts, sizeof(opts)); 3073 opts.cluster_sz *= 2; 3074 cluster_sz = opts.cluster_sz; 3075 3076 /* Initialize a new blob store */ 3077 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 3078 poll_threads(); 3079 CU_ASSERT(g_bserrno == 0); 3080 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 3081 bs = g_bs; 3082 3083 CU_ASSERT(spdk_bs_get_cluster_size(bs) == cluster_sz); 3084 3085 ut_bs_reload(&bs, &opts); 3086 3087 CU_ASSERT(spdk_bs_get_cluster_size(bs) == cluster_sz); 3088 3089 spdk_bs_unload(bs, bs_op_complete, NULL); 3090 poll_threads(); 3091 CU_ASSERT(g_bserrno == 0); 3092 g_bs = NULL; 3093 } 3094 3095 /* 3096 * Create a blobstore, reload it and ensure total usable cluster count 3097 * stays the same. 3098 */ 3099 static void 3100 bs_usable_clusters(void) 3101 { 3102 struct spdk_blob_store *bs = g_bs; 3103 struct spdk_blob *blob; 3104 uint32_t clusters; 3105 int i; 3106 3107 3108 clusters = spdk_bs_total_data_cluster_count(bs); 3109 3110 ut_bs_reload(&bs, NULL); 3111 3112 CU_ASSERT(spdk_bs_total_data_cluster_count(bs) == clusters); 3113 3114 /* Create and resize blobs to make sure that useable cluster count won't change */ 3115 for (i = 0; i < 4; i++) { 3116 g_bserrno = -1; 3117 g_blobid = SPDK_BLOBID_INVALID; 3118 blob = ut_blob_create_and_open(bs, NULL); 3119 3120 spdk_blob_resize(blob, 10, blob_op_complete, NULL); 3121 poll_threads(); 3122 CU_ASSERT(g_bserrno == 0); 3123 3124 g_bserrno = -1; 3125 spdk_blob_close(blob, blob_op_complete, NULL); 3126 poll_threads(); 3127 CU_ASSERT(g_bserrno == 0); 3128 3129 CU_ASSERT(spdk_bs_total_data_cluster_count(bs) == clusters); 3130 } 3131 3132 /* Reload the blob store to make sure that nothing changed */ 3133 ut_bs_reload(&bs, NULL); 3134 3135 CU_ASSERT(spdk_bs_total_data_cluster_count(bs) == clusters); 3136 } 3137 3138 /* 3139 * Test resizing of the metadata blob. This requires creating enough blobs 3140 * so that one cluster is not enough to fit the metadata for those blobs. 3141 * To induce this condition to happen more quickly, we reduce the cluster 3142 * size to 16KB, which means only 4 4KB blob metadata pages can fit. 3143 */ 3144 static void 3145 bs_resize_md(void) 3146 { 3147 struct spdk_blob_store *bs; 3148 const int CLUSTER_PAGE_COUNT = 4; 3149 const int NUM_BLOBS = CLUSTER_PAGE_COUNT * 4; 3150 struct spdk_bs_dev *dev; 3151 struct spdk_bs_opts opts; 3152 struct spdk_blob *blob; 3153 struct spdk_blob_opts blob_opts; 3154 uint32_t cluster_sz; 3155 spdk_blob_id blobids[NUM_BLOBS]; 3156 int i; 3157 3158 3159 dev = init_dev(); 3160 spdk_bs_opts_init(&opts, sizeof(opts)); 3161 opts.cluster_sz = CLUSTER_PAGE_COUNT * 4096; 3162 cluster_sz = opts.cluster_sz; 3163 3164 /* Initialize a new blob store */ 3165 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 3166 poll_threads(); 3167 CU_ASSERT(g_bserrno == 0); 3168 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 3169 bs = g_bs; 3170 3171 CU_ASSERT(spdk_bs_get_cluster_size(bs) == cluster_sz); 3172 3173 ut_spdk_blob_opts_init(&blob_opts); 3174 3175 for (i = 0; i < NUM_BLOBS; i++) { 3176 g_bserrno = -1; 3177 g_blobid = SPDK_BLOBID_INVALID; 3178 spdk_bs_create_blob_ext(bs, &blob_opts, blob_op_with_id_complete, NULL); 3179 poll_threads(); 3180 CU_ASSERT(g_bserrno == 0); 3181 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 3182 blobids[i] = g_blobid; 3183 } 3184 3185 ut_bs_reload(&bs, &opts); 3186 3187 CU_ASSERT(spdk_bs_get_cluster_size(bs) == cluster_sz); 3188 3189 for (i = 0; i < NUM_BLOBS; i++) { 3190 g_bserrno = -1; 3191 g_blob = NULL; 3192 spdk_bs_open_blob(bs, blobids[i], blob_op_with_handle_complete, NULL); 3193 poll_threads(); 3194 CU_ASSERT(g_bserrno == 0); 3195 CU_ASSERT(g_blob != NULL); 3196 blob = g_blob; 3197 g_bserrno = -1; 3198 spdk_blob_close(blob, blob_op_complete, NULL); 3199 poll_threads(); 3200 CU_ASSERT(g_bserrno == 0); 3201 } 3202 3203 spdk_bs_unload(bs, bs_op_complete, NULL); 3204 poll_threads(); 3205 CU_ASSERT(g_bserrno == 0); 3206 g_bs = NULL; 3207 } 3208 3209 static void 3210 bs_destroy(void) 3211 { 3212 struct spdk_blob_store *bs; 3213 struct spdk_bs_dev *dev; 3214 3215 /* Initialize a new blob store */ 3216 dev = init_dev(); 3217 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 3218 poll_threads(); 3219 CU_ASSERT(g_bserrno == 0); 3220 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 3221 bs = g_bs; 3222 3223 /* Destroy the blob store */ 3224 g_bserrno = -1; 3225 spdk_bs_destroy(bs, bs_op_complete, NULL); 3226 poll_threads(); 3227 CU_ASSERT(g_bserrno == 0); 3228 3229 /* Loading an non-existent blob store should fail. */ 3230 g_bs = NULL; 3231 dev = init_dev(); 3232 3233 g_bserrno = 0; 3234 spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL); 3235 poll_threads(); 3236 CU_ASSERT(g_bserrno != 0); 3237 } 3238 3239 /* Try to hit all of the corner cases associated with serializing 3240 * a blob to disk 3241 */ 3242 static void 3243 blob_serialize_test(void) 3244 { 3245 struct spdk_bs_dev *dev; 3246 struct spdk_bs_opts opts; 3247 struct spdk_blob_store *bs; 3248 spdk_blob_id blobid[2]; 3249 struct spdk_blob *blob[2]; 3250 uint64_t i; 3251 char *value; 3252 int rc; 3253 3254 dev = init_dev(); 3255 3256 /* Initialize a new blobstore with very small clusters */ 3257 spdk_bs_opts_init(&opts, sizeof(opts)); 3258 opts.cluster_sz = dev->blocklen * 8; 3259 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 3260 poll_threads(); 3261 CU_ASSERT(g_bserrno == 0); 3262 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 3263 bs = g_bs; 3264 3265 /* Create and open two blobs */ 3266 for (i = 0; i < 2; i++) { 3267 blob[i] = ut_blob_create_and_open(bs, NULL); 3268 blobid[i] = spdk_blob_get_id(blob[i]); 3269 3270 /* Set a fairly large xattr on both blobs to eat up 3271 * metadata space 3272 */ 3273 value = calloc(dev->blocklen - 64, sizeof(char)); 3274 SPDK_CU_ASSERT_FATAL(value != NULL); 3275 memset(value, i, dev->blocklen / 2); 3276 rc = spdk_blob_set_xattr(blob[i], "name", value, dev->blocklen - 64); 3277 CU_ASSERT(rc == 0); 3278 free(value); 3279 } 3280 3281 /* Resize the blobs, alternating 1 cluster at a time. 3282 * This thwarts run length encoding and will cause spill 3283 * over of the extents. 3284 */ 3285 for (i = 0; i < 6; i++) { 3286 spdk_blob_resize(blob[i % 2], (i / 2) + 1, blob_op_complete, NULL); 3287 poll_threads(); 3288 CU_ASSERT(g_bserrno == 0); 3289 } 3290 3291 for (i = 0; i < 2; i++) { 3292 spdk_blob_sync_md(blob[i], blob_op_complete, NULL); 3293 poll_threads(); 3294 CU_ASSERT(g_bserrno == 0); 3295 } 3296 3297 /* Close the blobs */ 3298 for (i = 0; i < 2; i++) { 3299 spdk_blob_close(blob[i], blob_op_complete, NULL); 3300 poll_threads(); 3301 CU_ASSERT(g_bserrno == 0); 3302 } 3303 3304 ut_bs_reload(&bs, &opts); 3305 3306 for (i = 0; i < 2; i++) { 3307 blob[i] = NULL; 3308 3309 spdk_bs_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL); 3310 poll_threads(); 3311 CU_ASSERT(g_bserrno == 0); 3312 CU_ASSERT(g_blob != NULL); 3313 blob[i] = g_blob; 3314 3315 CU_ASSERT(spdk_blob_get_num_clusters(blob[i]) == 3); 3316 3317 spdk_blob_close(blob[i], blob_op_complete, NULL); 3318 poll_threads(); 3319 CU_ASSERT(g_bserrno == 0); 3320 } 3321 3322 spdk_bs_unload(bs, bs_op_complete, NULL); 3323 poll_threads(); 3324 CU_ASSERT(g_bserrno == 0); 3325 g_bs = NULL; 3326 } 3327 3328 static void 3329 blob_crc(void) 3330 { 3331 struct spdk_blob_store *bs = g_bs; 3332 struct spdk_blob *blob; 3333 spdk_blob_id blobid; 3334 uint32_t page_num; 3335 int index; 3336 struct spdk_blob_md_page *page; 3337 3338 blob = ut_blob_create_and_open(bs, NULL); 3339 blobid = spdk_blob_get_id(blob); 3340 3341 spdk_blob_close(blob, blob_op_complete, NULL); 3342 poll_threads(); 3343 CU_ASSERT(g_bserrno == 0); 3344 3345 page_num = bs_blobid_to_page(blobid); 3346 index = DEV_BUFFER_BLOCKLEN * (bs->md_start + page_num); 3347 page = (struct spdk_blob_md_page *)&g_dev_buffer[index]; 3348 page->crc = 0; 3349 3350 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 3351 poll_threads(); 3352 CU_ASSERT(g_bserrno == -EINVAL); 3353 CU_ASSERT(g_blob == NULL); 3354 g_bserrno = 0; 3355 3356 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); 3357 poll_threads(); 3358 CU_ASSERT(g_bserrno == -EINVAL); 3359 } 3360 3361 static void 3362 super_block_crc(void) 3363 { 3364 struct spdk_blob_store *bs; 3365 struct spdk_bs_dev *dev; 3366 struct spdk_bs_super_block *super_block; 3367 3368 dev = init_dev(); 3369 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 3370 poll_threads(); 3371 CU_ASSERT(g_bserrno == 0); 3372 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 3373 bs = g_bs; 3374 3375 spdk_bs_unload(bs, bs_op_complete, NULL); 3376 poll_threads(); 3377 CU_ASSERT(g_bserrno == 0); 3378 g_bs = NULL; 3379 3380 super_block = (struct spdk_bs_super_block *)g_dev_buffer; 3381 super_block->crc = 0; 3382 dev = init_dev(); 3383 3384 /* Load an existing blob store */ 3385 g_bserrno = 0; 3386 spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL); 3387 poll_threads(); 3388 CU_ASSERT(g_bserrno == -EILSEQ); 3389 } 3390 3391 /* For blob dirty shutdown test case we do the following sub-test cases: 3392 * 1 Initialize new blob store and create 1 super blob with some xattrs, then we 3393 * dirty shutdown and reload the blob store and verify the xattrs. 3394 * 2 Resize the blob from 10 clusters to 20 clusters and then dirty shutdown, 3395 * reload the blob store and verify the clusters number. 3396 * 3 Create the second blob and then dirty shutdown, reload the blob store 3397 * and verify the second blob. 3398 * 4 Delete the second blob and then dirty shutdown, reload the blob store 3399 * and verify the second blob is invalid. 3400 * 5 Create the second blob again and also create the third blob, modify the 3401 * md of second blob which makes the md invalid, and then dirty shutdown, 3402 * reload the blob store verify the second blob, it should invalid and also 3403 * verify the third blob, it should correct. 3404 */ 3405 static void 3406 blob_dirty_shutdown(void) 3407 { 3408 int rc; 3409 int index; 3410 struct spdk_blob_store *bs = g_bs; 3411 spdk_blob_id blobid1, blobid2, blobid3; 3412 struct spdk_blob *blob = g_blob; 3413 uint64_t length; 3414 uint64_t free_clusters; 3415 const void *value; 3416 size_t value_len; 3417 uint32_t page_num; 3418 struct spdk_blob_md_page *page; 3419 struct spdk_blob_opts blob_opts; 3420 3421 /* Create first blob */ 3422 blobid1 = spdk_blob_get_id(blob); 3423 3424 /* Set some xattrs */ 3425 rc = spdk_blob_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1); 3426 CU_ASSERT(rc == 0); 3427 3428 length = 2345; 3429 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 3430 CU_ASSERT(rc == 0); 3431 3432 /* Put xattr that fits exactly single page. 3433 * This results in adding additional pages to MD. 3434 * First is flags and smaller xattr, second the large xattr, 3435 * third are just the extents. 3436 */ 3437 size_t xattr_length = 4072 - sizeof(struct spdk_blob_md_descriptor_xattr) - 3438 strlen("large_xattr"); 3439 char *xattr = calloc(xattr_length, sizeof(char)); 3440 SPDK_CU_ASSERT_FATAL(xattr != NULL); 3441 rc = spdk_blob_set_xattr(blob, "large_xattr", xattr, xattr_length); 3442 free(xattr); 3443 SPDK_CU_ASSERT_FATAL(rc == 0); 3444 3445 /* Resize the blob */ 3446 spdk_blob_resize(blob, 10, blob_op_complete, NULL); 3447 poll_threads(); 3448 CU_ASSERT(g_bserrno == 0); 3449 3450 /* Set the blob as the super blob */ 3451 spdk_bs_set_super(bs, blobid1, blob_op_complete, NULL); 3452 poll_threads(); 3453 CU_ASSERT(g_bserrno == 0); 3454 3455 free_clusters = spdk_bs_free_cluster_count(bs); 3456 3457 spdk_blob_close(blob, blob_op_complete, NULL); 3458 poll_threads(); 3459 CU_ASSERT(g_bserrno == 0); 3460 blob = NULL; 3461 g_blob = NULL; 3462 g_blobid = SPDK_BLOBID_INVALID; 3463 3464 ut_bs_dirty_load(&bs, NULL); 3465 3466 /* Get the super blob */ 3467 spdk_bs_get_super(bs, blob_op_with_id_complete, NULL); 3468 poll_threads(); 3469 CU_ASSERT(g_bserrno == 0); 3470 CU_ASSERT(blobid1 == g_blobid); 3471 3472 spdk_bs_open_blob(bs, blobid1, blob_op_with_handle_complete, NULL); 3473 poll_threads(); 3474 CU_ASSERT(g_bserrno == 0); 3475 CU_ASSERT(g_blob != NULL); 3476 blob = g_blob; 3477 3478 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 3479 3480 /* Get the xattrs */ 3481 value = NULL; 3482 rc = spdk_blob_get_xattr_value(blob, "length", &value, &value_len); 3483 CU_ASSERT(rc == 0); 3484 SPDK_CU_ASSERT_FATAL(value != NULL); 3485 CU_ASSERT(*(uint64_t *)value == length); 3486 CU_ASSERT(value_len == 8); 3487 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 3488 3489 /* Resize the blob */ 3490 spdk_blob_resize(blob, 20, blob_op_complete, NULL); 3491 poll_threads(); 3492 CU_ASSERT(g_bserrno == 0); 3493 3494 free_clusters = spdk_bs_free_cluster_count(bs); 3495 3496 spdk_blob_close(blob, blob_op_complete, NULL); 3497 poll_threads(); 3498 CU_ASSERT(g_bserrno == 0); 3499 blob = NULL; 3500 g_blob = NULL; 3501 g_blobid = SPDK_BLOBID_INVALID; 3502 3503 ut_bs_dirty_load(&bs, NULL); 3504 3505 spdk_bs_open_blob(bs, blobid1, blob_op_with_handle_complete, NULL); 3506 poll_threads(); 3507 CU_ASSERT(g_bserrno == 0); 3508 CU_ASSERT(g_blob != NULL); 3509 blob = g_blob; 3510 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 20); 3511 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 3512 3513 spdk_blob_close(blob, blob_op_complete, NULL); 3514 poll_threads(); 3515 CU_ASSERT(g_bserrno == 0); 3516 blob = NULL; 3517 g_blob = NULL; 3518 g_blobid = SPDK_BLOBID_INVALID; 3519 3520 /* Create second blob */ 3521 blob = ut_blob_create_and_open(bs, NULL); 3522 blobid2 = spdk_blob_get_id(blob); 3523 3524 /* Set some xattrs */ 3525 rc = spdk_blob_set_xattr(blob, "name", "log1.txt", strlen("log1.txt") + 1); 3526 CU_ASSERT(rc == 0); 3527 3528 length = 5432; 3529 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 3530 CU_ASSERT(rc == 0); 3531 3532 /* Resize the blob */ 3533 spdk_blob_resize(blob, 10, blob_op_complete, NULL); 3534 poll_threads(); 3535 CU_ASSERT(g_bserrno == 0); 3536 3537 free_clusters = spdk_bs_free_cluster_count(bs); 3538 3539 spdk_blob_close(blob, blob_op_complete, NULL); 3540 poll_threads(); 3541 CU_ASSERT(g_bserrno == 0); 3542 blob = NULL; 3543 g_blob = NULL; 3544 g_blobid = SPDK_BLOBID_INVALID; 3545 3546 ut_bs_dirty_load(&bs, NULL); 3547 3548 spdk_bs_open_blob(bs, blobid2, blob_op_with_handle_complete, NULL); 3549 poll_threads(); 3550 CU_ASSERT(g_bserrno == 0); 3551 CU_ASSERT(g_blob != NULL); 3552 blob = g_blob; 3553 3554 /* Get the xattrs */ 3555 value = NULL; 3556 rc = spdk_blob_get_xattr_value(blob, "length", &value, &value_len); 3557 CU_ASSERT(rc == 0); 3558 SPDK_CU_ASSERT_FATAL(value != NULL); 3559 CU_ASSERT(*(uint64_t *)value == length); 3560 CU_ASSERT(value_len == 8); 3561 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 3562 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 3563 3564 ut_blob_close_and_delete(bs, blob); 3565 3566 free_clusters = spdk_bs_free_cluster_count(bs); 3567 3568 ut_bs_dirty_load(&bs, NULL); 3569 3570 spdk_bs_open_blob(bs, blobid2, blob_op_with_handle_complete, NULL); 3571 poll_threads(); 3572 CU_ASSERT(g_bserrno != 0); 3573 CU_ASSERT(g_blob == NULL); 3574 3575 spdk_bs_open_blob(bs, blobid1, blob_op_with_handle_complete, NULL); 3576 poll_threads(); 3577 CU_ASSERT(g_bserrno == 0); 3578 CU_ASSERT(g_blob != NULL); 3579 blob = g_blob; 3580 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 3581 spdk_blob_close(blob, blob_op_complete, NULL); 3582 poll_threads(); 3583 CU_ASSERT(g_bserrno == 0); 3584 3585 ut_bs_reload(&bs, NULL); 3586 3587 /* Create second blob */ 3588 ut_spdk_blob_opts_init(&blob_opts); 3589 spdk_bs_create_blob_ext(bs, &blob_opts, blob_op_with_id_complete, NULL); 3590 poll_threads(); 3591 CU_ASSERT(g_bserrno == 0); 3592 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 3593 blobid2 = g_blobid; 3594 3595 /* Create third blob */ 3596 spdk_bs_create_blob_ext(bs, &blob_opts, blob_op_with_id_complete, NULL); 3597 poll_threads(); 3598 CU_ASSERT(g_bserrno == 0); 3599 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 3600 blobid3 = g_blobid; 3601 3602 spdk_bs_open_blob(bs, blobid2, blob_op_with_handle_complete, NULL); 3603 poll_threads(); 3604 CU_ASSERT(g_bserrno == 0); 3605 CU_ASSERT(g_blob != NULL); 3606 blob = g_blob; 3607 3608 /* Set some xattrs for second blob */ 3609 rc = spdk_blob_set_xattr(blob, "name", "log1.txt", strlen("log1.txt") + 1); 3610 CU_ASSERT(rc == 0); 3611 3612 length = 5432; 3613 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 3614 CU_ASSERT(rc == 0); 3615 3616 spdk_blob_close(blob, blob_op_complete, NULL); 3617 poll_threads(); 3618 CU_ASSERT(g_bserrno == 0); 3619 blob = NULL; 3620 g_blob = NULL; 3621 g_blobid = SPDK_BLOBID_INVALID; 3622 3623 spdk_bs_open_blob(bs, blobid3, blob_op_with_handle_complete, NULL); 3624 poll_threads(); 3625 CU_ASSERT(g_bserrno == 0); 3626 CU_ASSERT(g_blob != NULL); 3627 blob = g_blob; 3628 3629 /* Set some xattrs for third blob */ 3630 rc = spdk_blob_set_xattr(blob, "name", "log2.txt", strlen("log2.txt") + 1); 3631 CU_ASSERT(rc == 0); 3632 3633 length = 5432; 3634 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 3635 CU_ASSERT(rc == 0); 3636 3637 spdk_blob_close(blob, blob_op_complete, NULL); 3638 poll_threads(); 3639 CU_ASSERT(g_bserrno == 0); 3640 blob = NULL; 3641 g_blob = NULL; 3642 g_blobid = SPDK_BLOBID_INVALID; 3643 3644 /* Mark second blob as invalid */ 3645 page_num = bs_blobid_to_page(blobid2); 3646 3647 index = DEV_BUFFER_BLOCKLEN * (bs->md_start + page_num); 3648 page = (struct spdk_blob_md_page *)&g_dev_buffer[index]; 3649 page->sequence_num = 1; 3650 page->crc = blob_md_page_calc_crc(page); 3651 3652 free_clusters = spdk_bs_free_cluster_count(bs); 3653 3654 ut_bs_dirty_load(&bs, NULL); 3655 3656 spdk_bs_open_blob(bs, blobid2, blob_op_with_handle_complete, NULL); 3657 poll_threads(); 3658 CU_ASSERT(g_bserrno != 0); 3659 CU_ASSERT(g_blob == NULL); 3660 3661 spdk_bs_open_blob(bs, blobid3, blob_op_with_handle_complete, NULL); 3662 poll_threads(); 3663 CU_ASSERT(g_bserrno == 0); 3664 CU_ASSERT(g_blob != NULL); 3665 blob = g_blob; 3666 3667 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 3668 } 3669 3670 static void 3671 blob_flags(void) 3672 { 3673 struct spdk_blob_store *bs = g_bs; 3674 spdk_blob_id blobid_invalid, blobid_data_ro, blobid_md_ro; 3675 struct spdk_blob *blob_invalid, *blob_data_ro, *blob_md_ro; 3676 struct spdk_blob_opts blob_opts; 3677 int rc; 3678 3679 /* Create three blobs - one each for testing invalid, data_ro and md_ro flags. */ 3680 blob_invalid = ut_blob_create_and_open(bs, NULL); 3681 blobid_invalid = spdk_blob_get_id(blob_invalid); 3682 3683 blob_data_ro = ut_blob_create_and_open(bs, NULL); 3684 blobid_data_ro = spdk_blob_get_id(blob_data_ro); 3685 3686 ut_spdk_blob_opts_init(&blob_opts); 3687 blob_opts.clear_method = BLOB_CLEAR_WITH_WRITE_ZEROES; 3688 blob_md_ro = ut_blob_create_and_open(bs, &blob_opts); 3689 blobid_md_ro = spdk_blob_get_id(blob_md_ro); 3690 CU_ASSERT((blob_md_ro->md_ro_flags & SPDK_BLOB_MD_RO_FLAGS_MASK) == BLOB_CLEAR_WITH_WRITE_ZEROES); 3691 3692 /* Change the size of blob_data_ro to check if flags are serialized 3693 * when blob has non zero number of extents */ 3694 spdk_blob_resize(blob_data_ro, 10, blob_op_complete, NULL); 3695 poll_threads(); 3696 CU_ASSERT(g_bserrno == 0); 3697 3698 /* Set the xattr to check if flags are serialized 3699 * when blob has non zero number of xattrs */ 3700 rc = spdk_blob_set_xattr(blob_md_ro, "name", "log.txt", strlen("log.txt") + 1); 3701 CU_ASSERT(rc == 0); 3702 3703 blob_invalid->invalid_flags = (1ULL << 63); 3704 blob_invalid->state = SPDK_BLOB_STATE_DIRTY; 3705 blob_data_ro->data_ro_flags = (1ULL << 62); 3706 blob_data_ro->state = SPDK_BLOB_STATE_DIRTY; 3707 blob_md_ro->md_ro_flags = (1ULL << 61); 3708 blob_md_ro->state = SPDK_BLOB_STATE_DIRTY; 3709 3710 g_bserrno = -1; 3711 spdk_blob_sync_md(blob_invalid, blob_op_complete, NULL); 3712 poll_threads(); 3713 CU_ASSERT(g_bserrno == 0); 3714 g_bserrno = -1; 3715 spdk_blob_sync_md(blob_data_ro, blob_op_complete, NULL); 3716 poll_threads(); 3717 CU_ASSERT(g_bserrno == 0); 3718 g_bserrno = -1; 3719 spdk_blob_sync_md(blob_md_ro, blob_op_complete, NULL); 3720 poll_threads(); 3721 CU_ASSERT(g_bserrno == 0); 3722 3723 g_bserrno = -1; 3724 spdk_blob_close(blob_invalid, blob_op_complete, NULL); 3725 poll_threads(); 3726 CU_ASSERT(g_bserrno == 0); 3727 blob_invalid = NULL; 3728 g_bserrno = -1; 3729 spdk_blob_close(blob_data_ro, blob_op_complete, NULL); 3730 poll_threads(); 3731 CU_ASSERT(g_bserrno == 0); 3732 blob_data_ro = NULL; 3733 g_bserrno = -1; 3734 spdk_blob_close(blob_md_ro, blob_op_complete, NULL); 3735 poll_threads(); 3736 CU_ASSERT(g_bserrno == 0); 3737 blob_md_ro = NULL; 3738 3739 g_blob = NULL; 3740 g_blobid = SPDK_BLOBID_INVALID; 3741 3742 ut_bs_reload(&bs, NULL); 3743 3744 g_blob = NULL; 3745 g_bserrno = 0; 3746 spdk_bs_open_blob(bs, blobid_invalid, blob_op_with_handle_complete, NULL); 3747 poll_threads(); 3748 CU_ASSERT(g_bserrno != 0); 3749 CU_ASSERT(g_blob == NULL); 3750 3751 g_blob = NULL; 3752 g_bserrno = -1; 3753 spdk_bs_open_blob(bs, blobid_data_ro, blob_op_with_handle_complete, NULL); 3754 poll_threads(); 3755 CU_ASSERT(g_bserrno == 0); 3756 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 3757 blob_data_ro = g_blob; 3758 /* If an unknown data_ro flag was found, the blob should be marked both data and md read-only. */ 3759 CU_ASSERT(blob_data_ro->data_ro == true); 3760 CU_ASSERT(blob_data_ro->md_ro == true); 3761 CU_ASSERT(spdk_blob_get_num_clusters(blob_data_ro) == 10); 3762 3763 g_blob = NULL; 3764 g_bserrno = -1; 3765 spdk_bs_open_blob(bs, blobid_md_ro, blob_op_with_handle_complete, NULL); 3766 poll_threads(); 3767 CU_ASSERT(g_bserrno == 0); 3768 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 3769 blob_md_ro = g_blob; 3770 CU_ASSERT(blob_md_ro->data_ro == false); 3771 CU_ASSERT(blob_md_ro->md_ro == true); 3772 3773 g_bserrno = -1; 3774 spdk_blob_sync_md(blob_md_ro, blob_op_complete, NULL); 3775 poll_threads(); 3776 CU_ASSERT(g_bserrno == 0); 3777 3778 ut_blob_close_and_delete(bs, blob_data_ro); 3779 ut_blob_close_and_delete(bs, blob_md_ro); 3780 } 3781 3782 static void 3783 bs_version(void) 3784 { 3785 struct spdk_bs_super_block *super; 3786 struct spdk_blob_store *bs = g_bs; 3787 struct spdk_bs_dev *dev; 3788 struct spdk_blob *blob; 3789 struct spdk_blob_opts blob_opts; 3790 spdk_blob_id blobid; 3791 3792 /* Unload the blob store */ 3793 spdk_bs_unload(bs, bs_op_complete, NULL); 3794 poll_threads(); 3795 CU_ASSERT(g_bserrno == 0); 3796 g_bs = NULL; 3797 3798 /* 3799 * Change the bs version on disk. This will allow us to 3800 * test that the version does not get modified automatically 3801 * when loading and unloading the blobstore. 3802 */ 3803 super = (struct spdk_bs_super_block *)&g_dev_buffer[0]; 3804 CU_ASSERT(super->version == SPDK_BS_VERSION); 3805 CU_ASSERT(super->clean == 1); 3806 super->version = 2; 3807 /* 3808 * Version 2 metadata does not have a used blobid mask, so clear 3809 * those fields in the super block and zero the corresponding 3810 * region on "disk". We will use this to ensure blob IDs are 3811 * correctly reconstructed. 3812 */ 3813 memset(&g_dev_buffer[super->used_blobid_mask_start * SPDK_BS_PAGE_SIZE], 0, 3814 super->used_blobid_mask_len * SPDK_BS_PAGE_SIZE); 3815 super->used_blobid_mask_start = 0; 3816 super->used_blobid_mask_len = 0; 3817 super->crc = blob_md_page_calc_crc(super); 3818 3819 /* Load an existing blob store */ 3820 dev = init_dev(); 3821 spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL); 3822 poll_threads(); 3823 CU_ASSERT(g_bserrno == 0); 3824 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 3825 CU_ASSERT(super->clean == 1); 3826 bs = g_bs; 3827 3828 /* 3829 * Create a blob - just to make sure that when we unload it 3830 * results in writing the super block (since metadata pages 3831 * were allocated. 3832 */ 3833 ut_spdk_blob_opts_init(&blob_opts); 3834 spdk_bs_create_blob_ext(bs, &blob_opts, blob_op_with_id_complete, NULL); 3835 poll_threads(); 3836 CU_ASSERT(g_bserrno == 0); 3837 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 3838 blobid = g_blobid; 3839 3840 /* Unload the blob store */ 3841 spdk_bs_unload(bs, bs_op_complete, NULL); 3842 poll_threads(); 3843 CU_ASSERT(g_bserrno == 0); 3844 g_bs = NULL; 3845 CU_ASSERT(super->version == 2); 3846 CU_ASSERT(super->used_blobid_mask_start == 0); 3847 CU_ASSERT(super->used_blobid_mask_len == 0); 3848 3849 dev = init_dev(); 3850 spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL); 3851 poll_threads(); 3852 CU_ASSERT(g_bserrno == 0); 3853 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 3854 bs = g_bs; 3855 3856 g_blob = NULL; 3857 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 3858 poll_threads(); 3859 CU_ASSERT(g_bserrno == 0); 3860 CU_ASSERT(g_blob != NULL); 3861 blob = g_blob; 3862 3863 ut_blob_close_and_delete(bs, blob); 3864 3865 CU_ASSERT(super->version == 2); 3866 CU_ASSERT(super->used_blobid_mask_start == 0); 3867 CU_ASSERT(super->used_blobid_mask_len == 0); 3868 } 3869 3870 static void 3871 blob_set_xattrs_test(void) 3872 { 3873 struct spdk_blob_store *bs = g_bs; 3874 struct spdk_blob *blob; 3875 struct spdk_blob_opts opts; 3876 const void *value; 3877 size_t value_len; 3878 char *xattr; 3879 size_t xattr_length; 3880 int rc; 3881 3882 /* Create blob with extra attributes */ 3883 ut_spdk_blob_opts_init(&opts); 3884 3885 opts.xattrs.names = g_xattr_names; 3886 opts.xattrs.get_value = _get_xattr_value; 3887 opts.xattrs.count = 3; 3888 opts.xattrs.ctx = &g_ctx; 3889 3890 blob = ut_blob_create_and_open(bs, &opts); 3891 3892 /* Get the xattrs */ 3893 value = NULL; 3894 3895 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[0], &value, &value_len); 3896 CU_ASSERT(rc == 0); 3897 SPDK_CU_ASSERT_FATAL(value != NULL); 3898 CU_ASSERT(value_len == strlen(g_xattr_values[0])); 3899 CU_ASSERT_NSTRING_EQUAL_FATAL(value, g_xattr_values[0], value_len); 3900 3901 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[1], &value, &value_len); 3902 CU_ASSERT(rc == 0); 3903 SPDK_CU_ASSERT_FATAL(value != NULL); 3904 CU_ASSERT(value_len == strlen(g_xattr_values[1])); 3905 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[1], value_len); 3906 3907 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[2], &value, &value_len); 3908 CU_ASSERT(rc == 0); 3909 SPDK_CU_ASSERT_FATAL(value != NULL); 3910 CU_ASSERT(value_len == strlen(g_xattr_values[2])); 3911 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[2], value_len); 3912 3913 /* Try to get non existing attribute */ 3914 3915 rc = spdk_blob_get_xattr_value(blob, "foobar", &value, &value_len); 3916 CU_ASSERT(rc == -ENOENT); 3917 3918 /* Try xattr exceeding maximum length of descriptor in single page */ 3919 xattr_length = SPDK_BS_MAX_DESC_SIZE - sizeof(struct spdk_blob_md_descriptor_xattr) - 3920 strlen("large_xattr") + 1; 3921 xattr = calloc(xattr_length, sizeof(char)); 3922 SPDK_CU_ASSERT_FATAL(xattr != NULL); 3923 rc = spdk_blob_set_xattr(blob, "large_xattr", xattr, xattr_length); 3924 free(xattr); 3925 SPDK_CU_ASSERT_FATAL(rc == -ENOMEM); 3926 3927 spdk_blob_close(blob, blob_op_complete, NULL); 3928 poll_threads(); 3929 CU_ASSERT(g_bserrno == 0); 3930 blob = NULL; 3931 g_blob = NULL; 3932 g_blobid = SPDK_BLOBID_INVALID; 3933 3934 /* NULL callback */ 3935 ut_spdk_blob_opts_init(&opts); 3936 opts.xattrs.names = g_xattr_names; 3937 opts.xattrs.get_value = NULL; 3938 opts.xattrs.count = 1; 3939 opts.xattrs.ctx = &g_ctx; 3940 3941 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 3942 poll_threads(); 3943 CU_ASSERT(g_bserrno == -EINVAL); 3944 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 3945 3946 /* NULL values */ 3947 ut_spdk_blob_opts_init(&opts); 3948 opts.xattrs.names = g_xattr_names; 3949 opts.xattrs.get_value = _get_xattr_value_null; 3950 opts.xattrs.count = 1; 3951 opts.xattrs.ctx = NULL; 3952 3953 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 3954 poll_threads(); 3955 CU_ASSERT(g_bserrno == -EINVAL); 3956 } 3957 3958 static void 3959 blob_thin_prov_alloc(void) 3960 { 3961 struct spdk_blob_store *bs = g_bs; 3962 struct spdk_blob *blob; 3963 struct spdk_blob_opts opts; 3964 spdk_blob_id blobid; 3965 uint64_t free_clusters; 3966 3967 free_clusters = spdk_bs_free_cluster_count(bs); 3968 3969 /* Set blob as thin provisioned */ 3970 ut_spdk_blob_opts_init(&opts); 3971 opts.thin_provision = true; 3972 3973 blob = ut_blob_create_and_open(bs, &opts); 3974 blobid = spdk_blob_get_id(blob); 3975 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 3976 3977 CU_ASSERT(blob->active.num_clusters == 0); 3978 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 0); 3979 3980 /* The blob started at 0 clusters. Resize it to be 5, but still unallocated. */ 3981 spdk_blob_resize(blob, 5, blob_op_complete, NULL); 3982 poll_threads(); 3983 CU_ASSERT(g_bserrno == 0); 3984 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 3985 CU_ASSERT(blob->active.num_clusters == 5); 3986 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5); 3987 3988 /* Grow it to 1TB - still unallocated */ 3989 spdk_blob_resize(blob, 262144, blob_op_complete, NULL); 3990 poll_threads(); 3991 CU_ASSERT(g_bserrno == 0); 3992 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 3993 CU_ASSERT(blob->active.num_clusters == 262144); 3994 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 262144); 3995 3996 spdk_blob_sync_md(blob, blob_op_complete, NULL); 3997 poll_threads(); 3998 CU_ASSERT(g_bserrno == 0); 3999 /* Sync must not change anything */ 4000 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4001 CU_ASSERT(blob->active.num_clusters == 262144); 4002 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 262144); 4003 /* Since clusters are not allocated, 4004 * number of metadata pages is expected to be minimal. 4005 */ 4006 CU_ASSERT(blob->active.num_pages == 1); 4007 4008 /* Shrink the blob to 3 clusters - still unallocated */ 4009 spdk_blob_resize(blob, 3, blob_op_complete, NULL); 4010 poll_threads(); 4011 CU_ASSERT(g_bserrno == 0); 4012 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4013 CU_ASSERT(blob->active.num_clusters == 3); 4014 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 3); 4015 4016 spdk_blob_sync_md(blob, blob_op_complete, NULL); 4017 poll_threads(); 4018 CU_ASSERT(g_bserrno == 0); 4019 /* Sync must not change anything */ 4020 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4021 CU_ASSERT(blob->active.num_clusters == 3); 4022 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 3); 4023 4024 spdk_blob_close(blob, blob_op_complete, NULL); 4025 poll_threads(); 4026 CU_ASSERT(g_bserrno == 0); 4027 4028 ut_bs_reload(&bs, NULL); 4029 4030 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 4031 poll_threads(); 4032 CU_ASSERT(g_bserrno == 0); 4033 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 4034 blob = g_blob; 4035 4036 /* Check that clusters allocation and size is still the same */ 4037 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4038 CU_ASSERT(blob->active.num_clusters == 3); 4039 4040 ut_blob_close_and_delete(bs, blob); 4041 } 4042 4043 static void 4044 blob_insert_cluster_msg_test(void) 4045 { 4046 struct spdk_blob_store *bs = g_bs; 4047 struct spdk_blob *blob; 4048 struct spdk_blob_opts opts; 4049 struct spdk_blob_md_page page = {}; 4050 spdk_blob_id blobid; 4051 uint64_t free_clusters; 4052 uint64_t new_cluster = 0; 4053 uint32_t cluster_num = 3; 4054 uint32_t extent_page = 0; 4055 4056 free_clusters = spdk_bs_free_cluster_count(bs); 4057 4058 /* Set blob as thin provisioned */ 4059 ut_spdk_blob_opts_init(&opts); 4060 opts.thin_provision = true; 4061 opts.num_clusters = 4; 4062 4063 blob = ut_blob_create_and_open(bs, &opts); 4064 blobid = spdk_blob_get_id(blob); 4065 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4066 4067 CU_ASSERT(blob->active.num_clusters == 4); 4068 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 4); 4069 CU_ASSERT(blob->active.clusters[cluster_num] == 0); 4070 4071 /* Specify cluster_num to allocate and new_cluster will be returned to insert on md_thread. 4072 * This is to simulate behaviour when cluster is allocated after blob creation. 4073 * Such as _spdk_bs_allocate_and_copy_cluster(). */ 4074 spdk_spin_lock(&bs->used_lock); 4075 bs_allocate_cluster(blob, cluster_num, &new_cluster, &extent_page, false); 4076 CU_ASSERT(blob->active.clusters[cluster_num] == 0); 4077 spdk_spin_unlock(&bs->used_lock); 4078 4079 blob_insert_cluster_on_md_thread(blob, cluster_num, new_cluster, extent_page, &page, 4080 blob_op_complete, NULL); 4081 poll_threads(); 4082 4083 CU_ASSERT(blob->active.clusters[cluster_num] != 0); 4084 4085 spdk_blob_close(blob, blob_op_complete, NULL); 4086 poll_threads(); 4087 CU_ASSERT(g_bserrno == 0); 4088 4089 ut_bs_reload(&bs, NULL); 4090 4091 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 4092 poll_threads(); 4093 CU_ASSERT(g_bserrno == 0); 4094 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 4095 blob = g_blob; 4096 4097 CU_ASSERT(blob->active.clusters[cluster_num] != 0); 4098 4099 ut_blob_close_and_delete(bs, blob); 4100 } 4101 4102 static void 4103 blob_thin_prov_rw(void) 4104 { 4105 static const uint8_t zero[10 * 4096] = { 0 }; 4106 struct spdk_blob_store *bs = g_bs; 4107 struct spdk_blob *blob, *blob_id0; 4108 struct spdk_io_channel *channel, *channel_thread1; 4109 struct spdk_blob_opts opts; 4110 uint64_t free_clusters; 4111 uint64_t page_size; 4112 uint8_t payload_read[10 * 4096]; 4113 uint8_t payload_write[10 * 4096]; 4114 uint64_t write_bytes; 4115 uint64_t read_bytes; 4116 4117 free_clusters = spdk_bs_free_cluster_count(bs); 4118 page_size = spdk_bs_get_page_size(bs); 4119 4120 channel = spdk_bs_alloc_io_channel(bs); 4121 CU_ASSERT(channel != NULL); 4122 4123 ut_spdk_blob_opts_init(&opts); 4124 opts.thin_provision = true; 4125 4126 /* Create and delete blob at md page 0, so that next md page allocation 4127 * for extent will use that. */ 4128 blob_id0 = ut_blob_create_and_open(bs, &opts); 4129 blob = ut_blob_create_and_open(bs, &opts); 4130 ut_blob_close_and_delete(bs, blob_id0); 4131 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4132 4133 CU_ASSERT(blob->active.num_clusters == 0); 4134 4135 /* The blob started at 0 clusters. Resize it to be 5, but still unallocated. */ 4136 spdk_blob_resize(blob, 5, blob_op_complete, NULL); 4137 poll_threads(); 4138 CU_ASSERT(g_bserrno == 0); 4139 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4140 CU_ASSERT(blob->active.num_clusters == 5); 4141 4142 spdk_blob_sync_md(blob, blob_op_complete, NULL); 4143 poll_threads(); 4144 CU_ASSERT(g_bserrno == 0); 4145 /* Sync must not change anything */ 4146 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4147 CU_ASSERT(blob->active.num_clusters == 5); 4148 4149 /* Payload should be all zeros from unallocated clusters */ 4150 memset(payload_read, 0xFF, sizeof(payload_read)); 4151 spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL); 4152 poll_threads(); 4153 CU_ASSERT(g_bserrno == 0); 4154 CU_ASSERT(memcmp(zero, payload_read, 10 * 4096) == 0); 4155 4156 write_bytes = g_dev_write_bytes; 4157 read_bytes = g_dev_read_bytes; 4158 4159 /* Perform write on thread 1. That will allocate cluster on thread 0 via send_msg */ 4160 set_thread(1); 4161 channel_thread1 = spdk_bs_alloc_io_channel(bs); 4162 CU_ASSERT(channel_thread1 != NULL); 4163 memset(payload_write, 0xE5, sizeof(payload_write)); 4164 spdk_blob_io_write(blob, channel_thread1, payload_write, 4, 10, blob_op_complete, NULL); 4165 CU_ASSERT(free_clusters - 1 == spdk_bs_free_cluster_count(bs)); 4166 /* Perform write on thread 0. That will try to allocate cluster, 4167 * but fail due to another thread issuing the cluster allocation first. */ 4168 set_thread(0); 4169 memset(payload_write, 0xE5, sizeof(payload_write)); 4170 spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL); 4171 CU_ASSERT(free_clusters - 2 == spdk_bs_free_cluster_count(bs)); 4172 poll_threads(); 4173 CU_ASSERT(g_bserrno == 0); 4174 CU_ASSERT(free_clusters - 1 == spdk_bs_free_cluster_count(bs)); 4175 /* For thin-provisioned blob we need to write 20 pages plus one page metadata and 4176 * read 0 bytes */ 4177 if (g_use_extent_table) { 4178 /* Add one more page for EXTENT_PAGE write */ 4179 CU_ASSERT(g_dev_write_bytes - write_bytes == page_size * 22); 4180 } else { 4181 CU_ASSERT(g_dev_write_bytes - write_bytes == page_size * 21); 4182 } 4183 CU_ASSERT(g_dev_read_bytes - read_bytes == 0); 4184 4185 spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL); 4186 poll_threads(); 4187 CU_ASSERT(g_bserrno == 0); 4188 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0); 4189 4190 ut_blob_close_and_delete(bs, blob); 4191 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4192 4193 set_thread(1); 4194 spdk_bs_free_io_channel(channel_thread1); 4195 set_thread(0); 4196 spdk_bs_free_io_channel(channel); 4197 poll_threads(); 4198 g_blob = NULL; 4199 g_blobid = 0; 4200 } 4201 4202 static void 4203 blob_thin_prov_write_count_io(void) 4204 { 4205 struct spdk_blob_store *bs; 4206 struct spdk_blob *blob; 4207 struct spdk_io_channel *ch; 4208 struct spdk_bs_dev *dev; 4209 struct spdk_bs_opts bs_opts; 4210 struct spdk_blob_opts opts; 4211 uint64_t free_clusters; 4212 uint64_t page_size; 4213 uint8_t payload_write[4096]; 4214 uint64_t write_bytes; 4215 uint64_t read_bytes; 4216 const uint32_t CLUSTER_SZ = 16384; 4217 uint32_t pages_per_cluster; 4218 uint32_t pages_per_extent_page; 4219 uint32_t i; 4220 4221 /* Use a very small cluster size for this test. This ensures we need multiple 4222 * extent pages to hold all of the clusters even for relatively small blobs like 4223 * we are restricted to for the unit tests (i.e. we don't want to allocate multi-GB 4224 * buffers). 4225 */ 4226 dev = init_dev(); 4227 spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); 4228 bs_opts.cluster_sz = CLUSTER_SZ; 4229 4230 spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL); 4231 poll_threads(); 4232 CU_ASSERT(g_bserrno == 0); 4233 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 4234 bs = g_bs; 4235 4236 free_clusters = spdk_bs_free_cluster_count(bs); 4237 page_size = spdk_bs_get_page_size(bs); 4238 pages_per_cluster = CLUSTER_SZ / page_size; 4239 pages_per_extent_page = SPDK_EXTENTS_PER_EP * pages_per_cluster; 4240 4241 ch = spdk_bs_alloc_io_channel(bs); 4242 SPDK_CU_ASSERT_FATAL(ch != NULL); 4243 4244 ut_spdk_blob_opts_init(&opts); 4245 opts.thin_provision = true; 4246 4247 blob = ut_blob_create_and_open(bs, &opts); 4248 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4249 4250 /* Resize the blob so that it will require 8 extent pages to hold all of 4251 * the clusters. 4252 */ 4253 g_bserrno = -1; 4254 spdk_blob_resize(blob, SPDK_EXTENTS_PER_EP * 8, blob_op_complete, NULL); 4255 poll_threads(); 4256 CU_ASSERT(g_bserrno == 0); 4257 4258 g_bserrno = -1; 4259 spdk_blob_sync_md(blob, blob_op_complete, NULL); 4260 poll_threads(); 4261 CU_ASSERT(g_bserrno == 0); 4262 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4263 CU_ASSERT(blob->active.num_clusters == SPDK_EXTENTS_PER_EP * 8); 4264 4265 memset(payload_write, 0, sizeof(payload_write)); 4266 for (i = 0; i < 8; i++) { 4267 write_bytes = g_dev_write_bytes; 4268 read_bytes = g_dev_read_bytes; 4269 4270 g_bserrno = -1; 4271 spdk_blob_io_write(blob, ch, payload_write, pages_per_extent_page * i, 1, blob_op_complete, NULL); 4272 poll_threads(); 4273 CU_ASSERT(g_bserrno == 0); 4274 CU_ASSERT(free_clusters - (2 * i + 1) == spdk_bs_free_cluster_count(bs)); 4275 4276 CU_ASSERT(g_dev_read_bytes == read_bytes); 4277 if (!g_use_extent_table) { 4278 /* For legacy metadata, we should have written two pages - one for the 4279 * write I/O itself, another for the blob's primary metadata. 4280 */ 4281 CU_ASSERT((g_dev_write_bytes - write_bytes) / page_size == 2); 4282 } else { 4283 /* For extent table metadata, we should have written three pages - one 4284 * for the write I/O, one for the extent page, one for the blob's primary 4285 * metadata. 4286 */ 4287 CU_ASSERT((g_dev_write_bytes - write_bytes) / page_size == 3); 4288 } 4289 4290 /* The write should have synced the metadata already. Do another sync here 4291 * just to confirm. 4292 */ 4293 write_bytes = g_dev_write_bytes; 4294 read_bytes = g_dev_read_bytes; 4295 4296 g_bserrno = -1; 4297 spdk_blob_sync_md(blob, blob_op_complete, NULL); 4298 poll_threads(); 4299 CU_ASSERT(g_bserrno == 0); 4300 CU_ASSERT(free_clusters - (2 * i + 1) == spdk_bs_free_cluster_count(bs)); 4301 4302 CU_ASSERT(g_dev_read_bytes == read_bytes); 4303 CU_ASSERT(g_dev_write_bytes == write_bytes); 4304 4305 /* Now write to another unallocated cluster that is part of the same extent page. */ 4306 g_bserrno = -1; 4307 spdk_blob_io_write(blob, ch, payload_write, pages_per_extent_page * i + pages_per_cluster, 4308 1, blob_op_complete, NULL); 4309 poll_threads(); 4310 CU_ASSERT(g_bserrno == 0); 4311 CU_ASSERT(free_clusters - (2 * i + 2) == spdk_bs_free_cluster_count(bs)); 4312 4313 CU_ASSERT(g_dev_read_bytes == read_bytes); 4314 /* 4315 * For legacy metadata, we should have written the I/O and the primary metadata page. 4316 * For extent table metadata, we should have written the I/O and the extent metadata page. 4317 */ 4318 CU_ASSERT((g_dev_write_bytes - write_bytes) / page_size == 2); 4319 } 4320 4321 ut_blob_close_and_delete(bs, blob); 4322 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4323 4324 spdk_bs_free_io_channel(ch); 4325 poll_threads(); 4326 g_blob = NULL; 4327 g_blobid = 0; 4328 4329 spdk_bs_unload(bs, bs_op_complete, NULL); 4330 poll_threads(); 4331 CU_ASSERT(g_bserrno == 0); 4332 g_bs = NULL; 4333 } 4334 4335 static void 4336 blob_thin_prov_rle(void) 4337 { 4338 static const uint8_t zero[10 * 4096] = { 0 }; 4339 struct spdk_blob_store *bs = g_bs; 4340 struct spdk_blob *blob; 4341 struct spdk_io_channel *channel; 4342 struct spdk_blob_opts opts; 4343 spdk_blob_id blobid; 4344 uint64_t free_clusters; 4345 uint64_t page_size; 4346 uint8_t payload_read[10 * 4096]; 4347 uint8_t payload_write[10 * 4096]; 4348 uint64_t write_bytes; 4349 uint64_t read_bytes; 4350 uint64_t io_unit; 4351 4352 free_clusters = spdk_bs_free_cluster_count(bs); 4353 page_size = spdk_bs_get_page_size(bs); 4354 4355 ut_spdk_blob_opts_init(&opts); 4356 opts.thin_provision = true; 4357 opts.num_clusters = 5; 4358 4359 blob = ut_blob_create_and_open(bs, &opts); 4360 blobid = spdk_blob_get_id(blob); 4361 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4362 4363 channel = spdk_bs_alloc_io_channel(bs); 4364 CU_ASSERT(channel != NULL); 4365 4366 /* Target specifically second cluster in a blob as first allocation */ 4367 io_unit = bs_cluster_to_page(bs, 1) * bs_io_unit_per_page(bs); 4368 4369 /* Payload should be all zeros from unallocated clusters */ 4370 memset(payload_read, 0xFF, sizeof(payload_read)); 4371 spdk_blob_io_read(blob, channel, payload_read, io_unit, 10, blob_op_complete, NULL); 4372 poll_threads(); 4373 CU_ASSERT(g_bserrno == 0); 4374 CU_ASSERT(memcmp(zero, payload_read, 10 * 4096) == 0); 4375 4376 write_bytes = g_dev_write_bytes; 4377 read_bytes = g_dev_read_bytes; 4378 4379 /* Issue write to second cluster in a blob */ 4380 memset(payload_write, 0xE5, sizeof(payload_write)); 4381 spdk_blob_io_write(blob, channel, payload_write, io_unit, 10, blob_op_complete, NULL); 4382 poll_threads(); 4383 CU_ASSERT(g_bserrno == 0); 4384 CU_ASSERT(free_clusters - 1 == spdk_bs_free_cluster_count(bs)); 4385 /* For thin-provisioned blob we need to write 10 pages plus one page metadata and 4386 * read 0 bytes */ 4387 if (g_use_extent_table) { 4388 /* Add one more page for EXTENT_PAGE write */ 4389 CU_ASSERT(g_dev_write_bytes - write_bytes == page_size * 12); 4390 } else { 4391 CU_ASSERT(g_dev_write_bytes - write_bytes == page_size * 11); 4392 } 4393 CU_ASSERT(g_dev_read_bytes - read_bytes == 0); 4394 4395 spdk_blob_io_read(blob, channel, payload_read, io_unit, 10, blob_op_complete, NULL); 4396 poll_threads(); 4397 CU_ASSERT(g_bserrno == 0); 4398 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0); 4399 4400 spdk_bs_free_io_channel(channel); 4401 poll_threads(); 4402 4403 spdk_blob_close(blob, blob_op_complete, NULL); 4404 poll_threads(); 4405 CU_ASSERT(g_bserrno == 0); 4406 4407 ut_bs_reload(&bs, NULL); 4408 4409 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 4410 poll_threads(); 4411 CU_ASSERT(g_bserrno == 0); 4412 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 4413 blob = g_blob; 4414 4415 channel = spdk_bs_alloc_io_channel(bs); 4416 CU_ASSERT(channel != NULL); 4417 4418 /* Read second cluster after blob reload to confirm data written */ 4419 spdk_blob_io_read(blob, channel, payload_read, io_unit, 10, blob_op_complete, NULL); 4420 poll_threads(); 4421 CU_ASSERT(g_bserrno == 0); 4422 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0); 4423 4424 spdk_bs_free_io_channel(channel); 4425 poll_threads(); 4426 4427 ut_blob_close_and_delete(bs, blob); 4428 } 4429 4430 static void 4431 blob_thin_prov_rw_iov(void) 4432 { 4433 static const uint8_t zero[10 * 4096] = { 0 }; 4434 struct spdk_blob_store *bs = g_bs; 4435 struct spdk_blob *blob; 4436 struct spdk_io_channel *channel; 4437 struct spdk_blob_opts opts; 4438 uint64_t free_clusters; 4439 uint8_t payload_read[10 * 4096]; 4440 uint8_t payload_write[10 * 4096]; 4441 struct iovec iov_read[3]; 4442 struct iovec iov_write[3]; 4443 4444 free_clusters = spdk_bs_free_cluster_count(bs); 4445 4446 channel = spdk_bs_alloc_io_channel(bs); 4447 CU_ASSERT(channel != NULL); 4448 4449 ut_spdk_blob_opts_init(&opts); 4450 opts.thin_provision = true; 4451 4452 blob = ut_blob_create_and_open(bs, &opts); 4453 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4454 4455 CU_ASSERT(blob->active.num_clusters == 0); 4456 4457 /* The blob started at 0 clusters. Resize it to be 5, but still unallocated. */ 4458 spdk_blob_resize(blob, 5, blob_op_complete, NULL); 4459 poll_threads(); 4460 CU_ASSERT(g_bserrno == 0); 4461 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4462 CU_ASSERT(blob->active.num_clusters == 5); 4463 4464 spdk_blob_sync_md(blob, blob_op_complete, NULL); 4465 poll_threads(); 4466 CU_ASSERT(g_bserrno == 0); 4467 /* Sync must not change anything */ 4468 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4469 CU_ASSERT(blob->active.num_clusters == 5); 4470 4471 /* Payload should be all zeros from unallocated clusters */ 4472 memset(payload_read, 0xAA, sizeof(payload_read)); 4473 iov_read[0].iov_base = payload_read; 4474 iov_read[0].iov_len = 3 * 4096; 4475 iov_read[1].iov_base = payload_read + 3 * 4096; 4476 iov_read[1].iov_len = 4 * 4096; 4477 iov_read[2].iov_base = payload_read + 7 * 4096; 4478 iov_read[2].iov_len = 3 * 4096; 4479 spdk_blob_io_readv(blob, channel, iov_read, 3, 250, 10, blob_op_complete, NULL); 4480 poll_threads(); 4481 CU_ASSERT(g_bserrno == 0); 4482 CU_ASSERT(memcmp(zero, payload_read, 10 * 4096) == 0); 4483 4484 memset(payload_write, 0xE5, sizeof(payload_write)); 4485 iov_write[0].iov_base = payload_write; 4486 iov_write[0].iov_len = 1 * 4096; 4487 iov_write[1].iov_base = payload_write + 1 * 4096; 4488 iov_write[1].iov_len = 5 * 4096; 4489 iov_write[2].iov_base = payload_write + 6 * 4096; 4490 iov_write[2].iov_len = 4 * 4096; 4491 4492 spdk_blob_io_writev(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL); 4493 poll_threads(); 4494 CU_ASSERT(g_bserrno == 0); 4495 4496 memset(payload_read, 0xAA, sizeof(payload_read)); 4497 iov_read[0].iov_base = payload_read; 4498 iov_read[0].iov_len = 3 * 4096; 4499 iov_read[1].iov_base = payload_read + 3 * 4096; 4500 iov_read[1].iov_len = 4 * 4096; 4501 iov_read[2].iov_base = payload_read + 7 * 4096; 4502 iov_read[2].iov_len = 3 * 4096; 4503 spdk_blob_io_readv(blob, channel, iov_read, 3, 250, 10, blob_op_complete, NULL); 4504 poll_threads(); 4505 CU_ASSERT(g_bserrno == 0); 4506 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0); 4507 4508 spdk_bs_free_io_channel(channel); 4509 poll_threads(); 4510 4511 ut_blob_close_and_delete(bs, blob); 4512 } 4513 4514 struct iter_ctx { 4515 int current_iter; 4516 spdk_blob_id blobid[4]; 4517 }; 4518 4519 static void 4520 test_iter(void *arg, struct spdk_blob *blob, int bserrno) 4521 { 4522 struct iter_ctx *iter_ctx = arg; 4523 spdk_blob_id blobid; 4524 4525 CU_ASSERT(bserrno == 0); 4526 blobid = spdk_blob_get_id(blob); 4527 CU_ASSERT(blobid == iter_ctx->blobid[iter_ctx->current_iter++]); 4528 } 4529 4530 static void 4531 bs_load_iter_test(void) 4532 { 4533 struct spdk_blob_store *bs; 4534 struct spdk_bs_dev *dev; 4535 struct iter_ctx iter_ctx = { 0 }; 4536 struct spdk_blob *blob; 4537 int i, rc; 4538 struct spdk_bs_opts opts; 4539 4540 dev = init_dev(); 4541 spdk_bs_opts_init(&opts, sizeof(opts)); 4542 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 4543 4544 /* Initialize a new blob store */ 4545 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 4546 poll_threads(); 4547 CU_ASSERT(g_bserrno == 0); 4548 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 4549 bs = g_bs; 4550 4551 for (i = 0; i < 4; i++) { 4552 blob = ut_blob_create_and_open(bs, NULL); 4553 iter_ctx.blobid[i] = spdk_blob_get_id(blob); 4554 4555 /* Just save the blobid as an xattr for testing purposes. */ 4556 rc = spdk_blob_set_xattr(blob, "blobid", &iter_ctx.blobid[i], sizeof(spdk_blob_id)); 4557 CU_ASSERT(rc == 0); 4558 4559 /* Resize the blob */ 4560 spdk_blob_resize(blob, i, blob_op_complete, NULL); 4561 poll_threads(); 4562 CU_ASSERT(g_bserrno == 0); 4563 4564 spdk_blob_close(blob, blob_op_complete, NULL); 4565 poll_threads(); 4566 CU_ASSERT(g_bserrno == 0); 4567 } 4568 4569 g_bserrno = -1; 4570 spdk_bs_unload(bs, bs_op_complete, NULL); 4571 poll_threads(); 4572 CU_ASSERT(g_bserrno == 0); 4573 4574 dev = init_dev(); 4575 spdk_bs_opts_init(&opts, sizeof(opts)); 4576 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 4577 opts.iter_cb_fn = test_iter; 4578 opts.iter_cb_arg = &iter_ctx; 4579 4580 /* Test blob iteration during load after a clean shutdown. */ 4581 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 4582 poll_threads(); 4583 CU_ASSERT(g_bserrno == 0); 4584 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 4585 bs = g_bs; 4586 4587 /* Dirty shutdown */ 4588 bs_free(bs); 4589 4590 dev = init_dev(); 4591 spdk_bs_opts_init(&opts, sizeof(opts)); 4592 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); 4593 opts.iter_cb_fn = test_iter; 4594 iter_ctx.current_iter = 0; 4595 opts.iter_cb_arg = &iter_ctx; 4596 4597 /* Test blob iteration during load after a dirty shutdown. */ 4598 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 4599 poll_threads(); 4600 CU_ASSERT(g_bserrno == 0); 4601 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 4602 bs = g_bs; 4603 4604 spdk_bs_unload(bs, bs_op_complete, NULL); 4605 poll_threads(); 4606 CU_ASSERT(g_bserrno == 0); 4607 g_bs = NULL; 4608 } 4609 4610 static void 4611 blob_snapshot_rw(void) 4612 { 4613 static const uint8_t zero[10 * 4096] = { 0 }; 4614 struct spdk_blob_store *bs = g_bs; 4615 struct spdk_blob *blob, *snapshot; 4616 struct spdk_io_channel *channel; 4617 struct spdk_blob_opts opts; 4618 spdk_blob_id blobid, snapshotid; 4619 uint64_t free_clusters; 4620 uint64_t cluster_size; 4621 uint64_t page_size; 4622 uint8_t payload_read[10 * 4096]; 4623 uint8_t payload_write[10 * 4096]; 4624 uint64_t write_bytes_start; 4625 uint64_t read_bytes_start; 4626 uint64_t copy_bytes_start; 4627 uint64_t write_bytes; 4628 uint64_t read_bytes; 4629 uint64_t copy_bytes; 4630 4631 free_clusters = spdk_bs_free_cluster_count(bs); 4632 cluster_size = spdk_bs_get_cluster_size(bs); 4633 page_size = spdk_bs_get_page_size(bs); 4634 4635 channel = spdk_bs_alloc_io_channel(bs); 4636 CU_ASSERT(channel != NULL); 4637 4638 ut_spdk_blob_opts_init(&opts); 4639 opts.thin_provision = true; 4640 opts.num_clusters = 5; 4641 4642 blob = ut_blob_create_and_open(bs, &opts); 4643 blobid = spdk_blob_get_id(blob); 4644 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4645 4646 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5); 4647 4648 memset(payload_read, 0xFF, sizeof(payload_read)); 4649 spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL); 4650 poll_threads(); 4651 CU_ASSERT(g_bserrno == 0); 4652 CU_ASSERT(memcmp(zero, payload_read, 10 * 4096) == 0); 4653 4654 memset(payload_write, 0xE5, sizeof(payload_write)); 4655 spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL); 4656 poll_threads(); 4657 CU_ASSERT(g_bserrno == 0); 4658 CU_ASSERT(free_clusters != spdk_bs_free_cluster_count(bs)); 4659 4660 /* Create snapshot from blob */ 4661 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 4662 poll_threads(); 4663 CU_ASSERT(g_bserrno == 0); 4664 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 4665 snapshotid = g_blobid; 4666 4667 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 4668 poll_threads(); 4669 CU_ASSERT(g_bserrno == 0); 4670 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 4671 snapshot = g_blob; 4672 CU_ASSERT(snapshot->data_ro == true); 4673 CU_ASSERT(snapshot->md_ro == true); 4674 4675 CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 5); 4676 4677 write_bytes_start = g_dev_write_bytes; 4678 read_bytes_start = g_dev_read_bytes; 4679 copy_bytes_start = g_dev_copy_bytes; 4680 4681 memset(payload_write, 0xAA, sizeof(payload_write)); 4682 spdk_blob_io_write(blob, channel, payload_write, 4, 10, blob_op_complete, NULL); 4683 poll_threads(); 4684 CU_ASSERT(g_bserrno == 0); 4685 CU_ASSERT(free_clusters != spdk_bs_free_cluster_count(bs)); 4686 4687 /* For a clone we need to allocate and copy one cluster, update one page of metadata 4688 * and then write 10 pages of payload. 4689 */ 4690 write_bytes = g_dev_write_bytes - write_bytes_start; 4691 read_bytes = g_dev_read_bytes - read_bytes_start; 4692 copy_bytes = g_dev_copy_bytes - copy_bytes_start; 4693 if (g_dev_copy_enabled) { 4694 CU_ASSERT(copy_bytes == cluster_size); 4695 } else { 4696 CU_ASSERT(copy_bytes == 0); 4697 } 4698 if (g_use_extent_table) { 4699 /* Add one more page for EXTENT_PAGE write */ 4700 CU_ASSERT(write_bytes + copy_bytes == page_size * 12 + cluster_size); 4701 } else { 4702 CU_ASSERT(write_bytes + copy_bytes == page_size * 11 + cluster_size); 4703 } 4704 CU_ASSERT(read_bytes + copy_bytes == cluster_size); 4705 4706 spdk_blob_io_read(blob, channel, payload_read, 4, 10, blob_op_complete, NULL); 4707 poll_threads(); 4708 CU_ASSERT(g_bserrno == 0); 4709 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0); 4710 4711 /* Data on snapshot should not change after write to clone */ 4712 memset(payload_write, 0xE5, sizeof(payload_write)); 4713 spdk_blob_io_read(snapshot, channel, payload_read, 4, 10, blob_op_complete, NULL); 4714 poll_threads(); 4715 CU_ASSERT(g_bserrno == 0); 4716 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0); 4717 4718 ut_blob_close_and_delete(bs, blob); 4719 ut_blob_close_and_delete(bs, snapshot); 4720 4721 spdk_bs_free_io_channel(channel); 4722 poll_threads(); 4723 g_blob = NULL; 4724 g_blobid = 0; 4725 } 4726 4727 static void 4728 blob_snapshot_rw_iov(void) 4729 { 4730 static const uint8_t zero[10 * 4096] = { 0 }; 4731 struct spdk_blob_store *bs = g_bs; 4732 struct spdk_blob *blob, *snapshot; 4733 struct spdk_io_channel *channel; 4734 struct spdk_blob_opts opts; 4735 spdk_blob_id blobid, snapshotid; 4736 uint64_t free_clusters; 4737 uint8_t payload_read[10 * 4096]; 4738 uint8_t payload_write[10 * 4096]; 4739 struct iovec iov_read[3]; 4740 struct iovec iov_write[3]; 4741 4742 free_clusters = spdk_bs_free_cluster_count(bs); 4743 4744 channel = spdk_bs_alloc_io_channel(bs); 4745 CU_ASSERT(channel != NULL); 4746 4747 ut_spdk_blob_opts_init(&opts); 4748 opts.thin_provision = true; 4749 opts.num_clusters = 5; 4750 4751 blob = ut_blob_create_and_open(bs, &opts); 4752 blobid = spdk_blob_get_id(blob); 4753 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4754 4755 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5); 4756 4757 /* Create snapshot from blob */ 4758 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 4759 poll_threads(); 4760 CU_ASSERT(g_bserrno == 0); 4761 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 4762 snapshotid = g_blobid; 4763 4764 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 4765 poll_threads(); 4766 CU_ASSERT(g_bserrno == 0); 4767 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 4768 snapshot = g_blob; 4769 CU_ASSERT(snapshot->data_ro == true); 4770 CU_ASSERT(snapshot->md_ro == true); 4771 CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 5); 4772 4773 /* Payload should be all zeros from unallocated clusters */ 4774 memset(payload_read, 0xAA, sizeof(payload_read)); 4775 iov_read[0].iov_base = payload_read; 4776 iov_read[0].iov_len = 3 * 4096; 4777 iov_read[1].iov_base = payload_read + 3 * 4096; 4778 iov_read[1].iov_len = 4 * 4096; 4779 iov_read[2].iov_base = payload_read + 7 * 4096; 4780 iov_read[2].iov_len = 3 * 4096; 4781 spdk_blob_io_readv(blob, channel, iov_read, 3, 250, 10, blob_op_complete, NULL); 4782 poll_threads(); 4783 CU_ASSERT(g_bserrno == 0); 4784 CU_ASSERT(memcmp(zero, payload_read, 10 * 4096) == 0); 4785 4786 memset(payload_write, 0xE5, sizeof(payload_write)); 4787 iov_write[0].iov_base = payload_write; 4788 iov_write[0].iov_len = 1 * 4096; 4789 iov_write[1].iov_base = payload_write + 1 * 4096; 4790 iov_write[1].iov_len = 5 * 4096; 4791 iov_write[2].iov_base = payload_write + 6 * 4096; 4792 iov_write[2].iov_len = 4 * 4096; 4793 4794 spdk_blob_io_writev(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL); 4795 poll_threads(); 4796 CU_ASSERT(g_bserrno == 0); 4797 4798 memset(payload_read, 0xAA, sizeof(payload_read)); 4799 iov_read[0].iov_base = payload_read; 4800 iov_read[0].iov_len = 3 * 4096; 4801 iov_read[1].iov_base = payload_read + 3 * 4096; 4802 iov_read[1].iov_len = 4 * 4096; 4803 iov_read[2].iov_base = payload_read + 7 * 4096; 4804 iov_read[2].iov_len = 3 * 4096; 4805 spdk_blob_io_readv(blob, channel, iov_read, 3, 250, 10, blob_op_complete, NULL); 4806 poll_threads(); 4807 CU_ASSERT(g_bserrno == 0); 4808 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0); 4809 4810 spdk_bs_free_io_channel(channel); 4811 poll_threads(); 4812 4813 ut_blob_close_and_delete(bs, blob); 4814 ut_blob_close_and_delete(bs, snapshot); 4815 } 4816 4817 /** 4818 * Inflate / decouple parent rw unit tests. 4819 * 4820 * -------------- 4821 * original blob: 0 1 2 3 4 4822 * ,---------+---------+---------+---------+---------. 4823 * snapshot |xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx| - | 4824 * +---------+---------+---------+---------+---------+ 4825 * snapshot2 | - |yyyyyyyyy| - |yyyyyyyyy| - | 4826 * +---------+---------+---------+---------+---------+ 4827 * blob | - |zzzzzzzzz| - | - | - | 4828 * '---------+---------+---------+---------+---------' 4829 * . . . . . . 4830 * -------- . . . . . . 4831 * inflate: . . . . . . 4832 * ,---------+---------+---------+---------+---------. 4833 * blob |xxxxxxxxx|zzzzzzzzz|xxxxxxxxx|yyyyyyyyy|000000000| 4834 * '---------+---------+---------+---------+---------' 4835 * 4836 * NOTE: needs to allocate 4 clusters, thin provisioning removed, dependency 4837 * on snapshot2 and snapshot removed . . . 4838 * . . . . . . 4839 * ---------------- . . . . . . 4840 * decouple parent: . . . . . . 4841 * ,---------+---------+---------+---------+---------. 4842 * snapshot |xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx| - | 4843 * +---------+---------+---------+---------+---------+ 4844 * blob | - |zzzzzzzzz| - |yyyyyyyyy| - | 4845 * '---------+---------+---------+---------+---------' 4846 * 4847 * NOTE: needs to allocate 1 cluster, 3 clusters unallocated, dependency 4848 * on snapshot2 removed and on snapshot still exists. Snapshot2 4849 * should remain a clone of snapshot. 4850 */ 4851 static void 4852 _blob_inflate_rw(bool decouple_parent) 4853 { 4854 struct spdk_blob_store *bs = g_bs; 4855 struct spdk_blob *blob, *snapshot, *snapshot2; 4856 struct spdk_io_channel *channel; 4857 struct spdk_blob_opts opts; 4858 spdk_blob_id blobid, snapshotid, snapshot2id; 4859 uint64_t free_clusters; 4860 uint64_t cluster_size; 4861 4862 uint64_t payload_size; 4863 uint8_t *payload_read; 4864 uint8_t *payload_write; 4865 uint8_t *payload_clone; 4866 4867 uint64_t pages_per_cluster; 4868 uint64_t pages_per_payload; 4869 4870 int i; 4871 spdk_blob_id ids[2]; 4872 size_t count; 4873 4874 free_clusters = spdk_bs_free_cluster_count(bs); 4875 cluster_size = spdk_bs_get_cluster_size(bs); 4876 pages_per_cluster = cluster_size / spdk_bs_get_page_size(bs); 4877 pages_per_payload = pages_per_cluster * 5; 4878 4879 payload_size = cluster_size * 5; 4880 4881 payload_read = malloc(payload_size); 4882 SPDK_CU_ASSERT_FATAL(payload_read != NULL); 4883 4884 payload_write = malloc(payload_size); 4885 SPDK_CU_ASSERT_FATAL(payload_write != NULL); 4886 4887 payload_clone = malloc(payload_size); 4888 SPDK_CU_ASSERT_FATAL(payload_clone != NULL); 4889 4890 channel = spdk_bs_alloc_io_channel(bs); 4891 SPDK_CU_ASSERT_FATAL(channel != NULL); 4892 4893 /* Create blob */ 4894 ut_spdk_blob_opts_init(&opts); 4895 opts.thin_provision = true; 4896 opts.num_clusters = 5; 4897 4898 blob = ut_blob_create_and_open(bs, &opts); 4899 blobid = spdk_blob_get_id(blob); 4900 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 4901 4902 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5); 4903 4904 /* 1) Initial read should return zeroed payload */ 4905 memset(payload_read, 0xFF, payload_size); 4906 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload, 4907 blob_op_complete, NULL); 4908 poll_threads(); 4909 CU_ASSERT(g_bserrno == 0); 4910 CU_ASSERT(spdk_mem_all_zero(payload_read, payload_size)); 4911 4912 /* Fill whole blob with a pattern, except last cluster (to be sure it 4913 * isn't allocated) */ 4914 memset(payload_write, 0xE5, payload_size - cluster_size); 4915 spdk_blob_io_write(blob, channel, payload_write, 0, pages_per_payload - 4916 pages_per_cluster, blob_op_complete, NULL); 4917 poll_threads(); 4918 CU_ASSERT(g_bserrno == 0); 4919 CU_ASSERT(free_clusters != spdk_bs_free_cluster_count(bs)); 4920 4921 /* 2) Create snapshot from blob (first level) */ 4922 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 4923 poll_threads(); 4924 CU_ASSERT(g_bserrno == 0); 4925 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 4926 snapshotid = g_blobid; 4927 4928 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 4929 poll_threads(); 4930 CU_ASSERT(g_bserrno == 0); 4931 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 4932 snapshot = g_blob; 4933 CU_ASSERT(snapshot->data_ro == true); 4934 CU_ASSERT(snapshot->md_ro == true); 4935 4936 CU_ASSERT(spdk_blob_get_num_clusters(snapshot) == 5); 4937 4938 /* Write every second cluster with a pattern. 4939 * 4940 * Last cluster shouldn't be written, to be sure that snapshot nor clone 4941 * doesn't allocate it. 4942 * 4943 * payload_clone stores expected result on "blob" read at the time and 4944 * is used only to check data consistency on clone before and after 4945 * inflation. Initially we fill it with a backing snapshots pattern 4946 * used before. 4947 */ 4948 memset(payload_clone, 0xE5, payload_size - cluster_size); 4949 memset(payload_clone + payload_size - cluster_size, 0x00, cluster_size); 4950 memset(payload_write, 0xAA, payload_size); 4951 for (i = 1; i < 5; i += 2) { 4952 spdk_blob_io_write(blob, channel, payload_write, i * pages_per_cluster, 4953 pages_per_cluster, blob_op_complete, NULL); 4954 poll_threads(); 4955 CU_ASSERT(g_bserrno == 0); 4956 4957 /* Update expected result */ 4958 memcpy(payload_clone + (cluster_size * i), payload_write, 4959 cluster_size); 4960 } 4961 CU_ASSERT(free_clusters != spdk_bs_free_cluster_count(bs)); 4962 4963 /* Check data consistency on clone */ 4964 memset(payload_read, 0xFF, payload_size); 4965 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload, 4966 blob_op_complete, NULL); 4967 poll_threads(); 4968 CU_ASSERT(g_bserrno == 0); 4969 CU_ASSERT(memcmp(payload_clone, payload_read, payload_size) == 0); 4970 4971 /* 3) Create second levels snapshot from blob */ 4972 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 4973 poll_threads(); 4974 CU_ASSERT(g_bserrno == 0); 4975 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 4976 snapshot2id = g_blobid; 4977 4978 spdk_bs_open_blob(bs, snapshot2id, blob_op_with_handle_complete, NULL); 4979 poll_threads(); 4980 CU_ASSERT(g_bserrno == 0); 4981 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 4982 snapshot2 = g_blob; 4983 CU_ASSERT(snapshot2->data_ro == true); 4984 CU_ASSERT(snapshot2->md_ro == true); 4985 4986 CU_ASSERT(spdk_blob_get_num_clusters(snapshot2) == 5); 4987 4988 CU_ASSERT(snapshot2->parent_id == snapshotid); 4989 4990 /* Write one cluster on the top level blob. This cluster (1) covers 4991 * already allocated cluster in the snapshot2, so shouldn't be inflated 4992 * at all */ 4993 spdk_blob_io_write(blob, channel, payload_write, pages_per_cluster, 4994 pages_per_cluster, blob_op_complete, NULL); 4995 poll_threads(); 4996 CU_ASSERT(g_bserrno == 0); 4997 4998 /* Update expected result */ 4999 memcpy(payload_clone + cluster_size, payload_write, cluster_size); 5000 5001 /* Check data consistency on clone */ 5002 memset(payload_read, 0xFF, payload_size); 5003 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload, 5004 blob_op_complete, NULL); 5005 poll_threads(); 5006 CU_ASSERT(g_bserrno == 0); 5007 CU_ASSERT(memcmp(payload_clone, payload_read, payload_size) == 0); 5008 5009 5010 /* Close all blobs */ 5011 spdk_blob_close(blob, blob_op_complete, NULL); 5012 poll_threads(); 5013 CU_ASSERT(g_bserrno == 0); 5014 5015 spdk_blob_close(snapshot2, blob_op_complete, NULL); 5016 poll_threads(); 5017 CU_ASSERT(g_bserrno == 0); 5018 5019 spdk_blob_close(snapshot, blob_op_complete, NULL); 5020 poll_threads(); 5021 CU_ASSERT(g_bserrno == 0); 5022 5023 /* Check snapshot-clone relations */ 5024 count = 2; 5025 CU_ASSERT(spdk_blob_get_clones(bs, snapshotid, ids, &count) == 0); 5026 CU_ASSERT(count == 1); 5027 CU_ASSERT(ids[0] == snapshot2id); 5028 5029 count = 2; 5030 CU_ASSERT(spdk_blob_get_clones(bs, snapshot2id, ids, &count) == 0); 5031 CU_ASSERT(count == 1); 5032 CU_ASSERT(ids[0] == blobid); 5033 5034 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshot2id); 5035 5036 free_clusters = spdk_bs_free_cluster_count(bs); 5037 if (!decouple_parent) { 5038 /* Do full blob inflation */ 5039 spdk_bs_inflate_blob(bs, channel, blobid, blob_op_complete, NULL); 5040 poll_threads(); 5041 CU_ASSERT(g_bserrno == 0); 5042 5043 /* All clusters should be inflated (except one already allocated 5044 * in a top level blob) */ 5045 CU_ASSERT(spdk_bs_free_cluster_count(bs) == free_clusters - 4); 5046 5047 /* Check if relation tree updated correctly */ 5048 count = 2; 5049 CU_ASSERT(spdk_blob_get_clones(bs, snapshotid, ids, &count) == 0); 5050 5051 /* snapshotid have one clone */ 5052 CU_ASSERT(count == 1); 5053 CU_ASSERT(ids[0] == snapshot2id); 5054 5055 /* snapshot2id have no clones */ 5056 count = 2; 5057 CU_ASSERT(spdk_blob_get_clones(bs, snapshot2id, ids, &count) == 0); 5058 CU_ASSERT(count == 0); 5059 5060 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == SPDK_BLOBID_INVALID); 5061 } else { 5062 /* Decouple parent of blob */ 5063 spdk_bs_blob_decouple_parent(bs, channel, blobid, blob_op_complete, NULL); 5064 poll_threads(); 5065 CU_ASSERT(g_bserrno == 0); 5066 5067 /* Only one cluster from a parent should be inflated (second one 5068 * is covered by a cluster written on a top level blob, and 5069 * already allocated) */ 5070 CU_ASSERT(spdk_bs_free_cluster_count(bs) == free_clusters - 1); 5071 5072 /* Check if relation tree updated correctly */ 5073 count = 2; 5074 CU_ASSERT(spdk_blob_get_clones(bs, snapshotid, ids, &count) == 0); 5075 5076 /* snapshotid have two clones now */ 5077 CU_ASSERT(count == 2); 5078 CU_ASSERT(ids[0] == blobid || ids[1] == blobid); 5079 CU_ASSERT(ids[0] == snapshot2id || ids[1] == snapshot2id); 5080 5081 /* snapshot2id have no clones */ 5082 count = 2; 5083 CU_ASSERT(spdk_blob_get_clones(bs, snapshot2id, ids, &count) == 0); 5084 CU_ASSERT(count == 0); 5085 5086 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid); 5087 } 5088 5089 /* Try to delete snapshot2 (should pass) */ 5090 spdk_bs_delete_blob(bs, snapshot2id, blob_op_complete, NULL); 5091 poll_threads(); 5092 CU_ASSERT(g_bserrno == 0); 5093 5094 /* Try to delete base snapshot */ 5095 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL); 5096 poll_threads(); 5097 CU_ASSERT(g_bserrno == 0); 5098 5099 /* Reopen blob after snapshot deletion */ 5100 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 5101 poll_threads(); 5102 CU_ASSERT(g_bserrno == 0); 5103 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 5104 blob = g_blob; 5105 5106 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5); 5107 5108 /* Check data consistency on inflated blob */ 5109 memset(payload_read, 0xFF, payload_size); 5110 spdk_blob_io_read(blob, channel, payload_read, 0, pages_per_payload, 5111 blob_op_complete, NULL); 5112 poll_threads(); 5113 CU_ASSERT(g_bserrno == 0); 5114 CU_ASSERT(memcmp(payload_clone, payload_read, payload_size) == 0); 5115 5116 spdk_bs_free_io_channel(channel); 5117 poll_threads(); 5118 5119 free(payload_read); 5120 free(payload_write); 5121 free(payload_clone); 5122 5123 ut_blob_close_and_delete(bs, blob); 5124 } 5125 5126 static void 5127 blob_inflate_rw(void) 5128 { 5129 _blob_inflate_rw(false); 5130 _blob_inflate_rw(true); 5131 } 5132 5133 /** 5134 * Snapshot-clones relation test 5135 * 5136 * snapshot 5137 * | 5138 * +-----+-----+ 5139 * | | 5140 * blob(ro) snapshot2 5141 * | | 5142 * clone2 clone 5143 */ 5144 static void 5145 blob_relations(void) 5146 { 5147 struct spdk_blob_store *bs; 5148 struct spdk_bs_dev *dev; 5149 struct spdk_bs_opts bs_opts; 5150 struct spdk_blob_opts opts; 5151 struct spdk_blob *blob, *snapshot, *snapshot2, *clone, *clone2; 5152 spdk_blob_id blobid, cloneid, snapshotid, cloneid2, snapshotid2; 5153 int rc; 5154 size_t count; 5155 spdk_blob_id ids[10] = {}; 5156 5157 dev = init_dev(); 5158 spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); 5159 snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE"); 5160 5161 spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL); 5162 poll_threads(); 5163 CU_ASSERT(g_bserrno == 0); 5164 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 5165 bs = g_bs; 5166 5167 /* 1. Create blob with 10 clusters */ 5168 5169 ut_spdk_blob_opts_init(&opts); 5170 opts.num_clusters = 10; 5171 5172 blob = ut_blob_create_and_open(bs, &opts); 5173 blobid = spdk_blob_get_id(blob); 5174 5175 CU_ASSERT(!spdk_blob_is_read_only(blob)); 5176 CU_ASSERT(!spdk_blob_is_snapshot(blob)); 5177 CU_ASSERT(!spdk_blob_is_clone(blob)); 5178 CU_ASSERT(!spdk_blob_is_thin_provisioned(blob)); 5179 5180 /* blob should not have underlying snapshot nor clones */ 5181 CU_ASSERT(blob->parent_id == SPDK_BLOBID_INVALID); 5182 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == SPDK_BLOBID_INVALID); 5183 count = SPDK_COUNTOF(ids); 5184 rc = spdk_blob_get_clones(bs, blobid, ids, &count); 5185 CU_ASSERT(rc == 0); 5186 CU_ASSERT(count == 0); 5187 5188 5189 /* 2. Create snapshot */ 5190 5191 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 5192 poll_threads(); 5193 CU_ASSERT(g_bserrno == 0); 5194 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5195 snapshotid = g_blobid; 5196 5197 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 5198 poll_threads(); 5199 CU_ASSERT(g_bserrno == 0); 5200 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 5201 snapshot = g_blob; 5202 5203 CU_ASSERT(spdk_blob_is_read_only(snapshot)); 5204 CU_ASSERT(spdk_blob_is_snapshot(snapshot)); 5205 CU_ASSERT(!spdk_blob_is_clone(snapshot)); 5206 CU_ASSERT(snapshot->parent_id == SPDK_BLOBID_INVALID); 5207 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid) == SPDK_BLOBID_INVALID); 5208 5209 /* Check if original blob is converted to the clone of snapshot */ 5210 CU_ASSERT(!spdk_blob_is_read_only(blob)); 5211 CU_ASSERT(!spdk_blob_is_snapshot(blob)); 5212 CU_ASSERT(spdk_blob_is_clone(blob)); 5213 CU_ASSERT(spdk_blob_is_thin_provisioned(blob)); 5214 CU_ASSERT(blob->parent_id == snapshotid); 5215 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid); 5216 5217 count = SPDK_COUNTOF(ids); 5218 rc = spdk_blob_get_clones(bs, snapshotid, ids, &count); 5219 CU_ASSERT(rc == 0); 5220 CU_ASSERT(count == 1); 5221 CU_ASSERT(ids[0] == blobid); 5222 5223 5224 /* 3. Create clone from snapshot */ 5225 5226 spdk_bs_create_clone(bs, snapshotid, NULL, blob_op_with_id_complete, NULL); 5227 poll_threads(); 5228 CU_ASSERT(g_bserrno == 0); 5229 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5230 cloneid = g_blobid; 5231 5232 spdk_bs_open_blob(bs, cloneid, blob_op_with_handle_complete, NULL); 5233 poll_threads(); 5234 CU_ASSERT(g_bserrno == 0); 5235 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 5236 clone = g_blob; 5237 5238 CU_ASSERT(!spdk_blob_is_read_only(clone)); 5239 CU_ASSERT(!spdk_blob_is_snapshot(clone)); 5240 CU_ASSERT(spdk_blob_is_clone(clone)); 5241 CU_ASSERT(spdk_blob_is_thin_provisioned(clone)); 5242 CU_ASSERT(clone->parent_id == snapshotid); 5243 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid); 5244 5245 count = SPDK_COUNTOF(ids); 5246 rc = spdk_blob_get_clones(bs, cloneid, ids, &count); 5247 CU_ASSERT(rc == 0); 5248 CU_ASSERT(count == 0); 5249 5250 /* Check if clone is on the snapshot's list */ 5251 count = SPDK_COUNTOF(ids); 5252 rc = spdk_blob_get_clones(bs, snapshotid, ids, &count); 5253 CU_ASSERT(rc == 0); 5254 CU_ASSERT(ids[0] == blobid || ids[1] == blobid); 5255 CU_ASSERT(ids[0] == cloneid || ids[1] == cloneid); 5256 5257 5258 /* 4. Create snapshot of the clone */ 5259 5260 spdk_bs_create_snapshot(bs, cloneid, NULL, blob_op_with_id_complete, NULL); 5261 poll_threads(); 5262 CU_ASSERT(g_bserrno == 0); 5263 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5264 snapshotid2 = g_blobid; 5265 5266 spdk_bs_open_blob(bs, snapshotid2, blob_op_with_handle_complete, NULL); 5267 poll_threads(); 5268 CU_ASSERT(g_bserrno == 0); 5269 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 5270 snapshot2 = g_blob; 5271 5272 CU_ASSERT(spdk_blob_is_read_only(snapshot2)); 5273 CU_ASSERT(spdk_blob_is_snapshot(snapshot2)); 5274 CU_ASSERT(spdk_blob_is_clone(snapshot2)); 5275 CU_ASSERT(snapshot2->parent_id == snapshotid); 5276 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid2) == snapshotid); 5277 5278 /* Check if clone is converted to the clone of snapshot2 and snapshot2 5279 * is a child of snapshot */ 5280 CU_ASSERT(!spdk_blob_is_read_only(clone)); 5281 CU_ASSERT(!spdk_blob_is_snapshot(clone)); 5282 CU_ASSERT(spdk_blob_is_clone(clone)); 5283 CU_ASSERT(spdk_blob_is_thin_provisioned(clone)); 5284 CU_ASSERT(clone->parent_id == snapshotid2); 5285 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid2); 5286 5287 count = SPDK_COUNTOF(ids); 5288 rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count); 5289 CU_ASSERT(rc == 0); 5290 CU_ASSERT(count == 1); 5291 CU_ASSERT(ids[0] == cloneid); 5292 5293 5294 /* 5. Try to create clone from read only blob */ 5295 5296 /* Mark blob as read only */ 5297 spdk_blob_set_read_only(blob); 5298 spdk_blob_sync_md(blob, blob_op_complete, NULL); 5299 poll_threads(); 5300 CU_ASSERT(g_bserrno == 0); 5301 5302 /* Check if previously created blob is read only clone */ 5303 CU_ASSERT(spdk_blob_is_read_only(blob)); 5304 CU_ASSERT(!spdk_blob_is_snapshot(blob)); 5305 CU_ASSERT(spdk_blob_is_clone(blob)); 5306 CU_ASSERT(spdk_blob_is_thin_provisioned(blob)); 5307 5308 /* Create clone from read only blob */ 5309 spdk_bs_create_clone(bs, blobid, NULL, blob_op_with_id_complete, NULL); 5310 poll_threads(); 5311 CU_ASSERT(g_bserrno == 0); 5312 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5313 cloneid2 = g_blobid; 5314 5315 spdk_bs_open_blob(bs, cloneid2, blob_op_with_handle_complete, NULL); 5316 poll_threads(); 5317 CU_ASSERT(g_bserrno == 0); 5318 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 5319 clone2 = g_blob; 5320 5321 CU_ASSERT(!spdk_blob_is_read_only(clone2)); 5322 CU_ASSERT(!spdk_blob_is_snapshot(clone2)); 5323 CU_ASSERT(spdk_blob_is_clone(clone2)); 5324 CU_ASSERT(spdk_blob_is_thin_provisioned(clone2)); 5325 5326 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid2) == blobid); 5327 5328 count = SPDK_COUNTOF(ids); 5329 rc = spdk_blob_get_clones(bs, blobid, ids, &count); 5330 CU_ASSERT(rc == 0); 5331 5332 CU_ASSERT(count == 1); 5333 CU_ASSERT(ids[0] == cloneid2); 5334 5335 /* Close blobs */ 5336 5337 spdk_blob_close(clone2, blob_op_complete, NULL); 5338 poll_threads(); 5339 CU_ASSERT(g_bserrno == 0); 5340 5341 spdk_blob_close(blob, blob_op_complete, NULL); 5342 poll_threads(); 5343 CU_ASSERT(g_bserrno == 0); 5344 5345 spdk_blob_close(clone, blob_op_complete, NULL); 5346 poll_threads(); 5347 CU_ASSERT(g_bserrno == 0); 5348 5349 spdk_blob_close(snapshot, blob_op_complete, NULL); 5350 poll_threads(); 5351 CU_ASSERT(g_bserrno == 0); 5352 5353 spdk_blob_close(snapshot2, blob_op_complete, NULL); 5354 poll_threads(); 5355 CU_ASSERT(g_bserrno == 0); 5356 5357 /* Try to delete snapshot with more than 1 clone */ 5358 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL); 5359 poll_threads(); 5360 CU_ASSERT(g_bserrno != 0); 5361 5362 ut_bs_reload(&bs, &bs_opts); 5363 5364 /* NULL ids array should return number of clones in count */ 5365 count = SPDK_COUNTOF(ids); 5366 rc = spdk_blob_get_clones(bs, snapshotid, NULL, &count); 5367 CU_ASSERT(rc == -ENOMEM); 5368 CU_ASSERT(count == 2); 5369 5370 /* incorrect array size */ 5371 count = 1; 5372 rc = spdk_blob_get_clones(bs, snapshotid, ids, &count); 5373 CU_ASSERT(rc == -ENOMEM); 5374 CU_ASSERT(count == 2); 5375 5376 5377 /* Verify structure of loaded blob store */ 5378 5379 /* snapshot */ 5380 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid) == SPDK_BLOBID_INVALID); 5381 5382 count = SPDK_COUNTOF(ids); 5383 rc = spdk_blob_get_clones(bs, snapshotid, ids, &count); 5384 CU_ASSERT(rc == 0); 5385 CU_ASSERT(count == 2); 5386 CU_ASSERT(ids[0] == blobid || ids[1] == blobid); 5387 CU_ASSERT(ids[0] == snapshotid2 || ids[1] == snapshotid2); 5388 5389 /* blob */ 5390 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid); 5391 count = SPDK_COUNTOF(ids); 5392 rc = spdk_blob_get_clones(bs, blobid, ids, &count); 5393 CU_ASSERT(rc == 0); 5394 CU_ASSERT(count == 1); 5395 CU_ASSERT(ids[0] == cloneid2); 5396 5397 /* clone */ 5398 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid2); 5399 count = SPDK_COUNTOF(ids); 5400 rc = spdk_blob_get_clones(bs, cloneid, ids, &count); 5401 CU_ASSERT(rc == 0); 5402 CU_ASSERT(count == 0); 5403 5404 /* snapshot2 */ 5405 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid2) == snapshotid); 5406 count = SPDK_COUNTOF(ids); 5407 rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count); 5408 CU_ASSERT(rc == 0); 5409 CU_ASSERT(count == 1); 5410 CU_ASSERT(ids[0] == cloneid); 5411 5412 /* clone2 */ 5413 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid2) == blobid); 5414 count = SPDK_COUNTOF(ids); 5415 rc = spdk_blob_get_clones(bs, cloneid2, ids, &count); 5416 CU_ASSERT(rc == 0); 5417 CU_ASSERT(count == 0); 5418 5419 /* Try to delete blob that user should not be able to remove */ 5420 5421 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL); 5422 poll_threads(); 5423 CU_ASSERT(g_bserrno != 0); 5424 5425 /* Remove all blobs */ 5426 5427 spdk_bs_delete_blob(bs, cloneid, blob_op_complete, NULL); 5428 poll_threads(); 5429 CU_ASSERT(g_bserrno == 0); 5430 5431 spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL); 5432 poll_threads(); 5433 CU_ASSERT(g_bserrno == 0); 5434 5435 spdk_bs_delete_blob(bs, cloneid2, blob_op_complete, NULL); 5436 poll_threads(); 5437 CU_ASSERT(g_bserrno == 0); 5438 5439 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); 5440 poll_threads(); 5441 CU_ASSERT(g_bserrno == 0); 5442 5443 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL); 5444 poll_threads(); 5445 CU_ASSERT(g_bserrno == 0); 5446 5447 spdk_bs_unload(bs, bs_op_complete, NULL); 5448 poll_threads(); 5449 CU_ASSERT(g_bserrno == 0); 5450 5451 g_bs = NULL; 5452 } 5453 5454 /** 5455 * Snapshot-clones relation test 2 5456 * 5457 * snapshot1 5458 * | 5459 * snapshot2 5460 * | 5461 * +-----+-----+ 5462 * | | 5463 * blob(ro) snapshot3 5464 * | | 5465 * | snapshot4 5466 * | | | 5467 * clone2 clone clone3 5468 */ 5469 static void 5470 blob_relations2(void) 5471 { 5472 struct spdk_blob_store *bs; 5473 struct spdk_bs_dev *dev; 5474 struct spdk_bs_opts bs_opts; 5475 struct spdk_blob_opts opts; 5476 struct spdk_blob *blob, *snapshot1, *snapshot2, *snapshot3, *snapshot4, *clone, *clone2; 5477 spdk_blob_id blobid, snapshotid1, snapshotid2, snapshotid3, snapshotid4, cloneid, cloneid2, 5478 cloneid3; 5479 int rc; 5480 size_t count; 5481 spdk_blob_id ids[10] = {}; 5482 5483 dev = init_dev(); 5484 spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); 5485 snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE"); 5486 5487 spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL); 5488 poll_threads(); 5489 CU_ASSERT(g_bserrno == 0); 5490 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 5491 bs = g_bs; 5492 5493 /* 1. Create blob with 10 clusters */ 5494 5495 ut_spdk_blob_opts_init(&opts); 5496 opts.num_clusters = 10; 5497 5498 blob = ut_blob_create_and_open(bs, &opts); 5499 blobid = spdk_blob_get_id(blob); 5500 5501 /* 2. Create snapshot1 */ 5502 5503 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 5504 poll_threads(); 5505 CU_ASSERT(g_bserrno == 0); 5506 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5507 snapshotid1 = g_blobid; 5508 5509 spdk_bs_open_blob(bs, snapshotid1, blob_op_with_handle_complete, NULL); 5510 poll_threads(); 5511 CU_ASSERT(g_bserrno == 0); 5512 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 5513 snapshot1 = g_blob; 5514 5515 CU_ASSERT(snapshot1->parent_id == SPDK_BLOBID_INVALID); 5516 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid1) == SPDK_BLOBID_INVALID); 5517 5518 CU_ASSERT(blob->parent_id == snapshotid1); 5519 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid1); 5520 5521 /* Check if blob is the clone of snapshot1 */ 5522 CU_ASSERT(blob->parent_id == snapshotid1); 5523 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid1); 5524 5525 count = SPDK_COUNTOF(ids); 5526 rc = spdk_blob_get_clones(bs, snapshotid1, ids, &count); 5527 CU_ASSERT(rc == 0); 5528 CU_ASSERT(count == 1); 5529 CU_ASSERT(ids[0] == blobid); 5530 5531 /* 3. Create another snapshot */ 5532 5533 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 5534 poll_threads(); 5535 CU_ASSERT(g_bserrno == 0); 5536 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5537 snapshotid2 = g_blobid; 5538 5539 spdk_bs_open_blob(bs, snapshotid2, blob_op_with_handle_complete, NULL); 5540 poll_threads(); 5541 CU_ASSERT(g_bserrno == 0); 5542 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 5543 snapshot2 = g_blob; 5544 5545 CU_ASSERT(spdk_blob_is_clone(snapshot2)); 5546 CU_ASSERT(snapshot2->parent_id == snapshotid1); 5547 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid2) == snapshotid1); 5548 5549 /* Check if snapshot2 is the clone of snapshot1 and blob 5550 * is a child of snapshot2 */ 5551 CU_ASSERT(blob->parent_id == snapshotid2); 5552 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid2); 5553 5554 count = SPDK_COUNTOF(ids); 5555 rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count); 5556 CU_ASSERT(rc == 0); 5557 CU_ASSERT(count == 1); 5558 CU_ASSERT(ids[0] == blobid); 5559 5560 /* 4. Create clone from snapshot */ 5561 5562 spdk_bs_create_clone(bs, snapshotid2, NULL, blob_op_with_id_complete, NULL); 5563 poll_threads(); 5564 CU_ASSERT(g_bserrno == 0); 5565 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5566 cloneid = g_blobid; 5567 5568 spdk_bs_open_blob(bs, cloneid, blob_op_with_handle_complete, NULL); 5569 poll_threads(); 5570 CU_ASSERT(g_bserrno == 0); 5571 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 5572 clone = g_blob; 5573 5574 CU_ASSERT(clone->parent_id == snapshotid2); 5575 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid2); 5576 5577 /* Check if clone is on the snapshot's list */ 5578 count = SPDK_COUNTOF(ids); 5579 rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count); 5580 CU_ASSERT(rc == 0); 5581 CU_ASSERT(count == 2); 5582 CU_ASSERT(ids[0] == blobid || ids[1] == blobid); 5583 CU_ASSERT(ids[0] == cloneid || ids[1] == cloneid); 5584 5585 /* 5. Create snapshot of the clone */ 5586 5587 spdk_bs_create_snapshot(bs, cloneid, NULL, blob_op_with_id_complete, NULL); 5588 poll_threads(); 5589 CU_ASSERT(g_bserrno == 0); 5590 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5591 snapshotid3 = g_blobid; 5592 5593 spdk_bs_open_blob(bs, snapshotid3, blob_op_with_handle_complete, NULL); 5594 poll_threads(); 5595 CU_ASSERT(g_bserrno == 0); 5596 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 5597 snapshot3 = g_blob; 5598 5599 CU_ASSERT(snapshot3->parent_id == snapshotid2); 5600 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid3) == snapshotid2); 5601 5602 /* Check if clone is converted to the clone of snapshot3 and snapshot3 5603 * is a child of snapshot2 */ 5604 CU_ASSERT(clone->parent_id == snapshotid3); 5605 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid3); 5606 5607 count = SPDK_COUNTOF(ids); 5608 rc = spdk_blob_get_clones(bs, snapshotid3, ids, &count); 5609 CU_ASSERT(rc == 0); 5610 CU_ASSERT(count == 1); 5611 CU_ASSERT(ids[0] == cloneid); 5612 5613 /* 6. Create another snapshot of the clone */ 5614 5615 spdk_bs_create_snapshot(bs, cloneid, NULL, blob_op_with_id_complete, NULL); 5616 poll_threads(); 5617 CU_ASSERT(g_bserrno == 0); 5618 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5619 snapshotid4 = g_blobid; 5620 5621 spdk_bs_open_blob(bs, snapshotid4, blob_op_with_handle_complete, NULL); 5622 poll_threads(); 5623 CU_ASSERT(g_bserrno == 0); 5624 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 5625 snapshot4 = g_blob; 5626 5627 CU_ASSERT(snapshot4->parent_id == snapshotid3); 5628 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid4) == snapshotid3); 5629 5630 /* Check if clone is converted to the clone of snapshot4 and snapshot4 5631 * is a child of snapshot3 */ 5632 CU_ASSERT(clone->parent_id == snapshotid4); 5633 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid4); 5634 5635 count = SPDK_COUNTOF(ids); 5636 rc = spdk_blob_get_clones(bs, snapshotid4, ids, &count); 5637 CU_ASSERT(rc == 0); 5638 CU_ASSERT(count == 1); 5639 CU_ASSERT(ids[0] == cloneid); 5640 5641 /* 7. Remove snapshot 4 */ 5642 5643 ut_blob_close_and_delete(bs, snapshot4); 5644 5645 /* Check if relations are back to state from before creating snapshot 4 */ 5646 CU_ASSERT(clone->parent_id == snapshotid3); 5647 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid3); 5648 5649 count = SPDK_COUNTOF(ids); 5650 rc = spdk_blob_get_clones(bs, snapshotid3, ids, &count); 5651 CU_ASSERT(rc == 0); 5652 CU_ASSERT(count == 1); 5653 CU_ASSERT(ids[0] == cloneid); 5654 5655 /* 8. Create second clone of snapshot 3 and try to remove snapshot 3 */ 5656 5657 spdk_bs_create_clone(bs, snapshotid3, NULL, blob_op_with_id_complete, NULL); 5658 poll_threads(); 5659 CU_ASSERT(g_bserrno == 0); 5660 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5661 cloneid3 = g_blobid; 5662 5663 spdk_bs_delete_blob(bs, snapshotid3, blob_op_complete, NULL); 5664 poll_threads(); 5665 CU_ASSERT(g_bserrno != 0); 5666 5667 /* 9. Open snapshot 3 again and try to remove it while clone 3 is closed */ 5668 5669 spdk_bs_open_blob(bs, snapshotid3, blob_op_with_handle_complete, NULL); 5670 poll_threads(); 5671 CU_ASSERT(g_bserrno == 0); 5672 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 5673 snapshot3 = g_blob; 5674 5675 spdk_bs_delete_blob(bs, snapshotid3, blob_op_complete, NULL); 5676 poll_threads(); 5677 CU_ASSERT(g_bserrno != 0); 5678 5679 spdk_blob_close(snapshot3, blob_op_complete, NULL); 5680 poll_threads(); 5681 CU_ASSERT(g_bserrno == 0); 5682 5683 spdk_bs_delete_blob(bs, cloneid3, blob_op_complete, NULL); 5684 poll_threads(); 5685 CU_ASSERT(g_bserrno == 0); 5686 5687 /* 10. Remove snapshot 1 */ 5688 5689 ut_blob_close_and_delete(bs, snapshot1); 5690 5691 /* Check if relations are back to state from before creating snapshot 4 (before step 6) */ 5692 CU_ASSERT(snapshot2->parent_id == SPDK_BLOBID_INVALID); 5693 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid2) == SPDK_BLOBID_INVALID); 5694 5695 count = SPDK_COUNTOF(ids); 5696 rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count); 5697 CU_ASSERT(rc == 0); 5698 CU_ASSERT(count == 2); 5699 CU_ASSERT(ids[0] == blobid || ids[1] == blobid); 5700 CU_ASSERT(ids[0] == snapshotid3 || ids[1] == snapshotid3); 5701 5702 /* 11. Try to create clone from read only blob */ 5703 5704 /* Mark blob as read only */ 5705 spdk_blob_set_read_only(blob); 5706 spdk_blob_sync_md(blob, blob_op_complete, NULL); 5707 poll_threads(); 5708 CU_ASSERT(g_bserrno == 0); 5709 5710 /* Create clone from read only blob */ 5711 spdk_bs_create_clone(bs, blobid, NULL, blob_op_with_id_complete, NULL); 5712 poll_threads(); 5713 CU_ASSERT(g_bserrno == 0); 5714 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5715 cloneid2 = g_blobid; 5716 5717 spdk_bs_open_blob(bs, cloneid2, blob_op_with_handle_complete, NULL); 5718 poll_threads(); 5719 CU_ASSERT(g_bserrno == 0); 5720 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 5721 clone2 = g_blob; 5722 5723 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid2) == blobid); 5724 5725 count = SPDK_COUNTOF(ids); 5726 rc = spdk_blob_get_clones(bs, blobid, ids, &count); 5727 CU_ASSERT(rc == 0); 5728 CU_ASSERT(count == 1); 5729 CU_ASSERT(ids[0] == cloneid2); 5730 5731 /* Close blobs */ 5732 5733 spdk_blob_close(clone2, blob_op_complete, NULL); 5734 poll_threads(); 5735 CU_ASSERT(g_bserrno == 0); 5736 5737 spdk_blob_close(blob, blob_op_complete, NULL); 5738 poll_threads(); 5739 CU_ASSERT(g_bserrno == 0); 5740 5741 spdk_blob_close(clone, blob_op_complete, NULL); 5742 poll_threads(); 5743 CU_ASSERT(g_bserrno == 0); 5744 5745 spdk_blob_close(snapshot2, blob_op_complete, NULL); 5746 poll_threads(); 5747 CU_ASSERT(g_bserrno == 0); 5748 5749 spdk_blob_close(snapshot3, blob_op_complete, NULL); 5750 poll_threads(); 5751 CU_ASSERT(g_bserrno == 0); 5752 5753 ut_bs_reload(&bs, &bs_opts); 5754 5755 /* Verify structure of loaded blob store */ 5756 5757 /* snapshot2 */ 5758 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid2) == SPDK_BLOBID_INVALID); 5759 5760 count = SPDK_COUNTOF(ids); 5761 rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count); 5762 CU_ASSERT(rc == 0); 5763 CU_ASSERT(count == 2); 5764 CU_ASSERT(ids[0] == blobid || ids[1] == blobid); 5765 CU_ASSERT(ids[0] == snapshotid3 || ids[1] == snapshotid3); 5766 5767 /* blob */ 5768 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid2); 5769 count = SPDK_COUNTOF(ids); 5770 rc = spdk_blob_get_clones(bs, blobid, ids, &count); 5771 CU_ASSERT(rc == 0); 5772 CU_ASSERT(count == 1); 5773 CU_ASSERT(ids[0] == cloneid2); 5774 5775 /* clone */ 5776 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid3); 5777 count = SPDK_COUNTOF(ids); 5778 rc = spdk_blob_get_clones(bs, cloneid, ids, &count); 5779 CU_ASSERT(rc == 0); 5780 CU_ASSERT(count == 0); 5781 5782 /* snapshot3 */ 5783 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid3) == snapshotid2); 5784 count = SPDK_COUNTOF(ids); 5785 rc = spdk_blob_get_clones(bs, snapshotid3, ids, &count); 5786 CU_ASSERT(rc == 0); 5787 CU_ASSERT(count == 1); 5788 CU_ASSERT(ids[0] == cloneid); 5789 5790 /* clone2 */ 5791 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid2) == blobid); 5792 count = SPDK_COUNTOF(ids); 5793 rc = spdk_blob_get_clones(bs, cloneid2, ids, &count); 5794 CU_ASSERT(rc == 0); 5795 CU_ASSERT(count == 0); 5796 5797 /* Try to delete all blobs in the worse possible order */ 5798 5799 spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL); 5800 poll_threads(); 5801 CU_ASSERT(g_bserrno != 0); 5802 5803 spdk_bs_delete_blob(bs, snapshotid3, blob_op_complete, NULL); 5804 poll_threads(); 5805 CU_ASSERT(g_bserrno == 0); 5806 5807 spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL); 5808 poll_threads(); 5809 CU_ASSERT(g_bserrno != 0); 5810 5811 spdk_bs_delete_blob(bs, cloneid, blob_op_complete, NULL); 5812 poll_threads(); 5813 CU_ASSERT(g_bserrno == 0); 5814 5815 spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL); 5816 poll_threads(); 5817 CU_ASSERT(g_bserrno == 0); 5818 5819 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); 5820 poll_threads(); 5821 CU_ASSERT(g_bserrno == 0); 5822 5823 spdk_bs_delete_blob(bs, cloneid2, blob_op_complete, NULL); 5824 poll_threads(); 5825 CU_ASSERT(g_bserrno == 0); 5826 5827 spdk_bs_unload(bs, bs_op_complete, NULL); 5828 poll_threads(); 5829 CU_ASSERT(g_bserrno == 0); 5830 5831 g_bs = NULL; 5832 } 5833 5834 /** 5835 * Snapshot-clones relation test 3 5836 * 5837 * snapshot0 5838 * | 5839 * snapshot1 5840 * | 5841 * snapshot2 5842 * | 5843 * blob 5844 */ 5845 static void 5846 blob_relations3(void) 5847 { 5848 struct spdk_blob_store *bs; 5849 struct spdk_bs_dev *dev; 5850 struct spdk_io_channel *channel; 5851 struct spdk_bs_opts bs_opts; 5852 struct spdk_blob_opts opts; 5853 struct spdk_blob *blob; 5854 spdk_blob_id blobid, snapshotid0, snapshotid1, snapshotid2; 5855 5856 dev = init_dev(); 5857 spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); 5858 snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE"); 5859 5860 spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL); 5861 poll_threads(); 5862 CU_ASSERT(g_bserrno == 0); 5863 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 5864 bs = g_bs; 5865 5866 channel = spdk_bs_alloc_io_channel(bs); 5867 SPDK_CU_ASSERT_FATAL(channel != NULL); 5868 5869 /* 1. Create blob with 10 clusters */ 5870 ut_spdk_blob_opts_init(&opts); 5871 opts.num_clusters = 10; 5872 5873 blob = ut_blob_create_and_open(bs, &opts); 5874 blobid = spdk_blob_get_id(blob); 5875 5876 /* 2. Create snapshot0 */ 5877 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 5878 poll_threads(); 5879 CU_ASSERT(g_bserrno == 0); 5880 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5881 snapshotid0 = g_blobid; 5882 5883 /* 3. Create snapshot1 */ 5884 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 5885 poll_threads(); 5886 CU_ASSERT(g_bserrno == 0); 5887 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5888 snapshotid1 = g_blobid; 5889 5890 /* 4. Create snapshot2 */ 5891 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 5892 poll_threads(); 5893 CU_ASSERT(g_bserrno == 0); 5894 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 5895 snapshotid2 = g_blobid; 5896 5897 /* 5. Decouple blob */ 5898 spdk_bs_blob_decouple_parent(bs, channel, blobid, blob_op_complete, NULL); 5899 poll_threads(); 5900 CU_ASSERT(g_bserrno == 0); 5901 5902 /* 6. Decouple snapshot2. Make sure updating md of snapshot2 is possible */ 5903 spdk_bs_blob_decouple_parent(bs, channel, snapshotid2, blob_op_complete, NULL); 5904 poll_threads(); 5905 CU_ASSERT(g_bserrno == 0); 5906 5907 /* 7. Delete blob */ 5908 spdk_blob_close(blob, blob_op_complete, NULL); 5909 poll_threads(); 5910 CU_ASSERT(g_bserrno == 0); 5911 5912 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); 5913 poll_threads(); 5914 CU_ASSERT(g_bserrno == 0); 5915 5916 /* 8. Delete snapshot2. 5917 * If md of snapshot 2 was updated, it should be possible to delete it */ 5918 spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL); 5919 poll_threads(); 5920 CU_ASSERT(g_bserrno == 0); 5921 5922 /* Remove remaining blobs and unload bs */ 5923 spdk_bs_delete_blob(bs, snapshotid1, blob_op_complete, NULL); 5924 poll_threads(); 5925 CU_ASSERT(g_bserrno == 0); 5926 5927 spdk_bs_delete_blob(bs, snapshotid0, blob_op_complete, NULL); 5928 poll_threads(); 5929 CU_ASSERT(g_bserrno == 0); 5930 5931 spdk_bs_free_io_channel(channel); 5932 poll_threads(); 5933 5934 spdk_bs_unload(bs, bs_op_complete, NULL); 5935 poll_threads(); 5936 CU_ASSERT(g_bserrno == 0); 5937 5938 g_bs = NULL; 5939 } 5940 5941 static void 5942 blobstore_clean_power_failure(void) 5943 { 5944 struct spdk_blob_store *bs; 5945 struct spdk_blob *blob; 5946 struct spdk_power_failure_thresholds thresholds = {}; 5947 bool clean = false; 5948 struct spdk_bs_super_block *super = (struct spdk_bs_super_block *)&g_dev_buffer[0]; 5949 struct spdk_bs_super_block super_copy = {}; 5950 5951 thresholds.general_threshold = 1; 5952 while (!clean) { 5953 /* Create bs and blob */ 5954 suite_blob_setup(); 5955 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 5956 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 5957 bs = g_bs; 5958 blob = g_blob; 5959 5960 /* Super block should not change for rest of the UT, 5961 * save it and compare later. */ 5962 memcpy(&super_copy, super, sizeof(struct spdk_bs_super_block)); 5963 SPDK_CU_ASSERT_FATAL(super->clean == 0); 5964 SPDK_CU_ASSERT_FATAL(bs->clean == 0); 5965 5966 /* Force bs/super block in a clean state. 5967 * Along with marking blob dirty, to cause blob persist. */ 5968 blob->state = SPDK_BLOB_STATE_DIRTY; 5969 bs->clean = 1; 5970 super->clean = 1; 5971 super->crc = blob_md_page_calc_crc(super); 5972 5973 g_bserrno = -1; 5974 dev_set_power_failure_thresholds(thresholds); 5975 spdk_blob_sync_md(blob, blob_op_complete, NULL); 5976 poll_threads(); 5977 dev_reset_power_failure_event(); 5978 5979 if (g_bserrno == 0) { 5980 /* After successful md sync, both bs and super block 5981 * should be marked as not clean. */ 5982 SPDK_CU_ASSERT_FATAL(bs->clean == 0); 5983 SPDK_CU_ASSERT_FATAL(super->clean == 0); 5984 clean = true; 5985 } 5986 5987 /* Depending on the point of failure, super block was either updated or not. */ 5988 super_copy.clean = super->clean; 5989 super_copy.crc = blob_md_page_calc_crc(&super_copy); 5990 /* Compare that the values in super block remained unchanged. */ 5991 SPDK_CU_ASSERT_FATAL(!memcmp(&super_copy, super, sizeof(struct spdk_bs_super_block))); 5992 5993 /* Delete blob and unload bs */ 5994 suite_blob_cleanup(); 5995 5996 thresholds.general_threshold++; 5997 } 5998 } 5999 6000 static void 6001 blob_delete_snapshot_power_failure(void) 6002 { 6003 struct spdk_bs_dev *dev; 6004 struct spdk_blob_store *bs; 6005 struct spdk_blob_opts opts; 6006 struct spdk_blob *blob, *snapshot; 6007 struct spdk_power_failure_thresholds thresholds = {}; 6008 spdk_blob_id blobid, snapshotid; 6009 const void *value; 6010 size_t value_len; 6011 size_t count; 6012 spdk_blob_id ids[3] = {}; 6013 int rc; 6014 bool deleted = false; 6015 int delete_snapshot_bserrno = -1; 6016 6017 thresholds.general_threshold = 1; 6018 while (!deleted) { 6019 dev = init_dev(); 6020 6021 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 6022 poll_threads(); 6023 CU_ASSERT(g_bserrno == 0); 6024 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 6025 bs = g_bs; 6026 6027 /* Create blob */ 6028 ut_spdk_blob_opts_init(&opts); 6029 opts.num_clusters = 10; 6030 6031 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 6032 poll_threads(); 6033 CU_ASSERT(g_bserrno == 0); 6034 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 6035 blobid = g_blobid; 6036 6037 /* Create snapshot */ 6038 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 6039 poll_threads(); 6040 CU_ASSERT(g_bserrno == 0); 6041 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 6042 snapshotid = g_blobid; 6043 SPDK_CU_ASSERT_FATAL(spdk_bit_pool_is_allocated(bs->used_clusters, 1)); 6044 SPDK_CU_ASSERT_FATAL(!spdk_bit_pool_is_allocated(bs->used_clusters, 11)); 6045 6046 dev_set_power_failure_thresholds(thresholds); 6047 6048 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL); 6049 poll_threads(); 6050 delete_snapshot_bserrno = g_bserrno; 6051 6052 /* Do not shut down cleanly. Assumption is that after snapshot deletion 6053 * reports success, changes to both blobs should already persisted. */ 6054 dev_reset_power_failure_event(); 6055 ut_bs_dirty_load(&bs, NULL); 6056 6057 SPDK_CU_ASSERT_FATAL(spdk_bit_pool_is_allocated(bs->used_clusters, 1)); 6058 SPDK_CU_ASSERT_FATAL(!spdk_bit_pool_is_allocated(bs->used_clusters, 11)); 6059 6060 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 6061 poll_threads(); 6062 CU_ASSERT(g_bserrno == 0); 6063 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 6064 blob = g_blob; 6065 SPDK_CU_ASSERT_FATAL(spdk_blob_is_thin_provisioned(blob) == true); 6066 6067 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 6068 poll_threads(); 6069 6070 if (g_bserrno == 0) { 6071 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 6072 snapshot = g_blob; 6073 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid); 6074 count = SPDK_COUNTOF(ids); 6075 rc = spdk_blob_get_clones(bs, snapshotid, ids, &count); 6076 CU_ASSERT(rc == 0); 6077 CU_ASSERT(count == 1); 6078 CU_ASSERT(ids[0] == blobid); 6079 rc = spdk_blob_get_xattr_value(snapshot, SNAPSHOT_PENDING_REMOVAL, &value, &value_len); 6080 CU_ASSERT(rc != 0); 6081 SPDK_CU_ASSERT_FATAL(spdk_blob_is_thin_provisioned(snapshot) == false); 6082 6083 spdk_blob_close(snapshot, blob_op_complete, NULL); 6084 poll_threads(); 6085 CU_ASSERT(g_bserrno == 0); 6086 } else { 6087 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == SPDK_BLOBID_INVALID); 6088 /* Snapshot might have been left in unrecoverable state, so it does not open. 6089 * Yet delete might perform further changes to the clone after that. 6090 * This UT should test until snapshot is deleted and delete call succeeds. */ 6091 if (delete_snapshot_bserrno == 0) { 6092 deleted = true; 6093 } 6094 } 6095 6096 spdk_blob_close(blob, blob_op_complete, NULL); 6097 poll_threads(); 6098 CU_ASSERT(g_bserrno == 0); 6099 6100 spdk_bs_unload(bs, bs_op_complete, NULL); 6101 poll_threads(); 6102 CU_ASSERT(g_bserrno == 0); 6103 6104 thresholds.general_threshold++; 6105 } 6106 } 6107 6108 static void 6109 blob_create_snapshot_power_failure(void) 6110 { 6111 struct spdk_blob_store *bs = g_bs; 6112 struct spdk_bs_dev *dev; 6113 struct spdk_blob_opts opts; 6114 struct spdk_blob *blob, *snapshot; 6115 struct spdk_power_failure_thresholds thresholds = {}; 6116 spdk_blob_id blobid, snapshotid; 6117 const void *value; 6118 size_t value_len; 6119 size_t count; 6120 spdk_blob_id ids[3] = {}; 6121 int rc; 6122 bool created = false; 6123 int create_snapshot_bserrno = -1; 6124 6125 thresholds.general_threshold = 1; 6126 while (!created) { 6127 dev = init_dev(); 6128 6129 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 6130 poll_threads(); 6131 CU_ASSERT(g_bserrno == 0); 6132 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 6133 bs = g_bs; 6134 6135 /* Create blob */ 6136 ut_spdk_blob_opts_init(&opts); 6137 opts.num_clusters = 10; 6138 6139 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 6140 poll_threads(); 6141 CU_ASSERT(g_bserrno == 0); 6142 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 6143 blobid = g_blobid; 6144 SPDK_CU_ASSERT_FATAL(spdk_bit_pool_is_allocated(bs->used_clusters, 1)); 6145 SPDK_CU_ASSERT_FATAL(!spdk_bit_pool_is_allocated(bs->used_clusters, 11)); 6146 6147 dev_set_power_failure_thresholds(thresholds); 6148 6149 /* Create snapshot */ 6150 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 6151 poll_threads(); 6152 create_snapshot_bserrno = g_bserrno; 6153 snapshotid = g_blobid; 6154 SPDK_CU_ASSERT_FATAL(spdk_bit_pool_is_allocated(bs->used_clusters, 1)); 6155 SPDK_CU_ASSERT_FATAL(!spdk_bit_pool_is_allocated(bs->used_clusters, 11)); 6156 6157 /* Do not shut down cleanly. Assumption is that after create snapshot 6158 * reports success, both blobs should be power-fail safe. */ 6159 dev_reset_power_failure_event(); 6160 ut_bs_dirty_load(&bs, NULL); 6161 6162 SPDK_CU_ASSERT_FATAL(spdk_bit_pool_is_allocated(bs->used_clusters, 1)); 6163 SPDK_CU_ASSERT_FATAL(!spdk_bit_pool_is_allocated(bs->used_clusters, 11)); 6164 6165 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 6166 poll_threads(); 6167 CU_ASSERT(g_bserrno == 0); 6168 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 6169 blob = g_blob; 6170 6171 if (snapshotid != SPDK_BLOBID_INVALID) { 6172 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 6173 poll_threads(); 6174 } 6175 6176 if ((snapshotid != SPDK_BLOBID_INVALID) && (g_bserrno == 0)) { 6177 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 6178 snapshot = g_blob; 6179 SPDK_CU_ASSERT_FATAL(spdk_blob_is_thin_provisioned(blob) == true); 6180 SPDK_CU_ASSERT_FATAL(spdk_blob_is_thin_provisioned(snapshot) == false); 6181 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid); 6182 count = SPDK_COUNTOF(ids); 6183 rc = spdk_blob_get_clones(bs, snapshotid, ids, &count); 6184 CU_ASSERT(rc == 0); 6185 CU_ASSERT(count == 1); 6186 CU_ASSERT(ids[0] == blobid); 6187 rc = spdk_blob_get_xattr_value(snapshot, SNAPSHOT_IN_PROGRESS, &value, &value_len); 6188 CU_ASSERT(rc != 0); 6189 6190 spdk_blob_close(snapshot, blob_op_complete, NULL); 6191 poll_threads(); 6192 CU_ASSERT(g_bserrno == 0); 6193 if (create_snapshot_bserrno == 0) { 6194 created = true; 6195 } 6196 } else { 6197 CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == SPDK_BLOBID_INVALID); 6198 SPDK_CU_ASSERT_FATAL(spdk_blob_is_thin_provisioned(blob) == false); 6199 } 6200 6201 spdk_blob_close(blob, blob_op_complete, NULL); 6202 poll_threads(); 6203 CU_ASSERT(g_bserrno == 0); 6204 6205 spdk_bs_unload(bs, bs_op_complete, NULL); 6206 poll_threads(); 6207 CU_ASSERT(g_bserrno == 0); 6208 6209 thresholds.general_threshold++; 6210 } 6211 } 6212 6213 static void 6214 test_io_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel) 6215 { 6216 uint8_t payload_ff[64 * 512]; 6217 uint8_t payload_aa[64 * 512]; 6218 uint8_t payload_00[64 * 512]; 6219 uint8_t *cluster0, *cluster1; 6220 6221 memset(payload_ff, 0xFF, sizeof(payload_ff)); 6222 memset(payload_aa, 0xAA, sizeof(payload_aa)); 6223 memset(payload_00, 0x00, sizeof(payload_00)); 6224 6225 /* Try to perform I/O with io unit = 512 */ 6226 spdk_blob_io_write(blob, channel, payload_ff, 0, 1, blob_op_complete, NULL); 6227 poll_threads(); 6228 CU_ASSERT(g_bserrno == 0); 6229 6230 /* If thin provisioned is set cluster should be allocated now */ 6231 SPDK_CU_ASSERT_FATAL(blob->active.clusters[0] != 0); 6232 cluster0 = &g_dev_buffer[blob->active.clusters[0] * dev->blocklen]; 6233 6234 /* Each character 0-F symbolizes single io_unit containing 512 bytes block filled with that character. 6235 * Each page is separated by |. Whole block [...] symbolizes one cluster (containing 4 pages). */ 6236 /* cluster0: [ F000 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */ 6237 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6238 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 31 * 512) == 0); 6239 6240 /* Verify write with offset on first page */ 6241 spdk_blob_io_write(blob, channel, payload_ff, 2, 1, blob_op_complete, NULL); 6242 poll_threads(); 6243 CU_ASSERT(g_bserrno == 0); 6244 6245 /* cluster0: [ F0F0 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */ 6246 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6247 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0); 6248 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0); 6249 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0); 6250 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_00, 28 * 512) == 0); 6251 6252 /* Verify write with offset on first page */ 6253 spdk_blob_io_write(blob, channel, payload_ff, 4, 4, blob_op_complete, NULL); 6254 poll_threads(); 6255 6256 /* cluster0: [ F0F0 FFFF | 0000 0000 | 0000 0000 | 0000 0000 ] */ 6257 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6258 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0); 6259 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0); 6260 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0); 6261 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_ff, 4 * 512) == 0); 6262 CU_ASSERT(memcmp(cluster0 + 8 * 512, payload_00, 24 * 512) == 0); 6263 6264 /* Verify write with offset on second page */ 6265 spdk_blob_io_write(blob, channel, payload_ff, 8, 4, blob_op_complete, NULL); 6266 poll_threads(); 6267 6268 /* cluster0: [ F0F0 FFFF | FFFF 0000 | 0000 0000 | 0000 0000 ] */ 6269 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6270 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0); 6271 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0); 6272 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0); 6273 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_ff, 8 * 512) == 0); 6274 CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 20 * 512) == 0); 6275 6276 /* Verify write across multiple pages */ 6277 spdk_blob_io_write(blob, channel, payload_aa, 4, 8, blob_op_complete, NULL); 6278 poll_threads(); 6279 6280 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 0000 ] */ 6281 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6282 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0); 6283 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0); 6284 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0); 6285 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0); 6286 CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 20 * 512) == 0); 6287 6288 /* Verify write across multiple clusters */ 6289 spdk_blob_io_write(blob, channel, payload_ff, 28, 8, blob_op_complete, NULL); 6290 poll_threads(); 6291 6292 SPDK_CU_ASSERT_FATAL(blob->active.clusters[1] != 0); 6293 cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen]; 6294 6295 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ] 6296 * cluster1: [ FFFF 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */ 6297 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6298 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0); 6299 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0); 6300 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0); 6301 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0); 6302 CU_ASSERT(memcmp(cluster0 + 28 * 512, payload_ff, 4 * 512) == 0); 6303 6304 CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_ff, 4 * 512) == 0); 6305 CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, 28 * 512) == 0); 6306 6307 /* Verify write to second cluster */ 6308 spdk_blob_io_write(blob, channel, payload_ff, 32 + 12, 2, blob_op_complete, NULL); 6309 poll_threads(); 6310 6311 SPDK_CU_ASSERT_FATAL(blob->active.clusters[1] != 0); 6312 cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen]; 6313 6314 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ] 6315 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] */ 6316 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6317 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0); 6318 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0); 6319 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0); 6320 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0); 6321 CU_ASSERT(memcmp(cluster0 + 28 * 512, payload_ff, 4 * 512) == 0); 6322 6323 CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_ff, 4 * 512) == 0); 6324 CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, 8 * 512) == 0); 6325 CU_ASSERT(memcmp(cluster1 + 12 * 512, payload_ff, 2 * 512) == 0); 6326 CU_ASSERT(memcmp(cluster1 + 14 * 512, payload_00, 18 * 512) == 0); 6327 } 6328 6329 static void 6330 test_io_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel) 6331 { 6332 uint8_t payload_read[64 * 512]; 6333 uint8_t payload_ff[64 * 512]; 6334 uint8_t payload_aa[64 * 512]; 6335 uint8_t payload_00[64 * 512]; 6336 6337 memset(payload_ff, 0xFF, sizeof(payload_ff)); 6338 memset(payload_aa, 0xAA, sizeof(payload_aa)); 6339 memset(payload_00, 0x00, sizeof(payload_00)); 6340 6341 /* Read only first io unit */ 6342 /* cluster0: [ (F)0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ] 6343 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] 6344 * payload_read: F000 0000 | 0000 0000 ... */ 6345 memset(payload_read, 0x00, sizeof(payload_read)); 6346 spdk_blob_io_read(blob, channel, payload_read, 0, 1, blob_op_complete, NULL); 6347 poll_threads(); 6348 CU_ASSERT(g_bserrno == 0); 6349 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0); 6350 CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 31 * 512) == 0); 6351 6352 /* Read four io_units starting from offset = 2 6353 * cluster0: [ F0(F0 AA)AA | AAAA 0000 | 0000 0000 | 0000 FFFF ] 6354 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] 6355 * payload_read: F0AA 0000 | 0000 0000 ... */ 6356 6357 memset(payload_read, 0x00, sizeof(payload_read)); 6358 spdk_blob_io_read(blob, channel, payload_read, 2, 4, blob_op_complete, NULL); 6359 poll_threads(); 6360 CU_ASSERT(g_bserrno == 0); 6361 6362 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0); 6363 CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 512) == 0); 6364 CU_ASSERT(memcmp(payload_read + 2 * 512, payload_aa, 512) == 0); 6365 CU_ASSERT(memcmp(payload_read + 3 * 512, payload_aa, 512) == 0); 6366 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 28 * 512) == 0); 6367 6368 /* Read eight io_units across multiple pages 6369 * cluster0: [ F0F0 (AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ] 6370 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] 6371 * payload_read: AAAA AAAA | 0000 0000 ... */ 6372 memset(payload_read, 0x00, sizeof(payload_read)); 6373 spdk_blob_io_read(blob, channel, payload_read, 4, 8, blob_op_complete, NULL); 6374 poll_threads(); 6375 CU_ASSERT(g_bserrno == 0); 6376 6377 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_aa, 8 * 512) == 0); 6378 CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, 24 * 512) == 0); 6379 6380 /* Read eight io_units across multiple clusters 6381 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 (FFFF ] 6382 * cluster1: [ FFFF) 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] 6383 * payload_read: FFFF FFFF | 0000 0000 ... */ 6384 memset(payload_read, 0x00, sizeof(payload_read)); 6385 spdk_blob_io_read(blob, channel, payload_read, 28, 8, blob_op_complete, NULL); 6386 poll_threads(); 6387 CU_ASSERT(g_bserrno == 0); 6388 6389 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 8 * 512) == 0); 6390 CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, 24 * 512) == 0); 6391 6392 /* Read four io_units from second cluster 6393 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ] 6394 * cluster1: [ FFFF 0000 | 00(00 FF)00 | 0000 0000 | 0000 0000 ] 6395 * payload_read: 00FF 0000 | 0000 0000 ... */ 6396 memset(payload_read, 0x00, sizeof(payload_read)); 6397 spdk_blob_io_read(blob, channel, payload_read, 32 + 10, 4, blob_op_complete, NULL); 6398 poll_threads(); 6399 CU_ASSERT(g_bserrno == 0); 6400 6401 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_00, 2 * 512) == 0); 6402 CU_ASSERT(memcmp(payload_read + 2 * 512, payload_ff, 2 * 512) == 0); 6403 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 28 * 512) == 0); 6404 6405 /* Read second cluster 6406 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ] 6407 * cluster1: [ (FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ] 6408 * payload_read: FFFF 0000 | 0000 FF00 ... */ 6409 memset(payload_read, 0x00, sizeof(payload_read)); 6410 spdk_blob_io_read(blob, channel, payload_read, 32, 32, blob_op_complete, NULL); 6411 poll_threads(); 6412 CU_ASSERT(g_bserrno == 0); 6413 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 4 * 512) == 0); 6414 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 8 * 512) == 0); 6415 CU_ASSERT(memcmp(payload_read + 12 * 512, payload_ff, 2 * 512) == 0); 6416 CU_ASSERT(memcmp(payload_read + 14 * 512, payload_00, 18 * 512) == 0); 6417 6418 /* Read whole two clusters 6419 * cluster0: [ (F0F0 AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ] 6420 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ] */ 6421 memset(payload_read, 0x00, sizeof(payload_read)); 6422 spdk_blob_io_read(blob, channel, payload_read, 0, 64, blob_op_complete, NULL); 6423 poll_threads(); 6424 CU_ASSERT(g_bserrno == 0); 6425 6426 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0); 6427 CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 512) == 0); 6428 CU_ASSERT(memcmp(payload_read + 2 * 512, payload_ff, 512) == 0); 6429 CU_ASSERT(memcmp(payload_read + 3 * 512, payload_00, 512) == 0); 6430 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_aa, 8 * 512) == 0); 6431 CU_ASSERT(memcmp(payload_read + 28 * 512, payload_ff, 4 * 512) == 0); 6432 6433 CU_ASSERT(memcmp(payload_read + (32 + 0) * 512, payload_ff, 4 * 512) == 0); 6434 CU_ASSERT(memcmp(payload_read + (32 + 4) * 512, payload_00, 8 * 512) == 0); 6435 CU_ASSERT(memcmp(payload_read + (32 + 12) * 512, payload_ff, 2 * 512) == 0); 6436 CU_ASSERT(memcmp(payload_read + (32 + 14) * 512, payload_00, 18 * 512) == 0); 6437 } 6438 6439 6440 static void 6441 test_io_unmap(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel) 6442 { 6443 uint8_t payload_ff[64 * 512]; 6444 uint8_t payload_aa[64 * 512]; 6445 uint8_t payload_00[64 * 512]; 6446 uint8_t *cluster0, *cluster1; 6447 6448 memset(payload_ff, 0xFF, sizeof(payload_ff)); 6449 memset(payload_aa, 0xAA, sizeof(payload_aa)); 6450 memset(payload_00, 0x00, sizeof(payload_00)); 6451 6452 cluster0 = &g_dev_buffer[blob->active.clusters[0] * dev->blocklen]; 6453 cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen]; 6454 6455 /* Unmap */ 6456 spdk_blob_io_unmap(blob, channel, 0, 64, blob_op_complete, NULL); 6457 poll_threads(); 6458 6459 CU_ASSERT(g_bserrno == 0); 6460 6461 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_00, 32 * 512) == 0); 6462 CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_00, 32 * 512) == 0); 6463 } 6464 6465 static void 6466 test_io_zeroes(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel) 6467 { 6468 uint8_t payload_ff[64 * 512]; 6469 uint8_t payload_aa[64 * 512]; 6470 uint8_t payload_00[64 * 512]; 6471 uint8_t *cluster0, *cluster1; 6472 6473 memset(payload_ff, 0xFF, sizeof(payload_ff)); 6474 memset(payload_aa, 0xAA, sizeof(payload_aa)); 6475 memset(payload_00, 0x00, sizeof(payload_00)); 6476 6477 cluster0 = &g_dev_buffer[blob->active.clusters[0] * dev->blocklen]; 6478 cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen]; 6479 6480 /* Write zeroes */ 6481 spdk_blob_io_write_zeroes(blob, channel, 0, 64, blob_op_complete, NULL); 6482 poll_threads(); 6483 6484 CU_ASSERT(g_bserrno == 0); 6485 6486 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_00, 32 * 512) == 0); 6487 CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_00, 32 * 512) == 0); 6488 } 6489 6490 static inline void 6491 test_blob_io_writev(struct spdk_blob *blob, struct spdk_io_channel *channel, 6492 struct iovec *iov, int iovcnt, uint64_t offset, uint64_t length, 6493 spdk_blob_op_complete cb_fn, void *cb_arg, struct spdk_blob_ext_io_opts *io_opts) 6494 { 6495 if (io_opts) { 6496 g_dev_writev_ext_called = false; 6497 memset(&g_blob_ext_io_opts, 0, sizeof(g_blob_ext_io_opts)); 6498 spdk_blob_io_writev_ext(blob, channel, iov, iovcnt, offset, length, blob_op_complete, NULL, 6499 io_opts); 6500 } else { 6501 spdk_blob_io_writev(blob, channel, iov, iovcnt, offset, length, blob_op_complete, NULL); 6502 } 6503 poll_threads(); 6504 CU_ASSERT(g_bserrno == 0); 6505 if (io_opts) { 6506 CU_ASSERT(g_dev_writev_ext_called); 6507 CU_ASSERT(memcmp(io_opts, &g_blob_ext_io_opts, sizeof(g_blob_ext_io_opts)) == 0); 6508 } 6509 } 6510 6511 static void 6512 test_iov_write(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel, 6513 bool ext_api) 6514 { 6515 uint8_t payload_ff[64 * 512]; 6516 uint8_t payload_aa[64 * 512]; 6517 uint8_t payload_00[64 * 512]; 6518 uint8_t *cluster0, *cluster1; 6519 struct iovec iov[4]; 6520 struct spdk_blob_ext_io_opts ext_opts = { 6521 .memory_domain = (struct spdk_memory_domain *)0xfeedbeef, 6522 .memory_domain_ctx = (void *)0xf00df00d, 6523 .size = sizeof(struct spdk_blob_ext_io_opts), 6524 .user_ctx = (void *)123, 6525 }; 6526 6527 memset(payload_ff, 0xFF, sizeof(payload_ff)); 6528 memset(payload_aa, 0xAA, sizeof(payload_aa)); 6529 memset(payload_00, 0x00, sizeof(payload_00)); 6530 6531 /* Try to perform I/O with io unit = 512 */ 6532 iov[0].iov_base = payload_ff; 6533 iov[0].iov_len = 1 * 512; 6534 6535 test_blob_io_writev(blob, channel, iov, 1, 0, 1, blob_op_complete, NULL, 6536 ext_api ? &ext_opts : NULL); 6537 6538 /* If thin provisioned is set cluster should be allocated now */ 6539 SPDK_CU_ASSERT_FATAL(blob->active.clusters[0] != 0); 6540 cluster0 = &g_dev_buffer[blob->active.clusters[0] * dev->blocklen]; 6541 6542 /* Each character 0-F symbolizes single io_unit containing 512 bytes block filled with that character. 6543 * Each page is separated by |. Whole block [...] symbolizes one cluster (containing 4 pages). */ 6544 /* cluster0: [ F000 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */ 6545 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6546 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 31 * 512) == 0); 6547 6548 /* Verify write with offset on first page */ 6549 iov[0].iov_base = payload_ff; 6550 iov[0].iov_len = 1 * 512; 6551 6552 test_blob_io_writev(blob, channel, iov, 1, 2, 1, blob_op_complete, NULL, 6553 ext_api ? &ext_opts : NULL); 6554 6555 /* cluster0: [ F0F0 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */ 6556 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6557 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0); 6558 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0); 6559 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0); 6560 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_00, 28 * 512) == 0); 6561 6562 /* Verify write with offset on first page */ 6563 iov[0].iov_base = payload_ff; 6564 iov[0].iov_len = 4 * 512; 6565 spdk_blob_io_writev(blob, channel, iov, 1, 4, 4, blob_op_complete, NULL); 6566 poll_threads(); 6567 6568 /* cluster0: [ F0F0 FFFF | 0000 0000 | 0000 0000 | 0000 0000 ] */ 6569 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6570 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0); 6571 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0); 6572 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0); 6573 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_ff, 4 * 512) == 0); 6574 CU_ASSERT(memcmp(cluster0 + 8 * 512, payload_00, 24 * 512) == 0); 6575 6576 /* Verify write with offset on second page */ 6577 iov[0].iov_base = payload_ff; 6578 iov[0].iov_len = 4 * 512; 6579 spdk_blob_io_writev(blob, channel, iov, 1, 8, 4, blob_op_complete, NULL); 6580 poll_threads(); 6581 6582 /* cluster0: [ F0F0 FFFF | FFFF 0000 | 0000 0000 | 0000 0000 ] */ 6583 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6584 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0); 6585 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0); 6586 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0); 6587 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_ff, 8 * 512) == 0); 6588 CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 20 * 512) == 0); 6589 6590 /* Verify write across multiple pages */ 6591 iov[0].iov_base = payload_aa; 6592 iov[0].iov_len = 8 * 512; 6593 6594 test_blob_io_writev(blob, channel, iov, 1, 4, 8, blob_op_complete, NULL, 6595 ext_api ? &ext_opts : NULL); 6596 6597 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 0000 ] */ 6598 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6599 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0); 6600 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0); 6601 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0); 6602 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0); 6603 CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 20 * 512) == 0); 6604 6605 /* Verify write across multiple clusters */ 6606 6607 iov[0].iov_base = payload_ff; 6608 iov[0].iov_len = 8 * 512; 6609 6610 test_blob_io_writev(blob, channel, iov, 1, 28, 8, blob_op_complete, NULL, 6611 ext_api ? &ext_opts : NULL); 6612 6613 SPDK_CU_ASSERT_FATAL(blob->active.clusters[1] != 0); 6614 cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen]; 6615 6616 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ] 6617 * cluster1: [ FFFF 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */ 6618 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6619 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0); 6620 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0); 6621 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0); 6622 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0); 6623 CU_ASSERT(memcmp(cluster0 + 12 * 512, payload_00, 16 * 512) == 0); 6624 CU_ASSERT(memcmp(cluster0 + 28 * 512, payload_ff, 4 * 512) == 0); 6625 6626 CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_ff, 4 * 512) == 0); 6627 CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, 28 * 512) == 0); 6628 6629 /* Verify write to second cluster */ 6630 6631 iov[0].iov_base = payload_ff; 6632 iov[0].iov_len = 2 * 512; 6633 6634 test_blob_io_writev(blob, channel, iov, 1, 32 + 12, 2, blob_op_complete, NULL, 6635 ext_api ? &ext_opts : NULL); 6636 6637 SPDK_CU_ASSERT_FATAL(blob->active.clusters[1] != 0); 6638 cluster1 = &g_dev_buffer[blob->active.clusters[1] * dev->blocklen]; 6639 6640 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ] 6641 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] */ 6642 CU_ASSERT(memcmp(cluster0 + 0 * 512, payload_ff, 512) == 0); 6643 CU_ASSERT(memcmp(cluster0 + 1 * 512, payload_00, 512) == 0); 6644 CU_ASSERT(memcmp(cluster0 + 2 * 512, payload_ff, 512) == 0); 6645 CU_ASSERT(memcmp(cluster0 + 3 * 512, payload_00, 512) == 0); 6646 CU_ASSERT(memcmp(cluster0 + 4 * 512, payload_aa, 8 * 512) == 0); 6647 CU_ASSERT(memcmp(cluster0 + 28 * 512, payload_ff, 4 * 512) == 0); 6648 6649 CU_ASSERT(memcmp(cluster1 + 0 * 512, payload_ff, 4 * 512) == 0); 6650 CU_ASSERT(memcmp(cluster1 + 4 * 512, payload_00, 8 * 512) == 0); 6651 CU_ASSERT(memcmp(cluster1 + 12 * 512, payload_ff, 2 * 512) == 0); 6652 CU_ASSERT(memcmp(cluster1 + 14 * 512, payload_00, 18 * 512) == 0); 6653 } 6654 6655 static inline void 6656 test_blob_io_readv(struct spdk_blob *blob, struct spdk_io_channel *channel, 6657 struct iovec *iov, int iovcnt, uint64_t offset, uint64_t length, 6658 spdk_blob_op_complete cb_fn, void *cb_arg, struct spdk_blob_ext_io_opts *io_opts) 6659 { 6660 if (io_opts) { 6661 g_dev_readv_ext_called = false; 6662 memset(&g_blob_ext_io_opts, 0, sizeof(g_blob_ext_io_opts)); 6663 spdk_blob_io_readv_ext(blob, channel, iov, iovcnt, offset, length, blob_op_complete, NULL, io_opts); 6664 } else { 6665 spdk_blob_io_readv(blob, channel, iov, iovcnt, offset, length, blob_op_complete, NULL); 6666 } 6667 poll_threads(); 6668 CU_ASSERT(g_bserrno == 0); 6669 if (io_opts) { 6670 CU_ASSERT(g_dev_readv_ext_called); 6671 CU_ASSERT(memcmp(io_opts, &g_blob_ext_io_opts, sizeof(g_blob_ext_io_opts)) == 0); 6672 } 6673 } 6674 6675 static void 6676 test_iov_read(struct spdk_bs_dev *dev, struct spdk_blob *blob, struct spdk_io_channel *channel, 6677 bool ext_api) 6678 { 6679 uint8_t payload_read[64 * 512]; 6680 uint8_t payload_ff[64 * 512]; 6681 uint8_t payload_aa[64 * 512]; 6682 uint8_t payload_00[64 * 512]; 6683 struct iovec iov[4]; 6684 struct spdk_blob_ext_io_opts ext_opts = { 6685 .memory_domain = (struct spdk_memory_domain *)0xfeedbeef, 6686 .memory_domain_ctx = (void *)0xf00df00d, 6687 .size = sizeof(struct spdk_blob_ext_io_opts), 6688 .user_ctx = (void *)123, 6689 }; 6690 6691 memset(payload_ff, 0xFF, sizeof(payload_ff)); 6692 memset(payload_aa, 0xAA, sizeof(payload_aa)); 6693 memset(payload_00, 0x00, sizeof(payload_00)); 6694 6695 /* Read only first io unit */ 6696 /* cluster0: [ (F)0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ] 6697 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] 6698 * payload_read: F000 0000 | 0000 0000 ... */ 6699 memset(payload_read, 0x00, sizeof(payload_read)); 6700 iov[0].iov_base = payload_read; 6701 iov[0].iov_len = 1 * 512; 6702 6703 test_blob_io_readv(blob, channel, iov, 1, 0, 1, blob_op_complete, NULL, ext_api ? &ext_opts : NULL); 6704 6705 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0); 6706 CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 31 * 512) == 0); 6707 6708 /* Read four io_units starting from offset = 2 6709 * cluster0: [ F0(F0 AA)AA | AAAA 0000 | 0000 0000 | 0000 FFFF ] 6710 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] 6711 * payload_read: F0AA 0000 | 0000 0000 ... */ 6712 6713 memset(payload_read, 0x00, sizeof(payload_read)); 6714 iov[0].iov_base = payload_read; 6715 iov[0].iov_len = 4 * 512; 6716 6717 test_blob_io_readv(blob, channel, iov, 1, 2, 4, blob_op_complete, NULL, ext_api ? &ext_opts : NULL); 6718 6719 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0); 6720 CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 512) == 0); 6721 CU_ASSERT(memcmp(payload_read + 2 * 512, payload_aa, 512) == 0); 6722 CU_ASSERT(memcmp(payload_read + 3 * 512, payload_aa, 512) == 0); 6723 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 28 * 512) == 0); 6724 6725 /* Read eight io_units across multiple pages 6726 * cluster0: [ F0F0 (AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ] 6727 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] 6728 * payload_read: AAAA AAAA | 0000 0000 ... */ 6729 memset(payload_read, 0x00, sizeof(payload_read)); 6730 iov[0].iov_base = payload_read; 6731 iov[0].iov_len = 4 * 512; 6732 iov[1].iov_base = payload_read + 4 * 512; 6733 iov[1].iov_len = 4 * 512; 6734 6735 test_blob_io_readv(blob, channel, iov, 2, 4, 8, blob_op_complete, NULL, ext_api ? &ext_opts : NULL); 6736 6737 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_aa, 8 * 512) == 0); 6738 CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, 24 * 512) == 0); 6739 6740 /* Read eight io_units across multiple clusters 6741 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 (FFFF ] 6742 * cluster1: [ FFFF) 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] 6743 * payload_read: FFFF FFFF | 0000 0000 ... */ 6744 memset(payload_read, 0x00, sizeof(payload_read)); 6745 iov[0].iov_base = payload_read; 6746 iov[0].iov_len = 2 * 512; 6747 iov[1].iov_base = payload_read + 2 * 512; 6748 iov[1].iov_len = 2 * 512; 6749 iov[2].iov_base = payload_read + 4 * 512; 6750 iov[2].iov_len = 2 * 512; 6751 iov[3].iov_base = payload_read + 6 * 512; 6752 iov[3].iov_len = 2 * 512; 6753 6754 test_blob_io_readv(blob, channel, iov, 4, 28, 8, blob_op_complete, NULL, 6755 ext_api ? &ext_opts : NULL); 6756 6757 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 8 * 512) == 0); 6758 CU_ASSERT(memcmp(payload_read + 8 * 512, payload_00, 24 * 512) == 0); 6759 6760 /* Read four io_units from second cluster 6761 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ] 6762 * cluster1: [ FFFF 0000 | 00(00 FF)00 | 0000 0000 | 0000 0000 ] 6763 * payload_read: 00FF 0000 | 0000 0000 ... */ 6764 memset(payload_read, 0x00, sizeof(payload_read)); 6765 iov[0].iov_base = payload_read; 6766 iov[0].iov_len = 1 * 512; 6767 iov[1].iov_base = payload_read + 1 * 512; 6768 iov[1].iov_len = 3 * 512; 6769 6770 test_blob_io_readv(blob, channel, iov, 2, 32 + 10, 4, blob_op_complete, NULL, 6771 ext_api ? &ext_opts : NULL); 6772 6773 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_00, 2 * 512) == 0); 6774 CU_ASSERT(memcmp(payload_read + 2 * 512, payload_ff, 2 * 512) == 0); 6775 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 28 * 512) == 0); 6776 6777 /* Read second cluster 6778 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ] 6779 * cluster1: [ (FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ] 6780 * payload_read: FFFF 0000 | 0000 FF00 ... */ 6781 memset(payload_read, 0x00, sizeof(payload_read)); 6782 iov[0].iov_base = payload_read; 6783 iov[0].iov_len = 1 * 512; 6784 iov[1].iov_base = payload_read + 1 * 512; 6785 iov[1].iov_len = 2 * 512; 6786 iov[2].iov_base = payload_read + 3 * 512; 6787 iov[2].iov_len = 4 * 512; 6788 iov[3].iov_base = payload_read + 7 * 512; 6789 iov[3].iov_len = 25 * 512; 6790 6791 test_blob_io_readv(blob, channel, iov, 4, 32, 32, blob_op_complete, NULL, 6792 ext_api ? &ext_opts : NULL); 6793 6794 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 4 * 512) == 0); 6795 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_00, 8 * 512) == 0); 6796 CU_ASSERT(memcmp(payload_read + 12 * 512, payload_ff, 2 * 512) == 0); 6797 CU_ASSERT(memcmp(payload_read + 14 * 512, payload_00, 18 * 512) == 0); 6798 6799 /* Read whole two clusters 6800 * cluster0: [ (F0F0 AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ] 6801 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ] */ 6802 memset(payload_read, 0x00, sizeof(payload_read)); 6803 iov[0].iov_base = payload_read; 6804 iov[0].iov_len = 1 * 512; 6805 iov[1].iov_base = payload_read + 1 * 512; 6806 iov[1].iov_len = 8 * 512; 6807 iov[2].iov_base = payload_read + 9 * 512; 6808 iov[2].iov_len = 16 * 512; 6809 iov[3].iov_base = payload_read + 25 * 512; 6810 iov[3].iov_len = 39 * 512; 6811 6812 test_blob_io_readv(blob, channel, iov, 4, 0, 64, blob_op_complete, NULL, 6813 ext_api ? &ext_opts : NULL); 6814 6815 CU_ASSERT(memcmp(payload_read + 0 * 512, payload_ff, 512) == 0); 6816 CU_ASSERT(memcmp(payload_read + 1 * 512, payload_00, 512) == 0); 6817 CU_ASSERT(memcmp(payload_read + 2 * 512, payload_ff, 512) == 0); 6818 CU_ASSERT(memcmp(payload_read + 3 * 512, payload_00, 512) == 0); 6819 CU_ASSERT(memcmp(payload_read + 4 * 512, payload_aa, 8 * 512) == 0); 6820 CU_ASSERT(memcmp(payload_read + 28 * 512, payload_ff, 4 * 512) == 0); 6821 6822 CU_ASSERT(memcmp(payload_read + (32 + 0) * 512, payload_ff, 4 * 512) == 0); 6823 CU_ASSERT(memcmp(payload_read + (32 + 4) * 512, payload_00, 8 * 512) == 0); 6824 CU_ASSERT(memcmp(payload_read + (32 + 12) * 512, payload_ff, 2 * 512) == 0); 6825 CU_ASSERT(memcmp(payload_read + (32 + 14) * 512, payload_00, 18 * 512) == 0); 6826 } 6827 6828 static void 6829 blob_io_unit(void) 6830 { 6831 struct spdk_bs_opts bsopts; 6832 struct spdk_blob_opts opts; 6833 struct spdk_blob_store *bs; 6834 struct spdk_bs_dev *dev; 6835 struct spdk_blob *blob, *snapshot, *clone; 6836 spdk_blob_id blobid; 6837 struct spdk_io_channel *channel; 6838 6839 /* Create dev with 512 bytes io unit size */ 6840 6841 spdk_bs_opts_init(&bsopts, sizeof(bsopts)); 6842 bsopts.cluster_sz = SPDK_BS_PAGE_SIZE * 4; /* 8 * 4 = 32 io_unit */ 6843 snprintf(bsopts.bstype.bstype, sizeof(bsopts.bstype.bstype), "TESTTYPE"); 6844 6845 /* Try to initialize a new blob store with unsupported io_unit */ 6846 dev = init_dev(); 6847 dev->blocklen = 512; 6848 dev->blockcnt = DEV_BUFFER_SIZE / dev->blocklen; 6849 6850 /* Initialize a new blob store */ 6851 spdk_bs_init(dev, &bsopts, bs_op_with_handle_complete, NULL); 6852 poll_threads(); 6853 CU_ASSERT(g_bserrno == 0); 6854 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 6855 bs = g_bs; 6856 6857 CU_ASSERT(spdk_bs_get_io_unit_size(bs) == 512); 6858 channel = spdk_bs_alloc_io_channel(bs); 6859 6860 /* Create thick provisioned blob */ 6861 ut_spdk_blob_opts_init(&opts); 6862 opts.thin_provision = false; 6863 opts.num_clusters = 32; 6864 6865 blob = ut_blob_create_and_open(bs, &opts); 6866 blobid = spdk_blob_get_id(blob); 6867 6868 test_io_write(dev, blob, channel); 6869 test_io_read(dev, blob, channel); 6870 test_io_zeroes(dev, blob, channel); 6871 6872 test_iov_write(dev, blob, channel, false); 6873 test_iov_read(dev, blob, channel, false); 6874 test_io_zeroes(dev, blob, channel); 6875 6876 test_iov_write(dev, blob, channel, true); 6877 test_iov_read(dev, blob, channel, true); 6878 6879 test_io_unmap(dev, blob, channel); 6880 6881 spdk_blob_close(blob, blob_op_complete, NULL); 6882 poll_threads(); 6883 CU_ASSERT(g_bserrno == 0); 6884 blob = NULL; 6885 g_blob = NULL; 6886 6887 /* Create thin provisioned blob */ 6888 6889 ut_spdk_blob_opts_init(&opts); 6890 opts.thin_provision = true; 6891 opts.num_clusters = 32; 6892 6893 blob = ut_blob_create_and_open(bs, &opts); 6894 blobid = spdk_blob_get_id(blob); 6895 6896 test_io_write(dev, blob, channel); 6897 test_io_read(dev, blob, channel); 6898 test_io_zeroes(dev, blob, channel); 6899 6900 test_iov_write(dev, blob, channel, false); 6901 test_iov_read(dev, blob, channel, false); 6902 test_io_zeroes(dev, blob, channel); 6903 6904 test_iov_write(dev, blob, channel, true); 6905 test_iov_read(dev, blob, channel, true); 6906 6907 /* Create snapshot */ 6908 6909 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 6910 poll_threads(); 6911 CU_ASSERT(g_bserrno == 0); 6912 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 6913 blobid = g_blobid; 6914 6915 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 6916 poll_threads(); 6917 CU_ASSERT(g_bserrno == 0); 6918 CU_ASSERT(g_blob != NULL); 6919 snapshot = g_blob; 6920 6921 spdk_bs_create_clone(bs, blobid, NULL, blob_op_with_id_complete, NULL); 6922 poll_threads(); 6923 CU_ASSERT(g_bserrno == 0); 6924 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 6925 blobid = g_blobid; 6926 6927 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 6928 poll_threads(); 6929 CU_ASSERT(g_bserrno == 0); 6930 CU_ASSERT(g_blob != NULL); 6931 clone = g_blob; 6932 6933 test_io_read(dev, blob, channel); 6934 test_io_read(dev, snapshot, channel); 6935 test_io_read(dev, clone, channel); 6936 6937 test_iov_read(dev, blob, channel, false); 6938 test_iov_read(dev, snapshot, channel, false); 6939 test_iov_read(dev, clone, channel, false); 6940 6941 test_iov_read(dev, blob, channel, true); 6942 test_iov_read(dev, snapshot, channel, true); 6943 test_iov_read(dev, clone, channel, true); 6944 6945 /* Inflate clone */ 6946 6947 spdk_bs_inflate_blob(bs, channel, blobid, blob_op_complete, NULL); 6948 poll_threads(); 6949 6950 CU_ASSERT(g_bserrno == 0); 6951 6952 test_io_read(dev, clone, channel); 6953 6954 test_io_unmap(dev, clone, channel); 6955 6956 test_iov_write(dev, clone, channel, false); 6957 test_iov_read(dev, clone, channel, false); 6958 test_io_unmap(dev, clone, channel); 6959 6960 test_iov_write(dev, clone, channel, true); 6961 test_iov_read(dev, clone, channel, true); 6962 6963 spdk_blob_close(blob, blob_op_complete, NULL); 6964 spdk_blob_close(snapshot, blob_op_complete, NULL); 6965 spdk_blob_close(clone, blob_op_complete, NULL); 6966 poll_threads(); 6967 CU_ASSERT(g_bserrno == 0); 6968 blob = NULL; 6969 g_blob = NULL; 6970 6971 spdk_bs_free_io_channel(channel); 6972 poll_threads(); 6973 6974 /* Unload the blob store */ 6975 spdk_bs_unload(bs, bs_op_complete, NULL); 6976 poll_threads(); 6977 CU_ASSERT(g_bserrno == 0); 6978 g_bs = NULL; 6979 g_blob = NULL; 6980 g_blobid = 0; 6981 } 6982 6983 static void 6984 blob_io_unit_compatibility(void) 6985 { 6986 struct spdk_bs_opts bsopts; 6987 struct spdk_blob_store *bs; 6988 struct spdk_bs_dev *dev; 6989 struct spdk_bs_super_block *super; 6990 6991 /* Create dev with 512 bytes io unit size */ 6992 6993 spdk_bs_opts_init(&bsopts, sizeof(bsopts)); 6994 bsopts.cluster_sz = SPDK_BS_PAGE_SIZE * 4; /* 8 * 4 = 32 io_unit */ 6995 snprintf(bsopts.bstype.bstype, sizeof(bsopts.bstype.bstype), "TESTTYPE"); 6996 6997 /* Try to initialize a new blob store with unsupported io_unit */ 6998 dev = init_dev(); 6999 dev->blocklen = 512; 7000 dev->blockcnt = DEV_BUFFER_SIZE / dev->blocklen; 7001 7002 /* Initialize a new blob store */ 7003 spdk_bs_init(dev, &bsopts, bs_op_with_handle_complete, NULL); 7004 poll_threads(); 7005 CU_ASSERT(g_bserrno == 0); 7006 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 7007 bs = g_bs; 7008 7009 CU_ASSERT(spdk_bs_get_io_unit_size(bs) == 512); 7010 7011 /* Unload the blob store */ 7012 spdk_bs_unload(bs, bs_op_complete, NULL); 7013 poll_threads(); 7014 CU_ASSERT(g_bserrno == 0); 7015 7016 /* Modify super block to behave like older version. 7017 * Check if loaded io unit size equals SPDK_BS_PAGE_SIZE */ 7018 super = (struct spdk_bs_super_block *)&g_dev_buffer[0]; 7019 super->io_unit_size = 0; 7020 super->crc = blob_md_page_calc_crc(super); 7021 7022 dev = init_dev(); 7023 dev->blocklen = 512; 7024 dev->blockcnt = DEV_BUFFER_SIZE / dev->blocklen; 7025 7026 spdk_bs_load(dev, &bsopts, bs_op_with_handle_complete, NULL); 7027 poll_threads(); 7028 CU_ASSERT(g_bserrno == 0); 7029 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 7030 bs = g_bs; 7031 7032 CU_ASSERT(spdk_bs_get_io_unit_size(bs) == SPDK_BS_PAGE_SIZE); 7033 7034 /* Unload the blob store */ 7035 spdk_bs_unload(bs, bs_op_complete, NULL); 7036 poll_threads(); 7037 CU_ASSERT(g_bserrno == 0); 7038 7039 g_bs = NULL; 7040 g_blob = NULL; 7041 g_blobid = 0; 7042 } 7043 7044 static void 7045 first_sync_complete(void *cb_arg, int bserrno) 7046 { 7047 struct spdk_blob *blob = cb_arg; 7048 int rc; 7049 7050 CU_ASSERT(bserrno == 0); 7051 rc = spdk_blob_set_xattr(blob, "sync", "second", strlen("second") + 1); 7052 CU_ASSERT(rc == 0); 7053 CU_ASSERT(g_bserrno == -1); 7054 7055 /* Keep g_bserrno at -1, only the 7056 * second sync completion should set it at 0. */ 7057 } 7058 7059 static void 7060 second_sync_complete(void *cb_arg, int bserrno) 7061 { 7062 struct spdk_blob *blob = cb_arg; 7063 const void *value; 7064 size_t value_len; 7065 int rc; 7066 7067 CU_ASSERT(bserrno == 0); 7068 7069 /* Verify that the first sync completion had a chance to execute */ 7070 rc = spdk_blob_get_xattr_value(blob, "sync", &value, &value_len); 7071 CU_ASSERT(rc == 0); 7072 SPDK_CU_ASSERT_FATAL(value != NULL); 7073 CU_ASSERT(value_len == strlen("second") + 1); 7074 CU_ASSERT_NSTRING_EQUAL_FATAL(value, "second", value_len); 7075 7076 CU_ASSERT(g_bserrno == -1); 7077 g_bserrno = bserrno; 7078 } 7079 7080 static void 7081 blob_simultaneous_operations(void) 7082 { 7083 struct spdk_blob_store *bs = g_bs; 7084 struct spdk_blob_opts opts; 7085 struct spdk_blob *blob, *snapshot; 7086 spdk_blob_id blobid, snapshotid; 7087 struct spdk_io_channel *channel; 7088 int rc; 7089 7090 channel = spdk_bs_alloc_io_channel(bs); 7091 SPDK_CU_ASSERT_FATAL(channel != NULL); 7092 7093 ut_spdk_blob_opts_init(&opts); 7094 opts.num_clusters = 10; 7095 7096 blob = ut_blob_create_and_open(bs, &opts); 7097 blobid = spdk_blob_get_id(blob); 7098 7099 /* Create snapshot and try to remove blob in the same time: 7100 * - snapshot should be created successfully 7101 * - delete operation should fail w -EBUSY */ 7102 CU_ASSERT(blob->locked_operation_in_progress == false); 7103 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 7104 CU_ASSERT(blob->locked_operation_in_progress == true); 7105 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); 7106 CU_ASSERT(blob->locked_operation_in_progress == true); 7107 /* Deletion failure */ 7108 CU_ASSERT(g_bserrno == -EBUSY); 7109 poll_threads(); 7110 CU_ASSERT(blob->locked_operation_in_progress == false); 7111 /* Snapshot creation success */ 7112 CU_ASSERT(g_bserrno == 0); 7113 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 7114 7115 snapshotid = g_blobid; 7116 7117 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 7118 poll_threads(); 7119 CU_ASSERT(g_bserrno == 0); 7120 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 7121 snapshot = g_blob; 7122 7123 /* Inflate blob and try to remove blob in the same time: 7124 * - blob should be inflated successfully 7125 * - delete operation should fail w -EBUSY */ 7126 CU_ASSERT(blob->locked_operation_in_progress == false); 7127 spdk_bs_inflate_blob(bs, channel, blobid, blob_op_complete, NULL); 7128 CU_ASSERT(blob->locked_operation_in_progress == true); 7129 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); 7130 CU_ASSERT(blob->locked_operation_in_progress == true); 7131 /* Deletion failure */ 7132 CU_ASSERT(g_bserrno == -EBUSY); 7133 poll_threads(); 7134 CU_ASSERT(blob->locked_operation_in_progress == false); 7135 /* Inflation success */ 7136 CU_ASSERT(g_bserrno == 0); 7137 7138 /* Clone snapshot and try to remove snapshot in the same time: 7139 * - snapshot should be cloned successfully 7140 * - delete operation should fail w -EBUSY */ 7141 CU_ASSERT(blob->locked_operation_in_progress == false); 7142 spdk_bs_create_clone(bs, snapshotid, NULL, blob_op_with_id_complete, NULL); 7143 spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL); 7144 /* Deletion failure */ 7145 CU_ASSERT(g_bserrno == -EBUSY); 7146 poll_threads(); 7147 CU_ASSERT(blob->locked_operation_in_progress == false); 7148 /* Clone created */ 7149 CU_ASSERT(g_bserrno == 0); 7150 7151 /* Resize blob and try to remove blob in the same time: 7152 * - blob should be resized successfully 7153 * - delete operation should fail w -EBUSY */ 7154 CU_ASSERT(blob->locked_operation_in_progress == false); 7155 spdk_blob_resize(blob, 50, blob_op_complete, NULL); 7156 CU_ASSERT(blob->locked_operation_in_progress == true); 7157 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); 7158 CU_ASSERT(blob->locked_operation_in_progress == true); 7159 /* Deletion failure */ 7160 CU_ASSERT(g_bserrno == -EBUSY); 7161 poll_threads(); 7162 CU_ASSERT(blob->locked_operation_in_progress == false); 7163 /* Blob resized successfully */ 7164 spdk_blob_sync_md(blob, blob_op_complete, NULL); 7165 poll_threads(); 7166 CU_ASSERT(g_bserrno == 0); 7167 7168 /* Issue two consecutive blob syncs, neither should fail. 7169 * Force sync to actually occur by marking blob dirty each time. 7170 * Execution of sync should not be enough to complete the operation, 7171 * since disk I/O is required to complete it. */ 7172 g_bserrno = -1; 7173 7174 rc = spdk_blob_set_xattr(blob, "sync", "first", strlen("first") + 1); 7175 CU_ASSERT(rc == 0); 7176 spdk_blob_sync_md(blob, first_sync_complete, blob); 7177 CU_ASSERT(g_bserrno == -1); 7178 7179 spdk_blob_sync_md(blob, second_sync_complete, blob); 7180 CU_ASSERT(g_bserrno == -1); 7181 7182 poll_threads(); 7183 CU_ASSERT(g_bserrno == 0); 7184 7185 spdk_bs_free_io_channel(channel); 7186 poll_threads(); 7187 7188 ut_blob_close_and_delete(bs, snapshot); 7189 ut_blob_close_and_delete(bs, blob); 7190 } 7191 7192 static void 7193 blob_persist_test(void) 7194 { 7195 struct spdk_blob_store *bs = g_bs; 7196 struct spdk_blob_opts opts; 7197 struct spdk_blob *blob; 7198 spdk_blob_id blobid; 7199 struct spdk_io_channel *channel; 7200 char *xattr; 7201 size_t xattr_length; 7202 int rc; 7203 uint32_t page_count_clear, page_count_xattr; 7204 uint64_t poller_iterations; 7205 bool run_poller; 7206 7207 channel = spdk_bs_alloc_io_channel(bs); 7208 SPDK_CU_ASSERT_FATAL(channel != NULL); 7209 7210 ut_spdk_blob_opts_init(&opts); 7211 opts.num_clusters = 10; 7212 7213 blob = ut_blob_create_and_open(bs, &opts); 7214 blobid = spdk_blob_get_id(blob); 7215 7216 /* Save the amount of md pages used after creation of a blob. 7217 * This should be consistent after removing xattr. */ 7218 page_count_clear = spdk_bit_array_count_set(bs->used_md_pages); 7219 SPDK_CU_ASSERT_FATAL(blob->active.num_pages + blob->active.num_extent_pages == page_count_clear); 7220 SPDK_CU_ASSERT_FATAL(blob->clean.num_pages + blob->clean.num_extent_pages == page_count_clear); 7221 7222 /* Add xattr with maximum length of descriptor to exceed single metadata page. */ 7223 xattr_length = SPDK_BS_MAX_DESC_SIZE - sizeof(struct spdk_blob_md_descriptor_xattr) - 7224 strlen("large_xattr"); 7225 xattr = calloc(xattr_length, sizeof(char)); 7226 SPDK_CU_ASSERT_FATAL(xattr != NULL); 7227 7228 rc = spdk_blob_set_xattr(blob, "large_xattr", xattr, xattr_length); 7229 SPDK_CU_ASSERT_FATAL(rc == 0); 7230 spdk_blob_sync_md(blob, blob_op_complete, NULL); 7231 poll_threads(); 7232 SPDK_CU_ASSERT_FATAL(g_bserrno == 0); 7233 7234 /* Save the amount of md pages used after adding the large xattr */ 7235 page_count_xattr = spdk_bit_array_count_set(bs->used_md_pages); 7236 SPDK_CU_ASSERT_FATAL(blob->active.num_pages + blob->active.num_extent_pages == page_count_xattr); 7237 SPDK_CU_ASSERT_FATAL(blob->clean.num_pages + blob->clean.num_extent_pages == page_count_xattr); 7238 7239 /* Add xattr to a blob and sync it. While sync is occurring, remove the xattr and sync again. 7240 * Interrupt the first sync after increasing number of poller iterations, until it succeeds. 7241 * Expectation is that after second sync completes no xattr is saved in metadata. */ 7242 poller_iterations = 1; 7243 run_poller = true; 7244 while (run_poller) { 7245 rc = spdk_blob_set_xattr(blob, "large_xattr", xattr, xattr_length); 7246 SPDK_CU_ASSERT_FATAL(rc == 0); 7247 g_bserrno = -1; 7248 spdk_blob_sync_md(blob, blob_op_complete, NULL); 7249 poll_thread_times(0, poller_iterations); 7250 if (g_bserrno == 0) { 7251 /* Poller iteration count was high enough for first sync to complete. 7252 * Verify that blob takes up enough of md_pages to store the xattr. */ 7253 SPDK_CU_ASSERT_FATAL(blob->active.num_pages + blob->active.num_extent_pages == page_count_xattr); 7254 SPDK_CU_ASSERT_FATAL(blob->clean.num_pages + blob->clean.num_extent_pages == page_count_xattr); 7255 SPDK_CU_ASSERT_FATAL(spdk_bit_array_count_set(bs->used_md_pages) == page_count_xattr); 7256 run_poller = false; 7257 } 7258 rc = spdk_blob_remove_xattr(blob, "large_xattr"); 7259 SPDK_CU_ASSERT_FATAL(rc == 0); 7260 spdk_blob_sync_md(blob, blob_op_complete, NULL); 7261 poll_threads(); 7262 SPDK_CU_ASSERT_FATAL(g_bserrno == 0); 7263 SPDK_CU_ASSERT_FATAL(blob->active.num_pages + blob->active.num_extent_pages == page_count_clear); 7264 SPDK_CU_ASSERT_FATAL(blob->clean.num_pages + blob->clean.num_extent_pages == page_count_clear); 7265 SPDK_CU_ASSERT_FATAL(spdk_bit_array_count_set(bs->used_md_pages) == page_count_clear); 7266 7267 /* Reload bs and re-open blob to verify that xattr was not persisted. */ 7268 spdk_blob_close(blob, blob_op_complete, NULL); 7269 poll_threads(); 7270 CU_ASSERT(g_bserrno == 0); 7271 7272 ut_bs_reload(&bs, NULL); 7273 7274 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 7275 poll_threads(); 7276 CU_ASSERT(g_bserrno == 0); 7277 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 7278 blob = g_blob; 7279 7280 rc = spdk_blob_get_xattr_value(blob, "large_xattr", (const void **)&xattr, &xattr_length); 7281 SPDK_CU_ASSERT_FATAL(rc == -ENOENT); 7282 7283 poller_iterations++; 7284 /* Stop at high iteration count to prevent infinite loop. 7285 * This value should be enough for first md sync to complete in any case. */ 7286 SPDK_CU_ASSERT_FATAL(poller_iterations < 50); 7287 } 7288 7289 free(xattr); 7290 7291 ut_blob_close_and_delete(bs, blob); 7292 7293 spdk_bs_free_io_channel(channel); 7294 poll_threads(); 7295 } 7296 7297 static void 7298 blob_decouple_snapshot(void) 7299 { 7300 struct spdk_blob_store *bs = g_bs; 7301 struct spdk_blob_opts opts; 7302 struct spdk_blob *blob, *snapshot1, *snapshot2; 7303 struct spdk_io_channel *channel; 7304 spdk_blob_id blobid, snapshotid; 7305 uint64_t cluster; 7306 7307 for (int delete_snapshot_first = 0; delete_snapshot_first <= 1; delete_snapshot_first++) { 7308 channel = spdk_bs_alloc_io_channel(bs); 7309 SPDK_CU_ASSERT_FATAL(channel != NULL); 7310 7311 ut_spdk_blob_opts_init(&opts); 7312 opts.num_clusters = 10; 7313 opts.thin_provision = false; 7314 7315 blob = ut_blob_create_and_open(bs, &opts); 7316 blobid = spdk_blob_get_id(blob); 7317 7318 /* Create first snapshot */ 7319 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 0); 7320 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 7321 poll_threads(); 7322 CU_ASSERT(g_bserrno == 0); 7323 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 7324 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 1); 7325 snapshotid = g_blobid; 7326 7327 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 7328 poll_threads(); 7329 CU_ASSERT(g_bserrno == 0); 7330 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 7331 snapshot1 = g_blob; 7332 7333 /* Create the second one */ 7334 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 1); 7335 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 7336 poll_threads(); 7337 CU_ASSERT(g_bserrno == 0); 7338 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 7339 CU_ASSERT_EQUAL(_get_snapshots_count(bs), 2); 7340 snapshotid = g_blobid; 7341 7342 spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL); 7343 poll_threads(); 7344 CU_ASSERT(g_bserrno == 0); 7345 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 7346 snapshot2 = g_blob; 7347 CU_ASSERT_EQUAL(spdk_blob_get_parent_snapshot(bs, snapshot2->id), snapshot1->id); 7348 7349 /* Now decouple the second snapshot forcing it to copy the written clusters */ 7350 spdk_bs_blob_decouple_parent(bs, channel, snapshot2->id, blob_op_complete, NULL); 7351 poll_threads(); 7352 CU_ASSERT(g_bserrno == 0); 7353 7354 /* Verify that the snapshot has been decoupled and that the clusters have been copied */ 7355 CU_ASSERT_EQUAL(spdk_blob_get_parent_snapshot(bs, snapshot2->id), SPDK_BLOBID_INVALID); 7356 for (cluster = 0; cluster < snapshot2->active.num_clusters; ++cluster) { 7357 CU_ASSERT_NOT_EQUAL(snapshot2->active.clusters[cluster], 0); 7358 CU_ASSERT_NOT_EQUAL(snapshot2->active.clusters[cluster], 7359 snapshot1->active.clusters[cluster]); 7360 } 7361 7362 spdk_bs_free_io_channel(channel); 7363 7364 if (delete_snapshot_first) { 7365 ut_blob_close_and_delete(bs, snapshot2); 7366 ut_blob_close_and_delete(bs, snapshot1); 7367 ut_blob_close_and_delete(bs, blob); 7368 } else { 7369 ut_blob_close_and_delete(bs, blob); 7370 ut_blob_close_and_delete(bs, snapshot2); 7371 ut_blob_close_and_delete(bs, snapshot1); 7372 } 7373 poll_threads(); 7374 } 7375 } 7376 7377 static void 7378 blob_seek_io_unit(void) 7379 { 7380 struct spdk_blob_store *bs = g_bs; 7381 struct spdk_blob *blob; 7382 struct spdk_io_channel *channel; 7383 struct spdk_blob_opts opts; 7384 uint64_t free_clusters; 7385 uint8_t payload[10 * 4096]; 7386 uint64_t offset; 7387 uint64_t io_unit, io_units_per_cluster; 7388 7389 free_clusters = spdk_bs_free_cluster_count(bs); 7390 7391 channel = spdk_bs_alloc_io_channel(bs); 7392 CU_ASSERT(channel != NULL); 7393 7394 /* Set blob as thin provisioned */ 7395 ut_spdk_blob_opts_init(&opts); 7396 opts.thin_provision = true; 7397 7398 /* Create a blob */ 7399 blob = ut_blob_create_and_open(bs, &opts); 7400 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 7401 7402 io_units_per_cluster = bs_io_units_per_cluster(blob); 7403 7404 /* The blob started at 0 clusters. Resize it to be 5, but still unallocated. */ 7405 spdk_blob_resize(blob, 5, blob_op_complete, NULL); 7406 poll_threads(); 7407 CU_ASSERT(g_bserrno == 0); 7408 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 7409 CU_ASSERT(blob->active.num_clusters == 5); 7410 7411 /* Write at the beginning of first cluster */ 7412 offset = 0; 7413 spdk_blob_io_write(blob, channel, payload, offset, 1, blob_op_complete, NULL); 7414 poll_threads(); 7415 CU_ASSERT(g_bserrno == 0); 7416 7417 io_unit = spdk_blob_get_next_allocated_io_unit(blob, 0); 7418 CU_ASSERT(io_unit == offset); 7419 7420 io_unit = spdk_blob_get_next_unallocated_io_unit(blob, 0); 7421 CU_ASSERT(io_unit == io_units_per_cluster); 7422 7423 /* Write in the middle of third cluster */ 7424 offset = 2 * io_units_per_cluster + io_units_per_cluster / 2; 7425 spdk_blob_io_write(blob, channel, payload, offset, 1, blob_op_complete, NULL); 7426 poll_threads(); 7427 CU_ASSERT(g_bserrno == 0); 7428 7429 io_unit = spdk_blob_get_next_allocated_io_unit(blob, io_units_per_cluster); 7430 CU_ASSERT(io_unit == 2 * io_units_per_cluster); 7431 7432 io_unit = spdk_blob_get_next_unallocated_io_unit(blob, 2 * io_units_per_cluster); 7433 CU_ASSERT(io_unit == 3 * io_units_per_cluster); 7434 7435 /* Write at the end of last cluster */ 7436 offset = 5 * io_units_per_cluster - 1; 7437 spdk_blob_io_write(blob, channel, payload, offset, 1, blob_op_complete, NULL); 7438 poll_threads(); 7439 CU_ASSERT(g_bserrno == 0); 7440 7441 io_unit = spdk_blob_get_next_allocated_io_unit(blob, 3 * io_units_per_cluster); 7442 CU_ASSERT(io_unit == 4 * io_units_per_cluster); 7443 7444 io_unit = spdk_blob_get_next_unallocated_io_unit(blob, 4 * io_units_per_cluster); 7445 CU_ASSERT(io_unit == UINT64_MAX); 7446 7447 spdk_bs_free_io_channel(channel); 7448 poll_threads(); 7449 7450 ut_blob_close_and_delete(bs, blob); 7451 } 7452 7453 static void 7454 blob_esnap_create(void) 7455 { 7456 struct spdk_blob_store *bs = g_bs; 7457 struct spdk_bs_opts bs_opts; 7458 struct ut_esnap_opts esnap_opts; 7459 struct spdk_blob_opts opts; 7460 struct spdk_blob_open_opts open_opts; 7461 struct spdk_blob *blob; 7462 uint32_t cluster_sz, block_sz; 7463 const uint32_t esnap_num_clusters = 4; 7464 uint64_t esnap_num_blocks; 7465 uint32_t sz; 7466 spdk_blob_id blobid; 7467 uint32_t bs_ctx_count, blob_ctx_count; 7468 7469 cluster_sz = spdk_bs_get_cluster_size(bs); 7470 block_sz = spdk_bs_get_io_unit_size(bs); 7471 esnap_num_blocks = cluster_sz * esnap_num_clusters / block_sz; 7472 7473 /* Create a normal blob and verify it is not an esnap clone. */ 7474 ut_spdk_blob_opts_init(&opts); 7475 blob = ut_blob_create_and_open(bs, &opts); 7476 CU_ASSERT(!spdk_blob_is_esnap_clone(blob)); 7477 ut_blob_close_and_delete(bs, blob); 7478 7479 /* Create an esnap clone blob then verify it is an esnap clone and has the right size */ 7480 ut_spdk_blob_opts_init(&opts); 7481 ut_esnap_opts_init(block_sz, esnap_num_blocks, __func__, NULL, &esnap_opts); 7482 opts.esnap_id = &esnap_opts; 7483 opts.esnap_id_len = sizeof(esnap_opts); 7484 opts.num_clusters = esnap_num_clusters; 7485 blob = ut_blob_create_and_open(bs, &opts); 7486 SPDK_CU_ASSERT_FATAL(blob != NULL); 7487 SPDK_CU_ASSERT_FATAL(spdk_blob_is_esnap_clone(blob)); 7488 SPDK_CU_ASSERT_FATAL(blob_is_esnap_clone(blob)); 7489 SPDK_CU_ASSERT_FATAL(!spdk_blob_is_clone(blob)); 7490 sz = spdk_blob_get_num_clusters(blob); 7491 CU_ASSERT(sz == esnap_num_clusters); 7492 ut_blob_close_and_delete(bs, blob); 7493 7494 /* Create an esnap clone without the size and verify it can be grown */ 7495 ut_spdk_blob_opts_init(&opts); 7496 ut_esnap_opts_init(block_sz, esnap_num_blocks, __func__, NULL, &esnap_opts); 7497 opts.esnap_id = &esnap_opts; 7498 opts.esnap_id_len = sizeof(esnap_opts); 7499 blob = ut_blob_create_and_open(bs, &opts); 7500 SPDK_CU_ASSERT_FATAL(spdk_blob_is_esnap_clone(blob)); 7501 sz = spdk_blob_get_num_clusters(blob); 7502 CU_ASSERT(sz == 0); 7503 spdk_blob_resize(blob, 1, blob_op_complete, NULL); 7504 poll_threads(); 7505 CU_ASSERT(g_bserrno == 0); 7506 sz = spdk_blob_get_num_clusters(blob); 7507 CU_ASSERT(sz == 1); 7508 spdk_blob_resize(blob, esnap_num_clusters, blob_op_complete, NULL); 7509 poll_threads(); 7510 CU_ASSERT(g_bserrno == 0); 7511 sz = spdk_blob_get_num_clusters(blob); 7512 CU_ASSERT(sz == esnap_num_clusters); 7513 spdk_blob_resize(blob, esnap_num_clusters + 1, blob_op_complete, NULL); 7514 poll_threads(); 7515 CU_ASSERT(g_bserrno == 0); 7516 sz = spdk_blob_get_num_clusters(blob); 7517 CU_ASSERT(sz == esnap_num_clusters + 1); 7518 7519 /* Reload the blobstore and be sure that the blob can be opened. */ 7520 blobid = spdk_blob_get_id(blob); 7521 spdk_blob_close(blob, blob_op_complete, NULL); 7522 poll_threads(); 7523 CU_ASSERT(g_bserrno == 0); 7524 g_blob = NULL; 7525 spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); 7526 bs_opts.esnap_bs_dev_create = ut_esnap_create; 7527 ut_bs_reload(&bs, &bs_opts); 7528 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 7529 poll_threads(); 7530 CU_ASSERT(g_bserrno == 0); 7531 CU_ASSERT(g_blob != NULL); 7532 blob = g_blob; 7533 SPDK_CU_ASSERT_FATAL(spdk_blob_is_esnap_clone(blob)); 7534 sz = spdk_blob_get_num_clusters(blob); 7535 CU_ASSERT(sz == esnap_num_clusters + 1); 7536 7537 /* Reload the blobstore without esnap_bs_dev_create: should fail to open blob. */ 7538 spdk_blob_close(blob, blob_op_complete, NULL); 7539 poll_threads(); 7540 CU_ASSERT(g_bserrno == 0); 7541 g_blob = NULL; 7542 spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); 7543 ut_bs_reload(&bs, &bs_opts); 7544 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 7545 poll_threads(); 7546 CU_ASSERT(g_bserrno != 0); 7547 CU_ASSERT(g_blob == NULL); 7548 7549 /* Reload the blobstore with ctx set and verify it is passed to the esnap create callback */ 7550 bs_ctx_count = 0; 7551 spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); 7552 bs_opts.esnap_bs_dev_create = ut_esnap_create_with_count; 7553 bs_opts.esnap_ctx = &bs_ctx_count; 7554 ut_bs_reload(&bs, &bs_opts); 7555 /* Loading the blobstore triggers the esnap to be loaded */ 7556 CU_ASSERT(bs_ctx_count == 1); 7557 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 7558 poll_threads(); 7559 CU_ASSERT(g_bserrno == 0); 7560 CU_ASSERT(g_blob != NULL); 7561 /* Opening the blob also triggers the esnap to be loaded */ 7562 CU_ASSERT(bs_ctx_count == 2); 7563 blob = g_blob; 7564 SPDK_CU_ASSERT_FATAL(spdk_blob_is_esnap_clone(blob)); 7565 sz = spdk_blob_get_num_clusters(blob); 7566 CU_ASSERT(sz == esnap_num_clusters + 1); 7567 spdk_blob_close(blob, blob_op_complete, NULL); 7568 poll_threads(); 7569 CU_ASSERT(g_bserrno == 0); 7570 g_blob = NULL; 7571 /* If open_opts.esnap_ctx is set it is passed to the esnap create callback */ 7572 blob_ctx_count = 0; 7573 spdk_blob_open_opts_init(&open_opts, sizeof(open_opts)); 7574 open_opts.esnap_ctx = &blob_ctx_count; 7575 spdk_bs_open_blob_ext(bs, blobid, &open_opts, blob_op_with_handle_complete, NULL); 7576 poll_threads(); 7577 blob = g_blob; 7578 CU_ASSERT(bs_ctx_count == 3); 7579 CU_ASSERT(blob_ctx_count == 1); 7580 spdk_blob_close(blob, blob_op_complete, NULL); 7581 poll_threads(); 7582 CU_ASSERT(g_bserrno == 0); 7583 g_blob = NULL; 7584 } 7585 7586 static void 7587 blob_esnap_clone_reload(void) 7588 { 7589 struct spdk_blob_store *bs = g_bs; 7590 struct spdk_bs_opts bs_opts; 7591 struct ut_esnap_opts esnap_opts; 7592 struct spdk_blob_opts opts; 7593 struct spdk_blob *eclone1, *snap1, *clone1; 7594 uint32_t cluster_sz = spdk_bs_get_cluster_size(bs); 7595 uint32_t block_sz = spdk_bs_get_io_unit_size(bs); 7596 const uint32_t esnap_num_clusters = 4; 7597 uint64_t esnap_num_blocks = cluster_sz * esnap_num_clusters / block_sz; 7598 spdk_blob_id eclone1_id, snap1_id, clone1_id; 7599 struct spdk_io_channel *bs_ch; 7600 char buf[block_sz]; 7601 int bserr1, bserr2, bserr3, bserr4; 7602 struct spdk_bs_dev *dev; 7603 7604 /* Create and open an esnap clone blob */ 7605 ut_spdk_blob_opts_init(&opts); 7606 ut_esnap_opts_init(block_sz, esnap_num_blocks, __func__, NULL, &esnap_opts); 7607 opts.esnap_id = &esnap_opts; 7608 opts.esnap_id_len = sizeof(esnap_opts); 7609 opts.num_clusters = esnap_num_clusters; 7610 eclone1 = ut_blob_create_and_open(bs, &opts); 7611 CU_ASSERT(eclone1 != NULL); 7612 CU_ASSERT(spdk_blob_is_esnap_clone(eclone1)); 7613 eclone1_id = eclone1->id; 7614 7615 /* Create and open a snapshot of eclone1 */ 7616 spdk_bs_create_snapshot(bs, eclone1_id, NULL, blob_op_with_id_complete, NULL); 7617 poll_threads(); 7618 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 7619 CU_ASSERT(g_bserrno == 0); 7620 snap1_id = g_blobid; 7621 spdk_bs_open_blob(bs, snap1_id, blob_op_with_handle_complete, NULL); 7622 poll_threads(); 7623 CU_ASSERT(g_bserrno == 0); 7624 CU_ASSERT(g_blob != NULL); 7625 snap1 = g_blob; 7626 7627 /* Create and open regular clone of snap1 */ 7628 spdk_bs_create_clone(bs, snap1_id, NULL, blob_op_with_id_complete, NULL); 7629 poll_threads(); 7630 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 7631 SPDK_CU_ASSERT_FATAL(g_bserrno == 0); 7632 clone1_id = g_blobid; 7633 spdk_bs_open_blob(bs, clone1_id, blob_op_with_handle_complete, NULL); 7634 poll_threads(); 7635 CU_ASSERT(g_bserrno == 0); 7636 CU_ASSERT(g_blob != NULL); 7637 clone1 = g_blob; 7638 7639 /* Close the blobs in preparation for reloading the blobstore */ 7640 spdk_blob_close(clone1, blob_op_complete, NULL); 7641 poll_threads(); 7642 CU_ASSERT(g_bserrno == 0); 7643 spdk_blob_close(snap1, blob_op_complete, NULL); 7644 poll_threads(); 7645 CU_ASSERT(g_bserrno == 0); 7646 spdk_blob_close(eclone1, blob_op_complete, NULL); 7647 poll_threads(); 7648 CU_ASSERT(g_bserrno == 0); 7649 g_blob = NULL; 7650 7651 /* Reload the blobstore */ 7652 spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); 7653 bs_opts.esnap_bs_dev_create = ut_esnap_create; 7654 ut_bs_reload(&bs, &bs_opts); 7655 7656 /* Be sure each of the blobs can be opened */ 7657 spdk_bs_open_blob(bs, eclone1_id, blob_op_with_handle_complete, NULL); 7658 poll_threads(); 7659 CU_ASSERT(g_bserrno == 0); 7660 CU_ASSERT(g_blob != NULL); 7661 eclone1 = g_blob; 7662 spdk_bs_open_blob(bs, snap1_id, blob_op_with_handle_complete, NULL); 7663 poll_threads(); 7664 CU_ASSERT(g_bserrno == 0); 7665 CU_ASSERT(g_blob != NULL); 7666 snap1 = g_blob; 7667 spdk_bs_open_blob(bs, clone1_id, blob_op_with_handle_complete, NULL); 7668 poll_threads(); 7669 CU_ASSERT(g_bserrno == 0); 7670 CU_ASSERT(g_blob != NULL); 7671 clone1 = g_blob; 7672 7673 /* Perform some reads on each of them to cause channels to be allocated */ 7674 bs_ch = spdk_bs_alloc_io_channel(bs); 7675 CU_ASSERT(bs_ch != NULL); 7676 spdk_blob_io_read(eclone1, bs_ch, buf, 0, 1, bs_op_complete, NULL); 7677 poll_threads(); 7678 CU_ASSERT(g_bserrno == 0); 7679 spdk_blob_io_read(snap1, bs_ch, buf, 0, 1, bs_op_complete, NULL); 7680 poll_threads(); 7681 CU_ASSERT(g_bserrno == 0); 7682 spdk_blob_io_read(clone1, bs_ch, buf, 0, 1, bs_op_complete, NULL); 7683 poll_threads(); 7684 CU_ASSERT(g_bserrno == 0); 7685 7686 /* 7687 * Unload the blobstore in a way similar to how lvstore unloads it. This should exercise 7688 * the deferred unload path in spdk_bs_unload(). 7689 */ 7690 bserr1 = 0xbad; 7691 bserr2 = 0xbad; 7692 bserr3 = 0xbad; 7693 bserr4 = 0xbad; 7694 spdk_blob_close(eclone1, blob_op_complete, &bserr1); 7695 spdk_blob_close(snap1, blob_op_complete, &bserr2); 7696 spdk_blob_close(clone1, blob_op_complete, &bserr3); 7697 spdk_bs_unload(bs, blob_op_complete, &bserr4); 7698 spdk_bs_free_io_channel(bs_ch); 7699 poll_threads(); 7700 CU_ASSERT(bserr1 == 0); 7701 CU_ASSERT(bserr2 == 0); 7702 CU_ASSERT(bserr3 == 0); 7703 CU_ASSERT(bserr4 == 0); 7704 g_blob = NULL; 7705 7706 /* Reload the blobstore */ 7707 spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); 7708 bs_opts.esnap_bs_dev_create = ut_esnap_create; 7709 dev = init_dev(); 7710 spdk_bs_load(dev, &bs_opts, bs_op_with_handle_complete, NULL); 7711 poll_threads(); 7712 CU_ASSERT(g_bserrno == 0); 7713 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 7714 } 7715 7716 static bool 7717 blob_esnap_verify_contents(struct spdk_blob *blob, struct spdk_io_channel *ch, 7718 uint64_t offset, uint64_t size, uint32_t readsize, const char *how) 7719 { 7720 const uint32_t bs_blksz = blob->bs->io_unit_size; 7721 const uint32_t esnap_blksz = blob->back_bs_dev ? blob->back_bs_dev->blocklen : bs_blksz; 7722 const uint32_t start_blk = offset / bs_blksz; 7723 const uint32_t num_blocks = spdk_max(size, readsize) / bs_blksz; 7724 const uint32_t blocks_per_read = spdk_min(size, readsize) / bs_blksz; 7725 uint32_t blob_block; 7726 struct iovec iov; 7727 uint8_t buf[spdk_min(size, readsize)]; 7728 bool block_ok; 7729 7730 SPDK_CU_ASSERT_FATAL(offset % bs_blksz == 0); 7731 SPDK_CU_ASSERT_FATAL(size % bs_blksz == 0); 7732 SPDK_CU_ASSERT_FATAL(readsize % bs_blksz == 0); 7733 7734 memset(buf, 0, readsize); 7735 iov.iov_base = buf; 7736 iov.iov_len = readsize; 7737 for (blob_block = start_blk; blob_block < num_blocks; blob_block += blocks_per_read) { 7738 if (strcmp(how, "read") == 0) { 7739 spdk_blob_io_read(blob, ch, buf, blob_block, blocks_per_read, 7740 bs_op_complete, NULL); 7741 } else if (strcmp(how, "readv") == 0) { 7742 spdk_blob_io_readv(blob, ch, &iov, 1, blob_block, blocks_per_read, 7743 bs_op_complete, NULL); 7744 } else if (strcmp(how, "readv_ext") == 0) { 7745 /* 7746 * This is currently pointless. NULL ext_opts leads to dev->readv(), not 7747 * dev->readv_ext(). 7748 */ 7749 spdk_blob_io_readv_ext(blob, ch, &iov, 1, blob_block, blocks_per_read, 7750 bs_op_complete, NULL, NULL); 7751 } else { 7752 abort(); 7753 } 7754 poll_threads(); 7755 CU_ASSERT(g_bserrno == 0); 7756 if (g_bserrno != 0) { 7757 return false; 7758 } 7759 block_ok = ut_esnap_content_is_correct(buf, blocks_per_read * bs_blksz, blob->id, 7760 blob_block * bs_blksz, esnap_blksz); 7761 CU_ASSERT(block_ok); 7762 if (!block_ok) { 7763 return false; 7764 } 7765 } 7766 7767 return true; 7768 } 7769 7770 static void 7771 blob_esnap_io_size(uint32_t bs_blksz, uint32_t esnap_blksz) 7772 { 7773 struct spdk_bs_dev *dev; 7774 struct spdk_blob_store *bs; 7775 struct spdk_bs_opts bsopts; 7776 struct spdk_blob_opts opts; 7777 struct ut_esnap_opts esnap_opts; 7778 struct spdk_blob *blob; 7779 const uint32_t cluster_sz = 16 * 1024; 7780 const uint64_t esnap_num_clusters = 4; 7781 const uint32_t esnap_sz = cluster_sz * esnap_num_clusters; 7782 const uint64_t esnap_num_blocks = esnap_sz / esnap_blksz; 7783 const uint64_t blob_num_blocks = esnap_sz / bs_blksz; 7784 uint32_t block; 7785 struct spdk_io_channel *bs_ch; 7786 7787 spdk_bs_opts_init(&bsopts, sizeof(bsopts)); 7788 bsopts.cluster_sz = cluster_sz; 7789 bsopts.esnap_bs_dev_create = ut_esnap_create; 7790 7791 /* Create device with desired block size */ 7792 dev = init_dev(); 7793 dev->blocklen = bs_blksz; 7794 dev->blockcnt = DEV_BUFFER_SIZE / dev->blocklen; 7795 7796 /* Initialize a new blob store */ 7797 spdk_bs_init(dev, &bsopts, bs_op_with_handle_complete, NULL); 7798 poll_threads(); 7799 CU_ASSERT(g_bserrno == 0); 7800 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 7801 SPDK_CU_ASSERT_FATAL(g_bs->io_unit_size == bs_blksz); 7802 bs = g_bs; 7803 7804 bs_ch = spdk_bs_alloc_io_channel(bs); 7805 SPDK_CU_ASSERT_FATAL(bs_ch != NULL); 7806 7807 /* Create and open the esnap clone */ 7808 ut_spdk_blob_opts_init(&opts); 7809 ut_esnap_opts_init(esnap_blksz, esnap_num_blocks, __func__, NULL, &esnap_opts); 7810 opts.esnap_id = &esnap_opts; 7811 opts.esnap_id_len = sizeof(esnap_opts); 7812 opts.num_clusters = esnap_num_clusters; 7813 blob = ut_blob_create_and_open(bs, &opts); 7814 SPDK_CU_ASSERT_FATAL(blob != NULL); 7815 7816 /* Verify that large reads return the content of the esnap device */ 7817 CU_ASSERT(blob_esnap_verify_contents(blob, bs_ch, 0, esnap_sz, esnap_sz, "read")); 7818 CU_ASSERT(blob_esnap_verify_contents(blob, bs_ch, 0, esnap_sz, esnap_sz, "readv")); 7819 CU_ASSERT(blob_esnap_verify_contents(blob, bs_ch, 0, esnap_sz, esnap_sz, "readv_ext")); 7820 /* Verify that small reads return the content of the esnap device */ 7821 CU_ASSERT(blob_esnap_verify_contents(blob, bs_ch, 0, esnap_sz, bs_blksz, "read")); 7822 CU_ASSERT(blob_esnap_verify_contents(blob, bs_ch, 0, esnap_sz, bs_blksz, "readv")); 7823 CU_ASSERT(blob_esnap_verify_contents(blob, bs_ch, 0, esnap_sz, bs_blksz, "readv_ext")); 7824 7825 /* Write one blob block at a time; verify that the surrounding blocks are OK */ 7826 for (block = 0; block < blob_num_blocks; block++) { 7827 char buf[bs_blksz]; 7828 union ut_word word; 7829 7830 word.f.blob_id = 0xfedcba90; 7831 word.f.lba = block; 7832 ut_memset8(buf, word.num, bs_blksz); 7833 7834 spdk_blob_io_write(blob, bs_ch, buf, block, 1, bs_op_complete, NULL); 7835 poll_threads(); 7836 CU_ASSERT(g_bserrno == 0); 7837 if (g_bserrno != 0) { 7838 break; 7839 } 7840 7841 /* Read and verify the block before the current block */ 7842 if (block != 0) { 7843 spdk_blob_io_read(blob, bs_ch, buf, block - 1, 1, bs_op_complete, NULL); 7844 poll_threads(); 7845 CU_ASSERT(g_bserrno == 0); 7846 if (g_bserrno != 0) { 7847 break; 7848 } 7849 CU_ASSERT(ut_esnap_content_is_correct(buf, bs_blksz, word.f.blob_id, 7850 (block - 1) * bs_blksz, bs_blksz)); 7851 } 7852 7853 /* Read and verify the current block */ 7854 spdk_blob_io_read(blob, bs_ch, buf, block, 1, bs_op_complete, NULL); 7855 poll_threads(); 7856 CU_ASSERT(g_bserrno == 0); 7857 if (g_bserrno != 0) { 7858 break; 7859 } 7860 CU_ASSERT(ut_esnap_content_is_correct(buf, bs_blksz, word.f.blob_id, 7861 block * bs_blksz, bs_blksz)); 7862 7863 /* Check the block that follows */ 7864 if (block + 1 < blob_num_blocks) { 7865 g_bserrno = 0xbad; 7866 spdk_blob_io_read(blob, bs_ch, buf, block + 1, 1, bs_op_complete, NULL); 7867 poll_threads(); 7868 CU_ASSERT(g_bserrno == 0); 7869 if (g_bserrno != 0) { 7870 break; 7871 } 7872 CU_ASSERT(ut_esnap_content_is_correct(buf, bs_blksz, blob->id, 7873 (block + 1) * bs_blksz, 7874 esnap_blksz)); 7875 } 7876 } 7877 7878 /* Clean up */ 7879 spdk_bs_free_io_channel(bs_ch); 7880 g_bserrno = 0xbad; 7881 spdk_blob_close(blob, blob_op_complete, NULL); 7882 poll_threads(); 7883 CU_ASSERT(g_bserrno == 0); 7884 spdk_bs_unload(g_bs, bs_op_complete, NULL); 7885 poll_threads(); 7886 CU_ASSERT(g_bserrno == 0); 7887 g_bs = NULL; 7888 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE); 7889 } 7890 7891 static void 7892 blob_esnap_io_4096_4096(void) 7893 { 7894 blob_esnap_io_size(4096, 4096); 7895 } 7896 7897 static void 7898 blob_esnap_io_512_512(void) 7899 { 7900 blob_esnap_io_size(512, 512); 7901 } 7902 7903 static void 7904 blob_esnap_io_4096_512(void) 7905 { 7906 blob_esnap_io_size(4096, 512); 7907 } 7908 7909 static void 7910 blob_esnap_io_512_4096(void) 7911 { 7912 struct spdk_bs_dev *dev; 7913 struct spdk_blob_store *bs; 7914 struct spdk_bs_opts bs_opts; 7915 struct spdk_blob_opts blob_opts; 7916 struct ut_esnap_opts esnap_opts; 7917 uint64_t cluster_sz = 16 * 1024; 7918 uint32_t bs_blksz = 512; 7919 uint32_t esnap_blksz = 4096; 7920 uint64_t esnap_num_blocks = 64; 7921 spdk_blob_id blobid; 7922 7923 /* Create device with desired block size */ 7924 dev = init_dev(); 7925 dev->blocklen = bs_blksz; 7926 dev->blockcnt = DEV_BUFFER_SIZE / dev->blocklen; 7927 7928 /* Initialize a new blob store */ 7929 spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); 7930 bs_opts.cluster_sz = cluster_sz; 7931 bs_opts.esnap_bs_dev_create = ut_esnap_create; 7932 spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL); 7933 poll_threads(); 7934 CU_ASSERT(g_bserrno == 0); 7935 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 7936 SPDK_CU_ASSERT_FATAL(g_bs->io_unit_size == bs_blksz); 7937 bs = g_bs; 7938 7939 /* Try to create and open the esnap clone. Create should succeed, open should fail. */ 7940 ut_spdk_blob_opts_init(&blob_opts); 7941 ut_esnap_opts_init(esnap_blksz, esnap_num_blocks, __func__, NULL, &esnap_opts); 7942 blob_opts.esnap_id = &esnap_opts; 7943 blob_opts.esnap_id_len = sizeof(esnap_opts); 7944 blob_opts.num_clusters = esnap_num_blocks * esnap_blksz / bs_blksz; 7945 spdk_bs_create_blob_ext(bs, &blob_opts, blob_op_with_id_complete, NULL); 7946 poll_threads(); 7947 CU_ASSERT(g_bserrno == 0); 7948 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 7949 blobid = g_blobid; 7950 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 7951 poll_threads(); 7952 CU_ASSERT(g_bserrno == -EINVAL); 7953 CU_ASSERT(g_blob == NULL); 7954 7955 /* Clean up */ 7956 spdk_bs_unload(bs, bs_op_complete, NULL); 7957 poll_threads(); 7958 CU_ASSERT(g_bserrno == 0); 7959 g_bs = NULL; 7960 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE); 7961 } 7962 7963 static void 7964 blob_esnap_thread_add_remove(void) 7965 { 7966 struct spdk_blob_store *bs = g_bs; 7967 struct spdk_blob_opts opts; 7968 struct ut_esnap_opts ut_esnap_opts; 7969 struct spdk_blob *blob; 7970 struct ut_esnap_dev *ut_dev; 7971 spdk_blob_id blobid; 7972 uint64_t start_thread = g_ut_thread_id; 7973 bool destroyed = false; 7974 struct spdk_io_channel *ch0, *ch1; 7975 struct ut_esnap_channel *ut_ch0, *ut_ch1; 7976 const uint32_t blocklen = bs->io_unit_size; 7977 char buf[blocklen * 4]; 7978 7979 SPDK_CU_ASSERT_FATAL(g_ut_num_threads > 1); 7980 set_thread(0); 7981 7982 /* Create the esnap clone */ 7983 ut_esnap_opts_init(blocklen, 2048, "add_remove_1", &destroyed, &ut_esnap_opts); 7984 ut_spdk_blob_opts_init(&opts); 7985 opts.esnap_id = &ut_esnap_opts; 7986 opts.esnap_id_len = sizeof(ut_esnap_opts); 7987 opts.num_clusters = 10; 7988 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 7989 poll_threads(); 7990 CU_ASSERT(g_bserrno == 0); 7991 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 7992 blobid = g_blobid; 7993 7994 /* Open the blob. No channels should be allocated yet. */ 7995 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 7996 poll_threads(); 7997 CU_ASSERT(g_bserrno == 0); 7998 CU_ASSERT(g_blob != NULL); 7999 blob = g_blob; 8000 ut_dev = (struct ut_esnap_dev *)blob->back_bs_dev; 8001 CU_ASSERT(ut_dev != NULL); 8002 CU_ASSERT(ut_dev->num_channels == 0); 8003 8004 /* Create a channel on thread 0. It is lazily created on the first read. */ 8005 ch0 = spdk_bs_alloc_io_channel(bs); 8006 CU_ASSERT(ch0 != NULL); 8007 ut_ch0 = ut_esnap_get_io_channel(ch0, blobid); 8008 CU_ASSERT(ut_ch0 == NULL); 8009 CU_ASSERT(ut_dev->num_channels == 0); 8010 spdk_blob_io_read(blob, ch0, buf, 0, 1, bs_op_complete, NULL); 8011 poll_threads(); 8012 CU_ASSERT(g_bserrno == 0); 8013 CU_ASSERT(ut_dev->num_channels == 1); 8014 ut_ch0 = ut_esnap_get_io_channel(ch0, blobid); 8015 CU_ASSERT(ut_ch0 != NULL); 8016 CU_ASSERT(ut_ch0->blocks_read == 1); 8017 8018 /* Create a channel on thread 1 and verify its lazy creation too. */ 8019 set_thread(1); 8020 ch1 = spdk_bs_alloc_io_channel(bs); 8021 CU_ASSERT(ch1 != NULL); 8022 ut_ch1 = ut_esnap_get_io_channel(ch1, blobid); 8023 CU_ASSERT(ut_ch1 == NULL); 8024 CU_ASSERT(ut_dev->num_channels == 1); 8025 spdk_blob_io_read(blob, ch1, buf, 0, 4, bs_op_complete, NULL); 8026 poll_threads(); 8027 CU_ASSERT(g_bserrno == 0); 8028 CU_ASSERT(ut_dev->num_channels == 2); 8029 ut_ch1 = ut_esnap_get_io_channel(ch1, blobid); 8030 CU_ASSERT(ut_ch1 != NULL); 8031 CU_ASSERT(ut_ch1->blocks_read == 4); 8032 8033 /* Close the channel on thread 0 and verify the bs_dev channel is also gone. */ 8034 set_thread(0); 8035 spdk_bs_free_io_channel(ch0); 8036 poll_threads(); 8037 CU_ASSERT(ut_dev->num_channels == 1); 8038 8039 /* Close the blob. There is no outstanding IO so it should close right away. */ 8040 g_bserrno = 0xbad; 8041 spdk_blob_close(blob, blob_op_complete, NULL); 8042 poll_threads(); 8043 CU_ASSERT(g_bserrno == 0); 8044 CU_ASSERT(destroyed); 8045 8046 /* The esnap channel for the blob should be gone now too. */ 8047 ut_ch1 = ut_esnap_get_io_channel(ch1, blobid); 8048 CU_ASSERT(ut_ch1 == NULL); 8049 8050 /* Clean up */ 8051 set_thread(1); 8052 spdk_bs_free_io_channel(ch1); 8053 set_thread(start_thread); 8054 } 8055 8056 static void 8057 freeze_done(void *cb_arg, int bserrno) 8058 { 8059 uint32_t *freeze_cnt = cb_arg; 8060 8061 CU_ASSERT(bserrno == 0); 8062 (*freeze_cnt)++; 8063 } 8064 8065 static void 8066 unfreeze_done(void *cb_arg, int bserrno) 8067 { 8068 uint32_t *unfreeze_cnt = cb_arg; 8069 8070 CU_ASSERT(bserrno == 0); 8071 (*unfreeze_cnt)++; 8072 } 8073 8074 static void 8075 blob_nested_freezes(void) 8076 { 8077 struct spdk_blob_store *bs = g_bs; 8078 struct spdk_blob *blob; 8079 struct spdk_io_channel *channel[2]; 8080 struct spdk_blob_opts opts; 8081 uint32_t freeze_cnt, unfreeze_cnt; 8082 int i; 8083 8084 for (i = 0; i < 2; i++) { 8085 set_thread(i); 8086 channel[i] = spdk_bs_alloc_io_channel(bs); 8087 SPDK_CU_ASSERT_FATAL(channel[i] != NULL); 8088 } 8089 8090 set_thread(0); 8091 8092 ut_spdk_blob_opts_init(&opts); 8093 blob = ut_blob_create_and_open(bs, &opts); 8094 8095 /* First just test a single freeze/unfreeze. */ 8096 freeze_cnt = 0; 8097 unfreeze_cnt = 0; 8098 CU_ASSERT(blob->frozen_refcnt == 0); 8099 blob_freeze_io(blob, freeze_done, &freeze_cnt); 8100 CU_ASSERT(blob->frozen_refcnt == 1); 8101 CU_ASSERT(freeze_cnt == 0); 8102 poll_threads(); 8103 CU_ASSERT(freeze_cnt == 1); 8104 blob_unfreeze_io(blob, unfreeze_done, &unfreeze_cnt); 8105 CU_ASSERT(blob->frozen_refcnt == 0); 8106 CU_ASSERT(unfreeze_cnt == 0); 8107 poll_threads(); 8108 CU_ASSERT(unfreeze_cnt == 1); 8109 8110 /* Now nest multiple freeze/unfreeze operations. We should 8111 * expect a callback for each operation, but only after 8112 * the threads have been polled to ensure a for_each_channel() 8113 * was executed. 8114 */ 8115 freeze_cnt = 0; 8116 unfreeze_cnt = 0; 8117 CU_ASSERT(blob->frozen_refcnt == 0); 8118 blob_freeze_io(blob, freeze_done, &freeze_cnt); 8119 CU_ASSERT(blob->frozen_refcnt == 1); 8120 CU_ASSERT(freeze_cnt == 0); 8121 blob_freeze_io(blob, freeze_done, &freeze_cnt); 8122 CU_ASSERT(blob->frozen_refcnt == 2); 8123 CU_ASSERT(freeze_cnt == 0); 8124 poll_threads(); 8125 CU_ASSERT(freeze_cnt == 2); 8126 blob_unfreeze_io(blob, unfreeze_done, &unfreeze_cnt); 8127 CU_ASSERT(blob->frozen_refcnt == 1); 8128 CU_ASSERT(unfreeze_cnt == 0); 8129 blob_unfreeze_io(blob, unfreeze_done, &unfreeze_cnt); 8130 CU_ASSERT(blob->frozen_refcnt == 0); 8131 CU_ASSERT(unfreeze_cnt == 0); 8132 poll_threads(); 8133 CU_ASSERT(unfreeze_cnt == 2); 8134 8135 for (i = 0; i < 2; i++) { 8136 set_thread(i); 8137 spdk_bs_free_io_channel(channel[i]); 8138 } 8139 set_thread(0); 8140 ut_blob_close_and_delete(bs, blob); 8141 8142 poll_threads(); 8143 g_blob = NULL; 8144 g_blobid = 0; 8145 } 8146 8147 static void 8148 blob_ext_md_pages(void) 8149 { 8150 struct spdk_blob_store *bs; 8151 struct spdk_bs_dev *dev; 8152 struct spdk_blob *blob; 8153 struct spdk_blob_opts opts; 8154 struct spdk_bs_opts bs_opts; 8155 uint64_t free_clusters; 8156 8157 dev = init_dev(); 8158 spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); 8159 snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE"); 8160 /* Issue #2932 was a bug in how we use bs_allocate_cluster() during resize. 8161 * It requires num_md_pages that is much smaller than the number of clusters. 8162 * Make sure we can create a blob that uses all of the free clusters. 8163 */ 8164 bs_opts.cluster_sz = 65536; 8165 bs_opts.num_md_pages = 16; 8166 8167 /* Initialize a new blob store */ 8168 spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL); 8169 poll_threads(); 8170 CU_ASSERT(g_bserrno == 0); 8171 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 8172 bs = g_bs; 8173 8174 free_clusters = spdk_bs_free_cluster_count(bs); 8175 8176 ut_spdk_blob_opts_init(&opts); 8177 opts.num_clusters = free_clusters; 8178 8179 blob = ut_blob_create_and_open(bs, &opts); 8180 spdk_blob_close(blob, blob_op_complete, NULL); 8181 CU_ASSERT(g_bserrno == 0); 8182 8183 spdk_bs_unload(bs, bs_op_complete, NULL); 8184 poll_threads(); 8185 CU_ASSERT(g_bserrno == 0); 8186 g_bs = NULL; 8187 } 8188 8189 static void 8190 blob_esnap_clone_snapshot(void) 8191 { 8192 /* 8193 * When a snapshot is created, the blob that is being snapped becomes 8194 * the leaf node (a clone of the snapshot) and the newly created 8195 * snapshot sits between the snapped blob and the external snapshot. 8196 * 8197 * Before creating snap1 8198 * 8199 * ,--------. ,----------. 8200 * | blob | | vbdev | 8201 * | blob1 |<----| nvme1n42 | 8202 * | (rw) | | (ro) | 8203 * `--------' `----------' 8204 * Figure 1 8205 * 8206 * After creating snap1 8207 * 8208 * ,--------. ,--------. ,----------. 8209 * | blob | | blob | | vbdev | 8210 * | blob1 |<----| snap1 |<----| nvme1n42 | 8211 * | (rw) | | (ro) | | (ro) | 8212 * `--------' `--------' `----------' 8213 * Figure 2 8214 * 8215 * Starting from Figure 2, if snap1 is removed, the chain reverts to 8216 * what it looks like in Figure 1. 8217 * 8218 * Starting from Figure 2, if blob1 is removed, the chain becomes: 8219 * 8220 * ,--------. ,----------. 8221 * | blob | | vbdev | 8222 * | snap1 |<----| nvme1n42 | 8223 * | (ro) | | (ro) | 8224 * `--------' `----------' 8225 * Figure 3 8226 * 8227 * In each case, the blob pointed to by the nvme vbdev is considered 8228 * the "esnap clone". The esnap clone must have: 8229 * 8230 * - XATTR_INTERNAL for BLOB_EXTERNAL_SNAPSHOT_ID (e.g. name or UUID) 8231 * - blob->invalid_flags must contain SPDK_BLOB_EXTERNAL_SNAPSHOT 8232 * - blob->parent_id must be SPDK_BLOBID_EXTERNAL_SNAPSHOT. 8233 * 8234 * No other blob that descends from the esnap clone may have any of 8235 * those set. 8236 */ 8237 struct spdk_blob_store *bs = g_bs; 8238 const uint32_t blocklen = bs->io_unit_size; 8239 struct spdk_blob_opts opts; 8240 struct ut_esnap_opts esnap_opts; 8241 struct spdk_blob *blob, *snap_blob; 8242 spdk_blob_id blobid, snap_blobid; 8243 bool destroyed = false; 8244 8245 /* Create the esnap clone */ 8246 ut_esnap_opts_init(blocklen, 2048, __func__, &destroyed, &esnap_opts); 8247 ut_spdk_blob_opts_init(&opts); 8248 opts.esnap_id = &esnap_opts; 8249 opts.esnap_id_len = sizeof(esnap_opts); 8250 opts.num_clusters = 10; 8251 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 8252 poll_threads(); 8253 CU_ASSERT(g_bserrno == 0); 8254 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 8255 blobid = g_blobid; 8256 8257 /* Open the blob. */ 8258 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 8259 poll_threads(); 8260 CU_ASSERT(g_bserrno == 0); 8261 CU_ASSERT(g_blob != NULL); 8262 blob = g_blob; 8263 UT_ASSERT_IS_ESNAP_CLONE(blob, &esnap_opts, sizeof(esnap_opts)); 8264 8265 /* 8266 * Create a snapshot of the blob. The snapshot becomes the esnap clone. 8267 */ 8268 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 8269 poll_threads(); 8270 CU_ASSERT(g_bserrno == 0); 8271 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 8272 snap_blobid = g_blobid; 8273 8274 spdk_bs_open_blob(bs, snap_blobid, blob_op_with_handle_complete, NULL); 8275 poll_threads(); 8276 CU_ASSERT(g_bserrno == 0); 8277 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 8278 snap_blob = g_blob; 8279 8280 UT_ASSERT_IS_NOT_ESNAP_CLONE(blob); 8281 UT_ASSERT_IS_ESNAP_CLONE(snap_blob, &esnap_opts, sizeof(esnap_opts)); 8282 8283 /* 8284 * Delete the snapshot. The original blob becomes the esnap clone. 8285 */ 8286 ut_blob_close_and_delete(bs, snap_blob); 8287 snap_blob = NULL; 8288 snap_blobid = SPDK_BLOBID_INVALID; 8289 UT_ASSERT_IS_ESNAP_CLONE(blob, &esnap_opts, sizeof(esnap_opts)); 8290 8291 /* 8292 * Create the snapshot again, then delete the original blob. The 8293 * snapshot should survive as the esnap clone. 8294 */ 8295 spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL); 8296 poll_threads(); 8297 CU_ASSERT(g_bserrno == 0); 8298 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 8299 snap_blobid = g_blobid; 8300 8301 spdk_bs_open_blob(bs, snap_blobid, blob_op_with_handle_complete, NULL); 8302 poll_threads(); 8303 CU_ASSERT(g_bserrno == 0); 8304 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 8305 snap_blob = g_blob; 8306 8307 UT_ASSERT_IS_NOT_ESNAP_CLONE(blob); 8308 UT_ASSERT_IS_ESNAP_CLONE(snap_blob, &esnap_opts, sizeof(esnap_opts)); 8309 8310 ut_blob_close_and_delete(bs, blob); 8311 blob = NULL; 8312 blobid = SPDK_BLOBID_INVALID; 8313 UT_ASSERT_IS_ESNAP_CLONE(snap_blob, &esnap_opts, sizeof(esnap_opts)); 8314 8315 /* 8316 * Clone the snapshot. The snapshot continues to be the esnap clone. 8317 */ 8318 spdk_bs_create_clone(bs, snap_blobid, NULL, blob_op_with_id_complete, NULL); 8319 poll_threads(); 8320 CU_ASSERT(g_bserrno == 0); 8321 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 8322 blobid = g_blobid; 8323 8324 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 8325 poll_threads(); 8326 CU_ASSERT(g_bserrno == 0); 8327 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 8328 blob = g_blob; 8329 8330 UT_ASSERT_IS_NOT_ESNAP_CLONE(blob); 8331 UT_ASSERT_IS_ESNAP_CLONE(snap_blob, &esnap_opts, sizeof(esnap_opts)); 8332 8333 /* 8334 * Delete the snapshot. The clone becomes the esnap clone. 8335 */ 8336 ut_blob_close_and_delete(bs, snap_blob); 8337 snap_blob = NULL; 8338 snap_blobid = SPDK_BLOBID_INVALID; 8339 UT_ASSERT_IS_ESNAP_CLONE(blob, &esnap_opts, sizeof(esnap_opts)); 8340 8341 /* 8342 * Clean up 8343 */ 8344 ut_blob_close_and_delete(bs, blob); 8345 } 8346 8347 static uint64_t 8348 _blob_esnap_clone_hydrate(bool inflate) 8349 { 8350 struct spdk_blob_store *bs = g_bs; 8351 struct spdk_blob_opts opts; 8352 struct ut_esnap_opts esnap_opts; 8353 struct spdk_blob *blob; 8354 spdk_blob_id blobid; 8355 struct spdk_io_channel *channel; 8356 bool destroyed = false; 8357 const uint32_t blocklen = spdk_bs_get_io_unit_size(bs); 8358 const uint32_t cluster_sz = spdk_bs_get_cluster_size(bs); 8359 const uint64_t esnap_num_clusters = 4; 8360 const uint32_t esnap_sz = cluster_sz * esnap_num_clusters; 8361 const uint64_t esnap_num_blocks = esnap_sz / blocklen; 8362 uint64_t num_failures = CU_get_number_of_failures(); 8363 8364 channel = spdk_bs_alloc_io_channel(bs); 8365 SPDK_CU_ASSERT_FATAL(channel != NULL); 8366 8367 /* Create the esnap clone */ 8368 ut_spdk_blob_opts_init(&opts); 8369 ut_esnap_opts_init(blocklen, esnap_num_blocks, __func__, &destroyed, &esnap_opts); 8370 opts.esnap_id = &esnap_opts; 8371 opts.esnap_id_len = sizeof(esnap_opts); 8372 opts.num_clusters = esnap_num_clusters; 8373 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 8374 poll_threads(); 8375 CU_ASSERT(g_bserrno == 0); 8376 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 8377 blobid = g_blobid; 8378 8379 /* Open the esnap clone */ 8380 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 8381 poll_threads(); 8382 CU_ASSERT(g_bserrno == 0); 8383 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 8384 blob = g_blob; 8385 UT_ASSERT_IS_ESNAP_CLONE(blob, &esnap_opts, sizeof(esnap_opts)); 8386 8387 /* 8388 * Inflate or decouple the blob then verify that it is no longer an esnap clone and has 8389 * right content 8390 */ 8391 if (inflate) { 8392 spdk_bs_inflate_blob(bs, channel, blobid, blob_op_complete, NULL); 8393 } else { 8394 spdk_bs_blob_decouple_parent(bs, channel, blobid, blob_op_complete, NULL); 8395 } 8396 poll_threads(); 8397 CU_ASSERT(g_bserrno == 0); 8398 UT_ASSERT_IS_NOT_ESNAP_CLONE(blob); 8399 CU_ASSERT(blob_esnap_verify_contents(blob, channel, 0, esnap_sz, esnap_sz, "read")); 8400 ut_blob_close_and_delete(bs, blob); 8401 8402 /* 8403 * Clean up 8404 */ 8405 spdk_bs_free_io_channel(channel); 8406 poll_threads(); 8407 8408 /* Return number of new failures */ 8409 return CU_get_number_of_failures() - num_failures; 8410 } 8411 8412 static void 8413 blob_esnap_clone_inflate(void) 8414 { 8415 _blob_esnap_clone_hydrate(true); 8416 } 8417 8418 static void 8419 blob_esnap_clone_decouple(void) 8420 { 8421 _blob_esnap_clone_hydrate(false); 8422 } 8423 8424 static void 8425 blob_esnap_hotplug(void) 8426 { 8427 struct spdk_blob_store *bs = g_bs; 8428 struct ut_esnap_opts esnap1_opts, esnap2_opts; 8429 struct spdk_blob_opts opts; 8430 struct spdk_blob *blob; 8431 struct spdk_bs_dev *bs_dev; 8432 struct ut_esnap_dev *esnap_dev; 8433 uint32_t cluster_sz = spdk_bs_get_cluster_size(bs); 8434 uint32_t block_sz = spdk_bs_get_io_unit_size(bs); 8435 const uint32_t esnap_num_clusters = 4; 8436 uint64_t esnap_num_blocks = cluster_sz * esnap_num_clusters / block_sz; 8437 bool destroyed1 = false, destroyed2 = false; 8438 uint64_t start_thread = g_ut_thread_id; 8439 struct spdk_io_channel *ch0, *ch1; 8440 char buf[block_sz]; 8441 8442 /* Create and open an esnap clone blob */ 8443 ut_spdk_blob_opts_init(&opts); 8444 ut_esnap_opts_init(block_sz, esnap_num_blocks, "esnap1", &destroyed1, &esnap1_opts); 8445 opts.esnap_id = &esnap1_opts; 8446 opts.esnap_id_len = sizeof(esnap1_opts); 8447 opts.num_clusters = esnap_num_clusters; 8448 blob = ut_blob_create_and_open(bs, &opts); 8449 CU_ASSERT(blob != NULL); 8450 CU_ASSERT(spdk_blob_is_esnap_clone(blob)); 8451 SPDK_CU_ASSERT_FATAL(blob->back_bs_dev != NULL); 8452 esnap_dev = (struct ut_esnap_dev *)blob->back_bs_dev; 8453 CU_ASSERT(strcmp(esnap_dev->ut_opts.name, "esnap1") == 0); 8454 8455 /* Replace the external snapshot */ 8456 ut_esnap_opts_init(block_sz, esnap_num_blocks, "esnap2", &destroyed2, &esnap2_opts); 8457 bs_dev = ut_esnap_dev_alloc(&esnap2_opts); 8458 CU_ASSERT(!destroyed1); 8459 CU_ASSERT(!destroyed2); 8460 g_bserrno = 0xbad; 8461 spdk_blob_set_esnap_bs_dev(blob, bs_dev, bs_op_complete, NULL); 8462 poll_threads(); 8463 CU_ASSERT(g_bserrno == 0); 8464 CU_ASSERT(destroyed1); 8465 CU_ASSERT(!destroyed2); 8466 SPDK_CU_ASSERT_FATAL(bs_dev == blob->back_bs_dev); 8467 SPDK_CU_ASSERT_FATAL(bs_dev == spdk_blob_get_esnap_bs_dev(blob)); 8468 esnap_dev = (struct ut_esnap_dev *)blob->back_bs_dev; 8469 CU_ASSERT(strcmp(esnap_dev->ut_opts.name, "esnap2") == 0); 8470 8471 /* Create a couple channels */ 8472 set_thread(0); 8473 ch0 = spdk_bs_alloc_io_channel(bs); 8474 CU_ASSERT(ch0 != NULL); 8475 spdk_blob_io_read(blob, ch0, buf, 0, 1, bs_op_complete, NULL); 8476 set_thread(1); 8477 ch1 = spdk_bs_alloc_io_channel(bs); 8478 CU_ASSERT(ch1 != NULL); 8479 spdk_blob_io_read(blob, ch1, buf, 0, 1, bs_op_complete, NULL); 8480 set_thread(start_thread); 8481 poll_threads(); 8482 CU_ASSERT(esnap_dev->num_channels == 2); 8483 8484 /* Replace the external snapshot */ 8485 ut_esnap_opts_init(block_sz, esnap_num_blocks, "esnap1a", &destroyed1, &esnap1_opts); 8486 bs_dev = ut_esnap_dev_alloc(&esnap1_opts); 8487 destroyed1 = destroyed2 = false; 8488 g_bserrno = 0xbad; 8489 spdk_blob_set_esnap_bs_dev(blob, bs_dev, bs_op_complete, NULL); 8490 poll_threads(); 8491 CU_ASSERT(g_bserrno == 0); 8492 CU_ASSERT(!destroyed1); 8493 CU_ASSERT(destroyed2); 8494 SPDK_CU_ASSERT_FATAL(blob->back_bs_dev != NULL); 8495 esnap_dev = (struct ut_esnap_dev *)blob->back_bs_dev; 8496 CU_ASSERT(strcmp(esnap_dev->ut_opts.name, "esnap1a") == 0); 8497 8498 /* Clean up */ 8499 set_thread(0); 8500 spdk_bs_free_io_channel(ch0); 8501 set_thread(1); 8502 spdk_bs_free_io_channel(ch1); 8503 set_thread(start_thread); 8504 g_bserrno = 0xbad; 8505 spdk_blob_close(blob, bs_op_complete, NULL); 8506 poll_threads(); 8507 CU_ASSERT(g_bserrno == 0); 8508 } 8509 8510 static bool g_blob_is_degraded; 8511 static int g_blob_is_degraded_called; 8512 8513 static bool 8514 _blob_is_degraded(struct spdk_bs_dev *dev) 8515 { 8516 g_blob_is_degraded_called++; 8517 return g_blob_is_degraded; 8518 } 8519 8520 static void 8521 blob_is_degraded(void) 8522 { 8523 struct spdk_bs_dev bs_is_degraded_null = { 0 }; 8524 struct spdk_bs_dev bs_is_degraded = { .is_degraded = _blob_is_degraded }; 8525 8526 /* No back_bs_dev, no bs->dev->is_degraded */ 8527 g_blob_is_degraded_called = 0; 8528 CU_ASSERT(!spdk_blob_is_degraded(g_blob)); 8529 CU_ASSERT(g_blob_is_degraded_called == 0); 8530 8531 /* No back_bs_dev, blobstore device degraded */ 8532 g_bs->dev->is_degraded = _blob_is_degraded; 8533 g_blob_is_degraded_called = 0; 8534 g_blob_is_degraded = true; 8535 CU_ASSERT(spdk_blob_is_degraded(g_blob)); 8536 CU_ASSERT(g_blob_is_degraded_called == 1); 8537 8538 /* No back_bs_dev, blobstore device not degraded */ 8539 g_bs->dev->is_degraded = _blob_is_degraded; 8540 g_blob_is_degraded_called = 0; 8541 g_blob_is_degraded = false; 8542 CU_ASSERT(!spdk_blob_is_degraded(g_blob)); 8543 CU_ASSERT(g_blob_is_degraded_called == 1); 8544 8545 /* back_bs_dev does not define is_degraded, no bs->dev->is_degraded */ 8546 g_bs->dev->is_degraded = NULL; 8547 g_blob->back_bs_dev = &bs_is_degraded_null; 8548 g_blob_is_degraded_called = 0; 8549 g_blob_is_degraded = false; 8550 CU_ASSERT(!spdk_blob_is_degraded(g_blob)); 8551 CU_ASSERT(g_blob_is_degraded_called == 0); 8552 8553 /* back_bs_dev is not degraded, no bs->dev->is_degraded */ 8554 g_bs->dev->is_degraded = NULL; 8555 g_blob->back_bs_dev = &bs_is_degraded; 8556 g_blob_is_degraded_called = 0; 8557 g_blob_is_degraded = false; 8558 CU_ASSERT(!spdk_blob_is_degraded(g_blob)); 8559 CU_ASSERT(g_blob_is_degraded_called == 1); 8560 8561 /* back_bs_dev is degraded, no bs->dev->is_degraded */ 8562 g_bs->dev->is_degraded = NULL; 8563 g_blob->back_bs_dev = &bs_is_degraded; 8564 g_blob_is_degraded_called = 0; 8565 g_blob_is_degraded = true; 8566 CU_ASSERT(spdk_blob_is_degraded(g_blob)); 8567 CU_ASSERT(g_blob_is_degraded_called == 1); 8568 8569 /* back_bs_dev is not degraded, blobstore device is not degraded */ 8570 g_bs->dev->is_degraded = _blob_is_degraded; 8571 g_blob->back_bs_dev = &bs_is_degraded; 8572 g_blob_is_degraded_called = 0; 8573 g_blob_is_degraded = false; 8574 CU_ASSERT(!spdk_blob_is_degraded(g_blob)); 8575 CU_ASSERT(g_blob_is_degraded_called == 2); 8576 8577 g_blob->back_bs_dev = NULL; 8578 } 8579 8580 static void 8581 suite_bs_setup(void) 8582 { 8583 struct spdk_bs_dev *dev; 8584 8585 dev = init_dev(); 8586 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE); 8587 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 8588 poll_threads(); 8589 CU_ASSERT(g_bserrno == 0); 8590 CU_ASSERT(g_bs != NULL); 8591 } 8592 8593 static void 8594 suite_esnap_bs_setup(void) 8595 { 8596 struct spdk_bs_dev *dev; 8597 struct spdk_bs_opts bs_opts; 8598 8599 dev = init_dev(); 8600 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE); 8601 spdk_bs_opts_init(&bs_opts, sizeof(bs_opts)); 8602 bs_opts.cluster_sz = 16 * 1024; 8603 bs_opts.esnap_bs_dev_create = ut_esnap_create; 8604 spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL); 8605 poll_threads(); 8606 CU_ASSERT(g_bserrno == 0); 8607 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 8608 } 8609 8610 static void 8611 suite_bs_cleanup(void) 8612 { 8613 if (g_bs != NULL) { 8614 spdk_bs_unload(g_bs, bs_op_complete, NULL); 8615 poll_threads(); 8616 CU_ASSERT(g_bserrno == 0); 8617 g_bs = NULL; 8618 } 8619 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE); 8620 } 8621 8622 static struct spdk_blob * 8623 ut_blob_create_and_open(struct spdk_blob_store *bs, struct spdk_blob_opts *blob_opts) 8624 { 8625 struct spdk_blob *blob; 8626 struct spdk_blob_opts create_blob_opts; 8627 spdk_blob_id blobid; 8628 8629 if (blob_opts == NULL) { 8630 ut_spdk_blob_opts_init(&create_blob_opts); 8631 blob_opts = &create_blob_opts; 8632 } 8633 8634 spdk_bs_create_blob_ext(bs, blob_opts, blob_op_with_id_complete, NULL); 8635 poll_threads(); 8636 CU_ASSERT(g_bserrno == 0); 8637 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 8638 blobid = g_blobid; 8639 g_blobid = -1; 8640 8641 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 8642 poll_threads(); 8643 CU_ASSERT(g_bserrno == 0); 8644 CU_ASSERT(g_blob != NULL); 8645 blob = g_blob; 8646 8647 g_blob = NULL; 8648 g_bserrno = -1; 8649 8650 return blob; 8651 } 8652 8653 static void 8654 ut_blob_close_and_delete(struct spdk_blob_store *bs, struct spdk_blob *blob) 8655 { 8656 spdk_blob_id blobid = spdk_blob_get_id(blob); 8657 8658 spdk_blob_close(blob, blob_op_complete, NULL); 8659 poll_threads(); 8660 CU_ASSERT(g_bserrno == 0); 8661 g_blob = NULL; 8662 8663 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); 8664 poll_threads(); 8665 CU_ASSERT(g_bserrno == 0); 8666 g_bserrno = -1; 8667 } 8668 8669 static void 8670 suite_blob_setup(void) 8671 { 8672 suite_bs_setup(); 8673 CU_ASSERT(g_bs != NULL); 8674 8675 g_blob = ut_blob_create_and_open(g_bs, NULL); 8676 CU_ASSERT(g_blob != NULL); 8677 } 8678 8679 static void 8680 suite_blob_cleanup(void) 8681 { 8682 ut_blob_close_and_delete(g_bs, g_blob); 8683 CU_ASSERT(g_blob == NULL); 8684 8685 suite_bs_cleanup(); 8686 CU_ASSERT(g_bs == NULL); 8687 } 8688 8689 static int 8690 ut_setup_config_nocopy_noextent(void) 8691 { 8692 g_dev_copy_enabled = false; 8693 g_use_extent_table = false; 8694 8695 return 0; 8696 } 8697 8698 static int 8699 ut_setup_config_nocopy_extent(void) 8700 { 8701 g_dev_copy_enabled = false; 8702 g_use_extent_table = true; 8703 8704 return 0; 8705 } 8706 8707 static int 8708 ut_setup_config_copy_noextent(void) 8709 { 8710 g_dev_copy_enabled = true; 8711 g_use_extent_table = false; 8712 8713 return 0; 8714 } 8715 8716 static int 8717 ut_setup_config_copy_extent(void) 8718 { 8719 g_dev_copy_enabled = true; 8720 g_use_extent_table = true; 8721 8722 return 0; 8723 } 8724 8725 struct ut_config { 8726 const char *suffix; 8727 CU_InitializeFunc setup_cb; 8728 }; 8729 8730 int 8731 main(int argc, char **argv) 8732 { 8733 CU_pSuite suite, suite_bs, suite_blob, suite_esnap_bs; 8734 unsigned int i, num_failures; 8735 char suite_name[4096]; 8736 struct ut_config *config; 8737 struct ut_config configs[] = { 8738 {"nocopy_noextent", ut_setup_config_nocopy_noextent}, 8739 {"nocopy_extent", ut_setup_config_nocopy_extent}, 8740 {"copy_noextent", ut_setup_config_copy_noextent}, 8741 {"copy_extent", ut_setup_config_copy_extent}, 8742 }; 8743 8744 CU_initialize_registry(); 8745 8746 for (i = 0; i < SPDK_COUNTOF(configs); ++i) { 8747 config = &configs[i]; 8748 8749 snprintf(suite_name, sizeof(suite_name), "blob_%s", config->suffix); 8750 suite = CU_add_suite(suite_name, config->setup_cb, NULL); 8751 8752 snprintf(suite_name, sizeof(suite_name), "blob_bs_%s", config->suffix); 8753 suite_bs = CU_add_suite_with_setup_and_teardown(suite_name, config->setup_cb, NULL, 8754 suite_bs_setup, suite_bs_cleanup); 8755 8756 snprintf(suite_name, sizeof(suite_name), "blob_blob_%s", config->suffix); 8757 suite_blob = CU_add_suite_with_setup_and_teardown(suite_name, config->setup_cb, NULL, 8758 suite_blob_setup, suite_blob_cleanup); 8759 8760 snprintf(suite_name, sizeof(suite_name), "blob_esnap_bs_%s", config->suffix); 8761 suite_esnap_bs = CU_add_suite_with_setup_and_teardown(suite_name, config->setup_cb, NULL, 8762 suite_esnap_bs_setup, 8763 suite_bs_cleanup); 8764 8765 CU_ADD_TEST(suite, blob_init); 8766 CU_ADD_TEST(suite_bs, blob_open); 8767 CU_ADD_TEST(suite_bs, blob_create); 8768 CU_ADD_TEST(suite_bs, blob_create_loop); 8769 CU_ADD_TEST(suite_bs, blob_create_fail); 8770 CU_ADD_TEST(suite_bs, blob_create_internal); 8771 CU_ADD_TEST(suite_bs, blob_create_zero_extent); 8772 CU_ADD_TEST(suite, blob_thin_provision); 8773 CU_ADD_TEST(suite_bs, blob_snapshot); 8774 CU_ADD_TEST(suite_bs, blob_clone); 8775 CU_ADD_TEST(suite_bs, blob_inflate); 8776 CU_ADD_TEST(suite_bs, blob_delete); 8777 CU_ADD_TEST(suite_bs, blob_resize_test); 8778 CU_ADD_TEST(suite, blob_read_only); 8779 CU_ADD_TEST(suite_bs, channel_ops); 8780 CU_ADD_TEST(suite_bs, blob_super); 8781 CU_ADD_TEST(suite_blob, blob_write); 8782 CU_ADD_TEST(suite_blob, blob_read); 8783 CU_ADD_TEST(suite_blob, blob_rw_verify); 8784 CU_ADD_TEST(suite_bs, blob_rw_verify_iov); 8785 CU_ADD_TEST(suite_blob, blob_rw_verify_iov_nomem); 8786 CU_ADD_TEST(suite_blob, blob_rw_iov_read_only); 8787 CU_ADD_TEST(suite_bs, blob_unmap); 8788 CU_ADD_TEST(suite_bs, blob_iter); 8789 CU_ADD_TEST(suite_blob, blob_xattr); 8790 CU_ADD_TEST(suite_bs, blob_parse_md); 8791 CU_ADD_TEST(suite, bs_load); 8792 CU_ADD_TEST(suite_bs, bs_load_pending_removal); 8793 CU_ADD_TEST(suite, bs_load_custom_cluster_size); 8794 CU_ADD_TEST(suite, bs_load_after_failed_grow); 8795 CU_ADD_TEST(suite_bs, bs_unload); 8796 CU_ADD_TEST(suite, bs_cluster_sz); 8797 CU_ADD_TEST(suite_bs, bs_usable_clusters); 8798 CU_ADD_TEST(suite, bs_resize_md); 8799 CU_ADD_TEST(suite, bs_destroy); 8800 CU_ADD_TEST(suite, bs_type); 8801 CU_ADD_TEST(suite, bs_super_block); 8802 CU_ADD_TEST(suite, bs_test_recover_cluster_count); 8803 CU_ADD_TEST(suite, bs_test_grow); 8804 CU_ADD_TEST(suite, blob_serialize_test); 8805 CU_ADD_TEST(suite_bs, blob_crc); 8806 CU_ADD_TEST(suite, super_block_crc); 8807 CU_ADD_TEST(suite_blob, blob_dirty_shutdown); 8808 CU_ADD_TEST(suite_bs, blob_flags); 8809 CU_ADD_TEST(suite_bs, bs_version); 8810 CU_ADD_TEST(suite_bs, blob_set_xattrs_test); 8811 CU_ADD_TEST(suite_bs, blob_thin_prov_alloc); 8812 CU_ADD_TEST(suite_bs, blob_insert_cluster_msg_test); 8813 CU_ADD_TEST(suite_bs, blob_thin_prov_rw); 8814 CU_ADD_TEST(suite, blob_thin_prov_write_count_io); 8815 CU_ADD_TEST(suite_bs, blob_thin_prov_rle); 8816 CU_ADD_TEST(suite_bs, blob_thin_prov_rw_iov); 8817 CU_ADD_TEST(suite, bs_load_iter_test); 8818 CU_ADD_TEST(suite_bs, blob_snapshot_rw); 8819 CU_ADD_TEST(suite_bs, blob_snapshot_rw_iov); 8820 CU_ADD_TEST(suite, blob_relations); 8821 CU_ADD_TEST(suite, blob_relations2); 8822 CU_ADD_TEST(suite, blob_relations3); 8823 CU_ADD_TEST(suite, blobstore_clean_power_failure); 8824 CU_ADD_TEST(suite, blob_delete_snapshot_power_failure); 8825 CU_ADD_TEST(suite, blob_create_snapshot_power_failure); 8826 CU_ADD_TEST(suite_bs, blob_inflate_rw); 8827 CU_ADD_TEST(suite_bs, blob_snapshot_freeze_io); 8828 CU_ADD_TEST(suite_bs, blob_operation_split_rw); 8829 CU_ADD_TEST(suite_bs, blob_operation_split_rw_iov); 8830 CU_ADD_TEST(suite, blob_io_unit); 8831 CU_ADD_TEST(suite, blob_io_unit_compatibility); 8832 CU_ADD_TEST(suite_bs, blob_simultaneous_operations); 8833 CU_ADD_TEST(suite_bs, blob_persist_test); 8834 CU_ADD_TEST(suite_bs, blob_decouple_snapshot); 8835 CU_ADD_TEST(suite_bs, blob_seek_io_unit); 8836 CU_ADD_TEST(suite_esnap_bs, blob_esnap_create); 8837 CU_ADD_TEST(suite_bs, blob_nested_freezes); 8838 CU_ADD_TEST(suite, blob_ext_md_pages); 8839 CU_ADD_TEST(suite, blob_esnap_io_4096_4096); 8840 CU_ADD_TEST(suite, blob_esnap_io_512_512); 8841 CU_ADD_TEST(suite, blob_esnap_io_4096_512); 8842 CU_ADD_TEST(suite, blob_esnap_io_512_4096); 8843 CU_ADD_TEST(suite_esnap_bs, blob_esnap_thread_add_remove); 8844 CU_ADD_TEST(suite_esnap_bs, blob_esnap_clone_snapshot); 8845 CU_ADD_TEST(suite_esnap_bs, blob_esnap_clone_inflate); 8846 CU_ADD_TEST(suite_esnap_bs, blob_esnap_clone_decouple); 8847 CU_ADD_TEST(suite_esnap_bs, blob_esnap_clone_reload); 8848 CU_ADD_TEST(suite_esnap_bs, blob_esnap_hotplug); 8849 CU_ADD_TEST(suite_blob, blob_is_degraded); 8850 } 8851 8852 allocate_threads(2); 8853 set_thread(0); 8854 8855 g_dev_buffer = calloc(1, DEV_BUFFER_SIZE); 8856 8857 num_failures = spdk_ut_run_tests(argc, argv, NULL); 8858 8859 free(g_dev_buffer); 8860 8861 free_threads(); 8862 8863 return num_failures; 8864 } 8865