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