diff --git a/doc/blob.md b/doc/blob.md index 3421c8ae7..efb66b5ab 100644 --- a/doc/blob.md +++ b/doc/blob.md @@ -190,12 +190,13 @@ is the remainder of cluster 0 and may extend to additional clusters. The `` data contains parameters specified by the user when the blob store was initially formatted. - ::= + ::= ::= u32 # page size, in bytes. # Must be a multiple of the logical block size. # The implementation today requires this to be 4KiB. ::= u32 # Cluster size, in bytes. # Must be a multiple of the page size. + ::= char[16] # Blobstore type Each blob is allocated a non-contiguous set of pages inside the metadata region for its metadata. These pages form a linked list. The first page in the list diff --git a/examples/blob/cli/blobcli.c b/examples/blob/cli/blobcli.c index f7679b763..d711cbeb8 100644 --- a/examples/blob/cli/blobcli.c +++ b/examples/blob/cli/blobcli.c @@ -867,7 +867,7 @@ load_bs(struct cli_context_t *cli_context) return; } - spdk_bs_load(bs_dev, cli_context->next_func, cli_context); + spdk_bs_load(bs_dev, NULL, cli_context->next_func, cli_context); } /* diff --git a/include/spdk/blob.h b/include/spdk/blob.h index e3cbcc6f4..7e9f38d3f 100644 --- a/include/spdk/blob.h +++ b/include/spdk/blob.h @@ -70,6 +70,7 @@ typedef uint64_t spdk_blob_id; #define SPDK_BLOBID_INVALID (uint64_t)-1 +#define SPDK_BLOBSTORE_TYPE_LENGTH 16 struct spdk_blob_store; struct spdk_io_channel; @@ -139,18 +140,23 @@ struct spdk_bs_dev { uint32_t blocklen; /* In bytes */ }; +struct spdk_bs_type { + char bstype[SPDK_BLOBSTORE_TYPE_LENGTH]; +}; + struct spdk_bs_opts { uint32_t cluster_sz; /* In bytes. Must be multiple of page size. */ uint32_t num_md_pages; /* Count of the number of pages reserved for metadata */ uint32_t max_md_ops; /* Maximum simultaneous metadata operations */ uint32_t max_channel_ops; /* Maximum simultaneous operations per channel */ + struct spdk_bs_type bstype; /* Blobstore type */ }; /* Initialize an spdk_bs_opts structure to the default blobstore option values. */ void spdk_bs_opts_init(struct spdk_bs_opts *opts); /* Load a blob store from the given device. This will fail (return NULL) if no blob store is present. */ -void spdk_bs_load(struct spdk_bs_dev *dev, +void spdk_bs_load(struct spdk_bs_dev *dev, struct spdk_bs_opts *opts, spdk_bs_op_with_handle_complete cb_fn, void *cb_arg); /* Initialize a blob store on the given disk. Destroys all data present on the device. */ @@ -276,4 +282,7 @@ uint32_t spdk_xattr_names_get_count(struct spdk_xattr_names *names); const char *spdk_xattr_names_get_name(struct spdk_xattr_names *names, uint32_t index); void spdk_xattr_names_free(struct spdk_xattr_names *names); +struct spdk_bs_type spdk_bs_get_bstype(struct spdk_blob_store *bs); +void spdk_bs_set_bstype(struct spdk_blob_store *bs, struct spdk_bs_type bstype); + #endif /* SPDK_BLOB_H_ */ diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 4248c68dc..92b3aa5da 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -1380,6 +1380,7 @@ spdk_bs_opts_init(struct spdk_bs_opts *opts) opts->num_md_pages = SPDK_BLOB_OPTS_NUM_MD_PAGES; opts->max_md_ops = SPDK_BLOB_OPTS_MAX_MD_OPS; opts->max_channel_ops = SPDK_BLOB_OPTS_MAX_CHANNEL_OPS; + memset(&opts->bstype, 0, sizeof(opts->bstype)); } static int @@ -1432,6 +1433,7 @@ _spdk_bs_alloc(struct spdk_bs_dev *dev, struct spdk_bs_opts *opts) bs->md_target.max_md_ops = opts->max_md_ops; bs->io_target.max_channel_ops = opts->max_channel_ops; bs->super_blob = SPDK_BLOBID_INVALID; + memcpy(&bs->bstype, &opts->bstype, sizeof(opts->bstype)); /* The metadata is assumed to be at least 1 page */ bs->used_md_pages = spdk_bit_array_create(1); @@ -1476,6 +1478,7 @@ _spdk_bs_write_super(spdk_bs_sequence_t *seq, struct spdk_blob_store *bs, { /* Update the values in the super block */ super->super_blob = bs->super_blob; + memcpy(&super->bstype, &bs->bstype, sizeof(bs->bstype)); super->crc = _spdk_blob_md_page_calc_crc(super); spdk_bs_sequence_write(seq, super, _spdk_bs_page_to_lba(bs, 0), _spdk_bs_byte_to_lba(bs, sizeof(*super)), @@ -1644,6 +1647,7 @@ _spdk_bs_load_write_super_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno ctx->bs->md_start = ctx->super->md_start; ctx->bs->md_len = ctx->super->md_len; ctx->bs->super_blob = ctx->super->super_blob; + memcpy(&ctx->bs->bstype, &ctx->super->bstype, sizeof(ctx->super->bstype)); /* Read the used pages mask */ mask_size = ctx->super->used_page_mask_len * SPDK_BS_PAGE_SIZE; @@ -1667,8 +1671,10 @@ _spdk_bs_load_super_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) { struct spdk_bs_load_ctx *ctx = cb_arg; uint32_t crc; + static const char zeros[SPDK_BLOBSTORE_TYPE_LENGTH]; - if (ctx->super->version != SPDK_BS_VERSION) { + if (ctx->super->version > SPDK_BS_VERSION || + ctx->super->version < SPDK_BS_INITIAL_VERSION) { spdk_dma_free(ctx->super); _spdk_bs_free(ctx->bs); free(ctx); @@ -1694,6 +1700,21 @@ _spdk_bs_load_super_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) return; } + if (memcmp(&ctx->bs->bstype, &ctx->super->bstype, SPDK_BLOBSTORE_TYPE_LENGTH) == 0) { + SPDK_DEBUGLOG(SPDK_TRACE_BLOB, "Bstype matched - loading blobstore\n"); + } else if (memcmp(&ctx->bs->bstype, zeros, SPDK_BLOBSTORE_TYPE_LENGTH) == 0) { + SPDK_DEBUGLOG(SPDK_TRACE_BLOB, "Bstype wildcard used - loading blobstore regardless bstype\n"); + } else { + SPDK_DEBUGLOG(SPDK_TRACE_BLOB, "Unexpected bstype\n"); + SPDK_TRACEDUMP(SPDK_TRACE_BLOB, "Expected:", ctx->bs->bstype.bstype, SPDK_BLOBSTORE_TYPE_LENGTH); + SPDK_TRACEDUMP(SPDK_TRACE_BLOB, "Found:", ctx->super->bstype.bstype, SPDK_BLOBSTORE_TYPE_LENGTH); + spdk_dma_free(ctx->super); + _spdk_bs_free(ctx->bs); + free(ctx); + spdk_bs_sequence_finish(seq, -ENXIO); + return; + } + if (ctx->super->clean != 1) { /* TODO: ONLY CLEAN SHUTDOWN IS CURRENTLY SUPPORTED. * All of the necessary data to recover is available @@ -1712,7 +1733,7 @@ _spdk_bs_load_super_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) } void -spdk_bs_load(struct spdk_bs_dev *dev, +spdk_bs_load(struct spdk_bs_dev *dev, struct spdk_bs_opts *o, spdk_bs_op_with_handle_complete cb_fn, void *cb_arg) { struct spdk_blob_store *bs; @@ -1723,7 +1744,16 @@ spdk_bs_load(struct spdk_bs_dev *dev, SPDK_DEBUGLOG(SPDK_TRACE_BLOB, "Loading blobstore from dev %p\n", dev); - spdk_bs_opts_init(&opts); + if (o) { + opts = *o; + } else { + spdk_bs_opts_init(&opts); + } + + if (opts.max_md_ops == 0 || opts.max_channel_ops == 0) { + cb_fn(cb_arg, NULL, -EINVAL); + return; + } bs = _spdk_bs_alloc(dev, &opts); if (!bs) { @@ -1884,6 +1914,7 @@ spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *o, ctx->super->super_blob = bs->super_blob; ctx->super->clean = 0; ctx->super->cluster_size = bs->cluster_sz; + memcpy(&ctx->super->bstype, &bs->bstype, sizeof(bs->bstype)); /* Calculate how many pages the metadata consumes at the front * of the disk. @@ -2711,4 +2742,16 @@ spdk_xattr_names_free(struct spdk_xattr_names *names) free(names); } +struct spdk_bs_type +spdk_bs_get_bstype(struct spdk_blob_store *bs) +{ + return bs->bstype; +} + +void +spdk_bs_set_bstype(struct spdk_blob_store *bs, struct spdk_bs_type bstype) +{ + memcpy(&bs->bstype, &bstype, sizeof(bstype)); +} + SPDK_LOG_REGISTER_TRACE_FLAG("blob", SPDK_TRACE_BLOB); diff --git a/lib/blob/blobstore.h b/lib/blob/blobstore.h index 8d9a73d08..259437a06 100644 --- a/lib/blob/blobstore.h +++ b/lib/blob/blobstore.h @@ -158,6 +158,7 @@ struct spdk_blob_store { uint32_t pages_per_cluster; spdk_blob_id super_blob; + struct spdk_bs_type bstype; struct spdk_bs_cpl unload_cpl; int unload_err; @@ -179,7 +180,8 @@ struct spdk_bs_channel { * * The following data structures exist on disk. */ -#define SPDK_BS_VERSION 1 +#define SPDK_BS_INITIAL_VERSION 1 +#define SPDK_BS_VERSION 2 /* current version */ #pragma pack(push, 1) @@ -259,7 +261,9 @@ struct spdk_bs_super_block { uint32_t md_start; /* Offset from beginning of disk, in pages */ uint32_t md_len; /* Count, in pages */ - uint8_t reserved[4036]; + struct spdk_bs_type bstype; /* blobstore type */ + + uint8_t reserved[4020]; uint32_t crc; }; SPDK_STATIC_ASSERT(sizeof(struct spdk_bs_super_block) == 0x1000, "Invalid super block size"); diff --git a/lib/blobfs/blobfs.c b/lib/blobfs/blobfs.c index 7ba00f055..7e31fcb1b 100644 --- a/lib/blobfs/blobfs.c +++ b/lib/blobfs/blobfs.c @@ -441,6 +441,7 @@ spdk_fs_init(struct spdk_bs_dev *dev, fs_send_request_fn send_request_fn, struct spdk_filesystem *fs; struct spdk_fs_request *req; struct spdk_fs_cb_args *args; + struct spdk_bs_opts opts = {}; fs = fs_alloc(dev, send_request_fn); if (fs == NULL) { @@ -465,7 +466,10 @@ spdk_fs_init(struct spdk_bs_dev *dev, fs_send_request_fn send_request_fn, args->arg = cb_arg; args->fs = fs; - spdk_bs_init(dev, NULL, init_cb, req); + spdk_bs_opts_init(&opts); + strncpy(opts.bstype.bstype, "BLOBFS", SPDK_BLOBSTORE_TYPE_LENGTH); + + spdk_bs_init(dev, &opts, init_cb, req); } static struct spdk_file * @@ -609,6 +613,9 @@ load_cb(void *ctx, struct spdk_blob_store *bs, int bserrno) struct spdk_fs_request *req = ctx; struct spdk_fs_cb_args *args = &req->args; struct spdk_filesystem *fs = args->fs; + struct spdk_bs_type bstype; + static const char blobfs_type[SPDK_BLOBSTORE_TYPE_LENGTH] = {"BLOBFS"}; + static const char zeros[SPDK_BLOBSTORE_TYPE_LENGTH]; if (bserrno != 0) { args->fn.fs_op_with_handle(args->arg, NULL, bserrno); @@ -617,6 +624,20 @@ load_cb(void *ctx, struct spdk_blob_store *bs, int bserrno) return; } + bstype = spdk_bs_get_bstype(bs); + + if (!memcmp(&bstype, zeros, SPDK_BLOBSTORE_TYPE_LENGTH)) { + SPDK_DEBUGLOG(SPDK_TRACE_BLOB, "assigning bstype"); + snprintf(bstype.bstype, SPDK_BLOBSTORE_TYPE_LENGTH, blobfs_type); + spdk_bs_set_bstype(bs, bstype); + } else if (strncmp(bstype.bstype, blobfs_type, SPDK_BLOBSTORE_TYPE_LENGTH)) { + SPDK_DEBUGLOG(SPDK_TRACE_BLOB, "not blobfs: %s", bstype.bstype); + args->fn.fs_op_with_handle(args->arg, NULL, bserrno); + free_fs_request(req); + free(fs); + return; + } + common_fs_bs_init(fs, bs); spdk_bs_md_iter_first(fs->bs, iter_cb, req); } @@ -628,6 +649,7 @@ spdk_fs_load(struct spdk_bs_dev *dev, fs_send_request_fn send_request_fn, struct spdk_filesystem *fs; struct spdk_fs_cb_args *args; struct spdk_fs_request *req; + struct spdk_bs_opts opts = {}; fs = fs_alloc(dev, send_request_fn); if (fs == NULL) { @@ -652,7 +674,10 @@ spdk_fs_load(struct spdk_bs_dev *dev, fs_send_request_fn send_request_fn, args->arg = cb_arg; args->fs = fs; TAILQ_INIT(&args->op.fs_load.deleted_files); - spdk_bs_load(dev, load_cb, req); + + spdk_bs_opts_init(&opts); + + spdk_bs_load(dev, &opts, load_cb, req); } static void diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index 43628859f..3dcbc2679 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -59,6 +59,29 @@ struct scheduled_ops { static TAILQ_HEAD(, scheduled_ops) g_scheduled_ops = TAILQ_HEAD_INITIALIZER(g_scheduled_ops); +struct spdk_bs_super_block_ver1 { + uint8_t signature[8]; + uint32_t version; + uint32_t length; + uint32_t clean; /* If there was a clean shutdown, this is 1. */ + spdk_blob_id super_blob; + + uint32_t cluster_size; /* In bytes */ + + uint32_t used_page_mask_start; /* Offset from beginning of disk, in pages */ + uint32_t used_page_mask_len; /* Count, in pages */ + + uint32_t used_cluster_mask_start; /* Offset from beginning of disk, in pages */ + uint32_t used_cluster_mask_len; /* Count, in pages */ + + uint32_t md_start; /* Offset from beginning of disk, in pages */ + uint32_t md_len; /* Count, in pages */ + + uint8_t reserved[4036]; + uint32_t crc; +} __attribute__((packed)); +SPDK_STATIC_ASSERT(sizeof(struct spdk_bs_super_block_ver1) == 0x1000, "Invalid super block size"); + static void _bs_send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx) { @@ -842,16 +865,21 @@ bs_load(void) struct spdk_bs_dev *dev; spdk_blob_id blobid; struct spdk_blob *blob; - struct spdk_bs_super_block *super_blob; + struct spdk_bs_super_block *super_block; uint64_t length; int rc; const void *value; size_t value_len; + struct spdk_bs_opts opts; + + g_scheduler_delay = true; dev = init_dev(); + spdk_bs_opts_init(&opts); + strncpy(opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); /* Initialize a new blob store */ - spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); + spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); CU_ASSERT(g_bserrno == 0); SPDK_CU_ASSERT_FATAL(g_bs != NULL); @@ -901,16 +929,19 @@ bs_load(void) g_blob = NULL; g_blobid = 0; - super_blob = (struct spdk_bs_super_block *)g_dev_buffer; - CU_ASSERT(super_blob->clean == 1); - dev = init_dev(); + super_block = (struct spdk_bs_super_block *)g_dev_buffer; + CU_ASSERT(super_block->clean == 1); + + /* Load an existing blob store */ - spdk_bs_load(dev, bs_op_with_handle_complete, NULL); + dev = init_dev(); + strncpy(opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); + spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); CU_ASSERT(g_bserrno == 0); SPDK_CU_ASSERT_FATAL(g_bs != NULL); - super_blob = (struct spdk_bs_super_block *)g_dev_buffer; - CU_ASSERT(super_blob->clean == 0); + super_block = (struct spdk_bs_super_block *)g_dev_buffer; + CU_ASSERT(super_block->clean == 0); spdk_bs_md_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); CU_ASSERT(g_bserrno == 0); @@ -939,6 +970,139 @@ bs_load(void) spdk_bs_unload(g_bs, bs_op_complete, NULL); CU_ASSERT(g_bserrno == 0); g_bs = NULL; + g_scheduler_delay = false; +} + +static void +bs_type(void) +{ + struct spdk_bs_dev *dev; + struct spdk_bs_opts opts; + + g_scheduler_delay = true; + + dev = init_dev(); + spdk_bs_opts_init(&opts); + strncpy(opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); + + /* Initialize a new blob store */ + spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_bs != NULL); + + /* Unload the blob store */ + spdk_bs_unload(g_bs, bs_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + g_bs = NULL; + g_blob = NULL; + g_blobid = 0; + + /* Load non existing blobstore type */ + dev = init_dev(); + strncpy(opts.bstype.bstype, "NONEXISTING", SPDK_BLOBSTORE_TYPE_LENGTH); + spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno != 0); + + /* Load with empty blobstore type */ + dev = init_dev(); + strncpy(opts.bstype.bstype, "", SPDK_BLOBSTORE_TYPE_LENGTH); + spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + spdk_bs_unload(g_bs, bs_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + g_bs = NULL; + + /* Initialize a new blob store with empty bstype */ + dev = init_dev(); + strncpy(opts.bstype.bstype, "", SPDK_BLOBSTORE_TYPE_LENGTH); + spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_bs != NULL); + + spdk_bs_unload(g_bs, bs_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + g_bs = NULL; + + /* Load non existing blobstore type */ + dev = init_dev(); + strncpy(opts.bstype.bstype, "NONEXISTING", SPDK_BLOBSTORE_TYPE_LENGTH); + spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno != 0); + + /* Load with empty blobstore type */ + dev = init_dev(); + strncpy(opts.bstype.bstype, "", SPDK_BLOBSTORE_TYPE_LENGTH); + spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + spdk_bs_unload(g_bs, bs_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + g_bs = NULL; + g_scheduler_delay = false; +} + +static void +bs_super_block(void) +{ + struct spdk_bs_dev *dev; + struct spdk_bs_super_block *super_block; + struct spdk_bs_opts opts; + struct spdk_bs_super_block_ver1 super_block_v1; + + g_scheduler_delay = true; + + dev = init_dev(); + spdk_bs_opts_init(&opts); + strncpy(opts.bstype.bstype, "TESTTYPE", SPDK_BLOBSTORE_TYPE_LENGTH); + + /* Initialize a new blob store */ + spdk_bs_init(dev, &opts, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_bs != NULL); + + /* Unload the blob store */ + spdk_bs_unload(g_bs, bs_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + g_bs = NULL; + g_blob = NULL; + g_blobid = 0; + + /* Load an existing blob store with version newer than supported */ + super_block = (struct spdk_bs_super_block *)g_dev_buffer; + super_block->version++; + + dev = init_dev(); + strncpy(opts.bstype.bstype, "", SPDK_BLOBSTORE_TYPE_LENGTH); + spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno != 0); + + /* Create a new blob store with super block version 1 */ + dev = init_dev(); + super_block_v1.version = 1; + strncpy(super_block_v1.signature, "SPDKBLOB", sizeof(super_block_v1.signature)); + super_block_v1.length = 0x1000; + super_block_v1.clean = 1; + super_block_v1.super_blob = 0xFFFFFFFFFFFFFFFF; + super_block_v1.cluster_size = 0x100000; + super_block_v1.used_page_mask_start = 0x01; + super_block_v1.used_page_mask_len = 0x01; + super_block_v1.used_cluster_mask_start = 0x02; + super_block_v1.used_cluster_mask_len = 0x01; + super_block_v1.md_start = 0x03; + super_block_v1.md_len = 0x40; + memset(super_block_v1.reserved, 0, 4036); + super_block_v1.crc = _spdk_blob_md_page_calc_crc(&super_block_v1); + memcpy(g_dev_buffer, &super_block_v1, sizeof(struct spdk_bs_super_block_ver1)); + + strncpy(opts.bstype.bstype, "", SPDK_BLOBSTORE_TYPE_LENGTH); + spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + + spdk_bs_unload(g_bs, bs_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + g_bs = NULL; + g_scheduler_delay = false; } /* @@ -1017,7 +1181,7 @@ bs_cluster_sz(void) dev = init_dev(); /* Load an existing blob store */ - spdk_bs_load(dev, bs_op_with_handle_complete, NULL); + spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); CU_ASSERT(g_bserrno == 0); SPDK_CU_ASSERT_FATAL(g_bs != NULL); @@ -1077,7 +1241,7 @@ bs_resize_md(void) g_bserrno = -1; g_bs = NULL; dev = init_dev(); - spdk_bs_load(dev, bs_op_with_handle_complete, NULL); + spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); CU_ASSERT(g_bserrno == 0); SPDK_CU_ASSERT_FATAL(g_bs != NULL); @@ -1178,7 +1342,7 @@ blob_serialize(void) dev = init_dev(); /* Load an existing blob store */ - spdk_bs_load(dev, bs_op_with_handle_complete, NULL); + spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); CU_ASSERT(g_bserrno == 0); SPDK_CU_ASSERT_FATAL(g_bs != NULL); bs = g_bs; @@ -1257,8 +1421,10 @@ super_block_crc(void) { struct spdk_bs_dev *dev; struct spdk_bs_super_block *super_block; + struct spdk_bs_opts opts; dev = init_dev(); + spdk_bs_opts_init(&opts); spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL); CU_ASSERT(g_bserrno == 0); @@ -1274,7 +1440,7 @@ super_block_crc(void) g_scheduler_delay = true; /* Load an existing blob store */ - spdk_bs_load(dev, bs_op_with_handle_complete, NULL); + spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); CU_ASSERT(g_bserrno == -EILSEQ); _bs_flush_scheduler(); @@ -1316,6 +1482,8 @@ int main(int argc, char **argv) CU_add_test(suite, "bs_unload", bs_unload) == NULL || CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL || CU_add_test(suite, "bs_resize_md", bs_resize_md) == NULL || + CU_add_test(suite, "bs_type", bs_type) == NULL || + CU_add_test(suite, "bs_super_block", bs_super_block) == NULL || CU_add_test(suite, "blob_serialize", blob_serialize) == NULL || CU_add_test(suite, "blob_crc", blob_crc) == NULL || CU_add_test(suite, "super_block_crc", super_block_crc) == NULL