blobstore: add bstype to blobstore super block

Introducing bstype as a way to identify and verify
 blobstore type.

Signed-off-by: Maciej Szwed <maciej.szwed@intel.com>
Change-Id: I50267b5408625be10fe0c146ae329016d5509b4a
Reviewed-on: https://review.gerrithub.io/380476
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Maciej Szwed 2017-09-27 15:03:23 +02:00 committed by Jim Harris
parent 1a15ce9b46
commit eb8b1e20a9
7 changed files with 272 additions and 22 deletions

View File

@ -190,12 +190,13 @@ is the remainder of cluster 0 and may extend to additional clusters.
The `<sb-params>` data contains parameters specified by the user when the blob
store was initially formatted.
<sb-params> ::= <sb-page-size> <sb-cluster-size>
<sb-params> ::= <sb-page-size> <sb-cluster-size> <sb-bs-type>
<sb-page-size> ::= u32 # page size, in bytes.
# Must be a multiple of the logical block size.
# The implementation today requires this to be 4KiB.
<sb-cluster-size> ::= u32 # Cluster size, in bytes.
# Must be a multiple of the page size.
<sb-bs-type> ::= 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

View File

@ -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);
}
/*

View File

@ -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_ */

View File

@ -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);

View File

@ -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");

View File

@ -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

View File

@ -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