From 2c91e91907e2859a41259d322d5cab799146b6b3 Mon Sep 17 00:00:00 2001 From: Piotr Pelplinski Date: Thu, 10 May 2018 14:12:36 +0200 Subject: [PATCH] blobstore: Save the original size of the disk. Save the original size of the disk to metadata when it is first created. On load verify that the disk did not change size. Signed-off-by: Piotr Pelplinski Change-Id: I535940ee188425ee3b394effd99653cc073d541e Reviewed-on: https://review.gerrithub.io/410896 Tested-by: SPDK Automated Test System Reviewed-by: Daniel Verkamp Reviewed-by: Ben Walker --- lib/blob/blobstore.c | 18 +++++++++- lib/blob/blobstore.h | 4 ++- test/unit/lib/blob/blob.c/blob_ut.c | 51 ++++++++++++++++++++++++++++- 3 files changed, 70 insertions(+), 3 deletions(-) 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