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