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 char *g_xattr_names[] = {"first", "second", "third"}; 51 char *g_xattr_values[] = {"one", "two", "three"}; 52 uint64_t g_ctx = 1729; 53 54 bool g_scheduler_delay = false; 55 56 struct scheduled_ops { 57 spdk_thread_fn fn; 58 void *ctx; 59 60 TAILQ_ENTRY(scheduled_ops) ops_queue; 61 }; 62 63 static TAILQ_HEAD(, scheduled_ops) g_scheduled_ops = TAILQ_HEAD_INITIALIZER(g_scheduled_ops); 64 65 struct spdk_bs_super_block_ver1 { 66 uint8_t signature[8]; 67 uint32_t version; 68 uint32_t length; 69 uint32_t clean; /* If there was a clean shutdown, this is 1. */ 70 spdk_blob_id super_blob; 71 72 uint32_t cluster_size; /* In bytes */ 73 74 uint32_t used_page_mask_start; /* Offset from beginning of disk, in pages */ 75 uint32_t used_page_mask_len; /* Count, in pages */ 76 77 uint32_t used_cluster_mask_start; /* Offset from beginning of disk, in pages */ 78 uint32_t used_cluster_mask_len; /* Count, in pages */ 79 80 uint32_t md_start; /* Offset from beginning of disk, in pages */ 81 uint32_t md_len; /* Count, in pages */ 82 83 uint8_t reserved[4036]; 84 uint32_t crc; 85 } __attribute__((packed)); 86 SPDK_STATIC_ASSERT(sizeof(struct spdk_bs_super_block_ver1) == 0x1000, "Invalid super block size"); 87 88 static void 89 _bs_send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx) 90 { 91 if (g_scheduler_delay) { 92 struct scheduled_ops *ops = calloc(1, sizeof(*ops)); 93 94 SPDK_CU_ASSERT_FATAL(ops != NULL); 95 ops->fn = fn; 96 ops->ctx = ctx; 97 TAILQ_INSERT_TAIL(&g_scheduled_ops, ops, ops_queue); 98 } else { 99 fn(ctx); 100 } 101 } 102 103 static void 104 _bs_flush_scheduler(void) 105 { 106 struct scheduled_ops *ops, *tmp; 107 108 TAILQ_FOREACH_SAFE(ops, &g_scheduled_ops, ops_queue, tmp) { 109 ops->fn(ops->ctx); 110 TAILQ_REMOVE(&g_scheduled_ops, ops, ops_queue); 111 free(ops); 112 } 113 } 114 115 static void 116 bs_op_complete(void *cb_arg, int bserrno) 117 { 118 g_bserrno = bserrno; 119 } 120 121 static void 122 bs_op_with_handle_complete(void *cb_arg, struct spdk_blob_store *bs, 123 int bserrno) 124 { 125 g_bs = bs; 126 g_bserrno = bserrno; 127 } 128 129 static void 130 blob_op_complete(void *cb_arg, int bserrno) 131 { 132 g_bserrno = bserrno; 133 } 134 135 static void 136 blob_op_with_id_complete(void *cb_arg, spdk_blob_id blobid, int bserrno) 137 { 138 g_blobid = blobid; 139 g_bserrno = bserrno; 140 } 141 142 static void 143 blob_op_with_handle_complete(void *cb_arg, struct spdk_blob *blb, int bserrno) 144 { 145 g_blob = blb; 146 g_bserrno = bserrno; 147 } 148 149 static void 150 blob_init(void) 151 { 152 struct spdk_bs_dev *dev; 153 154 dev = init_dev(); 155 156 /* should fail for an unsupported blocklen */ 157 dev->blocklen = 500; 158 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 159 CU_ASSERT(g_bserrno == -EINVAL); 160 161 dev = init_dev(); 162 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 163 CU_ASSERT(g_bserrno == 0); 164 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 165 166 spdk_bs_unload(g_bs, bs_op_complete, NULL); 167 CU_ASSERT(g_bserrno == 0); 168 g_bs = NULL; 169 } 170 171 static void 172 blob_super(void) 173 { 174 struct spdk_blob_store *bs; 175 struct spdk_bs_dev *dev; 176 spdk_blob_id blobid; 177 178 dev = init_dev(); 179 180 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 181 CU_ASSERT(g_bserrno == 0); 182 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 183 bs = g_bs; 184 185 /* Get the super blob without having set one */ 186 spdk_bs_get_super(bs, blob_op_with_id_complete, NULL); 187 CU_ASSERT(g_bserrno == -ENOENT); 188 CU_ASSERT(g_blobid == SPDK_BLOBID_INVALID); 189 190 /* Create a blob */ 191 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 192 CU_ASSERT(g_bserrno == 0); 193 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 194 blobid = g_blobid; 195 196 /* Set the blob as the super blob */ 197 spdk_bs_set_super(bs, blobid, blob_op_complete, NULL); 198 CU_ASSERT(g_bserrno == 0); 199 200 /* Get the super blob */ 201 spdk_bs_get_super(bs, blob_op_with_id_complete, NULL); 202 CU_ASSERT(g_bserrno == 0); 203 CU_ASSERT(blobid == g_blobid); 204 205 spdk_bs_unload(g_bs, bs_op_complete, NULL); 206 CU_ASSERT(g_bserrno == 0); 207 g_bs = NULL; 208 } 209 210 static void 211 blob_open(void) 212 { 213 struct spdk_blob_store *bs; 214 struct spdk_bs_dev *dev; 215 struct spdk_blob *blob; 216 spdk_blob_id blobid, blobid2; 217 218 dev = init_dev(); 219 220 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 221 CU_ASSERT(g_bserrno == 0); 222 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 223 bs = g_bs; 224 225 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 226 CU_ASSERT(g_bserrno == 0); 227 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 228 blobid = g_blobid; 229 230 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 231 CU_ASSERT(g_bserrno == 0); 232 CU_ASSERT(g_blob != NULL); 233 blob = g_blob; 234 235 blobid2 = spdk_blob_get_id(blob); 236 CU_ASSERT(blobid == blobid2); 237 238 /* Try to open file again. It should return success. */ 239 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 240 CU_ASSERT(g_bserrno == 0); 241 CU_ASSERT(blob == g_blob); 242 243 spdk_blob_close(blob, blob_op_complete, NULL); 244 CU_ASSERT(g_bserrno == 0); 245 246 /* 247 * Close the file a second time, releasing the second reference. This 248 * should succeed. 249 */ 250 blob = g_blob; 251 spdk_blob_close(blob, blob_op_complete, NULL); 252 CU_ASSERT(g_bserrno == 0); 253 254 /* 255 * Try to open file again. It should succeed. This tests the case 256 * where the file is opened, closed, then re-opened again. 257 */ 258 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 259 CU_ASSERT(g_bserrno == 0); 260 CU_ASSERT(g_blob != NULL); 261 blob = g_blob; 262 263 spdk_blob_close(blob, blob_op_complete, NULL); 264 CU_ASSERT(g_bserrno == 0); 265 266 spdk_bs_unload(g_bs, bs_op_complete, NULL); 267 CU_ASSERT(g_bserrno == 0); 268 g_bs = NULL; 269 } 270 271 static void 272 blob_create(void) 273 { 274 struct spdk_blob_store *bs; 275 struct spdk_bs_dev *dev; 276 struct spdk_blob *blob; 277 struct spdk_blob_opts opts; 278 spdk_blob_id blobid; 279 280 dev = init_dev(); 281 282 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 283 CU_ASSERT(g_bserrno == 0); 284 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 285 bs = g_bs; 286 287 /* Create blob with 10 clusters */ 288 289 spdk_blob_opts_init(&opts); 290 opts.num_clusters = 10; 291 292 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 293 CU_ASSERT(g_bserrno == 0); 294 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 295 blobid = g_blobid; 296 297 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 298 CU_ASSERT(g_bserrno == 0); 299 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 300 blob = g_blob; 301 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10) 302 303 spdk_blob_close(blob, blob_op_complete, NULL); 304 CU_ASSERT(g_bserrno == 0); 305 306 /* Create blob with 0 clusters */ 307 308 spdk_blob_opts_init(&opts); 309 opts.num_clusters = 0; 310 311 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 312 CU_ASSERT(g_bserrno == 0); 313 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 314 blobid = g_blobid; 315 316 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 317 CU_ASSERT(g_bserrno == 0); 318 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 319 blob = g_blob; 320 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 0) 321 322 spdk_blob_close(blob, blob_op_complete, NULL); 323 CU_ASSERT(g_bserrno == 0); 324 325 /* Create blob with default options (opts == NULL) */ 326 327 spdk_bs_create_blob_ext(bs, NULL, blob_op_with_id_complete, NULL); 328 CU_ASSERT(g_bserrno == 0); 329 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 330 blobid = g_blobid; 331 332 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 333 CU_ASSERT(g_bserrno == 0); 334 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 335 blob = g_blob; 336 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 0) 337 338 spdk_blob_close(blob, blob_op_complete, NULL); 339 CU_ASSERT(g_bserrno == 0); 340 341 /* Try to create blob with size larger than blobstore */ 342 343 spdk_blob_opts_init(&opts); 344 opts.num_clusters = bs->total_clusters + 1; 345 346 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 347 CU_ASSERT(g_bserrno == -ENOSPC); 348 349 spdk_bs_unload(g_bs, bs_op_complete, NULL); 350 CU_ASSERT(g_bserrno == 0); 351 g_bs = NULL; 352 353 } 354 355 static void 356 blob_thin_provision(void) 357 { 358 struct spdk_blob_store *bs; 359 struct spdk_bs_dev *dev; 360 struct spdk_blob *blob; 361 struct spdk_blob_opts opts; 362 struct spdk_bs_opts bs_opts; 363 spdk_blob_id blobid; 364 365 dev = init_dev(); 366 spdk_bs_opts_init(&bs_opts); 367 strncpy(bs_opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); 368 369 /* Initialize a new blob store */ 370 spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL); 371 CU_ASSERT(g_bserrno == 0); 372 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 373 374 bs = g_bs; 375 376 /* Create blob with thin provisioning enabled */ 377 378 spdk_blob_opts_init(&opts); 379 opts.thin_provision = true; 380 opts.num_clusters = 10; 381 382 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 383 CU_ASSERT(g_bserrno == 0); 384 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 385 blobid = g_blobid; 386 387 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 388 CU_ASSERT(g_bserrno == 0); 389 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 390 blob = g_blob; 391 CU_ASSERT(__blob_to_data(blob)->invalid_flags & SPDK_BLOB_THIN_PROV); 392 393 spdk_blob_close(blob, blob_op_complete, NULL); 394 CU_ASSERT(g_bserrno == 0); 395 396 spdk_bs_unload(g_bs, bs_op_complete, NULL); 397 CU_ASSERT(g_bserrno == 0); 398 g_bs = NULL; 399 400 /* Load an existing blob store and check if invalid_flags is set */ 401 dev = init_dev(); 402 strncpy(bs_opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); 403 spdk_bs_load(dev, &bs_opts, bs_op_with_handle_complete, NULL); 404 CU_ASSERT(g_bserrno == 0); 405 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 406 407 bs = g_bs; 408 409 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 410 CU_ASSERT(g_bserrno == 0); 411 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 412 blob = g_blob; 413 CU_ASSERT(__blob_to_data(blob)->invalid_flags & SPDK_BLOB_THIN_PROV); 414 415 spdk_blob_close(blob, blob_op_complete, NULL); 416 CU_ASSERT(g_bserrno == 0); 417 418 spdk_bs_unload(g_bs, bs_op_complete, NULL); 419 CU_ASSERT(g_bserrno == 0); 420 g_bs = NULL; 421 } 422 423 static void 424 blob_delete(void) 425 { 426 struct spdk_blob_store *bs; 427 struct spdk_bs_dev *dev; 428 spdk_blob_id blobid; 429 430 dev = init_dev(); 431 432 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 433 CU_ASSERT(g_bserrno == 0); 434 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 435 bs = g_bs; 436 437 /* Create a blob and then delete it. */ 438 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 439 CU_ASSERT(g_bserrno == 0); 440 CU_ASSERT(g_blobid > 0); 441 blobid = g_blobid; 442 443 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); 444 CU_ASSERT(g_bserrno == 0); 445 446 /* Try to open the blob */ 447 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 448 CU_ASSERT(g_bserrno == -ENOENT); 449 450 spdk_bs_unload(g_bs, bs_op_complete, NULL); 451 CU_ASSERT(g_bserrno == 0); 452 g_bs = NULL; 453 } 454 455 static void 456 blob_resize(void) 457 { 458 struct spdk_blob_store *bs; 459 struct spdk_bs_dev *dev; 460 struct spdk_blob *blob; 461 spdk_blob_id blobid; 462 uint64_t free_clusters; 463 int rc; 464 465 dev = init_dev(); 466 467 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 468 CU_ASSERT(g_bserrno == 0); 469 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 470 bs = g_bs; 471 free_clusters = spdk_bs_free_cluster_count(bs); 472 473 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 474 CU_ASSERT(g_bserrno == 0); 475 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 476 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 477 blobid = g_blobid; 478 479 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 480 CU_ASSERT(g_bserrno == 0); 481 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 482 blob = g_blob; 483 484 /* Confirm that resize fails if blob is marked read-only. */ 485 __blob_to_data(blob)->md_ro = true; 486 rc = spdk_blob_resize(blob, 5); 487 CU_ASSERT(rc == -EPERM); 488 __blob_to_data(blob)->md_ro = false; 489 490 /* The blob started at 0 clusters. Resize it to be 5. */ 491 rc = spdk_blob_resize(blob, 5); 492 CU_ASSERT(rc == 0); 493 CU_ASSERT((free_clusters - 5) == spdk_bs_free_cluster_count(bs)); 494 495 /* Shrink the blob to 3 clusters. This will not actually release 496 * the old clusters until the blob is synced. 497 */ 498 rc = spdk_blob_resize(blob, 3); 499 CU_ASSERT(rc == 0); 500 /* Verify there are still 5 clusters in use */ 501 CU_ASSERT((free_clusters - 5) == spdk_bs_free_cluster_count(bs)); 502 503 spdk_blob_sync_md(blob, blob_op_complete, NULL); 504 CU_ASSERT(g_bserrno == 0); 505 /* Now there are only 3 clusters in use */ 506 CU_ASSERT((free_clusters - 3) == spdk_bs_free_cluster_count(bs)); 507 508 /* Resize the blob to be 10 clusters. Growth takes effect immediately. */ 509 rc = spdk_blob_resize(blob, 10); 510 CU_ASSERT(rc == 0); 511 CU_ASSERT((free_clusters - 10) == spdk_bs_free_cluster_count(bs)); 512 513 /* Try to resize the blob to size larger than blobstore. */ 514 rc = spdk_blob_resize(blob, bs->total_clusters + 1); 515 CU_ASSERT(rc == -ENOSPC); 516 517 spdk_blob_close(blob, blob_op_complete, NULL); 518 CU_ASSERT(g_bserrno == 0); 519 520 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); 521 CU_ASSERT(g_bserrno == 0); 522 523 spdk_bs_unload(g_bs, bs_op_complete, NULL); 524 CU_ASSERT(g_bserrno == 0); 525 g_bs = NULL; 526 } 527 528 static void 529 blob_read_only(void) 530 { 531 struct spdk_blob_store *bs; 532 struct spdk_bs_dev *dev; 533 struct spdk_blob *blob; 534 struct spdk_blob_data *blob_data; 535 struct spdk_bs_opts opts; 536 spdk_blob_id blobid; 537 538 dev = init_dev(); 539 spdk_bs_opts_init(&opts); 540 strncpy(opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); 541 542 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 543 CU_ASSERT(g_bserrno == 0); 544 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 545 bs = g_bs; 546 547 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 548 CU_ASSERT(g_bserrno == 0); 549 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 550 blobid = g_blobid; 551 552 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 553 CU_ASSERT(g_bserrno == 0); 554 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 555 blob = g_blob; 556 557 spdk_blob_set_read_only(blob); 558 559 blob_data = __blob_to_data(blob); 560 CU_ASSERT(blob_data->data_ro == false); 561 CU_ASSERT(blob_data->md_ro == false); 562 563 spdk_blob_sync_md(blob, bs_op_complete, NULL); 564 565 CU_ASSERT(blob_data->data_ro == true); 566 CU_ASSERT(blob_data->md_ro == true); 567 CU_ASSERT(blob_data->data_ro_flags & SPDK_BLOB_READ_ONLY); 568 569 spdk_blob_close(blob, blob_op_complete, NULL); 570 CU_ASSERT(g_bserrno == 0); 571 572 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 573 CU_ASSERT(g_bserrno == 0); 574 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 575 blob = g_blob; 576 577 blob_data = __blob_to_data(blob); 578 CU_ASSERT(blob_data->data_ro == true); 579 CU_ASSERT(blob_data->md_ro == true); 580 CU_ASSERT(blob_data->data_ro_flags & SPDK_BLOB_READ_ONLY); 581 582 spdk_blob_close(blob, blob_op_complete, NULL); 583 CU_ASSERT(g_bserrno == 0); 584 585 spdk_bs_unload(g_bs, bs_op_complete, NULL); 586 CU_ASSERT(g_bserrno == 0); 587 g_bs = NULL; 588 g_blob = NULL; 589 g_blobid = 0; 590 591 /* Load an existing blob store */ 592 dev = init_dev(); 593 strncpy(opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); 594 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 595 CU_ASSERT(g_bserrno == 0); 596 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 597 598 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); 599 CU_ASSERT(g_bserrno == 0); 600 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 601 blob = g_blob; 602 603 blob_data = __blob_to_data(blob); 604 CU_ASSERT(blob_data->data_ro == true); 605 CU_ASSERT(blob_data->md_ro == true); 606 CU_ASSERT(blob_data->data_ro_flags & SPDK_BLOB_READ_ONLY); 607 608 spdk_blob_close(blob, blob_op_complete, NULL); 609 CU_ASSERT(g_bserrno == 0); 610 611 spdk_bs_unload(g_bs, bs_op_complete, NULL); 612 CU_ASSERT(g_bserrno == 0); 613 614 } 615 616 static void 617 channel_ops(void) 618 { 619 struct spdk_blob_store *bs; 620 struct spdk_bs_dev *dev; 621 struct spdk_io_channel *channel; 622 623 dev = init_dev(); 624 625 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 626 CU_ASSERT(g_bserrno == 0); 627 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 628 bs = g_bs; 629 630 channel = spdk_bs_alloc_io_channel(bs); 631 CU_ASSERT(channel != NULL); 632 633 spdk_bs_free_io_channel(channel); 634 635 spdk_bs_unload(g_bs, bs_op_complete, NULL); 636 CU_ASSERT(g_bserrno == 0); 637 g_bs = NULL; 638 } 639 640 static void 641 blob_write(void) 642 { 643 struct spdk_blob_store *bs; 644 struct spdk_bs_dev *dev; 645 struct spdk_blob *blob; 646 struct spdk_io_channel *channel; 647 spdk_blob_id blobid; 648 uint64_t pages_per_cluster; 649 uint8_t payload[10 * 4096]; 650 int rc; 651 652 dev = init_dev(); 653 654 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 655 CU_ASSERT(g_bserrno == 0); 656 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 657 bs = g_bs; 658 659 pages_per_cluster = spdk_bs_get_cluster_size(bs) / spdk_bs_get_page_size(bs); 660 661 channel = spdk_bs_alloc_io_channel(bs); 662 CU_ASSERT(channel != NULL); 663 664 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 665 CU_ASSERT(g_bserrno == 0); 666 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 667 blobid = g_blobid; 668 669 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 670 CU_ASSERT(g_bserrno == 0); 671 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 672 blob = g_blob; 673 674 /* Write to a blob with 0 size */ 675 spdk_bs_io_write_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 676 CU_ASSERT(g_bserrno == -EINVAL); 677 678 /* Resize the blob */ 679 rc = spdk_blob_resize(blob, 5); 680 CU_ASSERT(rc == 0); 681 682 /* Confirm that write fails if blob is marked read-only. */ 683 __blob_to_data(blob)->data_ro = true; 684 spdk_bs_io_write_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 685 CU_ASSERT(g_bserrno == -EPERM); 686 __blob_to_data(blob)->data_ro = false; 687 688 /* Write to the blob */ 689 spdk_bs_io_write_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 690 CU_ASSERT(g_bserrno == 0); 691 692 /* Write starting beyond the end */ 693 spdk_bs_io_write_blob(blob, channel, payload, 5 * pages_per_cluster, 1, blob_op_complete, 694 NULL); 695 CU_ASSERT(g_bserrno == -EINVAL); 696 697 /* Write starting at a valid location but going off the end */ 698 spdk_bs_io_write_blob(blob, channel, payload, 4 * pages_per_cluster, pages_per_cluster + 1, 699 blob_op_complete, NULL); 700 CU_ASSERT(g_bserrno == -EINVAL); 701 702 spdk_blob_close(blob, blob_op_complete, NULL); 703 CU_ASSERT(g_bserrno == 0); 704 705 spdk_bs_free_io_channel(channel); 706 707 spdk_bs_unload(g_bs, bs_op_complete, NULL); 708 CU_ASSERT(g_bserrno == 0); 709 g_bs = NULL; 710 } 711 712 static void 713 blob_read(void) 714 { 715 struct spdk_blob_store *bs; 716 struct spdk_bs_dev *dev; 717 struct spdk_blob *blob; 718 struct spdk_io_channel *channel; 719 spdk_blob_id blobid; 720 uint64_t pages_per_cluster; 721 uint8_t payload[10 * 4096]; 722 int rc; 723 724 dev = init_dev(); 725 726 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 727 CU_ASSERT(g_bserrno == 0); 728 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 729 bs = g_bs; 730 731 pages_per_cluster = spdk_bs_get_cluster_size(bs) / spdk_bs_get_page_size(bs); 732 733 channel = spdk_bs_alloc_io_channel(bs); 734 CU_ASSERT(channel != NULL); 735 736 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 737 CU_ASSERT(g_bserrno == 0); 738 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 739 blobid = g_blobid; 740 741 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 742 CU_ASSERT(g_bserrno == 0); 743 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 744 blob = g_blob; 745 746 /* Read from a blob with 0 size */ 747 spdk_bs_io_read_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 748 CU_ASSERT(g_bserrno == -EINVAL); 749 750 /* Resize the blob */ 751 rc = spdk_blob_resize(blob, 5); 752 CU_ASSERT(rc == 0); 753 754 /* Confirm that read passes if blob is marked read-only. */ 755 __blob_to_data(blob)->data_ro = true; 756 spdk_bs_io_read_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 757 CU_ASSERT(g_bserrno == 0); 758 __blob_to_data(blob)->data_ro = false; 759 760 /* Read from the blob */ 761 spdk_bs_io_read_blob(blob, channel, payload, 0, 1, blob_op_complete, NULL); 762 CU_ASSERT(g_bserrno == 0); 763 764 /* Read starting beyond the end */ 765 spdk_bs_io_read_blob(blob, channel, payload, 5 * pages_per_cluster, 1, blob_op_complete, 766 NULL); 767 CU_ASSERT(g_bserrno == -EINVAL); 768 769 /* Read starting at a valid location but going off the end */ 770 spdk_bs_io_read_blob(blob, channel, payload, 4 * pages_per_cluster, pages_per_cluster + 1, 771 blob_op_complete, NULL); 772 CU_ASSERT(g_bserrno == -EINVAL); 773 774 spdk_blob_close(blob, blob_op_complete, NULL); 775 CU_ASSERT(g_bserrno == 0); 776 777 spdk_bs_free_io_channel(channel); 778 779 spdk_bs_unload(g_bs, bs_op_complete, NULL); 780 CU_ASSERT(g_bserrno == 0); 781 g_bs = NULL; 782 } 783 784 static void 785 blob_rw_verify(void) 786 { 787 struct spdk_blob_store *bs; 788 struct spdk_bs_dev *dev; 789 struct spdk_blob *blob; 790 struct spdk_io_channel *channel; 791 spdk_blob_id blobid; 792 uint8_t payload_read[10 * 4096]; 793 uint8_t payload_write[10 * 4096]; 794 int rc; 795 796 dev = init_dev(); 797 798 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 799 CU_ASSERT(g_bserrno == 0); 800 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 801 bs = g_bs; 802 803 channel = spdk_bs_alloc_io_channel(bs); 804 CU_ASSERT(channel != NULL); 805 806 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 807 CU_ASSERT(g_bserrno == 0); 808 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 809 blobid = g_blobid; 810 811 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 812 CU_ASSERT(g_bserrno == 0); 813 CU_ASSERT(g_blob != NULL); 814 blob = g_blob; 815 816 rc = spdk_blob_resize(blob, 32); 817 CU_ASSERT(rc == 0); 818 819 memset(payload_write, 0xE5, sizeof(payload_write)); 820 spdk_bs_io_write_blob(blob, channel, payload_write, 4, 10, blob_op_complete, NULL); 821 CU_ASSERT(g_bserrno == 0); 822 823 memset(payload_read, 0x00, sizeof(payload_read)); 824 spdk_bs_io_read_blob(blob, channel, payload_read, 4, 10, blob_op_complete, NULL); 825 CU_ASSERT(g_bserrno == 0); 826 CU_ASSERT(memcmp(payload_write, payload_read, 4 * 4096) == 0); 827 828 spdk_blob_close(blob, blob_op_complete, NULL); 829 CU_ASSERT(g_bserrno == 0); 830 831 spdk_bs_free_io_channel(channel); 832 833 spdk_bs_unload(g_bs, bs_op_complete, NULL); 834 CU_ASSERT(g_bserrno == 0); 835 g_bs = NULL; 836 } 837 838 static void 839 blob_rw_verify_iov(void) 840 { 841 struct spdk_blob_store *bs; 842 struct spdk_bs_dev *dev; 843 struct spdk_blob *blob; 844 struct spdk_io_channel *channel; 845 spdk_blob_id blobid; 846 uint8_t payload_read[10 * 4096]; 847 uint8_t payload_write[10 * 4096]; 848 struct iovec iov_read[3]; 849 struct iovec iov_write[3]; 850 void *buf; 851 int rc; 852 853 dev = init_dev(); 854 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE); 855 856 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 857 CU_ASSERT(g_bserrno == 0); 858 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 859 bs = g_bs; 860 861 channel = spdk_bs_alloc_io_channel(bs); 862 CU_ASSERT(channel != NULL); 863 864 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 865 CU_ASSERT(g_bserrno == 0); 866 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 867 blobid = g_blobid; 868 869 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 870 CU_ASSERT(g_bserrno == 0); 871 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 872 blob = g_blob; 873 874 rc = spdk_blob_resize(blob, 2); 875 CU_ASSERT(rc == 0); 876 877 /* 878 * Manually adjust the offset of the blob's second cluster. This allows 879 * us to make sure that the readv/write code correctly accounts for I/O 880 * that cross cluster boundaries. Start by asserting that the allocated 881 * clusters are where we expect before modifying the second cluster. 882 */ 883 CU_ASSERT(__blob_to_data(blob)->active.clusters[0] == 1 * 256); 884 CU_ASSERT(__blob_to_data(blob)->active.clusters[1] == 2 * 256); 885 __blob_to_data(blob)->active.clusters[1] = 3 * 256; 886 887 memset(payload_write, 0xE5, sizeof(payload_write)); 888 iov_write[0].iov_base = payload_write; 889 iov_write[0].iov_len = 1 * 4096; 890 iov_write[1].iov_base = payload_write + 1 * 4096; 891 iov_write[1].iov_len = 5 * 4096; 892 iov_write[2].iov_base = payload_write + 6 * 4096; 893 iov_write[2].iov_len = 4 * 4096; 894 /* 895 * Choose a page offset just before the cluster boundary. The first 6 pages of payload 896 * will get written to the first cluster, the last 4 to the second cluster. 897 */ 898 spdk_bs_io_writev_blob(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL); 899 CU_ASSERT(g_bserrno == 0); 900 901 memset(payload_read, 0xAA, sizeof(payload_read)); 902 iov_read[0].iov_base = payload_read; 903 iov_read[0].iov_len = 3 * 4096; 904 iov_read[1].iov_base = payload_read + 3 * 4096; 905 iov_read[1].iov_len = 4 * 4096; 906 iov_read[2].iov_base = payload_read + 7 * 4096; 907 iov_read[2].iov_len = 3 * 4096; 908 spdk_bs_io_readv_blob(blob, channel, iov_read, 3, 250, 10, blob_op_complete, NULL); 909 CU_ASSERT(g_bserrno == 0); 910 CU_ASSERT(memcmp(payload_write, payload_read, 10 * 4096) == 0); 911 912 buf = calloc(1, 256 * 4096); 913 SPDK_CU_ASSERT_FATAL(buf != NULL); 914 /* Check that cluster 2 on "disk" was not modified. */ 915 CU_ASSERT(memcmp(buf, &g_dev_buffer[512 * 4096], 256 * 4096) == 0); 916 free(buf); 917 918 spdk_blob_close(blob, blob_op_complete, NULL); 919 CU_ASSERT(g_bserrno == 0); 920 921 spdk_bs_free_io_channel(channel); 922 923 spdk_bs_unload(g_bs, bs_op_complete, NULL); 924 CU_ASSERT(g_bserrno == 0); 925 g_bs = NULL; 926 } 927 928 static uint32_t 929 bs_channel_get_req_count(struct spdk_io_channel *_channel) 930 { 931 struct spdk_bs_channel *channel = spdk_io_channel_get_ctx(_channel); 932 struct spdk_bs_request_set *set; 933 uint32_t count = 0; 934 935 TAILQ_FOREACH(set, &channel->reqs, link) { 936 count++; 937 } 938 939 return count; 940 } 941 942 static void 943 blob_rw_verify_iov_nomem(void) 944 { 945 struct spdk_blob_store *bs; 946 struct spdk_bs_dev *dev; 947 struct spdk_blob *blob; 948 struct spdk_io_channel *channel; 949 spdk_blob_id blobid; 950 uint8_t payload_write[10 * 4096]; 951 struct iovec iov_write[3]; 952 uint32_t req_count; 953 int rc; 954 955 dev = init_dev(); 956 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE); 957 958 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 959 CU_ASSERT(g_bserrno == 0); 960 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 961 bs = g_bs; 962 963 channel = spdk_bs_alloc_io_channel(bs); 964 CU_ASSERT(channel != NULL); 965 966 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 967 CU_ASSERT(g_bserrno == 0); 968 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 969 blobid = g_blobid; 970 971 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 972 CU_ASSERT(g_bserrno == 0); 973 CU_ASSERT(g_blob != NULL); 974 blob = g_blob; 975 976 rc = spdk_blob_resize(blob, 2); 977 CU_ASSERT(rc == 0); 978 979 /* 980 * Choose a page offset just before the cluster boundary. The first 6 pages of payload 981 * will get written to the first cluster, the last 4 to the second cluster. 982 */ 983 iov_write[0].iov_base = payload_write; 984 iov_write[0].iov_len = 1 * 4096; 985 iov_write[1].iov_base = payload_write + 1 * 4096; 986 iov_write[1].iov_len = 5 * 4096; 987 iov_write[2].iov_base = payload_write + 6 * 4096; 988 iov_write[2].iov_len = 4 * 4096; 989 MOCK_SET(calloc, void *, NULL); 990 req_count = bs_channel_get_req_count(channel); 991 spdk_bs_io_writev_blob(blob, channel, iov_write, 3, 250, 10, blob_op_complete, NULL); 992 CU_ASSERT(g_bserrno = -ENOMEM); 993 CU_ASSERT(req_count == bs_channel_get_req_count(channel)); 994 MOCK_SET(calloc, void *, (void *)MOCK_PASS_THRU); 995 996 spdk_blob_close(blob, blob_op_complete, NULL); 997 CU_ASSERT(g_bserrno == 0); 998 999 spdk_bs_free_io_channel(channel); 1000 1001 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1002 CU_ASSERT(g_bserrno == 0); 1003 g_bs = NULL; 1004 } 1005 1006 static void 1007 blob_rw_iov_read_only(void) 1008 { 1009 struct spdk_blob_store *bs; 1010 struct spdk_bs_dev *dev; 1011 struct spdk_blob *blob; 1012 struct spdk_io_channel *channel; 1013 spdk_blob_id blobid; 1014 uint8_t payload_read[4096]; 1015 uint8_t payload_write[4096]; 1016 struct iovec iov_read; 1017 struct iovec iov_write; 1018 int rc; 1019 1020 dev = init_dev(); 1021 memset(g_dev_buffer, 0, DEV_BUFFER_SIZE); 1022 1023 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 1024 CU_ASSERT(g_bserrno == 0); 1025 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1026 bs = g_bs; 1027 1028 channel = spdk_bs_alloc_io_channel(bs); 1029 CU_ASSERT(channel != NULL); 1030 1031 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 1032 CU_ASSERT(g_bserrno == 0); 1033 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1034 blobid = g_blobid; 1035 1036 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 1037 CU_ASSERT(g_bserrno == 0); 1038 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 1039 blob = g_blob; 1040 1041 rc = spdk_blob_resize(blob, 2); 1042 CU_ASSERT(rc == 0); 1043 1044 /* Verify that writev failed if read_only flag is set. */ 1045 __blob_to_data(blob)->data_ro = true; 1046 iov_write.iov_base = payload_write; 1047 iov_write.iov_len = sizeof(payload_write); 1048 spdk_bs_io_writev_blob(blob, channel, &iov_write, 1, 0, 1, blob_op_complete, NULL); 1049 CU_ASSERT(g_bserrno == -EPERM); 1050 1051 /* Verify that reads pass if data_ro flag is set. */ 1052 iov_read.iov_base = payload_read; 1053 iov_read.iov_len = sizeof(payload_read); 1054 spdk_bs_io_readv_blob(blob, channel, &iov_read, 1, 0, 1, blob_op_complete, NULL); 1055 CU_ASSERT(g_bserrno == 0); 1056 1057 spdk_blob_close(blob, blob_op_complete, NULL); 1058 CU_ASSERT(g_bserrno == 0); 1059 1060 spdk_bs_free_io_channel(channel); 1061 1062 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1063 CU_ASSERT(g_bserrno == 0); 1064 g_bs = NULL; 1065 } 1066 1067 static void 1068 blob_iter(void) 1069 { 1070 struct spdk_blob_store *bs; 1071 struct spdk_bs_dev *dev; 1072 struct spdk_blob *blob; 1073 spdk_blob_id blobid; 1074 1075 dev = init_dev(); 1076 1077 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 1078 CU_ASSERT(g_bserrno == 0); 1079 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1080 bs = g_bs; 1081 1082 spdk_bs_iter_first(bs, blob_op_with_handle_complete, NULL); 1083 CU_ASSERT(g_blob == NULL); 1084 CU_ASSERT(g_bserrno == -ENOENT); 1085 1086 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 1087 CU_ASSERT(g_bserrno == 0); 1088 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1089 blobid = g_blobid; 1090 1091 spdk_bs_iter_first(bs, blob_op_with_handle_complete, NULL); 1092 CU_ASSERT(g_blob != NULL); 1093 CU_ASSERT(g_bserrno == 0); 1094 blob = g_blob; 1095 CU_ASSERT(spdk_blob_get_id(blob) == blobid); 1096 1097 spdk_bs_iter_next(bs, blob, blob_op_with_handle_complete, NULL); 1098 CU_ASSERT(g_blob == NULL); 1099 CU_ASSERT(g_bserrno == -ENOENT); 1100 1101 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1102 CU_ASSERT(g_bserrno == 0); 1103 g_bs = NULL; 1104 } 1105 1106 static void 1107 blob_xattr(void) 1108 { 1109 struct spdk_blob_store *bs; 1110 struct spdk_bs_dev *dev; 1111 struct spdk_blob *blob; 1112 spdk_blob_id blobid; 1113 uint64_t length; 1114 int rc; 1115 const char *name1, *name2; 1116 const void *value; 1117 size_t value_len; 1118 struct spdk_xattr_names *names; 1119 1120 dev = init_dev(); 1121 1122 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 1123 CU_ASSERT(g_bserrno == 0); 1124 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1125 bs = g_bs; 1126 1127 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 1128 CU_ASSERT(g_bserrno == 0); 1129 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1130 blobid = g_blobid; 1131 1132 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 1133 CU_ASSERT(g_bserrno == 0); 1134 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 1135 blob = g_blob; 1136 1137 /* Test that set_xattr fails if md_ro flag is set. */ 1138 __blob_to_data(blob)->md_ro = true; 1139 rc = spdk_blob_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1); 1140 CU_ASSERT(rc == -EPERM); 1141 1142 __blob_to_data(blob)->md_ro = false; 1143 rc = spdk_blob_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1); 1144 CU_ASSERT(rc == 0); 1145 1146 length = 2345; 1147 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 1148 CU_ASSERT(rc == 0); 1149 1150 /* Overwrite "length" xattr. */ 1151 length = 3456; 1152 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 1153 CU_ASSERT(rc == 0); 1154 1155 /* get_xattr should still work even if md_ro flag is set. */ 1156 value = NULL; 1157 __blob_to_data(blob)->md_ro = true; 1158 rc = spdk_blob_get_xattr_value(blob, "length", &value, &value_len); 1159 CU_ASSERT(rc == 0); 1160 SPDK_CU_ASSERT_FATAL(value != NULL); 1161 CU_ASSERT(*(uint64_t *)value == length); 1162 CU_ASSERT(value_len == 8); 1163 __blob_to_data(blob)->md_ro = false; 1164 1165 rc = spdk_blob_get_xattr_value(blob, "foobar", &value, &value_len); 1166 CU_ASSERT(rc == -ENOENT); 1167 1168 names = NULL; 1169 rc = spdk_blob_get_xattr_names(blob, &names); 1170 CU_ASSERT(rc == 0); 1171 SPDK_CU_ASSERT_FATAL(names != NULL); 1172 CU_ASSERT(spdk_xattr_names_get_count(names) == 2); 1173 name1 = spdk_xattr_names_get_name(names, 0); 1174 SPDK_CU_ASSERT_FATAL(name1 != NULL); 1175 CU_ASSERT(!strcmp(name1, "name") || !strcmp(name1, "length")); 1176 name2 = spdk_xattr_names_get_name(names, 1); 1177 SPDK_CU_ASSERT_FATAL(name2 != NULL); 1178 CU_ASSERT(!strcmp(name2, "name") || !strcmp(name2, "length")); 1179 CU_ASSERT(strcmp(name1, name2)); 1180 spdk_xattr_names_free(names); 1181 1182 /* Confirm that remove_xattr fails if md_ro is set to true. */ 1183 __blob_to_data(blob)->md_ro = true; 1184 rc = spdk_blob_remove_xattr(blob, "name"); 1185 CU_ASSERT(rc == -EPERM); 1186 1187 __blob_to_data(blob)->md_ro = false; 1188 rc = spdk_blob_remove_xattr(blob, "name"); 1189 CU_ASSERT(rc == 0); 1190 1191 rc = spdk_blob_remove_xattr(blob, "foobar"); 1192 CU_ASSERT(rc == -ENOENT); 1193 1194 spdk_blob_close(blob, blob_op_complete, NULL); 1195 1196 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1197 CU_ASSERT(g_bserrno == 0); 1198 g_bs = NULL; 1199 } 1200 1201 static void 1202 bs_load(void) 1203 { 1204 struct spdk_bs_dev *dev; 1205 spdk_blob_id blobid; 1206 struct spdk_blob *blob; 1207 struct spdk_bs_super_block *super_block; 1208 uint64_t length; 1209 int rc; 1210 const void *value; 1211 size_t value_len; 1212 struct spdk_bs_opts opts; 1213 1214 g_scheduler_delay = true; 1215 1216 dev = init_dev(); 1217 spdk_bs_opts_init(&opts); 1218 strncpy(opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); 1219 1220 /* Initialize a new blob store */ 1221 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1222 CU_ASSERT(g_bserrno == 0); 1223 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1224 1225 /* Try to open a blobid that does not exist */ 1226 spdk_bs_open_blob(g_bs, 0, blob_op_with_handle_complete, NULL); 1227 CU_ASSERT(g_bserrno == -ENOENT); 1228 CU_ASSERT(g_blob == NULL); 1229 1230 /* Create a blob */ 1231 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL); 1232 CU_ASSERT(g_bserrno == 0); 1233 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1234 blobid = g_blobid; 1235 1236 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); 1237 CU_ASSERT(g_bserrno == 0); 1238 CU_ASSERT(g_blob != NULL); 1239 blob = g_blob; 1240 1241 /* Try again to open valid blob but without the upper bit set */ 1242 spdk_bs_open_blob(g_bs, blobid & 0xFFFFFFFF, blob_op_with_handle_complete, NULL); 1243 CU_ASSERT(g_bserrno == -ENOENT); 1244 CU_ASSERT(g_blob == NULL); 1245 1246 /* Set some xattrs */ 1247 rc = spdk_blob_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1); 1248 CU_ASSERT(rc == 0); 1249 1250 length = 2345; 1251 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 1252 CU_ASSERT(rc == 0); 1253 1254 /* Resize the blob */ 1255 rc = spdk_blob_resize(blob, 10); 1256 CU_ASSERT(rc == 0); 1257 1258 spdk_blob_close(blob, blob_op_complete, NULL); 1259 CU_ASSERT(g_bserrno == 0); 1260 blob = NULL; 1261 g_blob = NULL; 1262 g_blobid = SPDK_BLOBID_INVALID; 1263 1264 /* Unload the blob store */ 1265 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1266 CU_ASSERT(g_bserrno == 0); 1267 g_bs = NULL; 1268 g_blob = NULL; 1269 g_blobid = 0; 1270 1271 super_block = (struct spdk_bs_super_block *)g_dev_buffer; 1272 CU_ASSERT(super_block->clean == 1); 1273 1274 1275 /* Load an existing blob store */ 1276 dev = init_dev(); 1277 strncpy(opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); 1278 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1279 CU_ASSERT(g_bserrno == 0); 1280 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1281 1282 super_block = (struct spdk_bs_super_block *)g_dev_buffer; 1283 CU_ASSERT(super_block->clean == 0); 1284 1285 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); 1286 CU_ASSERT(g_bserrno == 0); 1287 CU_ASSERT(g_blob != NULL); 1288 blob = g_blob; 1289 1290 /* Get the xattrs */ 1291 value = NULL; 1292 rc = spdk_blob_get_xattr_value(blob, "length", &value, &value_len); 1293 CU_ASSERT(rc == 0); 1294 SPDK_CU_ASSERT_FATAL(value != NULL); 1295 CU_ASSERT(*(uint64_t *)value == length); 1296 CU_ASSERT(value_len == 8); 1297 1298 rc = spdk_blob_get_xattr_value(blob, "foobar", &value, &value_len); 1299 CU_ASSERT(rc == -ENOENT); 1300 1301 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 1302 1303 spdk_blob_close(blob, blob_op_complete, NULL); 1304 CU_ASSERT(g_bserrno == 0); 1305 blob = NULL; 1306 g_blob = NULL; 1307 g_blobid = SPDK_BLOBID_INVALID; 1308 1309 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1310 CU_ASSERT(g_bserrno == 0); 1311 g_bs = NULL; 1312 g_scheduler_delay = false; 1313 } 1314 1315 static void 1316 bs_type(void) 1317 { 1318 struct spdk_bs_dev *dev; 1319 struct spdk_bs_opts opts; 1320 1321 g_scheduler_delay = true; 1322 1323 dev = init_dev(); 1324 spdk_bs_opts_init(&opts); 1325 strncpy(opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); 1326 1327 /* Initialize a new blob store */ 1328 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1329 CU_ASSERT(g_bserrno == 0); 1330 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1331 1332 /* Unload the blob store */ 1333 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1334 CU_ASSERT(g_bserrno == 0); 1335 g_bs = NULL; 1336 g_blob = NULL; 1337 g_blobid = 0; 1338 1339 /* Load non existing blobstore type */ 1340 dev = init_dev(); 1341 strncpy(opts.bstype.bstype, "NONEXISTING", SPDK_BLOBSTORE_TYPE_LENGTH); 1342 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1343 CU_ASSERT(g_bserrno != 0); 1344 1345 /* Load with empty blobstore type */ 1346 dev = init_dev(); 1347 strncpy(opts.bstype.bstype, "", SPDK_BLOBSTORE_TYPE_LENGTH); 1348 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1349 CU_ASSERT(g_bserrno == 0); 1350 1351 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1352 CU_ASSERT(g_bserrno == 0); 1353 g_bs = NULL; 1354 1355 /* Initialize a new blob store with empty bstype */ 1356 dev = init_dev(); 1357 strncpy(opts.bstype.bstype, "", SPDK_BLOBSTORE_TYPE_LENGTH); 1358 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 1359 CU_ASSERT(g_bserrno == 0); 1360 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1361 1362 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1363 CU_ASSERT(g_bserrno == 0); 1364 g_bs = NULL; 1365 1366 /* Load non existing blobstore type */ 1367 dev = init_dev(); 1368 strncpy(opts.bstype.bstype, "NONEXISTING", SPDK_BLOBSTORE_TYPE_LENGTH); 1369 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1370 CU_ASSERT(g_bserrno != 0); 1371 1372 /* Load with empty blobstore type */ 1373 dev = init_dev(); 1374 strncpy(opts.bstype.bstype, "", SPDK_BLOBSTORE_TYPE_LENGTH); 1375 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1376 CU_ASSERT(g_bserrno == 0); 1377 1378 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1379 CU_ASSERT(g_bserrno == 0); 1380 g_bs = NULL; 1381 g_scheduler_delay = false; 1382 } 1383 1384 static void 1385 bs_super_block(void) 1386 { 1387 struct spdk_bs_dev *dev; 1388 struct spdk_bs_super_block *super_block; 1389 struct spdk_bs_opts opts; 1390 struct spdk_bs_super_block_ver1 super_block_v1; 1391 1392 g_scheduler_delay = true; 1393 1394 dev = init_dev(); 1395 spdk_bs_opts_init(&opts); 1396 strncpy(opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); 1397 1398 /* Initialize a new blob store */ 1399 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1400 CU_ASSERT(g_bserrno == 0); 1401 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1402 1403 /* Unload the blob store */ 1404 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1405 CU_ASSERT(g_bserrno == 0); 1406 g_bs = NULL; 1407 g_blob = NULL; 1408 g_blobid = 0; 1409 1410 /* Load an existing blob store with version newer than supported */ 1411 super_block = (struct spdk_bs_super_block *)g_dev_buffer; 1412 super_block->version++; 1413 1414 dev = init_dev(); 1415 strncpy(opts.bstype.bstype, "", SPDK_BLOBSTORE_TYPE_LENGTH); 1416 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1417 CU_ASSERT(g_bserrno != 0); 1418 1419 /* Create a new blob store with super block version 1 */ 1420 dev = init_dev(); 1421 super_block_v1.version = 1; 1422 strncpy(super_block_v1.signature, "SPDKBLOB", sizeof(super_block_v1.signature)); 1423 super_block_v1.length = 0x1000; 1424 super_block_v1.clean = 1; 1425 super_block_v1.super_blob = 0xFFFFFFFFFFFFFFFF; 1426 super_block_v1.cluster_size = 0x100000; 1427 super_block_v1.used_page_mask_start = 0x01; 1428 super_block_v1.used_page_mask_len = 0x01; 1429 super_block_v1.used_cluster_mask_start = 0x02; 1430 super_block_v1.used_cluster_mask_len = 0x01; 1431 super_block_v1.md_start = 0x03; 1432 super_block_v1.md_len = 0x40; 1433 memset(super_block_v1.reserved, 0, 4036); 1434 super_block_v1.crc = _spdk_blob_md_page_calc_crc(&super_block_v1); 1435 memcpy(g_dev_buffer, &super_block_v1, sizeof(struct spdk_bs_super_block_ver1)); 1436 1437 strncpy(opts.bstype.bstype, "", SPDK_BLOBSTORE_TYPE_LENGTH); 1438 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1439 CU_ASSERT(g_bserrno == 0); 1440 1441 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1442 CU_ASSERT(g_bserrno == 0); 1443 g_bs = NULL; 1444 g_scheduler_delay = false; 1445 } 1446 1447 /* 1448 * Create a blobstore and then unload it. 1449 */ 1450 static void 1451 bs_unload(void) 1452 { 1453 struct spdk_bs_dev *dev; 1454 struct spdk_blob_store *bs; 1455 spdk_blob_id blobid; 1456 struct spdk_blob *blob; 1457 1458 dev = init_dev(); 1459 1460 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 1461 CU_ASSERT(g_bserrno == 0); 1462 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1463 bs = g_bs; 1464 1465 /* Create a blob and open it. */ 1466 g_bserrno = -1; 1467 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 1468 CU_ASSERT(g_bserrno == 0); 1469 CU_ASSERT(g_blobid > 0); 1470 blobid = g_blobid; 1471 1472 g_bserrno = -1; 1473 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 1474 CU_ASSERT(g_bserrno == 0); 1475 CU_ASSERT(g_blob != NULL); 1476 blob = g_blob; 1477 1478 /* Try to unload blobstore, should fail with open blob */ 1479 g_bserrno = -1; 1480 spdk_bs_unload(bs, bs_op_complete, NULL); 1481 CU_ASSERT(g_bserrno == -EBUSY); 1482 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1483 1484 /* Close the blob, then successfully unload blobstore */ 1485 g_bserrno = -1; 1486 spdk_blob_close(blob, blob_op_complete, NULL); 1487 CU_ASSERT(g_bserrno == 0); 1488 1489 g_bserrno = -1; 1490 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1491 CU_ASSERT(g_bserrno == 0); 1492 g_bs = NULL; 1493 } 1494 1495 /* 1496 * Create a blobstore with a cluster size different than the default, and ensure it is 1497 * persisted. 1498 */ 1499 static void 1500 bs_cluster_sz(void) 1501 { 1502 struct spdk_bs_dev *dev; 1503 struct spdk_bs_opts opts; 1504 uint32_t cluster_sz; 1505 1506 /* Set cluster size to zero */ 1507 dev = init_dev(); 1508 spdk_bs_opts_init(&opts); 1509 opts.cluster_sz = 0; 1510 1511 /* Initialize a new blob store */ 1512 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1513 CU_ASSERT(g_bserrno == -EINVAL); 1514 SPDK_CU_ASSERT_FATAL(g_bs == NULL); 1515 1516 /* 1517 * Set cluster size to blobstore page size, 1518 * to work it is required to be at least twice the blobstore page size. 1519 */ 1520 dev = init_dev(); 1521 spdk_bs_opts_init(&opts); 1522 opts.cluster_sz = SPDK_BS_PAGE_SIZE; 1523 1524 /* Initialize a new blob store */ 1525 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1526 CU_ASSERT(g_bserrno == -ENOMEM); 1527 SPDK_CU_ASSERT_FATAL(g_bs == NULL); 1528 1529 /* 1530 * Set cluster size to lower than page size, 1531 * to work it is required to be at least twice the blobstore page size. 1532 */ 1533 dev = init_dev(); 1534 spdk_bs_opts_init(&opts); 1535 opts.cluster_sz = SPDK_BS_PAGE_SIZE - 1; 1536 1537 /* Initialize a new blob store */ 1538 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1539 CU_ASSERT(g_bserrno == -ENOMEM); 1540 SPDK_CU_ASSERT_FATAL(g_bs == NULL); 1541 1542 /* Set cluster size to twice the default */ 1543 dev = init_dev(); 1544 spdk_bs_opts_init(&opts); 1545 opts.cluster_sz *= 2; 1546 cluster_sz = opts.cluster_sz; 1547 1548 /* Initialize a new blob store */ 1549 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1550 CU_ASSERT(g_bserrno == 0); 1551 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1552 1553 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 1554 1555 /* Unload the blob store */ 1556 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1557 CU_ASSERT(g_bserrno == 0); 1558 g_bs = NULL; 1559 g_blob = NULL; 1560 g_blobid = 0; 1561 1562 dev = init_dev(); 1563 /* Load an existing blob store */ 1564 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1565 CU_ASSERT(g_bserrno == 0); 1566 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1567 1568 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 1569 1570 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1571 CU_ASSERT(g_bserrno == 0); 1572 g_bs = NULL; 1573 } 1574 1575 /* 1576 * Create a blobstore, reload it and ensure total usable cluster count 1577 * stays the same. 1578 */ 1579 static void 1580 bs_usable_clusters(void) 1581 { 1582 struct spdk_bs_dev *dev; 1583 struct spdk_bs_opts opts; 1584 uint32_t clusters; 1585 int i, rc; 1586 1587 /* Init blobstore */ 1588 dev = init_dev(); 1589 spdk_bs_opts_init(&opts); 1590 1591 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1592 CU_ASSERT(g_bserrno == 0); 1593 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1594 1595 clusters = spdk_bs_total_data_cluster_count(g_bs); 1596 1597 /* Unload the blob store */ 1598 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1599 CU_ASSERT(g_bserrno == 0); 1600 g_bs = NULL; 1601 1602 dev = init_dev(); 1603 /* Load an existing blob store */ 1604 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1605 CU_ASSERT(g_bserrno == 0); 1606 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1607 1608 CU_ASSERT(spdk_bs_total_data_cluster_count(g_bs) == clusters); 1609 1610 /* Create and resize blobs to make sure that useable cluster count won't change */ 1611 for (i = 0; i < 4; i++) { 1612 g_bserrno = -1; 1613 g_blobid = SPDK_BLOBID_INVALID; 1614 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL); 1615 CU_ASSERT(g_bserrno == 0); 1616 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1617 1618 g_bserrno = -1; 1619 g_blob = NULL; 1620 spdk_bs_open_blob(g_bs, g_blobid, blob_op_with_handle_complete, NULL); 1621 CU_ASSERT(g_bserrno == 0); 1622 CU_ASSERT(g_blob != NULL); 1623 1624 rc = spdk_blob_resize(g_blob, 10); 1625 CU_ASSERT(rc == 0); 1626 1627 g_bserrno = -1; 1628 spdk_blob_close(g_blob, blob_op_complete, NULL); 1629 CU_ASSERT(g_bserrno == 0); 1630 1631 CU_ASSERT(spdk_bs_total_data_cluster_count(g_bs) == clusters); 1632 } 1633 1634 /* Reload the blob store to make sure that nothing changed */ 1635 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1636 CU_ASSERT(g_bserrno == 0); 1637 g_bs = NULL; 1638 1639 dev = init_dev(); 1640 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1641 CU_ASSERT(g_bserrno == 0); 1642 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1643 1644 CU_ASSERT(spdk_bs_total_data_cluster_count(g_bs) == clusters); 1645 1646 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1647 CU_ASSERT(g_bserrno == 0); 1648 g_bs = NULL; 1649 } 1650 1651 /* 1652 * Test resizing of the metadata blob. This requires creating enough blobs 1653 * so that one cluster is not enough to fit the metadata for those blobs. 1654 * To induce this condition to happen more quickly, we reduce the cluster 1655 * size to 16KB, which means only 4 4KB blob metadata pages can fit. 1656 */ 1657 static void 1658 bs_resize_md(void) 1659 { 1660 const int CLUSTER_PAGE_COUNT = 4; 1661 const int NUM_BLOBS = CLUSTER_PAGE_COUNT * 4; 1662 struct spdk_bs_dev *dev; 1663 struct spdk_bs_opts opts; 1664 uint32_t cluster_sz; 1665 spdk_blob_id blobids[NUM_BLOBS]; 1666 int i; 1667 1668 1669 dev = init_dev(); 1670 spdk_bs_opts_init(&opts); 1671 opts.cluster_sz = CLUSTER_PAGE_COUNT * 4096; 1672 cluster_sz = opts.cluster_sz; 1673 1674 /* Initialize a new blob store */ 1675 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1676 CU_ASSERT(g_bserrno == 0); 1677 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1678 1679 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 1680 1681 for (i = 0; i < NUM_BLOBS; i++) { 1682 g_bserrno = -1; 1683 g_blobid = SPDK_BLOBID_INVALID; 1684 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL); 1685 CU_ASSERT(g_bserrno == 0); 1686 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1687 blobids[i] = g_blobid; 1688 } 1689 1690 /* Unload the blob store */ 1691 g_bserrno = -1; 1692 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1693 CU_ASSERT(g_bserrno == 0); 1694 1695 /* Load an existing blob store */ 1696 g_bserrno = -1; 1697 g_bs = NULL; 1698 dev = init_dev(); 1699 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1700 CU_ASSERT(g_bserrno == 0); 1701 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1702 1703 CU_ASSERT(spdk_bs_get_cluster_size(g_bs) == cluster_sz); 1704 1705 for (i = 0; i < NUM_BLOBS; i++) { 1706 g_bserrno = -1; 1707 g_blob = NULL; 1708 spdk_bs_open_blob(g_bs, blobids[i], blob_op_with_handle_complete, NULL); 1709 CU_ASSERT(g_bserrno == 0); 1710 CU_ASSERT(g_blob != NULL); 1711 g_bserrno = -1; 1712 spdk_blob_close(g_blob, blob_op_complete, NULL); 1713 CU_ASSERT(g_bserrno == 0); 1714 } 1715 1716 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1717 CU_ASSERT(g_bserrno == 0); 1718 g_bs = NULL; 1719 } 1720 1721 static void 1722 bs_destroy(void) 1723 { 1724 struct spdk_bs_dev *dev; 1725 struct spdk_bs_opts opts; 1726 1727 g_scheduler_delay = true; 1728 1729 _bs_flush_scheduler(); 1730 CU_ASSERT(TAILQ_EMPTY(&g_scheduled_ops)); 1731 1732 /* Initialize a new blob store */ 1733 dev = init_dev(); 1734 spdk_bs_opts_init(&opts); 1735 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1736 CU_ASSERT(g_bserrno == 0); 1737 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1738 1739 /* Destroy the blob store */ 1740 g_bserrno = -1; 1741 spdk_bs_destroy(g_bs, bs_op_complete, NULL); 1742 /* Callback is called after device is destroyed in next scheduler run. */ 1743 _bs_flush_scheduler(); 1744 CU_ASSERT(TAILQ_EMPTY(&g_scheduled_ops)); 1745 CU_ASSERT(g_bserrno == 0); 1746 1747 /* Loading an non-existent blob store should fail. */ 1748 g_bserrno = -1; 1749 g_bs = NULL; 1750 dev = init_dev(); 1751 1752 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1753 CU_ASSERT(g_bserrno != 0); 1754 g_scheduler_delay = false; 1755 } 1756 1757 /* Try to hit all of the corner cases associated with serializing 1758 * a blob to disk 1759 */ 1760 static void 1761 blob_serialize(void) 1762 { 1763 struct spdk_bs_dev *dev; 1764 struct spdk_bs_opts opts; 1765 struct spdk_blob_store *bs; 1766 spdk_blob_id blobid[2]; 1767 struct spdk_blob *blob[2]; 1768 uint64_t i; 1769 char *value; 1770 int rc; 1771 1772 dev = init_dev(); 1773 1774 /* Initialize a new blobstore with very small clusters */ 1775 spdk_bs_opts_init(&opts); 1776 opts.cluster_sz = dev->blocklen * 8; 1777 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 1778 CU_ASSERT(g_bserrno == 0); 1779 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1780 bs = g_bs; 1781 1782 /* Create and open two blobs */ 1783 for (i = 0; i < 2; i++) { 1784 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 1785 CU_ASSERT(g_bserrno == 0); 1786 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1787 blobid[i] = g_blobid; 1788 1789 /* Open a blob */ 1790 spdk_bs_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL); 1791 CU_ASSERT(g_bserrno == 0); 1792 CU_ASSERT(g_blob != NULL); 1793 blob[i] = g_blob; 1794 1795 /* Set a fairly large xattr on both blobs to eat up 1796 * metadata space 1797 */ 1798 value = calloc(dev->blocklen - 64, sizeof(char)); 1799 SPDK_CU_ASSERT_FATAL(value != NULL); 1800 memset(value, i, dev->blocklen / 2); 1801 rc = spdk_blob_set_xattr(blob[i], "name", value, dev->blocklen - 64); 1802 CU_ASSERT(rc == 0); 1803 free(value); 1804 } 1805 1806 /* Resize the blobs, alternating 1 cluster at a time. 1807 * This thwarts run length encoding and will cause spill 1808 * over of the extents. 1809 */ 1810 for (i = 0; i < 6; i++) { 1811 rc = spdk_blob_resize(blob[i % 2], (i / 2) + 1); 1812 CU_ASSERT(rc == 0); 1813 } 1814 1815 for (i = 0; i < 2; i++) { 1816 spdk_blob_sync_md(blob[i], blob_op_complete, NULL); 1817 CU_ASSERT(g_bserrno == 0); 1818 } 1819 1820 /* Close the blobs */ 1821 for (i = 0; i < 2; i++) { 1822 spdk_blob_close(blob[i], blob_op_complete, NULL); 1823 CU_ASSERT(g_bserrno == 0); 1824 } 1825 1826 /* Unload the blobstore */ 1827 spdk_bs_unload(bs, bs_op_complete, NULL); 1828 CU_ASSERT(g_bserrno == 0); 1829 g_bs = NULL; 1830 g_blob = NULL; 1831 g_blobid = 0; 1832 bs = NULL; 1833 1834 dev = init_dev(); 1835 /* Load an existing blob store */ 1836 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1837 CU_ASSERT(g_bserrno == 0); 1838 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1839 bs = g_bs; 1840 1841 for (i = 0; i < 2; i++) { 1842 blob[i] = NULL; 1843 1844 spdk_bs_open_blob(bs, blobid[i], blob_op_with_handle_complete, NULL); 1845 CU_ASSERT(g_bserrno == 0); 1846 CU_ASSERT(g_blob != NULL); 1847 blob[i] = g_blob; 1848 1849 CU_ASSERT(spdk_blob_get_num_clusters(blob[i]) == 3); 1850 1851 spdk_blob_close(blob[i], blob_op_complete, NULL); 1852 CU_ASSERT(g_bserrno == 0); 1853 } 1854 1855 spdk_bs_unload(bs, bs_op_complete, NULL); 1856 CU_ASSERT(g_bserrno == 0); 1857 g_bs = NULL; 1858 } 1859 1860 static void 1861 blob_crc(void) 1862 { 1863 struct spdk_blob_store *bs; 1864 struct spdk_bs_dev *dev; 1865 struct spdk_blob *blob; 1866 spdk_blob_id blobid; 1867 uint32_t page_num; 1868 int index; 1869 struct spdk_blob_md_page *page; 1870 1871 dev = init_dev(); 1872 1873 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 1874 CU_ASSERT(g_bserrno == 0); 1875 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1876 bs = g_bs; 1877 1878 spdk_bs_create_blob(bs, blob_op_with_id_complete, NULL); 1879 CU_ASSERT(g_bserrno == 0); 1880 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1881 blobid = g_blobid; 1882 1883 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 1884 CU_ASSERT(g_bserrno == 0); 1885 CU_ASSERT(g_blob != NULL); 1886 blob = g_blob; 1887 1888 spdk_blob_close(blob, blob_op_complete, NULL); 1889 CU_ASSERT(g_bserrno == 0); 1890 1891 page_num = _spdk_bs_blobid_to_page(blobid); 1892 index = DEV_BUFFER_BLOCKLEN * (bs->md_start + page_num); 1893 page = (struct spdk_blob_md_page *)&g_dev_buffer[index]; 1894 page->crc = 0; 1895 1896 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 1897 CU_ASSERT(g_bserrno == -EINVAL); 1898 CU_ASSERT(g_blob == NULL); 1899 g_bserrno = 0; 1900 1901 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); 1902 CU_ASSERT(g_bserrno == -EINVAL); 1903 1904 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1905 CU_ASSERT(g_bserrno == 0); 1906 g_bs = NULL; 1907 } 1908 1909 static void 1910 super_block_crc(void) 1911 { 1912 struct spdk_bs_dev *dev; 1913 struct spdk_bs_super_block *super_block; 1914 struct spdk_bs_opts opts; 1915 1916 dev = init_dev(); 1917 spdk_bs_opts_init(&opts); 1918 1919 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 1920 CU_ASSERT(g_bserrno == 0); 1921 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1922 1923 spdk_bs_unload(g_bs, bs_op_complete, NULL); 1924 CU_ASSERT(g_bserrno == 0); 1925 g_bs = NULL; 1926 1927 super_block = (struct spdk_bs_super_block *)g_dev_buffer; 1928 super_block->crc = 0; 1929 dev = init_dev(); 1930 1931 g_scheduler_delay = true; 1932 /* Load an existing blob store */ 1933 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 1934 1935 CU_ASSERT(g_bserrno == -EILSEQ); 1936 _bs_flush_scheduler(); 1937 CU_ASSERT(TAILQ_EMPTY(&g_scheduled_ops)); 1938 1939 g_scheduler_delay = false; 1940 } 1941 1942 /* For blob dirty shutdown test case we do the following sub-test cases: 1943 * 1 Initialize new blob store and create 1 blob with some xattrs, then we 1944 * dirty shutdown and reload the blob store and verify the xattrs. 1945 * 2 Resize the blob from 10 clusters to 20 clusters and then dirty shutdown, 1946 * reload the blob store and verify the clusters number. 1947 * 3 Create the second blob and then dirty shutdown, reload the blob store 1948 * and verify the second blob. 1949 * 4 Delete the second blob and then dirty shutdown, reload teh blob store 1950 * and verify the second blob is invalid. 1951 * 5 Create the second blob again and also create the third blob, modify the 1952 * md of second blob which makes the md invalid, and then dirty shutdown, 1953 * reload the blob store verify the second blob, it should invalid and also 1954 * verify the third blob, it should correct. 1955 */ 1956 static void 1957 blob_dirty_shutdown(void) 1958 { 1959 int rc; 1960 int index; 1961 struct spdk_bs_dev *dev; 1962 spdk_blob_id blobid1, blobid2, blobid3; 1963 struct spdk_blob *blob; 1964 uint64_t length; 1965 uint64_t free_clusters; 1966 const void *value; 1967 size_t value_len; 1968 uint32_t page_num; 1969 struct spdk_blob_md_page *page; 1970 struct spdk_bs_opts opts; 1971 1972 dev = init_dev(); 1973 spdk_bs_opts_init(&opts); 1974 /* Initialize a new blob store */ 1975 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 1976 CU_ASSERT(g_bserrno == 0); 1977 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 1978 1979 /* Create first blob */ 1980 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL); 1981 CU_ASSERT(g_bserrno == 0); 1982 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 1983 blobid1 = g_blobid; 1984 1985 spdk_bs_open_blob(g_bs, blobid1, blob_op_with_handle_complete, NULL); 1986 CU_ASSERT(g_bserrno == 0); 1987 CU_ASSERT(g_blob != NULL); 1988 blob = g_blob; 1989 1990 /* Set some xattrs */ 1991 rc = spdk_blob_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1); 1992 CU_ASSERT(rc == 0); 1993 1994 length = 2345; 1995 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 1996 CU_ASSERT(rc == 0); 1997 1998 /* Resize the blob */ 1999 rc = spdk_blob_resize(blob, 10); 2000 CU_ASSERT(rc == 0); 2001 2002 free_clusters = spdk_bs_free_cluster_count(g_bs); 2003 2004 spdk_blob_close(blob, blob_op_complete, NULL); 2005 blob = NULL; 2006 g_blob = NULL; 2007 g_blobid = SPDK_BLOBID_INVALID; 2008 2009 /* Dirty shutdown */ 2010 _spdk_bs_free(g_bs); 2011 2012 /* reload blobstore */ 2013 dev = init_dev(); 2014 spdk_bs_opts_init(&opts); 2015 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2016 CU_ASSERT(g_bserrno == 0); 2017 2018 spdk_bs_open_blob(g_bs, blobid1, blob_op_with_handle_complete, NULL); 2019 CU_ASSERT(g_bserrno == 0); 2020 CU_ASSERT(g_blob != NULL); 2021 blob = g_blob; 2022 2023 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(g_bs)); 2024 2025 /* Get the xattrs */ 2026 value = NULL; 2027 rc = spdk_blob_get_xattr_value(blob, "length", &value, &value_len); 2028 CU_ASSERT(rc == 0); 2029 SPDK_CU_ASSERT_FATAL(value != NULL); 2030 CU_ASSERT(*(uint64_t *)value == length); 2031 CU_ASSERT(value_len == 8); 2032 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 2033 2034 /* Resize the blob */ 2035 rc = spdk_blob_resize(blob, 20); 2036 CU_ASSERT(rc == 0); 2037 2038 free_clusters = spdk_bs_free_cluster_count(g_bs); 2039 2040 spdk_blob_close(blob, blob_op_complete, NULL); 2041 CU_ASSERT(g_bserrno == 0); 2042 blob = NULL; 2043 g_blob = NULL; 2044 g_blobid = SPDK_BLOBID_INVALID; 2045 2046 /* Dirty shutdown */ 2047 _spdk_bs_free(g_bs); 2048 2049 /* reload the blobstore */ 2050 dev = init_dev(); 2051 spdk_bs_opts_init(&opts); 2052 /* Load an existing blob store */ 2053 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2054 CU_ASSERT(g_bserrno == 0); 2055 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2056 spdk_bs_open_blob(g_bs, blobid1, blob_op_with_handle_complete, NULL); 2057 CU_ASSERT(g_bserrno == 0); 2058 CU_ASSERT(g_blob != NULL); 2059 blob = g_blob; 2060 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 20); 2061 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(g_bs)); 2062 2063 spdk_blob_close(blob, blob_op_complete, NULL); 2064 CU_ASSERT(g_bserrno == 0); 2065 blob = NULL; 2066 g_blob = NULL; 2067 g_blobid = SPDK_BLOBID_INVALID; 2068 2069 /* Create second blob */ 2070 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL); 2071 CU_ASSERT(g_bserrno == 0); 2072 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2073 blobid2 = g_blobid; 2074 2075 spdk_bs_open_blob(g_bs, blobid2, blob_op_with_handle_complete, NULL); 2076 CU_ASSERT(g_bserrno == 0); 2077 CU_ASSERT(g_blob != NULL); 2078 blob = g_blob; 2079 2080 /* Set some xattrs */ 2081 rc = spdk_blob_set_xattr(blob, "name", "log1.txt", strlen("log1.txt") + 1); 2082 CU_ASSERT(rc == 0); 2083 2084 length = 5432; 2085 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 2086 CU_ASSERT(rc == 0); 2087 2088 /* Resize the blob */ 2089 rc = spdk_blob_resize(blob, 10); 2090 CU_ASSERT(rc == 0); 2091 2092 free_clusters = spdk_bs_free_cluster_count(g_bs); 2093 2094 spdk_blob_close(blob, blob_op_complete, NULL); 2095 blob = NULL; 2096 g_blob = NULL; 2097 g_blobid = SPDK_BLOBID_INVALID; 2098 2099 /* Dirty shutdown */ 2100 _spdk_bs_free(g_bs); 2101 2102 /* reload the blobstore */ 2103 dev = init_dev(); 2104 spdk_bs_opts_init(&opts); 2105 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2106 CU_ASSERT(g_bserrno == 0); 2107 2108 spdk_bs_open_blob(g_bs, blobid2, blob_op_with_handle_complete, NULL); 2109 CU_ASSERT(g_bserrno == 0); 2110 CU_ASSERT(g_blob != NULL); 2111 blob = g_blob; 2112 2113 /* Get the xattrs */ 2114 value = NULL; 2115 rc = spdk_blob_get_xattr_value(blob, "length", &value, &value_len); 2116 CU_ASSERT(rc == 0); 2117 SPDK_CU_ASSERT_FATAL(value != NULL); 2118 CU_ASSERT(*(uint64_t *)value == length); 2119 CU_ASSERT(value_len == 8); 2120 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 10); 2121 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(g_bs)); 2122 2123 spdk_blob_close(blob, blob_op_complete, NULL); 2124 CU_ASSERT(g_bserrno == 0); 2125 spdk_bs_delete_blob(g_bs, blobid2, blob_op_complete, NULL); 2126 CU_ASSERT(g_bserrno == 0); 2127 2128 free_clusters = spdk_bs_free_cluster_count(g_bs); 2129 2130 /* Dirty shutdown */ 2131 _spdk_bs_free(g_bs); 2132 /* reload the blobstore */ 2133 dev = init_dev(); 2134 spdk_bs_opts_init(&opts); 2135 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2136 CU_ASSERT(g_bserrno == 0); 2137 2138 spdk_bs_open_blob(g_bs, blobid2, blob_op_with_handle_complete, NULL); 2139 CU_ASSERT(g_bserrno != 0); 2140 CU_ASSERT(g_blob == NULL); 2141 2142 spdk_bs_open_blob(g_bs, blobid1, blob_op_with_handle_complete, NULL); 2143 CU_ASSERT(g_bserrno == 0); 2144 CU_ASSERT(g_blob != NULL); 2145 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(g_bs)); 2146 spdk_blob_close(g_blob, blob_op_complete, NULL); 2147 CU_ASSERT(g_bserrno == 0); 2148 2149 spdk_bs_unload(g_bs, bs_op_complete, NULL); 2150 CU_ASSERT(g_bserrno == 0); 2151 g_bs = NULL; 2152 2153 /* reload the blobstore */ 2154 dev = init_dev(); 2155 spdk_bs_opts_init(&opts); 2156 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2157 CU_ASSERT(g_bserrno == 0); 2158 2159 /* Create second blob */ 2160 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL); 2161 CU_ASSERT(g_bserrno == 0); 2162 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2163 blobid2 = g_blobid; 2164 2165 /* Create third blob */ 2166 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL); 2167 CU_ASSERT(g_bserrno == 0); 2168 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2169 blobid3 = g_blobid; 2170 2171 spdk_bs_open_blob(g_bs, blobid2, blob_op_with_handle_complete, NULL); 2172 CU_ASSERT(g_bserrno == 0); 2173 CU_ASSERT(g_blob != NULL); 2174 blob = g_blob; 2175 2176 /* Set some xattrs for second blob */ 2177 rc = spdk_blob_set_xattr(blob, "name", "log1.txt", strlen("log1.txt") + 1); 2178 CU_ASSERT(rc == 0); 2179 2180 length = 5432; 2181 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 2182 CU_ASSERT(rc == 0); 2183 2184 spdk_blob_close(blob, blob_op_complete, NULL); 2185 blob = NULL; 2186 g_blob = NULL; 2187 g_blobid = SPDK_BLOBID_INVALID; 2188 2189 spdk_bs_open_blob(g_bs, blobid3, blob_op_with_handle_complete, NULL); 2190 CU_ASSERT(g_bserrno == 0); 2191 CU_ASSERT(g_blob != NULL); 2192 blob = g_blob; 2193 2194 /* Set some xattrs for third blob */ 2195 rc = spdk_blob_set_xattr(blob, "name", "log2.txt", strlen("log2.txt") + 1); 2196 CU_ASSERT(rc == 0); 2197 2198 length = 5432; 2199 rc = spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 2200 CU_ASSERT(rc == 0); 2201 2202 spdk_blob_close(blob, blob_op_complete, NULL); 2203 blob = NULL; 2204 g_blob = NULL; 2205 g_blobid = SPDK_BLOBID_INVALID; 2206 2207 /* Mark second blob as invalid */ 2208 page_num = _spdk_bs_blobid_to_page(blobid2); 2209 2210 index = DEV_BUFFER_BLOCKLEN * (g_bs->md_start + page_num); 2211 page = (struct spdk_blob_md_page *)&g_dev_buffer[index]; 2212 page->sequence_num = 1; 2213 page->crc = _spdk_blob_md_page_calc_crc(page); 2214 2215 free_clusters = spdk_bs_free_cluster_count(g_bs); 2216 2217 /* Dirty shutdown */ 2218 _spdk_bs_free(g_bs); 2219 /* reload the blobstore */ 2220 dev = init_dev(); 2221 spdk_bs_opts_init(&opts); 2222 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2223 CU_ASSERT(g_bserrno == 0); 2224 2225 spdk_bs_open_blob(g_bs, blobid2, blob_op_with_handle_complete, NULL); 2226 CU_ASSERT(g_bserrno != 0); 2227 CU_ASSERT(g_blob == NULL); 2228 2229 spdk_bs_open_blob(g_bs, blobid3, blob_op_with_handle_complete, NULL); 2230 CU_ASSERT(g_bserrno == 0); 2231 CU_ASSERT(g_blob != NULL); 2232 blob = g_blob; 2233 2234 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(g_bs)); 2235 2236 spdk_blob_close(blob, blob_op_complete, NULL); 2237 blob = NULL; 2238 g_blob = NULL; 2239 g_blobid = SPDK_BLOBID_INVALID; 2240 2241 spdk_bs_unload(g_bs, bs_op_complete, NULL); 2242 CU_ASSERT(g_bserrno == 0); 2243 g_bs = NULL; 2244 } 2245 2246 static void 2247 blob_flags(void) 2248 { 2249 struct spdk_bs_dev *dev; 2250 spdk_blob_id blobid_invalid, blobid_data_ro, blobid_md_ro; 2251 struct spdk_blob *blob_invalid, *blob_data_ro, *blob_md_ro; 2252 struct spdk_bs_opts opts; 2253 int rc; 2254 2255 dev = init_dev(); 2256 spdk_bs_opts_init(&opts); 2257 2258 /* Initialize a new blob store */ 2259 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 2260 CU_ASSERT(g_bserrno == 0); 2261 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2262 2263 /* Create three blobs - one each for testing invalid, data_ro and md_ro flags. */ 2264 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL); 2265 CU_ASSERT(g_bserrno == 0); 2266 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2267 blobid_invalid = g_blobid; 2268 2269 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL); 2270 CU_ASSERT(g_bserrno == 0); 2271 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2272 blobid_data_ro = g_blobid; 2273 2274 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL); 2275 CU_ASSERT(g_bserrno == 0); 2276 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2277 blobid_md_ro = g_blobid; 2278 2279 spdk_bs_open_blob(g_bs, blobid_invalid, blob_op_with_handle_complete, NULL); 2280 CU_ASSERT(g_bserrno == 0); 2281 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2282 blob_invalid = g_blob; 2283 2284 spdk_bs_open_blob(g_bs, blobid_data_ro, blob_op_with_handle_complete, NULL); 2285 CU_ASSERT(g_bserrno == 0); 2286 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2287 blob_data_ro = g_blob; 2288 2289 spdk_bs_open_blob(g_bs, blobid_md_ro, blob_op_with_handle_complete, NULL); 2290 CU_ASSERT(g_bserrno == 0); 2291 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2292 blob_md_ro = g_blob; 2293 2294 /* Change the size of blob_data_ro to check if flags are serialized 2295 * when blob has non zero number of extents */ 2296 rc = spdk_blob_resize(blob_data_ro, 10); 2297 CU_ASSERT(rc == 0); 2298 2299 /* Set the xattr to check if flags are serialized 2300 * when blob has non zero number of xattrs */ 2301 rc = spdk_blob_set_xattr(blob_md_ro, "name", "log.txt", strlen("log.txt") + 1); 2302 CU_ASSERT(rc == 0); 2303 2304 __blob_to_data(blob_invalid)->invalid_flags = (1ULL << 63); 2305 __blob_to_data(blob_invalid)->state = SPDK_BLOB_STATE_DIRTY; 2306 __blob_to_data(blob_data_ro)->data_ro_flags = (1ULL << 62); 2307 __blob_to_data(blob_data_ro)->state = SPDK_BLOB_STATE_DIRTY; 2308 __blob_to_data(blob_md_ro)->md_ro_flags = (1ULL << 61); 2309 __blob_to_data(blob_md_ro)->state = SPDK_BLOB_STATE_DIRTY; 2310 2311 g_bserrno = -1; 2312 spdk_blob_sync_md(blob_invalid, blob_op_complete, NULL); 2313 CU_ASSERT(g_bserrno == 0); 2314 g_bserrno = -1; 2315 spdk_blob_sync_md(blob_data_ro, blob_op_complete, NULL); 2316 CU_ASSERT(g_bserrno == 0); 2317 g_bserrno = -1; 2318 spdk_blob_sync_md(blob_md_ro, blob_op_complete, NULL); 2319 CU_ASSERT(g_bserrno == 0); 2320 2321 g_bserrno = -1; 2322 spdk_blob_close(blob_invalid, blob_op_complete, NULL); 2323 CU_ASSERT(g_bserrno == 0); 2324 blob_invalid = NULL; 2325 g_bserrno = -1; 2326 spdk_blob_close(blob_data_ro, blob_op_complete, NULL); 2327 CU_ASSERT(g_bserrno == 0); 2328 blob_data_ro = NULL; 2329 g_bserrno = -1; 2330 spdk_blob_close(blob_md_ro, blob_op_complete, NULL); 2331 CU_ASSERT(g_bserrno == 0); 2332 blob_md_ro = NULL; 2333 2334 g_blob = NULL; 2335 g_blobid = SPDK_BLOBID_INVALID; 2336 2337 /* Unload the blob store */ 2338 spdk_bs_unload(g_bs, bs_op_complete, NULL); 2339 CU_ASSERT(g_bserrno == 0); 2340 g_bs = NULL; 2341 2342 /* Load an existing blob store */ 2343 dev = init_dev(); 2344 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2345 CU_ASSERT(g_bserrno == 0); 2346 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2347 2348 g_blob = NULL; 2349 g_bserrno = 0; 2350 spdk_bs_open_blob(g_bs, blobid_invalid, blob_op_with_handle_complete, NULL); 2351 CU_ASSERT(g_bserrno != 0); 2352 CU_ASSERT(g_blob == NULL); 2353 2354 g_blob = NULL; 2355 g_bserrno = -1; 2356 spdk_bs_open_blob(g_bs, blobid_data_ro, blob_op_with_handle_complete, NULL); 2357 CU_ASSERT(g_bserrno == 0); 2358 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2359 blob_data_ro = g_blob; 2360 /* If an unknown data_ro flag was found, the blob should be marked both data and md read-only. */ 2361 CU_ASSERT(__blob_to_data(blob_data_ro)->data_ro == true); 2362 CU_ASSERT(__blob_to_data(blob_data_ro)->md_ro == true); 2363 CU_ASSERT(spdk_blob_get_num_clusters(blob_data_ro) == 10); 2364 2365 g_blob = NULL; 2366 g_bserrno = -1; 2367 spdk_bs_open_blob(g_bs, blobid_md_ro, blob_op_with_handle_complete, NULL); 2368 CU_ASSERT(g_bserrno == 0); 2369 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2370 blob_md_ro = g_blob; 2371 CU_ASSERT(__blob_to_data(blob_md_ro)->data_ro == false); 2372 CU_ASSERT(__blob_to_data(blob_md_ro)->md_ro == true); 2373 2374 g_bserrno = -1; 2375 spdk_blob_sync_md(blob_md_ro, blob_op_complete, NULL); 2376 CU_ASSERT(g_bserrno == 0); 2377 2378 spdk_blob_close(blob_data_ro, blob_op_complete, NULL); 2379 CU_ASSERT(g_bserrno == 0); 2380 spdk_blob_close(blob_md_ro, blob_op_complete, NULL); 2381 CU_ASSERT(g_bserrno == 0); 2382 2383 spdk_bs_unload(g_bs, bs_op_complete, NULL); 2384 CU_ASSERT(g_bserrno == 0); 2385 } 2386 2387 static void 2388 bs_version(void) 2389 { 2390 struct spdk_bs_super_block *super; 2391 struct spdk_bs_dev *dev; 2392 struct spdk_bs_opts opts; 2393 spdk_blob_id blobid; 2394 2395 dev = init_dev(); 2396 spdk_bs_opts_init(&opts); 2397 2398 /* Initialize a new blob store */ 2399 spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); 2400 CU_ASSERT(g_bserrno == 0); 2401 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2402 2403 /* Unload the blob store */ 2404 spdk_bs_unload(g_bs, bs_op_complete, NULL); 2405 CU_ASSERT(g_bserrno == 0); 2406 g_bs = NULL; 2407 2408 /* 2409 * Change the bs version on disk. This will allow us to 2410 * test that the version does not get modified automatically 2411 * when loading and unloading the blobstore. 2412 */ 2413 super = (struct spdk_bs_super_block *)&g_dev_buffer[0]; 2414 CU_ASSERT(super->version == SPDK_BS_VERSION); 2415 CU_ASSERT(super->clean == 1); 2416 super->version = 2; 2417 /* 2418 * Version 2 metadata does not have a used blobid mask, so clear 2419 * those fields in the super block and zero the corresponding 2420 * region on "disk". We will use this to ensure blob IDs are 2421 * correctly reconstructed. 2422 */ 2423 memset(&g_dev_buffer[super->used_blobid_mask_start * SPDK_BS_PAGE_SIZE], 0, 2424 super->used_blobid_mask_len * SPDK_BS_PAGE_SIZE); 2425 super->used_blobid_mask_start = 0; 2426 super->used_blobid_mask_len = 0; 2427 super->crc = _spdk_blob_md_page_calc_crc(super); 2428 2429 /* Load an existing blob store */ 2430 dev = init_dev(); 2431 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2432 CU_ASSERT(g_bserrno == 0); 2433 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2434 CU_ASSERT(super->clean == 0); 2435 2436 /* 2437 * Create a blob - just to make sure that when we unload it 2438 * results in writing the super block (since metadata pages 2439 * were allocated. 2440 */ 2441 spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL); 2442 CU_ASSERT(g_bserrno == 0); 2443 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2444 blobid = g_blobid; 2445 2446 /* Unload the blob store */ 2447 spdk_bs_unload(g_bs, bs_op_complete, NULL); 2448 CU_ASSERT(g_bserrno == 0); 2449 g_bs = NULL; 2450 CU_ASSERT(super->version == 2); 2451 CU_ASSERT(super->used_blobid_mask_start == 0); 2452 CU_ASSERT(super->used_blobid_mask_len == 0); 2453 2454 dev = init_dev(); 2455 spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); 2456 CU_ASSERT(g_bserrno == 0); 2457 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2458 2459 g_blob = NULL; 2460 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); 2461 CU_ASSERT(g_bserrno == 0); 2462 CU_ASSERT(g_blob != NULL); 2463 2464 spdk_blob_close(g_blob, blob_op_complete, NULL); 2465 CU_ASSERT(g_bserrno == 0); 2466 2467 spdk_bs_unload(g_bs, bs_op_complete, NULL); 2468 CU_ASSERT(g_bserrno == 0); 2469 g_bs = NULL; 2470 CU_ASSERT(super->version == 2); 2471 CU_ASSERT(super->used_blobid_mask_start == 0); 2472 CU_ASSERT(super->used_blobid_mask_len == 0); 2473 } 2474 2475 static void 2476 _get_xattr_value(void *arg, const char *name, 2477 const void **value, size_t *value_len) 2478 { 2479 uint64_t i; 2480 2481 SPDK_CU_ASSERT_FATAL(value_len != NULL); 2482 SPDK_CU_ASSERT_FATAL(value != NULL); 2483 CU_ASSERT(arg == &g_ctx) 2484 2485 for (i = 0; i < sizeof(g_xattr_names); i++) { 2486 if (!strcmp(name, g_xattr_names[i])) { 2487 *value_len = strlen(g_xattr_values[i]); 2488 *value = g_xattr_values[i]; 2489 break; 2490 } 2491 } 2492 } 2493 2494 static void 2495 _get_xattr_value_null(void *arg, const char *name, 2496 const void **value, size_t *value_len) 2497 { 2498 SPDK_CU_ASSERT_FATAL(value_len != NULL); 2499 SPDK_CU_ASSERT_FATAL(value != NULL); 2500 CU_ASSERT(arg == NULL) 2501 2502 *value_len = 0; 2503 *value = NULL; 2504 } 2505 2506 static void 2507 blob_set_xattrs(void) 2508 { 2509 struct spdk_blob_store *bs; 2510 struct spdk_bs_dev *dev; 2511 struct spdk_blob *blob; 2512 struct spdk_blob_opts opts; 2513 spdk_blob_id blobid; 2514 const void *value; 2515 size_t value_len; 2516 int rc; 2517 2518 dev = init_dev(); 2519 2520 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 2521 CU_ASSERT(g_bserrno == 0); 2522 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2523 bs = g_bs; 2524 2525 /* Create blob with extra attributes */ 2526 spdk_blob_opts_init(&opts); 2527 2528 opts.xattr_names = g_xattr_names; 2529 opts.get_xattr_value = _get_xattr_value; 2530 opts.xattr_count = 3; 2531 opts.xattr_ctx = &g_ctx; 2532 2533 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 2534 CU_ASSERT(g_bserrno == 0); 2535 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2536 blobid = g_blobid; 2537 2538 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 2539 CU_ASSERT(g_bserrno == 0); 2540 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2541 blob = g_blob; 2542 2543 /* Get the xattrs */ 2544 value = NULL; 2545 2546 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[0], &value, &value_len); 2547 CU_ASSERT(rc == 0); 2548 SPDK_CU_ASSERT_FATAL(value != NULL); 2549 CU_ASSERT(value_len == strlen(g_xattr_values[0])); 2550 CU_ASSERT_NSTRING_EQUAL_FATAL(value, g_xattr_values[0], value_len); 2551 2552 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[1], &value, &value_len); 2553 CU_ASSERT(rc == 0); 2554 SPDK_CU_ASSERT_FATAL(value != NULL); 2555 CU_ASSERT(value_len == strlen(g_xattr_values[1])); 2556 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[1], value_len); 2557 2558 rc = spdk_blob_get_xattr_value(blob, g_xattr_names[2], &value, &value_len); 2559 CU_ASSERT(rc == 0); 2560 SPDK_CU_ASSERT_FATAL(value != NULL); 2561 CU_ASSERT(value_len == strlen(g_xattr_values[2])); 2562 CU_ASSERT_NSTRING_EQUAL((char *)value, g_xattr_values[2], value_len); 2563 2564 /* Try to get non existing attribute */ 2565 2566 rc = spdk_blob_get_xattr_value(blob, "foobar", &value, &value_len); 2567 CU_ASSERT(rc == -ENOENT); 2568 2569 spdk_blob_close(blob, blob_op_complete, NULL); 2570 CU_ASSERT(g_bserrno == 0); 2571 blob = NULL; 2572 g_blob = NULL; 2573 g_blobid = SPDK_BLOBID_INVALID; 2574 2575 /* NULL callback */ 2576 spdk_blob_opts_init(&opts); 2577 opts.xattr_names = g_xattr_names; 2578 opts.get_xattr_value = NULL; 2579 opts.xattr_count = 1; 2580 opts.xattr_ctx = &g_ctx; 2581 2582 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 2583 CU_ASSERT(g_bserrno == -EINVAL); 2584 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2585 2586 /* NULL values */ 2587 spdk_blob_opts_init(&opts); 2588 opts.xattr_names = g_xattr_names; 2589 opts.get_xattr_value = _get_xattr_value_null; 2590 opts.xattr_count = 1; 2591 opts.xattr_ctx = NULL; 2592 2593 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 2594 CU_ASSERT(g_bserrno == -EINVAL); 2595 2596 spdk_bs_unload(g_bs, bs_op_complete, NULL); 2597 CU_ASSERT(g_bserrno == 0); 2598 g_bs = NULL; 2599 2600 } 2601 2602 static void 2603 blob_thin_prov_alloc(void) 2604 { 2605 struct spdk_blob_store *bs; 2606 struct spdk_bs_dev *dev; 2607 struct spdk_blob *blob; 2608 struct spdk_blob_data *blob_data; 2609 struct spdk_blob_opts opts; 2610 spdk_blob_id blobid; 2611 uint64_t free_clusters; 2612 int rc; 2613 2614 dev = init_dev(); 2615 2616 spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); 2617 CU_ASSERT(g_bserrno == 0); 2618 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2619 bs = g_bs; 2620 free_clusters = spdk_bs_free_cluster_count(bs); 2621 2622 /* Set blob as thin provisioned */ 2623 spdk_blob_opts_init(&opts); 2624 opts.thin_provision = true; 2625 2626 spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL); 2627 CU_ASSERT(g_bserrno == 0); 2628 CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); 2629 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 2630 blobid = g_blobid; 2631 2632 spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); 2633 CU_ASSERT(g_bserrno == 0); 2634 SPDK_CU_ASSERT_FATAL(g_blob != NULL); 2635 blob = g_blob; 2636 blob_data = __blob_to_data(blob); 2637 2638 CU_ASSERT(blob_data->active.num_clusters == 0); 2639 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 0); 2640 2641 /* The blob started at 0 clusters. Resize it to be 5, but still unallocated. */ 2642 rc = spdk_blob_resize(blob, 5); 2643 CU_ASSERT(rc == 0); 2644 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 2645 CU_ASSERT(blob_data->active.num_clusters == 5); 2646 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 5); 2647 2648 /* Shrink the blob to 3 clusters - still unallocated */ 2649 rc = spdk_blob_resize(blob, 3); 2650 CU_ASSERT(rc == 0); 2651 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 2652 CU_ASSERT(blob_data->active.num_clusters == 3); 2653 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 3); 2654 2655 spdk_blob_sync_md(blob, blob_op_complete, NULL); 2656 CU_ASSERT(g_bserrno == 0); 2657 /* Sync must not change anything */ 2658 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 2659 CU_ASSERT(blob_data->active.num_clusters == 3); 2660 CU_ASSERT(spdk_blob_get_num_clusters(blob) == 3); 2661 2662 spdk_blob_close(blob, blob_op_complete, NULL); 2663 CU_ASSERT(g_bserrno == 0); 2664 2665 /* Unload the blob store */ 2666 spdk_bs_unload(g_bs, bs_op_complete, NULL); 2667 CU_ASSERT(g_bserrno == 0); 2668 g_bs = NULL; 2669 g_blob = NULL; 2670 g_blobid = 0; 2671 2672 /* Load an existing blob store */ 2673 dev = init_dev(); 2674 spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL); 2675 CU_ASSERT(g_bserrno == 0); 2676 SPDK_CU_ASSERT_FATAL(g_bs != NULL); 2677 2678 bs = g_bs; 2679 2680 spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); 2681 CU_ASSERT(g_bserrno == 0); 2682 CU_ASSERT(g_blob != NULL); 2683 blob = g_blob; 2684 blob_data = __blob_to_data(blob); 2685 2686 /* Check that clusters allocation and size is still the same */ 2687 CU_ASSERT(free_clusters == spdk_bs_free_cluster_count(bs)); 2688 CU_ASSERT(blob_data->active.num_clusters == 3); 2689 2690 spdk_blob_close(blob, blob_op_complete, NULL); 2691 CU_ASSERT(g_bserrno == 0); 2692 2693 spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL); 2694 CU_ASSERT(g_bserrno == 0); 2695 2696 spdk_bs_unload(g_bs, bs_op_complete, NULL); 2697 CU_ASSERT(g_bserrno == 0); 2698 g_bs = NULL; 2699 } 2700 2701 int main(int argc, char **argv) 2702 { 2703 CU_pSuite suite = NULL; 2704 unsigned int num_failures; 2705 2706 if (CU_initialize_registry() != CUE_SUCCESS) { 2707 return CU_get_error(); 2708 } 2709 2710 suite = CU_add_suite("blob", NULL, NULL); 2711 if (suite == NULL) { 2712 CU_cleanup_registry(); 2713 return CU_get_error(); 2714 } 2715 2716 if ( 2717 CU_add_test(suite, "blob_init", blob_init) == NULL || 2718 CU_add_test(suite, "blob_open", blob_open) == NULL || 2719 CU_add_test(suite, "blob_create", blob_create) == NULL || 2720 CU_add_test(suite, "blob_thin_provision", blob_thin_provision) == NULL || 2721 CU_add_test(suite, "blob_delete", blob_delete) == NULL || 2722 CU_add_test(suite, "blob_resize", blob_resize) == NULL || 2723 CU_add_test(suite, "blob_read_only", blob_read_only) == NULL || 2724 CU_add_test(suite, "channel_ops", channel_ops) == NULL || 2725 CU_add_test(suite, "blob_super", blob_super) == NULL || 2726 CU_add_test(suite, "blob_write", blob_write) == NULL || 2727 CU_add_test(suite, "blob_read", blob_read) == NULL || 2728 CU_add_test(suite, "blob_rw_verify", blob_rw_verify) == NULL || 2729 CU_add_test(suite, "blob_rw_verify_iov", blob_rw_verify_iov) == NULL || 2730 CU_add_test(suite, "blob_rw_verify_iov_nomem", blob_rw_verify_iov_nomem) == NULL || 2731 CU_add_test(suite, "blob_rw_iov_read_only", blob_rw_iov_read_only) == NULL || 2732 CU_add_test(suite, "blob_iter", blob_iter) == NULL || 2733 CU_add_test(suite, "blob_xattr", blob_xattr) == NULL || 2734 CU_add_test(suite, "bs_load", bs_load) == NULL || 2735 CU_add_test(suite, "bs_unload", bs_unload) == NULL || 2736 CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL || 2737 CU_add_test(suite, "bs_usable_clusters", bs_usable_clusters) == NULL || 2738 CU_add_test(suite, "bs_resize_md", bs_resize_md) == NULL || 2739 CU_add_test(suite, "bs_destroy", bs_destroy) == NULL || 2740 CU_add_test(suite, "bs_type", bs_type) == NULL || 2741 CU_add_test(suite, "bs_super_block", bs_super_block) == NULL || 2742 CU_add_test(suite, "blob_serialize", blob_serialize) == NULL || 2743 CU_add_test(suite, "blob_crc", blob_crc) == NULL || 2744 CU_add_test(suite, "super_block_crc", super_block_crc) == NULL || 2745 CU_add_test(suite, "blob_dirty_shutdown", blob_dirty_shutdown) == NULL || 2746 CU_add_test(suite, "blob_flags", blob_flags) == NULL || 2747 CU_add_test(suite, "bs_version", bs_version) == NULL || 2748 CU_add_test(suite, "blob_set_xattrs", blob_set_xattrs) == NULL || 2749 CU_add_test(suite, "blob_thin_prov_alloc", blob_thin_prov_alloc) == NULL 2750 ) { 2751 CU_cleanup_registry(); 2752 return CU_get_error(); 2753 } 2754 2755 g_dev_buffer = calloc(1, DEV_BUFFER_SIZE); 2756 spdk_allocate_thread(_bs_send_msg, NULL, NULL, NULL, "thread0"); 2757 CU_basic_set_mode(CU_BRM_VERBOSE); 2758 CU_basic_run_tests(); 2759 num_failures = CU_get_number_of_failures(); 2760 CU_cleanup_registry(); 2761 spdk_free_thread(); 2762 free(g_dev_buffer); 2763 return num_failures; 2764 } 2765