4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 #include "spdk/stdinc.h"
36 #include "spdk_cunit.h"
37 #include "spdk/blob.h"
38 #include "spdk/string.h"
39 #include "spdk_internal/thread.h"
41 #include "common/lib/ut_multithread.c"
42 #include "../bs_dev_common.c"
43 #include "blob/blobstore.c"
44 #include "blob/request.c"
45 #include "blob/zeroes.c"
46 #include "blob/blob_bs_dev.c"
48 struct spdk_blob_store
*g_bs
;
49 spdk_blob_id g_blobid
;
50 struct spdk_blob
*g_blob
;
52 struct spdk_xattr_names
*g_names
;
54 char *g_xattr_names
[] = {"first", "second", "third"};
55 char *g_xattr_values
[] = {"one", "two", "three"};
56 uint64_t g_ctx
= 1729;
58 struct spdk_bs_super_block_ver1
{
62 uint32_t clean
; /* If there was a clean shutdown, this is 1. */
63 spdk_blob_id super_blob
;
65 uint32_t cluster_size
; /* In bytes */
67 uint32_t used_page_mask_start
; /* Offset from beginning of disk, in pages */
68 uint32_t used_page_mask_len
; /* Count, in pages */
70 uint32_t used_cluster_mask_start
; /* Offset from beginning of disk, in pages */
71 uint32_t used_cluster_mask_len
; /* Count, in pages */
73 uint32_t md_start
; /* Offset from beginning of disk, in pages */
74 uint32_t md_len
; /* Count, in pages */
76 uint8_t reserved
[4036];
78 } __attribute__((packed
));
79 SPDK_STATIC_ASSERT(sizeof(struct spdk_bs_super_block_ver1
) == 0x1000, "Invalid super block size");
82 _get_xattr_value(void *arg
, const char *name
,
83 const void **value
, size_t *value_len
)
87 SPDK_CU_ASSERT_FATAL(value_len
!= NULL
);
88 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
89 CU_ASSERT(arg
== &g_ctx
)
91 for (i
= 0; i
< sizeof(g_xattr_names
); i
++) {
92 if (!strcmp(name
, g_xattr_names
[i
])) {
93 *value_len
= strlen(g_xattr_values
[i
]);
94 *value
= g_xattr_values
[i
];
101 _get_xattr_value_null(void *arg
, const char *name
,
102 const void **value
, size_t *value_len
)
104 SPDK_CU_ASSERT_FATAL(value_len
!= NULL
);
105 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
106 CU_ASSERT(arg
== NULL
)
113 _get_snapshots_count(struct spdk_blob_store
*bs
)
115 struct spdk_blob_list
*snapshot
= NULL
;
118 TAILQ_FOREACH(snapshot
, &bs
->snapshots
, link
) {
126 bs_op_complete(void *cb_arg
, int bserrno
)
132 bs_op_with_handle_complete(void *cb_arg
, struct spdk_blob_store
*bs
,
140 blob_op_complete(void *cb_arg
, int bserrno
)
146 blob_op_with_id_complete(void *cb_arg
, spdk_blob_id blobid
, int bserrno
)
153 blob_op_with_handle_complete(void *cb_arg
, struct spdk_blob
*blb
, int bserrno
)
162 struct spdk_bs_dev
*dev
;
166 /* should fail for an unsupported blocklen */
168 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
170 CU_ASSERT(g_bserrno
== -EINVAL
);
173 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
175 CU_ASSERT(g_bserrno
== 0);
176 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
178 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
180 CU_ASSERT(g_bserrno
== 0);
187 struct spdk_blob_store
*bs
;
188 struct spdk_bs_dev
*dev
;
193 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
195 CU_ASSERT(g_bserrno
== 0);
196 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
199 /* Get the super blob without having set one */
200 spdk_bs_get_super(bs
, blob_op_with_id_complete
, NULL
);
202 CU_ASSERT(g_bserrno
== -ENOENT
);
203 CU_ASSERT(g_blobid
== SPDK_BLOBID_INVALID
);
206 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
208 CU_ASSERT(g_bserrno
== 0);
209 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
212 /* Set the blob as the super blob */
213 spdk_bs_set_super(bs
, blobid
, blob_op_complete
, NULL
);
215 CU_ASSERT(g_bserrno
== 0);
217 /* Get the super blob */
218 spdk_bs_get_super(bs
, blob_op_with_id_complete
, NULL
);
220 CU_ASSERT(g_bserrno
== 0);
221 CU_ASSERT(blobid
== g_blobid
);
223 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
225 CU_ASSERT(g_bserrno
== 0);
232 struct spdk_blob_store
*bs
;
233 struct spdk_bs_dev
*dev
;
234 struct spdk_blob
*blob
;
235 spdk_blob_id blobid
, blobid2
;
239 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
241 CU_ASSERT(g_bserrno
== 0);
242 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
245 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
247 CU_ASSERT(g_bserrno
== 0);
248 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
251 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
253 CU_ASSERT(g_bserrno
== 0);
254 CU_ASSERT(g_blob
!= NULL
);
257 blobid2
= spdk_blob_get_id(blob
);
258 CU_ASSERT(blobid
== blobid2
);
260 /* Try to open file again. It should return success. */
261 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
263 CU_ASSERT(g_bserrno
== 0);
264 CU_ASSERT(blob
== g_blob
);
266 spdk_blob_close(blob
, blob_op_complete
, NULL
);
268 CU_ASSERT(g_bserrno
== 0);
271 * Close the file a second time, releasing the second reference. This
275 spdk_blob_close(blob
, blob_op_complete
, NULL
);
277 CU_ASSERT(g_bserrno
== 0);
280 * Try to open file again. It should succeed. This tests the case
281 * where the file is opened, closed, then re-opened again.
283 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
285 CU_ASSERT(g_bserrno
== 0);
286 CU_ASSERT(g_blob
!= NULL
);
289 spdk_blob_close(blob
, blob_op_complete
, NULL
);
291 CU_ASSERT(g_bserrno
== 0);
293 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
295 CU_ASSERT(g_bserrno
== 0);
302 struct spdk_blob_store
*bs
;
303 struct spdk_bs_dev
*dev
;
304 struct spdk_blob
*blob
;
305 struct spdk_blob_opts opts
;
310 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
312 CU_ASSERT(g_bserrno
== 0);
313 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
316 /* Create blob with 10 clusters */
318 spdk_blob_opts_init(&opts
);
319 opts
.num_clusters
= 10;
321 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
323 CU_ASSERT(g_bserrno
== 0);
324 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
327 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
329 CU_ASSERT(g_bserrno
== 0);
330 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
332 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 10)
334 spdk_blob_close(blob
, blob_op_complete
, NULL
);
336 CU_ASSERT(g_bserrno
== 0);
338 /* Create blob with 0 clusters */
340 spdk_blob_opts_init(&opts
);
341 opts
.num_clusters
= 0;
343 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
345 CU_ASSERT(g_bserrno
== 0);
346 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
349 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
351 CU_ASSERT(g_bserrno
== 0);
352 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
354 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 0)
356 spdk_blob_close(blob
, blob_op_complete
, NULL
);
358 CU_ASSERT(g_bserrno
== 0);
360 /* Create blob with default options (opts == NULL) */
362 spdk_bs_create_blob_ext(bs
, NULL
, blob_op_with_id_complete
, NULL
);
364 CU_ASSERT(g_bserrno
== 0);
365 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
368 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
370 CU_ASSERT(g_bserrno
== 0);
371 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
373 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 0)
375 spdk_blob_close(blob
, blob_op_complete
, NULL
);
377 CU_ASSERT(g_bserrno
== 0);
379 /* Try to create blob with size larger than blobstore */
381 spdk_blob_opts_init(&opts
);
382 opts
.num_clusters
= bs
->total_clusters
+ 1;
384 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
386 CU_ASSERT(g_bserrno
== -ENOSPC
);
388 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
390 CU_ASSERT(g_bserrno
== 0);
396 blob_create_internal(void)
398 struct spdk_blob_store
*bs
;
399 struct spdk_bs_dev
*dev
;
400 struct spdk_blob
*blob
;
401 struct spdk_blob_opts opts
;
402 struct spdk_blob_xattr_opts internal_xattrs
;
410 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
412 CU_ASSERT(g_bserrno
== 0);
413 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
416 /* Create blob with custom xattrs */
418 spdk_blob_opts_init(&opts
);
419 _spdk_blob_xattrs_init(&internal_xattrs
);
420 internal_xattrs
.count
= 3;
421 internal_xattrs
.names
= g_xattr_names
;
422 internal_xattrs
.get_value
= _get_xattr_value
;
423 internal_xattrs
.ctx
= &g_ctx
;
425 _spdk_bs_create_blob(bs
, &opts
, &internal_xattrs
, blob_op_with_id_complete
, NULL
);
427 CU_ASSERT(g_bserrno
== 0);
428 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
431 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
433 CU_ASSERT(g_bserrno
== 0);
434 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
437 rc
= _spdk_blob_get_xattr_value(blob
, g_xattr_names
[0], &value
, &value_len
, true);
439 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
440 CU_ASSERT(value_len
== strlen(g_xattr_values
[0]));
441 CU_ASSERT_NSTRING_EQUAL_FATAL(value
, g_xattr_values
[0], value_len
);
443 rc
= _spdk_blob_get_xattr_value(blob
, g_xattr_names
[1], &value
, &value_len
, true);
445 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
446 CU_ASSERT(value_len
== strlen(g_xattr_values
[1]));
447 CU_ASSERT_NSTRING_EQUAL((char *)value
, g_xattr_values
[1], value_len
);
449 rc
= _spdk_blob_get_xattr_value(blob
, g_xattr_names
[2], &value
, &value_len
, true);
451 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
452 CU_ASSERT(value_len
== strlen(g_xattr_values
[2]));
453 CU_ASSERT_NSTRING_EQUAL((char *)value
, g_xattr_values
[2], value_len
);
455 rc
= spdk_blob_get_xattr_value(blob
, g_xattr_names
[0], &value
, &value_len
);
458 rc
= spdk_blob_get_xattr_value(blob
, g_xattr_names
[1], &value
, &value_len
);
461 rc
= spdk_blob_get_xattr_value(blob
, g_xattr_names
[2], &value
, &value_len
);
464 spdk_blob_close(blob
, blob_op_complete
, NULL
);
466 CU_ASSERT(g_bserrno
== 0);
468 /* Create blob with NULL internal options */
470 _spdk_bs_create_blob(bs
, NULL
, NULL
, blob_op_with_id_complete
, NULL
);
472 CU_ASSERT(g_bserrno
== 0);
473 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
476 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
478 CU_ASSERT(g_bserrno
== 0);
479 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
480 CU_ASSERT(TAILQ_FIRST(&g_blob
->xattrs_internal
) == NULL
);
484 spdk_blob_close(blob
, blob_op_complete
, NULL
);
486 CU_ASSERT(g_bserrno
== 0);
488 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
490 CU_ASSERT(g_bserrno
== 0);
496 blob_thin_provision(void)
498 struct spdk_blob_store
*bs
;
499 struct spdk_bs_dev
*dev
;
500 struct spdk_blob
*blob
;
501 struct spdk_blob_opts opts
;
502 struct spdk_bs_opts bs_opts
;
506 spdk_bs_opts_init(&bs_opts
);
507 snprintf(bs_opts
.bstype
.bstype
, sizeof(bs_opts
.bstype
.bstype
), "TESTTYPE");
509 /* Initialize a new blob store */
510 spdk_bs_init(dev
, &bs_opts
, bs_op_with_handle_complete
, NULL
);
512 CU_ASSERT(g_bserrno
== 0);
513 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
517 /* Create blob with thin provisioning enabled */
519 spdk_blob_opts_init(&opts
);
520 opts
.thin_provision
= true;
521 opts
.num_clusters
= 10;
523 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
525 CU_ASSERT(g_bserrno
== 0);
526 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
529 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
531 CU_ASSERT(g_bserrno
== 0);
532 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
534 CU_ASSERT(blob
->invalid_flags
& SPDK_BLOB_THIN_PROV
);
536 spdk_blob_close(blob
, blob_op_complete
, NULL
);
537 CU_ASSERT(g_bserrno
== 0);
539 /* Do not shut down cleanly. This makes sure that when we load again
540 * and try to recover a valid used_cluster map, that blobstore will
541 * ignore clusters with index 0 since these are unallocated clusters.
544 /* Load an existing blob store and check if invalid_flags is set */
546 snprintf(bs_opts
.bstype
.bstype
, sizeof(bs_opts
.bstype
.bstype
), "TESTTYPE");
547 spdk_bs_load(dev
, &bs_opts
, bs_op_with_handle_complete
, NULL
);
549 CU_ASSERT(g_bserrno
== 0);
550 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
554 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
556 CU_ASSERT(g_bserrno
== 0);
557 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
559 CU_ASSERT(blob
->invalid_flags
& SPDK_BLOB_THIN_PROV
);
561 spdk_blob_close(blob
, blob_op_complete
, NULL
);
563 CU_ASSERT(g_bserrno
== 0);
565 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
567 CU_ASSERT(g_bserrno
== 0);
574 struct spdk_blob_store
*bs
;
575 struct spdk_bs_dev
*dev
;
576 struct spdk_blob
*blob
;
577 struct spdk_blob
*snapshot
, *snapshot2
;
578 struct spdk_blob_bs_dev
*blob_bs_dev
;
579 struct spdk_blob_opts opts
;
580 struct spdk_blob_xattr_opts xattrs
;
582 spdk_blob_id snapshotid
;
583 spdk_blob_id snapshotid2
;
590 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
592 CU_ASSERT(g_bserrno
== 0);
593 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
596 /* Create blob with 10 clusters */
597 spdk_blob_opts_init(&opts
);
598 opts
.num_clusters
= 10;
600 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
602 CU_ASSERT(g_bserrno
== 0);
603 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
606 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
608 CU_ASSERT(g_bserrno
== 0);
609 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
611 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 10)
613 /* Create snapshot from blob */
614 CU_ASSERT_EQUAL(_get_snapshots_count(bs
), 0);
615 spdk_bs_create_snapshot(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
617 CU_ASSERT(g_bserrno
== 0);
618 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
619 CU_ASSERT_EQUAL(_get_snapshots_count(bs
), 1);
620 snapshotid
= g_blobid
;
622 spdk_bs_open_blob(bs
, snapshotid
, blob_op_with_handle_complete
, NULL
);
624 CU_ASSERT(g_bserrno
== 0);
625 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
627 CU_ASSERT(snapshot
->data_ro
== true)
628 CU_ASSERT(snapshot
->md_ro
== true)
629 CU_ASSERT(spdk_blob_get_num_clusters(snapshot
) == 10)
631 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 10)
632 CU_ASSERT(blob
->invalid_flags
& SPDK_BLOB_THIN_PROV
);
633 CU_ASSERT(spdk_mem_all_zero(blob
->active
.clusters
,
634 blob
->active
.num_clusters
* sizeof(blob
->active
.clusters
[0])));
636 /* Try to create snapshot from clone with xattrs */
637 xattrs
.names
= g_xattr_names
;
638 xattrs
.get_value
= _get_xattr_value
;
641 spdk_bs_create_snapshot(bs
, blobid
, &xattrs
, blob_op_with_id_complete
, NULL
);
643 CU_ASSERT(g_bserrno
== 0);
644 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
645 CU_ASSERT_EQUAL(_get_snapshots_count(bs
), 2);
646 snapshotid2
= g_blobid
;
648 spdk_bs_open_blob(bs
, snapshotid2
, blob_op_with_handle_complete
, NULL
);
649 CU_ASSERT(g_bserrno
== 0);
650 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
652 CU_ASSERT(snapshot2
->data_ro
== true)
653 CU_ASSERT(snapshot2
->md_ro
== true)
654 CU_ASSERT(spdk_blob_get_num_clusters(snapshot2
) == 10)
656 /* Confirm that blob is backed by snapshot2 and snapshot2 is backed by snapshot */
657 CU_ASSERT(snapshot
->back_bs_dev
== NULL
);
658 SPDK_CU_ASSERT_FATAL(blob
->back_bs_dev
!= NULL
);
659 SPDK_CU_ASSERT_FATAL(snapshot2
->back_bs_dev
!= NULL
);
661 blob_bs_dev
= (struct spdk_blob_bs_dev
*)blob
->back_bs_dev
;
662 CU_ASSERT(blob_bs_dev
->blob
== snapshot2
);
664 blob_bs_dev
= (struct spdk_blob_bs_dev
*)snapshot2
->back_bs_dev
;
665 CU_ASSERT(blob_bs_dev
->blob
== snapshot
);
667 rc
= spdk_blob_get_xattr_value(snapshot2
, g_xattr_names
[0], &value
, &value_len
);
669 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
670 CU_ASSERT(value_len
== strlen(g_xattr_values
[0]));
671 CU_ASSERT_NSTRING_EQUAL_FATAL(value
, g_xattr_values
[0], value_len
);
673 rc
= spdk_blob_get_xattr_value(snapshot2
, g_xattr_names
[1], &value
, &value_len
);
675 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
676 CU_ASSERT(value_len
== strlen(g_xattr_values
[1]));
677 CU_ASSERT_NSTRING_EQUAL((char *)value
, g_xattr_values
[1], value_len
);
679 rc
= spdk_blob_get_xattr_value(snapshot2
, g_xattr_names
[2], &value
, &value_len
);
681 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
682 CU_ASSERT(value_len
== strlen(g_xattr_values
[2]));
683 CU_ASSERT_NSTRING_EQUAL((char *)value
, g_xattr_values
[2], value_len
);
685 /* Try to create snapshot from snapshot */
686 spdk_bs_create_snapshot(bs
, snapshotid
, NULL
, blob_op_with_id_complete
, NULL
);
688 CU_ASSERT(g_bserrno
== -EINVAL
);
689 CU_ASSERT(g_blobid
== SPDK_BLOBID_INVALID
);
690 CU_ASSERT_EQUAL(_get_snapshots_count(bs
), 2);
692 spdk_blob_close(blob
, blob_op_complete
, NULL
);
694 CU_ASSERT(g_bserrno
== 0);
696 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
697 CU_ASSERT(g_bserrno
== 0);
698 CU_ASSERT_EQUAL(_get_snapshots_count(bs
), 2);
700 spdk_blob_close(snapshot2
, blob_op_complete
, NULL
);
702 CU_ASSERT(g_bserrno
== 0);
704 spdk_bs_delete_blob(bs
, snapshotid2
, blob_op_complete
, NULL
);
706 CU_ASSERT(g_bserrno
== 0);
707 CU_ASSERT_EQUAL(_get_snapshots_count(bs
), 1);
709 spdk_blob_close(snapshot
, blob_op_complete
, NULL
);
711 CU_ASSERT(g_bserrno
== 0);
713 spdk_bs_delete_blob(bs
, snapshotid
, blob_op_complete
, NULL
);
715 CU_ASSERT(g_bserrno
== 0);
716 CU_ASSERT_EQUAL(_get_snapshots_count(bs
), 0);
718 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
720 CU_ASSERT(g_bserrno
== 0);
725 blob_snapshot_freeze_io(void)
727 struct spdk_thread
*thread
;
728 struct spdk_io_channel
*channel
;
729 struct spdk_bs_channel
*bs_channel
;
730 struct spdk_blob_store
*bs
;
731 struct spdk_bs_dev
*dev
;
732 struct spdk_blob
*blob
;
733 struct spdk_blob_opts opts
;
735 uint32_t num_of_pages
= 10;
736 uint8_t payload_read
[num_of_pages
* SPDK_BS_PAGE_SIZE
];
737 uint8_t payload_write
[num_of_pages
* SPDK_BS_PAGE_SIZE
];
738 uint8_t payload_zero
[num_of_pages
* SPDK_BS_PAGE_SIZE
];
740 memset(payload_write
, 0xE5, sizeof(payload_write
));
741 memset(payload_read
, 0x00, sizeof(payload_read
));
742 memset(payload_zero
, 0x00, sizeof(payload_zero
));
745 memset(g_dev_buffer
, 0, DEV_BUFFER_SIZE
);
747 /* Test freeze I/O during snapshot */
749 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
751 CU_ASSERT(g_bserrno
== 0);
752 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
755 channel
= spdk_bs_alloc_io_channel(bs
);
756 bs_channel
= spdk_io_channel_get_ctx(channel
);
758 /* Create blob with 10 clusters */
759 spdk_blob_opts_init(&opts
);
760 opts
.num_clusters
= 10;
761 opts
.thin_provision
= false;
763 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
765 CU_ASSERT(g_bserrno
== 0);
766 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
769 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
771 CU_ASSERT(g_bserrno
== 0);
772 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
774 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 10);
776 spdk_bs_create_snapshot(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
778 /* This is implementation specific.
779 * Flag 'frozen_io' is set in _spdk_bs_snapshot_freeze_cpl callback.
780 * Four async I/O operations happen before that. */
781 thread
= spdk_get_thread();
782 spdk_thread_poll(thread
, 1, 0);
783 spdk_thread_poll(thread
, 1, 0);
784 spdk_thread_poll(thread
, 1, 0);
786 CU_ASSERT(TAILQ_EMPTY(&bs_channel
->queued_io
));
788 /* Blob I/O should be frozen here */
789 CU_ASSERT(blob
->frozen_refcnt
== 1);
791 /* Write to the blob */
792 spdk_blob_io_write(blob
, channel
, payload_write
, 0, num_of_pages
, blob_op_complete
, NULL
);
794 /* Verify that I/O is queued */
795 CU_ASSERT(!TAILQ_EMPTY(&bs_channel
->queued_io
));
796 /* Verify that payload is not written to disk */
797 CU_ASSERT(memcmp(payload_zero
, &g_dev_buffer
[blob
->active
.clusters
[0]*SPDK_BS_PAGE_SIZE
],
798 SPDK_BS_PAGE_SIZE
) == 0);
800 /* Finish all operations including spdk_bs_create_snapshot */
803 /* Verify snapshot */
804 CU_ASSERT(g_bserrno
== 0);
805 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
807 /* Verify that blob has unset frozen_io */
808 CU_ASSERT(blob
->frozen_refcnt
== 0);
810 /* Verify that postponed I/O completed successfully by comparing payload */
811 spdk_blob_io_read(blob
, channel
, payload_read
, 0, num_of_pages
, blob_op_complete
, NULL
);
813 CU_ASSERT(g_bserrno
== 0);
814 CU_ASSERT(memcmp(payload_write
, payload_read
, num_of_pages
* SPDK_BS_PAGE_SIZE
) == 0);
816 spdk_blob_close(blob
, blob_op_complete
, NULL
);
818 CU_ASSERT(g_bserrno
== 0);
820 spdk_bs_free_io_channel(channel
);
823 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
825 CU_ASSERT(g_bserrno
== 0);
832 struct spdk_blob_store
*bs
;
833 struct spdk_bs_dev
*dev
;
834 struct spdk_blob_opts opts
;
835 struct spdk_blob
*blob
, *snapshot
, *clone
;
836 spdk_blob_id blobid
, cloneid
, snapshotid
;
837 struct spdk_blob_xattr_opts xattrs
;
844 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
846 CU_ASSERT(g_bserrno
== 0);
847 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
850 /* Create blob with 10 clusters */
852 spdk_blob_opts_init(&opts
);
853 opts
.num_clusters
= 10;
855 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
857 CU_ASSERT(g_bserrno
== 0);
858 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
861 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
863 CU_ASSERT(g_bserrno
== 0);
864 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
866 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 10)
868 /* Create snapshot */
869 spdk_bs_create_snapshot(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
871 CU_ASSERT(g_bserrno
== 0);
872 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
873 snapshotid
= g_blobid
;
875 spdk_bs_open_blob(bs
, snapshotid
, blob_op_with_handle_complete
, NULL
);
877 CU_ASSERT(g_bserrno
== 0);
878 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
880 CU_ASSERT(snapshot
->data_ro
== true)
881 CU_ASSERT(snapshot
->md_ro
== true)
882 CU_ASSERT(spdk_blob_get_num_clusters(snapshot
) == 10);
884 spdk_blob_close(snapshot
, blob_op_complete
, NULL
);
886 CU_ASSERT(g_bserrno
== 0);
888 /* Create clone from snapshot with xattrs */
889 xattrs
.names
= g_xattr_names
;
890 xattrs
.get_value
= _get_xattr_value
;
894 spdk_bs_create_clone(bs
, snapshotid
, &xattrs
, blob_op_with_id_complete
, NULL
);
896 CU_ASSERT(g_bserrno
== 0);
897 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
900 spdk_bs_open_blob(bs
, cloneid
, blob_op_with_handle_complete
, NULL
);
902 CU_ASSERT(g_bserrno
== 0);
903 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
905 CU_ASSERT(clone
->data_ro
== false)
906 CU_ASSERT(clone
->md_ro
== false)
907 CU_ASSERT(spdk_blob_get_num_clusters(clone
) == 10);
909 rc
= spdk_blob_get_xattr_value(clone
, g_xattr_names
[0], &value
, &value_len
);
911 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
912 CU_ASSERT(value_len
== strlen(g_xattr_values
[0]));
913 CU_ASSERT_NSTRING_EQUAL_FATAL(value
, g_xattr_values
[0], value_len
);
915 rc
= spdk_blob_get_xattr_value(clone
, g_xattr_names
[1], &value
, &value_len
);
917 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
918 CU_ASSERT(value_len
== strlen(g_xattr_values
[1]));
919 CU_ASSERT_NSTRING_EQUAL((char *)value
, g_xattr_values
[1], value_len
);
921 rc
= spdk_blob_get_xattr_value(clone
, g_xattr_names
[2], &value
, &value_len
);
923 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
924 CU_ASSERT(value_len
== strlen(g_xattr_values
[2]));
925 CU_ASSERT_NSTRING_EQUAL((char *)value
, g_xattr_values
[2], value_len
);
928 spdk_blob_close(clone
, blob_op_complete
, NULL
);
930 CU_ASSERT(g_bserrno
== 0);
932 /* Try to create clone from not read only blob */
933 spdk_bs_create_clone(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
935 CU_ASSERT(g_bserrno
== -EINVAL
);
936 CU_ASSERT(g_blobid
== SPDK_BLOBID_INVALID
);
938 /* Mark blob as read only */
939 spdk_blob_set_read_only(blob
);
940 spdk_blob_sync_md(blob
, blob_op_complete
, NULL
);
942 CU_ASSERT(g_bserrno
== 0);
944 /* Create clone from read only blob */
945 spdk_bs_create_clone(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
947 CU_ASSERT(g_bserrno
== 0);
948 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
951 spdk_bs_open_blob(bs
, cloneid
, blob_op_with_handle_complete
, NULL
);
953 CU_ASSERT(g_bserrno
== 0);
954 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
956 CU_ASSERT(clone
->data_ro
== false)
957 CU_ASSERT(clone
->md_ro
== false)
958 CU_ASSERT(spdk_blob_get_num_clusters(clone
) == 10);
960 spdk_blob_close(clone
, blob_op_complete
, NULL
);
962 CU_ASSERT(g_bserrno
== 0);
964 spdk_blob_close(blob
, blob_op_complete
, NULL
);
966 CU_ASSERT(g_bserrno
== 0);
968 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
970 CU_ASSERT(g_bserrno
== 0);
976 _blob_inflate(bool decouple_parent
)
978 struct spdk_blob_store
*bs
;
979 struct spdk_bs_dev
*dev
;
980 struct spdk_blob_opts opts
;
981 struct spdk_blob
*blob
, *snapshot
;
982 spdk_blob_id blobid
, snapshotid
;
983 struct spdk_io_channel
*channel
;
984 uint64_t free_clusters
;
988 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
990 CU_ASSERT(g_bserrno
== 0);
991 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
994 channel
= spdk_bs_alloc_io_channel(bs
);
995 SPDK_CU_ASSERT_FATAL(channel
!= NULL
);
997 /* Create blob with 10 clusters */
999 spdk_blob_opts_init(&opts
);
1000 opts
.num_clusters
= 10;
1001 opts
.thin_provision
= true;
1003 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
1005 CU_ASSERT(g_bserrno
== 0);
1006 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
1009 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
1011 CU_ASSERT(g_bserrno
== 0);
1012 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
1015 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 10)
1016 CU_ASSERT(spdk_blob_is_thin_provisioned(blob
) == true);
1018 /* 1) Blob with no parent */
1019 if (decouple_parent
) {
1020 /* Decouple parent of blob with no parent (should fail) */
1021 spdk_bs_blob_decouple_parent(bs
, channel
, blobid
, blob_op_complete
, NULL
);
1023 CU_ASSERT(g_bserrno
!= 0);
1025 /* Inflate of thin blob with no parent should made it thick */
1026 spdk_bs_inflate_blob(bs
, channel
, blobid
, blob_op_complete
, NULL
);
1028 CU_ASSERT(g_bserrno
== 0);
1029 CU_ASSERT(spdk_blob_is_thin_provisioned(blob
) == false);
1032 spdk_bs_create_snapshot(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
1034 CU_ASSERT(g_bserrno
== 0);
1035 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
1036 snapshotid
= g_blobid
;
1038 CU_ASSERT(spdk_blob_is_thin_provisioned(blob
) == true);
1039 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 10)
1041 spdk_bs_open_blob(bs
, snapshotid
, blob_op_with_handle_complete
, NULL
);
1043 CU_ASSERT(g_bserrno
== 0);
1044 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
1046 CU_ASSERT(snapshot
->data_ro
== true)
1047 CU_ASSERT(snapshot
->md_ro
== true)
1048 CU_ASSERT(spdk_blob_get_num_clusters(snapshot
) == 10);
1050 spdk_blob_close(snapshot
, blob_op_complete
, NULL
);
1052 CU_ASSERT(g_bserrno
== 0);
1054 free_clusters
= spdk_bs_free_cluster_count(bs
);
1056 /* 2) Blob with parent */
1057 if (!decouple_parent
) {
1058 /* Do full blob inflation */
1059 spdk_bs_inflate_blob(bs
, channel
, blobid
, blob_op_complete
, NULL
);
1061 CU_ASSERT(g_bserrno
== 0);
1062 /* all 10 clusters should be allocated */
1063 CU_ASSERT(spdk_bs_free_cluster_count(bs
) == free_clusters
- 10);
1065 /* Decouple parent of blob */
1066 spdk_bs_blob_decouple_parent(bs
, channel
, blobid
, blob_op_complete
, NULL
);
1068 CU_ASSERT(g_bserrno
== 0);
1069 /* when only parent is removed, none of the clusters should be allocated */
1070 CU_ASSERT(spdk_bs_free_cluster_count(bs
) == free_clusters
);
1073 /* Now, it should be possible to delete snapshot */
1074 spdk_bs_delete_blob(bs
, snapshotid
, blob_op_complete
, NULL
);
1076 CU_ASSERT(g_bserrno
== 0);
1078 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 10)
1079 CU_ASSERT(spdk_blob_is_thin_provisioned(blob
) == decouple_parent
);
1081 spdk_blob_close(blob
, blob_op_complete
, NULL
);
1083 CU_ASSERT(g_bserrno
== 0);
1085 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
1087 CU_ASSERT(g_bserrno
== 0);
1090 spdk_bs_free_io_channel(channel
);
1097 _blob_inflate(false);
1098 _blob_inflate(true);
1104 struct spdk_blob_store
*bs
;
1105 struct spdk_bs_dev
*dev
;
1106 spdk_blob_id blobid
;
1110 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
1112 CU_ASSERT(g_bserrno
== 0);
1113 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
1116 /* Create a blob and then delete it. */
1117 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
1119 CU_ASSERT(g_bserrno
== 0);
1120 CU_ASSERT(g_blobid
> 0);
1123 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
1125 CU_ASSERT(g_bserrno
== 0);
1127 /* Try to open the blob */
1128 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
1130 CU_ASSERT(g_bserrno
== -ENOENT
);
1132 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
1134 CU_ASSERT(g_bserrno
== 0);
1141 struct spdk_blob_store
*bs
;
1142 struct spdk_bs_dev
*dev
;
1143 struct spdk_blob
*blob
;
1144 spdk_blob_id blobid
;
1145 uint64_t free_clusters
;
1149 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
1151 CU_ASSERT(g_bserrno
== 0);
1152 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
1154 free_clusters
= spdk_bs_free_cluster_count(bs
);
1156 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
1158 CU_ASSERT(g_bserrno
== 0);
1159 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
1160 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
1163 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
1165 CU_ASSERT(g_bserrno
== 0);
1166 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
1169 /* Confirm that resize fails if blob is marked read-only. */
1171 spdk_blob_resize(blob
, 5, blob_op_complete
, NULL
);
1173 CU_ASSERT(g_bserrno
== -EPERM
);
1174 blob
->md_ro
= false;
1176 /* The blob started at 0 clusters. Resize it to be 5. */
1177 spdk_blob_resize(blob
, 5, blob_op_complete
, NULL
);
1179 CU_ASSERT(g_bserrno
== 0);
1180 CU_ASSERT((free_clusters
- 5) == spdk_bs_free_cluster_count(bs
));
1182 /* Shrink the blob to 3 clusters. This will not actually release
1183 * the old clusters until the blob is synced.
1185 spdk_blob_resize(blob
, 3, blob_op_complete
, NULL
);
1187 CU_ASSERT(g_bserrno
== 0);
1188 /* Verify there are still 5 clusters in use */
1189 CU_ASSERT((free_clusters
- 5) == spdk_bs_free_cluster_count(bs
));
1191 spdk_blob_sync_md(blob
, blob_op_complete
, NULL
);
1193 CU_ASSERT(g_bserrno
== 0);
1194 /* Now there are only 3 clusters in use */
1195 CU_ASSERT((free_clusters
- 3) == spdk_bs_free_cluster_count(bs
));
1197 /* Resize the blob to be 10 clusters. Growth takes effect immediately. */
1198 spdk_blob_resize(blob
, 10, blob_op_complete
, NULL
);
1200 CU_ASSERT(g_bserrno
== 0);
1201 CU_ASSERT((free_clusters
- 10) == spdk_bs_free_cluster_count(bs
));
1203 /* Try to resize the blob to size larger than blobstore. */
1204 spdk_blob_resize(blob
, bs
->total_clusters
+ 1, blob_op_complete
, NULL
);
1206 CU_ASSERT(g_bserrno
== -ENOSPC
);
1208 spdk_blob_close(blob
, blob_op_complete
, NULL
);
1210 CU_ASSERT(g_bserrno
== 0);
1212 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
1214 CU_ASSERT(g_bserrno
== 0);
1216 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
1218 CU_ASSERT(g_bserrno
== 0);
1223 blob_read_only(void)
1225 struct spdk_blob_store
*bs
;
1226 struct spdk_bs_dev
*dev
;
1227 struct spdk_blob
*blob
;
1228 struct spdk_bs_opts opts
;
1229 spdk_blob_id blobid
;
1233 spdk_bs_opts_init(&opts
);
1234 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
1236 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
1238 CU_ASSERT(g_bserrno
== 0);
1239 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
1242 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
1244 CU_ASSERT(g_bserrno
== 0);
1245 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
1248 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
1250 CU_ASSERT(g_bserrno
== 0);
1251 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
1254 rc
= spdk_blob_set_read_only(blob
);
1257 CU_ASSERT(blob
->data_ro
== false);
1258 CU_ASSERT(blob
->md_ro
== false);
1260 spdk_blob_sync_md(blob
, bs_op_complete
, NULL
);
1263 CU_ASSERT(blob
->data_ro
== true);
1264 CU_ASSERT(blob
->md_ro
== true);
1265 CU_ASSERT(blob
->data_ro_flags
& SPDK_BLOB_READ_ONLY
);
1267 spdk_blob_close(blob
, blob_op_complete
, NULL
);
1269 CU_ASSERT(g_bserrno
== 0);
1271 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
1273 CU_ASSERT(g_bserrno
== 0);
1274 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
1277 CU_ASSERT(blob
->data_ro
== true);
1278 CU_ASSERT(blob
->md_ro
== true);
1279 CU_ASSERT(blob
->data_ro_flags
& SPDK_BLOB_READ_ONLY
);
1281 spdk_blob_close(blob
, blob_op_complete
, NULL
);
1283 CU_ASSERT(g_bserrno
== 0);
1285 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
1287 CU_ASSERT(g_bserrno
== 0);
1292 /* Load an existing blob store */
1294 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
1295 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
1297 CU_ASSERT(g_bserrno
== 0);
1298 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
1300 spdk_bs_open_blob(g_bs
, blobid
, blob_op_with_handle_complete
, NULL
);
1302 CU_ASSERT(g_bserrno
== 0);
1303 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
1306 CU_ASSERT(blob
->data_ro
== true);
1307 CU_ASSERT(blob
->md_ro
== true);
1308 CU_ASSERT(blob
->data_ro_flags
& SPDK_BLOB_READ_ONLY
);
1310 spdk_blob_close(blob
, blob_op_complete
, NULL
);
1312 CU_ASSERT(g_bserrno
== 0);
1314 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
1316 CU_ASSERT(g_bserrno
== 0);
1323 struct spdk_blob_store
*bs
;
1324 struct spdk_bs_dev
*dev
;
1325 struct spdk_io_channel
*channel
;
1329 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
1331 CU_ASSERT(g_bserrno
== 0);
1332 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
1335 channel
= spdk_bs_alloc_io_channel(bs
);
1336 CU_ASSERT(channel
!= NULL
);
1338 spdk_bs_free_io_channel(channel
);
1341 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
1343 CU_ASSERT(g_bserrno
== 0);
1350 struct spdk_blob_store
*bs
;
1351 struct spdk_bs_dev
*dev
;
1352 struct spdk_blob
*blob
;
1353 struct spdk_io_channel
*channel
;
1354 spdk_blob_id blobid
;
1355 uint64_t pages_per_cluster
;
1356 uint8_t payload
[10 * 4096];
1360 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
1362 CU_ASSERT(g_bserrno
== 0);
1363 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
1366 pages_per_cluster
= spdk_bs_get_cluster_size(bs
) / spdk_bs_get_page_size(bs
);
1368 channel
= spdk_bs_alloc_io_channel(bs
);
1369 CU_ASSERT(channel
!= NULL
);
1371 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
1373 CU_ASSERT(g_bserrno
== 0);
1374 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
1377 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
1379 CU_ASSERT(g_bserrno
== 0);
1380 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
1383 /* Write to a blob with 0 size */
1384 spdk_blob_io_write(blob
, channel
, payload
, 0, 1, blob_op_complete
, NULL
);
1386 CU_ASSERT(g_bserrno
== -EINVAL
);
1388 /* Resize the blob */
1389 spdk_blob_resize(blob
, 5, blob_op_complete
, NULL
);
1391 CU_ASSERT(g_bserrno
== 0);
1393 /* Confirm that write fails if blob is marked read-only. */
1394 blob
->data_ro
= true;
1395 spdk_blob_io_write(blob
, channel
, payload
, 0, 1, blob_op_complete
, NULL
);
1397 CU_ASSERT(g_bserrno
== -EPERM
);
1398 blob
->data_ro
= false;
1400 /* Write to the blob */
1401 spdk_blob_io_write(blob
, channel
, payload
, 0, 1, blob_op_complete
, NULL
);
1403 CU_ASSERT(g_bserrno
== 0);
1405 /* Write starting beyond the end */
1406 spdk_blob_io_write(blob
, channel
, payload
, 5 * pages_per_cluster
, 1, blob_op_complete
,
1409 CU_ASSERT(g_bserrno
== -EINVAL
);
1411 /* Write starting at a valid location but going off the end */
1412 spdk_blob_io_write(blob
, channel
, payload
, 4 * pages_per_cluster
, pages_per_cluster
+ 1,
1413 blob_op_complete
, NULL
);
1415 CU_ASSERT(g_bserrno
== -EINVAL
);
1417 spdk_blob_close(blob
, blob_op_complete
, NULL
);
1419 CU_ASSERT(g_bserrno
== 0);
1421 spdk_bs_free_io_channel(channel
);
1424 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
1426 CU_ASSERT(g_bserrno
== 0);
1433 struct spdk_blob_store
*bs
;
1434 struct spdk_bs_dev
*dev
;
1435 struct spdk_blob
*blob
;
1436 struct spdk_io_channel
*channel
;
1437 spdk_blob_id blobid
;
1438 uint64_t pages_per_cluster
;
1439 uint8_t payload
[10 * 4096];
1443 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
1445 CU_ASSERT(g_bserrno
== 0);
1446 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
1449 pages_per_cluster
= spdk_bs_get_cluster_size(bs
) / spdk_bs_get_page_size(bs
);
1451 channel
= spdk_bs_alloc_io_channel(bs
);
1452 CU_ASSERT(channel
!= NULL
);
1454 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
1456 CU_ASSERT(g_bserrno
== 0);
1457 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
1460 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
1462 CU_ASSERT(g_bserrno
== 0);
1463 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
1466 /* Read from a blob with 0 size */
1467 spdk_blob_io_read(blob
, channel
, payload
, 0, 1, blob_op_complete
, NULL
);
1469 CU_ASSERT(g_bserrno
== -EINVAL
);
1471 /* Resize the blob */
1472 spdk_blob_resize(blob
, 5, blob_op_complete
, NULL
);
1474 CU_ASSERT(g_bserrno
== 0);
1476 /* Confirm that read passes if blob is marked read-only. */
1477 blob
->data_ro
= true;
1478 spdk_blob_io_read(blob
, channel
, payload
, 0, 1, blob_op_complete
, NULL
);
1480 CU_ASSERT(g_bserrno
== 0);
1481 blob
->data_ro
= false;
1483 /* Read from the blob */
1484 spdk_blob_io_read(blob
, channel
, payload
, 0, 1, blob_op_complete
, NULL
);
1486 CU_ASSERT(g_bserrno
== 0);
1488 /* Read starting beyond the end */
1489 spdk_blob_io_read(blob
, channel
, payload
, 5 * pages_per_cluster
, 1, blob_op_complete
,
1492 CU_ASSERT(g_bserrno
== -EINVAL
);
1494 /* Read starting at a valid location but going off the end */
1495 spdk_blob_io_read(blob
, channel
, payload
, 4 * pages_per_cluster
, pages_per_cluster
+ 1,
1496 blob_op_complete
, NULL
);
1498 CU_ASSERT(g_bserrno
== -EINVAL
);
1500 spdk_blob_close(blob
, blob_op_complete
, NULL
);
1502 CU_ASSERT(g_bserrno
== 0);
1504 spdk_bs_free_io_channel(channel
);
1507 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
1509 CU_ASSERT(g_bserrno
== 0);
1514 blob_rw_verify(void)
1516 struct spdk_blob_store
*bs
;
1517 struct spdk_bs_dev
*dev
;
1518 struct spdk_blob
*blob
;
1519 struct spdk_io_channel
*channel
;
1520 spdk_blob_id blobid
;
1521 uint8_t payload_read
[10 * 4096];
1522 uint8_t payload_write
[10 * 4096];
1526 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
1528 CU_ASSERT(g_bserrno
== 0);
1529 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
1532 channel
= spdk_bs_alloc_io_channel(bs
);
1533 CU_ASSERT(channel
!= NULL
);
1535 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
1537 CU_ASSERT(g_bserrno
== 0);
1538 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
1541 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
1543 CU_ASSERT(g_bserrno
== 0);
1544 CU_ASSERT(g_blob
!= NULL
);
1547 spdk_blob_resize(blob
, 32, blob_op_complete
, NULL
);
1549 CU_ASSERT(g_bserrno
== 0);
1551 memset(payload_write
, 0xE5, sizeof(payload_write
));
1552 spdk_blob_io_write(blob
, channel
, payload_write
, 4, 10, blob_op_complete
, NULL
);
1554 CU_ASSERT(g_bserrno
== 0);
1556 memset(payload_read
, 0x00, sizeof(payload_read
));
1557 spdk_blob_io_read(blob
, channel
, payload_read
, 4, 10, blob_op_complete
, NULL
);
1559 CU_ASSERT(g_bserrno
== 0);
1560 CU_ASSERT(memcmp(payload_write
, payload_read
, 4 * 4096) == 0);
1562 spdk_blob_close(blob
, blob_op_complete
, NULL
);
1564 CU_ASSERT(g_bserrno
== 0);
1566 spdk_bs_free_io_channel(channel
);
1569 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
1571 CU_ASSERT(g_bserrno
== 0);
1576 blob_rw_verify_iov(void)
1578 struct spdk_blob_store
*bs
;
1579 struct spdk_bs_dev
*dev
;
1580 struct spdk_blob
*blob
;
1581 struct spdk_io_channel
*channel
;
1582 spdk_blob_id blobid
;
1583 uint8_t payload_read
[10 * 4096];
1584 uint8_t payload_write
[10 * 4096];
1585 struct iovec iov_read
[3];
1586 struct iovec iov_write
[3];
1590 memset(g_dev_buffer
, 0, DEV_BUFFER_SIZE
);
1592 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
1594 CU_ASSERT(g_bserrno
== 0);
1595 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
1598 channel
= spdk_bs_alloc_io_channel(bs
);
1599 CU_ASSERT(channel
!= NULL
);
1601 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
1603 CU_ASSERT(g_bserrno
== 0);
1604 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
1607 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
1609 CU_ASSERT(g_bserrno
== 0);
1610 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
1613 spdk_blob_resize(blob
, 2, blob_op_complete
, NULL
);
1615 CU_ASSERT(g_bserrno
== 0);
1618 * Manually adjust the offset of the blob's second cluster. This allows
1619 * us to make sure that the readv/write code correctly accounts for I/O
1620 * that cross cluster boundaries. Start by asserting that the allocated
1621 * clusters are where we expect before modifying the second cluster.
1623 CU_ASSERT(blob
->active
.clusters
[0] == 1 * 256);
1624 CU_ASSERT(blob
->active
.clusters
[1] == 2 * 256);
1625 blob
->active
.clusters
[1] = 3 * 256;
1627 memset(payload_write
, 0xE5, sizeof(payload_write
));
1628 iov_write
[0].iov_base
= payload_write
;
1629 iov_write
[0].iov_len
= 1 * 4096;
1630 iov_write
[1].iov_base
= payload_write
+ 1 * 4096;
1631 iov_write
[1].iov_len
= 5 * 4096;
1632 iov_write
[2].iov_base
= payload_write
+ 6 * 4096;
1633 iov_write
[2].iov_len
= 4 * 4096;
1635 * Choose a page offset just before the cluster boundary. The first 6 pages of payload
1636 * will get written to the first cluster, the last 4 to the second cluster.
1638 spdk_blob_io_writev(blob
, channel
, iov_write
, 3, 250, 10, blob_op_complete
, NULL
);
1640 CU_ASSERT(g_bserrno
== 0);
1642 memset(payload_read
, 0xAA, sizeof(payload_read
));
1643 iov_read
[0].iov_base
= payload_read
;
1644 iov_read
[0].iov_len
= 3 * 4096;
1645 iov_read
[1].iov_base
= payload_read
+ 3 * 4096;
1646 iov_read
[1].iov_len
= 4 * 4096;
1647 iov_read
[2].iov_base
= payload_read
+ 7 * 4096;
1648 iov_read
[2].iov_len
= 3 * 4096;
1649 spdk_blob_io_readv(blob
, channel
, iov_read
, 3, 250, 10, blob_op_complete
, NULL
);
1651 CU_ASSERT(g_bserrno
== 0);
1652 CU_ASSERT(memcmp(payload_write
, payload_read
, 10 * 4096) == 0);
1654 buf
= calloc(1, 256 * 4096);
1655 SPDK_CU_ASSERT_FATAL(buf
!= NULL
);
1656 /* Check that cluster 2 on "disk" was not modified. */
1657 CU_ASSERT(memcmp(buf
, &g_dev_buffer
[512 * 4096], 256 * 4096) == 0);
1660 spdk_blob_close(blob
, blob_op_complete
, NULL
);
1662 CU_ASSERT(g_bserrno
== 0);
1664 spdk_bs_free_io_channel(channel
);
1667 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
1669 CU_ASSERT(g_bserrno
== 0);
1674 bs_channel_get_req_count(struct spdk_io_channel
*_channel
)
1676 struct spdk_bs_channel
*channel
= spdk_io_channel_get_ctx(_channel
);
1677 struct spdk_bs_request_set
*set
;
1680 TAILQ_FOREACH(set
, &channel
->reqs
, link
) {
1688 blob_rw_verify_iov_nomem(void)
1690 struct spdk_blob_store
*bs
;
1691 struct spdk_bs_dev
*dev
;
1692 struct spdk_blob
*blob
;
1693 struct spdk_io_channel
*channel
;
1694 spdk_blob_id blobid
;
1695 uint8_t payload_write
[10 * 4096];
1696 struct iovec iov_write
[3];
1700 memset(g_dev_buffer
, 0, DEV_BUFFER_SIZE
);
1702 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
1704 CU_ASSERT(g_bserrno
== 0);
1705 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
1708 channel
= spdk_bs_alloc_io_channel(bs
);
1709 CU_ASSERT(channel
!= NULL
);
1711 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
1713 CU_ASSERT(g_bserrno
== 0);
1714 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
1717 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
1719 CU_ASSERT(g_bserrno
== 0);
1720 CU_ASSERT(g_blob
!= NULL
);
1723 spdk_blob_resize(blob
, 2, blob_op_complete
, NULL
);
1725 CU_ASSERT(g_bserrno
== 0);
1728 * Choose a page offset just before the cluster boundary. The first 6 pages of payload
1729 * will get written to the first cluster, the last 4 to the second cluster.
1731 iov_write
[0].iov_base
= payload_write
;
1732 iov_write
[0].iov_len
= 1 * 4096;
1733 iov_write
[1].iov_base
= payload_write
+ 1 * 4096;
1734 iov_write
[1].iov_len
= 5 * 4096;
1735 iov_write
[2].iov_base
= payload_write
+ 6 * 4096;
1736 iov_write
[2].iov_len
= 4 * 4096;
1737 MOCK_SET(calloc
, NULL
);
1738 req_count
= bs_channel_get_req_count(channel
);
1739 spdk_blob_io_writev(blob
, channel
, iov_write
, 3, 250, 10, blob_op_complete
, NULL
);
1741 CU_ASSERT(g_bserrno
= -ENOMEM
);
1742 CU_ASSERT(req_count
== bs_channel_get_req_count(channel
));
1745 spdk_blob_close(blob
, blob_op_complete
, NULL
);
1747 CU_ASSERT(g_bserrno
== 0);
1749 spdk_bs_free_io_channel(channel
);
1752 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
1754 CU_ASSERT(g_bserrno
== 0);
1759 blob_rw_iov_read_only(void)
1761 struct spdk_blob_store
*bs
;
1762 struct spdk_bs_dev
*dev
;
1763 struct spdk_blob
*blob
;
1764 struct spdk_io_channel
*channel
;
1765 spdk_blob_id blobid
;
1766 uint8_t payload_read
[4096];
1767 uint8_t payload_write
[4096];
1768 struct iovec iov_read
;
1769 struct iovec iov_write
;
1772 memset(g_dev_buffer
, 0, DEV_BUFFER_SIZE
);
1774 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
1776 CU_ASSERT(g_bserrno
== 0);
1777 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
1780 channel
= spdk_bs_alloc_io_channel(bs
);
1781 CU_ASSERT(channel
!= NULL
);
1783 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
);
1789 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
1791 CU_ASSERT(g_bserrno
== 0);
1792 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
1795 spdk_blob_resize(blob
, 2, blob_op_complete
, NULL
);
1797 CU_ASSERT(g_bserrno
== 0);
1799 /* Verify that writev failed if read_only flag is set. */
1800 blob
->data_ro
= true;
1801 iov_write
.iov_base
= payload_write
;
1802 iov_write
.iov_len
= sizeof(payload_write
);
1803 spdk_blob_io_writev(blob
, channel
, &iov_write
, 1, 0, 1, blob_op_complete
, NULL
);
1805 CU_ASSERT(g_bserrno
== -EPERM
);
1807 /* Verify that reads pass if data_ro flag is set. */
1808 iov_read
.iov_base
= payload_read
;
1809 iov_read
.iov_len
= sizeof(payload_read
);
1810 spdk_blob_io_readv(blob
, channel
, &iov_read
, 1, 0, 1, blob_op_complete
, NULL
);
1812 CU_ASSERT(g_bserrno
== 0);
1814 spdk_blob_close(blob
, blob_op_complete
, NULL
);
1816 CU_ASSERT(g_bserrno
== 0);
1818 spdk_bs_free_io_channel(channel
);
1821 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
1823 CU_ASSERT(g_bserrno
== 0);
1828 _blob_io_read_no_split(struct spdk_blob
*blob
, struct spdk_io_channel
*channel
,
1829 uint8_t *payload
, uint64_t offset
, uint64_t length
,
1830 spdk_blob_op_complete cb_fn
, void *cb_arg
)
1834 uint64_t page_size
= spdk_bs_get_page_size(blob
->bs
);
1836 /* To be sure that operation is NOT splitted, read one page at the time */
1838 for (i
= 0; i
< length
; i
++) {
1839 spdk_blob_io_read(blob
, channel
, buf
, i
+ offset
, 1, blob_op_complete
, NULL
);
1841 if (g_bserrno
!= 0) {
1842 /* Pass the error code up */
1848 cb_fn(cb_arg
, g_bserrno
);
1852 _blob_io_write_no_split(struct spdk_blob
*blob
, struct spdk_io_channel
*channel
,
1853 uint8_t *payload
, uint64_t offset
, uint64_t length
,
1854 spdk_blob_op_complete cb_fn
, void *cb_arg
)
1858 uint64_t page_size
= spdk_bs_get_page_size(blob
->bs
);
1860 /* To be sure that operation is NOT splitted, write one page at the time */
1862 for (i
= 0; i
< length
; i
++) {
1863 spdk_blob_io_write(blob
, channel
, buf
, i
+ offset
, 1, blob_op_complete
, NULL
);
1865 if (g_bserrno
!= 0) {
1866 /* Pass the error code up */
1872 cb_fn(cb_arg
, g_bserrno
);
1876 blob_operation_split_rw(void)
1878 struct spdk_blob_store
*bs
;
1879 struct spdk_bs_dev
*dev
;
1880 struct spdk_blob
*blob
;
1881 struct spdk_io_channel
*channel
;
1882 struct spdk_blob_opts opts
;
1883 spdk_blob_id blobid
;
1884 uint64_t cluster_size
;
1886 uint64_t payload_size
;
1887 uint8_t *payload_read
;
1888 uint8_t *payload_write
;
1889 uint8_t *payload_pattern
;
1892 uint64_t pages_per_cluster
;
1893 uint64_t pages_per_payload
;
1899 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
1901 CU_ASSERT(g_bserrno
== 0);
1902 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
1905 cluster_size
= spdk_bs_get_cluster_size(bs
);
1906 page_size
= spdk_bs_get_page_size(bs
);
1907 pages_per_cluster
= cluster_size
/ page_size
;
1908 pages_per_payload
= pages_per_cluster
* 5;
1909 payload_size
= cluster_size
* 5;
1911 payload_read
= malloc(payload_size
);
1912 SPDK_CU_ASSERT_FATAL(payload_read
!= NULL
);
1914 payload_write
= malloc(payload_size
);
1915 SPDK_CU_ASSERT_FATAL(payload_write
!= NULL
);
1917 payload_pattern
= malloc(payload_size
);
1918 SPDK_CU_ASSERT_FATAL(payload_pattern
!= NULL
);
1920 /* Prepare random pattern to write */
1921 memset(payload_pattern
, 0xFF, payload_size
);
1922 for (i
= 0; i
< pages_per_payload
; i
++) {
1923 *((uint64_t *)(payload_pattern
+ page_size
* i
)) = (i
+ 1);
1926 channel
= spdk_bs_alloc_io_channel(bs
);
1927 SPDK_CU_ASSERT_FATAL(channel
!= NULL
);
1930 spdk_blob_opts_init(&opts
);
1931 opts
.thin_provision
= false;
1932 opts
.num_clusters
= 5;
1934 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
1936 CU_ASSERT(g_bserrno
== 0);
1937 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
1940 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
1942 CU_ASSERT(g_bserrno
== 0);
1943 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
1946 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 5);
1948 /* Initial read should return zeroed payload */
1949 memset(payload_read
, 0xFF, payload_size
);
1950 spdk_blob_io_read(blob
, channel
, payload_read
, 0, pages_per_payload
, blob_op_complete
, NULL
);
1952 CU_ASSERT(g_bserrno
== 0);
1953 CU_ASSERT(spdk_mem_all_zero(payload_read
, payload_size
));
1955 /* Fill whole blob except last page */
1956 spdk_blob_io_write(blob
, channel
, payload_pattern
, 0, pages_per_payload
- 1,
1957 blob_op_complete
, NULL
);
1959 CU_ASSERT(g_bserrno
== 0);
1961 /* Write last page with a pattern */
1962 spdk_blob_io_write(blob
, channel
, payload_pattern
, pages_per_payload
- 1, 1,
1963 blob_op_complete
, NULL
);
1965 CU_ASSERT(g_bserrno
== 0);
1967 /* Read whole blob and check consistency */
1968 memset(payload_read
, 0xFF, payload_size
);
1969 spdk_blob_io_read(blob
, channel
, payload_read
, 0, pages_per_payload
, blob_op_complete
, NULL
);
1971 CU_ASSERT(g_bserrno
== 0);
1972 CU_ASSERT(memcmp(payload_pattern
, payload_read
, payload_size
- page_size
) == 0);
1973 CU_ASSERT(memcmp(payload_pattern
, payload_read
+ payload_size
- page_size
, page_size
) == 0);
1975 /* Fill whole blob except first page */
1976 spdk_blob_io_write(blob
, channel
, payload_pattern
, 1, pages_per_payload
- 1,
1977 blob_op_complete
, NULL
);
1979 CU_ASSERT(g_bserrno
== 0);
1981 /* Write first page with a pattern */
1982 spdk_blob_io_write(blob
, channel
, payload_pattern
, 0, 1,
1983 blob_op_complete
, NULL
);
1985 CU_ASSERT(g_bserrno
== 0);
1987 /* Read whole blob and check consistency */
1988 memset(payload_read
, 0xFF, payload_size
);
1989 spdk_blob_io_read(blob
, channel
, payload_read
, 0, pages_per_payload
, blob_op_complete
, NULL
);
1991 CU_ASSERT(g_bserrno
== 0);
1992 CU_ASSERT(memcmp(payload_pattern
, payload_read
+ page_size
, payload_size
- page_size
) == 0);
1993 CU_ASSERT(memcmp(payload_pattern
, payload_read
, page_size
) == 0);
1996 /* Fill whole blob with a pattern (5 clusters) */
1999 _blob_io_write_no_split(blob
, channel
, payload_pattern
, 0, pages_per_payload
,
2000 blob_op_complete
, NULL
);
2002 CU_ASSERT(g_bserrno
== 0);
2004 memset(payload_read
, 0xFF, payload_size
);
2005 spdk_blob_io_read(blob
, channel
, payload_read
, 0, pages_per_payload
, blob_op_complete
, NULL
);
2008 CU_ASSERT(g_bserrno
== 0);
2009 CU_ASSERT(memcmp(payload_pattern
, payload_read
, payload_size
) == 0);
2011 /* 2. Write test. */
2012 spdk_blob_io_write(blob
, channel
, payload_pattern
, 0, pages_per_payload
,
2013 blob_op_complete
, NULL
);
2015 CU_ASSERT(g_bserrno
== 0);
2017 memset(payload_read
, 0xFF, payload_size
);
2018 _blob_io_read_no_split(blob
, channel
, payload_read
, 0, pages_per_payload
, blob_op_complete
, NULL
);
2020 CU_ASSERT(g_bserrno
== 0);
2021 CU_ASSERT(memcmp(payload_pattern
, payload_read
, payload_size
) == 0);
2023 spdk_blob_close(blob
, blob_op_complete
, NULL
);
2025 CU_ASSERT(g_bserrno
== 0);
2027 spdk_bs_free_io_channel(channel
);
2030 /* Unload the blob store */
2031 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2033 CU_ASSERT(g_bserrno
== 0);
2039 free(payload_write
);
2040 free(payload_pattern
);
2044 blob_operation_split_rw_iov(void)
2046 struct spdk_blob_store
*bs
;
2047 struct spdk_bs_dev
*dev
;
2048 struct spdk_blob
*blob
;
2049 struct spdk_io_channel
*channel
;
2050 struct spdk_blob_opts opts
;
2051 spdk_blob_id blobid
;
2052 uint64_t cluster_size
;
2054 uint64_t payload_size
;
2055 uint8_t *payload_read
;
2056 uint8_t *payload_write
;
2057 uint8_t *payload_pattern
;
2060 uint64_t pages_per_cluster
;
2061 uint64_t pages_per_payload
;
2063 struct iovec iov_read
[2];
2064 struct iovec iov_write
[2];
2070 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
2072 CU_ASSERT(g_bserrno
== 0);
2073 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2076 cluster_size
= spdk_bs_get_cluster_size(bs
);
2077 page_size
= spdk_bs_get_page_size(bs
);
2078 pages_per_cluster
= cluster_size
/ page_size
;
2079 pages_per_payload
= pages_per_cluster
* 5;
2080 payload_size
= cluster_size
* 5;
2082 payload_read
= malloc(payload_size
);
2083 SPDK_CU_ASSERT_FATAL(payload_read
!= NULL
);
2085 payload_write
= malloc(payload_size
);
2086 SPDK_CU_ASSERT_FATAL(payload_write
!= NULL
);
2088 payload_pattern
= malloc(payload_size
);
2089 SPDK_CU_ASSERT_FATAL(payload_pattern
!= NULL
);
2091 /* Prepare random pattern to write */
2092 for (i
= 0; i
< pages_per_payload
; i
++) {
2093 for (j
= 0; j
< page_size
/ sizeof(uint64_t); j
++) {
2096 tmp
= (uint64_t *)payload_pattern
;
2097 tmp
+= ((page_size
* i
) / sizeof(uint64_t)) + j
;
2102 channel
= spdk_bs_alloc_io_channel(bs
);
2103 SPDK_CU_ASSERT_FATAL(channel
!= NULL
);
2106 spdk_blob_opts_init(&opts
);
2107 opts
.thin_provision
= false;
2108 opts
.num_clusters
= 5;
2110 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
2112 CU_ASSERT(g_bserrno
== 0);
2113 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
2116 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
2118 CU_ASSERT(g_bserrno
== 0);
2119 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
2122 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 5);
2124 /* Initial read should return zeroes payload */
2125 memset(payload_read
, 0xFF, payload_size
);
2126 iov_read
[0].iov_base
= payload_read
;
2127 iov_read
[0].iov_len
= cluster_size
* 3;
2128 iov_read
[1].iov_base
= payload_read
+ cluster_size
* 3;
2129 iov_read
[1].iov_len
= cluster_size
* 2;
2130 spdk_blob_io_readv(blob
, channel
, iov_read
, 2, 0, pages_per_payload
, blob_op_complete
, NULL
);
2132 CU_ASSERT(g_bserrno
== 0);
2133 CU_ASSERT(spdk_mem_all_zero(payload_read
, payload_size
));
2135 /* First of iovs fills whole blob except last page and second of iovs writes last page
2136 * with a pattern. */
2137 iov_write
[0].iov_base
= payload_pattern
;
2138 iov_write
[0].iov_len
= payload_size
- page_size
;
2139 iov_write
[1].iov_base
= payload_pattern
;
2140 iov_write
[1].iov_len
= page_size
;
2141 spdk_blob_io_writev(blob
, channel
, iov_write
, 2, 0, pages_per_payload
, blob_op_complete
, NULL
);
2143 CU_ASSERT(g_bserrno
== 0);
2145 /* Read whole blob and check consistency */
2146 memset(payload_read
, 0xFF, payload_size
);
2147 iov_read
[0].iov_base
= payload_read
;
2148 iov_read
[0].iov_len
= cluster_size
* 2;
2149 iov_read
[1].iov_base
= payload_read
+ cluster_size
* 2;
2150 iov_read
[1].iov_len
= cluster_size
* 3;
2151 spdk_blob_io_readv(blob
, channel
, iov_read
, 2, 0, pages_per_payload
, blob_op_complete
, NULL
);
2153 CU_ASSERT(g_bserrno
== 0);
2154 CU_ASSERT(memcmp(payload_pattern
, payload_read
, payload_size
- page_size
) == 0);
2155 CU_ASSERT(memcmp(payload_pattern
, payload_read
+ payload_size
- page_size
, page_size
) == 0);
2157 /* First of iovs fills only first page and second of iovs writes whole blob except
2158 * first page with a pattern. */
2159 iov_write
[0].iov_base
= payload_pattern
;
2160 iov_write
[0].iov_len
= page_size
;
2161 iov_write
[1].iov_base
= payload_pattern
;
2162 iov_write
[1].iov_len
= payload_size
- page_size
;
2163 spdk_blob_io_writev(blob
, channel
, iov_write
, 2, 0, pages_per_payload
, blob_op_complete
, NULL
);
2165 CU_ASSERT(g_bserrno
== 0);
2167 /* Read whole blob and check consistency */
2168 memset(payload_read
, 0xFF, payload_size
);
2169 iov_read
[0].iov_base
= payload_read
;
2170 iov_read
[0].iov_len
= cluster_size
* 4;
2171 iov_read
[1].iov_base
= payload_read
+ cluster_size
* 4;
2172 iov_read
[1].iov_len
= cluster_size
;
2173 spdk_blob_io_readv(blob
, channel
, iov_read
, 2, 0, pages_per_payload
, blob_op_complete
, NULL
);
2175 CU_ASSERT(g_bserrno
== 0);
2176 CU_ASSERT(memcmp(payload_pattern
, payload_read
+ page_size
, payload_size
- page_size
) == 0);
2177 CU_ASSERT(memcmp(payload_pattern
, payload_read
, page_size
) == 0);
2180 /* Fill whole blob with a pattern (5 clusters) */
2183 _blob_io_write_no_split(blob
, channel
, payload_pattern
, 0, pages_per_payload
,
2184 blob_op_complete
, NULL
);
2186 CU_ASSERT(g_bserrno
== 0);
2188 memset(payload_read
, 0xFF, payload_size
);
2189 iov_read
[0].iov_base
= payload_read
;
2190 iov_read
[0].iov_len
= cluster_size
;
2191 iov_read
[1].iov_base
= payload_read
+ cluster_size
;
2192 iov_read
[1].iov_len
= cluster_size
* 4;
2193 spdk_blob_io_readv(blob
, channel
, iov_read
, 2, 0, pages_per_payload
, blob_op_complete
, NULL
);
2195 CU_ASSERT(g_bserrno
== 0);
2196 CU_ASSERT(memcmp(payload_pattern
, payload_read
, payload_size
) == 0);
2198 /* 2. Write test. */
2199 iov_write
[0].iov_base
= payload_read
;
2200 iov_write
[0].iov_len
= cluster_size
* 2;
2201 iov_write
[1].iov_base
= payload_read
+ cluster_size
* 2;
2202 iov_write
[1].iov_len
= cluster_size
* 3;
2203 spdk_blob_io_writev(blob
, channel
, iov_write
, 2, 0, pages_per_payload
, blob_op_complete
, NULL
);
2205 CU_ASSERT(g_bserrno
== 0);
2207 memset(payload_read
, 0xFF, payload_size
);
2208 _blob_io_read_no_split(blob
, channel
, payload_read
, 0, pages_per_payload
, blob_op_complete
, NULL
);
2210 CU_ASSERT(g_bserrno
== 0);
2211 CU_ASSERT(memcmp(payload_pattern
, payload_read
, payload_size
) == 0);
2213 spdk_blob_close(blob
, blob_op_complete
, NULL
);
2214 CU_ASSERT(g_bserrno
== 0);
2216 spdk_bs_free_io_channel(channel
);
2219 /* Unload the blob store */
2220 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2222 CU_ASSERT(g_bserrno
== 0);
2228 free(payload_write
);
2229 free(payload_pattern
);
2235 struct spdk_blob_store
*bs
;
2236 struct spdk_bs_dev
*dev
;
2237 struct spdk_blob
*blob
;
2238 struct spdk_io_channel
*channel
;
2239 spdk_blob_id blobid
;
2240 struct spdk_blob_opts opts
;
2241 uint8_t payload
[4096];
2246 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
2248 CU_ASSERT(g_bserrno
== 0);
2249 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2252 channel
= spdk_bs_alloc_io_channel(bs
);
2253 CU_ASSERT(channel
!= NULL
);
2255 spdk_blob_opts_init(&opts
);
2256 opts
.num_clusters
= 10;
2258 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
2260 CU_ASSERT(g_bserrno
== 0);
2261 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
2264 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
2266 CU_ASSERT(g_bserrno
== 0);
2267 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
2270 spdk_blob_resize(blob
, 10, blob_op_complete
, NULL
);
2272 CU_ASSERT(g_bserrno
== 0);
2274 memset(payload
, 0, sizeof(payload
));
2278 * Set first byte of every cluster to 0xFF.
2279 * First cluster on device is reserved so let's start from cluster number 1
2281 for (i
= 1; i
< 11; i
++) {
2282 g_dev_buffer
[i
* SPDK_BLOB_OPTS_CLUSTER_SZ
] = 0xFF;
2285 /* Confirm writes */
2286 for (i
= 0; i
< 10; i
++) {
2288 spdk_blob_io_read(blob
, channel
, &payload
, i
* SPDK_BLOB_OPTS_CLUSTER_SZ
/ 4096, 1,
2289 blob_op_complete
, NULL
);
2291 CU_ASSERT(g_bserrno
== 0);
2292 CU_ASSERT(payload
[0] == 0xFF);
2295 /* Mark some clusters as unallocated */
2296 blob
->active
.clusters
[1] = 0;
2297 blob
->active
.clusters
[2] = 0;
2298 blob
->active
.clusters
[3] = 0;
2299 blob
->active
.clusters
[6] = 0;
2300 blob
->active
.clusters
[8] = 0;
2302 /* Unmap clusters by resizing to 0 */
2303 spdk_blob_resize(blob
, 0, blob_op_complete
, NULL
);
2305 CU_ASSERT(g_bserrno
== 0);
2307 spdk_blob_sync_md(blob
, blob_op_complete
, NULL
);
2309 CU_ASSERT(g_bserrno
== 0);
2311 /* Confirm that only 'allocated' clusters were unmapped */
2312 for (i
= 1; i
< 11; i
++) {
2319 CU_ASSERT(g_dev_buffer
[i
* SPDK_BLOB_OPTS_CLUSTER_SZ
] == 0xFF);
2322 CU_ASSERT(g_dev_buffer
[i
* SPDK_BLOB_OPTS_CLUSTER_SZ
] == 0);
2327 spdk_blob_close(blob
, blob_op_complete
, NULL
);
2329 CU_ASSERT(g_bserrno
== 0);
2331 spdk_bs_free_io_channel(channel
);
2334 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2336 CU_ASSERT(g_bserrno
== 0);
2344 struct spdk_blob_store
*bs
;
2345 struct spdk_bs_dev
*dev
;
2346 struct spdk_blob
*blob
;
2347 spdk_blob_id blobid
;
2351 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
2353 CU_ASSERT(g_bserrno
== 0);
2354 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2357 spdk_bs_iter_first(bs
, blob_op_with_handle_complete
, NULL
);
2359 CU_ASSERT(g_blob
== NULL
);
2360 CU_ASSERT(g_bserrno
== -ENOENT
);
2362 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
2364 CU_ASSERT(g_bserrno
== 0);
2365 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
2368 spdk_bs_iter_first(bs
, blob_op_with_handle_complete
, NULL
);
2370 CU_ASSERT(g_blob
!= NULL
);
2371 CU_ASSERT(g_bserrno
== 0);
2373 CU_ASSERT(spdk_blob_get_id(blob
) == blobid
);
2375 spdk_bs_iter_next(bs
, blob
, blob_op_with_handle_complete
, NULL
);
2377 CU_ASSERT(g_blob
== NULL
);
2378 CU_ASSERT(g_bserrno
== -ENOENT
);
2380 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2382 CU_ASSERT(g_bserrno
== 0);
2389 struct spdk_blob_store
*bs
;
2390 struct spdk_bs_dev
*dev
;
2391 struct spdk_blob
*blob
;
2392 spdk_blob_id blobid
;
2395 const char *name1
, *name2
;
2398 struct spdk_xattr_names
*names
;
2402 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
2404 CU_ASSERT(g_bserrno
== 0);
2405 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2408 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
2410 CU_ASSERT(g_bserrno
== 0);
2411 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
2414 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
2416 CU_ASSERT(g_bserrno
== 0);
2417 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
2420 /* Test that set_xattr fails if md_ro flag is set. */
2422 rc
= spdk_blob_set_xattr(blob
, "name", "log.txt", strlen("log.txt") + 1);
2423 CU_ASSERT(rc
== -EPERM
);
2425 blob
->md_ro
= false;
2426 rc
= spdk_blob_set_xattr(blob
, "name", "log.txt", strlen("log.txt") + 1);
2430 rc
= spdk_blob_set_xattr(blob
, "length", &length
, sizeof(length
));
2433 /* Overwrite "length" xattr. */
2435 rc
= spdk_blob_set_xattr(blob
, "length", &length
, sizeof(length
));
2438 /* get_xattr should still work even if md_ro flag is set. */
2441 rc
= spdk_blob_get_xattr_value(blob
, "length", &value
, &value_len
);
2443 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
2444 CU_ASSERT(*(uint64_t *)value
== length
);
2445 CU_ASSERT(value_len
== 8);
2446 blob
->md_ro
= false;
2448 rc
= spdk_blob_get_xattr_value(blob
, "foobar", &value
, &value_len
);
2449 CU_ASSERT(rc
== -ENOENT
);
2452 rc
= spdk_blob_get_xattr_names(blob
, &names
);
2454 SPDK_CU_ASSERT_FATAL(names
!= NULL
);
2455 CU_ASSERT(spdk_xattr_names_get_count(names
) == 2);
2456 name1
= spdk_xattr_names_get_name(names
, 0);
2457 SPDK_CU_ASSERT_FATAL(name1
!= NULL
);
2458 CU_ASSERT(!strcmp(name1
, "name") || !strcmp(name1
, "length"));
2459 name2
= spdk_xattr_names_get_name(names
, 1);
2460 SPDK_CU_ASSERT_FATAL(name2
!= NULL
);
2461 CU_ASSERT(!strcmp(name2
, "name") || !strcmp(name2
, "length"));
2462 CU_ASSERT(strcmp(name1
, name2
));
2463 spdk_xattr_names_free(names
);
2465 /* Confirm that remove_xattr fails if md_ro is set to true. */
2467 rc
= spdk_blob_remove_xattr(blob
, "name");
2468 CU_ASSERT(rc
== -EPERM
);
2470 blob
->md_ro
= false;
2471 rc
= spdk_blob_remove_xattr(blob
, "name");
2474 rc
= spdk_blob_remove_xattr(blob
, "foobar");
2475 CU_ASSERT(rc
== -ENOENT
);
2477 /* Set internal xattr */
2479 rc
= _spdk_blob_set_xattr(blob
, "internal", &length
, sizeof(length
), true);
2481 rc
= _spdk_blob_get_xattr_value(blob
, "internal", &value
, &value_len
, true);
2483 CU_ASSERT(*(uint64_t *)value
== length
);
2484 /* try to get public xattr with same name */
2485 rc
= spdk_blob_get_xattr_value(blob
, "internal", &value
, &value_len
);
2487 rc
= _spdk_blob_get_xattr_value(blob
, "internal", &value
, &value_len
, false);
2489 /* Check if SPDK_BLOB_INTERNAL_XATTR is set */
2490 CU_ASSERT((blob
->invalid_flags
& SPDK_BLOB_INTERNAL_XATTR
) ==
2491 SPDK_BLOB_INTERNAL_XATTR
)
2493 spdk_blob_close(blob
, blob_op_complete
, NULL
);
2496 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2499 /* Check if xattrs are persisted */
2502 spdk_bs_load(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
2504 CU_ASSERT(g_bserrno
== 0);
2505 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2509 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
2511 CU_ASSERT(g_bserrno
== 0);
2512 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
2515 rc
= _spdk_blob_get_xattr_value(blob
, "internal", &value
, &value_len
, true);
2517 CU_ASSERT(*(uint64_t *)value
== length
);
2519 /* try to get internal xattr trough public call */
2520 rc
= spdk_blob_get_xattr_value(blob
, "internal", &value
, &value_len
);
2523 rc
= _spdk_blob_remove_xattr(blob
, "internal", true);
2526 CU_ASSERT((blob
->invalid_flags
& SPDK_BLOB_INTERNAL_XATTR
) == 0);
2528 CU_ASSERT(g_bserrno
== 0);
2535 struct spdk_bs_dev
*dev
;
2536 spdk_blob_id blobid
;
2537 struct spdk_blob
*blob
;
2538 struct spdk_bs_super_block
*super_block
;
2543 struct spdk_bs_opts opts
;
2546 spdk_bs_opts_init(&opts
);
2547 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
2549 /* Initialize a new blob store */
2550 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
2552 CU_ASSERT(g_bserrno
== 0);
2553 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2555 /* Try to open a blobid that does not exist */
2556 spdk_bs_open_blob(g_bs
, 0, blob_op_with_handle_complete
, NULL
);
2558 CU_ASSERT(g_bserrno
== -ENOENT
);
2559 CU_ASSERT(g_blob
== NULL
);
2562 spdk_bs_create_blob(g_bs
, blob_op_with_id_complete
, NULL
);
2564 CU_ASSERT(g_bserrno
== 0);
2565 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
2568 spdk_bs_open_blob(g_bs
, blobid
, blob_op_with_handle_complete
, NULL
);
2570 CU_ASSERT(g_bserrno
== 0);
2571 CU_ASSERT(g_blob
!= NULL
);
2574 /* Try again to open valid blob but without the upper bit set */
2575 spdk_bs_open_blob(g_bs
, blobid
& 0xFFFFFFFF, blob_op_with_handle_complete
, NULL
);
2577 CU_ASSERT(g_bserrno
== -ENOENT
);
2578 CU_ASSERT(g_blob
== NULL
);
2580 /* Set some xattrs */
2581 rc
= spdk_blob_set_xattr(blob
, "name", "log.txt", strlen("log.txt") + 1);
2585 rc
= spdk_blob_set_xattr(blob
, "length", &length
, sizeof(length
));
2588 /* Resize the blob */
2589 spdk_blob_resize(blob
, 10, blob_op_complete
, NULL
);
2591 CU_ASSERT(g_bserrno
== 0);
2593 spdk_blob_close(blob
, blob_op_complete
, NULL
);
2595 CU_ASSERT(g_bserrno
== 0);
2598 g_blobid
= SPDK_BLOBID_INVALID
;
2600 /* Unload the blob store */
2601 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2603 CU_ASSERT(g_bserrno
== 0);
2608 super_block
= (struct spdk_bs_super_block
*)g_dev_buffer
;
2609 CU_ASSERT(super_block
->clean
== 1);
2611 /* Load should fail for device with an unsupported blocklen */
2613 dev
->blocklen
= SPDK_BS_PAGE_SIZE
* 2;
2614 spdk_bs_load(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
2616 CU_ASSERT(g_bserrno
== -EINVAL
);
2618 /* Load should when max_md_ops is set to zero */
2620 spdk_bs_opts_init(&opts
);
2621 opts
.max_md_ops
= 0;
2622 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
2624 CU_ASSERT(g_bserrno
== -EINVAL
);
2626 /* Load should when max_channel_ops is set to zero */
2628 spdk_bs_opts_init(&opts
);
2629 opts
.max_channel_ops
= 0;
2630 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
2632 CU_ASSERT(g_bserrno
== -EINVAL
);
2634 /* Load an existing blob store */
2636 spdk_bs_opts_init(&opts
);
2637 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
2638 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
2640 CU_ASSERT(g_bserrno
== 0);
2641 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2643 super_block
= (struct spdk_bs_super_block
*)g_dev_buffer
;
2644 CU_ASSERT(super_block
->clean
== 1);
2645 CU_ASSERT(super_block
->size
== dev
->blockcnt
* dev
->blocklen
);
2647 spdk_bs_open_blob(g_bs
, blobid
, blob_op_with_handle_complete
, NULL
);
2649 CU_ASSERT(g_bserrno
== 0);
2650 CU_ASSERT(g_blob
!= NULL
);
2653 /* Verify that blobstore is marked dirty after first metadata sync */
2654 spdk_blob_sync_md(blob
, blob_op_complete
, NULL
);
2655 CU_ASSERT(super_block
->clean
== 1);
2657 /* Get the xattrs */
2659 rc
= spdk_blob_get_xattr_value(blob
, "length", &value
, &value_len
);
2661 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
2662 CU_ASSERT(*(uint64_t *)value
== length
);
2663 CU_ASSERT(value_len
== 8);
2665 rc
= spdk_blob_get_xattr_value(blob
, "foobar", &value
, &value_len
);
2666 CU_ASSERT(rc
== -ENOENT
);
2668 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 10);
2670 spdk_blob_close(blob
, blob_op_complete
, NULL
);
2672 CU_ASSERT(g_bserrno
== 0);
2676 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2678 CU_ASSERT(g_bserrno
== 0);
2681 /* Load should fail: bdev size < saved size */
2685 spdk_bs_opts_init(&opts
);
2686 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
2687 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
2690 CU_ASSERT(g_bserrno
== -EILSEQ
);
2692 /* Load should succeed: bdev size > saved size */
2696 spdk_bs_opts_init(&opts
);
2697 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
2698 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
2701 CU_ASSERT(g_bserrno
== 0);
2702 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2706 /* Test compatibility mode */
2709 super_block
->size
= 0;
2710 super_block
->crc
= _spdk_blob_md_page_calc_crc(super_block
);
2712 spdk_bs_opts_init(&opts
);
2713 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
2714 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
2716 CU_ASSERT(g_bserrno
== 0);
2717 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2720 spdk_bs_create_blob(g_bs
, blob_op_with_id_complete
, NULL
);
2722 CU_ASSERT(g_bserrno
== 0);
2723 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
2725 /* Blobstore should update number of blocks in super_block */
2726 CU_ASSERT(super_block
->size
== dev
->blockcnt
* dev
->blocklen
);
2727 CU_ASSERT(super_block
->clean
== 0);
2729 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2731 CU_ASSERT(g_bserrno
== 0);
2732 CU_ASSERT(super_block
->clean
== 1);
2738 bs_load_pending_removal(void)
2740 struct spdk_blob_store
*bs
;
2741 struct spdk_bs_dev
*dev
;
2742 struct spdk_blob_opts opts
;
2743 struct spdk_blob
*blob
, *snapshot
;
2744 spdk_blob_id blobid
, snapshotid
;
2751 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
2753 CU_ASSERT(g_bserrno
== 0);
2754 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2758 spdk_blob_opts_init(&opts
);
2759 opts
.num_clusters
= 10;
2761 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
2763 CU_ASSERT(g_bserrno
== 0);
2764 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
2767 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
2769 CU_ASSERT(g_bserrno
== 0);
2770 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
2773 /* Create snapshot */
2774 spdk_bs_create_snapshot(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
2776 CU_ASSERT(g_bserrno
== 0);
2777 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
2778 snapshotid
= g_blobid
;
2780 spdk_bs_open_blob(bs
, snapshotid
, blob_op_with_handle_complete
, NULL
);
2782 CU_ASSERT(g_bserrno
== 0);
2783 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
2786 /* Set SNAPSHOT_PENDING_REMOVAL xattr */
2787 snapshot
->md_ro
= false;
2788 rc
= _spdk_blob_set_xattr(snapshot
, SNAPSHOT_PENDING_REMOVAL
, &blobid
, sizeof(spdk_blob_id
), true);
2790 snapshot
->md_ro
= true;
2792 spdk_blob_close(snapshot
, blob_op_complete
, NULL
);
2794 CU_ASSERT(g_bserrno
== 0);
2796 spdk_blob_close(blob
, blob_op_complete
, NULL
);
2798 CU_ASSERT(g_bserrno
== 0);
2800 /* Reload blobstore */
2801 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2803 CU_ASSERT(g_bserrno
== 0);
2807 spdk_bs_load(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
2809 CU_ASSERT(g_bserrno
== 0);
2810 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2813 /* Snapshot should not be removed as blob is still pointing to it */
2814 spdk_bs_open_blob(bs
, snapshotid
, blob_op_with_handle_complete
, NULL
);
2816 CU_ASSERT(g_bserrno
== 0);
2817 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
2820 /* SNAPSHOT_PENDING_REMOVAL xattr should be removed during load */
2821 rc
= spdk_blob_get_xattr_value(snapshot
, SNAPSHOT_PENDING_REMOVAL
, &value
, &value_len
);
2824 /* Set SNAPSHOT_PENDING_REMOVAL xattr again */
2825 snapshot
->md_ro
= false;
2826 rc
= _spdk_blob_set_xattr(snapshot
, SNAPSHOT_PENDING_REMOVAL
, &blobid
, sizeof(spdk_blob_id
), true);
2828 snapshot
->md_ro
= true;
2830 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
2832 CU_ASSERT(g_bserrno
== 0);
2833 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
2836 /* Remove parent_id from blob by removing BLOB_SNAPSHOT xattr */
2837 _spdk_blob_remove_xattr(blob
, BLOB_SNAPSHOT
, true);
2839 spdk_blob_sync_md(blob
, blob_op_complete
, NULL
);
2841 CU_ASSERT(g_bserrno
== 0);
2843 spdk_blob_close(snapshot
, blob_op_complete
, NULL
);
2845 CU_ASSERT(g_bserrno
== 0);
2847 spdk_blob_close(blob
, blob_op_complete
, NULL
);
2849 CU_ASSERT(g_bserrno
== 0);
2851 /* Reload blobstore */
2852 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2854 CU_ASSERT(g_bserrno
== 0);
2858 spdk_bs_load(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
2860 CU_ASSERT(g_bserrno
== 0);
2861 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2864 /* Snapshot should be removed as blob is not pointing to it anymore */
2865 spdk_bs_open_blob(bs
, snapshotid
, blob_op_with_handle_complete
, NULL
);
2867 CU_ASSERT(g_bserrno
!= 0);
2869 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2871 CU_ASSERT(g_bserrno
== 0);
2876 bs_load_custom_cluster_size(void)
2878 struct spdk_bs_dev
*dev
;
2879 struct spdk_bs_super_block
*super_block
;
2880 struct spdk_bs_opts opts
;
2881 uint32_t custom_cluster_size
= 4194304; /* 4MiB */
2882 uint32_t cluster_sz
;
2883 uint64_t total_clusters
;
2886 spdk_bs_opts_init(&opts
);
2887 opts
.cluster_sz
= custom_cluster_size
;
2888 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
2890 /* Initialize a new blob store */
2891 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
2893 CU_ASSERT(g_bserrno
== 0);
2894 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2895 cluster_sz
= g_bs
->cluster_sz
;
2896 total_clusters
= g_bs
->total_clusters
;
2898 /* Unload the blob store */
2899 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2901 CU_ASSERT(g_bserrno
== 0);
2906 super_block
= (struct spdk_bs_super_block
*)g_dev_buffer
;
2907 CU_ASSERT(super_block
->clean
== 1);
2909 /* Load an existing blob store */
2911 spdk_bs_opts_init(&opts
);
2912 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
2913 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
2915 CU_ASSERT(g_bserrno
== 0);
2916 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2917 /* Compare cluster size and number to one after initialization */
2918 CU_ASSERT(cluster_sz
== g_bs
->cluster_sz
);
2919 CU_ASSERT(total_clusters
== g_bs
->total_clusters
);
2921 super_block
= (struct spdk_bs_super_block
*)g_dev_buffer
;
2922 CU_ASSERT(super_block
->clean
== 1);
2923 CU_ASSERT(super_block
->size
== dev
->blockcnt
* dev
->blocklen
);
2925 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2927 CU_ASSERT(g_bserrno
== 0);
2928 CU_ASSERT(super_block
->clean
== 1);
2935 struct spdk_bs_dev
*dev
;
2936 struct spdk_bs_opts opts
;
2939 spdk_bs_opts_init(&opts
);
2940 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
2942 /* Initialize a new blob store */
2943 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
2945 CU_ASSERT(g_bserrno
== 0);
2946 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2948 /* Unload the blob store */
2949 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2951 CU_ASSERT(g_bserrno
== 0);
2956 /* Load non existing blobstore type */
2958 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "NONEXISTING");
2959 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
2961 CU_ASSERT(g_bserrno
!= 0);
2963 /* Load with empty blobstore type */
2965 memset(opts
.bstype
.bstype
, 0, sizeof(opts
.bstype
.bstype
));
2966 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
2968 CU_ASSERT(g_bserrno
== 0);
2970 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2972 CU_ASSERT(g_bserrno
== 0);
2975 /* Initialize a new blob store with empty bstype */
2977 memset(opts
.bstype
.bstype
, 0, sizeof(opts
.bstype
.bstype
));
2978 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
2980 CU_ASSERT(g_bserrno
== 0);
2981 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
2983 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
2985 CU_ASSERT(g_bserrno
== 0);
2988 /* Load non existing blobstore type */
2990 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "NONEXISTING");
2991 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
2993 CU_ASSERT(g_bserrno
!= 0);
2995 /* Load with empty blobstore type */
2997 memset(opts
.bstype
.bstype
, 0, sizeof(opts
.bstype
.bstype
));
2998 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3000 CU_ASSERT(g_bserrno
== 0);
3002 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3004 CU_ASSERT(g_bserrno
== 0);
3009 bs_super_block(void)
3011 struct spdk_bs_dev
*dev
;
3012 struct spdk_bs_super_block
*super_block
;
3013 struct spdk_bs_opts opts
;
3014 struct spdk_bs_super_block_ver1 super_block_v1
;
3017 spdk_bs_opts_init(&opts
);
3018 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
3020 /* Initialize a new blob store */
3021 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3023 CU_ASSERT(g_bserrno
== 0);
3024 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3026 /* Unload the blob store */
3027 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3029 CU_ASSERT(g_bserrno
== 0);
3034 /* Load an existing blob store with version newer than supported */
3035 super_block
= (struct spdk_bs_super_block
*)g_dev_buffer
;
3036 super_block
->version
++;
3039 memset(opts
.bstype
.bstype
, 0, sizeof(opts
.bstype
.bstype
));
3040 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3042 CU_ASSERT(g_bserrno
!= 0);
3044 /* Create a new blob store with super block version 1 */
3046 super_block_v1
.version
= 1;
3047 memcpy(super_block_v1
.signature
, "SPDKBLOB", sizeof(super_block_v1
.signature
));
3048 super_block_v1
.length
= 0x1000;
3049 super_block_v1
.clean
= 1;
3050 super_block_v1
.super_blob
= 0xFFFFFFFFFFFFFFFF;
3051 super_block_v1
.cluster_size
= 0x100000;
3052 super_block_v1
.used_page_mask_start
= 0x01;
3053 super_block_v1
.used_page_mask_len
= 0x01;
3054 super_block_v1
.used_cluster_mask_start
= 0x02;
3055 super_block_v1
.used_cluster_mask_len
= 0x01;
3056 super_block_v1
.md_start
= 0x03;
3057 super_block_v1
.md_len
= 0x40;
3058 memset(super_block_v1
.reserved
, 0, 4036);
3059 super_block_v1
.crc
= _spdk_blob_md_page_calc_crc(&super_block_v1
);
3060 memcpy(g_dev_buffer
, &super_block_v1
, sizeof(struct spdk_bs_super_block_ver1
));
3062 memset(opts
.bstype
.bstype
, 0, sizeof(opts
.bstype
.bstype
));
3063 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3065 CU_ASSERT(g_bserrno
== 0);
3067 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3069 CU_ASSERT(g_bserrno
== 0);
3074 * Create a blobstore and then unload it.
3079 struct spdk_bs_dev
*dev
;
3080 struct spdk_blob_store
*bs
;
3081 spdk_blob_id blobid
;
3082 struct spdk_blob
*blob
;
3086 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
3088 CU_ASSERT(g_bserrno
== 0);
3089 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3092 /* Create a blob and open it. */
3094 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
3096 CU_ASSERT(g_bserrno
== 0);
3097 CU_ASSERT(g_blobid
> 0);
3101 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
3103 CU_ASSERT(g_bserrno
== 0);
3104 CU_ASSERT(g_blob
!= NULL
);
3107 /* Try to unload blobstore, should fail with open blob */
3109 spdk_bs_unload(bs
, bs_op_complete
, NULL
);
3111 CU_ASSERT(g_bserrno
== -EBUSY
);
3112 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3114 /* Close the blob, then successfully unload blobstore */
3116 spdk_blob_close(blob
, blob_op_complete
, NULL
);
3118 CU_ASSERT(g_bserrno
== 0);
3121 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3123 CU_ASSERT(g_bserrno
== 0);
3128 * Create a blobstore with a cluster size different than the default, and ensure it is
3134 struct spdk_bs_dev
*dev
;
3135 struct spdk_bs_opts opts
;
3136 uint32_t cluster_sz
;
3138 /* Set cluster size to zero */
3140 spdk_bs_opts_init(&opts
);
3141 opts
.cluster_sz
= 0;
3143 /* Initialize a new blob store */
3144 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3146 CU_ASSERT(g_bserrno
== -EINVAL
);
3147 SPDK_CU_ASSERT_FATAL(g_bs
== NULL
);
3150 * Set cluster size to blobstore page size,
3151 * to work it is required to be at least twice the blobstore page size.
3154 spdk_bs_opts_init(&opts
);
3155 opts
.cluster_sz
= SPDK_BS_PAGE_SIZE
;
3157 /* Initialize a new blob store */
3158 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3160 CU_ASSERT(g_bserrno
== -ENOMEM
);
3161 SPDK_CU_ASSERT_FATAL(g_bs
== NULL
);
3164 * Set cluster size to lower than page size,
3165 * to work it is required to be at least twice the blobstore page size.
3168 spdk_bs_opts_init(&opts
);
3169 opts
.cluster_sz
= SPDK_BS_PAGE_SIZE
- 1;
3171 /* Initialize a new blob store */
3172 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3174 CU_ASSERT(g_bserrno
== -EINVAL
);
3175 SPDK_CU_ASSERT_FATAL(g_bs
== NULL
);
3177 /* Set cluster size to twice the default */
3179 spdk_bs_opts_init(&opts
);
3180 opts
.cluster_sz
*= 2;
3181 cluster_sz
= opts
.cluster_sz
;
3183 /* Initialize a new blob store */
3184 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3186 CU_ASSERT(g_bserrno
== 0);
3187 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3189 CU_ASSERT(spdk_bs_get_cluster_size(g_bs
) == cluster_sz
);
3191 /* Unload the blob store */
3192 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3194 CU_ASSERT(g_bserrno
== 0);
3200 /* Load an existing blob store */
3201 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3203 CU_ASSERT(g_bserrno
== 0);
3204 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3206 CU_ASSERT(spdk_bs_get_cluster_size(g_bs
) == cluster_sz
);
3208 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3210 CU_ASSERT(g_bserrno
== 0);
3215 * Create a blobstore, reload it and ensure total usable cluster count
3219 bs_usable_clusters(void)
3221 struct spdk_bs_dev
*dev
;
3222 struct spdk_bs_opts opts
;
3226 /* Init blobstore */
3228 spdk_bs_opts_init(&opts
);
3230 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3232 CU_ASSERT(g_bserrno
== 0);
3233 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3235 clusters
= spdk_bs_total_data_cluster_count(g_bs
);
3237 /* Unload the blob store */
3238 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3240 CU_ASSERT(g_bserrno
== 0);
3244 /* Load an existing blob store */
3245 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3247 CU_ASSERT(g_bserrno
== 0);
3248 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3250 CU_ASSERT(spdk_bs_total_data_cluster_count(g_bs
) == clusters
);
3252 /* Create and resize blobs to make sure that useable cluster count won't change */
3253 for (i
= 0; i
< 4; i
++) {
3255 g_blobid
= SPDK_BLOBID_INVALID
;
3256 spdk_bs_create_blob(g_bs
, blob_op_with_id_complete
, NULL
);
3258 CU_ASSERT(g_bserrno
== 0);
3259 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
3263 spdk_bs_open_blob(g_bs
, g_blobid
, blob_op_with_handle_complete
, NULL
);
3265 CU_ASSERT(g_bserrno
== 0);
3266 CU_ASSERT(g_blob
!= NULL
);
3268 spdk_blob_resize(g_blob
, 10, blob_op_complete
, NULL
);
3270 CU_ASSERT(g_bserrno
== 0);
3273 spdk_blob_close(g_blob
, blob_op_complete
, NULL
);
3275 CU_ASSERT(g_bserrno
== 0);
3277 CU_ASSERT(spdk_bs_total_data_cluster_count(g_bs
) == clusters
);
3280 /* Reload the blob store to make sure that nothing changed */
3281 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3283 CU_ASSERT(g_bserrno
== 0);
3287 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3289 CU_ASSERT(g_bserrno
== 0);
3290 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3292 CU_ASSERT(spdk_bs_total_data_cluster_count(g_bs
) == clusters
);
3294 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3296 CU_ASSERT(g_bserrno
== 0);
3301 * Test resizing of the metadata blob. This requires creating enough blobs
3302 * so that one cluster is not enough to fit the metadata for those blobs.
3303 * To induce this condition to happen more quickly, we reduce the cluster
3304 * size to 16KB, which means only 4 4KB blob metadata pages can fit.
3309 const int CLUSTER_PAGE_COUNT
= 4;
3310 const int NUM_BLOBS
= CLUSTER_PAGE_COUNT
* 4;
3311 struct spdk_bs_dev
*dev
;
3312 struct spdk_bs_opts opts
;
3313 uint32_t cluster_sz
;
3314 spdk_blob_id blobids
[NUM_BLOBS
];
3319 spdk_bs_opts_init(&opts
);
3320 opts
.cluster_sz
= CLUSTER_PAGE_COUNT
* 4096;
3321 cluster_sz
= opts
.cluster_sz
;
3323 /* Initialize a new blob store */
3324 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3326 CU_ASSERT(g_bserrno
== 0);
3327 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3329 CU_ASSERT(spdk_bs_get_cluster_size(g_bs
) == cluster_sz
);
3331 for (i
= 0; i
< NUM_BLOBS
; i
++) {
3333 g_blobid
= SPDK_BLOBID_INVALID
;
3334 spdk_bs_create_blob(g_bs
, blob_op_with_id_complete
, NULL
);
3336 CU_ASSERT(g_bserrno
== 0);
3337 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
3338 blobids
[i
] = g_blobid
;
3341 /* Unload the blob store */
3343 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3345 CU_ASSERT(g_bserrno
== 0);
3347 /* Load an existing blob store */
3351 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3353 CU_ASSERT(g_bserrno
== 0);
3354 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3356 CU_ASSERT(spdk_bs_get_cluster_size(g_bs
) == cluster_sz
);
3358 for (i
= 0; i
< NUM_BLOBS
; i
++) {
3361 spdk_bs_open_blob(g_bs
, blobids
[i
], blob_op_with_handle_complete
, NULL
);
3363 CU_ASSERT(g_bserrno
== 0);
3364 CU_ASSERT(g_blob
!= NULL
);
3366 spdk_blob_close(g_blob
, blob_op_complete
, NULL
);
3368 CU_ASSERT(g_bserrno
== 0);
3371 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3373 CU_ASSERT(g_bserrno
== 0);
3380 struct spdk_bs_dev
*dev
;
3381 struct spdk_bs_opts opts
;
3383 /* Initialize a new blob store */
3385 spdk_bs_opts_init(&opts
);
3386 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3388 CU_ASSERT(g_bserrno
== 0);
3389 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3391 /* Destroy the blob store */
3393 spdk_bs_destroy(g_bs
, bs_op_complete
, NULL
);
3395 CU_ASSERT(g_bserrno
== 0);
3397 /* Loading an non-existent blob store should fail. */
3402 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3404 CU_ASSERT(g_bserrno
!= 0);
3407 /* Try to hit all of the corner cases associated with serializing
3411 blob_serialize(void)
3413 struct spdk_bs_dev
*dev
;
3414 struct spdk_bs_opts opts
;
3415 struct spdk_blob_store
*bs
;
3416 spdk_blob_id blobid
[2];
3417 struct spdk_blob
*blob
[2];
3424 /* Initialize a new blobstore with very small clusters */
3425 spdk_bs_opts_init(&opts
);
3426 opts
.cluster_sz
= dev
->blocklen
* 8;
3427 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3429 CU_ASSERT(g_bserrno
== 0);
3430 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3433 /* Create and open two blobs */
3434 for (i
= 0; i
< 2; i
++) {
3435 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
3437 CU_ASSERT(g_bserrno
== 0);
3438 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
3439 blobid
[i
] = g_blobid
;
3442 spdk_bs_open_blob(bs
, blobid
[i
], blob_op_with_handle_complete
, NULL
);
3444 CU_ASSERT(g_bserrno
== 0);
3445 CU_ASSERT(g_blob
!= NULL
);
3448 /* Set a fairly large xattr on both blobs to eat up
3451 value
= calloc(dev
->blocklen
- 64, sizeof(char));
3452 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
3453 memset(value
, i
, dev
->blocklen
/ 2);
3454 rc
= spdk_blob_set_xattr(blob
[i
], "name", value
, dev
->blocklen
- 64);
3459 /* Resize the blobs, alternating 1 cluster at a time.
3460 * This thwarts run length encoding and will cause spill
3461 * over of the extents.
3463 for (i
= 0; i
< 6; i
++) {
3464 spdk_blob_resize(blob
[i
% 2], (i
/ 2) + 1, blob_op_complete
, NULL
);
3466 CU_ASSERT(g_bserrno
== 0);
3469 for (i
= 0; i
< 2; i
++) {
3470 spdk_blob_sync_md(blob
[i
], blob_op_complete
, NULL
);
3472 CU_ASSERT(g_bserrno
== 0);
3475 /* Close the blobs */
3476 for (i
= 0; i
< 2; i
++) {
3477 spdk_blob_close(blob
[i
], blob_op_complete
, NULL
);
3479 CU_ASSERT(g_bserrno
== 0);
3482 /* Unload the blobstore */
3483 spdk_bs_unload(bs
, bs_op_complete
, NULL
);
3485 CU_ASSERT(g_bserrno
== 0);
3492 /* Load an existing blob store */
3493 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3495 CU_ASSERT(g_bserrno
== 0);
3496 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3499 for (i
= 0; i
< 2; i
++) {
3502 spdk_bs_open_blob(bs
, blobid
[i
], blob_op_with_handle_complete
, NULL
);
3504 CU_ASSERT(g_bserrno
== 0);
3505 CU_ASSERT(g_blob
!= NULL
);
3508 CU_ASSERT(spdk_blob_get_num_clusters(blob
[i
]) == 3);
3510 spdk_blob_close(blob
[i
], blob_op_complete
, NULL
);
3512 CU_ASSERT(g_bserrno
== 0);
3515 spdk_bs_unload(bs
, bs_op_complete
, NULL
);
3517 CU_ASSERT(g_bserrno
== 0);
3524 struct spdk_blob_store
*bs
;
3525 struct spdk_bs_dev
*dev
;
3526 struct spdk_blob
*blob
;
3527 spdk_blob_id blobid
;
3530 struct spdk_blob_md_page
*page
;
3534 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
3536 CU_ASSERT(g_bserrno
== 0);
3537 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3540 spdk_bs_create_blob(bs
, blob_op_with_id_complete
, NULL
);
3542 CU_ASSERT(g_bserrno
== 0);
3543 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
3546 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
3548 CU_ASSERT(g_bserrno
== 0);
3549 CU_ASSERT(g_blob
!= NULL
);
3552 spdk_blob_close(blob
, blob_op_complete
, NULL
);
3554 CU_ASSERT(g_bserrno
== 0);
3556 page_num
= _spdk_bs_blobid_to_page(blobid
);
3557 index
= DEV_BUFFER_BLOCKLEN
* (bs
->md_start
+ page_num
);
3558 page
= (struct spdk_blob_md_page
*)&g_dev_buffer
[index
];
3561 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
3563 CU_ASSERT(g_bserrno
== -EINVAL
);
3564 CU_ASSERT(g_blob
== NULL
);
3567 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
3569 CU_ASSERT(g_bserrno
== -EINVAL
);
3571 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3573 CU_ASSERT(g_bserrno
== 0);
3578 super_block_crc(void)
3580 struct spdk_bs_dev
*dev
;
3581 struct spdk_bs_super_block
*super_block
;
3582 struct spdk_bs_opts opts
;
3585 spdk_bs_opts_init(&opts
);
3587 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
3589 CU_ASSERT(g_bserrno
== 0);
3590 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3592 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3594 CU_ASSERT(g_bserrno
== 0);
3597 super_block
= (struct spdk_bs_super_block
*)g_dev_buffer
;
3598 super_block
->crc
= 0;
3601 /* Load an existing blob store */
3603 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3605 CU_ASSERT(g_bserrno
== -EILSEQ
);
3608 /* For blob dirty shutdown test case we do the following sub-test cases:
3609 * 1 Initialize new blob store and create 1 super blob with some xattrs, then we
3610 * dirty shutdown and reload the blob store and verify the xattrs.
3611 * 2 Resize the blob from 10 clusters to 20 clusters and then dirty shutdown,
3612 * reload the blob store and verify the clusters number.
3613 * 3 Create the second blob and then dirty shutdown, reload the blob store
3614 * and verify the second blob.
3615 * 4 Delete the second blob and then dirty shutdown, reload the blob store
3616 * and verify the second blob is invalid.
3617 * 5 Create the second blob again and also create the third blob, modify the
3618 * md of second blob which makes the md invalid, and then dirty shutdown,
3619 * reload the blob store verify the second blob, it should invalid and also
3620 * verify the third blob, it should correct.
3623 blob_dirty_shutdown(void)
3627 struct spdk_bs_dev
*dev
;
3628 spdk_blob_id blobid1
, blobid2
, blobid3
;
3629 struct spdk_blob
*blob
;
3631 uint64_t free_clusters
;
3635 struct spdk_blob_md_page
*page
;
3636 struct spdk_bs_opts opts
;
3639 spdk_bs_opts_init(&opts
);
3640 /* Initialize a new blob store */
3641 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
3643 CU_ASSERT(g_bserrno
== 0);
3644 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3646 /* Create first blob */
3647 spdk_bs_create_blob(g_bs
, blob_op_with_id_complete
, NULL
);
3649 CU_ASSERT(g_bserrno
== 0);
3650 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
3653 spdk_bs_open_blob(g_bs
, blobid1
, blob_op_with_handle_complete
, NULL
);
3655 CU_ASSERT(g_bserrno
== 0);
3656 CU_ASSERT(g_blob
!= NULL
);
3659 /* Set some xattrs */
3660 rc
= spdk_blob_set_xattr(blob
, "name", "log.txt", strlen("log.txt") + 1);
3664 rc
= spdk_blob_set_xattr(blob
, "length", &length
, sizeof(length
));
3667 /* Resize the blob */
3668 spdk_blob_resize(blob
, 10, blob_op_complete
, NULL
);
3670 CU_ASSERT(g_bserrno
== 0);
3672 /* Set the blob as the super blob */
3673 spdk_bs_set_super(g_bs
, blobid1
, blob_op_complete
, NULL
);
3675 CU_ASSERT(g_bserrno
== 0);
3677 free_clusters
= spdk_bs_free_cluster_count(g_bs
);
3679 spdk_blob_close(blob
, blob_op_complete
, NULL
);
3681 CU_ASSERT(g_bserrno
== 0);
3684 g_blobid
= SPDK_BLOBID_INVALID
;
3686 /* Dirty shutdown */
3687 _spdk_bs_free(g_bs
);
3689 /* reload blobstore */
3691 spdk_bs_opts_init(&opts
);
3692 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3694 CU_ASSERT(g_bserrno
== 0);
3696 /* Get the super blob */
3697 spdk_bs_get_super(g_bs
, blob_op_with_id_complete
, NULL
);
3699 CU_ASSERT(g_bserrno
== 0);
3700 CU_ASSERT(blobid1
== g_blobid
);
3702 spdk_bs_open_blob(g_bs
, blobid1
, blob_op_with_handle_complete
, NULL
);
3704 CU_ASSERT(g_bserrno
== 0);
3705 CU_ASSERT(g_blob
!= NULL
);
3708 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(g_bs
));
3710 /* Get the xattrs */
3712 rc
= spdk_blob_get_xattr_value(blob
, "length", &value
, &value_len
);
3714 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
3715 CU_ASSERT(*(uint64_t *)value
== length
);
3716 CU_ASSERT(value_len
== 8);
3717 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 10);
3719 /* Resize the blob */
3720 spdk_blob_resize(blob
, 20, blob_op_complete
, NULL
);
3722 CU_ASSERT(g_bserrno
== 0);
3724 free_clusters
= spdk_bs_free_cluster_count(g_bs
);
3726 spdk_blob_close(blob
, blob_op_complete
, NULL
);
3728 CU_ASSERT(g_bserrno
== 0);
3731 g_blobid
= SPDK_BLOBID_INVALID
;
3733 /* Dirty shutdown */
3734 _spdk_bs_free(g_bs
);
3736 /* reload the blobstore */
3738 spdk_bs_opts_init(&opts
);
3739 /* Load an existing blob store */
3740 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3742 CU_ASSERT(g_bserrno
== 0);
3743 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3744 spdk_bs_open_blob(g_bs
, blobid1
, blob_op_with_handle_complete
, NULL
);
3746 CU_ASSERT(g_bserrno
== 0);
3747 CU_ASSERT(g_blob
!= NULL
);
3749 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 20);
3750 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(g_bs
));
3752 spdk_blob_close(blob
, blob_op_complete
, NULL
);
3754 CU_ASSERT(g_bserrno
== 0);
3757 g_blobid
= SPDK_BLOBID_INVALID
;
3759 /* Create second blob */
3760 spdk_bs_create_blob(g_bs
, blob_op_with_id_complete
, NULL
);
3762 CU_ASSERT(g_bserrno
== 0);
3763 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
3766 spdk_bs_open_blob(g_bs
, blobid2
, blob_op_with_handle_complete
, NULL
);
3768 CU_ASSERT(g_bserrno
== 0);
3769 CU_ASSERT(g_blob
!= NULL
);
3772 /* Set some xattrs */
3773 rc
= spdk_blob_set_xattr(blob
, "name", "log1.txt", strlen("log1.txt") + 1);
3777 rc
= spdk_blob_set_xattr(blob
, "length", &length
, sizeof(length
));
3780 /* Resize the blob */
3781 spdk_blob_resize(blob
, 10, blob_op_complete
, NULL
);
3783 CU_ASSERT(g_bserrno
== 0);
3785 free_clusters
= spdk_bs_free_cluster_count(g_bs
);
3787 spdk_blob_close(blob
, blob_op_complete
, NULL
);
3789 CU_ASSERT(g_bserrno
== 0);
3792 g_blobid
= SPDK_BLOBID_INVALID
;
3794 /* Dirty shutdown */
3795 _spdk_bs_free(g_bs
);
3797 /* reload the blobstore */
3799 spdk_bs_opts_init(&opts
);
3800 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3802 CU_ASSERT(g_bserrno
== 0);
3804 spdk_bs_open_blob(g_bs
, blobid2
, blob_op_with_handle_complete
, NULL
);
3806 CU_ASSERT(g_bserrno
== 0);
3807 CU_ASSERT(g_blob
!= NULL
);
3810 /* Get the xattrs */
3812 rc
= spdk_blob_get_xattr_value(blob
, "length", &value
, &value_len
);
3814 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
3815 CU_ASSERT(*(uint64_t *)value
== length
);
3816 CU_ASSERT(value_len
== 8);
3817 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 10);
3818 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(g_bs
));
3820 spdk_blob_close(blob
, blob_op_complete
, NULL
);
3822 CU_ASSERT(g_bserrno
== 0);
3823 spdk_bs_delete_blob(g_bs
, blobid2
, blob_op_complete
, NULL
);
3825 CU_ASSERT(g_bserrno
== 0);
3827 free_clusters
= spdk_bs_free_cluster_count(g_bs
);
3829 /* Dirty shutdown */
3830 _spdk_bs_free(g_bs
);
3831 /* reload the blobstore */
3833 spdk_bs_opts_init(&opts
);
3834 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3836 CU_ASSERT(g_bserrno
== 0);
3838 spdk_bs_open_blob(g_bs
, blobid2
, blob_op_with_handle_complete
, NULL
);
3840 CU_ASSERT(g_bserrno
!= 0);
3841 CU_ASSERT(g_blob
== NULL
);
3843 spdk_bs_open_blob(g_bs
, blobid1
, blob_op_with_handle_complete
, NULL
);
3845 CU_ASSERT(g_bserrno
== 0);
3846 CU_ASSERT(g_blob
!= NULL
);
3847 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(g_bs
));
3848 spdk_blob_close(g_blob
, blob_op_complete
, NULL
);
3850 CU_ASSERT(g_bserrno
== 0);
3852 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3854 CU_ASSERT(g_bserrno
== 0);
3857 /* reload the blobstore */
3859 spdk_bs_opts_init(&opts
);
3860 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3862 CU_ASSERT(g_bserrno
== 0);
3864 /* Create second blob */
3865 spdk_bs_create_blob(g_bs
, blob_op_with_id_complete
, NULL
);
3867 CU_ASSERT(g_bserrno
== 0);
3868 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
3871 /* Create third blob */
3872 spdk_bs_create_blob(g_bs
, blob_op_with_id_complete
, NULL
);
3874 CU_ASSERT(g_bserrno
== 0);
3875 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
3878 spdk_bs_open_blob(g_bs
, blobid2
, blob_op_with_handle_complete
, NULL
);
3880 CU_ASSERT(g_bserrno
== 0);
3881 CU_ASSERT(g_blob
!= NULL
);
3884 /* Set some xattrs for second blob */
3885 rc
= spdk_blob_set_xattr(blob
, "name", "log1.txt", strlen("log1.txt") + 1);
3889 rc
= spdk_blob_set_xattr(blob
, "length", &length
, sizeof(length
));
3892 spdk_blob_close(blob
, blob_op_complete
, NULL
);
3894 CU_ASSERT(g_bserrno
== 0);
3897 g_blobid
= SPDK_BLOBID_INVALID
;
3899 spdk_bs_open_blob(g_bs
, blobid3
, blob_op_with_handle_complete
, NULL
);
3901 CU_ASSERT(g_bserrno
== 0);
3902 CU_ASSERT(g_blob
!= NULL
);
3905 /* Set some xattrs for third blob */
3906 rc
= spdk_blob_set_xattr(blob
, "name", "log2.txt", strlen("log2.txt") + 1);
3910 rc
= spdk_blob_set_xattr(blob
, "length", &length
, sizeof(length
));
3913 spdk_blob_close(blob
, blob_op_complete
, NULL
);
3915 CU_ASSERT(g_bserrno
== 0);
3918 g_blobid
= SPDK_BLOBID_INVALID
;
3920 /* Mark second blob as invalid */
3921 page_num
= _spdk_bs_blobid_to_page(blobid2
);
3923 index
= DEV_BUFFER_BLOCKLEN
* (g_bs
->md_start
+ page_num
);
3924 page
= (struct spdk_blob_md_page
*)&g_dev_buffer
[index
];
3925 page
->sequence_num
= 1;
3926 page
->crc
= _spdk_blob_md_page_calc_crc(page
);
3928 free_clusters
= spdk_bs_free_cluster_count(g_bs
);
3930 /* Dirty shutdown */
3931 _spdk_bs_free(g_bs
);
3932 /* reload the blobstore */
3934 spdk_bs_opts_init(&opts
);
3935 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3937 CU_ASSERT(g_bserrno
== 0);
3939 spdk_bs_open_blob(g_bs
, blobid2
, blob_op_with_handle_complete
, NULL
);
3941 CU_ASSERT(g_bserrno
!= 0);
3942 CU_ASSERT(g_blob
== NULL
);
3944 spdk_bs_open_blob(g_bs
, blobid3
, blob_op_with_handle_complete
, NULL
);
3946 CU_ASSERT(g_bserrno
== 0);
3947 CU_ASSERT(g_blob
!= NULL
);
3950 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(g_bs
));
3952 spdk_blob_close(blob
, blob_op_complete
, NULL
);
3954 CU_ASSERT(g_bserrno
== 0);
3957 g_blobid
= SPDK_BLOBID_INVALID
;
3959 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
3961 CU_ASSERT(g_bserrno
== 0);
3968 struct spdk_bs_dev
*dev
;
3969 spdk_blob_id blobid_invalid
, blobid_data_ro
, blobid_md_ro
;
3970 struct spdk_blob
*blob_invalid
, *blob_data_ro
, *blob_md_ro
;
3971 struct spdk_bs_opts opts
;
3975 spdk_bs_opts_init(&opts
);
3977 /* Initialize a new blob store */
3978 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
3980 CU_ASSERT(g_bserrno
== 0);
3981 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
3983 /* Create three blobs - one each for testing invalid, data_ro and md_ro flags. */
3984 spdk_bs_create_blob(g_bs
, blob_op_with_id_complete
, NULL
);
3986 CU_ASSERT(g_bserrno
== 0);
3987 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
3988 blobid_invalid
= g_blobid
;
3990 spdk_bs_create_blob(g_bs
, blob_op_with_id_complete
, NULL
);
3992 CU_ASSERT(g_bserrno
== 0);
3993 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
3994 blobid_data_ro
= g_blobid
;
3996 spdk_bs_create_blob(g_bs
, blob_op_with_id_complete
, NULL
);
3998 CU_ASSERT(g_bserrno
== 0);
3999 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
4000 blobid_md_ro
= g_blobid
;
4002 spdk_bs_open_blob(g_bs
, blobid_invalid
, blob_op_with_handle_complete
, NULL
);
4004 CU_ASSERT(g_bserrno
== 0);
4005 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4006 blob_invalid
= g_blob
;
4008 spdk_bs_open_blob(g_bs
, blobid_data_ro
, blob_op_with_handle_complete
, NULL
);
4010 CU_ASSERT(g_bserrno
== 0);
4011 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4012 blob_data_ro
= g_blob
;
4014 spdk_bs_open_blob(g_bs
, blobid_md_ro
, blob_op_with_handle_complete
, NULL
);
4016 CU_ASSERT(g_bserrno
== 0);
4017 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4018 blob_md_ro
= g_blob
;
4020 /* Change the size of blob_data_ro to check if flags are serialized
4021 * when blob has non zero number of extents */
4022 spdk_blob_resize(blob_data_ro
, 10, blob_op_complete
, NULL
);
4024 CU_ASSERT(g_bserrno
== 0);
4026 /* Set the xattr to check if flags are serialized
4027 * when blob has non zero number of xattrs */
4028 rc
= spdk_blob_set_xattr(blob_md_ro
, "name", "log.txt", strlen("log.txt") + 1);
4031 blob_invalid
->invalid_flags
= (1ULL << 63);
4032 blob_invalid
->state
= SPDK_BLOB_STATE_DIRTY
;
4033 blob_data_ro
->data_ro_flags
= (1ULL << 62);
4034 blob_data_ro
->state
= SPDK_BLOB_STATE_DIRTY
;
4035 blob_md_ro
->md_ro_flags
= (1ULL << 61);
4036 blob_md_ro
->state
= SPDK_BLOB_STATE_DIRTY
;
4039 spdk_blob_sync_md(blob_invalid
, blob_op_complete
, NULL
);
4041 CU_ASSERT(g_bserrno
== 0);
4043 spdk_blob_sync_md(blob_data_ro
, blob_op_complete
, NULL
);
4045 CU_ASSERT(g_bserrno
== 0);
4047 spdk_blob_sync_md(blob_md_ro
, blob_op_complete
, NULL
);
4049 CU_ASSERT(g_bserrno
== 0);
4052 spdk_blob_close(blob_invalid
, blob_op_complete
, NULL
);
4054 CU_ASSERT(g_bserrno
== 0);
4055 blob_invalid
= NULL
;
4057 spdk_blob_close(blob_data_ro
, blob_op_complete
, NULL
);
4059 CU_ASSERT(g_bserrno
== 0);
4060 blob_data_ro
= NULL
;
4062 spdk_blob_close(blob_md_ro
, blob_op_complete
, NULL
);
4064 CU_ASSERT(g_bserrno
== 0);
4068 g_blobid
= SPDK_BLOBID_INVALID
;
4070 /* Unload the blob store */
4071 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4073 CU_ASSERT(g_bserrno
== 0);
4076 /* Load an existing blob store */
4078 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
4080 CU_ASSERT(g_bserrno
== 0);
4081 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4085 spdk_bs_open_blob(g_bs
, blobid_invalid
, blob_op_with_handle_complete
, NULL
);
4087 CU_ASSERT(g_bserrno
!= 0);
4088 CU_ASSERT(g_blob
== NULL
);
4092 spdk_bs_open_blob(g_bs
, blobid_data_ro
, blob_op_with_handle_complete
, NULL
);
4094 CU_ASSERT(g_bserrno
== 0);
4095 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4096 blob_data_ro
= g_blob
;
4097 /* If an unknown data_ro flag was found, the blob should be marked both data and md read-only. */
4098 CU_ASSERT(blob_data_ro
->data_ro
== true);
4099 CU_ASSERT(blob_data_ro
->md_ro
== true);
4100 CU_ASSERT(spdk_blob_get_num_clusters(blob_data_ro
) == 10);
4104 spdk_bs_open_blob(g_bs
, blobid_md_ro
, blob_op_with_handle_complete
, NULL
);
4106 CU_ASSERT(g_bserrno
== 0);
4107 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4108 blob_md_ro
= g_blob
;
4109 CU_ASSERT(blob_md_ro
->data_ro
== false);
4110 CU_ASSERT(blob_md_ro
->md_ro
== true);
4113 spdk_blob_sync_md(blob_md_ro
, blob_op_complete
, NULL
);
4115 CU_ASSERT(g_bserrno
== 0);
4117 spdk_blob_close(blob_data_ro
, blob_op_complete
, NULL
);
4119 CU_ASSERT(g_bserrno
== 0);
4120 spdk_blob_close(blob_md_ro
, blob_op_complete
, NULL
);
4122 CU_ASSERT(g_bserrno
== 0);
4124 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4126 CU_ASSERT(g_bserrno
== 0);
4132 struct spdk_bs_super_block
*super
;
4133 struct spdk_bs_dev
*dev
;
4134 struct spdk_bs_opts opts
;
4135 spdk_blob_id blobid
;
4138 spdk_bs_opts_init(&opts
);
4140 /* Initialize a new blob store */
4141 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
4143 CU_ASSERT(g_bserrno
== 0);
4144 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4146 /* Unload the blob store */
4147 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4149 CU_ASSERT(g_bserrno
== 0);
4153 * Change the bs version on disk. This will allow us to
4154 * test that the version does not get modified automatically
4155 * when loading and unloading the blobstore.
4157 super
= (struct spdk_bs_super_block
*)&g_dev_buffer
[0];
4158 CU_ASSERT(super
->version
== SPDK_BS_VERSION
);
4159 CU_ASSERT(super
->clean
== 1);
4162 * Version 2 metadata does not have a used blobid mask, so clear
4163 * those fields in the super block and zero the corresponding
4164 * region on "disk". We will use this to ensure blob IDs are
4165 * correctly reconstructed.
4167 memset(&g_dev_buffer
[super
->used_blobid_mask_start
* SPDK_BS_PAGE_SIZE
], 0,
4168 super
->used_blobid_mask_len
* SPDK_BS_PAGE_SIZE
);
4169 super
->used_blobid_mask_start
= 0;
4170 super
->used_blobid_mask_len
= 0;
4171 super
->crc
= _spdk_blob_md_page_calc_crc(super
);
4173 /* Load an existing blob store */
4175 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
4177 CU_ASSERT(g_bserrno
== 0);
4178 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4179 CU_ASSERT(super
->clean
== 1);
4182 * Create a blob - just to make sure that when we unload it
4183 * results in writing the super block (since metadata pages
4186 spdk_bs_create_blob(g_bs
, blob_op_with_id_complete
, NULL
);
4188 CU_ASSERT(g_bserrno
== 0);
4189 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
4192 /* Unload the blob store */
4193 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4195 CU_ASSERT(g_bserrno
== 0);
4197 CU_ASSERT(super
->version
== 2);
4198 CU_ASSERT(super
->used_blobid_mask_start
== 0);
4199 CU_ASSERT(super
->used_blobid_mask_len
== 0);
4202 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
4204 CU_ASSERT(g_bserrno
== 0);
4205 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4208 spdk_bs_open_blob(g_bs
, blobid
, blob_op_with_handle_complete
, NULL
);
4210 CU_ASSERT(g_bserrno
== 0);
4211 CU_ASSERT(g_blob
!= NULL
);
4213 spdk_blob_close(g_blob
, blob_op_complete
, NULL
);
4215 CU_ASSERT(g_bserrno
== 0);
4217 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4219 CU_ASSERT(g_bserrno
== 0);
4221 CU_ASSERT(super
->version
== 2);
4222 CU_ASSERT(super
->used_blobid_mask_start
== 0);
4223 CU_ASSERT(super
->used_blobid_mask_len
== 0);
4227 blob_set_xattrs(void)
4229 struct spdk_blob_store
*bs
;
4230 struct spdk_bs_dev
*dev
;
4231 struct spdk_blob
*blob
;
4232 struct spdk_blob_opts opts
;
4233 spdk_blob_id blobid
;
4240 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
4242 CU_ASSERT(g_bserrno
== 0);
4243 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4246 /* Create blob with extra attributes */
4247 spdk_blob_opts_init(&opts
);
4249 opts
.xattrs
.names
= g_xattr_names
;
4250 opts
.xattrs
.get_value
= _get_xattr_value
;
4251 opts
.xattrs
.count
= 3;
4252 opts
.xattrs
.ctx
= &g_ctx
;
4254 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
4256 CU_ASSERT(g_bserrno
== 0);
4257 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
4260 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
4262 CU_ASSERT(g_bserrno
== 0);
4263 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4266 /* Get the xattrs */
4269 rc
= spdk_blob_get_xattr_value(blob
, g_xattr_names
[0], &value
, &value_len
);
4271 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
4272 CU_ASSERT(value_len
== strlen(g_xattr_values
[0]));
4273 CU_ASSERT_NSTRING_EQUAL_FATAL(value
, g_xattr_values
[0], value_len
);
4275 rc
= spdk_blob_get_xattr_value(blob
, g_xattr_names
[1], &value
, &value_len
);
4277 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
4278 CU_ASSERT(value_len
== strlen(g_xattr_values
[1]));
4279 CU_ASSERT_NSTRING_EQUAL((char *)value
, g_xattr_values
[1], value_len
);
4281 rc
= spdk_blob_get_xattr_value(blob
, g_xattr_names
[2], &value
, &value_len
);
4283 SPDK_CU_ASSERT_FATAL(value
!= NULL
);
4284 CU_ASSERT(value_len
== strlen(g_xattr_values
[2]));
4285 CU_ASSERT_NSTRING_EQUAL((char *)value
, g_xattr_values
[2], value_len
);
4287 /* Try to get non existing attribute */
4289 rc
= spdk_blob_get_xattr_value(blob
, "foobar", &value
, &value_len
);
4290 CU_ASSERT(rc
== -ENOENT
);
4292 spdk_blob_close(blob
, blob_op_complete
, NULL
);
4294 CU_ASSERT(g_bserrno
== 0);
4297 g_blobid
= SPDK_BLOBID_INVALID
;
4300 spdk_blob_opts_init(&opts
);
4301 opts
.xattrs
.names
= g_xattr_names
;
4302 opts
.xattrs
.get_value
= NULL
;
4303 opts
.xattrs
.count
= 1;
4304 opts
.xattrs
.ctx
= &g_ctx
;
4306 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
4308 CU_ASSERT(g_bserrno
== -EINVAL
);
4309 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
4312 spdk_blob_opts_init(&opts
);
4313 opts
.xattrs
.names
= g_xattr_names
;
4314 opts
.xattrs
.get_value
= _get_xattr_value_null
;
4315 opts
.xattrs
.count
= 1;
4316 opts
.xattrs
.ctx
= NULL
;
4318 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
4320 CU_ASSERT(g_bserrno
== -EINVAL
);
4322 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4324 CU_ASSERT(g_bserrno
== 0);
4330 blob_thin_prov_alloc(void)
4332 struct spdk_blob_store
*bs
;
4333 struct spdk_bs_dev
*dev
;
4334 struct spdk_blob
*blob
;
4335 struct spdk_blob_opts opts
;
4336 spdk_blob_id blobid
;
4337 uint64_t free_clusters
;
4341 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
4343 CU_ASSERT(g_bserrno
== 0);
4344 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4346 free_clusters
= spdk_bs_free_cluster_count(bs
);
4348 /* Set blob as thin provisioned */
4349 spdk_blob_opts_init(&opts
);
4350 opts
.thin_provision
= true;
4352 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
4354 CU_ASSERT(g_bserrno
== 0);
4355 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
4356 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4359 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
4361 CU_ASSERT(g_bserrno
== 0);
4362 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4365 CU_ASSERT(blob
->active
.num_clusters
== 0);
4366 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 0);
4368 /* The blob started at 0 clusters. Resize it to be 5, but still unallocated. */
4369 spdk_blob_resize(blob
, 5, blob_op_complete
, NULL
);
4371 CU_ASSERT(g_bserrno
== 0);
4372 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4373 CU_ASSERT(blob
->active
.num_clusters
== 5);
4374 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 5);
4376 /* Grow it to 1TB - still unallocated */
4377 spdk_blob_resize(blob
, 262144, blob_op_complete
, NULL
);
4379 CU_ASSERT(g_bserrno
== 0);
4380 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4381 CU_ASSERT(blob
->active
.num_clusters
== 262144);
4382 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 262144);
4384 spdk_blob_sync_md(blob
, blob_op_complete
, NULL
);
4386 CU_ASSERT(g_bserrno
== 0);
4387 /* Sync must not change anything */
4388 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4389 CU_ASSERT(blob
->active
.num_clusters
== 262144);
4390 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 262144);
4391 /* Since clusters are not allocated,
4392 * number of metadata pages is expected to be minimal.
4394 CU_ASSERT(blob
->active
.num_pages
== 1);
4396 /* Shrink the blob to 3 clusters - still unallocated */
4397 spdk_blob_resize(blob
, 3, blob_op_complete
, NULL
);
4399 CU_ASSERT(g_bserrno
== 0);
4400 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4401 CU_ASSERT(blob
->active
.num_clusters
== 3);
4402 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 3);
4404 spdk_blob_sync_md(blob
, blob_op_complete
, NULL
);
4406 CU_ASSERT(g_bserrno
== 0);
4407 /* Sync must not change anything */
4408 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4409 CU_ASSERT(blob
->active
.num_clusters
== 3);
4410 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 3);
4412 spdk_blob_close(blob
, blob_op_complete
, NULL
);
4414 CU_ASSERT(g_bserrno
== 0);
4416 /* Unload the blob store */
4417 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4419 CU_ASSERT(g_bserrno
== 0);
4424 /* Load an existing blob store */
4426 spdk_bs_load(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
4428 CU_ASSERT(g_bserrno
== 0);
4429 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4433 spdk_bs_open_blob(g_bs
, blobid
, blob_op_with_handle_complete
, NULL
);
4435 CU_ASSERT(g_bserrno
== 0);
4436 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4439 /* Check that clusters allocation and size is still the same */
4440 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4441 CU_ASSERT(blob
->active
.num_clusters
== 3);
4443 spdk_blob_close(blob
, blob_op_complete
, NULL
);
4445 CU_ASSERT(g_bserrno
== 0);
4447 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
4449 CU_ASSERT(g_bserrno
== 0);
4451 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4453 CU_ASSERT(g_bserrno
== 0);
4458 blob_insert_cluster_msg(void)
4460 struct spdk_blob_store
*bs
;
4461 struct spdk_bs_dev
*dev
;
4462 struct spdk_blob
*blob
;
4463 struct spdk_blob_opts opts
;
4464 spdk_blob_id blobid
;
4465 uint64_t free_clusters
;
4469 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
4471 CU_ASSERT(g_bserrno
== 0);
4472 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4474 free_clusters
= spdk_bs_free_cluster_count(bs
);
4476 /* Set blob as thin provisioned */
4477 spdk_blob_opts_init(&opts
);
4478 opts
.thin_provision
= true;
4479 opts
.num_clusters
= 4;
4481 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
4483 CU_ASSERT(g_bserrno
== 0);
4484 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
4485 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4488 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
4490 CU_ASSERT(g_bserrno
== 0);
4491 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4494 CU_ASSERT(blob
->active
.num_clusters
== 4);
4495 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 4);
4496 CU_ASSERT(blob
->active
.clusters
[1] == 0);
4498 _spdk_bs_claim_cluster(bs
, 0xF);
4499 _spdk_blob_insert_cluster_on_md_thread(blob
, 1, 0xF, blob_op_complete
, NULL
);
4502 CU_ASSERT(blob
->active
.clusters
[1] != 0);
4504 spdk_blob_close(blob
, blob_op_complete
, NULL
);
4506 CU_ASSERT(g_bserrno
== 0);
4508 /* Unload the blob store */
4509 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4511 CU_ASSERT(g_bserrno
== 0);
4516 /* Load an existing blob store */
4518 spdk_bs_load(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
4520 CU_ASSERT(g_bserrno
== 0);
4521 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4525 spdk_bs_open_blob(g_bs
, blobid
, blob_op_with_handle_complete
, NULL
);
4527 CU_ASSERT(g_bserrno
== 0);
4528 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4531 CU_ASSERT(blob
->active
.clusters
[1] != 0);
4533 spdk_blob_close(blob
, blob_op_complete
, NULL
);
4535 CU_ASSERT(g_bserrno
== 0);
4537 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
4539 CU_ASSERT(g_bserrno
== 0);
4541 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4543 CU_ASSERT(g_bserrno
== 0);
4548 blob_thin_prov_rw(void)
4550 static const uint8_t zero
[10 * 4096] = { 0 };
4551 struct spdk_blob_store
*bs
;
4552 struct spdk_bs_dev
*dev
;
4553 struct spdk_blob
*blob
;
4554 struct spdk_io_channel
*channel
, *channel_thread1
;
4555 struct spdk_blob_opts opts
;
4556 spdk_blob_id blobid
;
4557 uint64_t free_clusters
;
4559 uint8_t payload_read
[10 * 4096];
4560 uint8_t payload_write
[10 * 4096];
4561 uint64_t write_bytes
;
4562 uint64_t read_bytes
;
4566 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
4568 CU_ASSERT(g_bserrno
== 0);
4569 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4571 free_clusters
= spdk_bs_free_cluster_count(bs
);
4572 page_size
= spdk_bs_get_page_size(bs
);
4574 channel
= spdk_bs_alloc_io_channel(bs
);
4575 CU_ASSERT(channel
!= NULL
);
4577 spdk_blob_opts_init(&opts
);
4578 opts
.thin_provision
= true;
4580 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
4582 CU_ASSERT(g_bserrno
== 0);
4583 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
4584 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4587 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
4589 CU_ASSERT(g_bserrno
== 0);
4590 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4593 CU_ASSERT(blob
->active
.num_clusters
== 0);
4595 /* The blob started at 0 clusters. Resize it to be 5, but still unallocated. */
4596 spdk_blob_resize(blob
, 5, blob_op_complete
, NULL
);
4598 CU_ASSERT(g_bserrno
== 0);
4599 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4600 CU_ASSERT(blob
->active
.num_clusters
== 5);
4602 spdk_blob_sync_md(blob
, blob_op_complete
, NULL
);
4604 CU_ASSERT(g_bserrno
== 0);
4605 /* Sync must not change anything */
4606 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4607 CU_ASSERT(blob
->active
.num_clusters
== 5);
4609 /* Payload should be all zeros from unallocated clusters */
4610 memset(payload_read
, 0xFF, sizeof(payload_read
));
4611 spdk_blob_io_read(blob
, channel
, payload_read
, 4, 10, blob_op_complete
, NULL
);
4613 CU_ASSERT(g_bserrno
== 0);
4614 CU_ASSERT(memcmp(zero
, payload_read
, 10 * 4096) == 0);
4616 write_bytes
= g_dev_write_bytes
;
4617 read_bytes
= g_dev_read_bytes
;
4619 /* Perform write on thread 1. That will allocate cluster on thread 0 via send_msg */
4621 channel_thread1
= spdk_bs_alloc_io_channel(bs
);
4622 CU_ASSERT(channel_thread1
!= NULL
);
4623 memset(payload_write
, 0xE5, sizeof(payload_write
));
4624 spdk_blob_io_write(blob
, channel_thread1
, payload_write
, 4, 10, blob_op_complete
, NULL
);
4625 CU_ASSERT(free_clusters
- 1 == spdk_bs_free_cluster_count(bs
));
4626 /* Perform write on thread 0. That will try to allocate cluster,
4627 * but fail due to another thread issuing the cluster allocation first. */
4629 memset(payload_write
, 0xE5, sizeof(payload_write
));
4630 spdk_blob_io_write(blob
, channel
, payload_write
, 4, 10, blob_op_complete
, NULL
);
4631 CU_ASSERT(free_clusters
- 2 == spdk_bs_free_cluster_count(bs
));
4633 CU_ASSERT(g_bserrno
== 0);
4634 CU_ASSERT(free_clusters
- 1 == spdk_bs_free_cluster_count(bs
));
4635 /* For thin-provisioned blob we need to write 20 pages plus one page metadata and
4637 CU_ASSERT(g_dev_write_bytes
- write_bytes
== page_size
* 21);
4638 CU_ASSERT(g_dev_read_bytes
- read_bytes
== 0);
4640 spdk_blob_io_read(blob
, channel
, payload_read
, 4, 10, blob_op_complete
, NULL
);
4642 CU_ASSERT(g_bserrno
== 0);
4643 CU_ASSERT(memcmp(payload_write
, payload_read
, 10 * 4096) == 0);
4645 spdk_blob_close(blob
, blob_op_complete
, NULL
);
4647 CU_ASSERT(g_bserrno
== 0);
4649 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
4651 CU_ASSERT(g_bserrno
== 0);
4652 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4654 spdk_bs_free_io_channel(channel_thread1
);
4655 spdk_bs_free_io_channel(channel
);
4658 /* Unload the blob store */
4659 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4661 CU_ASSERT(g_bserrno
== 0);
4668 blob_thin_prov_rw_iov(void)
4670 static const uint8_t zero
[10 * 4096] = { 0 };
4671 struct spdk_blob_store
*bs
;
4672 struct spdk_bs_dev
*dev
;
4673 struct spdk_blob
*blob
;
4674 struct spdk_io_channel
*channel
;
4675 struct spdk_blob_opts opts
;
4676 spdk_blob_id blobid
;
4677 uint64_t free_clusters
;
4678 uint8_t payload_read
[10 * 4096];
4679 uint8_t payload_write
[10 * 4096];
4680 struct iovec iov_read
[3];
4681 struct iovec iov_write
[3];
4685 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
4687 CU_ASSERT(g_bserrno
== 0);
4688 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4690 free_clusters
= spdk_bs_free_cluster_count(bs
);
4692 channel
= spdk_bs_alloc_io_channel(bs
);
4693 CU_ASSERT(channel
!= NULL
);
4695 spdk_blob_opts_init(&opts
);
4696 opts
.thin_provision
= true;
4698 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
4700 CU_ASSERT(g_bserrno
== 0);
4701 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
4702 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4705 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
4707 CU_ASSERT(g_bserrno
== 0);
4708 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4711 CU_ASSERT(blob
->active
.num_clusters
== 0);
4713 /* The blob started at 0 clusters. Resize it to be 5, but still unallocated. */
4714 spdk_blob_resize(blob
, 5, blob_op_complete
, NULL
);
4716 CU_ASSERT(g_bserrno
== 0);
4717 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4718 CU_ASSERT(blob
->active
.num_clusters
== 5);
4720 spdk_blob_sync_md(blob
, blob_op_complete
, NULL
);
4722 CU_ASSERT(g_bserrno
== 0);
4723 /* Sync must not change anything */
4724 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4725 CU_ASSERT(blob
->active
.num_clusters
== 5);
4727 /* Payload should be all zeros from unallocated clusters */
4728 memset(payload_read
, 0xAA, sizeof(payload_read
));
4729 iov_read
[0].iov_base
= payload_read
;
4730 iov_read
[0].iov_len
= 3 * 4096;
4731 iov_read
[1].iov_base
= payload_read
+ 3 * 4096;
4732 iov_read
[1].iov_len
= 4 * 4096;
4733 iov_read
[2].iov_base
= payload_read
+ 7 * 4096;
4734 iov_read
[2].iov_len
= 3 * 4096;
4735 spdk_blob_io_readv(blob
, channel
, iov_read
, 3, 250, 10, blob_op_complete
, NULL
);
4737 CU_ASSERT(g_bserrno
== 0);
4738 CU_ASSERT(memcmp(zero
, payload_read
, 10 * 4096) == 0);
4740 memset(payload_write
, 0xE5, sizeof(payload_write
));
4741 iov_write
[0].iov_base
= payload_write
;
4742 iov_write
[0].iov_len
= 1 * 4096;
4743 iov_write
[1].iov_base
= payload_write
+ 1 * 4096;
4744 iov_write
[1].iov_len
= 5 * 4096;
4745 iov_write
[2].iov_base
= payload_write
+ 6 * 4096;
4746 iov_write
[2].iov_len
= 4 * 4096;
4748 spdk_blob_io_writev(blob
, channel
, iov_write
, 3, 250, 10, blob_op_complete
, NULL
);
4750 CU_ASSERT(g_bserrno
== 0);
4752 memset(payload_read
, 0xAA, sizeof(payload_read
));
4753 iov_read
[0].iov_base
= payload_read
;
4754 iov_read
[0].iov_len
= 3 * 4096;
4755 iov_read
[1].iov_base
= payload_read
+ 3 * 4096;
4756 iov_read
[1].iov_len
= 4 * 4096;
4757 iov_read
[2].iov_base
= payload_read
+ 7 * 4096;
4758 iov_read
[2].iov_len
= 3 * 4096;
4759 spdk_blob_io_readv(blob
, channel
, iov_read
, 3, 250, 10, blob_op_complete
, NULL
);
4761 CU_ASSERT(g_bserrno
== 0);
4762 CU_ASSERT(memcmp(payload_write
, payload_read
, 10 * 4096) == 0);
4764 spdk_blob_close(blob
, blob_op_complete
, NULL
);
4766 CU_ASSERT(g_bserrno
== 0);
4768 spdk_bs_free_io_channel(channel
);
4771 /* Unload the blob store */
4772 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4774 CU_ASSERT(g_bserrno
== 0);
4782 spdk_blob_id blobid
[4];
4786 test_iter(void *arg
, struct spdk_blob
*blob
, int bserrno
)
4788 struct iter_ctx
*iter_ctx
= arg
;
4789 spdk_blob_id blobid
;
4791 CU_ASSERT(bserrno
== 0);
4792 blobid
= spdk_blob_get_id(blob
);
4793 CU_ASSERT(blobid
== iter_ctx
->blobid
[iter_ctx
->current_iter
++]);
4799 struct spdk_bs_dev
*dev
;
4800 struct iter_ctx iter_ctx
= { 0 };
4801 struct spdk_blob
*blob
;
4803 struct spdk_bs_opts opts
;
4806 spdk_bs_opts_init(&opts
);
4807 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
4809 /* Initialize a new blob store */
4810 spdk_bs_init(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
4812 CU_ASSERT(g_bserrno
== 0);
4813 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4815 for (i
= 0; i
< 4; i
++) {
4817 g_blobid
= SPDK_BLOBID_INVALID
;
4818 spdk_bs_create_blob(g_bs
, blob_op_with_id_complete
, NULL
);
4820 CU_ASSERT(g_bserrno
== 0);
4821 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
4822 iter_ctx
.blobid
[i
] = g_blobid
;
4826 spdk_bs_open_blob(g_bs
, g_blobid
, blob_op_with_handle_complete
, NULL
);
4828 CU_ASSERT(g_bserrno
== 0);
4829 CU_ASSERT(g_blob
!= NULL
);
4832 /* Just save the blobid as an xattr for testing purposes. */
4833 rc
= spdk_blob_set_xattr(blob
, "blobid", &g_blobid
, sizeof(g_blobid
));
4836 /* Resize the blob */
4837 spdk_blob_resize(blob
, i
, blob_op_complete
, NULL
);
4839 CU_ASSERT(g_bserrno
== 0);
4841 spdk_blob_close(blob
, blob_op_complete
, NULL
);
4843 CU_ASSERT(g_bserrno
== 0);
4847 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4849 CU_ASSERT(g_bserrno
== 0);
4852 spdk_bs_opts_init(&opts
);
4853 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
4854 opts
.iter_cb_fn
= test_iter
;
4855 opts
.iter_cb_arg
= &iter_ctx
;
4857 /* Test blob iteration during load after a clean shutdown. */
4858 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
4860 CU_ASSERT(g_bserrno
== 0);
4861 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4863 /* Dirty shutdown */
4864 _spdk_bs_free(g_bs
);
4867 spdk_bs_opts_init(&opts
);
4868 snprintf(opts
.bstype
.bstype
, sizeof(opts
.bstype
.bstype
), "TESTTYPE");
4869 opts
.iter_cb_fn
= test_iter
;
4870 iter_ctx
.current_iter
= 0;
4871 opts
.iter_cb_arg
= &iter_ctx
;
4873 /* Test blob iteration during load after a dirty shutdown. */
4874 spdk_bs_load(dev
, &opts
, bs_op_with_handle_complete
, NULL
);
4876 CU_ASSERT(g_bserrno
== 0);
4877 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4879 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
4881 CU_ASSERT(g_bserrno
== 0);
4886 blob_snapshot_rw(void)
4888 static const uint8_t zero
[10 * 4096] = { 0 };
4889 struct spdk_blob_store
*bs
;
4890 struct spdk_bs_dev
*dev
;
4891 struct spdk_blob
*blob
, *snapshot
;
4892 struct spdk_io_channel
*channel
;
4893 struct spdk_blob_opts opts
;
4894 spdk_blob_id blobid
, snapshotid
;
4895 uint64_t free_clusters
;
4896 uint64_t cluster_size
;
4898 uint8_t payload_read
[10 * 4096];
4899 uint8_t payload_write
[10 * 4096];
4900 uint64_t write_bytes
;
4901 uint64_t read_bytes
;
4905 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
4907 CU_ASSERT(g_bserrno
== 0);
4908 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
4910 free_clusters
= spdk_bs_free_cluster_count(bs
);
4911 cluster_size
= spdk_bs_get_cluster_size(bs
);
4912 page_size
= spdk_bs_get_page_size(bs
);
4914 channel
= spdk_bs_alloc_io_channel(bs
);
4915 CU_ASSERT(channel
!= NULL
);
4917 spdk_blob_opts_init(&opts
);
4918 opts
.thin_provision
= true;
4919 opts
.num_clusters
= 5;
4921 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
4923 CU_ASSERT(g_bserrno
== 0);
4924 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
4925 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
4928 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
4930 CU_ASSERT(g_bserrno
== 0);
4931 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4934 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 5);
4936 memset(payload_read
, 0xFF, sizeof(payload_read
));
4937 spdk_blob_io_read(blob
, channel
, payload_read
, 4, 10, blob_op_complete
, NULL
);
4939 CU_ASSERT(g_bserrno
== 0);
4940 CU_ASSERT(memcmp(zero
, payload_read
, 10 * 4096) == 0);
4942 memset(payload_write
, 0xE5, sizeof(payload_write
));
4943 spdk_blob_io_write(blob
, channel
, payload_write
, 4, 10, blob_op_complete
, NULL
);
4945 CU_ASSERT(g_bserrno
== 0);
4946 CU_ASSERT(free_clusters
!= spdk_bs_free_cluster_count(bs
));
4948 /* Create snapshot from blob */
4949 spdk_bs_create_snapshot(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
4951 CU_ASSERT(g_bserrno
== 0);
4952 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
4953 snapshotid
= g_blobid
;
4955 spdk_bs_open_blob(bs
, snapshotid
, blob_op_with_handle_complete
, NULL
);
4957 CU_ASSERT(g_bserrno
== 0);
4958 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
4960 CU_ASSERT(snapshot
->data_ro
== true)
4961 CU_ASSERT(snapshot
->md_ro
== true)
4963 CU_ASSERT(spdk_blob_get_num_clusters(snapshot
) == 5)
4965 write_bytes
= g_dev_write_bytes
;
4966 read_bytes
= g_dev_read_bytes
;
4968 memset(payload_write
, 0xAA, sizeof(payload_write
));
4969 spdk_blob_io_write(blob
, channel
, payload_write
, 4, 10, blob_op_complete
, NULL
);
4971 CU_ASSERT(g_bserrno
== 0);
4972 CU_ASSERT(free_clusters
!= spdk_bs_free_cluster_count(bs
));
4974 /* For a clone we need to allocate and copy one cluster, update one page of metadata
4975 * and then write 10 pages of payload.
4977 CU_ASSERT(g_dev_write_bytes
- write_bytes
== page_size
* 11 + cluster_size
);
4978 CU_ASSERT(g_dev_read_bytes
- read_bytes
== cluster_size
);
4980 spdk_blob_io_read(blob
, channel
, payload_read
, 4, 10, blob_op_complete
, NULL
);
4982 CU_ASSERT(g_bserrno
== 0);
4983 CU_ASSERT(memcmp(payload_write
, payload_read
, 10 * 4096) == 0);
4985 /* Data on snapshot should not change after write to clone */
4986 memset(payload_write
, 0xE5, sizeof(payload_write
));
4987 spdk_blob_io_read(snapshot
, channel
, payload_read
, 4, 10, blob_op_complete
, NULL
);
4989 CU_ASSERT(g_bserrno
== 0);
4990 CU_ASSERT(memcmp(payload_write
, payload_read
, 10 * 4096) == 0);
4992 spdk_blob_close(blob
, blob_op_complete
, NULL
);
4994 CU_ASSERT(g_bserrno
== 0);
4996 spdk_blob_close(snapshot
, blob_op_complete
, NULL
);
4998 CU_ASSERT(g_bserrno
== 0);
5000 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
5002 CU_ASSERT(g_bserrno
== 0);
5004 spdk_bs_delete_blob(bs
, snapshotid
, blob_op_complete
, NULL
);
5006 CU_ASSERT(g_bserrno
== 0);
5008 spdk_bs_free_io_channel(channel
);
5011 /* Unload the blob store */
5012 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
5014 CU_ASSERT(g_bserrno
== 0);
5021 blob_snapshot_rw_iov(void)
5023 static const uint8_t zero
[10 * 4096] = { 0 };
5024 struct spdk_blob_store
*bs
;
5025 struct spdk_bs_dev
*dev
;
5026 struct spdk_blob
*blob
, *snapshot
;
5027 struct spdk_io_channel
*channel
;
5028 struct spdk_blob_opts opts
;
5029 spdk_blob_id blobid
, snapshotid
;
5030 uint64_t free_clusters
;
5031 uint8_t payload_read
[10 * 4096];
5032 uint8_t payload_write
[10 * 4096];
5033 struct iovec iov_read
[3];
5034 struct iovec iov_write
[3];
5038 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
5040 CU_ASSERT(g_bserrno
== 0);
5041 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
5043 free_clusters
= spdk_bs_free_cluster_count(bs
);
5045 channel
= spdk_bs_alloc_io_channel(bs
);
5046 CU_ASSERT(channel
!= NULL
);
5048 spdk_blob_opts_init(&opts
);
5049 opts
.thin_provision
= true;
5050 opts
.num_clusters
= 5;
5052 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
5054 CU_ASSERT(g_bserrno
== 0);
5055 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
5056 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
5059 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
5061 CU_ASSERT(g_bserrno
== 0);
5062 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
5065 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 5);
5067 /* Create snapshot from blob */
5068 spdk_bs_create_snapshot(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
5070 CU_ASSERT(g_bserrno
== 0);
5071 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
5072 snapshotid
= g_blobid
;
5074 spdk_bs_open_blob(bs
, snapshotid
, blob_op_with_handle_complete
, NULL
);
5076 CU_ASSERT(g_bserrno
== 0);
5077 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
5079 CU_ASSERT(snapshot
->data_ro
== true)
5080 CU_ASSERT(snapshot
->md_ro
== true)
5081 CU_ASSERT(spdk_blob_get_num_clusters(snapshot
) == 5);
5083 /* Payload should be all zeros from unallocated clusters */
5084 memset(payload_read
, 0xAA, sizeof(payload_read
));
5085 iov_read
[0].iov_base
= payload_read
;
5086 iov_read
[0].iov_len
= 3 * 4096;
5087 iov_read
[1].iov_base
= payload_read
+ 3 * 4096;
5088 iov_read
[1].iov_len
= 4 * 4096;
5089 iov_read
[2].iov_base
= payload_read
+ 7 * 4096;
5090 iov_read
[2].iov_len
= 3 * 4096;
5091 spdk_blob_io_readv(blob
, channel
, iov_read
, 3, 250, 10, blob_op_complete
, NULL
);
5093 CU_ASSERT(g_bserrno
== 0);
5094 CU_ASSERT(memcmp(zero
, payload_read
, 10 * 4096) == 0);
5096 memset(payload_write
, 0xE5, sizeof(payload_write
));
5097 iov_write
[0].iov_base
= payload_write
;
5098 iov_write
[0].iov_len
= 1 * 4096;
5099 iov_write
[1].iov_base
= payload_write
+ 1 * 4096;
5100 iov_write
[1].iov_len
= 5 * 4096;
5101 iov_write
[2].iov_base
= payload_write
+ 6 * 4096;
5102 iov_write
[2].iov_len
= 4 * 4096;
5104 spdk_blob_io_writev(blob
, channel
, iov_write
, 3, 250, 10, blob_op_complete
, NULL
);
5106 CU_ASSERT(g_bserrno
== 0);
5108 memset(payload_read
, 0xAA, sizeof(payload_read
));
5109 iov_read
[0].iov_base
= payload_read
;
5110 iov_read
[0].iov_len
= 3 * 4096;
5111 iov_read
[1].iov_base
= payload_read
+ 3 * 4096;
5112 iov_read
[1].iov_len
= 4 * 4096;
5113 iov_read
[2].iov_base
= payload_read
+ 7 * 4096;
5114 iov_read
[2].iov_len
= 3 * 4096;
5115 spdk_blob_io_readv(blob
, channel
, iov_read
, 3, 250, 10, blob_op_complete
, NULL
);
5117 CU_ASSERT(g_bserrno
== 0);
5118 CU_ASSERT(memcmp(payload_write
, payload_read
, 10 * 4096) == 0);
5120 spdk_blob_close(blob
, blob_op_complete
, NULL
);
5122 CU_ASSERT(g_bserrno
== 0);
5124 spdk_blob_close(snapshot
, blob_op_complete
, NULL
);
5126 CU_ASSERT(g_bserrno
== 0);
5128 spdk_bs_free_io_channel(channel
);
5131 /* Unload the blob store */
5132 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
5134 CU_ASSERT(g_bserrno
== 0);
5141 * Inflate / decouple parent rw unit tests.
5144 * original blob: 0 1 2 3 4
5145 * ,---------+---------+---------+---------+---------.
5146 * snapshot |xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx| - |
5147 * +---------+---------+---------+---------+---------+
5148 * snapshot2 | - |yyyyyyyyy| - |yyyyyyyyy| - |
5149 * +---------+---------+---------+---------+---------+
5150 * blob | - |zzzzzzzzz| - | - | - |
5151 * '---------+---------+---------+---------+---------'
5153 * -------- . . . . . .
5154 * inflate: . . . . . .
5155 * ,---------+---------+---------+---------+---------.
5156 * blob |xxxxxxxxx|zzzzzzzzz|xxxxxxxxx|yyyyyyyyy|000000000|
5157 * '---------+---------+---------+---------+---------'
5159 * NOTE: needs to allocate 4 clusters, thin provisioning removed, dependency
5160 * on snapshot2 and snapshot removed . . .
5162 * ---------------- . . . . . .
5163 * decouple parent: . . . . . .
5164 * ,---------+---------+---------+---------+---------.
5165 * snapshot |xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx| - |
5166 * +---------+---------+---------+---------+---------+
5167 * blob | - |zzzzzzzzz| - |yyyyyyyyy| - |
5168 * '---------+---------+---------+---------+---------'
5170 * NOTE: needs to allocate 1 cluster, 3 clusters unallocated, dependency
5171 * on snapshot2 removed and on snapshot still exists. Snapshot2
5172 * should remain a clone of snapshot.
5175 _blob_inflate_rw(bool decouple_parent
)
5177 struct spdk_blob_store
*bs
;
5178 struct spdk_bs_dev
*dev
;
5179 struct spdk_blob
*blob
, *snapshot
, *snapshot2
;
5180 struct spdk_io_channel
*channel
;
5181 struct spdk_blob_opts opts
;
5182 spdk_blob_id blobid
, snapshotid
, snapshot2id
;
5183 uint64_t free_clusters
;
5184 uint64_t cluster_size
;
5186 uint64_t payload_size
;
5187 uint8_t *payload_read
;
5188 uint8_t *payload_write
;
5189 uint8_t *payload_clone
;
5191 uint64_t pages_per_cluster
;
5192 uint64_t pages_per_payload
;
5195 spdk_blob_id ids
[2];
5200 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
5202 CU_ASSERT(g_bserrno
== 0);
5203 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
5206 free_clusters
= spdk_bs_free_cluster_count(bs
);
5207 cluster_size
= spdk_bs_get_cluster_size(bs
);
5208 pages_per_cluster
= cluster_size
/ spdk_bs_get_page_size(bs
);
5209 pages_per_payload
= pages_per_cluster
* 5;
5211 payload_size
= cluster_size
* 5;
5213 payload_read
= malloc(payload_size
);
5214 SPDK_CU_ASSERT_FATAL(payload_read
!= NULL
);
5216 payload_write
= malloc(payload_size
);
5217 SPDK_CU_ASSERT_FATAL(payload_write
!= NULL
);
5219 payload_clone
= malloc(payload_size
);
5220 SPDK_CU_ASSERT_FATAL(payload_clone
!= NULL
);
5222 channel
= spdk_bs_alloc_io_channel(bs
);
5223 SPDK_CU_ASSERT_FATAL(channel
!= NULL
);
5226 spdk_blob_opts_init(&opts
);
5227 opts
.thin_provision
= true;
5228 opts
.num_clusters
= 5;
5230 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
5232 CU_ASSERT(g_bserrno
== 0);
5233 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
5234 CU_ASSERT(free_clusters
== spdk_bs_free_cluster_count(bs
));
5237 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
5239 CU_ASSERT(g_bserrno
== 0);
5240 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
5243 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 5);
5245 /* 1) Initial read should return zeroed payload */
5246 memset(payload_read
, 0xFF, payload_size
);
5247 spdk_blob_io_read(blob
, channel
, payload_read
, 0, pages_per_payload
,
5248 blob_op_complete
, NULL
);
5250 CU_ASSERT(g_bserrno
== 0);
5251 CU_ASSERT(spdk_mem_all_zero(payload_read
, payload_size
));
5253 /* Fill whole blob with a pattern, except last cluster (to be sure it
5254 * isn't allocated) */
5255 memset(payload_write
, 0xE5, payload_size
- cluster_size
);
5256 spdk_blob_io_write(blob
, channel
, payload_write
, 0, pages_per_payload
-
5257 pages_per_cluster
, blob_op_complete
, NULL
);
5259 CU_ASSERT(g_bserrno
== 0);
5260 CU_ASSERT(free_clusters
!= spdk_bs_free_cluster_count(bs
));
5262 /* 2) Create snapshot from blob (first level) */
5263 spdk_bs_create_snapshot(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
5265 CU_ASSERT(g_bserrno
== 0);
5266 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
5267 snapshotid
= g_blobid
;
5269 spdk_bs_open_blob(bs
, snapshotid
, blob_op_with_handle_complete
, NULL
);
5271 CU_ASSERT(g_bserrno
== 0);
5272 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
5274 CU_ASSERT(snapshot
->data_ro
== true)
5275 CU_ASSERT(snapshot
->md_ro
== true)
5277 CU_ASSERT(spdk_blob_get_num_clusters(snapshot
) == 5)
5279 /* Write every second cluster with a pattern.
5281 * Last cluster shouldn't be written, to be sure that snapshot nor clone
5282 * doesn't allocate it.
5284 * payload_clone stores expected result on "blob" read at the time and
5285 * is used only to check data consistency on clone before and after
5286 * inflation. Initially we fill it with a backing snapshots pattern
5289 memset(payload_clone
, 0xE5, payload_size
- cluster_size
);
5290 memset(payload_clone
+ payload_size
- cluster_size
, 0x00, cluster_size
);
5291 memset(payload_write
, 0xAA, payload_size
);
5292 for (i
= 1; i
< 5; i
+= 2) {
5293 spdk_blob_io_write(blob
, channel
, payload_write
, i
* pages_per_cluster
,
5294 pages_per_cluster
, blob_op_complete
, NULL
);
5296 CU_ASSERT(g_bserrno
== 0);
5298 /* Update expected result */
5299 memcpy(payload_clone
+ (cluster_size
* i
), payload_write
,
5302 CU_ASSERT(free_clusters
!= spdk_bs_free_cluster_count(bs
));
5304 /* Check data consistency on clone */
5305 memset(payload_read
, 0xFF, payload_size
);
5306 spdk_blob_io_read(blob
, channel
, payload_read
, 0, pages_per_payload
,
5307 blob_op_complete
, NULL
);
5309 CU_ASSERT(g_bserrno
== 0);
5310 CU_ASSERT(memcmp(payload_clone
, payload_read
, payload_size
) == 0);
5312 /* 3) Create second levels snapshot from blob */
5313 spdk_bs_create_snapshot(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
5315 CU_ASSERT(g_bserrno
== 0);
5316 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
5317 snapshot2id
= g_blobid
;
5319 spdk_bs_open_blob(bs
, snapshot2id
, blob_op_with_handle_complete
, NULL
);
5321 CU_ASSERT(g_bserrno
== 0);
5322 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
5324 CU_ASSERT(snapshot2
->data_ro
== true)
5325 CU_ASSERT(snapshot2
->md_ro
== true)
5327 CU_ASSERT(spdk_blob_get_num_clusters(snapshot2
) == 5)
5329 CU_ASSERT(snapshot2
->parent_id
== snapshotid
);
5331 /* Write one cluster on the top level blob. This cluster (1) covers
5332 * already allocated cluster in the snapshot2, so shouldn't be inflated
5334 spdk_blob_io_write(blob
, channel
, payload_write
, pages_per_cluster
,
5335 pages_per_cluster
, blob_op_complete
, NULL
);
5337 CU_ASSERT(g_bserrno
== 0);
5339 /* Update expected result */
5340 memcpy(payload_clone
+ cluster_size
, payload_write
, cluster_size
);
5342 /* Check data consistency on clone */
5343 memset(payload_read
, 0xFF, payload_size
);
5344 spdk_blob_io_read(blob
, channel
, payload_read
, 0, pages_per_payload
,
5345 blob_op_complete
, NULL
);
5347 CU_ASSERT(g_bserrno
== 0);
5348 CU_ASSERT(memcmp(payload_clone
, payload_read
, payload_size
) == 0);
5351 /* Close all blobs */
5352 spdk_blob_close(blob
, blob_op_complete
, NULL
);
5354 CU_ASSERT(g_bserrno
== 0);
5356 spdk_blob_close(snapshot2
, blob_op_complete
, NULL
);
5358 CU_ASSERT(g_bserrno
== 0);
5360 spdk_blob_close(snapshot
, blob_op_complete
, NULL
);
5362 CU_ASSERT(g_bserrno
== 0);
5364 /* Check snapshot-clone relations */
5366 CU_ASSERT(spdk_blob_get_clones(bs
, snapshotid
, ids
, &count
) == 0);
5367 CU_ASSERT(count
== 1);
5368 CU_ASSERT(ids
[0] == snapshot2id
);
5371 CU_ASSERT(spdk_blob_get_clones(bs
, snapshot2id
, ids
, &count
) == 0);
5372 CU_ASSERT(count
== 1);
5373 CU_ASSERT(ids
[0] == blobid
);
5375 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, blobid
) == snapshot2id
);
5377 free_clusters
= spdk_bs_free_cluster_count(bs
);
5378 if (!decouple_parent
) {
5379 /* Do full blob inflation */
5380 spdk_bs_inflate_blob(bs
, channel
, blobid
, blob_op_complete
, NULL
);
5382 CU_ASSERT(g_bserrno
== 0);
5384 /* All clusters should be inflated (except one already allocated
5385 * in a top level blob) */
5386 CU_ASSERT(spdk_bs_free_cluster_count(bs
) == free_clusters
- 4);
5388 /* Check if relation tree updated correctly */
5390 CU_ASSERT(spdk_blob_get_clones(bs
, snapshotid
, ids
, &count
) == 0);
5392 /* snapshotid have one clone */
5393 CU_ASSERT(count
== 1);
5394 CU_ASSERT(ids
[0] == snapshot2id
);
5396 /* snapshot2id have no clones */
5398 CU_ASSERT(spdk_blob_get_clones(bs
, snapshot2id
, ids
, &count
) == 0);
5399 CU_ASSERT(count
== 0);
5401 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, blobid
) == SPDK_BLOBID_INVALID
);
5403 /* Decouple parent of blob */
5404 spdk_bs_blob_decouple_parent(bs
, channel
, blobid
, blob_op_complete
, NULL
);
5406 CU_ASSERT(g_bserrno
== 0);
5408 /* Only one cluster from a parent should be inflated (second one
5409 * is covered by a cluster written on a top level blob, and
5410 * already allocated) */
5411 CU_ASSERT(spdk_bs_free_cluster_count(bs
) == free_clusters
- 1);
5413 /* Check if relation tree updated correctly */
5415 CU_ASSERT(spdk_blob_get_clones(bs
, snapshotid
, ids
, &count
) == 0);
5417 /* snapshotid have two clones now */
5418 CU_ASSERT(count
== 2);
5419 CU_ASSERT(ids
[0] == blobid
|| ids
[1] == blobid
);
5420 CU_ASSERT(ids
[0] == snapshot2id
|| ids
[1] == snapshot2id
);
5422 /* snapshot2id have no clones */
5424 CU_ASSERT(spdk_blob_get_clones(bs
, snapshot2id
, ids
, &count
) == 0);
5425 CU_ASSERT(count
== 0);
5427 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, blobid
) == snapshotid
);
5430 /* Try to delete snapshot2 (should pass) */
5431 spdk_bs_delete_blob(bs
, snapshot2id
, blob_op_complete
, NULL
);
5433 CU_ASSERT(g_bserrno
== 0);
5435 /* Try to delete base snapshot (for decouple_parent should fail while
5436 * dependency still exists) */
5437 spdk_bs_delete_blob(bs
, snapshotid
, blob_op_complete
, NULL
);
5439 CU_ASSERT(decouple_parent
|| g_bserrno
== 0);
5440 CU_ASSERT(!decouple_parent
|| g_bserrno
!= 0);
5442 /* Reopen blob after snapshot deletion */
5443 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
5445 CU_ASSERT(g_bserrno
== 0);
5446 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
5449 CU_ASSERT(spdk_blob_get_num_clusters(blob
) == 5);
5451 /* Check data consistency on inflated blob */
5452 memset(payload_read
, 0xFF, payload_size
);
5453 spdk_blob_io_read(blob
, channel
, payload_read
, 0, pages_per_payload
,
5454 blob_op_complete
, NULL
);
5456 CU_ASSERT(g_bserrno
== 0);
5457 CU_ASSERT(memcmp(payload_clone
, payload_read
, payload_size
) == 0);
5459 spdk_blob_close(blob
, blob_op_complete
, NULL
);
5461 CU_ASSERT(g_bserrno
== 0);
5463 spdk_bs_free_io_channel(channel
);
5466 /* Unload the blob store */
5467 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
5469 CU_ASSERT(g_bserrno
== 0);
5475 free(payload_write
);
5476 free(payload_clone
);
5480 blob_inflate_rw(void)
5482 _blob_inflate_rw(false);
5483 _blob_inflate_rw(true);
5487 * Snapshot-clones relation test
5493 * blob(ro) snapshot2
5498 blob_relations(void)
5500 struct spdk_blob_store
*bs
;
5501 struct spdk_bs_dev
*dev
;
5502 struct spdk_bs_opts bs_opts
;
5503 struct spdk_blob_opts opts
;
5504 struct spdk_blob
*blob
, *snapshot
, *snapshot2
, *clone
, *clone2
;
5505 spdk_blob_id blobid
, cloneid
, snapshotid
, cloneid2
, snapshotid2
;
5508 spdk_blob_id ids
[10] = {};
5511 spdk_bs_opts_init(&bs_opts
);
5512 snprintf(bs_opts
.bstype
.bstype
, sizeof(bs_opts
.bstype
.bstype
), "TESTTYPE");
5514 spdk_bs_init(dev
, &bs_opts
, bs_op_with_handle_complete
, NULL
);
5516 CU_ASSERT(g_bserrno
== 0);
5517 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
5520 /* 1. Create blob with 10 clusters */
5522 spdk_blob_opts_init(&opts
);
5523 opts
.num_clusters
= 10;
5525 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
5527 CU_ASSERT(g_bserrno
== 0);
5528 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
5531 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
5533 CU_ASSERT(g_bserrno
== 0);
5534 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
5537 CU_ASSERT(!spdk_blob_is_read_only(blob
));
5538 CU_ASSERT(!spdk_blob_is_snapshot(blob
));
5539 CU_ASSERT(!spdk_blob_is_clone(blob
));
5540 CU_ASSERT(!spdk_blob_is_thin_provisioned(blob
));
5542 /* blob should not have underlying snapshot nor clones */
5543 CU_ASSERT(blob
->parent_id
== SPDK_BLOBID_INVALID
);
5544 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, blobid
) == SPDK_BLOBID_INVALID
);
5545 count
= SPDK_COUNTOF(ids
);
5546 rc
= spdk_blob_get_clones(bs
, blobid
, ids
, &count
);
5548 CU_ASSERT(count
== 0);
5551 /* 2. Create snapshot */
5553 spdk_bs_create_snapshot(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
5555 CU_ASSERT(g_bserrno
== 0);
5556 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
5557 snapshotid
= g_blobid
;
5559 spdk_bs_open_blob(bs
, snapshotid
, blob_op_with_handle_complete
, NULL
);
5561 CU_ASSERT(g_bserrno
== 0);
5562 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
5565 CU_ASSERT(spdk_blob_is_read_only(snapshot
));
5566 CU_ASSERT(spdk_blob_is_snapshot(snapshot
));
5567 CU_ASSERT(!spdk_blob_is_clone(snapshot
));
5568 CU_ASSERT(snapshot
->parent_id
== SPDK_BLOBID_INVALID
);
5569 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, snapshotid
) == SPDK_BLOBID_INVALID
);
5571 /* Check if original blob is converted to the clone of snapshot */
5572 CU_ASSERT(!spdk_blob_is_read_only(blob
));
5573 CU_ASSERT(!spdk_blob_is_snapshot(blob
));
5574 CU_ASSERT(spdk_blob_is_clone(blob
));
5575 CU_ASSERT(spdk_blob_is_thin_provisioned(blob
));
5576 CU_ASSERT(blob
->parent_id
== snapshotid
);
5577 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, blobid
) == snapshotid
);
5579 count
= SPDK_COUNTOF(ids
);
5580 rc
= spdk_blob_get_clones(bs
, snapshotid
, ids
, &count
);
5582 CU_ASSERT(count
== 1);
5583 CU_ASSERT(ids
[0] == blobid
);
5586 /* 3. Create clone from snapshot */
5588 spdk_bs_create_clone(bs
, snapshotid
, NULL
, blob_op_with_id_complete
, NULL
);
5590 CU_ASSERT(g_bserrno
== 0);
5591 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
5594 spdk_bs_open_blob(bs
, cloneid
, blob_op_with_handle_complete
, NULL
);
5596 CU_ASSERT(g_bserrno
== 0);
5597 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
5600 CU_ASSERT(!spdk_blob_is_read_only(clone
));
5601 CU_ASSERT(!spdk_blob_is_snapshot(clone
));
5602 CU_ASSERT(spdk_blob_is_clone(clone
));
5603 CU_ASSERT(spdk_blob_is_thin_provisioned(clone
));
5604 CU_ASSERT(clone
->parent_id
== snapshotid
);
5605 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, cloneid
) == snapshotid
);
5607 count
= SPDK_COUNTOF(ids
);
5608 rc
= spdk_blob_get_clones(bs
, cloneid
, ids
, &count
);
5610 CU_ASSERT(count
== 0);
5612 /* Check if clone is on the snapshot's list */
5613 count
= SPDK_COUNTOF(ids
);
5614 rc
= spdk_blob_get_clones(bs
, snapshotid
, ids
, &count
);
5616 CU_ASSERT(ids
[0] == blobid
|| ids
[1] == blobid
);
5617 CU_ASSERT(ids
[0] == cloneid
|| ids
[1] == cloneid
);
5620 /* 4. Create snapshot of the clone */
5622 spdk_bs_create_snapshot(bs
, cloneid
, NULL
, blob_op_with_id_complete
, NULL
);
5624 CU_ASSERT(g_bserrno
== 0);
5625 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
5626 snapshotid2
= g_blobid
;
5628 spdk_bs_open_blob(bs
, snapshotid2
, blob_op_with_handle_complete
, NULL
);
5630 CU_ASSERT(g_bserrno
== 0);
5631 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
5634 CU_ASSERT(spdk_blob_is_read_only(snapshot2
));
5635 CU_ASSERT(spdk_blob_is_snapshot(snapshot2
));
5636 CU_ASSERT(spdk_blob_is_clone(snapshot2
));
5637 CU_ASSERT(snapshot2
->parent_id
== snapshotid
);
5638 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, snapshotid2
) == snapshotid
);
5640 /* Check if clone is converted to the clone of snapshot2 and snapshot2
5641 * is a child of snapshot */
5642 CU_ASSERT(!spdk_blob_is_read_only(clone
));
5643 CU_ASSERT(!spdk_blob_is_snapshot(clone
));
5644 CU_ASSERT(spdk_blob_is_clone(clone
));
5645 CU_ASSERT(spdk_blob_is_thin_provisioned(clone
));
5646 CU_ASSERT(clone
->parent_id
== snapshotid2
);
5647 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, cloneid
) == snapshotid2
);
5649 count
= SPDK_COUNTOF(ids
);
5650 rc
= spdk_blob_get_clones(bs
, snapshotid2
, ids
, &count
);
5652 CU_ASSERT(count
== 1);
5653 CU_ASSERT(ids
[0] == cloneid
);
5656 /* 5. Try to create clone from read only blob */
5658 /* Mark blob as read only */
5659 spdk_blob_set_read_only(blob
);
5660 spdk_blob_sync_md(blob
, blob_op_complete
, NULL
);
5662 CU_ASSERT(g_bserrno
== 0);
5664 /* Check if previously created blob is read only clone */
5665 CU_ASSERT(spdk_blob_is_read_only(blob
));
5666 CU_ASSERT(!spdk_blob_is_snapshot(blob
));
5667 CU_ASSERT(spdk_blob_is_clone(blob
));
5668 CU_ASSERT(spdk_blob_is_thin_provisioned(blob
));
5670 /* Create clone from read only blob */
5671 spdk_bs_create_clone(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
5673 CU_ASSERT(g_bserrno
== 0);
5674 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
5675 cloneid2
= g_blobid
;
5677 spdk_bs_open_blob(bs
, cloneid2
, blob_op_with_handle_complete
, NULL
);
5679 CU_ASSERT(g_bserrno
== 0);
5680 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
5683 CU_ASSERT(!spdk_blob_is_read_only(clone2
));
5684 CU_ASSERT(!spdk_blob_is_snapshot(clone2
));
5685 CU_ASSERT(spdk_blob_is_clone(clone2
));
5686 CU_ASSERT(spdk_blob_is_thin_provisioned(clone2
));
5688 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, cloneid2
) == blobid
);
5690 count
= SPDK_COUNTOF(ids
);
5691 rc
= spdk_blob_get_clones(bs
, blobid
, ids
, &count
);
5694 CU_ASSERT(count
== 1);
5695 CU_ASSERT(ids
[0] == cloneid2
);
5699 spdk_blob_close(clone2
, blob_op_complete
, NULL
);
5701 CU_ASSERT(g_bserrno
== 0);
5703 spdk_blob_close(blob
, blob_op_complete
, NULL
);
5705 CU_ASSERT(g_bserrno
== 0);
5707 spdk_blob_close(clone
, blob_op_complete
, NULL
);
5709 CU_ASSERT(g_bserrno
== 0);
5711 spdk_blob_close(snapshot
, blob_op_complete
, NULL
);
5713 CU_ASSERT(g_bserrno
== 0);
5715 spdk_blob_close(snapshot2
, blob_op_complete
, NULL
);
5717 CU_ASSERT(g_bserrno
== 0);
5719 /* Try to delete snapshot with created clones */
5720 spdk_bs_delete_blob(bs
, snapshotid
, blob_op_complete
, NULL
);
5722 CU_ASSERT(g_bserrno
!= 0);
5724 spdk_bs_delete_blob(bs
, snapshotid2
, blob_op_complete
, NULL
);
5726 CU_ASSERT(g_bserrno
!= 0);
5728 spdk_bs_unload(bs
, bs_op_complete
, NULL
);
5730 CU_ASSERT(g_bserrno
== 0);
5733 /* Load an existing blob store */
5735 snprintf(bs_opts
.bstype
.bstype
, sizeof(bs_opts
.bstype
.bstype
), "TESTTYPE");
5737 spdk_bs_load(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
5739 CU_ASSERT(g_bserrno
== 0);
5740 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
5744 /* NULL ids array should return number of clones in count */
5745 count
= SPDK_COUNTOF(ids
);
5746 rc
= spdk_blob_get_clones(bs
, snapshotid
, NULL
, &count
);
5747 CU_ASSERT(rc
== -ENOMEM
);
5748 CU_ASSERT(count
== 2);
5750 /* incorrect array size */
5752 rc
= spdk_blob_get_clones(bs
, snapshotid
, ids
, &count
);
5753 CU_ASSERT(rc
== -ENOMEM
);
5754 CU_ASSERT(count
== 2);
5757 /* Verify structure of loaded blob store */
5760 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, snapshotid
) == SPDK_BLOBID_INVALID
);
5762 count
= SPDK_COUNTOF(ids
);
5763 rc
= spdk_blob_get_clones(bs
, snapshotid
, ids
, &count
);
5765 CU_ASSERT(count
== 2);
5766 CU_ASSERT(ids
[0] == blobid
|| ids
[1] == blobid
);
5767 CU_ASSERT(ids
[0] == snapshotid2
|| ids
[1] == snapshotid2
);
5770 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, blobid
) == snapshotid
);
5771 count
= SPDK_COUNTOF(ids
);
5772 rc
= spdk_blob_get_clones(bs
, blobid
, ids
, &count
);
5774 CU_ASSERT(count
== 1);
5775 CU_ASSERT(ids
[0] == cloneid2
);
5778 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, cloneid
) == snapshotid2
);
5779 count
= SPDK_COUNTOF(ids
);
5780 rc
= spdk_blob_get_clones(bs
, cloneid
, ids
, &count
);
5782 CU_ASSERT(count
== 0);
5785 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, snapshotid2
) == snapshotid
);
5786 count
= SPDK_COUNTOF(ids
);
5787 rc
= spdk_blob_get_clones(bs
, snapshotid2
, ids
, &count
);
5789 CU_ASSERT(count
== 1);
5790 CU_ASSERT(ids
[0] == cloneid
);
5793 CU_ASSERT(spdk_blob_get_parent_snapshot(bs
, cloneid2
) == blobid
);
5794 count
= SPDK_COUNTOF(ids
);
5795 rc
= spdk_blob_get_clones(bs
, cloneid2
, ids
, &count
);
5797 CU_ASSERT(count
== 0);
5799 /* Try to delete all blobs in the worse possible order */
5801 spdk_bs_delete_blob(bs
, snapshotid
, blob_op_complete
, NULL
);
5803 CU_ASSERT(g_bserrno
!= 0);
5805 spdk_bs_delete_blob(bs
, snapshotid2
, blob_op_complete
, NULL
);
5807 CU_ASSERT(g_bserrno
!= 0);
5809 spdk_bs_delete_blob(bs
, cloneid
, blob_op_complete
, NULL
);
5811 CU_ASSERT(g_bserrno
== 0);
5813 spdk_bs_delete_blob(bs
, snapshotid2
, blob_op_complete
, NULL
);
5815 CU_ASSERT(g_bserrno
== 0);
5817 spdk_bs_delete_blob(bs
, snapshotid
, blob_op_complete
, NULL
);
5819 CU_ASSERT(g_bserrno
!= 0);
5821 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
5823 CU_ASSERT(g_bserrno
!= 0);
5825 spdk_bs_delete_blob(bs
, cloneid2
, blob_op_complete
, NULL
);
5827 CU_ASSERT(g_bserrno
== 0);
5829 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
5831 CU_ASSERT(g_bserrno
== 0);
5833 spdk_bs_delete_blob(bs
, snapshotid
, blob_op_complete
, NULL
);
5835 CU_ASSERT(g_bserrno
== 0);
5837 spdk_bs_unload(bs
, bs_op_complete
, NULL
);
5839 CU_ASSERT(g_bserrno
== 0);
5845 test_io_write(struct spdk_bs_dev
*dev
, struct spdk_blob
*blob
, struct spdk_io_channel
*channel
)
5847 uint8_t payload_ff
[64 * 512];
5848 uint8_t payload_aa
[64 * 512];
5849 uint8_t payload_00
[64 * 512];
5850 uint8_t *cluster0
, *cluster1
;
5852 memset(payload_ff
, 0xFF, sizeof(payload_ff
));
5853 memset(payload_aa
, 0xAA, sizeof(payload_aa
));
5854 memset(payload_00
, 0x00, sizeof(payload_00
));
5856 /* Try to perform I/O with io unit = 512 */
5857 spdk_blob_io_write(blob
, channel
, payload_ff
, 0, 1, blob_op_complete
, NULL
);
5859 CU_ASSERT(g_bserrno
== 0);
5861 /* If thin provisioned is set cluster should be allocated now */
5862 SPDK_CU_ASSERT_FATAL(blob
->active
.clusters
[0] != 0);
5863 cluster0
= &g_dev_buffer
[blob
->active
.clusters
[0] * dev
->blocklen
];
5865 /* Each character 0-F symbolizes single io_unit containing 512 bytes block filled with that character.
5866 * Each page is separated by |. Whole block [...] symbolizes one cluster (containing 4 pages). */
5867 /* cluster0: [ F000 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
5868 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
5869 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 31 * 512) == 0);
5871 /* Verify write with offset on first page */
5872 spdk_blob_io_write(blob
, channel
, payload_ff
, 2, 1, blob_op_complete
, NULL
);
5874 CU_ASSERT(g_bserrno
== 0);
5876 /* cluster0: [ F0F0 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
5877 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
5878 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 512) == 0);
5879 CU_ASSERT(memcmp(cluster0
+ 2 * 512, payload_ff
, 512) == 0);
5880 CU_ASSERT(memcmp(cluster0
+ 3 * 512, payload_00
, 512) == 0);
5881 CU_ASSERT(memcmp(cluster0
+ 4 * 512, payload_00
, 28 * 512) == 0);
5883 /* Verify write with offset on first page */
5884 spdk_blob_io_write(blob
, channel
, payload_ff
, 4, 4, blob_op_complete
, NULL
);
5887 /* cluster0: [ F0F0 FFFF | 0000 0000 | 0000 0000 | 0000 0000 ] */
5888 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
5889 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 512) == 0);
5890 CU_ASSERT(memcmp(cluster0
+ 2 * 512, payload_ff
, 512) == 0);
5891 CU_ASSERT(memcmp(cluster0
+ 3 * 512, payload_00
, 512) == 0);
5892 CU_ASSERT(memcmp(cluster0
+ 4 * 512, payload_ff
, 4 * 512) == 0);
5893 CU_ASSERT(memcmp(cluster0
+ 8 * 512, payload_00
, 24 * 512) == 0);
5895 /* Verify write with offset on second page */
5896 spdk_blob_io_write(blob
, channel
, payload_ff
, 8, 4, blob_op_complete
, NULL
);
5899 /* cluster0: [ F0F0 FFFF | FFFF 0000 | 0000 0000 | 0000 0000 ] */
5900 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
5901 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 512) == 0);
5902 CU_ASSERT(memcmp(cluster0
+ 2 * 512, payload_ff
, 512) == 0);
5903 CU_ASSERT(memcmp(cluster0
+ 3 * 512, payload_00
, 512) == 0);
5904 CU_ASSERT(memcmp(cluster0
+ 4 * 512, payload_ff
, 8 * 512) == 0);
5905 CU_ASSERT(memcmp(cluster0
+ 12 * 512, payload_00
, 20 * 512) == 0);
5907 /* Verify write across multiple pages */
5908 spdk_blob_io_write(blob
, channel
, payload_aa
, 4, 8, blob_op_complete
, NULL
);
5911 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 0000 ] */
5912 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
5913 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 512) == 0);
5914 CU_ASSERT(memcmp(cluster0
+ 2 * 512, payload_ff
, 512) == 0);
5915 CU_ASSERT(memcmp(cluster0
+ 3 * 512, payload_00
, 512) == 0);
5916 CU_ASSERT(memcmp(cluster0
+ 4 * 512, payload_aa
, 8 * 512) == 0);
5917 CU_ASSERT(memcmp(cluster0
+ 12 * 512, payload_00
, 20 * 512) == 0);
5919 /* Verify write across multiple clusters */
5920 spdk_blob_io_write(blob
, channel
, payload_ff
, 28, 8, blob_op_complete
, NULL
);
5923 SPDK_CU_ASSERT_FATAL(blob
->active
.clusters
[1] != 0);
5924 cluster1
= &g_dev_buffer
[blob
->active
.clusters
[1] * dev
->blocklen
];
5926 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
5927 * cluster1: [ FFFF 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
5928 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
5929 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 512) == 0);
5930 CU_ASSERT(memcmp(cluster0
+ 2 * 512, payload_ff
, 512) == 0);
5931 CU_ASSERT(memcmp(cluster0
+ 3 * 512, payload_00
, 512) == 0);
5932 CU_ASSERT(memcmp(cluster0
+ 4 * 512, payload_aa
, 8 * 512) == 0);
5933 CU_ASSERT(memcmp(cluster0
+ 28 * 512, payload_ff
, 4 * 512) == 0);
5935 CU_ASSERT(memcmp(cluster1
+ 0 * 512, payload_ff
, 4 * 512) == 0);
5936 CU_ASSERT(memcmp(cluster1
+ 4 * 512, payload_00
, 28 * 512) == 0);
5938 /* Verify write to second cluster */
5939 spdk_blob_io_write(blob
, channel
, payload_ff
, 32 + 12, 2, blob_op_complete
, NULL
);
5942 SPDK_CU_ASSERT_FATAL(blob
->active
.clusters
[1] != 0);
5943 cluster1
= &g_dev_buffer
[blob
->active
.clusters
[1] * dev
->blocklen
];
5945 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
5946 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] */
5947 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
5948 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 512) == 0);
5949 CU_ASSERT(memcmp(cluster0
+ 2 * 512, payload_ff
, 512) == 0);
5950 CU_ASSERT(memcmp(cluster0
+ 3 * 512, payload_00
, 512) == 0);
5951 CU_ASSERT(memcmp(cluster0
+ 4 * 512, payload_aa
, 8 * 512) == 0);
5952 CU_ASSERT(memcmp(cluster0
+ 28 * 512, payload_ff
, 4 * 512) == 0);
5954 CU_ASSERT(memcmp(cluster1
+ 0 * 512, payload_ff
, 4 * 512) == 0);
5955 CU_ASSERT(memcmp(cluster1
+ 4 * 512, payload_00
, 8 * 512) == 0);
5956 CU_ASSERT(memcmp(cluster1
+ 12 * 512, payload_ff
, 2 * 512) == 0);
5957 CU_ASSERT(memcmp(cluster1
+ 14 * 512, payload_00
, 18 * 512) == 0);
5961 test_io_read(struct spdk_bs_dev
*dev
, struct spdk_blob
*blob
, struct spdk_io_channel
*channel
)
5963 uint8_t payload_read
[64 * 512];
5964 uint8_t payload_ff
[64 * 512];
5965 uint8_t payload_aa
[64 * 512];
5966 uint8_t payload_00
[64 * 512];
5968 memset(payload_ff
, 0xFF, sizeof(payload_ff
));
5969 memset(payload_aa
, 0xAA, sizeof(payload_aa
));
5970 memset(payload_00
, 0x00, sizeof(payload_00
));
5972 /* Read only first io unit */
5973 /* cluster0: [ (F)0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
5974 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
5975 * payload_read: F000 0000 | 0000 0000 ... */
5976 memset(payload_read
, 0x00, sizeof(payload_read
));
5977 spdk_blob_io_read(blob
, channel
, payload_read
, 0, 1, blob_op_complete
, NULL
);
5979 CU_ASSERT(g_bserrno
== 0);
5980 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_ff
, 512) == 0);
5981 CU_ASSERT(memcmp(payload_read
+ 1 * 512, payload_00
, 31 * 512) == 0);
5983 /* Read four io_units starting from offset = 2
5984 * cluster0: [ F0(F0 AA)AA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
5985 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
5986 * payload_read: F0AA 0000 | 0000 0000 ... */
5988 memset(payload_read
, 0x00, sizeof(payload_read
));
5989 spdk_blob_io_read(blob
, channel
, payload_read
, 2, 4, blob_op_complete
, NULL
);
5991 CU_ASSERT(g_bserrno
== 0);
5993 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_ff
, 512) == 0);
5994 CU_ASSERT(memcmp(payload_read
+ 1 * 512, payload_00
, 512) == 0);
5995 CU_ASSERT(memcmp(payload_read
+ 2 * 512, payload_aa
, 512) == 0);
5996 CU_ASSERT(memcmp(payload_read
+ 3 * 512, payload_aa
, 512) == 0);
5997 CU_ASSERT(memcmp(payload_read
+ 4 * 512, payload_00
, 28 * 512) == 0);
5999 /* Read eight io_units across multiple pages
6000 * cluster0: [ F0F0 (AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ]
6001 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
6002 * payload_read: AAAA AAAA | 0000 0000 ... */
6003 memset(payload_read
, 0x00, sizeof(payload_read
));
6004 spdk_blob_io_read(blob
, channel
, payload_read
, 4, 8, blob_op_complete
, NULL
);
6006 CU_ASSERT(g_bserrno
== 0);
6008 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_aa
, 8 * 512) == 0);
6009 CU_ASSERT(memcmp(payload_read
+ 8 * 512, payload_00
, 24 * 512) == 0);
6011 /* Read eight io_units across multiple clusters
6012 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 (FFFF ]
6013 * cluster1: [ FFFF) 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
6014 * payload_read: FFFF FFFF | 0000 0000 ... */
6015 memset(payload_read
, 0x00, sizeof(payload_read
));
6016 spdk_blob_io_read(blob
, channel
, payload_read
, 28, 8, blob_op_complete
, NULL
);
6018 CU_ASSERT(g_bserrno
== 0);
6020 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_ff
, 8 * 512) == 0);
6021 CU_ASSERT(memcmp(payload_read
+ 8 * 512, payload_00
, 24 * 512) == 0);
6023 /* Read four io_units from second cluster
6024 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6025 * cluster1: [ FFFF 0000 | 00(00 FF)00 | 0000 0000 | 0000 0000 ]
6026 * payload_read: 00FF 0000 | 0000 0000 ... */
6027 memset(payload_read
, 0x00, sizeof(payload_read
));
6028 spdk_blob_io_read(blob
, channel
, payload_read
, 32 + 10, 4, blob_op_complete
, NULL
);
6030 CU_ASSERT(g_bserrno
== 0);
6032 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_00
, 2 * 512) == 0);
6033 CU_ASSERT(memcmp(payload_read
+ 2 * 512, payload_ff
, 2 * 512) == 0);
6034 CU_ASSERT(memcmp(payload_read
+ 4 * 512, payload_00
, 28 * 512) == 0);
6036 /* Read second cluster
6037 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6038 * cluster1: [ (FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ]
6039 * payload_read: FFFF 0000 | 0000 FF00 ... */
6040 memset(payload_read
, 0x00, sizeof(payload_read
));
6041 spdk_blob_io_read(blob
, channel
, payload_read
, 32, 32, blob_op_complete
, NULL
);
6043 CU_ASSERT(g_bserrno
== 0);
6044 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_ff
, 4 * 512) == 0);
6045 CU_ASSERT(memcmp(payload_read
+ 4 * 512, payload_00
, 8 * 512) == 0);
6046 CU_ASSERT(memcmp(payload_read
+ 12 * 512, payload_ff
, 2 * 512) == 0);
6047 CU_ASSERT(memcmp(payload_read
+ 14 * 512, payload_00
, 18 * 512) == 0);
6049 /* Read whole two clusters
6050 * cluster0: [ (F0F0 AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ]
6051 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ] */
6052 memset(payload_read
, 0x00, sizeof(payload_read
));
6053 spdk_blob_io_read(blob
, channel
, payload_read
, 0, 64, blob_op_complete
, NULL
);
6055 CU_ASSERT(g_bserrno
== 0);
6057 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_ff
, 512) == 0);
6058 CU_ASSERT(memcmp(payload_read
+ 1 * 512, payload_00
, 512) == 0);
6059 CU_ASSERT(memcmp(payload_read
+ 2 * 512, payload_ff
, 512) == 0);
6060 CU_ASSERT(memcmp(payload_read
+ 3 * 512, payload_00
, 512) == 0);
6061 CU_ASSERT(memcmp(payload_read
+ 4 * 512, payload_aa
, 8 * 512) == 0);
6062 CU_ASSERT(memcmp(payload_read
+ 28 * 512, payload_ff
, 4 * 512) == 0);
6064 CU_ASSERT(memcmp(payload_read
+ (32 + 0) * 512, payload_ff
, 4 * 512) == 0);
6065 CU_ASSERT(memcmp(payload_read
+ (32 + 4) * 512, payload_00
, 8 * 512) == 0);
6066 CU_ASSERT(memcmp(payload_read
+ (32 + 12) * 512, payload_ff
, 2 * 512) == 0);
6067 CU_ASSERT(memcmp(payload_read
+ (32 + 14) * 512, payload_00
, 18 * 512) == 0);
6072 test_io_unmap(struct spdk_bs_dev
*dev
, struct spdk_blob
*blob
, struct spdk_io_channel
*channel
)
6074 uint8_t payload_ff
[64 * 512];
6075 uint8_t payload_aa
[64 * 512];
6076 uint8_t payload_00
[64 * 512];
6077 uint8_t *cluster0
, *cluster1
;
6079 memset(payload_ff
, 0xFF, sizeof(payload_ff
));
6080 memset(payload_aa
, 0xAA, sizeof(payload_aa
));
6081 memset(payload_00
, 0x00, sizeof(payload_00
));
6083 cluster0
= &g_dev_buffer
[blob
->active
.clusters
[0] * dev
->blocklen
];
6084 cluster1
= &g_dev_buffer
[blob
->active
.clusters
[1] * dev
->blocklen
];
6087 spdk_blob_io_unmap(blob
, channel
, 0, 64, blob_op_complete
, NULL
);
6090 CU_ASSERT(g_bserrno
== 0);
6092 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_00
, 32 * 512) == 0);
6093 CU_ASSERT(memcmp(cluster1
+ 0 * 512, payload_00
, 32 * 512) == 0);
6097 test_io_zeroes(struct spdk_bs_dev
*dev
, struct spdk_blob
*blob
, struct spdk_io_channel
*channel
)
6099 uint8_t payload_ff
[64 * 512];
6100 uint8_t payload_aa
[64 * 512];
6101 uint8_t payload_00
[64 * 512];
6102 uint8_t *cluster0
, *cluster1
;
6104 memset(payload_ff
, 0xFF, sizeof(payload_ff
));
6105 memset(payload_aa
, 0xAA, sizeof(payload_aa
));
6106 memset(payload_00
, 0x00, sizeof(payload_00
));
6108 cluster0
= &g_dev_buffer
[blob
->active
.clusters
[0] * dev
->blocklen
];
6109 cluster1
= &g_dev_buffer
[blob
->active
.clusters
[1] * dev
->blocklen
];
6112 spdk_blob_io_write_zeroes(blob
, channel
, 0, 64, blob_op_complete
, NULL
);
6115 CU_ASSERT(g_bserrno
== 0);
6117 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_00
, 32 * 512) == 0);
6118 CU_ASSERT(memcmp(cluster1
+ 0 * 512, payload_00
, 32 * 512) == 0);
6123 test_iov_write(struct spdk_bs_dev
*dev
, struct spdk_blob
*blob
, struct spdk_io_channel
*channel
)
6125 uint8_t payload_ff
[64 * 512];
6126 uint8_t payload_aa
[64 * 512];
6127 uint8_t payload_00
[64 * 512];
6128 uint8_t *cluster0
, *cluster1
;
6129 struct iovec iov
[4];
6131 memset(payload_ff
, 0xFF, sizeof(payload_ff
));
6132 memset(payload_aa
, 0xAA, sizeof(payload_aa
));
6133 memset(payload_00
, 0x00, sizeof(payload_00
));
6135 /* Try to perform I/O with io unit = 512 */
6136 iov
[0].iov_base
= payload_ff
;
6137 iov
[0].iov_len
= 1 * 512;
6138 spdk_blob_io_writev(blob
, channel
, iov
, 1, 0, 1, blob_op_complete
, NULL
);
6140 CU_ASSERT(g_bserrno
== 0);
6142 /* If thin provisioned is set cluster should be allocated now */
6143 SPDK_CU_ASSERT_FATAL(blob
->active
.clusters
[0] != 0);
6144 cluster0
= &g_dev_buffer
[blob
->active
.clusters
[0] * dev
->blocklen
];
6146 /* Each character 0-F symbolizes single io_unit containing 512 bytes block filled with that character.
6147 * Each page is separated by |. Whole block [...] symbolizes one cluster (containing 4 pages). */
6148 /* cluster0: [ F000 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
6149 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
6150 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 31 * 512) == 0);
6152 /* Verify write with offset on first page */
6153 iov
[0].iov_base
= payload_ff
;
6154 iov
[0].iov_len
= 1 * 512;
6155 spdk_blob_io_writev(blob
, channel
, iov
, 1, 2, 1, blob_op_complete
, NULL
);
6157 CU_ASSERT(g_bserrno
== 0);
6159 /* cluster0: [ F0F0 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
6160 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
6161 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 512) == 0);
6162 CU_ASSERT(memcmp(cluster0
+ 2 * 512, payload_ff
, 512) == 0);
6163 CU_ASSERT(memcmp(cluster0
+ 3 * 512, payload_00
, 512) == 0);
6164 CU_ASSERT(memcmp(cluster0
+ 4 * 512, payload_00
, 28 * 512) == 0);
6166 /* Verify write with offset on first page */
6167 iov
[0].iov_base
= payload_ff
;
6168 iov
[0].iov_len
= 4 * 512;
6169 spdk_blob_io_writev(blob
, channel
, iov
, 1, 4, 4, blob_op_complete
, NULL
);
6172 /* cluster0: [ F0F0 FFFF | 0000 0000 | 0000 0000 | 0000 0000 ] */
6173 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
6174 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 512) == 0);
6175 CU_ASSERT(memcmp(cluster0
+ 2 * 512, payload_ff
, 512) == 0);
6176 CU_ASSERT(memcmp(cluster0
+ 3 * 512, payload_00
, 512) == 0);
6177 CU_ASSERT(memcmp(cluster0
+ 4 * 512, payload_ff
, 4 * 512) == 0);
6178 CU_ASSERT(memcmp(cluster0
+ 8 * 512, payload_00
, 24 * 512) == 0);
6180 /* Verify write with offset on second page */
6181 iov
[0].iov_base
= payload_ff
;
6182 iov
[0].iov_len
= 4 * 512;
6183 spdk_blob_io_writev(blob
, channel
, iov
, 1, 8, 4, blob_op_complete
, NULL
);
6186 /* cluster0: [ F0F0 FFFF | FFFF 0000 | 0000 0000 | 0000 0000 ] */
6187 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
6188 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 512) == 0);
6189 CU_ASSERT(memcmp(cluster0
+ 2 * 512, payload_ff
, 512) == 0);
6190 CU_ASSERT(memcmp(cluster0
+ 3 * 512, payload_00
, 512) == 0);
6191 CU_ASSERT(memcmp(cluster0
+ 4 * 512, payload_ff
, 8 * 512) == 0);
6192 CU_ASSERT(memcmp(cluster0
+ 12 * 512, payload_00
, 20 * 512) == 0);
6194 /* Verify write across multiple pages */
6195 iov
[0].iov_base
= payload_aa
;
6196 iov
[0].iov_len
= 8 * 512;
6197 spdk_blob_io_writev(blob
, channel
, iov
, 1, 4, 8, blob_op_complete
, NULL
);
6200 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 0000 ] */
6201 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
6202 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 512) == 0);
6203 CU_ASSERT(memcmp(cluster0
+ 2 * 512, payload_ff
, 512) == 0);
6204 CU_ASSERT(memcmp(cluster0
+ 3 * 512, payload_00
, 512) == 0);
6205 CU_ASSERT(memcmp(cluster0
+ 4 * 512, payload_aa
, 8 * 512) == 0);
6206 CU_ASSERT(memcmp(cluster0
+ 12 * 512, payload_00
, 20 * 512) == 0);
6208 /* Verify write across multiple clusters */
6210 iov
[0].iov_base
= payload_ff
;
6211 iov
[0].iov_len
= 8 * 512;
6212 spdk_blob_io_writev(blob
, channel
, iov
, 1, 28, 8, blob_op_complete
, NULL
);
6215 SPDK_CU_ASSERT_FATAL(blob
->active
.clusters
[1] != 0);
6216 cluster1
= &g_dev_buffer
[blob
->active
.clusters
[1] * dev
->blocklen
];
6218 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6219 * cluster1: [ FFFF 0000 | 0000 0000 | 0000 0000 | 0000 0000 ] */
6220 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
6221 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 512) == 0);
6222 CU_ASSERT(memcmp(cluster0
+ 2 * 512, payload_ff
, 512) == 0);
6223 CU_ASSERT(memcmp(cluster0
+ 3 * 512, payload_00
, 512) == 0);
6224 CU_ASSERT(memcmp(cluster0
+ 4 * 512, payload_aa
, 8 * 512) == 0);
6225 CU_ASSERT(memcmp(cluster0
+ 12 * 512, payload_00
, 16 * 512) == 0);
6226 CU_ASSERT(memcmp(cluster0
+ 28 * 512, payload_ff
, 4 * 512) == 0);
6228 CU_ASSERT(memcmp(cluster1
+ 0 * 512, payload_ff
, 4 * 512) == 0);
6229 CU_ASSERT(memcmp(cluster1
+ 4 * 512, payload_00
, 28 * 512) == 0);
6231 /* Verify write to second cluster */
6233 iov
[0].iov_base
= payload_ff
;
6234 iov
[0].iov_len
= 2 * 512;
6235 spdk_blob_io_writev(blob
, channel
, iov
, 1, 32 + 12, 2, blob_op_complete
, NULL
);
6238 SPDK_CU_ASSERT_FATAL(blob
->active
.clusters
[1] != 0);
6239 cluster1
= &g_dev_buffer
[blob
->active
.clusters
[1] * dev
->blocklen
];
6241 /* cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6242 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ] */
6243 CU_ASSERT(memcmp(cluster0
+ 0 * 512, payload_ff
, 512) == 0);
6244 CU_ASSERT(memcmp(cluster0
+ 1 * 512, payload_00
, 512) == 0);
6245 CU_ASSERT(memcmp(cluster0
+ 2 * 512, payload_ff
, 512) == 0);
6246 CU_ASSERT(memcmp(cluster0
+ 3 * 512, payload_00
, 512) == 0);
6247 CU_ASSERT(memcmp(cluster0
+ 4 * 512, payload_aa
, 8 * 512) == 0);
6248 CU_ASSERT(memcmp(cluster0
+ 28 * 512, payload_ff
, 4 * 512) == 0);
6250 CU_ASSERT(memcmp(cluster1
+ 0 * 512, payload_ff
, 4 * 512) == 0);
6251 CU_ASSERT(memcmp(cluster1
+ 4 * 512, payload_00
, 8 * 512) == 0);
6252 CU_ASSERT(memcmp(cluster1
+ 12 * 512, payload_ff
, 2 * 512) == 0);
6253 CU_ASSERT(memcmp(cluster1
+ 14 * 512, payload_00
, 18 * 512) == 0);
6257 test_iov_read(struct spdk_bs_dev
*dev
, struct spdk_blob
*blob
, struct spdk_io_channel
*channel
)
6259 uint8_t payload_read
[64 * 512];
6260 uint8_t payload_ff
[64 * 512];
6261 uint8_t payload_aa
[64 * 512];
6262 uint8_t payload_00
[64 * 512];
6263 struct iovec iov
[4];
6265 memset(payload_ff
, 0xFF, sizeof(payload_ff
));
6266 memset(payload_aa
, 0xAA, sizeof(payload_aa
));
6267 memset(payload_00
, 0x00, sizeof(payload_00
));
6269 /* Read only first io unit */
6270 /* cluster0: [ (F)0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6271 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
6272 * payload_read: F000 0000 | 0000 0000 ... */
6273 memset(payload_read
, 0x00, sizeof(payload_read
));
6274 iov
[0].iov_base
= payload_read
;
6275 iov
[0].iov_len
= 1 * 512;
6276 spdk_blob_io_readv(blob
, channel
, iov
, 1, 0, 1, blob_op_complete
, NULL
);
6279 CU_ASSERT(g_bserrno
== 0);
6280 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_ff
, 512) == 0);
6281 CU_ASSERT(memcmp(payload_read
+ 1 * 512, payload_00
, 31 * 512) == 0);
6283 /* Read four io_units starting from offset = 2
6284 * cluster0: [ F0(F0 AA)AA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6285 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
6286 * payload_read: F0AA 0000 | 0000 0000 ... */
6288 memset(payload_read
, 0x00, sizeof(payload_read
));
6289 iov
[0].iov_base
= payload_read
;
6290 iov
[0].iov_len
= 4 * 512;
6291 spdk_blob_io_readv(blob
, channel
, iov
, 1, 2, 4, blob_op_complete
, NULL
);
6293 CU_ASSERT(g_bserrno
== 0);
6295 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_ff
, 512) == 0);
6296 CU_ASSERT(memcmp(payload_read
+ 1 * 512, payload_00
, 512) == 0);
6297 CU_ASSERT(memcmp(payload_read
+ 2 * 512, payload_aa
, 512) == 0);
6298 CU_ASSERT(memcmp(payload_read
+ 3 * 512, payload_aa
, 512) == 0);
6299 CU_ASSERT(memcmp(payload_read
+ 4 * 512, payload_00
, 28 * 512) == 0);
6301 /* Read eight io_units across multiple pages
6302 * cluster0: [ F0F0 (AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ]
6303 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
6304 * payload_read: AAAA AAAA | 0000 0000 ... */
6305 memset(payload_read
, 0x00, sizeof(payload_read
));
6306 iov
[0].iov_base
= payload_read
;
6307 iov
[0].iov_len
= 4 * 512;
6308 iov
[1].iov_base
= payload_read
+ 4 * 512;
6309 iov
[1].iov_len
= 4 * 512;
6310 spdk_blob_io_readv(blob
, channel
, iov
, 2, 4, 8, blob_op_complete
, NULL
);
6312 CU_ASSERT(g_bserrno
== 0);
6314 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_aa
, 8 * 512) == 0);
6315 CU_ASSERT(memcmp(payload_read
+ 8 * 512, payload_00
, 24 * 512) == 0);
6317 /* Read eight io_units across multiple clusters
6318 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 (FFFF ]
6319 * cluster1: [ FFFF) 0000 | 0000 FF00 | 0000 0000 | 0000 0000 ]
6320 * payload_read: FFFF FFFF | 0000 0000 ... */
6321 memset(payload_read
, 0x00, sizeof(payload_read
));
6322 iov
[0].iov_base
= payload_read
;
6323 iov
[0].iov_len
= 2 * 512;
6324 iov
[1].iov_base
= payload_read
+ 2 * 512;
6325 iov
[1].iov_len
= 2 * 512;
6326 iov
[2].iov_base
= payload_read
+ 4 * 512;
6327 iov
[2].iov_len
= 2 * 512;
6328 iov
[3].iov_base
= payload_read
+ 6 * 512;
6329 iov
[3].iov_len
= 2 * 512;
6330 spdk_blob_io_readv(blob
, channel
, iov
, 4, 28, 8, blob_op_complete
, NULL
);
6332 CU_ASSERT(g_bserrno
== 0);
6334 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_ff
, 8 * 512) == 0);
6335 CU_ASSERT(memcmp(payload_read
+ 8 * 512, payload_00
, 24 * 512) == 0);
6337 /* Read four io_units from second cluster
6338 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6339 * cluster1: [ FFFF 0000 | 00(00 FF)00 | 0000 0000 | 0000 0000 ]
6340 * payload_read: 00FF 0000 | 0000 0000 ... */
6341 memset(payload_read
, 0x00, sizeof(payload_read
));
6342 iov
[0].iov_base
= payload_read
;
6343 iov
[0].iov_len
= 1 * 512;
6344 iov
[1].iov_base
= payload_read
+ 1 * 512;
6345 iov
[1].iov_len
= 3 * 512;
6346 spdk_blob_io_readv(blob
, channel
, iov
, 2, 32 + 10, 4, blob_op_complete
, NULL
);
6348 CU_ASSERT(g_bserrno
== 0);
6350 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_00
, 2 * 512) == 0);
6351 CU_ASSERT(memcmp(payload_read
+ 2 * 512, payload_ff
, 2 * 512) == 0);
6352 CU_ASSERT(memcmp(payload_read
+ 4 * 512, payload_00
, 28 * 512) == 0);
6354 /* Read second cluster
6355 * cluster0: [ F0F0 AAAA | AAAA 0000 | 0000 0000 | 0000 FFFF ]
6356 * cluster1: [ (FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ]
6357 * payload_read: FFFF 0000 | 0000 FF00 ... */
6358 memset(payload_read
, 0x00, sizeof(payload_read
));
6359 iov
[0].iov_base
= payload_read
;
6360 iov
[0].iov_len
= 1 * 512;
6361 iov
[1].iov_base
= payload_read
+ 1 * 512;
6362 iov
[1].iov_len
= 2 * 512;
6363 iov
[2].iov_base
= payload_read
+ 3 * 512;
6364 iov
[2].iov_len
= 4 * 512;
6365 iov
[3].iov_base
= payload_read
+ 7 * 512;
6366 iov
[3].iov_len
= 25 * 512;
6367 spdk_blob_io_readv(blob
, channel
, iov
, 4, 32, 32, blob_op_complete
, NULL
);
6369 CU_ASSERT(g_bserrno
== 0);
6370 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_ff
, 4 * 512) == 0);
6371 CU_ASSERT(memcmp(payload_read
+ 4 * 512, payload_00
, 8 * 512) == 0);
6372 CU_ASSERT(memcmp(payload_read
+ 12 * 512, payload_ff
, 2 * 512) == 0);
6373 CU_ASSERT(memcmp(payload_read
+ 14 * 512, payload_00
, 18 * 512) == 0);
6375 /* Read whole two clusters
6376 * cluster0: [ (F0F0 AAAA | AAAA) 0000 | 0000 0000 | 0000 FFFF ]
6377 * cluster1: [ FFFF 0000 | 0000 FF00 | 0000 0000 | 0000 0000) ] */
6378 memset(payload_read
, 0x00, sizeof(payload_read
));
6379 iov
[0].iov_base
= payload_read
;
6380 iov
[0].iov_len
= 1 * 512;
6381 iov
[1].iov_base
= payload_read
+ 1 * 512;
6382 iov
[1].iov_len
= 8 * 512;
6383 iov
[2].iov_base
= payload_read
+ 9 * 512;
6384 iov
[2].iov_len
= 16 * 512;
6385 iov
[3].iov_base
= payload_read
+ 25 * 512;
6386 iov
[3].iov_len
= 39 * 512;
6387 spdk_blob_io_readv(blob
, channel
, iov
, 4, 0, 64, blob_op_complete
, NULL
);
6389 CU_ASSERT(g_bserrno
== 0);
6391 CU_ASSERT(memcmp(payload_read
+ 0 * 512, payload_ff
, 512) == 0);
6392 CU_ASSERT(memcmp(payload_read
+ 1 * 512, payload_00
, 512) == 0);
6393 CU_ASSERT(memcmp(payload_read
+ 2 * 512, payload_ff
, 512) == 0);
6394 CU_ASSERT(memcmp(payload_read
+ 3 * 512, payload_00
, 512) == 0);
6395 CU_ASSERT(memcmp(payload_read
+ 4 * 512, payload_aa
, 8 * 512) == 0);
6396 CU_ASSERT(memcmp(payload_read
+ 28 * 512, payload_ff
, 4 * 512) == 0);
6398 CU_ASSERT(memcmp(payload_read
+ (32 + 0) * 512, payload_ff
, 4 * 512) == 0);
6399 CU_ASSERT(memcmp(payload_read
+ (32 + 4) * 512, payload_00
, 8 * 512) == 0);
6400 CU_ASSERT(memcmp(payload_read
+ (32 + 12) * 512, payload_ff
, 2 * 512) == 0);
6401 CU_ASSERT(memcmp(payload_read
+ (32 + 14) * 512, payload_00
, 18 * 512) == 0);
6407 struct spdk_bs_opts bsopts
;
6408 struct spdk_blob_opts opts
;
6409 struct spdk_bs_dev
*dev
;
6410 struct spdk_blob
*blob
, *snapshot
, *clone
;
6411 spdk_blob_id blobid
;
6412 struct spdk_io_channel
*channel
;
6414 /* Create dev with 512 bytes io unit size */
6416 spdk_bs_opts_init(&bsopts
);
6417 bsopts
.cluster_sz
= SPDK_BS_PAGE_SIZE
* 4; /* 8 * 4 = 32 io_unit */
6418 snprintf(bsopts
.bstype
.bstype
, sizeof(bsopts
.bstype
.bstype
), "TESTTYPE");
6420 /* Try to initialize a new blob store with unsupported io_unit */
6422 dev
->blocklen
= 512;
6423 dev
->blockcnt
= DEV_BUFFER_SIZE
/ dev
->blocklen
;
6425 /* Initialize a new blob store */
6426 spdk_bs_init(dev
, &bsopts
, bs_op_with_handle_complete
, NULL
);
6428 CU_ASSERT(g_bserrno
== 0);
6429 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
6431 CU_ASSERT(spdk_bs_get_io_unit_size(g_bs
) == 512);
6432 channel
= spdk_bs_alloc_io_channel(g_bs
);
6434 /* Create thick provisioned blob */
6435 spdk_blob_opts_init(&opts
);
6436 opts
.thin_provision
= false;
6437 opts
.num_clusters
= 32;
6439 spdk_bs_create_blob_ext(g_bs
, &opts
, blob_op_with_id_complete
, NULL
);
6442 CU_ASSERT(g_bserrno
== 0);
6443 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
6446 spdk_bs_open_blob(g_bs
, blobid
, blob_op_with_handle_complete
, NULL
);
6448 CU_ASSERT(g_bserrno
== 0);
6449 CU_ASSERT(g_blob
!= NULL
);
6452 test_io_write(dev
, blob
, channel
);
6453 test_io_read(dev
, blob
, channel
);
6454 test_io_zeroes(dev
, blob
, channel
);
6456 test_iov_write(dev
, blob
, channel
);
6457 test_iov_read(dev
, blob
, channel
);
6459 test_io_unmap(dev
, blob
, channel
);
6461 spdk_blob_close(blob
, blob_op_complete
, NULL
);
6463 CU_ASSERT(g_bserrno
== 0);
6467 /* Create thin provisioned blob */
6469 spdk_blob_opts_init(&opts
);
6470 opts
.thin_provision
= true;
6471 opts
.num_clusters
= 32;
6473 spdk_bs_create_blob_ext(g_bs
, &opts
, blob_op_with_id_complete
, NULL
);
6475 CU_ASSERT(g_bserrno
== 0);
6476 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
6479 spdk_bs_open_blob(g_bs
, blobid
, blob_op_with_handle_complete
, NULL
);
6481 CU_ASSERT(g_bserrno
== 0);
6482 CU_ASSERT(g_blob
!= NULL
);
6485 test_io_write(dev
, blob
, channel
);
6486 test_io_read(dev
, blob
, channel
);
6488 test_io_zeroes(dev
, blob
, channel
);
6490 test_iov_write(dev
, blob
, channel
);
6491 test_iov_read(dev
, blob
, channel
);
6493 /* Create snapshot */
6495 spdk_bs_create_snapshot(g_bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
6497 CU_ASSERT(g_bserrno
== 0);
6498 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
6501 spdk_bs_open_blob(g_bs
, blobid
, blob_op_with_handle_complete
, NULL
);
6503 CU_ASSERT(g_bserrno
== 0);
6504 CU_ASSERT(g_blob
!= NULL
);
6507 spdk_bs_create_clone(g_bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
6509 CU_ASSERT(g_bserrno
== 0);
6510 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
6513 spdk_bs_open_blob(g_bs
, blobid
, blob_op_with_handle_complete
, NULL
);
6515 CU_ASSERT(g_bserrno
== 0);
6516 CU_ASSERT(g_blob
!= NULL
);
6519 test_io_read(dev
, blob
, channel
);
6520 test_io_read(dev
, snapshot
, channel
);
6521 test_io_read(dev
, clone
, channel
);
6523 test_iov_read(dev
, blob
, channel
);
6524 test_iov_read(dev
, snapshot
, channel
);
6525 test_iov_read(dev
, clone
, channel
);
6529 spdk_bs_inflate_blob(g_bs
, channel
, blobid
, blob_op_complete
, NULL
);
6532 CU_ASSERT(g_bserrno
== 0);
6534 test_io_read(dev
, clone
, channel
);
6536 test_io_unmap(dev
, clone
, channel
);
6538 test_iov_write(dev
, clone
, channel
);
6539 test_iov_read(dev
, clone
, channel
);
6541 spdk_blob_close(blob
, blob_op_complete
, NULL
);
6542 spdk_blob_close(snapshot
, blob_op_complete
, NULL
);
6543 spdk_blob_close(clone
, blob_op_complete
, NULL
);
6545 CU_ASSERT(g_bserrno
== 0);
6549 /* Unload the blob store */
6550 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
6552 CU_ASSERT(g_bserrno
== 0);
6559 blob_io_unit_compatiblity(void)
6561 struct spdk_bs_opts bsopts
;
6562 struct spdk_bs_dev
*dev
;
6563 struct spdk_bs_super_block
*super
;
6565 /* Create dev with 512 bytes io unit size */
6567 spdk_bs_opts_init(&bsopts
);
6568 bsopts
.cluster_sz
= SPDK_BS_PAGE_SIZE
* 4; /* 8 * 4 = 32 io_unit */
6569 snprintf(bsopts
.bstype
.bstype
, sizeof(bsopts
.bstype
.bstype
), "TESTTYPE");
6571 /* Try to initialize a new blob store with unsupported io_unit */
6573 dev
->blocklen
= 512;
6574 dev
->blockcnt
= DEV_BUFFER_SIZE
/ dev
->blocklen
;
6576 /* Initialize a new blob store */
6577 spdk_bs_init(dev
, &bsopts
, bs_op_with_handle_complete
, NULL
);
6579 CU_ASSERT(g_bserrno
== 0);
6580 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
6582 CU_ASSERT(spdk_bs_get_io_unit_size(g_bs
) == 512);
6584 /* Unload the blob store */
6585 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
6587 CU_ASSERT(g_bserrno
== 0);
6589 /* Modify super block to behave like older version.
6590 * Check if loaded io unit size equals SPDK_BS_PAGE_SIZE */
6591 super
= (struct spdk_bs_super_block
*)&g_dev_buffer
[0];
6592 super
->io_unit_size
= 0;
6593 super
->crc
= _spdk_blob_md_page_calc_crc(super
);
6596 dev
->blocklen
= 512;
6597 dev
->blockcnt
= DEV_BUFFER_SIZE
/ dev
->blocklen
;
6599 spdk_bs_load(dev
, &bsopts
, bs_op_with_handle_complete
, NULL
);
6601 CU_ASSERT(g_bserrno
== 0);
6602 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
6604 CU_ASSERT(spdk_bs_get_io_unit_size(g_bs
) == SPDK_BS_PAGE_SIZE
);
6606 /* Unload the blob store */
6607 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
6609 CU_ASSERT(g_bserrno
== 0);
6617 blob_simultaneous_operations(void)
6619 struct spdk_blob_store
*bs
;
6620 struct spdk_bs_dev
*dev
;
6621 struct spdk_blob_opts opts
;
6622 struct spdk_blob
*blob
, *snapshot
;
6623 spdk_blob_id blobid
, snapshotid
;
6624 struct spdk_io_channel
*channel
;
6628 spdk_bs_init(dev
, NULL
, bs_op_with_handle_complete
, NULL
);
6630 CU_ASSERT(g_bserrno
== 0);
6631 SPDK_CU_ASSERT_FATAL(g_bs
!= NULL
);
6634 channel
= spdk_bs_alloc_io_channel(bs
);
6635 SPDK_CU_ASSERT_FATAL(channel
!= NULL
);
6637 spdk_blob_opts_init(&opts
);
6638 opts
.num_clusters
= 10;
6640 spdk_bs_create_blob_ext(bs
, &opts
, blob_op_with_id_complete
, NULL
);
6642 CU_ASSERT(g_bserrno
== 0);
6643 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
6646 spdk_bs_open_blob(bs
, blobid
, blob_op_with_handle_complete
, NULL
);
6648 CU_ASSERT(g_bserrno
== 0);
6649 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
6652 /* Create snapshot and try to remove blob in the same time:
6653 * - snapshot should be created successfully
6654 * - delete operation should fail w -EBUSY */
6655 CU_ASSERT(blob
->locked_operation_in_progress
== false);
6656 spdk_bs_create_snapshot(bs
, blobid
, NULL
, blob_op_with_id_complete
, NULL
);
6657 CU_ASSERT(blob
->locked_operation_in_progress
== true);
6658 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
6659 CU_ASSERT(blob
->locked_operation_in_progress
== true);
6660 /* Deletion failure */
6661 CU_ASSERT(g_bserrno
== -EBUSY
);
6663 CU_ASSERT(blob
->locked_operation_in_progress
== false);
6664 /* Snapshot creation success */
6665 CU_ASSERT(g_bserrno
== 0);
6666 CU_ASSERT(g_blobid
!= SPDK_BLOBID_INVALID
);
6668 snapshotid
= g_blobid
;
6670 spdk_bs_open_blob(bs
, snapshotid
, blob_op_with_handle_complete
, NULL
);
6672 CU_ASSERT(g_bserrno
== 0);
6673 SPDK_CU_ASSERT_FATAL(g_blob
!= NULL
);
6676 /* Inflate blob and try to remove blob in the same time:
6677 * - blob should be inflated successfully
6678 * - delete operation should fail w -EBUSY */
6679 CU_ASSERT(blob
->locked_operation_in_progress
== false);
6680 spdk_bs_inflate_blob(bs
, channel
, blobid
, blob_op_complete
, NULL
);
6681 CU_ASSERT(blob
->locked_operation_in_progress
== true);
6682 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
6683 CU_ASSERT(blob
->locked_operation_in_progress
== true);
6684 /* Deletion failure */
6685 CU_ASSERT(g_bserrno
== -EBUSY
);
6687 CU_ASSERT(blob
->locked_operation_in_progress
== false);
6688 /* Inflation success */
6689 CU_ASSERT(g_bserrno
== 0);
6691 /* Clone snapshot and try to remove snapshot in the same time:
6692 * - snapshot should be cloned successfully
6693 * - delete operation should fail w -EBUSY */
6694 CU_ASSERT(blob
->locked_operation_in_progress
== false);
6695 spdk_bs_create_clone(bs
, snapshotid
, NULL
, blob_op_with_id_complete
, NULL
);
6696 spdk_bs_delete_blob(bs
, snapshotid
, blob_op_complete
, NULL
);
6697 /* Deletion failure */
6698 CU_ASSERT(g_bserrno
== -EBUSY
);
6700 CU_ASSERT(blob
->locked_operation_in_progress
== false);
6702 CU_ASSERT(g_bserrno
== 0);
6704 /* Resize blob and try to remove blob in the same time:
6705 * - blob should be resized successfully
6706 * - delete operation should fail w -EBUSY */
6707 CU_ASSERT(blob
->locked_operation_in_progress
== false);
6708 spdk_blob_resize(blob
, 50, blob_op_complete
, NULL
);
6709 CU_ASSERT(blob
->locked_operation_in_progress
== true);
6710 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
6711 CU_ASSERT(blob
->locked_operation_in_progress
== true);
6712 /* Deletion failure */
6713 CU_ASSERT(g_bserrno
== -EBUSY
);
6715 CU_ASSERT(blob
->locked_operation_in_progress
== false);
6716 /* Blob resized successfully */
6717 CU_ASSERT(g_bserrno
== 0);
6719 spdk_blob_close(blob
, blob_op_complete
, NULL
);
6721 CU_ASSERT(g_bserrno
== 0);
6723 spdk_blob_close(snapshot
, blob_op_complete
, NULL
);
6725 CU_ASSERT(g_bserrno
== 0);
6727 spdk_bs_delete_blob(bs
, blobid
, blob_op_complete
, NULL
);
6729 CU_ASSERT(g_bserrno
== 0);
6731 spdk_bs_unload(g_bs
, bs_op_complete
, NULL
);
6733 CU_ASSERT(g_bserrno
== 0);
6736 spdk_bs_free_io_channel(channel
);
6740 int main(int argc
, char **argv
)
6742 CU_pSuite suite
= NULL
;
6743 unsigned int num_failures
;
6745 if (CU_initialize_registry() != CUE_SUCCESS
) {
6746 return CU_get_error();
6749 suite
= CU_add_suite("blob", NULL
, NULL
);
6750 if (suite
== NULL
) {
6751 CU_cleanup_registry();
6752 return CU_get_error();
6756 CU_add_test(suite
, "blob_init", blob_init
) == NULL
||
6757 CU_add_test(suite
, "blob_open", blob_open
) == NULL
||
6758 CU_add_test(suite
, "blob_create", blob_create
) == NULL
||
6759 CU_add_test(suite
, "blob_create_internal", blob_create_internal
) == NULL
||
6760 CU_add_test(suite
, "blob_thin_provision", blob_thin_provision
) == NULL
||
6761 CU_add_test(suite
, "blob_snapshot", blob_snapshot
) == NULL
||
6762 CU_add_test(suite
, "blob_clone", blob_clone
) == NULL
||
6763 CU_add_test(suite
, "blob_inflate", blob_inflate
) == NULL
||
6764 CU_add_test(suite
, "blob_delete", blob_delete
) == NULL
||
6765 CU_add_test(suite
, "blob_resize", blob_resize
) == NULL
||
6766 CU_add_test(suite
, "blob_read_only", blob_read_only
) == NULL
||
6767 CU_add_test(suite
, "channel_ops", channel_ops
) == NULL
||
6768 CU_add_test(suite
, "blob_super", blob_super
) == NULL
||
6769 CU_add_test(suite
, "blob_write", blob_write
) == NULL
||
6770 CU_add_test(suite
, "blob_read", blob_read
) == NULL
||
6771 CU_add_test(suite
, "blob_rw_verify", blob_rw_verify
) == NULL
||
6772 CU_add_test(suite
, "blob_rw_verify_iov", blob_rw_verify_iov
) == NULL
||
6773 CU_add_test(suite
, "blob_rw_verify_iov_nomem", blob_rw_verify_iov_nomem
) == NULL
||
6774 CU_add_test(suite
, "blob_rw_iov_read_only", blob_rw_iov_read_only
) == NULL
||
6775 CU_add_test(suite
, "blob_unmap", blob_unmap
) == NULL
||
6776 CU_add_test(suite
, "blob_iter", blob_iter
) == NULL
||
6777 CU_add_test(suite
, "blob_xattr", blob_xattr
) == NULL
||
6778 CU_add_test(suite
, "bs_load", bs_load
) == NULL
||
6779 CU_add_test(suite
, "bs_load_pending_removal", bs_load_pending_removal
) == NULL
||
6780 CU_add_test(suite
, "bs_load_custom_cluster_size", bs_load_custom_cluster_size
) == NULL
||
6781 CU_add_test(suite
, "bs_unload", bs_unload
) == NULL
||
6782 CU_add_test(suite
, "bs_cluster_sz", bs_cluster_sz
) == NULL
||
6783 CU_add_test(suite
, "bs_usable_clusters", bs_usable_clusters
) == NULL
||
6784 CU_add_test(suite
, "bs_resize_md", bs_resize_md
) == NULL
||
6785 CU_add_test(suite
, "bs_destroy", bs_destroy
) == NULL
||
6786 CU_add_test(suite
, "bs_type", bs_type
) == NULL
||
6787 CU_add_test(suite
, "bs_super_block", bs_super_block
) == NULL
||
6788 CU_add_test(suite
, "blob_serialize", blob_serialize
) == NULL
||
6789 CU_add_test(suite
, "blob_crc", blob_crc
) == NULL
||
6790 CU_add_test(suite
, "super_block_crc", super_block_crc
) == NULL
||
6791 CU_add_test(suite
, "blob_dirty_shutdown", blob_dirty_shutdown
) == NULL
||
6792 CU_add_test(suite
, "blob_flags", blob_flags
) == NULL
||
6793 CU_add_test(suite
, "bs_version", bs_version
) == NULL
||
6794 CU_add_test(suite
, "blob_set_xattrs", blob_set_xattrs
) == NULL
||
6795 CU_add_test(suite
, "blob_thin_prov_alloc", blob_thin_prov_alloc
) == NULL
||
6796 CU_add_test(suite
, "blob_insert_cluster_msg", blob_insert_cluster_msg
) == NULL
||
6797 CU_add_test(suite
, "blob_thin_prov_rw", blob_thin_prov_rw
) == NULL
||
6798 CU_add_test(suite
, "blob_thin_prov_rw_iov", blob_thin_prov_rw_iov
) == NULL
||
6799 CU_add_test(suite
, "bs_load_iter", bs_load_iter
) == NULL
||
6800 CU_add_test(suite
, "blob_snapshot_rw", blob_snapshot_rw
) == NULL
||
6801 CU_add_test(suite
, "blob_snapshot_rw_iov", blob_snapshot_rw_iov
) == NULL
||
6802 CU_add_test(suite
, "blob_relations", blob_relations
) == NULL
||
6803 CU_add_test(suite
, "blob_inflate_rw", blob_inflate_rw
) == NULL
||
6804 CU_add_test(suite
, "blob_snapshot_freeze_io", blob_snapshot_freeze_io
) == NULL
||
6805 CU_add_test(suite
, "blob_operation_split_rw", blob_operation_split_rw
) == NULL
||
6806 CU_add_test(suite
, "blob_operation_split_rw_iov", blob_operation_split_rw_iov
) == NULL
||
6807 CU_add_test(suite
, "blob_io_unit", blob_io_unit
) == NULL
||
6808 CU_add_test(suite
, "blob_io_unit_compatiblity", blob_io_unit_compatiblity
) == NULL
||
6809 CU_add_test(suite
, "blob_simultaneous_operations", blob_simultaneous_operations
) == NULL
6811 CU_cleanup_registry();
6812 return CU_get_error();
6815 allocate_threads(2);
6818 g_dev_buffer
= calloc(1, DEV_BUFFER_SIZE
);
6820 CU_basic_set_mode(CU_BRM_VERBOSE
);
6821 CU_basic_run_tests();
6822 num_failures
= CU_get_number_of_failures();
6823 CU_cleanup_registry();
6829 return num_failures
;