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 dev = init_dev(); 966 spdk_bs_opts_init(&opts); 967 opts.cluster_sz *= 2; 968 cluster_sz = opts.cluster_sz; 969 970 /* Initialize a new blob store */ 971 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 972 CU_ASSERT(g_bserrno == 0); 973 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 974 975 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 976 977 /* Unload the blob store */ 978 spdk_bs_unload(g_bs, bs_op_complete, NULL); 979 CU_ASSERT(g_bserrno == 0); 980 g_bs = NULL; 981 g_blob = NULL; 982 g_blobid = 0; 983 984 dev = init_dev(); 985 /* Load an existing blob store */ 986 spdk_bs_load(dev, bs_op_with_handle_complete, NULL); 987 CU_ASSERT(g_bserrno == 0); 988 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 989 990 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 991 992 spdk_bs_unload(g_bs, bs_op_complete, NULL); 993 CU_ASSERT(g_bserrno == 0); 994 g_bs = NULL; 995 } 996 997 /* 998 * Test resizing of the metadata blob. This requires creating enough blobs 999 * so that one cluster is not enough to fit the metadata for those blobs. 1000 * To induce this condition to happen more quickly, we reduce the cluster 1001 * size to 16KB, which means only 4 4KB blob metadata pages can fit. 1002 */ 1003 static void 1004 bs_resize_md(void) 1005 { 1006 const int CLUSTER_PAGE_COUNT = 4; 1007 const int NUM_BLOBS = CLUSTER_PAGE_COUNT * 4; 1008 struct spdk_bs_dev *dev; 1009 struct spdk_bs_opts opts; 1010 uint32_t cluster_sz; 1011 spdk_blob_id blobids[NUM_BLOBS]; 1012 int i; 1013 1014 1015 dev = init_dev(); 1016 spdk_bs_opts_init(&opts); 1017 opts.cluster_sz = CLUSTER_PAGE_COUNT * 4096; 1018 cluster_sz = opts.cluster_sz; 1019 1020 /* Initialize a new blob store */ 1021 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1022 CU_ASSERT(g_bserrno == 0); 1023 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1024 1025 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 1026 1027 for (i = 0; i < NUM_BLOBS; i++) { 1028 g_bserrno = -1; 1029 g_blobid = SPDK_BLOBID_INVALID; 1030 spdk_bs_md_create_blob(g_bs, 1031 blob_op_with_id_complete, NULL); 1032 CU_ASSERT(g_bserrno == 0); 1033 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1034 blobids[i] = g_blobid; 1035 } 1036 1037 /* Unload the blob store */ 1038 g_bserrno = -1; 1039 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1040 CU_ASSERT(g_bserrno == 0); 1041 1042 /* Load an existing blob store */ 1043 g_bserrno = -1; 1044 g_bs = NULL; 1045 dev = init_dev(); 1046 spdk_bs_load(dev, bs_op_with_handle_complete, NULL); 1047 CU_ASSERT(g_bserrno == 0); 1048 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1049 1050 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 1051 1052 for (i = 0; i < NUM_BLOBS; i++) { 1053 g_bserrno = -1; 1054 g_blob = NULL; 1055 spdk_bs_md_open_blob(g_bs, blobids[i], blob_op_with_handle_complete, NULL); 1056 CU_ASSERT(g_bserrno == 0); 1057 CU_ASSERT(g_blob != NULL); 1058 g_bserrno = -1; 1059 spdk_bs_md_close_blob(&g_blob, blob_op_complete, NULL); 1060 CU_ASSERT(g_bserrno == 0); 1061 } 1062 1063 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1064 CU_ASSERT(g_bserrno == 0); 1065 g_bs = NULL; 1066 } 1067 1068 /* Try to hit all of the corner cases associated with serializing 1069 * a blob to disk 1070 */ 1071 static void 1072 blob_serialize(void) 1073 { 1074 struct spdk_bs_dev *dev; 1075 struct spdk_bs_opts opts; 1076 struct spdk_blob_store *bs; 1077 spdk_blob_id blobid[2]; 1078 struct spdk_blob *blob[2]; 1079 uint64_t i; 1080 char *value; 1081 int rc; 1082 1083 dev = init_dev(); 1084 1085 /* Initialize a new blobstore with very small clusters */ 1086 spdk_bs_opts_init(&opts); 1087 opts.cluster_sz = dev->blocklen * 8; 1088 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1089 CU_ASSERT(g_bserrno == 0); 1090 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1091 bs = g_bs; 1092 1093 /* Create and open two blobs */ 1094 for (i = 0; i < 2; i++) { 1095 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 1096 CU_ASSERT(g_bserrno == 0); 1097 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1098 blobid[i] = g_blobid; 1099 1100 /* Open a blob */ 1101 spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL); 1102 CU_ASSERT(g_bserrno == 0); 1103 CU_ASSERT(g_blob != NULL); 1104 blob[i] = g_blob; 1105 1106 /* Set a fairly large xattr on both blobs to eat up 1107 * metadata space 1108 */ 1109 value = calloc(dev->blocklen - 64, sizeof(char)); 1110 SPDK_CU_ASSERT_FATAL(value != NULL); 1111 memset(value, i, dev->blocklen / 2); 1112 rc = spdk_blob_md_set_xattr(blob[i], "name", value, dev->blocklen - 64); 1113 CU_ASSERT(rc == 0); 1114 free(value); 1115 } 1116 1117 /* Resize the blobs, alternating 1 cluster at a time. 1118 * This thwarts run length encoding and will cause spill 1119 * over of the extents. 1120 */ 1121 for (i = 0; i < 6; i++) { 1122 rc = spdk_bs_md_resize_blob(blob[i % 2], (i / 2) + 1); 1123 CU_ASSERT(rc == 0); 1124 } 1125 1126 for (i = 0; i < 2; i++) { 1127 spdk_bs_md_sync_blob(blob[i], blob_op_complete, NULL); 1128 CU_ASSERT(g_bserrno == 0); 1129 } 1130 1131 /* Close the blobs */ 1132 for (i = 0; i < 2; i++) { 1133 spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL); 1134 CU_ASSERT(g_bserrno == 0); 1135 } 1136 1137 /* Unload the blobstore */ 1138 spdk_bs_unload(bs, bs_op_complete, NULL); 1139 CU_ASSERT(g_bserrno == 0); 1140 g_bs = NULL; 1141 g_blob = NULL; 1142 g_blobid = 0; 1143 bs = NULL; 1144 1145 dev = init_dev(); 1146 /* Load an existing blob store */ 1147 spdk_bs_load(dev, bs_op_with_handle_complete, NULL); 1148 CU_ASSERT(g_bserrno == 0); 1149 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1150 bs = g_bs; 1151 1152 for (i = 0; i < 2; i++) { 1153 blob[i] = NULL; 1154 1155 spdk_bs_md_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL); 1156 CU_ASSERT(g_bserrno == 0); 1157 CU_ASSERT(g_blob != NULL); 1158 blob[i] = g_blob; 1159 1160 CU_ASSERT(spdk_blob_get_num_clusters(blob[i]) == 3); 1161 1162 spdk_bs_md_close_blob(&blob[i], blob_op_complete, NULL); 1163 CU_ASSERT(g_bserrno == 0); 1164 } 1165 1166 spdk_bs_unload(bs, bs_op_complete, NULL); 1167 CU_ASSERT(g_bserrno == 0); 1168 g_bs = NULL; 1169 } 1170 1171 static void 1172 blob_crc(void) 1173 { 1174 struct spdk_blob_store *bs; 1175 struct spdk_bs_dev *dev; 1176 struct spdk_blob *blob; 1177 spdk_blob_id blobid; 1178 uint32_t page_num; 1179 int index; 1180 struct spdk_blob_md_page *page; 1181 1182 dev = init_dev(); 1183 1184 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 1185 CU_ASSERT(g_bserrno == 0); 1186 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1187 bs = g_bs; 1188 1189 spdk_bs_md_create_blob(bs, blob_op_with_id_complete, NULL); 1190 CU_ASSERT(g_bserrno == 0); 1191 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1192 blobid = g_blobid; 1193 1194 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 1195 CU_ASSERT(g_bserrno == 0); 1196 CU_ASSERT(g_blob != NULL); 1197 blob = g_blob; 1198 1199 spdk_bs_md_close_blob(&blob, blob_op_complete, NULL); 1200 CU_ASSERT(g_bserrno == 0); 1201 CU_ASSERT(blob == NULL); 1202 1203 page_num = _spdk_bs_blobid_to_page(blobid); 1204 index = DEV_BUFFER_BLOCKLEN * (bs->md_start + page_num); 1205 page = (struct spdk_blob_md_page *)&g_dev_buffer[index]; 1206 page->crc = 0; 1207 1208 spdk_bs_md_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 1209 CU_ASSERT(g_bserrno == -EINVAL); 1210 CU_ASSERT(g_blob == NULL); 1211 g_bserrno = 0; 1212 1213 spdk_bs_md_delete_blob(bs, blobid, blob_op_complete, NULL); 1214 CU_ASSERT(g_bserrno == -EINVAL); 1215 1216 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1217 CU_ASSERT(g_bserrno == 0); 1218 g_bs = NULL; 1219 } 1220 1221 static void 1222 super_block_crc(void) 1223 { 1224 struct spdk_bs_dev *dev; 1225 struct spdk_bs_super_block *super_block; 1226 1227 dev = init_dev(); 1228 1229 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 1230 CU_ASSERT(g_bserrno == 0); 1231 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1232 1233 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1234 CU_ASSERT(g_bserrno == 0); 1235 g_bs = NULL; 1236 1237 super_block = (struct spdk_bs_super_block *)g_dev_buffer; 1238 super_block->crc = 0; 1239 dev = init_dev(); 1240 1241 g_scheduler_delay = true; 1242 /* Load an existing blob store */ 1243 spdk_bs_load(dev, bs_op_with_handle_complete, NULL); 1244 1245 CU_ASSERT(g_bserrno == -EILSEQ); 1246 _bs_flush_scheduler(); 1247 CU_ASSERT(TAILQ_EMPTY(&g_scheduled_ops)); 1248 1249 g_scheduler_delay = false; 1250 } 1251 1252 int main(int argc, char **argv) 1253 { 1254 CU_pSuite suite = NULL; 1255 unsigned int num_failures; 1256 1257 if (CU_initialize_registry() != CUE_SUCCESS) { 1258 return CU_get_error(); 1259 } 1260 1261 suite = CU_add_suite("blob", NULL, NULL); 1262 if (suite == NULL) { 1263 CU_cleanup_registry(); 1264 return CU_get_error(); 1265 } 1266 1267 if ( 1268 CU_add_test(suite, "blob_init", blob_init) == NULL || 1269 CU_add_test(suite, "blob_open", blob_open) == NULL || 1270 CU_add_test(suite, "blob_delete", blob_delete) == NULL || 1271 CU_add_test(suite, "blob_resize", blob_resize) == NULL || 1272 CU_add_test(suite, "channel_ops", channel_ops) == NULL || 1273 CU_add_test(suite, "blob_super", blob_super) == NULL || 1274 CU_add_test(suite, "blob_write", blob_write) == NULL || 1275 CU_add_test(suite, "blob_read", blob_read) == NULL || 1276 CU_add_test(suite, "blob_rw_verify", blob_rw_verify) == NULL || 1277 CU_add_test(suite, "blob_rw_verify_iov", blob_rw_verify_iov) == NULL || 1278 CU_add_test(suite, "blob_rw_verify_iov_nomem", blob_rw_verify_iov_nomem) == NULL || 1279 CU_add_test(suite, "blob_iter", blob_iter) == NULL || 1280 CU_add_test(suite, "blob_xattr", blob_xattr) == NULL || 1281 CU_add_test(suite, "bs_load", bs_load) == NULL || 1282 CU_add_test(suite, "bs_unload", bs_unload) == NULL || 1283 CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL || 1284 CU_add_test(suite, "bs_resize_md", bs_resize_md) == NULL || 1285 CU_add_test(suite, "blob_serialize", blob_serialize) == NULL || 1286 CU_add_test(suite, "blob_crc", blob_crc) == NULL || 1287 CU_add_test(suite, "super_block_crc", super_block_crc) == NULL 1288 ) { 1289 CU_cleanup_registry(); 1290 return CU_get_error(); 1291 } 1292 1293 g_dev_buffer = calloc(1, DEV_BUFFER_SIZE); 1294 spdk_allocate_thread(_bs_send_msg, NULL, "thread0"); 1295 CU_basic_set_mode(CU_BRM_VERBOSE); 1296 CU_basic_run_tests(); 1297 num_failures = CU_get_number_of_failures(); 1298 CU_cleanup_registry(); 1299 spdk_free_thread(); 1300 free(g_dev_buffer); 1301 return num_failures; 1302 } 1303