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 uint64_t length; 853 int rc; 854 const void *value; 855 size_t value_len; 856 857 dev = init_dev(); 858 859 /* Initialize a new blob store */ 860 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 861 CU_ASSERT(g_bserrno == 0); 862 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 863 864 /* Create a blob */ 865 spdk_bs_md_create_blob(g_bs, blob_op_with_id_complete, NULL); 866 CU_ASSERT(g_bserrno == 0); 867 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 868 blobid = g_blobid; 869 870 spdk_bs_md_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); 871 CU_ASSERT(g_bserrno == 0); 872 CU_ASSERT(g_blob != NULL); 873 blob = g_blob; 874 875 /* Set some xattrs */ 876 rc = spdk_blob_md_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1); 877 CU_ASSERT(rc == 0); 878 879 length = 2345; 880 rc = spdk_blob_md_set_xattr(blob, "length", &length, sizeof(length)); 881 CU_ASSERT(rc == 0); 882 883 /* Resize the blob */ 884 rc = spdk_bs_md_resize_blob(blob, 10); 885 CU_ASSERT(rc == 0); 886 887 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 888 CU_ASSERT(g_bserrno == 0); 889 blob = NULL; 890 g_blob = NULL; 891 g_blobid = SPDK_BLOBID_INVALID; 892 893 /* Unload the blob store */ 894 spdk_bs_unload(g_bs, bs_op_complete, NULL); 895 CU_ASSERT(g_bserrno == 0); 896 g_bs = NULL; 897 g_blob = NULL; 898 g_blobid = 0; 899 900 dev = init_dev(); 901 /* Load an existing blob store */ 902 spdk_bs_load(dev, bs_op_with_handle_complete, NULL); 903 CU_ASSERT(g_bserrno == 0); 904 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 905 906 spdk_bs_md_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); 907 CU_ASSERT(g_bserrno == 0); 908 CU_ASSERT(g_blob != NULL); 909 blob = g_blob; 910 911 /* Get the xattrs */ 912 value = NULL; 913 rc = spdk_bs_md_get_xattr_value(blob, "length", &value, &value_len); 914 CU_ASSERT(rc == 0); 915 SPDK_CU_ASSERT_FATAL(value != NULL); 916 CU_ASSERT(*(uint64_t *)value == length); 917 CU_ASSERT(value_len == 8); 918 919 rc = spdk_bs_md_get_xattr_value(blob, "foobar", &value, &value_len); 920 CU_ASSERT(rc == -ENOENT); 921 922 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 923 924 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 925 CU_ASSERT(g_bserrno == 0); 926 blob = NULL; 927 g_blob = NULL; 928 g_blobid = SPDK_BLOBID_INVALID; 929 930 spdk_bs_unload(g_bs, bs_op_complete, NULL); 931 CU_ASSERT(g_bserrno == 0); 932 g_bs = NULL; 933 } 934 935 /* 936 * Create a blobstore and then unload it, while delaying all scheduled operations 937 * until after spdk_bs_unload call has finished. This ensures the memory associated 938 * with the internal blobstore channels is not touched after it is freed. 939 */ 940 static void 941 bs_unload_delayed(void) 942 { 943 struct spdk_bs_dev *dev; 944 945 dev = init_dev(); 946 947 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 948 CU_ASSERT(g_bserrno == 0); 949 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 950 951 g_scheduler_delay = true; 952 953 g_bserrno = -1; 954 spdk_bs_unload(g_bs, bs_op_complete, NULL); 955 CU_ASSERT(g_bserrno == 0); 956 g_bs = NULL; 957 958 _bs_flush_scheduler(); 959 CU_ASSERT(TAILQ_EMPTY(&g_scheduled_ops)); 960 961 g_scheduler_delay = false; 962 } 963 964 /* 965 * Create a blobstore with a cluster size different than the default, and ensure it is 966 * persisted. 967 */ 968 static void 969 bs_cluster_sz(void) 970 { 971 struct spdk_bs_dev *dev; 972 struct spdk_bs_opts opts; 973 uint32_t cluster_sz; 974 975 dev = init_dev(); 976 spdk_bs_opts_init(&opts); 977 opts.cluster_sz *= 2; 978 cluster_sz = opts.cluster_sz; 979 980 /* Initialize a new blob store */ 981 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 982 CU_ASSERT(g_bserrno == 0); 983 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 984 985 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 986 987 /* Unload the blob store */ 988 spdk_bs_unload(g_bs, bs_op_complete, NULL); 989 CU_ASSERT(g_bserrno == 0); 990 g_bs = NULL; 991 g_blob = NULL; 992 g_blobid = 0; 993 994 dev = init_dev(); 995 /* Load an existing blob store */ 996 spdk_bs_load(dev, bs_op_with_handle_complete, NULL); 997 CU_ASSERT(g_bserrno == 0); 998 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 999 1000 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 1001 1002 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1003 CU_ASSERT(g_bserrno == 0); 1004 g_bs = NULL; 1005 } 1006 1007 /* 1008 * Test resizing of the metadata blob. This requires creating enough blobs 1009 * so that one cluster is not enough to fit the metadata for those blobs. 1010 * To induce this condition to happen more quickly, we reduce the cluster 1011 * size to 16KB, which means only 4 4KB blob metadata pages can fit. 1012 */ 1013 static void 1014 bs_resize_md(void) 1015 { 1016 const int CLUSTER_PAGE_COUNT = 4; 1017 const int NUM_BLOBS = CLUSTER_PAGE_COUNT * 4; 1018 struct spdk_bs_dev *dev; 1019 struct spdk_bs_opts opts; 1020 uint32_t cluster_sz; 1021 spdk_blob_id blobids[NUM_BLOBS]; 1022 int i; 1023 1024 1025 dev = init_dev(); 1026 spdk_bs_opts_init(&opts); 1027 opts.cluster_sz = CLUSTER_PAGE_COUNT * 4096; 1028 cluster_sz = opts.cluster_sz; 1029 1030 /* Initialize a new blob store */ 1031 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1032 CU_ASSERT(g_bserrno == 0); 1033 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1034 1035 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 1036 1037 for (i = 0; i < NUM_BLOBS; i++) { 1038 g_bserrno = -1; 1039 g_blobid = SPDK_BLOBID_INVALID; 1040 spdk_bs_md_create_blob(g_bs, 1041 blob_op_with_id_complete, NULL); 1042 CU_ASSERT(g_bserrno == 0); 1043 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1044 blobids[i] = g_blobid; 1045 } 1046 1047 /* Unload the blob store */ 1048 g_bserrno = -1; 1049 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1050 CU_ASSERT(g_bserrno == 0); 1051 1052 /* Load an existing blob store */ 1053 g_bserrno = -1; 1054 g_bs = NULL; 1055 dev = init_dev(); 1056 spdk_bs_load(dev, bs_op_with_handle_complete, NULL); 1057 CU_ASSERT(g_bserrno == 0); 1058 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1059 1060 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 1061 1062 for (i = 0; i < NUM_BLOBS; i++) { 1063 g_bserrno = -1; 1064 g_blob = NULL; 1065 spdk_bs_md_open_blob(g_bs, blobids[i], blob_op_with_handle_complete, NULL); 1066 CU_ASSERT(g_bserrno == 0); 1067 CU_ASSERT(g_blob != NULL); 1068 g_bserrno = -1; 1069 spdk_bs_md_close_blob(&g_blob, blob_op_complete, NULL); 1070 CU_ASSERT(g_bserrno == 0); 1071 } 1072 1073 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1074 CU_ASSERT(g_bserrno == 0); 1075 g_bs = NULL; 1076 } 1077 1078 /* Try to hit all of the corner cases associated with serializing 1079 * a blob to disk 1080 */ 1081 static void 1082 blob_serialize(void) 1083 { 1084 struct spdk_bs_dev *dev; 1085 struct spdk_bs_opts opts; 1086 struct spdk_blob_store *bs; 1087 spdk_blob_id blobid[2]; 1088 struct spdk_blob *blob[2]; 1089 uint64_t i; 1090 char *value; 1091 int rc; 1092 1093 dev = init_dev(); 1094 1095 /* Initialize a new blobstore with very small clusters */ 1096 spdk_bs_opts_init(&opts); 1097 opts.cluster_sz = dev->blocklen * 8; 1098 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1099 CU_ASSERT(g_bserrno == 0); 1100 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1101 bs = g_bs; 1102 1103 /* Create and open two blobs */ 1104 for (i = 0; i < 2; i++) { 1105 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 1106 CU_ASSERT(g_bserrno == 0); 1107 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1108 blobid[i] = g_blobid; 1109 1110 /* Open a blob */ 1111 spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL); 1112 CU_ASSERT(g_bserrno == 0); 1113 CU_ASSERT(g_blob != NULL); 1114 blob[i] = g_blob; 1115 1116 /* Set a fairly large xattr on both blobs to eat up 1117 * metadata space 1118 */ 1119 value = calloc(dev->blocklen - 64, sizeof(char)); 1120 SPDK_CU_ASSERT_FATAL(value != NULL); 1121 memset(value, i, dev->blocklen / 2); 1122 rc = spdk_blob_md_set_xattr(blob[i], "name", value, dev->blocklen - 64); 1123 CU_ASSERT(rc == 0); 1124 free(value); 1125 } 1126 1127 /* Resize the blobs, alternating 1 cluster at a time. 1128 * This thwarts run length encoding and will cause spill 1129 * over of the extents. 1130 */ 1131 for (i = 0; i < 6; i++) { 1132 rc = spdk_bs_md_resize_blob(blob[i % 2], (i / 2) + 1); 1133 CU_ASSERT(rc == 0); 1134 } 1135 1136 for (i = 0; i < 2; i++) { 1137 spdk_bs_md_sync_blob(blob[i], blob_op_complete, NULL); 1138 CU_ASSERT(g_bserrno == 0); 1139 } 1140 1141 /* Close the blobs */ 1142 for (i = 0; i < 2; i++) { 1143 spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL); 1144 CU_ASSERT(g_bserrno == 0); 1145 } 1146 1147 /* Unload the blobstore */ 1148 spdk_bs_unload(bs, bs_op_complete, NULL); 1149 CU_ASSERT(g_bserrno == 0); 1150 g_bs = NULL; 1151 g_blob = NULL; 1152 g_blobid = 0; 1153 bs = NULL; 1154 1155 dev = init_dev(); 1156 /* Load an existing blob store */ 1157 spdk_bs_load(dev, bs_op_with_handle_complete, NULL); 1158 CU_ASSERT(g_bserrno == 0); 1159 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1160 bs = g_bs; 1161 1162 for (i = 0; i < 2; i++) { 1163 blob[i] = NULL; 1164 1165 spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL); 1166 CU_ASSERT(g_bserrno == 0); 1167 CU_ASSERT(g_blob != NULL); 1168 blob[i] = g_blob; 1169 1170 CU_ASSERT(spdk_blob_get_num_clusters(blob[i]) == 3); 1171 1172 spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL); 1173 CU_ASSERT(g_bserrno == 0); 1174 } 1175 1176 spdk_bs_unload(bs, bs_op_complete, NULL); 1177 CU_ASSERT(g_bserrno == 0); 1178 g_bs = NULL; 1179 } 1180 1181 int main(int argc, char **argv) 1182 { 1183 CU_pSuite suite = NULL; 1184 unsigned int num_failures; 1185 1186 if (CU_initialize_registry() != CUE_SUCCESS) { 1187 return CU_get_error(); 1188 } 1189 1190 suite = CU_add_suite("blob", NULL, NULL); 1191 if (suite == NULL) { 1192 CU_cleanup_registry(); 1193 return CU_get_error(); 1194 } 1195 1196 if ( 1197 CU_add_test(suite, "blob_init", blob_init) == NULL || 1198 CU_add_test(suite, "blob_open", blob_open) == NULL || 1199 CU_add_test(suite, "blob_delete", blob_delete) == NULL || 1200 CU_add_test(suite, "blob_resize", blob_resize) == NULL || 1201 CU_add_test(suite, "channel_ops", channel_ops) == NULL || 1202 CU_add_test(suite, "blob_super", blob_super) == NULL || 1203 CU_add_test(suite, "blob_write", blob_write) == NULL || 1204 CU_add_test(suite, "blob_read", blob_read) == NULL || 1205 CU_add_test(suite, "blob_rw_verify", blob_rw_verify) == NULL || 1206 CU_add_test(suite, "blob_rw_verify_iov", blob_rw_verify_iov) == NULL || 1207 CU_add_test(suite, "blob_rw_verify_iov_nomem", blob_rw_verify_iov_nomem) == NULL || 1208 CU_add_test(suite, "blob_iter", blob_iter) == NULL || 1209 CU_add_test(suite, "blob_xattr", blob_xattr) == NULL || 1210 CU_add_test(suite, "bs_load", bs_load) == NULL || 1211 CU_add_test(suite, "bs_unload_delayed", bs_unload_delayed) == NULL || 1212 CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL || 1213 CU_add_test(suite, "bs_resize_md", bs_resize_md) == NULL || 1214 CU_add_test(suite, "blob_serialize", blob_serialize) == NULL 1215 ) { 1216 CU_cleanup_registry(); 1217 return CU_get_error(); 1218 } 1219 1220 g_dev_buffer = calloc(1, DEV_BUFFER_SIZE); 1221 spdk_allocate_thread(_bs_send_msg, NULL, "thread0"); 1222 CU_basic_set_mode(CU_BRM_VERBOSE); 1223 CU_basic_run_tests(); 1224 num_failures = CU_get_number_of_failures(); 1225 CU_cleanup_registry(); 1226 spdk_free_thread(); 1227 free(g_dev_buffer); 1228 return num_failures; 1229 } 1230