diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index ff1dd809af..80101b1120 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -1465,6 +1465,9 @@ _spdk_blob_persist_dirty(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) struct spdk_blob_persist_ctx *ctx = cb_arg; ctx->super->clean = 0; + if (ctx->super->size == 0) { + ctx->super->size = ctx->blob->bs->dev->blockcnt * ctx->blob->bs->dev->blocklen; + } _spdk_bs_write_super(seq, ctx->blob->bs, ctx->super, _spdk_blob_persist_dirty_cpl, ctx); } @@ -3068,10 +3071,21 @@ _spdk_bs_load_super_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) return; } + if (ctx->super->size == 0) { + /* Update number of blocks for blobstore */ + ctx->bs->total_clusters = ctx->bs->dev->blockcnt * ctx->bs->dev->blocklen / ctx->bs->cluster_sz; + } else if (ctx->super->size > ctx->bs->dev->blockcnt * ctx->bs->dev->blocklen) { + SPDK_NOTICELOG("Size mismatch, dev size: %lu, blobstore size: %lu\n", + ctx->bs->dev->blockcnt * ctx->bs->dev->blocklen, ctx->super->size); + _spdk_bs_load_ctx_fail(seq, ctx, -EILSEQ); + return; + } else { + ctx->bs->total_clusters = ctx->super->size / ctx->bs->cluster_sz; + } + /* Parse the super block */ ctx->bs->clean = 1; ctx->bs->cluster_sz = ctx->super->cluster_size; - ctx->bs->total_clusters = ctx->bs->dev->blockcnt / (ctx->bs->cluster_sz / ctx->bs->dev->blocklen); ctx->bs->pages_per_cluster = ctx->bs->cluster_sz / SPDK_BS_PAGE_SIZE; ctx->bs->md_start = ctx->super->md_start; ctx->bs->md_len = ctx->super->md_len; @@ -3599,6 +3613,8 @@ spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *o, num_md_lba = _spdk_bs_page_to_lba(bs, num_md_pages); + ctx->super->size = dev->blockcnt * dev->blocklen; + ctx->super->crc = _spdk_blob_md_page_calc_crc(ctx->super); num_md_clusters = divide_round_up(num_md_pages, bs->pages_per_cluster); diff --git a/lib/blob/blobstore.h b/lib/blob/blobstore.h index e0a2a737d3..755fc5938e 100644 --- a/lib/blob/blobstore.h +++ b/lib/blob/blobstore.h @@ -344,7 +344,9 @@ struct spdk_bs_super_block { uint32_t used_blobid_mask_start; /* Offset from beginning of disk, in pages */ uint32_t used_blobid_mask_len; /* Count, in pages */ - uint8_t reserved[4012]; + uint64_t size; /* size of blobstore in bytes */ + + uint8_t reserved[4004]; uint32_t crc; }; SPDK_STATIC_ASSERT(sizeof(struct spdk_bs_super_block) == 0x1000, "Invalid super block size"); diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index 2263d66078..6d084aa215 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -1991,6 +1991,7 @@ bs_load(void) super_block = (struct spdk_bs_super_block *)g_dev_buffer; CU_ASSERT(super_block->clean == 1); + CU_ASSERT(super_block->size == dev->blockcnt * dev->blocklen); spdk_bs_open_blob(g_bs, blobid, blob_op_with_handle_complete, NULL); CU_ASSERT(g_bserrno == 0); @@ -2018,11 +2019,59 @@ bs_load(void) CU_ASSERT(g_bserrno == 0); blob = NULL; g_blob = NULL; - g_blobid = SPDK_BLOBID_INVALID; spdk_bs_unload(g_bs, bs_op_complete, NULL); CU_ASSERT(g_bserrno == 0); g_bs = NULL; + + /* Load should fail: bdev size < saved size */ + dev = init_dev(); + dev->blockcnt /= 2; + + spdk_bs_opts_init(&opts); + snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); + spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); + + CU_ASSERT(g_bserrno == -EILSEQ); + + /* Load should succeed: bdev size > saved size */ + dev = init_dev(); + dev->blockcnt *= 4; + + spdk_bs_opts_init(&opts); + snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); + 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); + + + /* Test compatibility mode */ + + dev = init_dev(); + super_block->size = 0; + super_block->crc = _spdk_blob_md_page_calc_crc(super_block); + + spdk_bs_opts_init(&opts); + snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "TESTTYPE"); + spdk_bs_load(dev, &opts, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_bs != NULL); + + /* Create a blob */ + spdk_bs_create_blob(g_bs, blob_op_with_id_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID); + + /* Blobstore should update number of blocks in super_block */ + CU_ASSERT(super_block->size == dev->blockcnt * dev->blocklen); + CU_ASSERT(super_block->clean == 0); + + spdk_bs_unload(g_bs, bs_op_complete, NULL); + CU_ASSERT(g_bserrno == 0); + CU_ASSERT(super_block->clean == 1); + g_bs = NULL; + } static void