1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "spdk_cunit.h" 37 #include "spdk/blob.h" 38 39 #include "lib/test_env.c" 40 #include "../bs_dev_common.c" 41 #include "blobstore.c" 42 #include "request.c" 43 44 struct spdk_blob_store *g_bs; 45 spdk_blob_id g_blobid; 46 struct spdk_blob *g_blob; 47 int g_bserrno; 48 struct spdk_xattr_names *g_names; 49 int g_done; 50 51 static void 52 _bs_send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx) 53 { 54 fn(ctx); 55 } 56 57 static void 58 bs_op_complete(void *cb_arg, int bserrno) 59 { 60 g_bserrno = bserrno; 61 } 62 63 static void 64 bs_op_with_handle_complete(void *cb_arg, struct spdk_blob_store *bs, 65 int bserrno) 66 { 67 g_bs = bs; 68 g_bserrno = bserrno; 69 } 70 71 static void 72 blob_op_complete(void *cb_arg, int bserrno) 73 { 74 g_bserrno = bserrno; 75 } 76 77 static void 78 blob_op_with_id_complete(void *cb_arg, spdk_blob_id blobid, int bserrno) 79 { 80 g_blobid = blobid; 81 g_bserrno = bserrno; 82 } 83 84 static void 85 blob_op_with_handle_complete(void *cb_arg, struct spdk_blob *blb, int bserrno) 86 { 87 g_blob = blb; 88 g_bserrno = bserrno; 89 } 90 91 static void 92 blob_init(void) 93 { 94 struct spdk_bs_dev dev; 95 96 init_dev(&dev); 97 98 spdk_bs_init(&dev, NULL, bs_op_with_handle_complete, NULL); 99 CU_ASSERT(g_bserrno == 0); 100 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 101 102 spdk_bs_unload(g_bs, bs_op_complete, NULL); 103 CU_ASSERT(g_bserrno == 0); 104 g_bs = NULL; 105 } 106 107 static void 108 blob_super(void) 109 { 110 struct spdk_blob_store *bs; 111 struct spdk_bs_dev dev; 112 spdk_blob_id blobid; 113 114 init_dev(&dev); 115 116 spdk_bs_init(&dev, NULL, bs_op_with_handle_complete, NULL); 117 CU_ASSERT(g_bserrno == 0); 118 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 119 bs = g_bs; 120 121 /* Get the super blob without having set one */ 122 spdk_bs_get_super(bs, blob_op_with_id_complete, NULL); 123 CU_ASSERT(g_bserrno == -ENOENT); 124 CU_ASSERT(g_blobid == SPDK_BLOBID_INVALID); 125 126 /* Create a blob */ 127 spdk_bs_md_create_blob(bs, 128 blob_op_with_id_complete, NULL); 129 CU_ASSERT(g_bserrno == 0); 130 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 131 blobid = g_blobid; 132 133 /* Set the blob as the super blob */ 134 spdk_bs_set_super(bs, blobid, blob_op_complete, NULL); 135 CU_ASSERT(g_bserrno == 0); 136 137 /* Get the super blob */ 138 spdk_bs_get_super(bs, blob_op_with_id_complete, NULL); 139 CU_ASSERT(g_bserrno == 0); 140 CU_ASSERT(blobid == g_blobid); 141 142 spdk_bs_unload(g_bs, bs_op_complete, NULL); 143 CU_ASSERT(g_bserrno == 0); 144 g_bs = NULL; 145 } 146 147 static void 148 blob_open(void) 149 { 150 struct spdk_blob_store *bs; 151 struct spdk_bs_dev dev; 152 struct spdk_blob *blob; 153 spdk_blob_id blobid, blobid2; 154 155 init_dev(&dev); 156 157 spdk_bs_init(&dev, NULL, bs_op_with_handle_complete, NULL); 158 CU_ASSERT(g_bserrno == 0); 159 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 160 bs = g_bs; 161 162 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 163 CU_ASSERT(g_bserrno == 0); 164 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 165 blobid = g_blobid; 166 167 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 168 CU_ASSERT(g_bserrno == 0); 169 CU_ASSERT(g_blob != NULL); 170 blob = g_blob; 171 172 blobid2 = spdk_blob_get_id(blob); 173 CU_ASSERT(blobid == blobid2); 174 175 /* Try to open file again. It should return success. */ 176 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 177 CU_ASSERT(g_bserrno == 0); 178 CU_ASSERT(blob == g_blob); 179 180 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 181 CU_ASSERT(g_bserrno == 0); 182 CU_ASSERT(blob == NULL); 183 184 /* 185 * Close the file a second time, releasing the second reference. This 186 * should succeed. 187 */ 188 blob = g_blob; 189 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 190 CU_ASSERT(g_bserrno == 0); 191 192 /* 193 * Try to open file again. It should succeed. This tests the case 194 * where the file is opened, closed, then re-opened again. 195 */ 196 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 197 CU_ASSERT(g_bserrno == 0); 198 CU_ASSERT(g_blob != NULL); 199 blob = g_blob; 200 201 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 202 CU_ASSERT(g_bserrno == 0); 203 204 spdk_bs_unload(g_bs, bs_op_complete, NULL); 205 CU_ASSERT(g_bserrno == 0); 206 g_bs = NULL; 207 } 208 209 static void 210 blob_delete(void) 211 { 212 struct spdk_blob_store *bs; 213 struct spdk_bs_dev dev; 214 spdk_blob_id blobid; 215 216 init_dev(&dev); 217 218 spdk_bs_init(&dev, NULL, bs_op_with_handle_complete, NULL); 219 CU_ASSERT(g_bserrno == 0); 220 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 221 bs = g_bs; 222 223 /* Create a blob and then delete it. */ 224 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 225 CU_ASSERT(g_bserrno == 0); 226 CU_ASSERT(g_blobid > 0); 227 blobid = g_blobid; 228 229 spdk_bs_md_delete_blob(bs, blobid, blob_op_complete, NULL); 230 CU_ASSERT(g_bserrno == 0); 231 232 /* Try to open the blob */ 233 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 234 CU_ASSERT(g_bserrno == -ENOENT); 235 236 spdk_bs_unload(g_bs, bs_op_complete, NULL); 237 CU_ASSERT(g_bserrno == 0); 238 g_bs = NULL; 239 } 240 241 static void 242 blob_resize(void) 243 { 244 struct spdk_blob_store *bs; 245 struct spdk_bs_dev dev; 246 struct spdk_blob *blob; 247 spdk_blob_id blobid; 248 uint64_t free_clusters; 249 int rc; 250 251 init_dev(&dev); 252 253 spdk_bs_init(&dev, NULL, bs_op_with_handle_complete, NULL); 254 CU_ASSERT(g_bserrno == 0); 255 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 256 bs = g_bs; 257 free_clusters = spdk_bs_free_cluster_count(bs); 258 259 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 260 CU_ASSERT(g_bserrno == 0); 261 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 262 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 263 blobid = g_blobid; 264 265 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 266 CU_ASSERT(g_bserrno == 0); 267 CU_ASSERT(g_blob != NULL); 268 blob = g_blob; 269 270 /* The blob started at 0 clusters. Resize it to be 5. */ 271 rc = spdk_bs_md_resize_blob(blob, 5); 272 CU_ASSERT(rc == 0); 273 CU_ASSERT((free_clusters - 5) == spdk_bs_free_cluster_count(bs)); 274 275 /* Shrink the blob to 3 clusters. This will not actually release 276 * the old clusters until the blob is synced. 277 */ 278 rc = spdk_bs_md_resize_blob(blob, 3); 279 CU_ASSERT(rc == 0); 280 /* Verify there are still 5 clusters in use */ 281 CU_ASSERT((free_clusters - 5) == spdk_bs_free_cluster_count(bs)); 282 283 spdk_bs_md_sync_blob(blob, blob_op_complete, NULL); 284 CU_ASSERT(g_bserrno == 0); 285 /* Now there are only 3 clusters in use */ 286 CU_ASSERT((free_clusters - 3) == spdk_bs_free_cluster_count(bs)); 287 288 /* Resize the blob to be 10 clusters. Growth takes effect immediately. */ 289 rc = spdk_bs_md_resize_blob(blob, 10); 290 CU_ASSERT(rc == 0); 291 CU_ASSERT((free_clusters - 10) == spdk_bs_free_cluster_count(bs)); 292 293 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 294 CU_ASSERT(g_bserrno == 0); 295 296 spdk_bs_md_delete_blob(bs, blobid, blob_op_complete, NULL); 297 CU_ASSERT(g_bserrno == 0); 298 299 spdk_bs_unload(g_bs, bs_op_complete, NULL); 300 CU_ASSERT(g_bserrno == 0); 301 g_bs = NULL; 302 } 303 304 static void 305 channel_ops(void) 306 { 307 struct spdk_blob_store *bs; 308 struct spdk_bs_dev dev; 309 struct spdk_io_channel *channel; 310 311 init_dev(&dev); 312 313 spdk_bs_init(&dev, NULL, bs_op_with_handle_complete, NULL); 314 CU_ASSERT(g_bserrno == 0); 315 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 316 bs = g_bs; 317 318 channel = spdk_bs_alloc_io_channel(bs); 319 CU_ASSERT(channel != NULL); 320 321 spdk_bs_free_io_channel(channel); 322 323 spdk_bs_unload(g_bs, bs_op_complete, NULL); 324 CU_ASSERT(g_bserrno == 0); 325 g_bs = NULL; 326 } 327 328 static void 329 blob_write(void) 330 { 331 struct spdk_blob_store *bs; 332 struct spdk_bs_dev dev; 333 struct spdk_blob *blob; 334 struct spdk_io_channel *channel; 335 spdk_blob_id blobid; 336 uint64_t pages_per_cluster; 337 uint8_t payload[10 * 4096]; 338 int rc; 339 340 init_dev(&dev); 341 342 spdk_bs_init(&dev, NULL, bs_op_with_handle_complete, NULL); 343 CU_ASSERT(g_bserrno == 0); 344 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 345 bs = g_bs; 346 347 pages_per_cluster = spdk_bs_get_cluster_size(bs) / spdk_bs_get_page_size(bs); 348 349 channel = spdk_bs_alloc_io_channel(bs); 350 CU_ASSERT(channel != NULL); 351 352 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 353 CU_ASSERT(g_bserrno == 0); 354 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 355 blobid = g_blobid; 356 357 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 358 CU_ASSERT(g_bserrno == 0); 359 CU_ASSERT(g_blob != NULL); 360 blob = g_blob; 361 362 /* Write to a blob with 0 size */ 363 spdk_bs_io_write_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 364 CU_ASSERT(g_bserrno == -EINVAL); 365 366 /* Resize the blob */ 367 rc = spdk_bs_md_resize_blob(blob, 5); 368 CU_ASSERT(rc == 0); 369 370 /* Write to the blob */ 371 spdk_bs_io_write_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 372 CU_ASSERT(g_bserrno == 0); 373 374 /* Write starting beyond the end */ 375 spdk_bs_io_write_blob(blob, channel, payload, 5 * pages_per_cluster, 1, blob_op_complete, 376 NULL); 377 CU_ASSERT(g_bserrno == -EINVAL); 378 379 /* Write starting at a valid location but going off the end */ 380 spdk_bs_io_write_blob(blob, channel, payload, 4 * pages_per_cluster, pages_per_cluster + 1, 381 blob_op_complete, NULL); 382 CU_ASSERT(g_bserrno == -EINVAL); 383 384 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 385 CU_ASSERT(g_bserrno == 0); 386 387 spdk_bs_free_io_channel(channel); 388 389 spdk_bs_unload(g_bs, bs_op_complete, NULL); 390 CU_ASSERT(g_bserrno == 0); 391 g_bs = NULL; 392 } 393 394 static void 395 blob_read(void) 396 { 397 struct spdk_blob_store *bs; 398 struct spdk_bs_dev dev; 399 struct spdk_blob *blob; 400 struct spdk_io_channel *channel; 401 spdk_blob_id blobid; 402 uint64_t pages_per_cluster; 403 uint8_t payload[10 * 4096]; 404 int rc; 405 406 init_dev(&dev); 407 408 spdk_bs_init(&dev, NULL, bs_op_with_handle_complete, NULL); 409 CU_ASSERT(g_bserrno == 0); 410 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 411 bs = g_bs; 412 413 pages_per_cluster = spdk_bs_get_cluster_size(bs) / spdk_bs_get_page_size(bs); 414 415 channel = spdk_bs_alloc_io_channel(bs); 416 CU_ASSERT(channel != NULL); 417 418 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 419 CU_ASSERT(g_bserrno == 0); 420 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 421 blobid = g_blobid; 422 423 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 424 CU_ASSERT(g_bserrno == 0); 425 CU_ASSERT(g_blob != NULL); 426 blob = g_blob; 427 428 /* Read from a blob with 0 size */ 429 spdk_bs_io_read_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 430 CU_ASSERT(g_bserrno == -EINVAL); 431 432 /* Resize the blob */ 433 rc = spdk_bs_md_resize_blob(blob, 5); 434 CU_ASSERT(rc == 0); 435 436 /* Read from the blob */ 437 spdk_bs_io_read_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 438 CU_ASSERT(g_bserrno == 0); 439 440 /* Read starting beyond the end */ 441 spdk_bs_io_read_blob(blob, channel, payload, 5 * pages_per_cluster, 1, blob_op_complete, 442 NULL); 443 CU_ASSERT(g_bserrno == -EINVAL); 444 445 /* Read starting at a valid location but going off the end */ 446 spdk_bs_io_read_blob(blob, channel, payload, 4 * pages_per_cluster, pages_per_cluster + 1, 447 blob_op_complete, NULL); 448 CU_ASSERT(g_bserrno == -EINVAL); 449 450 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 451 CU_ASSERT(g_bserrno == 0); 452 453 spdk_bs_free_io_channel(channel); 454 455 spdk_bs_unload(g_bs, bs_op_complete, NULL); 456 CU_ASSERT(g_bserrno == 0); 457 g_bs = NULL; 458 } 459 460 static void 461 blob_rw_verify(void) 462 { 463 struct spdk_blob_store *bs; 464 struct spdk_bs_dev dev; 465 struct spdk_blob *blob; 466 struct spdk_io_channel *channel; 467 spdk_blob_id blobid; 468 uint8_t payload_read[10 * 4096]; 469 uint8_t payload_write[10 * 4096]; 470 int rc; 471 472 init_dev(&dev); 473 474 spdk_bs_init(&dev, NULL, bs_op_with_handle_complete, NULL); 475 CU_ASSERT(g_bserrno == 0); 476 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 477 bs = g_bs; 478 479 channel = spdk_bs_alloc_io_channel(bs); 480 CU_ASSERT(channel != NULL); 481 482 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 483 CU_ASSERT(g_bserrno == 0); 484 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 485 blobid = g_blobid; 486 487 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 488 CU_ASSERT(g_bserrno == 0); 489 CU_ASSERT(g_blob != NULL); 490 blob = g_blob; 491 492 rc = spdk_bs_md_resize_blob(blob, 32); 493 CU_ASSERT(rc == 0); 494 495 memset(payload_write, 0xE5, sizeof(payload_write)); 496 spdk_bs_io_write_blob(blob, channel, payload_write, 4, 10, blob_op_complete, NULL); 497 CU_ASSERT(g_bserrno == 0); 498 499 memset(payload_read, 0x00, sizeof(payload_read)); 500 spdk_bs_io_read_blob(blob, channel, payload_read, 4, 10, blob_op_complete, NULL); 501 CU_ASSERT(g_bserrno == 0); 502 CU_ASSERT(memcmp(payload_write, payload_read, 4 * 4096) == 0); 503 504 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 505 CU_ASSERT(g_bserrno == 0); 506 507 spdk_bs_free_io_channel(channel); 508 509 spdk_bs_unload(g_bs, bs_op_complete, NULL); 510 CU_ASSERT(g_bserrno == 0); 511 g_bs = NULL; 512 } 513 514 static void 515 blob_iter(void) 516 { 517 struct spdk_blob_store *bs; 518 struct spdk_bs_dev dev; 519 struct spdk_blob *blob; 520 spdk_blob_id blobid; 521 522 init_dev(&dev); 523 524 spdk_bs_init(&dev, NULL, bs_op_with_handle_complete, NULL); 525 CU_ASSERT(g_bserrno == 0); 526 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 527 bs = g_bs; 528 529 spdk_bs_md_iter_first(bs, blob_op_with_handle_complete, NULL); 530 CU_ASSERT(g_blob == NULL); 531 CU_ASSERT(g_bserrno == -ENOENT); 532 533 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 534 CU_ASSERT(g_bserrno == 0); 535 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 536 blobid = g_blobid; 537 538 spdk_bs_md_iter_first(bs, blob_op_with_handle_complete, NULL); 539 CU_ASSERT(g_blob != NULL); 540 CU_ASSERT(g_bserrno == 0); 541 blob = g_blob; 542 CU_ASSERT(spdk_blob_get_id(blob) == blobid); 543 544 spdk_bs_md_iter_next(bs, &blob, blob_op_with_handle_complete, NULL); 545 CU_ASSERT(g_blob == NULL); 546 CU_ASSERT(g_bserrno == -ENOENT); 547 548 spdk_bs_unload(g_bs, bs_op_complete, NULL); 549 CU_ASSERT(g_bserrno == 0); 550 g_bs = NULL; 551 } 552 553 static void 554 blob_xattr(void) 555 { 556 struct spdk_blob_store *bs; 557 struct spdk_bs_dev dev; 558 struct spdk_blob *blob; 559 spdk_blob_id blobid; 560 uint64_t length; 561 int rc; 562 const char *name1, *name2; 563 const void *value; 564 size_t value_len; 565 struct spdk_xattr_names *names; 566 567 init_dev(&dev); 568 569 spdk_bs_init(&dev, NULL, bs_op_with_handle_complete, NULL); 570 CU_ASSERT(g_bserrno == 0); 571 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 572 bs = g_bs; 573 574 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 575 CU_ASSERT(g_bserrno == 0); 576 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 577 blobid = g_blobid; 578 579 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 580 CU_ASSERT(g_bserrno == 0); 581 CU_ASSERT(g_blob != NULL); 582 blob = g_blob; 583 584 rc = spdk_blob_md_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1); 585 CU_ASSERT(rc == 0); 586 587 length = 2345; 588 rc = spdk_blob_md_set_xattr(blob, "length", &length, sizeof(length)); 589 CU_ASSERT(rc == 0); 590 591 /* Overwrite "length" xattr. */ 592 length = 3456; 593 rc = spdk_blob_md_set_xattr(blob, "length", &length, sizeof(length)); 594 CU_ASSERT(rc == 0); 595 596 value = NULL; 597 rc = spdk_bs_md_get_xattr_value(blob, "length", &value, &value_len); 598 CU_ASSERT(rc == 0); 599 SPDK_CU_ASSERT_FATAL(value != NULL); 600 CU_ASSERT(*(uint64_t *)value == length); 601 CU_ASSERT(value_len == 8); 602 603 rc = spdk_bs_md_get_xattr_value(blob, "foobar", &value, &value_len); 604 CU_ASSERT(rc == -ENOENT); 605 606 names = NULL; 607 rc = spdk_bs_md_get_xattr_names(blob, &names); 608 CU_ASSERT(rc == 0); 609 SPDK_CU_ASSERT_FATAL(names != NULL); 610 CU_ASSERT(spdk_xattr_names_get_count(names) == 2); 611 name1 = spdk_xattr_names_get_name(names, 0); 612 SPDK_CU_ASSERT_FATAL(name1 != NULL); 613 CU_ASSERT(!strcmp(name1, "name") || !strcmp(name1, "length")); 614 name2 = spdk_xattr_names_get_name(names, 1); 615 SPDK_CU_ASSERT_FATAL(name2 != NULL); 616 CU_ASSERT(!strcmp(name2, "name") || !strcmp(name2, "length")); 617 CU_ASSERT(strcmp(name1, name2)); 618 spdk_xattr_names_free(names); 619 620 rc = spdk_blob_md_remove_xattr(blob, "name"); 621 CU_ASSERT(rc == 0); 622 623 rc = spdk_blob_md_remove_xattr(blob, "foobar"); 624 CU_ASSERT(rc == -ENOENT); 625 626 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 627 628 spdk_bs_unload(g_bs, bs_op_complete, NULL); 629 CU_ASSERT(g_bserrno == 0); 630 g_bs = NULL; 631 } 632 633 static void 634 bs_load(void) 635 { 636 struct spdk_bs_dev dev; 637 spdk_blob_id blobid; 638 struct spdk_blob *blob; 639 uint64_t length; 640 int rc; 641 const void *value; 642 size_t value_len; 643 644 init_dev(&dev); 645 646 /* Initialize a new blob store */ 647 spdk_bs_init(&dev, NULL, bs_op_with_handle_complete, NULL); 648 CU_ASSERT(g_bserrno == 0); 649 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 650 651 /* Create a blob */ 652 spdk_bs_md_create_blob(g_bs, blob_op_with_id_complete, NULL); 653 CU_ASSERT(g_bserrno == 0); 654 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 655 blobid = g_blobid; 656 657 spdk_bs_md_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); 658 CU_ASSERT(g_bserrno == 0); 659 CU_ASSERT(g_blob != NULL); 660 blob = g_blob; 661 662 /* Set some xattrs */ 663 rc = spdk_blob_md_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1); 664 CU_ASSERT(rc == 0); 665 666 length = 2345; 667 rc = spdk_blob_md_set_xattr(blob, "length", &length, sizeof(length)); 668 CU_ASSERT(rc == 0); 669 670 /* Resize the blob */ 671 rc = spdk_bs_md_resize_blob(blob, 10); 672 CU_ASSERT(rc == 0); 673 674 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 675 CU_ASSERT(g_bserrno == 0); 676 blob = NULL; 677 g_blob = NULL; 678 g_blobid = SPDK_BLOBID_INVALID; 679 680 /* Unload the blob store */ 681 spdk_bs_unload(g_bs, bs_op_complete, NULL); 682 CU_ASSERT(g_bserrno == 0); 683 g_bs = NULL; 684 g_blob = NULL; 685 g_blobid = 0; 686 687 /* Load an existing blob store */ 688 spdk_bs_load(&dev, bs_op_with_handle_complete, NULL); 689 CU_ASSERT(g_bserrno == 0); 690 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 691 692 spdk_bs_md_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); 693 CU_ASSERT(g_bserrno == 0); 694 CU_ASSERT(g_blob != NULL); 695 blob = g_blob; 696 697 /* Get the xattrs */ 698 value = NULL; 699 rc = spdk_bs_md_get_xattr_value(blob, "length", &value, &value_len); 700 CU_ASSERT(rc == 0); 701 SPDK_CU_ASSERT_FATAL(value != NULL); 702 CU_ASSERT(*(uint64_t *)value == length); 703 CU_ASSERT(value_len == 8); 704 705 rc = spdk_bs_md_get_xattr_value(blob, "foobar", &value, &value_len); 706 CU_ASSERT(rc == -ENOENT); 707 708 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 709 710 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 711 CU_ASSERT(g_bserrno == 0); 712 blob = NULL; 713 g_blob = NULL; 714 g_blobid = SPDK_BLOBID_INVALID; 715 716 spdk_bs_unload(g_bs, bs_op_complete, NULL); 717 CU_ASSERT(g_bserrno == 0); 718 g_bs = NULL; 719 } 720 721 /* 722 * Create a blobstore with a cluster size different than the default, and ensure it is 723 * persisted. 724 */ 725 static void 726 bs_cluster_sz(void) 727 { 728 struct spdk_bs_dev dev; 729 struct spdk_bs_opts opts; 730 uint32_t cluster_sz; 731 732 init_dev(&dev); 733 spdk_bs_opts_init(&opts); 734 opts.cluster_sz *= 2; 735 cluster_sz = opts.cluster_sz; 736 737 /* Initialize a new blob store */ 738 spdk_bs_init(&dev, &opts, bs_op_with_handle_complete, NULL); 739 CU_ASSERT(g_bserrno == 0); 740 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 741 742 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 743 744 /* Unload the blob store */ 745 spdk_bs_unload(g_bs, bs_op_complete, NULL); 746 CU_ASSERT(g_bserrno == 0); 747 g_bs = NULL; 748 g_blob = NULL; 749 g_blobid = 0; 750 751 /* Load an existing blob store */ 752 spdk_bs_load(&dev, bs_op_with_handle_complete, NULL); 753 CU_ASSERT(g_bserrno == 0); 754 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 755 756 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 757 758 spdk_bs_unload(g_bs, bs_op_complete, NULL); 759 CU_ASSERT(g_bserrno == 0); 760 g_bs = NULL; 761 } 762 763 /* 764 * Test resizing of the metadata blob. This requires creating enough blobs 765 * so that one cluster is not enough to fit the metadata for those blobs. 766 * To induce this condition to happen more quickly, we reduce the cluster 767 * size to 16KB, which means only 4 4KB blob metadata pages can fit. 768 */ 769 static void 770 bs_resize_md(void) 771 { 772 const int CLUSTER_PAGE_COUNT = 4; 773 const int NUM_BLOBS = CLUSTER_PAGE_COUNT * 4; 774 struct spdk_bs_dev dev; 775 struct spdk_bs_opts opts; 776 uint32_t cluster_sz; 777 spdk_blob_id blobids[NUM_BLOBS]; 778 int i; 779 780 781 init_dev(&dev); 782 spdk_bs_opts_init(&opts); 783 opts.cluster_sz = CLUSTER_PAGE_COUNT * 4096; 784 cluster_sz = opts.cluster_sz; 785 786 /* Initialize a new blob store */ 787 spdk_bs_init(&dev, &opts, bs_op_with_handle_complete, NULL); 788 CU_ASSERT(g_bserrno == 0); 789 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 790 791 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 792 793 for (i = 0; i < NUM_BLOBS; i++) { 794 g_bserrno = -1; 795 g_blobid = SPDK_BLOBID_INVALID; 796 spdk_bs_md_create_blob(g_bs, 797 blob_op_with_id_complete, NULL); 798 CU_ASSERT(g_bserrno == 0); 799 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 800 blobids[i] = g_blobid; 801 } 802 803 /* Unload the blob store */ 804 g_bserrno = -1; 805 spdk_bs_unload(g_bs, bs_op_complete, NULL); 806 CU_ASSERT(g_bserrno == 0); 807 808 /* Load an existing blob store */ 809 g_bserrno = -1; 810 g_bs = NULL; 811 spdk_bs_load(&dev, bs_op_with_handle_complete, NULL); 812 CU_ASSERT(g_bserrno == 0); 813 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 814 815 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 816 817 for (i = 0; i < NUM_BLOBS; i++) { 818 g_bserrno = -1; 819 g_blob = NULL; 820 spdk_bs_md_open_blob(g_bs, blobids[i], blob_op_with_handle_complete, NULL); 821 CU_ASSERT(g_bserrno == 0); 822 CU_ASSERT(g_blob != NULL); 823 g_bserrno = -1; 824 spdk_bs_md_close_blob(&g_blob, blob_op_complete, NULL); 825 CU_ASSERT(g_bserrno == 0); 826 } 827 828 spdk_bs_unload(g_bs, bs_op_complete, NULL); 829 CU_ASSERT(g_bserrno == 0); 830 g_bs = NULL; 831 } 832 833 /* Try to hit all of the corner cases associated with serializing 834 * a blob to disk 835 */ 836 static void 837 blob_serialize(void) 838 { 839 struct spdk_bs_dev dev; 840 struct spdk_bs_opts opts; 841 struct spdk_blob_store *bs; 842 spdk_blob_id blobid[2]; 843 struct spdk_blob *blob[2]; 844 uint64_t i; 845 char *value; 846 int rc; 847 848 init_dev(&dev); 849 850 /* Initialize a new blobstore with very small clusters */ 851 spdk_bs_opts_init(&opts); 852 opts.cluster_sz = dev.blocklen * 8; 853 spdk_bs_init(&dev, &opts, bs_op_with_handle_complete, NULL); 854 CU_ASSERT(g_bserrno == 0); 855 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 856 bs = g_bs; 857 858 /* Create and open two blobs */ 859 for (i = 0; i < 2; i++) { 860 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 861 CU_ASSERT(g_bserrno == 0); 862 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 863 blobid[i] = g_blobid; 864 865 /* Open a blob */ 866 spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL); 867 CU_ASSERT(g_bserrno == 0); 868 CU_ASSERT(g_blob != NULL); 869 blob[i] = g_blob; 870 871 /* Set a fairly large xattr on both blobs to eat up 872 * metadata space 873 */ 874 value = calloc(dev.blocklen - 64, sizeof(char)); 875 SPDK_CU_ASSERT_FATAL(value != NULL); 876 memset(value, i, dev.blocklen / 2); 877 rc = spdk_blob_md_set_xattr(blob[i], "name", value, dev.blocklen - 64); 878 CU_ASSERT(rc == 0); 879 free(value); 880 } 881 882 /* Resize the blobs, alternating 1 cluster at a time. 883 * This thwarts run length encoding and will cause spill 884 * over of the extents. 885 */ 886 for (i = 0; i < 6; i++) { 887 rc = spdk_bs_md_resize_blob(blob[i % 2], (i / 2) + 1); 888 CU_ASSERT(rc == 0); 889 } 890 891 for (i = 0; i < 2; i++) { 892 spdk_bs_md_sync_blob(blob[i], blob_op_complete, NULL); 893 CU_ASSERT(g_bserrno == 0); 894 } 895 896 /* Close the blobs */ 897 for (i = 0; i < 2; i++) { 898 spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL); 899 CU_ASSERT(g_bserrno == 0); 900 } 901 902 /* Unload the blobstore */ 903 spdk_bs_unload(bs, bs_op_complete, NULL); 904 CU_ASSERT(g_bserrno == 0); 905 g_bs = NULL; 906 g_blob = NULL; 907 g_blobid = 0; 908 bs = NULL; 909 910 /* Load an existing blob store */ 911 spdk_bs_load(&dev, bs_op_with_handle_complete, NULL); 912 CU_ASSERT(g_bserrno == 0); 913 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 914 bs = g_bs; 915 916 for (i = 0; i < 2; i++) { 917 blob[i] = NULL; 918 919 spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL); 920 CU_ASSERT(g_bserrno == 0); 921 CU_ASSERT(g_blob != NULL); 922 blob[i] = g_blob; 923 924 CU_ASSERT(spdk_blob_get_num_clusters(blob[i]) == 3); 925 926 spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL); 927 CU_ASSERT(g_bserrno == 0); 928 } 929 930 spdk_bs_unload(bs, bs_op_complete, NULL); 931 CU_ASSERT(g_bserrno == 0); 932 g_bs = NULL; 933 } 934 935 int main(int argc, char **argv) 936 { 937 CU_pSuite suite = NULL; 938 unsigned int num_failures; 939 940 if (CU_initialize_registry() != CUE_SUCCESS) { 941 return CU_get_error(); 942 } 943 944 suite = CU_add_suite("blob", NULL, NULL); 945 if (suite == NULL) { 946 CU_cleanup_registry(); 947 return CU_get_error(); 948 } 949 950 if ( 951 CU_add_test(suite, "blob_init", blob_init) == NULL || 952 CU_add_test(suite, "blob_open", blob_open) == NULL || 953 CU_add_test(suite, "blob_delete", blob_delete) == NULL || 954 CU_add_test(suite, "blob_resize", blob_resize) == NULL || 955 CU_add_test(suite, "channel_ops", channel_ops) == NULL || 956 CU_add_test(suite, "blob_super", blob_super) == NULL || 957 CU_add_test(suite, "blob_write", blob_write) == NULL || 958 CU_add_test(suite, "blob_read", blob_read) == NULL || 959 CU_add_test(suite, "blob_rw_verify", blob_rw_verify) == NULL || 960 CU_add_test(suite, "blob_iter", blob_iter) == NULL || 961 CU_add_test(suite, "blob_xattr", blob_xattr) == NULL || 962 CU_add_test(suite, "bs_load", bs_load) == NULL || 963 CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL || 964 CU_add_test(suite, "bs_resize_md", bs_resize_md) == NULL || 965 CU_add_test(suite, "blob_serialize", blob_serialize) == NULL 966 ) { 967 CU_cleanup_registry(); 968 return CU_get_error(); 969 } 970 971 g_dev_buffer = calloc(1, DEV_BUFFER_SIZE); 972 spdk_allocate_thread(_bs_send_msg, NULL); 973 CU_basic_set_mode(CU_BRM_VERBOSE); 974 CU_basic_run_tests(); 975 num_failures = CU_get_number_of_failures(); 976 CU_cleanup_registry(); 977 spdk_free_thread(); 978 free(g_dev_buffer); 979 return num_failures; 980 } 981