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 bool g_scheduler_delay = false; 52 53 struct scheduled_ops { 54 spdk_thread_fn fn; 55 void *ctx; 56 57 TAILQ_ENTRY(scheduled_ops) ops_queue; 58 }; 59 60 static TAILQ_HEAD(, scheduled_ops) g_scheduled_ops = TAILQ_HEAD_INITIALIZER(g_scheduled_ops); 61 62 static void 63 _bs_send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx) 64 { 65 if (g_scheduler_delay) { 66 struct scheduled_ops *ops = calloc(1, sizeof(*ops)); 67 68 SPDK_CU_ASSERT_FATAL(ops != NULL); 69 ops->fn = fn; 70 ops->ctx = ctx; 71 TAILQ_INSERT_TAIL(&g_scheduled_ops, ops, ops_queue); 72 } else { 73 fn(ctx); 74 } 75 } 76 77 static void 78 _bs_flush_scheduler(void) 79 { 80 struct scheduled_ops *ops, *tmp; 81 82 TAILQ_FOREACH_SAFE(ops, &g_scheduled_ops, ops_queue, tmp) { 83 ops->fn(ops->ctx); 84 TAILQ_REMOVE(&g_scheduled_ops, ops, ops_queue); 85 free(ops); 86 } 87 } 88 89 static void 90 bs_op_complete(void *cb_arg, int bserrno) 91 { 92 g_bserrno = bserrno; 93 } 94 95 static void 96 bs_op_with_handle_complete(void *cb_arg, struct spdk_blob_store *bs, 97 int bserrno) 98 { 99 g_bs = bs; 100 g_bserrno = bserrno; 101 } 102 103 static void 104 blob_op_complete(void *cb_arg, int bserrno) 105 { 106 g_bserrno = bserrno; 107 } 108 109 static void 110 blob_op_with_id_complete(void *cb_arg, spdk_blob_id blobid, int bserrno) 111 { 112 g_blobid = blobid; 113 g_bserrno = bserrno; 114 } 115 116 static void 117 blob_op_with_handle_complete(void *cb_arg, struct spdk_blob *blb, int bserrno) 118 { 119 g_blob = blb; 120 g_bserrno = bserrno; 121 } 122 123 static void 124 blob_init(void) 125 { 126 struct spdk_bs_dev *dev; 127 128 dev = init_dev(); 129 130 /* should fail for an unsupported blocklen */ 131 dev->blocklen = 500; 132 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 133 CU_ASSERT(g_bserrno == -EINVAL); 134 /* 135 * Normally dev gets deleted as part of the dev->destroy callback. But 136 * that doesn't get invoked when init() fails. So manually free it here 137 * instead. Probably blobstore should still destroy the dev when init 138 * fails, but we'll do that in a separate patch. 139 */ 140 free(dev); 141 142 dev = init_dev(); 143 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 144 CU_ASSERT(g_bserrno == 0); 145 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 146 147 spdk_bs_unload(g_bs, bs_op_complete, NULL); 148 CU_ASSERT(g_bserrno == 0); 149 g_bs = NULL; 150 } 151 152 static void 153 blob_super(void) 154 { 155 struct spdk_blob_store *bs; 156 struct spdk_bs_dev *dev; 157 spdk_blob_id blobid; 158 159 dev = init_dev(); 160 161 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 162 CU_ASSERT(g_bserrno == 0); 163 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 164 bs = g_bs; 165 166 /* Get the super blob without having set one */ 167 spdk_bs_get_super(bs, blob_op_with_id_complete, NULL); 168 CU_ASSERT(g_bserrno == -ENOENT); 169 CU_ASSERT(g_blobid == SPDK_BLOBID_INVALID); 170 171 /* Create a blob */ 172 spdk_bs_md_create_blob(bs, 173 blob_op_with_id_complete, NULL); 174 CU_ASSERT(g_bserrno == 0); 175 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 176 blobid = g_blobid; 177 178 /* Set the blob as the super blob */ 179 spdk_bs_set_super(bs, blobid, blob_op_complete, NULL); 180 CU_ASSERT(g_bserrno == 0); 181 182 /* Get the super blob */ 183 spdk_bs_get_super(bs, blob_op_with_id_complete, NULL); 184 CU_ASSERT(g_bserrno == 0); 185 CU_ASSERT(blobid == g_blobid); 186 187 spdk_bs_unload(g_bs, bs_op_complete, NULL); 188 CU_ASSERT(g_bserrno == 0); 189 g_bs = NULL; 190 } 191 192 static void 193 blob_open(void) 194 { 195 struct spdk_blob_store *bs; 196 struct spdk_bs_dev *dev; 197 struct spdk_blob *blob; 198 spdk_blob_id blobid, blobid2; 199 200 dev = init_dev(); 201 202 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 203 CU_ASSERT(g_bserrno == 0); 204 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 205 bs = g_bs; 206 207 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 208 CU_ASSERT(g_bserrno == 0); 209 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 210 blobid = g_blobid; 211 212 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 213 CU_ASSERT(g_bserrno == 0); 214 CU_ASSERT(g_blob != NULL); 215 blob = g_blob; 216 217 blobid2 = spdk_blob_get_id(blob); 218 CU_ASSERT(blobid == blobid2); 219 220 /* Try to open file again. It should return success. */ 221 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 222 CU_ASSERT(g_bserrno == 0); 223 CU_ASSERT(blob == g_blob); 224 225 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 226 CU_ASSERT(g_bserrno == 0); 227 CU_ASSERT(blob == NULL); 228 229 /* 230 * Close the file a second time, releasing the second reference. This 231 * should succeed. 232 */ 233 blob = g_blob; 234 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 235 CU_ASSERT(g_bserrno == 0); 236 237 /* 238 * Try to open file again. It should succeed. This tests the case 239 * where the file is opened, closed, then re-opened again. 240 */ 241 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 242 CU_ASSERT(g_bserrno == 0); 243 CU_ASSERT(g_blob != NULL); 244 blob = g_blob; 245 246 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 247 CU_ASSERT(g_bserrno == 0); 248 249 spdk_bs_unload(g_bs, bs_op_complete, NULL); 250 CU_ASSERT(g_bserrno == 0); 251 g_bs = NULL; 252 } 253 254 static void 255 blob_delete(void) 256 { 257 struct spdk_blob_store *bs; 258 struct spdk_bs_dev *dev; 259 spdk_blob_id blobid; 260 261 dev = init_dev(); 262 263 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 264 CU_ASSERT(g_bserrno == 0); 265 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 266 bs = g_bs; 267 268 /* Create a blob and then delete it. */ 269 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 270 CU_ASSERT(g_bserrno == 0); 271 CU_ASSERT(g_blobid > 0); 272 blobid = g_blobid; 273 274 spdk_bs_md_delete_blob(bs, blobid, blob_op_complete, NULL); 275 CU_ASSERT(g_bserrno == 0); 276 277 /* Try to open the blob */ 278 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 279 CU_ASSERT(g_bserrno == -ENOENT); 280 281 spdk_bs_unload(g_bs, bs_op_complete, NULL); 282 CU_ASSERT(g_bserrno == 0); 283 g_bs = NULL; 284 } 285 286 static void 287 blob_resize(void) 288 { 289 struct spdk_blob_store *bs; 290 struct spdk_bs_dev *dev; 291 struct spdk_blob *blob; 292 spdk_blob_id blobid; 293 uint64_t free_clusters; 294 int rc; 295 296 dev = init_dev(); 297 298 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 299 CU_ASSERT(g_bserrno == 0); 300 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 301 bs = g_bs; 302 free_clusters = spdk_bs_free_cluster_count(bs); 303 304 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 305 CU_ASSERT(g_bserrno == 0); 306 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 307 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 308 blobid = g_blobid; 309 310 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 311 CU_ASSERT(g_bserrno == 0); 312 CU_ASSERT(g_blob != NULL); 313 blob = g_blob; 314 315 /* The blob started at 0 clusters. Resize it to be 5. */ 316 rc = spdk_bs_md_resize_blob(blob, 5); 317 CU_ASSERT(rc == 0); 318 CU_ASSERT((free_clusters - 5) == spdk_bs_free_cluster_count(bs)); 319 320 /* Shrink the blob to 3 clusters. This will not actually release 321 * the old clusters until the blob is synced. 322 */ 323 rc = spdk_bs_md_resize_blob(blob, 3); 324 CU_ASSERT(rc == 0); 325 /* Verify there are still 5 clusters in use */ 326 CU_ASSERT((free_clusters - 5) == spdk_bs_free_cluster_count(bs)); 327 328 spdk_bs_md_sync_blob(blob, blob_op_complete, NULL); 329 CU_ASSERT(g_bserrno == 0); 330 /* Now there are only 3 clusters in use */ 331 CU_ASSERT((free_clusters - 3) == spdk_bs_free_cluster_count(bs)); 332 333 /* Resize the blob to be 10 clusters. Growth takes effect immediately. */ 334 rc = spdk_bs_md_resize_blob(blob, 10); 335 CU_ASSERT(rc == 0); 336 CU_ASSERT((free_clusters - 10) == spdk_bs_free_cluster_count(bs)); 337 338 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 339 CU_ASSERT(g_bserrno == 0); 340 341 spdk_bs_md_delete_blob(bs, blobid, blob_op_complete, NULL); 342 CU_ASSERT(g_bserrno == 0); 343 344 spdk_bs_unload(g_bs, bs_op_complete, NULL); 345 CU_ASSERT(g_bserrno == 0); 346 g_bs = NULL; 347 } 348 349 static void 350 channel_ops(void) 351 { 352 struct spdk_blob_store *bs; 353 struct spdk_bs_dev *dev; 354 struct spdk_io_channel *channel; 355 356 dev = init_dev(); 357 358 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 359 CU_ASSERT(g_bserrno == 0); 360 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 361 bs = g_bs; 362 363 channel = spdk_bs_alloc_io_channel(bs); 364 CU_ASSERT(channel != NULL); 365 366 spdk_bs_free_io_channel(channel); 367 368 spdk_bs_unload(g_bs, bs_op_complete, NULL); 369 CU_ASSERT(g_bserrno == 0); 370 g_bs = NULL; 371 } 372 373 static void 374 blob_write(void) 375 { 376 struct spdk_blob_store *bs; 377 struct spdk_bs_dev *dev; 378 struct spdk_blob *blob; 379 struct spdk_io_channel *channel; 380 spdk_blob_id blobid; 381 uint64_t pages_per_cluster; 382 uint8_t payload[10 * 4096]; 383 int rc; 384 385 dev = init_dev(); 386 387 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 388 CU_ASSERT(g_bserrno == 0); 389 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 390 bs = g_bs; 391 392 pages_per_cluster = spdk_bs_get_cluster_size(bs) / spdk_bs_get_page_size(bs); 393 394 channel = spdk_bs_alloc_io_channel(bs); 395 CU_ASSERT(channel != NULL); 396 397 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 398 CU_ASSERT(g_bserrno == 0); 399 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 400 blobid = g_blobid; 401 402 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 403 CU_ASSERT(g_bserrno == 0); 404 CU_ASSERT(g_blob != NULL); 405 blob = g_blob; 406 407 /* Write to a blob with 0 size */ 408 spdk_bs_io_write_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 409 CU_ASSERT(g_bserrno == -EINVAL); 410 411 /* Resize the blob */ 412 rc = spdk_bs_md_resize_blob(blob, 5); 413 CU_ASSERT(rc == 0); 414 415 /* Write to the blob */ 416 spdk_bs_io_write_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 417 CU_ASSERT(g_bserrno == 0); 418 419 /* Write starting beyond the end */ 420 spdk_bs_io_write_blob(blob, channel, payload, 5 * pages_per_cluster, 1, blob_op_complete, 421 NULL); 422 CU_ASSERT(g_bserrno == -EINVAL); 423 424 /* Write starting at a valid location but going off the end */ 425 spdk_bs_io_write_blob(blob, channel, payload, 4 * pages_per_cluster, pages_per_cluster + 1, 426 blob_op_complete, NULL); 427 CU_ASSERT(g_bserrno == -EINVAL); 428 429 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 430 CU_ASSERT(g_bserrno == 0); 431 432 spdk_bs_free_io_channel(channel); 433 434 spdk_bs_unload(g_bs, bs_op_complete, NULL); 435 CU_ASSERT(g_bserrno == 0); 436 g_bs = NULL; 437 } 438 439 static void 440 blob_read(void) 441 { 442 struct spdk_blob_store *bs; 443 struct spdk_bs_dev *dev; 444 struct spdk_blob *blob; 445 struct spdk_io_channel *channel; 446 spdk_blob_id blobid; 447 uint64_t pages_per_cluster; 448 uint8_t payload[10 * 4096]; 449 int rc; 450 451 dev = init_dev(); 452 453 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 454 CU_ASSERT(g_bserrno == 0); 455 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 456 bs = g_bs; 457 458 pages_per_cluster = spdk_bs_get_cluster_size(bs) / spdk_bs_get_page_size(bs); 459 460 channel = spdk_bs_alloc_io_channel(bs); 461 CU_ASSERT(channel != NULL); 462 463 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 464 CU_ASSERT(g_bserrno == 0); 465 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 466 blobid = g_blobid; 467 468 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 469 CU_ASSERT(g_bserrno == 0); 470 CU_ASSERT(g_blob != NULL); 471 blob = g_blob; 472 473 /* Read from a blob with 0 size */ 474 spdk_bs_io_read_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 475 CU_ASSERT(g_bserrno == -EINVAL); 476 477 /* Resize the blob */ 478 rc = spdk_bs_md_resize_blob(blob, 5); 479 CU_ASSERT(rc == 0); 480 481 /* Read from the blob */ 482 spdk_bs_io_read_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 483 CU_ASSERT(g_bserrno == 0); 484 485 /* Read starting beyond the end */ 486 spdk_bs_io_read_blob(blob, channel, payload, 5 * pages_per_cluster, 1, blob_op_complete, 487 NULL); 488 CU_ASSERT(g_bserrno == -EINVAL); 489 490 /* Read starting at a valid location but going off the end */ 491 spdk_bs_io_read_blob(blob, channel, payload, 4 * pages_per_cluster, pages_per_cluster + 1, 492 blob_op_complete, NULL); 493 CU_ASSERT(g_bserrno == -EINVAL); 494 495 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 496 CU_ASSERT(g_bserrno == 0); 497 498 spdk_bs_free_io_channel(channel); 499 500 spdk_bs_unload(g_bs, bs_op_complete, NULL); 501 CU_ASSERT(g_bserrno == 0); 502 g_bs = NULL; 503 } 504 505 static void 506 blob_rw_verify(void) 507 { 508 struct spdk_blob_store *bs; 509 struct spdk_bs_dev *dev; 510 struct spdk_blob *blob; 511 struct spdk_io_channel *channel; 512 spdk_blob_id blobid; 513 uint8_t payload_read[10 * 4096]; 514 uint8_t payload_write[10 * 4096]; 515 int rc; 516 517 dev = init_dev(); 518 519 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 520 CU_ASSERT(g_bserrno == 0); 521 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 522 bs = g_bs; 523 524 channel = spdk_bs_alloc_io_channel(bs); 525 CU_ASSERT(channel != NULL); 526 527 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 528 CU_ASSERT(g_bserrno == 0); 529 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 530 blobid = g_blobid; 531 532 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 533 CU_ASSERT(g_bserrno == 0); 534 CU_ASSERT(g_blob != NULL); 535 blob = g_blob; 536 537 rc = spdk_bs_md_resize_blob(blob, 32); 538 CU_ASSERT(rc == 0); 539 540 memset(payload_write, 0xE5, sizeof(payload_write)); 541 spdk_bs_io_write_blob(blob, channel, payload_write, 4, 10, blob_op_complete, NULL); 542 CU_ASSERT(g_bserrno == 0); 543 544 memset(payload_read, 0x00, sizeof(payload_read)); 545 spdk_bs_io_read_blob(blob, channel, payload_read, 4, 10, blob_op_complete, NULL); 546 CU_ASSERT(g_bserrno == 0); 547 CU_ASSERT(memcmp(payload_write, payload_read, 4 * 4096) == 0); 548 549 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 550 CU_ASSERT(g_bserrno == 0); 551 552 spdk_bs_free_io_channel(channel); 553 554 spdk_bs_unload(g_bs, bs_op_complete, NULL); 555 CU_ASSERT(g_bserrno == 0); 556 g_bs = NULL; 557 } 558 559 static void 560 blob_rw_verify_iov(void) 561 { 562 struct spdk_blob_store *bs; 563 struct spdk_bs_dev *dev; 564 struct spdk_blob *blob; 565 struct spdk_io_channel *channel; 566 spdk_blob_id blobid; 567 uint8_t payload_read[10 * 4096]; 568 uint8_t payload_write[10 * 4096]; 569 struct iovec iov_read[3]; 570 struct iovec iov_write[3]; 571 void *buf; 572 int rc; 573 574 dev = init_dev(); 575 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE); 576 577 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 578 CU_ASSERT(g_bserrno == 0); 579 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 580 bs = g_bs; 581 582 channel = spdk_bs_alloc_io_channel(bs); 583 CU_ASSERT(channel != NULL); 584 585 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 586 CU_ASSERT(g_bserrno == 0); 587 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 588 blobid = g_blobid; 589 590 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 591 CU_ASSERT(g_bserrno == 0); 592 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 593 blob = g_blob; 594 595 rc = spdk_bs_md_resize_blob(blob, 2); 596 CU_ASSERT(rc == 0); 597 598 /* 599 * Manually adjust the offset of the blob's second cluster. This allows 600 * us to make sure that the readv/write code correctly accounts for I/O 601 * that cross cluster boundaries. Start by asserting that the allocated 602 * clusters are where we expect before modifying the second cluster. 603 */ 604 CU_ASSERT(blob->active.clusters[0] == 1 * 256); 605 CU_ASSERT(blob->active.clusters[1] == 2 * 256); 606 blob->active.clusters[1] = 3 * 256; 607 608 memset(payload_write, 0xE5, sizeof(payload_write)); 609 iov_write[0].iov_base = payload_write; 610 iov_write[0].iov_len = 1 * 4096; 611 iov_write[1].iov_base = payload_write + 1 * 4096; 612 iov_write[1].iov_len = 5 * 4096; 613 iov_write[2].iov_base = payload_write + 6 * 4096; 614 iov_write[2].iov_len = 4 * 4096; 615 /* 616 * Choose a page offset just before the cluster boundary. The first 6 pages of payload 617 * will get written to the first cluster, the last 4 to the second cluster. 618 */ 619 spdk_bs_io_writev_blob(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL); 620 CU_ASSERT(g_bserrno == 0); 621 622 memset(payload_read, 0xAA, sizeof(payload_read)); 623 iov_read[0].iov_base = payload_read; 624 iov_read[0].iov_len = 3 * 4096; 625 iov_read[1].iov_base = payload_read + 3 * 4096; 626 iov_read[1].iov_len = 4 * 4096; 627 iov_read[2].iov_base = payload_read + 7 * 4096; 628 iov_read[2].iov_len = 3 * 4096; 629 spdk_bs_io_readv_blob(blob, channel, iov_read, 3, 250, 10, blob_op_complete, NULL); 630 CU_ASSERT(g_bserrno == 0); 631 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0); 632 633 buf = calloc(1, 256 * 4096); 634 SPDK_CU_ASSERT_FATAL(buf != NULL); 635 /* Check that cluster 2 on "disk" was not modified. */ 636 CU_ASSERT(memcmp(buf, &g_dev_buffer[512 * 4096], 256 * 4096) == 0); 637 free(buf); 638 639 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 640 CU_ASSERT(g_bserrno == 0); 641 642 spdk_bs_free_io_channel(channel); 643 644 spdk_bs_unload(g_bs, bs_op_complete, NULL); 645 CU_ASSERT(g_bserrno == 0); 646 g_bs = NULL; 647 } 648 649 static uint32_t 650 bs_channel_get_req_count(struct spdk_io_channel *_channel) 651 { 652 struct spdk_bs_channel *channel = spdk_io_channel_get_ctx(_channel); 653 struct spdk_bs_request_set *set; 654 uint32_t count = 0; 655 656 TAILQ_FOREACH(set, &channel->reqs, link) { 657 count++; 658 } 659 660 return count; 661 } 662 663 static void 664 blob_rw_verify_iov_nomem(void) 665 { 666 struct spdk_blob_store *bs; 667 struct spdk_bs_dev *dev; 668 struct spdk_blob *blob; 669 struct spdk_io_channel *channel; 670 spdk_blob_id blobid; 671 uint8_t payload_write[10 * 4096]; 672 struct iovec iov_write[3]; 673 uint32_t req_count; 674 int rc; 675 676 dev = init_dev(); 677 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE); 678 679 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 680 CU_ASSERT(g_bserrno == 0); 681 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 682 bs = g_bs; 683 684 channel = spdk_bs_alloc_io_channel(bs); 685 CU_ASSERT(channel != NULL); 686 687 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 688 CU_ASSERT(g_bserrno == 0); 689 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 690 blobid = g_blobid; 691 692 spdk_bs_md_open_blob(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 rc = spdk_bs_md_resize_blob(blob, 2); 698 CU_ASSERT(rc == 0); 699 700 /* 701 * Choose a page offset just before the cluster boundary. The first 6 pages of payload 702 * will get written to the first cluster, the last 4 to the second cluster. 703 */ 704 iov_write[0].iov_base = payload_write; 705 iov_write[0].iov_len = 1 * 4096; 706 iov_write[1].iov_base = payload_write + 1 * 4096; 707 iov_write[1].iov_len = 5 * 4096; 708 iov_write[2].iov_base = payload_write + 6 * 4096; 709 iov_write[2].iov_len = 4 * 4096; 710 MOCK_SET(calloc, void *, NULL); 711 req_count = bs_channel_get_req_count(channel); 712 spdk_bs_io_writev_blob(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL); 713 CU_ASSERT(g_bserrno = -ENOMEM); 714 CU_ASSERT(req_count == bs_channel_get_req_count(channel)); 715 MOCK_SET(calloc, void *, (void *)MOCK_PASS_THRU); 716 717 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 718 CU_ASSERT(g_bserrno == 0); 719 720 spdk_bs_free_io_channel(channel); 721 722 spdk_bs_unload(g_bs, bs_op_complete, NULL); 723 CU_ASSERT(g_bserrno == 0); 724 g_bs = NULL; 725 } 726 727 static void 728 blob_iter(void) 729 { 730 struct spdk_blob_store *bs; 731 struct spdk_bs_dev *dev; 732 struct spdk_blob *blob; 733 spdk_blob_id blobid; 734 735 dev = init_dev(); 736 737 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 738 CU_ASSERT(g_bserrno == 0); 739 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 740 bs = g_bs; 741 742 spdk_bs_md_iter_first(bs, blob_op_with_handle_complete, NULL); 743 CU_ASSERT(g_blob == NULL); 744 CU_ASSERT(g_bserrno == -ENOENT); 745 746 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 747 CU_ASSERT(g_bserrno == 0); 748 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 749 blobid = g_blobid; 750 751 spdk_bs_md_iter_first(bs, blob_op_with_handle_complete, NULL); 752 CU_ASSERT(g_blob != NULL); 753 CU_ASSERT(g_bserrno == 0); 754 blob = g_blob; 755 CU_ASSERT(spdk_blob_get_id(blob) == blobid); 756 757 spdk_bs_md_iter_next(bs, &blob, blob_op_with_handle_complete, NULL); 758 CU_ASSERT(g_blob == NULL); 759 CU_ASSERT(g_bserrno == -ENOENT); 760 761 spdk_bs_unload(g_bs, bs_op_complete, NULL); 762 CU_ASSERT(g_bserrno == 0); 763 g_bs = NULL; 764 } 765 766 static void 767 blob_xattr(void) 768 { 769 struct spdk_blob_store *bs; 770 struct spdk_bs_dev *dev; 771 struct spdk_blob *blob; 772 spdk_blob_id blobid; 773 uint64_t length; 774 int rc; 775 const char *name1, *name2; 776 const void *value; 777 size_t value_len; 778 struct spdk_xattr_names *names; 779 780 dev = init_dev(); 781 782 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 783 CU_ASSERT(g_bserrno == 0); 784 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 785 bs = g_bs; 786 787 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 788 CU_ASSERT(g_bserrno == 0); 789 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 790 blobid = g_blobid; 791 792 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 793 CU_ASSERT(g_bserrno == 0); 794 CU_ASSERT(g_blob != NULL); 795 blob = g_blob; 796 797 rc = spdk_blob_md_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1); 798 CU_ASSERT(rc == 0); 799 800 length = 2345; 801 rc = spdk_blob_md_set_xattr(blob, "length", &length, sizeof(length)); 802 CU_ASSERT(rc == 0); 803 804 /* Overwrite "length" xattr. */ 805 length = 3456; 806 rc = spdk_blob_md_set_xattr(blob, "length", &length, sizeof(length)); 807 CU_ASSERT(rc == 0); 808 809 value = NULL; 810 rc = spdk_bs_md_get_xattr_value(blob, "length", &value, &value_len); 811 CU_ASSERT(rc == 0); 812 SPDK_CU_ASSERT_FATAL(value != NULL); 813 CU_ASSERT(*(uint64_t *)value == length); 814 CU_ASSERT(value_len == 8); 815 816 rc = spdk_bs_md_get_xattr_value(blob, "foobar", &value, &value_len); 817 CU_ASSERT(rc == -ENOENT); 818 819 names = NULL; 820 rc = spdk_bs_md_get_xattr_names(blob, &names); 821 CU_ASSERT(rc == 0); 822 SPDK_CU_ASSERT_FATAL(names != NULL); 823 CU_ASSERT(spdk_xattr_names_get_count(names) == 2); 824 name1 = spdk_xattr_names_get_name(names, 0); 825 SPDK_CU_ASSERT_FATAL(name1 != NULL); 826 CU_ASSERT(!strcmp(name1, "name") || !strcmp(name1, "length")); 827 name2 = spdk_xattr_names_get_name(names, 1); 828 SPDK_CU_ASSERT_FATAL(name2 != NULL); 829 CU_ASSERT(!strcmp(name2, "name") || !strcmp(name2, "length")); 830 CU_ASSERT(strcmp(name1, name2)); 831 spdk_xattr_names_free(names); 832 833 rc = spdk_blob_md_remove_xattr(blob, "name"); 834 CU_ASSERT(rc == 0); 835 836 rc = spdk_blob_md_remove_xattr(blob, "foobar"); 837 CU_ASSERT(rc == -ENOENT); 838 839 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 840 841 spdk_bs_unload(g_bs, bs_op_complete, NULL); 842 CU_ASSERT(g_bserrno == 0); 843 g_bs = NULL; 844 } 845 846 static void 847 bs_load(void) 848 { 849 struct spdk_bs_dev *dev; 850 spdk_blob_id blobid; 851 struct spdk_blob *blob; 852 struct spdk_bs_super_block *super_blob; 853 uint64_t length; 854 int rc; 855 const void *value; 856 size_t value_len; 857 858 dev = init_dev(); 859 860 /* Initialize a new blob store */ 861 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 862 CU_ASSERT(g_bserrno == 0); 863 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 864 865 /* Create a blob */ 866 spdk_bs_md_create_blob(g_bs, blob_op_with_id_complete, NULL); 867 CU_ASSERT(g_bserrno == 0); 868 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 869 blobid = g_blobid; 870 871 spdk_bs_md_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); 872 CU_ASSERT(g_bserrno == 0); 873 CU_ASSERT(g_blob != NULL); 874 blob = g_blob; 875 876 /* Set some xattrs */ 877 rc = spdk_blob_md_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1); 878 CU_ASSERT(rc == 0); 879 880 length = 2345; 881 rc = spdk_blob_md_set_xattr(blob, "length", &length, sizeof(length)); 882 CU_ASSERT(rc == 0); 883 884 /* Resize the blob */ 885 rc = spdk_bs_md_resize_blob(blob, 10); 886 CU_ASSERT(rc == 0); 887 888 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 889 CU_ASSERT(g_bserrno == 0); 890 blob = NULL; 891 g_blob = NULL; 892 g_blobid = SPDK_BLOBID_INVALID; 893 894 /* Unload the blob store */ 895 spdk_bs_unload(g_bs, bs_op_complete, NULL); 896 CU_ASSERT(g_bserrno == 0); 897 g_bs = NULL; 898 g_blob = NULL; 899 g_blobid = 0; 900 901 super_blob = (struct spdk_bs_super_block *)g_dev_buffer; 902 CU_ASSERT(super_blob->clean == 1); 903 dev = init_dev(); 904 /* Load an existing blob store */ 905 spdk_bs_load(dev, bs_op_with_handle_complete, NULL); 906 CU_ASSERT(g_bserrno == 0); 907 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 908 909 super_blob = (struct spdk_bs_super_block *)g_dev_buffer; 910 CU_ASSERT(super_blob->clean == 0); 911 912 spdk_bs_md_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); 913 CU_ASSERT(g_bserrno == 0); 914 CU_ASSERT(g_blob != NULL); 915 blob = g_blob; 916 917 /* Get the xattrs */ 918 value = NULL; 919 rc = spdk_bs_md_get_xattr_value(blob, "length", &value, &value_len); 920 CU_ASSERT(rc == 0); 921 SPDK_CU_ASSERT_FATAL(value != NULL); 922 CU_ASSERT(*(uint64_t *)value == length); 923 CU_ASSERT(value_len == 8); 924 925 rc = spdk_bs_md_get_xattr_value(blob, "foobar", &value, &value_len); 926 CU_ASSERT(rc == -ENOENT); 927 928 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 929 930 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 931 CU_ASSERT(g_bserrno == 0); 932 blob = NULL; 933 g_blob = NULL; 934 g_blobid = SPDK_BLOBID_INVALID; 935 936 spdk_bs_unload(g_bs, bs_op_complete, NULL); 937 CU_ASSERT(g_bserrno == 0); 938 g_bs = NULL; 939 } 940 941 /* 942 * Create a blobstore and then unload it, while delaying all scheduled operations 943 * until after spdk_bs_unload call has finished. This ensures the memory associated 944 * with the internal blobstore channels is not touched after it is freed. 945 */ 946 static void 947 bs_unload_delayed(void) 948 { 949 struct spdk_bs_dev *dev; 950 951 dev = init_dev(); 952 953 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 954 CU_ASSERT(g_bserrno == 0); 955 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 956 957 g_scheduler_delay = true; 958 959 g_bserrno = -1; 960 spdk_bs_unload(g_bs, bs_op_complete, NULL); 961 CU_ASSERT(g_bserrno == 0); 962 g_bs = NULL; 963 964 _bs_flush_scheduler(); 965 CU_ASSERT(TAILQ_EMPTY(&g_scheduled_ops)); 966 967 g_scheduler_delay = false; 968 } 969 970 /* 971 * Create a blobstore with a cluster size different than the default, and ensure it is 972 * persisted. 973 */ 974 static void 975 bs_cluster_sz(void) 976 { 977 struct spdk_bs_dev *dev; 978 struct spdk_bs_opts opts; 979 uint32_t cluster_sz; 980 981 dev = init_dev(); 982 spdk_bs_opts_init(&opts); 983 opts.cluster_sz *= 2; 984 cluster_sz = opts.cluster_sz; 985 986 /* Initialize a new blob store */ 987 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 988 CU_ASSERT(g_bserrno == 0); 989 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 990 991 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 992 993 /* Unload the blob store */ 994 spdk_bs_unload(g_bs, bs_op_complete, NULL); 995 CU_ASSERT(g_bserrno == 0); 996 g_bs = NULL; 997 g_blob = NULL; 998 g_blobid = 0; 999 1000 dev = init_dev(); 1001 /* Load an existing blob store */ 1002 spdk_bs_load(dev, bs_op_with_handle_complete, NULL); 1003 CU_ASSERT(g_bserrno == 0); 1004 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1005 1006 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 1007 1008 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1009 CU_ASSERT(g_bserrno == 0); 1010 g_bs = NULL; 1011 } 1012 1013 /* 1014 * Test resizing of the metadata blob. This requires creating enough blobs 1015 * so that one cluster is not enough to fit the metadata for those blobs. 1016 * To induce this condition to happen more quickly, we reduce the cluster 1017 * size to 16KB, which means only 4 4KB blob metadata pages can fit. 1018 */ 1019 static void 1020 bs_resize_md(void) 1021 { 1022 const int CLUSTER_PAGE_COUNT = 4; 1023 const int NUM_BLOBS = CLUSTER_PAGE_COUNT * 4; 1024 struct spdk_bs_dev *dev; 1025 struct spdk_bs_opts opts; 1026 uint32_t cluster_sz; 1027 spdk_blob_id blobids[NUM_BLOBS]; 1028 int i; 1029 1030 1031 dev = init_dev(); 1032 spdk_bs_opts_init(&opts); 1033 opts.cluster_sz = CLUSTER_PAGE_COUNT * 4096; 1034 cluster_sz = opts.cluster_sz; 1035 1036 /* Initialize a new blob store */ 1037 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1038 CU_ASSERT(g_bserrno == 0); 1039 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1040 1041 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 1042 1043 for (i = 0; i < NUM_BLOBS; i++) { 1044 g_bserrno = -1; 1045 g_blobid = SPDK_BLOBID_INVALID; 1046 spdk_bs_md_create_blob(g_bs, 1047 blob_op_with_id_complete, NULL); 1048 CU_ASSERT(g_bserrno == 0); 1049 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1050 blobids[i] = g_blobid; 1051 } 1052 1053 /* Unload the blob store */ 1054 g_bserrno = -1; 1055 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1056 CU_ASSERT(g_bserrno == 0); 1057 1058 /* Load an existing blob store */ 1059 g_bserrno = -1; 1060 g_bs = NULL; 1061 dev = init_dev(); 1062 spdk_bs_load(dev, bs_op_with_handle_complete, NULL); 1063 CU_ASSERT(g_bserrno == 0); 1064 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1065 1066 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 1067 1068 for (i = 0; i < NUM_BLOBS; i++) { 1069 g_bserrno = -1; 1070 g_blob = NULL; 1071 spdk_bs_md_open_blob(g_bs, blobids[i], blob_op_with_handle_complete, NULL); 1072 CU_ASSERT(g_bserrno == 0); 1073 CU_ASSERT(g_blob != NULL); 1074 g_bserrno = -1; 1075 spdk_bs_md_close_blob(&g_blob, blob_op_complete, NULL); 1076 CU_ASSERT(g_bserrno == 0); 1077 } 1078 1079 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1080 CU_ASSERT(g_bserrno == 0); 1081 g_bs = NULL; 1082 } 1083 1084 /* Try to hit all of the corner cases associated with serializing 1085 * a blob to disk 1086 */ 1087 static void 1088 blob_serialize(void) 1089 { 1090 struct spdk_bs_dev *dev; 1091 struct spdk_bs_opts opts; 1092 struct spdk_blob_store *bs; 1093 spdk_blob_id blobid[2]; 1094 struct spdk_blob *blob[2]; 1095 uint64_t i; 1096 char *value; 1097 int rc; 1098 1099 dev = init_dev(); 1100 1101 /* Initialize a new blobstore with very small clusters */ 1102 spdk_bs_opts_init(&opts); 1103 opts.cluster_sz = dev->blocklen * 8; 1104 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1105 CU_ASSERT(g_bserrno == 0); 1106 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1107 bs = g_bs; 1108 1109 /* Create and open two blobs */ 1110 for (i = 0; i < 2; i++) { 1111 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 1112 CU_ASSERT(g_bserrno == 0); 1113 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1114 blobid[i] = g_blobid; 1115 1116 /* Open a blob */ 1117 spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL); 1118 CU_ASSERT(g_bserrno == 0); 1119 CU_ASSERT(g_blob != NULL); 1120 blob[i] = g_blob; 1121 1122 /* Set a fairly large xattr on both blobs to eat up 1123 * metadata space 1124 */ 1125 value = calloc(dev->blocklen - 64, sizeof(char)); 1126 SPDK_CU_ASSERT_FATAL(value != NULL); 1127 memset(value, i, dev->blocklen / 2); 1128 rc = spdk_blob_md_set_xattr(blob[i], "name", value, dev->blocklen - 64); 1129 CU_ASSERT(rc == 0); 1130 free(value); 1131 } 1132 1133 /* Resize the blobs, alternating 1 cluster at a time. 1134 * This thwarts run length encoding and will cause spill 1135 * over of the extents. 1136 */ 1137 for (i = 0; i < 6; i++) { 1138 rc = spdk_bs_md_resize_blob(blob[i % 2], (i / 2) + 1); 1139 CU_ASSERT(rc == 0); 1140 } 1141 1142 for (i = 0; i < 2; i++) { 1143 spdk_bs_md_sync_blob(blob[i], blob_op_complete, NULL); 1144 CU_ASSERT(g_bserrno == 0); 1145 } 1146 1147 /* Close the blobs */ 1148 for (i = 0; i < 2; i++) { 1149 spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL); 1150 CU_ASSERT(g_bserrno == 0); 1151 } 1152 1153 /* Unload the blobstore */ 1154 spdk_bs_unload(bs, bs_op_complete, NULL); 1155 CU_ASSERT(g_bserrno == 0); 1156 g_bs = NULL; 1157 g_blob = NULL; 1158 g_blobid = 0; 1159 bs = NULL; 1160 1161 dev = init_dev(); 1162 /* Load an existing blob store */ 1163 spdk_bs_load(dev, bs_op_with_handle_complete, NULL); 1164 CU_ASSERT(g_bserrno == 0); 1165 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1166 bs = g_bs; 1167 1168 for (i = 0; i < 2; i++) { 1169 blob[i] = NULL; 1170 1171 spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL); 1172 CU_ASSERT(g_bserrno == 0); 1173 CU_ASSERT(g_blob != NULL); 1174 blob[i] = g_blob; 1175 1176 CU_ASSERT(spdk_blob_get_num_clusters(blob[i]) == 3); 1177 1178 spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL); 1179 CU_ASSERT(g_bserrno == 0); 1180 } 1181 1182 spdk_bs_unload(bs, bs_op_complete, NULL); 1183 CU_ASSERT(g_bserrno == 0); 1184 g_bs = NULL; 1185 } 1186 1187 static void 1188 blob_crc(void) 1189 { 1190 struct spdk_blob_store *bs; 1191 struct spdk_bs_dev *dev; 1192 struct spdk_blob *blob; 1193 spdk_blob_id blobid; 1194 uint32_t page_num; 1195 int index; 1196 struct spdk_blob_md_page *page; 1197 1198 dev = init_dev(); 1199 1200 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 1201 CU_ASSERT(g_bserrno == 0); 1202 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1203 bs = g_bs; 1204 1205 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 1206 CU_ASSERT(g_bserrno == 0); 1207 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1208 blobid = g_blobid; 1209 1210 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 1211 CU_ASSERT(g_bserrno == 0); 1212 CU_ASSERT(g_blob != NULL); 1213 blob = g_blob; 1214 1215 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 1216 CU_ASSERT(g_bserrno == 0); 1217 CU_ASSERT(blob == NULL); 1218 1219 page_num = _spdk_bs_blobid_to_page(blobid); 1220 index = DEV_BUFFER_BLOCKLEN * (bs->md_start + page_num); 1221 page = (struct spdk_blob_md_page *)&g_dev_buffer[index]; 1222 page->crc = 0; 1223 1224 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 1225 CU_ASSERT(g_bserrno == -EINVAL); 1226 CU_ASSERT(g_blob == NULL); 1227 g_bserrno = 0; 1228 1229 spdk_bs_md_delete_blob(bs, blobid, blob_op_complete, NULL); 1230 CU_ASSERT(g_bserrno == -EINVAL); 1231 1232 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1233 CU_ASSERT(g_bserrno == 0); 1234 g_bs = NULL; 1235 } 1236 1237 int main(int argc, char **argv) 1238 { 1239 CU_pSuite suite = NULL; 1240 unsigned int num_failures; 1241 1242 if (CU_initialize_registry() != CUE_SUCCESS) { 1243 return CU_get_error(); 1244 } 1245 1246 suite = CU_add_suite("blob", NULL, NULL); 1247 if (suite == NULL) { 1248 CU_cleanup_registry(); 1249 return CU_get_error(); 1250 } 1251 1252 if ( 1253 CU_add_test(suite, "blob_init", blob_init) == NULL || 1254 CU_add_test(suite, "blob_open", blob_open) == NULL || 1255 CU_add_test(suite, "blob_delete", blob_delete) == NULL || 1256 CU_add_test(suite, "blob_resize", blob_resize) == NULL || 1257 CU_add_test(suite, "channel_ops", channel_ops) == NULL || 1258 CU_add_test(suite, "blob_super", blob_super) == NULL || 1259 CU_add_test(suite, "blob_write", blob_write) == NULL || 1260 CU_add_test(suite, "blob_read", blob_read) == NULL || 1261 CU_add_test(suite, "blob_rw_verify", blob_rw_verify) == NULL || 1262 CU_add_test(suite, "blob_rw_verify_iov", blob_rw_verify_iov) == NULL || 1263 CU_add_test(suite, "blob_rw_verify_iov_nomem", blob_rw_verify_iov_nomem) == NULL || 1264 CU_add_test(suite, "blob_iter", blob_iter) == NULL || 1265 CU_add_test(suite, "blob_xattr", blob_xattr) == NULL || 1266 CU_add_test(suite, "bs_load", bs_load) == NULL || 1267 CU_add_test(suite, "bs_unload_delayed", bs_unload_delayed) == NULL || 1268 CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL || 1269 CU_add_test(suite, "bs_resize_md", bs_resize_md) == NULL || 1270 CU_add_test(suite, "blob_serialize", blob_serialize) == NULL || 1271 CU_add_test(suite, "blob_crc", blob_crc) == NULL 1272 ) { 1273 CU_cleanup_registry(); 1274 return CU_get_error(); 1275 } 1276 1277 g_dev_buffer = calloc(1, DEV_BUFFER_SIZE); 1278 spdk_allocate_thread(_bs_send_msg, NULL, "thread0"); 1279 CU_basic_set_mode(CU_BRM_VERBOSE); 1280 CU_basic_run_tests(); 1281 num_failures = CU_get_number_of_failures(); 1282 CU_cleanup_registry(); 1283 spdk_free_thread(); 1284 free(g_dev_buffer); 1285 return num_failures; 1286 } 1287