diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 0de9698f0..44e08bafc 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -3144,14 +3144,92 @@ spdk_bs_unload(struct spdk_blob_store *bs, spdk_bs_op_complete cb_fn, void *cb_a /* END spdk_bs_unload */ +/* START spdk_bs_set_super */ + +struct spdk_bs_set_super_ctx { + struct spdk_blob_store *bs; + struct spdk_bs_super_block *super; +}; + +static void +_spdk_bs_set_super_write_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) +{ + struct spdk_bs_set_super_ctx *ctx = cb_arg; + + if (bserrno != 0) { + SPDK_ERRLOG("Unable to write to super block of blobstore\n"); + } + + spdk_dma_free(ctx->super); + + spdk_bs_sequence_finish(seq, bserrno); + + free(ctx); +} + +static void +_spdk_bs_set_super_read_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) +{ + struct spdk_bs_set_super_ctx *ctx = cb_arg; + + if (bserrno != 0) { + SPDK_ERRLOG("Unable to read super block of blobstore\n"); + spdk_dma_free(ctx->super); + spdk_bs_sequence_finish(seq, bserrno); + free(ctx); + return; + } + + _spdk_bs_write_super(seq, ctx->bs, ctx->super, _spdk_bs_set_super_write_cpl, ctx); +} + void spdk_bs_set_super(struct spdk_blob_store *bs, spdk_blob_id blobid, spdk_bs_op_complete cb_fn, void *cb_arg) { + struct spdk_bs_cpl cpl; + spdk_bs_sequence_t *seq; + struct spdk_bs_set_super_ctx *ctx; + + SPDK_DEBUGLOG(SPDK_LOG_BLOB, "Setting super blob id on blobstore\n"); + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) { + cb_fn(cb_arg, -ENOMEM); + return; + } + + ctx->bs = bs; + + ctx->super = spdk_dma_zmalloc(sizeof(*ctx->super), 0x1000, NULL); + if (!ctx->super) { + free(ctx); + cb_fn(cb_arg, -ENOMEM); + return; + } + + cpl.type = SPDK_BS_CPL_TYPE_BS_BASIC; + cpl.u.bs_basic.cb_fn = cb_fn; + cpl.u.bs_basic.cb_arg = cb_arg; + + seq = spdk_bs_sequence_start(bs->md_channel, &cpl); + if (!seq) { + spdk_dma_free(ctx->super); + free(ctx); + cb_fn(cb_arg, -ENOMEM); + return; + } + bs->super_blob = blobid; - cb_fn(cb_arg, 0); + + /* Read super block */ + spdk_bs_sequence_read_dev(seq, ctx->super, _spdk_bs_page_to_lba(bs, 0), + _spdk_bs_byte_to_lba(bs, sizeof(*ctx->super)), + _spdk_bs_set_super_read_cpl, ctx); } +/* END spdk_bs_set_super */ + void spdk_bs_get_super(struct spdk_blob_store *bs, spdk_blob_op_with_id_complete cb_fn, void *cb_arg) diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index 423d74db0..a047b3de3 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -2063,13 +2063,13 @@ super_block_crc(void) } /* For blob dirty shutdown test case we do the following sub-test cases: - * 1 Initialize new blob store and create 1 blob with some xattrs, then we + * 1 Initialize new blob store and create 1 super blob with some xattrs, then we * dirty shutdown and reload the blob store and verify the xattrs. * 2 Resize the blob from 10 clusters to 20 clusters and then dirty shutdown, * reload the blob store and verify the clusters number. * 3 Create the second blob and then dirty shutdown, reload the blob store * and verify the second blob. - * 4 Delete the second blob and then dirty shutdown, reload teh blob store + * 4 Delete the second blob and then dirty shutdown, reload the blob store * and verify the second blob is invalid. * 5 Create the second blob again and also create the third blob, modify the * md of second blob which makes the md invalid, and then dirty shutdown, @@ -2122,6 +2122,10 @@ blob_dirty_shutdown(void) rc = spdk_blob_resize(blob, 10); CU_ASSERT(rc == 0); + /* Set the blob as the super blob */ + spdk_bs_set_super(g_bs, blobid1, blob_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + free_clusters = spdk_bs_free_cluster_count(g_bs); spdk_blob_close(blob, blob_op_complete, NULL); @@ -2138,6 +2142,11 @@ blob_dirty_shutdown(void) spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); CU_ASSERT(g_bserrno == 0); + /* Get the super blob */ + spdk_bs_get_super(g_bs, blob_op_with_id_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(blobid1 == g_blobid); + spdk_bs_open_blob(g_bs, blobid1, blob_op_with_handle_complete, NULL); CU_ASSERT(g_bserrno == 0); CU_ASSERT(g_blob != NULL);